USM WIP
parent
1b4c13e5f5
commit
e6b25374f3
|
@ -47,7 +47,7 @@ namespace ln.snmp
|
|||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2} FirstByte=0x{3,02:X}]",IdentifierClass,Constructed,Number,Firstbyte);
|
||||
return String.Format("[ASN.1 Type Class={0} Constructed={1} Number={2} FirstByte=0x{3,2:X}]",IdentifierClass,Constructed,Number,Firstbyte);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ using ln.snmp.types;
|
|||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using ln.snmp.asn1;
|
||||
using ln.logging;
|
||||
|
||||
namespace ln.snmp
|
||||
{
|
||||
|
@ -23,10 +25,14 @@ namespace ln.snmp
|
|||
public UdpClient LocalEndpoint { get; private set; }
|
||||
public int Timeout { get; set; } = 1000;
|
||||
|
||||
private Dictionary<IPEndPoint, InternalRequest> queuedRequests = new Dictionary<IPEndPoint, InternalRequest>();
|
||||
private Dictionary<int, SnmpMessage> queuedRequests = new Dictionary<int, SnmpMessage>();
|
||||
private bool shutdown = false;
|
||||
private Thread ReceiverThread { get; set; }
|
||||
|
||||
|
||||
private int nextMessageID = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
public int NextMessageID => nextMessageID++;
|
||||
|
||||
public SNMPEngine()
|
||||
{
|
||||
LocalEndpoint = new UdpClient();
|
||||
|
@ -55,86 +61,81 @@ namespace ln.snmp
|
|||
IPEndPoint remoteEndpoint = null;
|
||||
byte[] datagram = LocalEndpoint.Receive(ref remoteEndpoint);
|
||||
|
||||
Logging.Log(LogLevel.DEBUG,"SNMPClient: Received: {0}", BitConverter.ToString(datagram));
|
||||
|
||||
ASN1Value asn = new ASN1Value(datagram);
|
||||
|
||||
asn.Dump();
|
||||
|
||||
SnmpMessage snmpMessage = asn;
|
||||
|
||||
snmpMessage.Dump();
|
||||
|
||||
lock (queuedRequests)
|
||||
{
|
||||
if (queuedRequests.ContainsKey(remoteEndpoint))
|
||||
if (queuedRequests.ContainsKey(snmpMessage.MessageID))
|
||||
{
|
||||
InternalRequest internalRequest = queuedRequests[remoteEndpoint];
|
||||
internalRequest.Response = datagram;
|
||||
lock (internalRequest)
|
||||
SnmpMessage snmpRequestMessage = queuedRequests[snmpMessage.MessageID];
|
||||
lock (snmpRequestMessage)
|
||||
{
|
||||
Monitor.PulseAll(internalRequest);
|
||||
queuedRequests[snmpMessage.MessageID] = snmpMessage;
|
||||
Monitor.PulseAll(snmpRequestMessage);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(LogLevel.WARNING, "SnmpEngine.Receiver(): Can't find pending request with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
catch (SocketException se)
|
||||
{
|
||||
|
||||
Logging.Log(se);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Receiver(): {0}", e);
|
||||
Logging.Log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] SendRequest(IPEndPoint remoteEndpoint,byte[] request,int timeout)
|
||||
public SnmpMessage SNMPRequest(IPEndPoint remoteEndpoint,SnmpMessage snmpMessage,int timeout)
|
||||
{
|
||||
InternalRequest internalRequest = new InternalRequest();
|
||||
internalRequest.RemoteEndpoint = remoteEndpoint;
|
||||
|
||||
lock(queuedRequests)
|
||||
lock (queuedRequests)
|
||||
{
|
||||
if (queuedRequests.ContainsKey(remoteEndpoint))
|
||||
throw new ArgumentException("Already pending request exists for this remote endpoint", nameof(remoteEndpoint));
|
||||
ASN1Value snmpRequest = snmpMessage;
|
||||
byte[] snmpRequestBytes = snmpRequest.AsByteArray;
|
||||
|
||||
queuedRequests.Add(remoteEndpoint,internalRequest);
|
||||
queuedRequests.Add(snmpMessage.MessageID, snmpMessage);
|
||||
|
||||
if (DEBUG)
|
||||
Console.WriteLine("SNMPClient: Send: {0}", BitConverter.ToString(request));
|
||||
Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes));
|
||||
Logging.Log(LogLevel.DEBUG,"sent snmpMessage with MessageID {0} ( 0x{0:x8} )",snmpMessage.MessageID);
|
||||
snmpMessage.Dump();
|
||||
|
||||
LocalEndpoint.Send(request, request.Length, remoteEndpoint);
|
||||
LocalEndpoint.Send(snmpRequestBytes, snmpRequestBytes.Length, remoteEndpoint);
|
||||
|
||||
lock (internalRequest)
|
||||
lock (snmpMessage)
|
||||
{
|
||||
Monitor.Exit(queuedRequests);
|
||||
bool success = Monitor.Wait(internalRequest, timeout);
|
||||
bool success = Monitor.Wait(snmpMessage, timeout);
|
||||
Monitor.Enter(queuedRequests);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
queuedRequests.Remove(snmpMessage.MessageID);
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
queuedRequests.Remove(remoteEndpoint);
|
||||
|
||||
SnmpMessage responseMessage = queuedRequests[snmpMessage.MessageID];
|
||||
queuedRequests.Remove(snmpMessage.MessageID);
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
return internalRequest.Response;
|
||||
}
|
||||
|
||||
|
||||
public Variable SNMPRequest(IPEndPoint remoteEndpoint,Sequence request)
|
||||
{
|
||||
byte[] response = SendRequest(remoteEndpoint, request.ToBytes(), Timeout);
|
||||
|
||||
if (DEBUG)
|
||||
Console.WriteLine("SNMPClient: Received: {0}", BitConverter.ToString(response));
|
||||
|
||||
Variable vreply = Variable.Read(response);
|
||||
return vreply;
|
||||
}
|
||||
|
||||
|
||||
//public abstract List<Variable> Walk(ObjectIdentifier baseOID);
|
||||
//public abstract List<Variable> Get(List<ObjectIdentifier> baseOID);
|
||||
|
||||
//public virtual Variable Get(ObjectIdentifier oid)
|
||||
//{
|
||||
// return Get(new List<ObjectIdentifier>(new ObjectIdentifier[] { oid }))[0];
|
||||
//}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (ReceiverThread != null)
|
||||
|
@ -151,10 +152,5 @@ namespace ln.snmp
|
|||
}
|
||||
}
|
||||
|
||||
class InternalRequest
|
||||
{
|
||||
public IPEndPoint RemoteEndpoint;
|
||||
public byte[] Response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,20 +10,20 @@ namespace ln.snmp
|
|||
{
|
||||
public enum SnmpVersion : int { V1 = 0, V2c = 1, V3 = 3 }
|
||||
|
||||
public class SNMPInterface
|
||||
public abstract class SNMPInterface
|
||||
{
|
||||
public SnmpPDUChannel PDUChannel { get; set; }
|
||||
|
||||
public SNMPEngine SNMPEngine { get; }
|
||||
public IPEndPoint RemoteEndpoint { get; set; }
|
||||
|
||||
public SnmpVersion SnmpVersion => PDUChannel.SnmpVersion;
|
||||
public abstract SnmpVersion SnmpVersion { get; }
|
||||
|
||||
public SNMPInterface(SnmpPDUChannel PDUChannel,IPEndPoint remoteEndpoint)
|
||||
public SNMPInterface(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint)
|
||||
{
|
||||
this.PDUChannel = PDUChannel;
|
||||
SNMPEngine = snmpEngine;
|
||||
RemoteEndpoint = remoteEndpoint;
|
||||
}
|
||||
|
||||
public abstract PDU snmpRequest(PDU pdu);
|
||||
|
||||
private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new()
|
||||
{
|
||||
|
@ -34,6 +34,13 @@ namespace ln.snmp
|
|||
}
|
||||
|
||||
PDU responsePDU = snmpRequest(pdu);
|
||||
|
||||
if (responsePDU.Error.LongValue != 0)
|
||||
{
|
||||
string indicator = responsePDU.ErrorIndex > 0 && responsePDU.ErrorIndex <= pdu.VarBinds.Items.Length ? ((pdu.VarBinds.Items[(int)responsePDU.ErrorIndex - 1] as Sequence).Items[0] as ObjectIdentifier).AsString : "";
|
||||
throw new SnmpError(responsePDU.Error, responsePDU.ErrorIndex, indicator);
|
||||
}
|
||||
|
||||
Sequence varBinds = responsePDU.VarBinds as Sequence;
|
||||
|
||||
List<Sequence> results = new List<Sequence>();
|
||||
|
@ -44,12 +51,6 @@ namespace ln.snmp
|
|||
return results;
|
||||
}
|
||||
|
||||
private PDU snmpRequest(PDU pdu)
|
||||
{
|
||||
GetResponse responsePDU = PDUChannel.RequestResponse(pdu, RemoteEndpoint) as GetResponse;
|
||||
return responsePDU;
|
||||
}
|
||||
|
||||
public List<Sequence> snmpGet(IEnumerable<ObjectIdentifier> objectIdentifiers)
|
||||
{
|
||||
return snmpRequest<GetRequest>(objectIdentifiers);
|
||||
|
@ -224,14 +225,10 @@ namespace ln.snmp
|
|||
}
|
||||
return results.ToArray();
|
||||
}
|
||||
else if (SnmpVersion == SnmpVersion.V2c)
|
||||
else
|
||||
{
|
||||
return snmpGetBulk(objectIdentifiers);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
public Sequence[][] snmpWalk(IEnumerable<String> objectIdentifiers)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,185 @@
|
|||
// /**
|
||||
// * File: ASN1Value.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ln.snmp.types;
|
||||
using ln.logging;
|
||||
namespace ln.snmp.asn1
|
||||
{
|
||||
public class ASN1Value
|
||||
{
|
||||
public Identifier Identifier { get; set; }
|
||||
|
||||
private byte[] octets;
|
||||
private List<ASN1Value> items;
|
||||
|
||||
public ASN1Value(byte[] source)
|
||||
:this(new MemoryStream(source))
|
||||
{
|
||||
}
|
||||
public ASN1Value(Stream stream)
|
||||
{
|
||||
Identifier = BasicEncodingRules.ReadIdentifier(stream);
|
||||
int length = BasicEncodingRules.ReadLength(stream);
|
||||
|
||||
if (Identifier.Constructed)
|
||||
{
|
||||
items = new List<ASN1Value>();
|
||||
|
||||
long next = stream.Position + length;
|
||||
while (stream.Position < next)
|
||||
items.Add(new ASN1Value(stream));
|
||||
}
|
||||
else
|
||||
{
|
||||
octets = new byte[length];
|
||||
stream.Read(octets, 0, length);
|
||||
}
|
||||
}
|
||||
|
||||
public ASN1Value(Identifier identifier)
|
||||
{
|
||||
Identifier = identifier;
|
||||
if (Identifier.Constructed)
|
||||
items = new List<ASN1Value>();
|
||||
else
|
||||
octets = new byte[0];
|
||||
}
|
||||
|
||||
public byte[] AsByteArray
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Identifier.Constructed)
|
||||
{
|
||||
byte[][] binaryItems = new byte[items.Count][];
|
||||
int length = 0;
|
||||
for (int n = 0; n < binaryItems.Length; n++)
|
||||
{
|
||||
binaryItems[n] = items[n].AsByteArray;
|
||||
length += binaryItems[n].Length;
|
||||
}
|
||||
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BasicEncodingRules.WriteIdentifier(stream, Identifier);
|
||||
BasicEncodingRules.WriteLength(stream, length);
|
||||
for (int n = 0; n < binaryItems.Length; n++)
|
||||
stream.Write(binaryItems[n], 0, binaryItems[n].Length);
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
BasicEncodingRules.WriteIdentifier(stream, Identifier);
|
||||
BasicEncodingRules.WriteLength(stream, octets.Length);
|
||||
stream.Write(octets, 0, octets.Length);
|
||||
return stream.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public byte[] Bytes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Identifier.Constructed)
|
||||
{
|
||||
return octets;
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[][] binaryItems = new byte[items.Count][];
|
||||
int length = 0;
|
||||
for (int n = 0; n < binaryItems.Length; n++)
|
||||
{
|
||||
binaryItems[n] = items[n].AsByteArray;
|
||||
length += binaryItems[n].Length;
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[length];
|
||||
int offset = 0;
|
||||
|
||||
for (int n = 0; n < binaryItems.Length; n++)
|
||||
{
|
||||
Array.Copy(binaryItems[n], 0, bytes, offset, binaryItems[n].Length);
|
||||
offset += binaryItems[n].Length;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!Identifier.Constructed)
|
||||
{
|
||||
octets = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ASN1Value[] Items
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Identifier.Constructed)
|
||||
throw new ArgumentOutOfRangeException("ASN1Value is not constructed");
|
||||
|
||||
return items.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!Identifier.Constructed)
|
||||
throw new ArgumentOutOfRangeException("ASN1Value is not constructed");
|
||||
|
||||
items = new List<ASN1Value>(value);
|
||||
}
|
||||
}
|
||||
|
||||
public void Add(ASN1Value item)
|
||||
{
|
||||
if (!Identifier.Constructed)
|
||||
throw new ArgumentOutOfRangeException("ASN1Value is not constructed");
|
||||
items.Add(item);
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("[ASN1Value Identifier={0}]",Identifier);
|
||||
}
|
||||
|
||||
public void Dump()
|
||||
{
|
||||
Dump("");
|
||||
}
|
||||
public void Dump(string prefix)
|
||||
{
|
||||
if (Identifier.Constructed)
|
||||
{
|
||||
Logging.Log(LogLevel.DEBUG, "{1}{0}", this.Identifier, prefix);
|
||||
foreach (ASN1Value item in items)
|
||||
item.Dump(prefix + " ");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Log(LogLevel.DEBUG, "{2}{0} {1}",this.Identifier,BitConverter.ToString(Bytes),prefix);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using System;
|
||||
using ln.snmp.types;
|
||||
using System.Net;
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public abstract class SnmpPDUChannel
|
||||
{
|
||||
public SNMPEngine SNMPClient { get; set; }
|
||||
|
||||
|
||||
public abstract SnmpVersion SnmpVersion { get; }
|
||||
|
||||
public SnmpPDUChannel(SNMPEngine client)
|
||||
{
|
||||
SNMPClient = client;
|
||||
}
|
||||
|
||||
public abstract PDU RequestResponse(PDU pdu, IPEndPoint remoteEndpoint);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
using System;
|
||||
using ln.snmp.types;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public class SnmpV1Channel : SnmpPDUChannel
|
||||
{
|
||||
public override SnmpVersion SnmpVersion => SnmpVersion.V1;
|
||||
|
||||
public OctetString CommunityString { get; set; }
|
||||
|
||||
|
||||
public SnmpV1Channel(SNMPEngine client)
|
||||
:base(client)
|
||||
{
|
||||
CommunityString = "public";
|
||||
}
|
||||
public SnmpV1Channel(SNMPEngine client,string communityString)
|
||||
:base(client)
|
||||
{
|
||||
CommunityString = communityString;
|
||||
}
|
||||
|
||||
public override PDU RequestResponse(PDU pdu,IPEndPoint remoteEndpoint)
|
||||
{
|
||||
Integer version = new Integer((int)SnmpVersion);
|
||||
|
||||
Sequence snmpRequest = new Sequence();
|
||||
snmpRequest.Add(version);
|
||||
snmpRequest.Add(CommunityString);
|
||||
snmpRequest.Add(pdu);
|
||||
|
||||
Variable reply = SNMPClient.SNMPRequest(remoteEndpoint, snmpRequest);
|
||||
|
||||
Sequence sreply = reply as Sequence;
|
||||
PDU responsePDU = sreply.Items[2] as PDU;
|
||||
|
||||
if (responsePDU.Error.LongValue != 0)
|
||||
{
|
||||
string indicator = responsePDU.ErrorIndex > 0 && responsePDU.ErrorIndex <= pdu.VarBinds.Items.Length ? ((pdu.VarBinds.Items[(int)responsePDU.ErrorIndex - 1] as Sequence).Items[0] as ObjectIdentifier).AsString : "";
|
||||
throw new SnmpError(responsePDU.Error, responsePDU.ErrorIndex, indicator);
|
||||
}
|
||||
|
||||
return responsePDU;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using ln.snmp.types;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public class SnmpV1Endpoint : SNMPInterface
|
||||
{
|
||||
public OctetString CommunityString { get; set; }
|
||||
|
||||
public override SnmpVersion SnmpVersion => SnmpVersion.V1;
|
||||
|
||||
public SnmpV1Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = "public";
|
||||
}
|
||||
public SnmpV1Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, OctetString communityString)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = communityString;
|
||||
}
|
||||
public SnmpV1Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, String communityString)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = new OctetString(communityString);
|
||||
}
|
||||
|
||||
public override PDU snmpRequest(PDU pdu)
|
||||
{
|
||||
SnmpV1Message request = new SnmpV1Message();
|
||||
request.MessageID = SNMPEngine.NextMessageID;
|
||||
request.snmpCommunity = CommunityString;
|
||||
request.snmpPDU = pdu;
|
||||
|
||||
SnmpV1Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV1Message;
|
||||
return response.snmpPDU;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
using System;
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public class SnmpV2Channel : SnmpV1Channel
|
||||
{
|
||||
public override SnmpVersion SnmpVersion => SnmpVersion.V2c;
|
||||
|
||||
public SnmpV2Channel(SNMPEngine client)
|
||||
: base(client)
|
||||
{
|
||||
}
|
||||
public SnmpV2Channel(SNMPEngine client, string communityString)
|
||||
: base(client, communityString)
|
||||
{ }
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using ln.snmp.types;
|
||||
using System.Net;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public class SnmpV2Endpoint : SNMPInterface
|
||||
{
|
||||
public OctetString CommunityString { get; set; }
|
||||
|
||||
public override SnmpVersion SnmpVersion => SnmpVersion.V2c;
|
||||
|
||||
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = "public";
|
||||
}
|
||||
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, OctetString communityString)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = communityString;
|
||||
}
|
||||
public SnmpV2Endpoint(SNMPEngine snmpEngine, IPEndPoint remoteEndpoint, String communityString)
|
||||
: base(snmpEngine, remoteEndpoint)
|
||||
{
|
||||
CommunityString = new OctetString(communityString);
|
||||
}
|
||||
|
||||
public override PDU snmpRequest(PDU pdu)
|
||||
{
|
||||
SnmpV2Message request = new SnmpV2Message();
|
||||
request.MessageID = SNMPEngine.NextMessageID;
|
||||
request.snmpCommunity = CommunityString;
|
||||
request.snmpPDU = pdu;
|
||||
|
||||
SnmpV2Message response = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout) as SnmpV2Message;
|
||||
return response.snmpPDU;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
using System;
|
||||
using System.Net;
|
||||
using ln.snmp.types;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
using ln.snmp.asn1;
|
||||
using System.Linq;
|
||||
|
||||
namespace ln.snmp.channel
|
||||
{
|
||||
public enum SnmpV3AuthMethod { MD5, SHA }
|
||||
public enum SnmpV3PrivMethod { DES }
|
||||
public enum SnmpAuthLevel : int { noAuthNoPriv = 0, authNoPriv = 0x01, authPriv = 0x03 }
|
||||
|
||||
public class USMEndpoint : SNMPInterface
|
||||
{
|
||||
public OctetString RemoteEngineID { get; set; }
|
||||
|
||||
public string Username { get; set; }
|
||||
public string AuthKey { get; set; }
|
||||
public string PrivKey { get; set; }
|
||||
|
||||
public SnmpV3AuthMethod AuthMethod { get; set; }
|
||||
public SnmpV3PrivMethod PrivMethod { get; set; }
|
||||
|
||||
public override SnmpVersion SnmpVersion => SnmpVersion.V3;
|
||||
|
||||
public USMEndpoint(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint)
|
||||
:base(snmpEngine,remoteEndpoint)
|
||||
{
|
||||
}
|
||||
|
||||
public SnmpAuthLevel AuthLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
if (PrivKey != null)
|
||||
return SnmpAuthLevel.authPriv;
|
||||
if (AuthKey != null)
|
||||
return SnmpAuthLevel.authNoPriv;
|
||||
|
||||
return SnmpAuthLevel.noAuthNoPriv;
|
||||
}
|
||||
}
|
||||
|
||||
public override PDU snmpRequest(PDU pdu)
|
||||
{
|
||||
if ((RemoteEngineID == null)||(RemoteEngineID.Bytes.Length == 0))
|
||||
{
|
||||
QueryEngineID();
|
||||
}
|
||||
|
||||
USMMessage request = new USMMessage();
|
||||
ScopedPDU scopedPDU = new ScopedPDU();
|
||||
|
||||
request.MessageID = SNMPEngine.NextMessageID;
|
||||
request.msgData = scopedPDU;
|
||||
|
||||
scopedPDU.contextEngineID = RemoteEngineID;
|
||||
scopedPDU.PDU = pdu;
|
||||
|
||||
AuthenticateMessage(request);
|
||||
|
||||
|
||||
SnmpMessage reply = SNMPEngine.SNMPRequest(RemoteEndpoint, request, SNMPEngine.Timeout);
|
||||
USMMessage replyUSM = reply as USMMessage;
|
||||
|
||||
PDU responsePDU = (replyUSM.msgData as ScopedPDU).PDU;
|
||||
|
||||
return responsePDU;
|
||||
}
|
||||
|
||||
public void QueryEngineID()
|
||||
{
|
||||
USMMessage queryMessage = new USMMessage();
|
||||
queryMessage.MessageID = SNMPEngine.NextMessageID;
|
||||
|
||||
ScopedPDU scopedPDU = new ScopedPDU();
|
||||
|
||||
queryMessage.msgData = scopedPDU;
|
||||
|
||||
queryMessage.Dump();
|
||||
|
||||
|
||||
SnmpMessage reply = SNMPEngine.SNMPRequest(RemoteEndpoint, queryMessage, SNMPEngine.Timeout);
|
||||
USMMessage usmReply = reply as USMMessage;
|
||||
|
||||
RemoteEngineID = usmReply.SecurityParameters.msgAuthoritativeEngineID;
|
||||
}
|
||||
|
||||
public bool AuthenticateMessage(USMMessage message)
|
||||
{
|
||||
message.msgGlobalData.msgFlags.Bytes = new byte[] { (byte)(int)AuthLevel };
|
||||
message.SecurityParameters.msgUserName.StringValue = Username;
|
||||
message.SecurityParameters.msgAuthoritativeEngineID = RemoteEngineID;
|
||||
message.SecurityParameters.msgAuthenticationParameters.Bytes = new byte[12];
|
||||
|
||||
byte[] wholeMsg = ((ASN1Value)message).AsByteArray;
|
||||
|
||||
byte[] extendedAuthKey = new byte[64];
|
||||
byte[] authKey = Encoding.ASCII.GetBytes(AuthKey);
|
||||
|
||||
//Array.Copy(authKey, extendedAuthKey, 16);
|
||||
|
||||
//byte[] K1 = new byte[64];
|
||||
//for (int n = 0; n < 64; n++)
|
||||
// K1[n] = (byte)(extendedAuthKey[n] ^ IPAD[n]);
|
||||
|
||||
//byte[] K2 = new byte[64];
|
||||
//for (int n = 0; n < 64; n++)
|
||||
//K2[n] = (byte)(extendedAuthKey[n] ^ OPAD[n]);
|
||||
|
||||
HMAC hmac = null;
|
||||
|
||||
switch (AuthMethod)
|
||||
{
|
||||
case SnmpV3AuthMethod.MD5:
|
||||
hmac = HMACMD5.Create();
|
||||
break;
|
||||
case SnmpV3AuthMethod.SHA:
|
||||
hmac = HMACSHA1.Create();
|
||||
break;
|
||||
}
|
||||
|
||||
hmac.Key = authKey;
|
||||
byte[] mac = hmac.ComputeHash(wholeMsg);
|
||||
|
||||
message.SecurityParameters.msgAuthenticationParameters.Bytes = mac.Take(12).ToArray();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static byte[] IPAD = __PAD(0x36);
|
||||
static byte[] OPAD = __PAD(0x5C);
|
||||
|
||||
public static byte[] __PAD(byte pad)
|
||||
{
|
||||
byte[] ipad = new byte[0x40];
|
||||
for (int n = 0; n < ipad.Length; n++)
|
||||
ipad[n] = pad;
|
||||
return ipad;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -46,13 +46,28 @@
|
|||
<Compile Include="types\Counter64.cs" />
|
||||
<Compile Include="SNMPInterface.cs" />
|
||||
<Compile Include="SnmpError.cs" />
|
||||
<Compile Include="channel\SnmpPDUChannel.cs" />
|
||||
<Compile Include="channel\SnmpV1Channel.cs" />
|
||||
<Compile Include="channel\SnmpV2Channel.cs" />
|
||||
<Compile Include="channel\SnmpV1Endpoint.cs" />
|
||||
<Compile Include="channel\SnmpV2Endpoint.cs" />
|
||||
<Compile Include="channel\USMEndpoint.cs" />
|
||||
<Compile Include="types\V3Packet.cs" />
|
||||
<Compile Include="types\ScopedPDU.cs" />
|
||||
<Compile Include="asn1\ASN1Value.cs" />
|
||||
<Compile Include="types\SnmpV1Message.cs" />
|
||||
<Compile Include="types\SnmpMessage.cs" />
|
||||
<Compile Include="types\SnmpV2Message.cs" />
|
||||
<Compile Include="types\USMMessage.cs" />
|
||||
<Compile Include="types\UsmSecurityParameters.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="types\" />
|
||||
<Folder Include="channel\" />
|
||||
<Folder Include="asn1\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ln.logging\ln.logging.csproj">
|
||||
<Project>{D471A566-9FB6-41B2-A777-3C32874ECD0E}</Project>
|
||||
<Name>ln.logging</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
|
@ -8,6 +8,8 @@
|
|||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class Boolean : Variable
|
||||
|
@ -19,6 +21,7 @@ namespace ln.snmp.types
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
public override byte[] Bytes
|
||||
{
|
||||
get => BooleanValue ? new byte[] { 0xFF } : new byte[] { 0x00 };
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
using ln.logging;
|
||||
using System.Linq;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class Integer : Variable
|
||||
|
@ -30,10 +33,11 @@ namespace ln.snmp.types
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
public override byte[] Bytes
|
||||
{
|
||||
get => BasicEncodingRules.EncodeInteger(LongValue);
|
||||
set => LongValue = BasicEncodingRules.DecodeInteger(value);
|
||||
set => LongValue = BasicEncodingRules.DecodeInteger(value.Reverse().ToArray());
|
||||
}
|
||||
public override object Value { get => LongValue; set => LongValue = (long)value; }
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class NullValue : Variable
|
||||
|
@ -16,7 +17,7 @@ namespace ln.snmp.types
|
|||
|
||||
byte[] value = new byte[0];
|
||||
|
||||
private NullValue()
|
||||
public NullValue()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL,false,0x05))
|
||||
{
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// **/
|
||||
using System;
|
||||
using System.Linq;
|
||||
using ln.snmp.asn1;
|
||||
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class ObjectIdentifier : Variable
|
||||
|
@ -32,6 +34,7 @@ namespace ln.snmp.types
|
|||
OIDValue = ioid;
|
||||
}
|
||||
|
||||
|
||||
/* Check is b is part of the my subtree or is equal*/
|
||||
public bool Contains(ObjectIdentifier b)
|
||||
{
|
||||
|
|
|
@ -9,35 +9,48 @@
|
|||
// **/
|
||||
using System;
|
||||
using System.Text;
|
||||
using ln.snmp.asn1;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class OctetString : Variable
|
||||
{
|
||||
public string StringValue { get; set; }
|
||||
public override byte[] Bytes { get; set; }
|
||||
|
||||
public string StringValue {
|
||||
get => Encoding.UTF8.GetString(Bytes);
|
||||
set => Bytes = Encoding.UTF8.GetBytes(value);
|
||||
}
|
||||
|
||||
public char[] Characters
|
||||
{
|
||||
get => StringValue.ToCharArray();
|
||||
set => StringValue = new string(value);
|
||||
}
|
||||
public override object Value { get => Bytes; set => Bytes = (byte[])value; }
|
||||
|
||||
public OctetString()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL, false, 4))
|
||||
{
|
||||
StringValue = "";
|
||||
}
|
||||
|
||||
public OctetString(String text)
|
||||
:this()
|
||||
: this()
|
||||
{
|
||||
StringValue = text;
|
||||
}
|
||||
|
||||
public override byte[] Bytes {
|
||||
get => Encoding.UTF8.GetBytes(StringValue);
|
||||
set => StringValue = Encoding.UTF8.GetString(value);
|
||||
}
|
||||
public override object Value {
|
||||
get => StringValue;
|
||||
set => StringValue = value as string;
|
||||
}
|
||||
public OctetString(byte[] bytes)
|
||||
: this()
|
||||
{
|
||||
Bytes = bytes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("[OctetString StringValue={0}]", StringValue);
|
||||
return String.Format("[OctetString StringValue={0}]", StringValue.Replace("\0","\\0"));
|
||||
}
|
||||
|
||||
public static implicit operator String(OctetString octetString)
|
||||
|
|
64
types/PDU.cs
64
types/PDU.cs
|
@ -9,6 +9,7 @@
|
|||
// **/
|
||||
using System;
|
||||
using System.IO;
|
||||
using ln.snmp.asn1;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class PDU : AbstractSequence
|
||||
|
@ -22,9 +23,10 @@ namespace ln.snmp.types
|
|||
private Variable[] items;
|
||||
|
||||
public PDU(Identifier identifier)
|
||||
:base(identifier)
|
||||
: base(identifier)
|
||||
{
|
||||
RequestID = new Integer(Environment.TickCount);
|
||||
//RequestID = new Integer(Environment.TickCount);
|
||||
RequestID = new Integer(0xDEADBEEF);
|
||||
Error = new Integer();
|
||||
ErrorIndex = new Integer();
|
||||
|
||||
|
@ -33,7 +35,27 @@ namespace ln.snmp.types
|
|||
items = new Variable[] { RequestID, Error, ErrorIndex, VarBinds };
|
||||
}
|
||||
|
||||
public override Variable[] Items => items;
|
||||
public PDU(ASN1Value value)
|
||||
: base(value.Identifier)
|
||||
{
|
||||
RequestID = (Integer)value.Items[0];
|
||||
|
||||
Error = (Integer)value.Items[1];
|
||||
Error = (Integer)value.Items[2];
|
||||
VarBinds = (Sequence)value.Items[3];
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => items;
|
||||
set
|
||||
{
|
||||
RequestID = value[0] as Integer;
|
||||
Error = value[1] as Integer;
|
||||
ErrorIndex= value[2] as Integer;
|
||||
VarBinds = value[3] as Sequence;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(Variable item)
|
||||
{
|
||||
|
@ -45,18 +67,6 @@ namespace ln.snmp.types
|
|||
VarBinds.Remove(item);
|
||||
}
|
||||
|
||||
public override byte[] Bytes
|
||||
{
|
||||
set
|
||||
{
|
||||
MemoryStream bytes = new MemoryStream(value);
|
||||
|
||||
RequestID = Variable.Read(bytes) as Integer;
|
||||
Error = Variable.Read(bytes) as Integer;
|
||||
ErrorIndex = Variable.Read(bytes) as Integer;
|
||||
VarBinds = Variable.Read(bytes) as Sequence;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -67,20 +77,32 @@ namespace ln.snmp.types
|
|||
public GetRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x00))
|
||||
{
|
||||
}
|
||||
public GetRequest(ASN1Value value)
|
||||
: base(value)
|
||||
{ }
|
||||
|
||||
}
|
||||
public class GetNextRequest : PDU
|
||||
{
|
||||
public GetNextRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x01))
|
||||
{
|
||||
}
|
||||
public GetNextRequest(ASN1Value value)
|
||||
: base(value)
|
||||
{ }
|
||||
|
||||
}
|
||||
public class GetResponse : PDU
|
||||
{
|
||||
public GetResponse() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x02))
|
||||
{
|
||||
}
|
||||
// public GetResponse(ASN1Value value)
|
||||
//: base(value)
|
||||
//{ }
|
||||
|
||||
}
|
||||
public class GetBulkRequest: PDU
|
||||
public class GetBulkRequest : PDU
|
||||
{
|
||||
public Integer NonRepeaters => Error;
|
||||
public Integer MaxRepetitions => ErrorIndex;
|
||||
|
@ -89,14 +111,22 @@ namespace ln.snmp.types
|
|||
{
|
||||
NonRepeaters.LongValue = 0;
|
||||
MaxRepetitions.LongValue = 32;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public class SetRequest : PDU
|
||||
{
|
||||
public SetRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x03))
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class Report: PDU
|
||||
{
|
||||
public Report() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x08))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// /**
|
||||
// * File: ScopedPDU.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class ScopedPDU : AbstractSequence
|
||||
{
|
||||
public OctetString contextEngineID { get; set; }
|
||||
public OctetString contextName { get; set; }
|
||||
|
||||
public PDU PDU { get; set; }
|
||||
|
||||
public ScopedPDU()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL,true,0x10))
|
||||
{
|
||||
contextEngineID = new OctetString();
|
||||
contextName = new OctetString();
|
||||
PDU = new GetRequest();
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] { contextEngineID, contextName, PDU };
|
||||
set
|
||||
{
|
||||
contextEngineID = value[0] as OctetString;
|
||||
contextName = value[1] as OctetString;
|
||||
PDU = value[2] as PDU;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(Variable item) => throw new NotImplementedException();
|
||||
public override void Remove(Variable item) => throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using ln.snmp.asn1;
|
||||
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class Sequence : AbstractSequence
|
||||
|
@ -29,7 +31,13 @@ namespace ln.snmp.types
|
|||
Add(variable);
|
||||
}
|
||||
|
||||
public override Variable[] Items => items.ToArray();
|
||||
public override Variable[] Items {
|
||||
get => items.ToArray();
|
||||
set
|
||||
{
|
||||
items = new List<Variable>(value);
|
||||
}
|
||||
}
|
||||
public override void Add(Variable item)
|
||||
{
|
||||
this.items.Add(item);
|
||||
|
@ -51,8 +59,9 @@ namespace ln.snmp.types
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
/* Items */
|
||||
public abstract Variable[] Items { get; }
|
||||
public abstract Variable[] Items { get; set; }
|
||||
public abstract void Add(Variable item);
|
||||
public abstract void Remove(Variable item);
|
||||
public virtual void Remove(int n)
|
||||
|
@ -74,29 +83,31 @@ namespace ln.snmp.types
|
|||
{
|
||||
get
|
||||
{
|
||||
MemoryStream payload = new MemoryStream();
|
||||
MemoryStream stream = new MemoryStream();
|
||||
|
||||
foreach (Variable item in Items)
|
||||
foreach (byte[] binaryItem in Items.Select((x) => (ASN1Value)x).Select((asn1) => asn1.AsByteArray).ToArray())
|
||||
{
|
||||
item.Write(payload);
|
||||
stream.Write(binaryItem, 0, binaryItem.Length);
|
||||
}
|
||||
|
||||
return payload.ToArray();
|
||||
return stream.ToArray();
|
||||
}
|
||||
set
|
||||
{
|
||||
MemoryStream bytes = new MemoryStream(value);
|
||||
List<ASN1Value> items = new List<ASN1Value>();
|
||||
MemoryStream stream = new MemoryStream(value);
|
||||
|
||||
while (bytes.Position < bytes.Length)
|
||||
while (stream.Position < stream.Length)
|
||||
{
|
||||
Add(Variable.Read(bytes));
|
||||
items.Add(new ASN1Value(stream));
|
||||
}
|
||||
Items = items.Select((x) => (Variable)x).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[Sequence {0}]",String.Join(", ",Items.Select((x) => x.ToString())));
|
||||
return string.Format("[{1} {0}]",String.Join(", ",Items.Select((x) => x?.ToString())),GetType().Name);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// /**
|
||||
// * File: SnmpMessage.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public abstract class SnmpMessage : AbstractSequence
|
||||
{
|
||||
public SnmpVersion SnmpVersion { get; }
|
||||
|
||||
public abstract int MessageID { get; set; }
|
||||
|
||||
|
||||
public SnmpMessage(SnmpVersion snmpVersion)
|
||||
: base(new Identifier(IdentifierClass.UNIVERSAL, true, 0x10))
|
||||
{
|
||||
SnmpVersion = snmpVersion;
|
||||
}
|
||||
|
||||
public override void Add(Variable item) => throw new NotImplementedException();
|
||||
public override void Remove(Variable item) => throw new NotImplementedException();
|
||||
|
||||
|
||||
public static implicit operator SnmpMessage(ASN1Value asn)
|
||||
{
|
||||
Integer snmpVersion = (Integer)(Variable)asn.Items[0];
|
||||
switch (snmpVersion.LongValue)
|
||||
{
|
||||
case 0:
|
||||
return new SnmpV1Message(asn);
|
||||
case 1:
|
||||
return new SnmpV2Message(asn);
|
||||
case 3:
|
||||
return new USMMessage(asn);
|
||||
}
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
// /**
|
||||
// * File: SnmpV1Message.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class SnmpV1Message : SnmpMessage
|
||||
{
|
||||
public OctetString snmpCommunity { get; set; }
|
||||
public PDU snmpPDU { get; set; }
|
||||
|
||||
public SnmpV1Message()
|
||||
:base(SnmpVersion.V1)
|
||||
{
|
||||
}
|
||||
public SnmpV1Message(ASN1Value value)
|
||||
:this()
|
||||
{
|
||||
snmpCommunity = (OctetString)value.Items[1];
|
||||
snmpPDU = (PDU)value.Items[2];
|
||||
}
|
||||
|
||||
public override int MessageID
|
||||
{
|
||||
get => (int)snmpPDU.RequestID.LongValue;
|
||||
set => snmpPDU.RequestID.LongValue = value;
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] { new Integer((int)SnmpVersion), snmpCommunity, snmpPDU };
|
||||
set
|
||||
{
|
||||
snmpCommunity = value[1] as OctetString;
|
||||
snmpPDU = value[2] as PDU;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
// /**
|
||||
// * File: SnmpV1Message.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
using ln.logging;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class SnmpV2Message : SnmpMessage
|
||||
{
|
||||
public OctetString snmpCommunity { get; set; }
|
||||
public PDU snmpPDU { get; set; }
|
||||
|
||||
public SnmpV2Message()
|
||||
:base(SnmpVersion.V2c)
|
||||
{
|
||||
}
|
||||
public SnmpV2Message(ASN1Value value)
|
||||
:this()
|
||||
{
|
||||
snmpCommunity = (OctetString)value.Items[1];
|
||||
|
||||
Logging.Log(LogLevel.DEBUG, "ASN1Value->PDU: {0}", value.Items[2]);
|
||||
snmpPDU = (PDU)value.Items[2];
|
||||
Logging.Log(LogLevel.DEBUG, "PDU: {0}", snmpPDU);
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] { new Integer((int)SnmpVersion), snmpCommunity, snmpPDU };
|
||||
set
|
||||
{
|
||||
snmpCommunity = value[1] as OctetString;
|
||||
snmpPDU = value[2] as PDU;
|
||||
}
|
||||
}
|
||||
|
||||
public override int MessageID
|
||||
{
|
||||
get => (int)snmpPDU.RequestID.LongValue;
|
||||
set => snmpPDU.RequestID.LongValue = value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
// /**
|
||||
// * File: USMMessage.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
using System.Linq;
|
||||
using ln.snmp.channel;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class USMMessage : SnmpMessage
|
||||
{
|
||||
public SnmpV3AuthMethod AuthMethod { get; set; }
|
||||
public SnmpV3PrivMethod PrivMethod { get; set; }
|
||||
|
||||
public Integer msgVersion { get; } = new Integer(3);
|
||||
public MsgGlobalData msgGlobalData { get; set; }
|
||||
public UsmSecurityParameters SecurityParameters { get; set; }
|
||||
|
||||
public Variable msgData { get; set; }
|
||||
|
||||
public USMMessage()
|
||||
: base(SnmpVersion.V3)
|
||||
{
|
||||
msgGlobalData = new MsgGlobalData();
|
||||
SecurityParameters = new UsmSecurityParameters();
|
||||
msgData = new NullValue();
|
||||
}
|
||||
|
||||
public USMMessage(ASN1Value asn)
|
||||
:this()
|
||||
{
|
||||
Items = asn.Items.Select((x) => (Variable)x).ToArray();
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] {
|
||||
msgVersion,
|
||||
msgGlobalData,
|
||||
new OctetString(((ASN1Value)SecurityParameters).AsByteArray),
|
||||
msgData
|
||||
};
|
||||
set
|
||||
{
|
||||
msgGlobalData = new MsgGlobalData(value[1]);
|
||||
SecurityParameters = new UsmSecurityParameters(new ASN1Value(value[2].Bytes));
|
||||
msgData = value[3];
|
||||
}
|
||||
}
|
||||
|
||||
public override int MessageID
|
||||
{
|
||||
get => (int)msgGlobalData.msgID.LongValue;
|
||||
set => msgGlobalData.msgID.LongValue = value;
|
||||
}
|
||||
|
||||
public override void Add(Variable item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public override void Remove(Variable item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public class MsgGlobalData : AbstractSequence
|
||||
{
|
||||
public Integer msgID { get; set; }
|
||||
public Integer msgMaxSize { get; set; }
|
||||
public OctetString msgFlags { get; set; }
|
||||
public Integer msgSecurityModel { get; set; }
|
||||
|
||||
public MsgGlobalData()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL,true,0x10))
|
||||
{
|
||||
msgID = new Integer((int)(DateTimeOffset.Now.ToUnixTimeSeconds()));
|
||||
msgMaxSize = new Integer(65000);
|
||||
msgFlags = new OctetString("\0");
|
||||
msgSecurityModel = new Integer(3);
|
||||
}
|
||||
public MsgGlobalData(ASN1Value asn)
|
||||
:this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Add(Variable item) => throw new NotImplementedException();
|
||||
public override void Remove(Variable item) => throw new NotImplementedException();
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] { msgID,msgMaxSize,msgFlags,msgSecurityModel };
|
||||
set
|
||||
{
|
||||
msgID = value[0] as Integer;
|
||||
msgMaxSize = value[1] as Integer;
|
||||
msgFlags = value[2] as OctetString;
|
||||
msgSecurityModel = value[3] as Integer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
// /**
|
||||
// * File: UsmSecurityParameters.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using ln.snmp.asn1;
|
||||
using System.Linq;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class UsmSecurityParameters : AbstractSequence
|
||||
{
|
||||
public OctetString msgAuthoritativeEngineID { get; set; }
|
||||
public Integer msgAuthoritativeEngineBoots { get; set; }
|
||||
public Integer msgAuthoritativeEngineTime { get; set; }
|
||||
|
||||
public OctetString msgUserName { get; set; }
|
||||
public OctetString msgAuthenticationParameters { get; set; }
|
||||
public OctetString msgPrivacyParameters { get; set; }
|
||||
|
||||
|
||||
public UsmSecurityParameters()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL,true,0x10))
|
||||
{
|
||||
msgAuthoritativeEngineID = new OctetString();
|
||||
msgAuthoritativeEngineBoots = new Integer();
|
||||
msgAuthoritativeEngineTime = new Integer();
|
||||
|
||||
msgUserName = new OctetString();
|
||||
msgAuthenticationParameters = new OctetString();
|
||||
msgPrivacyParameters = new OctetString();
|
||||
}
|
||||
|
||||
public UsmSecurityParameters(ASN1Value asn)
|
||||
:base(asn.Identifier)
|
||||
{
|
||||
Items = asn.Items.Select((x) => (Variable)x).ToArray();
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => new Variable[] {
|
||||
msgAuthoritativeEngineID,
|
||||
msgAuthoritativeEngineBoots,
|
||||
msgAuthoritativeEngineTime,
|
||||
msgUserName,
|
||||
msgAuthenticationParameters,
|
||||
msgPrivacyParameters
|
||||
};
|
||||
set
|
||||
{
|
||||
msgAuthoritativeEngineID = value[0] as OctetString;
|
||||
msgAuthoritativeEngineBoots = value[1] as Integer;
|
||||
msgAuthoritativeEngineTime = value[2] as Integer;
|
||||
msgUserName = value[3] as OctetString;
|
||||
msgAuthenticationParameters = value[4] as OctetString;
|
||||
msgPrivacyParameters = value[5] as OctetString;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Add(Variable item) => throw new NotImplementedException();
|
||||
public override void Remove(Variable item) => throw new NotImplementedException();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
// /**
|
||||
// * File: V3Packet.cs
|
||||
// * Author: haraldwolff
|
||||
// *
|
||||
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
||||
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
||||
// *
|
||||
// *
|
||||
// **/
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public class V3Packet : AbstractSequence
|
||||
{
|
||||
public Integer msgVersion { get; }
|
||||
public Sequence msgGlobalData { get; }
|
||||
|
||||
public Integer msgID { get; }
|
||||
public Integer msgMaxSize { get; }
|
||||
public OctetString msgFlags { get; }
|
||||
public Integer msgSecurityModel { get; }
|
||||
|
||||
public V3Packet()
|
||||
:base(new Identifier(IdentifierClass.UNIVERSAL,true,0x10))
|
||||
{
|
||||
msgVersion = new Integer(3);
|
||||
msgGlobalData = new Sequence();
|
||||
|
||||
msgID = new Integer(DateTimeOffset.Now.ToUnixTimeSeconds());
|
||||
msgMaxSize = new Integer(65000);
|
||||
msgSecurityModel = new Integer(3);
|
||||
}
|
||||
|
||||
public override Variable[] Items
|
||||
{
|
||||
get => throw new NotImplementedException();
|
||||
set => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Add(Variable item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Remove(Variable item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,12 @@
|
|||
// **/
|
||||
using System;
|
||||
using System.IO;
|
||||
using ln.snmp.asn1;
|
||||
using ln.logging;
|
||||
using System.Collections.Generic;
|
||||
using System.CodeDom;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
namespace ln.snmp.types
|
||||
{
|
||||
public abstract class Variable
|
||||
|
@ -23,96 +29,110 @@ namespace ln.snmp.types
|
|||
public abstract byte[] Bytes { get; set; }
|
||||
public abstract object Value { get; set; }
|
||||
|
||||
public virtual void Write(Stream stream)
|
||||
public void Dump()
|
||||
{
|
||||
byte[] payload = Bytes;
|
||||
|
||||
BasicEncodingRules.WriteIdentifier(stream,Identifier);
|
||||
BasicEncodingRules.WriteLength(stream, payload.Length);
|
||||
stream.Write(payload, 0, payload.Length);
|
||||
Dump("");
|
||||
}
|
||||
|
||||
public byte[] ToBytes()
|
||||
public void Dump(string prefix)
|
||||
{
|
||||
MemoryStream memoryStream = new MemoryStream();
|
||||
Write(memoryStream);
|
||||
return memoryStream.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public static Variable Read(Stream stream)
|
||||
{
|
||||
Variable variable = null;
|
||||
|
||||
Identifier identifier = BasicEncodingRules.ReadIdentifier(stream);
|
||||
int length = BasicEncodingRules.ReadLength(stream);
|
||||
byte[] payload = new byte[length];
|
||||
stream.Read(payload, 0, length);
|
||||
|
||||
variable = FromIdentifier(identifier);
|
||||
variable.Bytes = payload;
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
public static Variable Read(byte[] bytes)
|
||||
{
|
||||
MemoryStream stream = new MemoryStream(bytes);
|
||||
return Read(stream);
|
||||
}
|
||||
|
||||
public static void Write(Stream stream,Variable variable)
|
||||
{
|
||||
variable.Write(stream);
|
||||
}
|
||||
|
||||
|
||||
public static Variable FromIdentifier(Identifier identifier)
|
||||
{
|
||||
if (identifier.IdentifierClass == IdentifierClass.UNIVERSAL)
|
||||
if (this is AbstractSequence)
|
||||
{
|
||||
switch (identifier.Number)
|
||||
AbstractSequence sequence = this as AbstractSequence;
|
||||
Logging.Log(LogLevel.DEBUG, "{0}{1}", prefix, this.ToString());
|
||||
foreach (Variable item in sequence.Items)
|
||||
{
|
||||
case 0x02:
|
||||
return new Integer();
|
||||
case 0x04:
|
||||
return new OctetString();
|
||||
case 0x05:
|
||||
return NullValue.Instance;
|
||||
case 0x06:
|
||||
return new ObjectIdentifier();
|
||||
case 0x10:
|
||||
return new Sequence();
|
||||
if (item != null)
|
||||
item.Dump(prefix + " ");
|
||||
else
|
||||
Logging.Log(LogLevel.DEBUG, "{0}NULL", prefix);
|
||||
}
|
||||
}
|
||||
else if (identifier.IdentifierClass == IdentifierClass.CONTEXT)
|
||||
else
|
||||
{
|
||||
switch (identifier.Number)
|
||||
{
|
||||
case 0x00:
|
||||
return new GetRequest();
|
||||
case 0x02:
|
||||
return new GetResponse();
|
||||
case 0x03:
|
||||
return new SetRequest();
|
||||
}
|
||||
Logging.Log(LogLevel.DEBUG, "{0}{1} {2}", prefix, this.ToString(), BitConverter.ToString(this.Bytes));
|
||||
}
|
||||
else if (identifier.IdentifierClass == IdentifierClass.APPLICATION)
|
||||
{
|
||||
switch (identifier.Number)
|
||||
{
|
||||
case 0x01:
|
||||
return new Counter32();
|
||||
case 0x02:
|
||||
return new Unsigned32();
|
||||
case 0x06:
|
||||
return new Counter64();
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotSupportedException(String.Format("Unsupported ASN Type: {0}",identifier));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static implicit operator ASN1Value(Variable variable)
|
||||
{
|
||||
ASN1Value value = new ASN1Value(variable.Identifier);
|
||||
if (variable is AbstractSequence)
|
||||
{
|
||||
AbstractSequence sequence = variable as AbstractSequence;
|
||||
foreach (Variable item in sequence.Items)
|
||||
value.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
value.Bytes = variable.Bytes;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static implicit operator Variable(ASN1Value value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (knownTypes.ContainsKey(value.Identifier))
|
||||
{
|
||||
Type type = knownTypes[value.Identifier];
|
||||
|
||||
//Logging.Log(LogLevel.DEBUGDETAIL, "ASN1Value->Variable: {0} -> {1}", value, type.Name);
|
||||
|
||||
Variable variable = Activator.CreateInstance(type,true) as Variable;
|
||||
if (variable is AbstractSequence)
|
||||
{
|
||||
AbstractSequence sequence = variable as AbstractSequence;
|
||||
sequence.Items = value.Items.Select((x) => (Variable)x).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
variable.Bytes = value.Bytes;
|
||||
}
|
||||
|
||||
return variable;
|
||||
}
|
||||
throw new ArgumentException(String.Format("{0}",value.Identifier),nameof(value));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logging.Log(e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Dictionary<Identifier, Type> knownTypes = new Dictionary<Identifier, Type>();
|
||||
static bool __initialized__ = initialize();
|
||||
|
||||
static void registerKnownType<T>() where T:Variable, new()
|
||||
{
|
||||
T i = new T();
|
||||
knownTypes.Add(i.Identifier, typeof(T));
|
||||
}
|
||||
|
||||
static bool initialize()
|
||||
{
|
||||
registerKnownType<NullValue>();
|
||||
registerKnownType<Boolean>();
|
||||
registerKnownType<Integer>();
|
||||
registerKnownType<OctetString>();
|
||||
registerKnownType<Unsigned32>();
|
||||
registerKnownType<Counter32>();
|
||||
registerKnownType<Counter64>();
|
||||
registerKnownType<Sequence>();
|
||||
registerKnownType<ObjectIdentifier>();
|
||||
|
||||
registerKnownType<GetRequest>();
|
||||
registerKnownType<GetNextRequest>();
|
||||
registerKnownType<GetResponse>();
|
||||
registerKnownType<GetBulkRequest>();
|
||||
registerKnownType<Report>();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue