SNMP v1 and v2c Protocol Data Unit, represented by the Pdu class in the SnmpSharpNet library, contains request and reply values relevant to the data exchange manager initiated.
Protocol Data Unit is a sequence of values. Following values are encoded in the PDU sequence:
Two additional values are available for GetBulk PDUs:
Pdu type is set using PduType enumeration. Following values are defined in the enumeration:
PduType.Get; // Value: 0xa0 PduType.GetNext; // Value: 0xa1 PduType.Response; // Value: 0xa2 PduType.Set; // Value: 0xa3 PduType.GetBulk; // Value: 0xa5
Using the PduType enumeration you can set the Pdu type this way:
Pdu pdu = new Pdu(); pdu.Type = PduType.GetBulk;
There are convenience static methods available to help with the creation of different Pdu types:
Pdu getPdu = Pdu.GetPdu(vbs); Pdu getNextPdu = Pdu.GetNextPdu(vbs); Pdu getBulkPdu = Pdu.GetBulkPdu(vbs); Pdu setPdu = Pdu.setPdu(vbs);
I'll expain what the vbs argument in the above examples is later on...
Request id is a unique identifier used to match requests and responses. Pdu class by default sets the request id to a random value using the standard Random class that is part of the .NET framework.
If you wish to reset the request id to a new random value, just set the request id value to 0 (zero). This action will cause the encoding routine to retrieve a new random request id:
Pdu pdu = new Pdu(); pdu.RequestId = 0;
Above example will result in the Pdu being encoded with a new random value. This is mostly useful when you are reusing a Pdu for multiple requests. By setting the RequestId value to 0 you can ensure that each request is sent with a different request id.
Another way to reuse a Pdu class instance is to call the Pdu.Reset() method. When called, Reset method sets the RequestId value to the previous value incremented by 1. Request id value will rollover to 1 when maximum value of integer variable is reached to avoid overflow exceptions.
Error status is a value used to represent error that was encountered by the agent when processing the request. Error status values can be tested using PduErrorStatus enumeration. Error status value of PduErrorStatus.NoError (or value of 0 - zero) signifies that there was no error. When there is no error in the request, Error index value will be set to 0.
For different error status codes and their meaning, have a look at PduErrorStatus code documentation.
Error index is used when error reported in Error status is related to a specific variable in the Pdu. In all other cases (like if there is no error or if error is not related to a variable) Error index value is set to zero. If Error index value is set to value 1+ then that value points to a variable binding in the variable binding list.
When processing replies it is critically important to verify that ErrorStatus value does not contain an error. If error is returned and you continue to process the response there is a good chance further processing will fail.
Here is a full example of how to handle a response:
VbCollection vbCol = new VbCollection(); vbCol.Add("1.3.6.1.2.1.1.1.0"); vbCol.Add("1.3.6.1.2.1.1.2.0"); // vbCol.Add("1.3.6.1.2.1.1.1.1.0"); Pdu getPdu = Pdu.GetPdu(vbCol); UdpTarget target = new UdpTarget(IPAddress.Loopback); AgentParameters agentParams = new AgentParameters(SnmpVersion.Ver2, new OctetString("public")); SnmpV2Packet response = (SnmpV2Packet)target.Request(getPdu, agentParams); if (response != null) { if( response.Pdu.ErrorStatus == (int)PduErrorStatus.noError ) { Console.WriteLine("Response id {0}\n1: {1}\n2: {2}", response.Pdu.RequestId, response.Pdu.VbList[0].Value.ToString(), response.Pdu.VbList[1].Value.ToString()); Console.WriteLine("Error status: {0}", ((PduErrorStatus)response.Pdu.ErrorStatus).ToString()); } else { Console.WriteLine("Response id {0}", response.Pdu.RequestId); Console.WriteLine("Error code: {0} index: {1} name: {2}", response.Pdu.ErrorStatus, response.Pdu.ErrorIndex, ((PduErrorStatus)response.Pdu.ErrorStatus).ToString()); } } target.Dispose();
Important part to focus on is the processing of response.Pdu.ErrorStatus. Before focusing attempting to process data in the packet you will want to check if ErrorStatus value is equal to noError. Any other value represents an error and data in the packet is suspect.
Pdu class provides helper methods to make access to the variable binding collection easier. You can access VarBind collection directly through an indexer in the Pdu class itself (without using Pdu.VbList collection) or by accessing Pdu class enumerator:
// SnmpV2Packet response = (SnmpV2Packet)target.Request(pdu, param); foreach (Vb v in response.Pdu) { Console.WriteLine("{0}: {1}", v.Oid.ToString(), v.Value.ToString()); } // or for (int i = 0; i < response.Pdu.VbCount; i++) { Console.WriteLine("{0} - {1}: {2}", i, response.Pdu[i].Oid.ToString(), response.Pdu[i].Value.ToString()); }
VarBind collection access helpers were introduced in library version 0.7.8