Working with SNMP Packets



Working with SNMP Packets

Now that you have seen what constitutes the SNMP system, let’s discuss how to place those pieces in a packet to send to the remote device. This section describes the process of creating SNMP packets and how C# can be used to create and send them.

SNMP Packet Format

Each SNMP packet is defined as a sequence. The sequence consists of three basic parts:

  • The SNMP version number

  • The community name used in the query

  • The SNMP PDU (protocol data unit)

Version and Community Name

The first section of the SNMP packet is standard for all PDU types. For SNMP version 1 packets, the version number is always set to zero (strange, but true). The second section, the community name, is also standard in each of the PDU types. Each character in the community name is placed in a byte in the packet. If the community name passed in the SNMP packet is invalid, no response is returned from the network device.

PDU

The final part of the packet sequence is the PDU. It contains information specific to the PDU type of the packet. Each SNMP packet contains only one PDU section, which can contain only one PDU type.

The five PDU types of SNMP version 1 all have their own formats, but three of them (GetRequest, GetNextRequest, and GetResponse) all use the same PDU format, making things a little bit easier. Let’s look under the hood of these PDU types. Their common format contains the following fields, which define the PDU information passed to the SNMP device:

  • PDU type

  • Request-ID

  • Error status

  • Error index

  • One or more variable bindings

PDU Type

The PDU type is a 1-byte value that identifies which PDU format the SNMP packet is using. The values for the PDU types are as follows:

GetRequest

0xA0

GetNextRequest

0xA1

GetResponse

0xA2

SetRequest

0xA3

Trap

0xA4

Request-ID

The request-ID is a 4-byte integer value that uniquely identifies each query sent to a device. The response from the device must contain a matching request-ID.

Error Status and Error Index

The error status and error index fields are both 1-byte integers. They contain a zero for the GetRequest. The GetResponse packet contains values that indicate whether an error has occurred in the SNMP transaction, and what kind of error it was, as listed in Figure. The error index further defines the specific error condition within the error status of the SNMP transaction.

Figure: SNMP Error Status Values

Error Status

Name

Description

0

No error

No errors are present in the transaction.

1

tooBig

The SNMP packet is too large.

2

noSuchName

The MIB object does not exist.

3

badValue

The MIB object value is not the proper datatype or is not in the proper range.

4

readOnly

A SetRequest message is attempting to modify a MIB entry with read-only privileges.

5

genErr

Generic error condition.

Variable Binding

A variable binding represents a single object identifier/object value pair in the SNMP packet. For example, the following is a valid variable binding for the sysName MIB object:

1.3.6.1.2.1.1.5.0Jessica's workstation

In this example, the object identifier 1.3.6.1.2.1.1.5.0 is the sysName object, and the object value is Jessica's workstation.

For GetRequest and GetNextRequest PDUs, the object value is obviously not known (since it is querying the remote device for the value); in these cases it is set to null. The GetResponse packet returned by the remote device will have the object value set to the database value of the object queried.

A single SNMP packet can contain multiple variable bindings. The variable bindings are separated by a sequence identifier (described in the SNMP Packet Layout section). There is no limit on the number of variable bindings that can be in an SNMP packet. The GetResponse packet should contain information for each variable binding sent by the querying device.

SNMP Packet Layout

The tricky part of running SNMP is placing all the SNMP information into a packet. There are plenty of rules for these packets, and if anything is not right the remote host will silently ignore the SNMP packet. Because SNMP uses UDP, you can never be sure whether the SNMP query was lost on the network or if something was actually wrong and made the remote device ignore the packet. That makes for fun troubleshooting.

The easiest way to study the SNMP packet layout is to show a sample SNMP packet and walk through it byte by byte. Take a look at Figure.

Click To expand
Figure: Simple SNMP GetRequest packet layout

The SNMP packet starts with a sequence byte (0x30) to indicate the start of an SNMP transaction.

Next comes the length of the entire SNMP packet (0x28) so the remote device can determine whether the packet was received in its entirety.

After the length byte, each remaining data value in the SNMP packet is preceded by a 2-byte sequence. Within that sequence, the first byte represents the SNMP datatype of the object value. The second byte represents the length of the value. Here are the contents of these 2-byte values, as illustrated in Figure:

SNMP version number An Integer datatype (0x02) with a length of 1 (0x01). The version number value itself is zero (0x00), which is used for SNMP version 1 packets (go figure).

Community name Starts with two bytes, then the string object datatype (0x04) and the length of the community name string (0x05). After the length comes the community name bytes.

SNMP PDU type A single byte. Because the value here is 0xA0, this is a GetRequest PDU packet.

Length of the PDU area of the packet A single byte (0x1c).

Request ID An Integer datatype (0x02), a length of 4 bytes (0x04), and the actual request ID. The request ID can be any value and is matched with the GetResponse Request ID value. In this example, the value is 1 (0x00 0x00 0x00 0x01).

Error information This includes error status and error index values with their respective datatypes and lengths. This is a GetRequest packet, so the error status and error index values are set to zero.

Variable bindings section Because there can be more than one variable binding, it is encapsulated with a Sequence byte (0x30), along with the size of the entire variable bindings section (0x0e). After that, each individual variable binding will be preceded with Sequence and length bytes for the variable binding. This SNMP packet contains a single variable binding, with a length of 0x0c.

Object identifier/object value pair in the variable binding The object identifier has a datatype showing that it is an Object Identifier (0x06). Following the datatype is the length of the object identifier (0x09), followed by the object identifier itself.

Note that there is an oddity with how the object identifier is placed in the SNMP packet. Each of the individual object identifier node values are converted to a single-byte value with two exceptions:

  • The first two objects in the object identifier (1.3) are converted to a single-byte value of 0x2B

  • Node values over 127 are converted to a 2-byte signed integer value

    The object identifier seen in the example is 1.3.6.1.2.1.1.5.0. This represents a single instance of the sysName object.

    Object value This is a GetRequest packet, so the object value is set to null, identified by the null datatype (0x05) and the length of zero (0x00).

SNMP Communication

SNMP packets use UDP to communicate with remote devices. Because UDP is a connectionless protocol, your SNMP programs should be formulated to be capable of accounting for typical UDP problems, as described in Chapter 6, “Connectionless Sockets.” The biggest problem encountered when sending and receiving SNMP packets is packets that get lost in the network and are never received.

SNMP uses two separate UDP ports for communications: port 161 for GetRequest, GetNextRequest, and SetRequest PDUs, and port 162 for Trap PDUs.

Individual SNMP packets are created by placing the appropriate data into the SNMP byte array. When the entire packet is assembled, the byte array is sent to the remote network device using the appropriate UDP port. Devices that accept GetRequest, GetNextRequest, and SetRequest queries must listen to port 161, while SNMP management stations must listen to port 162 for Trap packets being sent from SNMP devices.

 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows