Next: A simple example
Up: The Net-SNMP C API
Previous: SNMP Internals
Contents
To illustrate more accurately how SNMP actually works on the wire, lets look at
sniffed packets captured during an SNMP GET. Only 2 packets are exchanged, a
request by the manager and a response by the agent. The following was gathered
using Ethereal:
No. Time Source Destination Protocol Info
112 1.936155 10.10.1.110 10.10.1.224 SNMP GET SNMP...
Simple Network Management Protocol
Version: 1 (0)
Community: public
PDU type: GET (0)
Request Id: 0x2a7ee1af
Error Status: NO ERROR (0)
Error Index: 0
Object identifier 1: 1.3.6.1.2.1.1.4.0 (SNMPv2-MIB::sysContact.0)
Value: NULL
No. Time Source Destination Protocol Info
113 1.943425 10.10.1.224 10.10.1.110 SNMP RESPONSE SN...
Simple Network Management Protocol
Version: 1 (0)
Community: public
PDU type: RESPONSE (2)
Request Id: 0x2a7ee1af
Error Status: NO ERROR (0)
Error Index: 0
Object identifier 1: 1.3.6.1.2.1.1.4.0 (SNMPv2-MIB::sysContact.0)
Value: STRING: Ben Rockwood
Each packet is referred to as a PDU in SNMP speak. The first packet (with the Ethernet, IP, and UDP
headers removed) is a version 1 GET request with an OID to get and a community name of "public".
Notice that the GET PDU has a Value field, but its NULL. The second packet is
the response which you'll notice is identical to the GET PDU with 2 exceptions: the PDU type
is RESPONSE instead of GET and the Value field is populated.
Given this example you can see that when you make a request you hand a PDU to an agent and
say "Please fill this in".
Putting this into the context of the Net-SNMP C API, look at the snmp_PDU structure.
typedef struct snmp_pdu {
long version;
int command;
long reqid;
...
long errstat;
long errindex;
...
netsnmp_variable_list *variables;
...
u_char *community;
...
The version value maps directly the value seen in the packet above. The
command value is the PDU type as seen in the packet above. And you can
also see the reqid in the packets above as the Request ID.
The important point here is that when a PDU structure is manipulated using the API
your actually preparing an SNMP packet for transmission.
Forming a request, such as a GET, can be done in several ways. One method is to
create a single PDU per OID you wish to request. As we saw above this would mean
sending one packet per OID and thus receiving one packet for each request. Another
method, which is completely valid, is to pack a single GET PDU with multiple
OIDs for retrieval. The following is a break capture of such an exchange as seen on the
wire:
No.Time Source Destination Protocol Info
28 2.240789 10.10.1.110 10.10.1.224 SNMP GET SNMPv...
Simple Network Management Protocol
Version: 1 (0)
Community: public
PDU type: GET (0)
Request Id: 0x30549f5c
Error Status: NO ERROR (0)
Error Index: 0
Object identifier 1: 1.3.6.1.4.1.318.1.1.1.1.1.1.0 (SNMP...
Value: NULL
Object identifier 2: 1.3.6.1.4.1.318.1.1.1.1.2.3.0 (SNMP...
Value: NULL
No.Time Source Destination Protocol Info
41 2.328751 10.10.1.224 10.10.1.110 SNMP RESPONSE SNM...
Simple Network Management Protocol
Version: 1 (0)
Community: public
PDU type: RESPONSE (2)
Request Id: 0x30549f5c
Error Status: NO ERROR (0)
Error Index: 0
Object identifier 1: 1.3.6.1.4.1.318.1.1.1.1.1.1.0 (SNMP...
Value: STRING: "Silcon DP340E"
Object identifier 2: 1.3.6.1.4.1.318.1.1.1.1.2.3.0 (SNMP...
Value: STRING: "SE0XXXXXXX "
This exchange looks identical to the previous exchange but this time we've packed multiple (8 total,
but I only show 2 for brevity) OIDs into the PDU. Hence, we send one packet and we are returned one packet.
Looking back at the PDU structure, it should not be obvious why there is no fixed value for the OID
but instead an included netsnmp_variable_list pointer. This variable list is otherwise
referred to as a VARLIST or VARBIND.
typedef struct variable_list netsnmp_variable_list;
struct variable_list {
struct variable_list *next_variable;
oid *name;
size_t name_length;
u_char type;
netsnmp_vardata val;
size_t val_len;
oid name_loc[MAX_OID_LEN];
u_char buf[40];
void *data;
void (*dataFreeHook)(void *);
int index;
};
So looking at the variable list we immediately notice that its a linked list,
hence the ability to pack multiple values into a single OID.
We can pull all this information together to get a much clearer idea of how the API really works.
As seen in the captures what we really need to do is create, send, receive and then process one or more
PDUs; thats the basics. In order to do this we need to initialize a PDU structure, append one or more
variables into the variable list and then send that PDU out. What we'll get back is a fully populated (we hope)
PDU, but this time each OID in the variable list will have a value referenced by the data pointer.
Next lets look at the actual code.
Next: A simple example
Up: The Net-SNMP C API
Previous: SNMP Internals
Contents
2004-11-23