ln.snmp/SNMPInterface.cs

270 lines
9.1 KiB
C#

using System;
using ln.snmp.types;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using ln.snmp.channel;
using System.Reflection;
namespace ln.snmp
{
public enum SnmpVersion : int { V1 = 0, V2c = 1, V3 = 3 }
public abstract class SNMPInterface
{
public SNMPEngine SNMPEngine { get; }
public IPEndPoint RemoteEndpoint { get; set; }
public abstract SnmpVersion SnmpVersion { get; }
public SNMPInterface(SNMPEngine snmpEngine,IPEndPoint remoteEndpoint)
{
SNMPEngine = snmpEngine;
RemoteEndpoint = remoteEndpoint;
}
public abstract PDU snmpRequest(PDU pdu);
private List<Sequence> snmpRequest<T>(IEnumerable<ObjectIdentifier> objectIdentifiers) where T: PDU, new()
{
PDU pdu = new T();
foreach (ObjectIdentifier oid in objectIdentifiers)
{
pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance }));
}
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>();
foreach (Variable varBind in varBinds.Items)
{
results.Add(varBind as Sequence);
}
return results;
}
public List<Sequence> snmpGet(IEnumerable<ObjectIdentifier> objectIdentifiers)
{
return snmpRequest<GetRequest>(objectIdentifiers);
}
public Variable snmpGet(ObjectIdentifier objectIdentifier)
{
return snmpGet(new ObjectIdentifier[] { objectIdentifier })[0].Items[1];
}
public Variable snmpGet(string objectIdentifier)
{
return snmpGet(new ObjectIdentifier[] { new ObjectIdentifier(objectIdentifier) })[0].Items[1];
}
public List<Sequence> snmpGet(IEnumerable<String> objectIdentifiers)
{
return snmpGet(objectIdentifiers.Select((x) => new ObjectIdentifier(x)));
}
public List<Sequence> snmpGetNext(IEnumerable<ObjectIdentifier> objectIdentifiers)
{
return snmpRequest<GetNextRequest>(objectIdentifiers);
}
public Sequence snmpGetNext(ObjectIdentifier objectIdentifier)
{
return snmpGetNext(new ObjectIdentifier[] { objectIdentifier })[0];
}
public Sequence snmpGetNext(string objectIdentifier)
{
return snmpGetNext(new ObjectIdentifier[] { new ObjectIdentifier(objectIdentifier) })[0];
}
public List<Sequence> snmpGetNext(IEnumerable<String> objectIdentifiers)
{
return snmpGetNext(objectIdentifiers.Select((x) => new ObjectIdentifier(x)));
}
private PDU TryBulk(GetBulkRequest bulkRequest)
{
try
{
return snmpRequest(bulkRequest);
} catch (SnmpError se)
{
if ((se.Error == 1)&&(bulkRequest.MaxRepetitions.LongValue > 1))
{
bulkRequest.MaxRepetitions.LongValue >>= 1;
return TryBulk(bulkRequest);
}
throw se;
}
}
/*
* ToDO: Algorithm is not perfect, when receiving an inclomplete "row", the already received partial row is ignored
*/
public Sequence[][] snmpGetBulk(IEnumerable<ObjectIdentifier> objectIdentifiers, int maxRepetitions = 32)
{
ObjectIdentifier[] OIDs = objectIdentifiers.ToArray();
int ncolumns = OIDs.Length;
GetBulkRequest pdu = new GetBulkRequest();
pdu.MaxRepetitions.LongValue = maxRepetitions;
foreach (ObjectIdentifier oid in objectIdentifiers)
{
pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance }));
}
List<Sequence[]> result = new List<Sequence[]>();
int nchunk;
bool inTree = false;
do
{
PDU responsePDU = TryBulk(pdu);
Variable[] values = responsePDU.VarBinds.Items;
nchunk = values.Length / ncolumns;
inTree = false;
for (int n = 0; n < nchunk; n++)
{
Sequence[] row = new Sequence[ncolumns];
for (int c = 0; c < ncolumns; c++)
{
Sequence v = values[(n * ncolumns) + c] as Sequence;
if (OIDs[c].Contains(v.Items[0] as ObjectIdentifier))
{
row[c] = v;
inTree = true;
}
}
if (inTree)
result.Add(row);
else
{
break;
}
}
pdu.VarBinds.RemoveAll();
for (int c = 0; c < ncolumns; c++)
{
pdu.VarBinds.Add(new Sequence(new Variable[] { (responsePDU.VarBinds.Items[(ncolumns * (nchunk - 1)) + c] as Sequence).Items[0], NullValue.Instance }));
}
pdu.RequestID.LongValue++;
} while (inTree); //((nchunk == pdu.MaxRepetitions.LongValue) && inTree);
return result.ToArray();
}
public List<Sequence> snmpGetBulk(ObjectIdentifier objectIdentifier)
{
List<Sequence> results = new List<Sequence>();
List<Sequence> parts;
do
{
parts = snmpRequest<GetBulkRequest>(new ObjectIdentifier[] { objectIdentifier });
foreach (Sequence ps in parts)
{
ObjectIdentifier oid = ps.Items[0] as ObjectIdentifier;
if (objectIdentifier.Contains(oid))
results.Add(ps);
else
return results;
}
} while (parts.Count >= 32);
return results;
}
public List<Sequence> snmpGetBulk(String objectIdentifier)
{
return snmpGetBulk(new ObjectIdentifier(objectIdentifier));
}
public Sequence[][] snmpWalk(IEnumerable<ObjectIdentifier> objectIdentifiers)
{
if (SnmpVersion == SnmpVersion.V1)
{
ObjectIdentifier[] OIDs = objectIdentifiers.ToArray();
ObjectIdentifier[] lastOIDs = objectIdentifiers.ToArray();
List<Sequence[]> results = new List<Sequence[]>();
bool cont = true;
while (cont)
{
cont = false;
List<Sequence> next = snmpGetNext(lastOIDs);
Sequence[] row = new Sequence[lastOIDs.Length];
for (int n = 0; n < lastOIDs.Length; n++)
{
lastOIDs[n] = next[n].Items[0] as ObjectIdentifier;
if (OIDs[n].Contains(lastOIDs[n]))
{
cont = true;
row[n] = next[n];
}
else
{
row[n] = null;
}
}
results.Add(row);
}
return results.ToArray();
}
else
{
return snmpGetBulk(objectIdentifiers);
}
}
public Sequence[][] snmpWalk(IEnumerable<String> objectIdentifiers)
{
return snmpWalk(objectIdentifiers.Select((x) => new ObjectIdentifier(x)));
}
public List<Sequence> snmpWalk(ObjectIdentifier objectIdentifier)
{
if (SnmpVersion == SnmpVersion.V1)
{
List<Sequence> results = new List<Sequence>();
ObjectIdentifier oiLast = objectIdentifier;
while (objectIdentifier.Contains(oiLast))
{
Sequence next = snmpGetNext(oiLast);
oiLast = next.Items[0] as ObjectIdentifier;
if (objectIdentifier.Contains(oiLast))
results.Add(next);
}
return results;
} else if (SnmpVersion == SnmpVersion.V2c)
{
return snmpGetBulk(objectIdentifier);
}
else
{
throw new NotImplementedException();
}
}
public List<Sequence> snmpWalk(string objectIdentifier)
{
return snmpWalk(new ObjectIdentifier(objectIdentifier));
}
}
}