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 snmpRequest(IEnumerable 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 results = new List(); foreach (Variable varBind in varBinds.Items) { results.Add(varBind as Sequence); } return results; } public List snmpGet(IEnumerable objectIdentifiers) { return snmpRequest(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 snmpGet(IEnumerable objectIdentifiers) { return snmpGet(objectIdentifiers.Select((x) => new ObjectIdentifier(x))); } public List snmpGetNext(IEnumerable objectIdentifiers) { return snmpRequest(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 snmpGetNext(IEnumerable 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 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) { List results = new List(); List parts; do { parts = snmpRequest(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 snmpGetBulk(String objectIdentifier) { return snmpGetBulk(new ObjectIdentifier(objectIdentifier)); } 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 { return snmpGetBulk(objectIdentifiers); } } public Sequence[][] snmpWalk(IEnumerable objectIdentifiers) { return snmpWalk(objectIdentifiers.Select((x) => new ObjectIdentifier(x))); } public List snmpWalk(ObjectIdentifier objectIdentifier) { if (SnmpVersion == SnmpVersion.V1) { List results = new List(); 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 snmpWalk(string objectIdentifier) { return snmpWalk(new ObjectIdentifier(objectIdentifier)); } } }