From 1b4c13e5f5671394ddd86ddd227b929519a5b2ca Mon Sep 17 00:00:00 2001 From: Harald Wolff Date: Mon, 4 Mar 2019 20:48:25 +0100 Subject: [PATCH] Added GetBulkRequest, snmpWalk() for V2c --- SNMPEngine.cs | 6 ++ SNMPInterface.cs | 138 +++++++++++++++++++++++++++++++++++++-- channel/SnmpV1Channel.cs | 3 +- ln.snmp.csproj | 6 -- packages.config | 4 -- 5 files changed, 142 insertions(+), 15 deletions(-) delete mode 100644 packages.config diff --git a/SNMPEngine.cs b/SNMPEngine.cs index 59efe33..46dd36b 100644 --- a/SNMPEngine.cs +++ b/SNMPEngine.cs @@ -27,6 +27,12 @@ namespace ln.snmp private bool shutdown = false; private Thread ReceiverThread { get; set; } + public SNMPEngine() + { + LocalEndpoint = new UdpClient(); + ReceiverThread = new Thread(Receiver); + ReceiverThread.Start(); + } public SNMPEngine(IPEndPoint localEndpoint) { LocalEndpoint = new UdpClient(localEndpoint); diff --git a/SNMPInterface.cs b/SNMPInterface.cs index 335e0b1..e2dd587 100644 --- a/SNMPInterface.cs +++ b/SNMPInterface.cs @@ -4,6 +4,8 @@ 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 } @@ -25,24 +27,29 @@ namespace ln.snmp private List snmpRequest(IEnumerable objectIdentifiers) where T: PDU, new() { - T pdu = new T(); + PDU pdu = new T(); foreach (ObjectIdentifier oid in objectIdentifiers) { pdu.Add(new Sequence(new Variable[] { oid, NullValue.Instance })); } - GetResponse responsePDU = PDUChannel.RequestResponse(pdu, RemoteEndpoint) as GetResponse; + PDU responsePDU = snmpRequest(pdu); Sequence varBinds = responsePDU.VarBinds as Sequence; - List results = new List(); + List results = new List(); foreach (Variable varBind in varBinds.Items) { results.Add(varBind as Sequence); } - return results; } + private PDU snmpRequest(PDU pdu) + { + GetResponse responsePDU = PDUChannel.RequestResponse(pdu, RemoteEndpoint) as GetResponse; + return responsePDU; + } + public List snmpGet(IEnumerable objectIdentifiers) { return snmpRequest(objectIdentifiers); @@ -77,6 +84,83 @@ namespace ln.snmp 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 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 result = new List(); + 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 snmpGetBulk(ObjectIdentifier objectIdentifier) { @@ -107,6 +191,52 @@ namespace ln.snmp } + public Sequence[][] snmpWalk(IEnumerable objectIdentifiers) + { + if (SnmpVersion == SnmpVersion.V1) + { + ObjectIdentifier[] OIDs = objectIdentifiers.ToArray(); + ObjectIdentifier[] lastOIDs = objectIdentifiers.ToArray(); + List results = new List(); + + bool cont = true; + while (cont) + { + cont = false; + List 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 if (SnmpVersion == SnmpVersion.V2c) + { + return snmpGetBulk(objectIdentifiers); + } + else + { + throw new NotImplementedException(); + } + } + public Sequence[][] snmpWalk(IEnumerable objectIdentifiers) + { + return snmpWalk(objectIdentifiers.Select((x) => new ObjectIdentifier(x))); + } public List snmpWalk(ObjectIdentifier objectIdentifier) { diff --git a/channel/SnmpV1Channel.cs b/channel/SnmpV1Channel.cs index add5686..7ba570f 100644 --- a/channel/SnmpV1Channel.cs +++ b/channel/SnmpV1Channel.cs @@ -39,7 +39,8 @@ namespace ln.snmp.channel if (responsePDU.Error.LongValue != 0) { - throw new SnmpError(responsePDU.Error, responsePDU.ErrorIndex, ((pdu.VarBinds.Items[(int)responsePDU.ErrorIndex - 1] as Sequence).Items[0] as ObjectIdentifier).AsString); + 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; diff --git a/ln.snmp.csproj b/ln.snmp.csproj index 60f3140..1236036 100644 --- a/ln.snmp.csproj +++ b/ln.snmp.csproj @@ -28,9 +28,6 @@ - - ..\packages\Lextm.SharpSnmpLib.11.1.0\lib\net452\SharpSnmpLib.dll - @@ -53,9 +50,6 @@ - - - diff --git a/packages.config b/packages.config deleted file mode 100644 index 509e2ef..0000000 --- a/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file