SNMP Version 1 Low Level Packet Class

If you are using SnmpSharpNet library to build advanced manager (or agent) functionality, you will need to use low level functions to craft individual packets. Low level access to the SNMP packets can be archived through version specific classes derived from SnmpPacket base class.

To manipulate SNMP version 1 packet, you will need to use SnmpV1Packet class.

Before you can start using the class, you need to understand the structure of the SNMP packet and the information required to assemble a valid packet. To begin understanding the packet format, we’ll begin with the encoded packet layout.

SNMP version 1 packet is layed out as follows:

Name Type Length Description
Sequence Sequence variable Packet sequence
Version Integer32 1 byte Protocol version number. For SNMPv1 this field is set to 0
Community OctetString variable SNMP community name
Pdu Sequence Sequence variable Start of the Protocol Data Unit
RequestId Integer32 variable Unique request id
ErrorStatus Integer32 variable ErrorStatus of SNMP request. 0 = noError
ErrorIndex Integer32 variable Index of the VarBind in the request that caused the error
Variable Bindings Sequence variable Sequence of VarBind entries

Variable Bindings format is:

Field # Name Type Description
1 VarBinds header Sequence Wrapper header around the entire sequence
2 VarBind header Sequence Wrapper around a single Variable Binding
3 ObjectID Oid ObjectID for the value in the Variable Binding
4 ASN Value variable Value associated with the ObjectID
Fields 2 to 4 are repeated for every VarBind entry in the collection

Information required to encode a valid SNMP request is:

  • Protocol version
  • SNMP community name
  • PDU Type – operation you wish to perform
  • Request ID
  • Variable binding information
    • For requests it can be one or more Oid’ with Null values
    • For SET operation, you will need both Oid and valid values

Now that you know what information you need to create a valid request lets create a SnmpV1Packet:

SnmpV1Packet packet = new SnmpV1Packet();
// Set the community name 
packet.Community.Set("public");
// Set the Pdu type 
packet.Pdu.Type = PduType.Get;
// Set request id 
packet.Pdu.RequestID = 100;
// Add an Oid for the SNMP-Get operation 
packet.Pdu.VbList.Add(".1.3.6.1.2.1.1.1.0");

This example shows how to prepare a SNMP-Get request. By default, when calling Pdu.VbList.Add(string) method, Oid is parsed from the string and value in the VariableBinding is set to Null.

GetNext request is identical except for setting the Pdu type to PduType.GetNext.

SET request is different because you have to set both the Oid and value to set the Oid to on the agent. Here is what you would change for an SNMP-Set request:

// Set the Pdu type 
packet.Pdu.Type = PduType.Set;
// Add an Oid and Value for the SNMP-Set operation 
packet.Pdu.VbList.Add(new Oid(".1.3.6.1.2.1.1.1.0"), new OctetString("New sysDescr.0 value"));

SNMP version 1 class is now ready to be BER encoded for transmission:

byte[] outBuffer = packet.encode();

That is it! outBuffer byte array now holds the BER encoded SNMP version 1 packet that is ready for transmission to an agent. Just call Socket.Send or Socket.SendTo to send the request.

Now that you have sent a request, what do you do when you receive a reply? Nothing easier, assuming you have received a reply from the agent (you should check IP address and port number of the sender to make sure it’s from the expected device) you need to decode it. In this example, I assume you received the packet into a pre-defined byte array inBuffer and that received data length is stored in inLength variable:

SnmpV1Packet result = new SnmpV1Packet();
result.decode(inBuffer, inLength);

or you can choose to reuse the class you created to send the request:

packet.Reset();
packet.decode(inBuffer, inLength);

From this point, data is available to you in the usable format. You should compare the SNMP community name and request id to confirm they match your request and then process the information returned by the agent.

Both SnmpV1Packet encode and decode methods will throw Exceptions if an error is encountered. Please check library documentation for details of Exceptions that can be thrown.