USM WIP
parent
1b4c13e5f5
commit
e6b25374f3
|
@ -47,7 +47,7 @@ namespace ln.snmp
|
||||||
|
|
||||||
public override string ToString()
|
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.Sockets;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using ln.snmp.asn1;
|
||||||
|
using ln.logging;
|
||||||
|
|
||||||
namespace ln.snmp
|
namespace ln.snmp
|
||||||
{
|
{
|
||||||
|
@ -23,10 +25,14 @@ namespace ln.snmp
|
||||||
public UdpClient LocalEndpoint { get; private set; }
|
public UdpClient LocalEndpoint { get; private set; }
|
||||||
public int Timeout { get; set; } = 1000;
|
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 bool shutdown = false;
|
||||||
private Thread ReceiverThread { get; set; }
|
private Thread ReceiverThread { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
private int nextMessageID = (int)DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||||
|
public int NextMessageID => nextMessageID++;
|
||||||
|
|
||||||
public SNMPEngine()
|
public SNMPEngine()
|
||||||
{
|
{
|
||||||
LocalEndpoint = new UdpClient();
|
LocalEndpoint = new UdpClient();
|
||||||
|
@ -55,86 +61,81 @@ namespace ln.snmp
|
||||||
IPEndPoint remoteEndpoint = null;
|
IPEndPoint remoteEndpoint = null;
|
||||||
byte[] datagram = LocalEndpoint.Receive(ref remoteEndpoint);
|
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)
|
lock (queuedRequests)
|
||||||
{
|
{
|
||||||
if (queuedRequests.ContainsKey(remoteEndpoint))
|
if (queuedRequests.ContainsKey(snmpMessage.MessageID))
|
||||||
{
|
{
|
||||||
InternalRequest internalRequest = queuedRequests[remoteEndpoint];
|
SnmpMessage snmpRequestMessage = queuedRequests[snmpMessage.MessageID];
|
||||||
internalRequest.Response = datagram;
|
lock (snmpRequestMessage)
|
||||||
lock (internalRequest)
|
|
||||||
{
|
{
|
||||||
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)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
Logging.Log(se);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
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();
|
lock (queuedRequests)
|
||||||
internalRequest.RemoteEndpoint = remoteEndpoint;
|
|
||||||
|
|
||||||
lock(queuedRequests)
|
|
||||||
{
|
{
|
||||||
if (queuedRequests.ContainsKey(remoteEndpoint))
|
ASN1Value snmpRequest = snmpMessage;
|
||||||
throw new ArgumentException("Already pending request exists for this remote endpoint", nameof(remoteEndpoint));
|
byte[] snmpRequestBytes = snmpRequest.AsByteArray;
|
||||||
|
|
||||||
queuedRequests.Add(remoteEndpoint,internalRequest);
|
queuedRequests.Add(snmpMessage.MessageID, snmpMessage);
|
||||||
|
|
||||||
if (DEBUG)
|
Logging.Log(LogLevel.DEBUG,"SNMPClient: Send: {0}", BitConverter.ToString(snmpRequestBytes));
|
||||||
Console.WriteLine("SNMPClient: Send: {0}", BitConverter.ToString(request));
|
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);
|
Monitor.Exit(queuedRequests);
|
||||||
bool success = Monitor.Wait(internalRequest, timeout);
|
bool success = Monitor.Wait(snmpMessage, timeout);
|
||||||
Monitor.Enter(queuedRequests);
|
Monitor.Enter(queuedRequests);
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
|
queuedRequests.Remove(snmpMessage.MessageID);
|
||||||
throw new TimeoutException();
|
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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (ReceiverThread != null)
|
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 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 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;
|
RemoteEndpoint = remoteEndpoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract PDU snmpRequest(PDU pdu);
|
||||||
|
|
||||||
private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new()
|
private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new()
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,13 @@ namespace ln.snmp
|
||||||
}
|
}
|
||||||
|
|
||||||
PDU responsePDU = snmpRequest(pdu);
|
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;
|
Sequence varBinds = responsePDU.VarBinds as Sequence;
|
||||||
|
|
||||||
List<Sequence> results = new List<Sequence>();
|
List<Sequence> results = new List<Sequence>();
|
||||||
|
@ -44,12 +51,6 @@ namespace ln.snmp
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PDU snmpRequest(PDU pdu)
|
|
||||||
{
|
|
||||||
GetResponse responsePDU = PDUChannel.RequestResponse(pdu, RemoteEndpoint) as GetResponse;
|
|
||||||
return responsePDU;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Sequence> snmpGet(IEnumerable<ObjectIdentifier> objectIdentifiers)
|
public List<Sequence> snmpGet(IEnumerable<ObjectIdentifier> objectIdentifiers)
|
||||||
{
|
{
|
||||||
return snmpRequest<GetRequest>(objectIdentifiers);
|
return snmpRequest<GetRequest>(objectIdentifiers);
|
||||||
|
@ -224,14 +225,10 @@ namespace ln.snmp
|
||||||
}
|
}
|
||||||
return results.ToArray();
|
return results.ToArray();
|
||||||
}
|
}
|
||||||
else if (SnmpVersion == SnmpVersion.V2c)
|
else
|
||||||
{
|
{
|
||||||
return snmpGetBulk(objectIdentifiers);
|
return snmpGetBulk(objectIdentifiers);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public Sequence[][] snmpWalk(IEnumerable<String> objectIdentifiers)
|
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="types\Counter64.cs" />
|
||||||
<Compile Include="SNMPInterface.cs" />
|
<Compile Include="SNMPInterface.cs" />
|
||||||
<Compile Include="SnmpError.cs" />
|
<Compile Include="SnmpError.cs" />
|
||||||
<Compile Include="channel\SnmpPDUChannel.cs" />
|
<Compile Include="channel\SnmpV1Endpoint.cs" />
|
||||||
<Compile Include="channel\SnmpV1Channel.cs" />
|
<Compile Include="channel\SnmpV2Endpoint.cs" />
|
||||||
<Compile Include="channel\SnmpV2Channel.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>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="types\" />
|
<Folder Include="types\" />
|
||||||
<Folder Include="channel\" />
|
<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>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -8,6 +8,8 @@
|
||||||
// *
|
// *
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
|
using ln.snmp.asn1;
|
||||||
|
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class Boolean : Variable
|
public class Boolean : Variable
|
||||||
|
@ -19,6 +21,7 @@ namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override byte[] Bytes
|
public override byte[] Bytes
|
||||||
{
|
{
|
||||||
get => BooleanValue ? new byte[] { 0xFF } : new byte[] { 0x00 };
|
get => BooleanValue ? new byte[] { 0xFF } : new byte[] { 0x00 };
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
// *
|
// *
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
|
using ln.snmp.asn1;
|
||||||
|
using ln.logging;
|
||||||
|
using System.Linq;
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class Integer : Variable
|
public class Integer : Variable
|
||||||
|
@ -30,10 +33,11 @@ namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public override byte[] Bytes
|
public override byte[] Bytes
|
||||||
{
|
{
|
||||||
get => BasicEncodingRules.EncodeInteger(LongValue);
|
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; }
|
public override object Value { get => LongValue; set => LongValue = (long)value; }
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
// *
|
// *
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
|
using ln.snmp.asn1;
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class NullValue : Variable
|
public class NullValue : Variable
|
||||||
|
@ -16,7 +17,7 @@ namespace ln.snmp.types
|
||||||
|
|
||||||
byte[] value = new byte[0];
|
byte[] value = new byte[0];
|
||||||
|
|
||||||
private NullValue()
|
public NullValue()
|
||||||
:base(new Identifier(IdentifierClass.UNIVERSAL,false,0x05))
|
:base(new Identifier(IdentifierClass.UNIVERSAL,false,0x05))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using ln.snmp.asn1;
|
||||||
|
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class ObjectIdentifier : Variable
|
public class ObjectIdentifier : Variable
|
||||||
|
@ -32,6 +34,7 @@ namespace ln.snmp.types
|
||||||
OIDValue = ioid;
|
OIDValue = ioid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check is b is part of the my subtree or is equal*/
|
/* Check is b is part of the my subtree or is equal*/
|
||||||
public bool Contains(ObjectIdentifier b)
|
public bool Contains(ObjectIdentifier b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,35 +9,48 @@
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using ln.snmp.asn1;
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class OctetString : Variable
|
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()
|
public OctetString()
|
||||||
:base(new Identifier(IdentifierClass.UNIVERSAL, false, 4))
|
:base(new Identifier(IdentifierClass.UNIVERSAL, false, 4))
|
||||||
{
|
{
|
||||||
|
StringValue = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public OctetString(String text)
|
public OctetString(String text)
|
||||||
:this()
|
: this()
|
||||||
{
|
{
|
||||||
StringValue = text;
|
StringValue = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override byte[] Bytes {
|
public OctetString(byte[] bytes)
|
||||||
get => Encoding.UTF8.GetBytes(StringValue);
|
: this()
|
||||||
set => StringValue = Encoding.UTF8.GetString(value);
|
{
|
||||||
}
|
Bytes = bytes;
|
||||||
public override object Value {
|
}
|
||||||
get => StringValue;
|
|
||||||
set => StringValue = value as string;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
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)
|
public static implicit operator String(OctetString octetString)
|
||||||
|
|
64
types/PDU.cs
64
types/PDU.cs
|
@ -9,6 +9,7 @@
|
||||||
// **/
|
// **/
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using ln.snmp.asn1;
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class PDU : AbstractSequence
|
public class PDU : AbstractSequence
|
||||||
|
@ -22,9 +23,10 @@ namespace ln.snmp.types
|
||||||
private Variable[] items;
|
private Variable[] items;
|
||||||
|
|
||||||
public PDU(Identifier identifier)
|
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();
|
Error = new Integer();
|
||||||
ErrorIndex = new Integer();
|
ErrorIndex = new Integer();
|
||||||
|
|
||||||
|
@ -33,7 +35,27 @@ namespace ln.snmp.types
|
||||||
items = new Variable[] { RequestID, Error, ErrorIndex, VarBinds };
|
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)
|
public override void Add(Variable item)
|
||||||
{
|
{
|
||||||
|
@ -45,18 +67,6 @@ namespace ln.snmp.types
|
||||||
VarBinds.Remove(item);
|
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() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x00))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public GetRequest(ASN1Value value)
|
||||||
|
: base(value)
|
||||||
|
{ }
|
||||||
|
|
||||||
}
|
}
|
||||||
public class GetNextRequest : PDU
|
public class GetNextRequest : PDU
|
||||||
{
|
{
|
||||||
public GetNextRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x01))
|
public GetNextRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x01))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
public GetNextRequest(ASN1Value value)
|
||||||
|
: base(value)
|
||||||
|
{ }
|
||||||
|
|
||||||
}
|
}
|
||||||
public class GetResponse : PDU
|
public class GetResponse : PDU
|
||||||
{
|
{
|
||||||
public GetResponse() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x02))
|
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 NonRepeaters => Error;
|
||||||
public Integer MaxRepetitions => ErrorIndex;
|
public Integer MaxRepetitions => ErrorIndex;
|
||||||
|
@ -89,14 +111,22 @@ namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
NonRepeaters.LongValue = 0;
|
NonRepeaters.LongValue = 0;
|
||||||
MaxRepetitions.LongValue = 32;
|
MaxRepetitions.LongValue = 32;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
public class SetRequest : PDU
|
public class SetRequest : PDU
|
||||||
{
|
{
|
||||||
public SetRequest() : base(new Identifier(IdentifierClass.CONTEXT, true, 0x03))
|
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.Linq;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using ln.snmp.asn1;
|
||||||
|
|
||||||
namespace ln.snmp.types
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public class Sequence : AbstractSequence
|
public class Sequence : AbstractSequence
|
||||||
|
@ -29,7 +31,13 @@ namespace ln.snmp.types
|
||||||
Add(variable);
|
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)
|
public override void Add(Variable item)
|
||||||
{
|
{
|
||||||
this.items.Add(item);
|
this.items.Add(item);
|
||||||
|
@ -51,8 +59,9 @@ namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Items */
|
/* Items */
|
||||||
public abstract Variable[] Items { get; }
|
public abstract Variable[] Items { get; set; }
|
||||||
public abstract void Add(Variable item);
|
public abstract void Add(Variable item);
|
||||||
public abstract void Remove(Variable item);
|
public abstract void Remove(Variable item);
|
||||||
public virtual void Remove(int n)
|
public virtual void Remove(int n)
|
||||||
|
@ -74,29 +83,31 @@ namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
get
|
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
|
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()
|
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;
|
||||||
using System.IO;
|
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
|
namespace ln.snmp.types
|
||||||
{
|
{
|
||||||
public abstract class Variable
|
public abstract class Variable
|
||||||
|
@ -23,96 +29,110 @@ namespace ln.snmp.types
|
||||||
public abstract byte[] Bytes { get; set; }
|
public abstract byte[] Bytes { get; set; }
|
||||||
public abstract object Value { get; set; }
|
public abstract object Value { get; set; }
|
||||||
|
|
||||||
public virtual void Write(Stream stream)
|
public void Dump()
|
||||||
{
|
{
|
||||||
byte[] payload = Bytes;
|
Dump("");
|
||||||
|
|
||||||
BasicEncodingRules.WriteIdentifier(stream,Identifier);
|
|
||||||
BasicEncodingRules.WriteLength(stream, payload.Length);
|
|
||||||
stream.Write(payload, 0, payload.Length);
|
|
||||||
}
|
}
|
||||||
|
public void Dump(string prefix)
|
||||||
public byte[] ToBytes()
|
|
||||||
{
|
{
|
||||||
MemoryStream memoryStream = new MemoryStream();
|
if (this is AbstractSequence)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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:
|
if (item != null)
|
||||||
return new Integer();
|
item.Dump(prefix + " ");
|
||||||
case 0x04:
|
else
|
||||||
return new OctetString();
|
Logging.Log(LogLevel.DEBUG, "{0}NULL", prefix);
|
||||||
case 0x05:
|
|
||||||
return NullValue.Instance;
|
|
||||||
case 0x06:
|
|
||||||
return new ObjectIdentifier();
|
|
||||||
case 0x10:
|
|
||||||
return new Sequence();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (identifier.IdentifierClass == IdentifierClass.CONTEXT)
|
else
|
||||||
{
|
{
|
||||||
switch (identifier.Number)
|
Logging.Log(LogLevel.DEBUG, "{0}{1} {2}", prefix, this.ToString(), BitConverter.ToString(this.Bytes));
|
||||||
{
|
|
||||||
case 0x00:
|
|
||||||
return new GetRequest();
|
|
||||||
case 0x02:
|
|
||||||
return new GetResponse();
|
|
||||||
case 0x03:
|
|
||||||
return new SetRequest();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
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