RFC 1592
Simple Network Management Protocol Distributed Protocol Interface Version 2.0
RFC 1592: SNMP DPI Version 2.0 π¦
okay bestie, this one is an Experimental RFC from March 1994, and it's giving a sub-agent protocol for SNMP π It's called the Distributed Protocol Interface (DPI), version 2.0, and it obsoletes RFC 1228. The authors are B. Wijnen and G. Carpenter from the T.J. Watson Research Center at IBM, plus K. Curran, A. Sehgal, and G. Waters from Bell Northern Research, Ltd. πΈ
Status of this Memo π
this memo defines an Experimental Protocol for the Internet community. it does NOT specify an Internet standard of any kind π the authors are literally asking for discussion and suggestions for improvement, so send feedback! distribution of this memo is unlimited π«Ά
Table of Contents π
1. INTRODUCTION . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1 Motivation . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Summary of Changes . . . . . . . . . . . . . . . . . . . . 4
2. THEORY OF OPERATION . . . . . . . . . . . . . . . . . . . . . 5
2.1 Connection Establishment and Termination . . . . . . . . . 5
2.2 Registration . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Normal Operation . . . . . . . . . . . . . . . . . . . . . 6
2.4 DPI Architecture . . . . . . . . . . . . . . . . . . . . . 6
3. SNMP DPI PROTOCOL . . . . . . . . . . . . . . . . . . . . . 10
3.1 Connection Establishment . . . . . . . . . . . . . . . . 10
3.1.1 SNMP PDU to GET the Agent's DPI port . . . . . . . . . 11
3.1.2 SNMP PDU Containing the RESPONSE to the GET . . . . . 13
3.2 SNMP DPI Packet Formats . . . . . . . . . . . . . . . . 15
3.2.1 DPI Packet Header . . . . . . . . . . . . . . . . . . 15
3.2.2 OPEN . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2.3 CLOSE . . . . . . . . . . . . . . . . . . . . . . . . 18
3.2.4 ARE_YOU_THERE . . . . . . . . . . . . . . . . . . . . 19
3.2.5 REGISTER . . . . . . . . . . . . . . . . . . . . . . . 20
3.2.6 UNREGISTER . . . . . . . . . . . . . . . . . . . . . . 22
3.2.7 GET . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2.8 GETNEXT . . . . . . . . . . . . . . . . . . . . . . . 24
3.2.9 GETBULK . . . . . . . . . . . . . . . . . . . . . . . 25
3.2.10 SET, COMMIT and UNDO . . . . . . . . . . . . . . . . 26
3.2.11 RESPONSE . . . . . . . . . . . . . . . . . . . . . . 29
3.2.12 TRAP . . . . . . . . . . . . . . . . . . . . . . . . 31
3.3 Constants and Values . . . . . . . . . . . . . . . . . . 33
3.3.1 Protocol Version and Release Values . . . . . . . . . 33
3.3.2 Packet Type Values . . . . . . . . . . . . . . . . . . 34
3.3.3 Variable Type Values . . . . . . . . . . . . . . . . . 35
3.3.4 Value Representation . . . . . . . . . . . . . . . . . 36
3.3.5 Character set selection . . . . . . . . . . . . . . . 36
3.3.6 Error Code Values for SNMP DPI RESPONSE packets . . . 37
3.3.7 UNREGISTER Reason Codes . . . . . . . . . . . . . . . 40
3.3.8 CLOSE Reason Codes . . . . . . . . . . . . . . . . . . 41
4. DPI 2.0 MIB DEFINITION . . . . . . . . . . . . . . . . . . 41
5. SUBAGENT CONSIDERATIONS . . . . . . . . . . . . . . . . . . 42
5.1 DPI API . . . . . . . . . . . . . . . . . . . . . . . . 43
5.2 Overview of Request Processing . . . . . . . . . . . . . 44
5.2.1 GET Processing . . . . . . . . . . . . . . . . . . . . 44
5.2.2 SET Processing . . . . . . . . . . . . . . . . . . . . 44
5.2.3 GETNEXT Processing . . . . . . . . . . . . . . . . . . 46
5.2.4 GETBULK Processing . . . . . . . . . . . . . . . . . . 47
5.2.5 OPEN Request . . . . . . . . . . . . . . . . . . . . . 48
5.2.6 CLOSE Request . . . . . . . . . . . . . . . . . . . . 49
5.2.7 REGISTER Request . . . . . . . . . . . . . . . . . . . 49
5.2.8 UNREGISTER Request . . . . . . . . . . . . . . . . . . 50
5.2.9 TRAP Request . . . . . . . . . . . . . . . . . . . . . 51
5.2.10 ARE_YOU_THERE request . . . . . . . . . . . . . . . . 51
5.2.11 How to query the DPI port. . . . . . . . . . . . . . 51
6. REFERENCES . . . . . . . . . . . . . . . . . . . . . . . . 51
7. SECURITY CONSIDERATIONS . . . . . . . . . . . . . . . . . . 52
8. AUTHORS' ADDRESSES . . . . . . . . . . . . . . . . . . . . 53
9. SAMPLE SOURCES FOR ANONYMOUS FTP . . . . . . . . . . . . . 54
1. Introduction β¨
okay so this RFC describes version 2.0 of a protocol that International Business Machines Corporation (IBM) has been implementing in most of its SNMP agents to allow dynamic extension of supported MIBs π Bell Northern Research (BNR) also implemented a version of this protocol in some of its SNMP agents, for the same reason π
the Simple Network Management Protocol (SNMP [1]) Distributed Protocol Interface (DPI) is an extension to SNMP agents that lets end-users dynamically add, delete or replace management variables in the local Management Information Base without recompiling the SNMP agent π§ the trick is writing a so-called sub-agent that talks to the agent through the SNMP-DPI. it's giving plug-in energy π
for the author of a sub-agent, the SNMP-DPI means you don't have to know the details of ASN.1 [2] or SNMP PDU (Protocol Data Unit) encoding/decoding [1, 3]. no cap, that's a huge glow-up for developers π
versions 1.0 and 1.1 of this protocol have been in use within IBM since 1989, and they're included in the SNMP agents for VM, MVS and OS/2 π version 1.2 has been in use within BNR since 1992.
1.1. Motivation π·
okay so the Simple Network Management Protocol [1] defines a protocol for operations on a collection of variables. that set of variables is called the Management Information Base (MIB), and a core set of variables has already been defined [4, 5]. but the MIB's design makes room for extending that core set, so an enterprise or an individual can define their own variables that represent information they care about π¦ an example of a potentially interesting variable that's not in the core MIB would be CPU utilization (percent busy). the problem is that conventional SNMP agent implementations give end-users no way to make new variables available π
besides that, there are today lots of MIBs that people want to implement on a system. without a capability for sub-agents, all of those MIBs have to live in one big monolithic agent, and that's undesirable in many cases π
the SNMP DPI handles this by providing a light-weight mechanism where a process can register the existence of a MIB variable or a MIB sub-tree with the SNMP agent β¨ requests for those variables that the SNMP agent receives get passed to the process acting as a sub-agent. the sub-agent then returns an appropriate answer to the SNMP agent. the SNMP agent eventually packages an SNMP response packet and sends the answer back to the remote network management station that started the request π«Ά
the remote network management stations have no idea that the SNMP agent is calling on other processes to get an answer. as far as they can tell, there's only one network management application (agent) running on the host π
at the San Diego IETF (March 1992), there was a BOF on multiplexing SNMP agents' requirements π both the SMUX [6] and DPI [7] protocols were discussed, along with other unpublished approaches. there was also discussion about needing a standard for multiplexing SNMP agents or for sub-agent support. at the end of the BOF, though, there wasn't enough support to define a standard π€ this was due, at least partially, to a few well-known SNMP authors who said that the proxy and party support for SNMPv2 (SMP at the time) would solve the problem.
nevertheless, questions keep getting raised about sub-agent support on both the SNMP and SNMP2 mail lists, even though SNMPv2 [8] is on the standards track and SMUX has been changed to a historic RFC π and honestly? within IBM and BNR we keep seeing substantial and expanding use of the DPI protocol, with positive results π₯
so we believe there's a place for a sub-agent protocol, and we're offering this new version again as an experimental protocol π§ we encourage people to try it and send us feedback! depending on that feedback, we may decide to try to get onto the standards track at a later time π
during the discussions about sub-agent interfaces at the San Diego BOF, it also became clear that we should reduce the focus on the API for sub-agent programmers π so this RFC specifies only the protocol that distributes SNMP requests from the main SNMP agent to the sub-agents. programmers can build one or more Programming APIs on top of that protocol as needed, and sample API code is available from the authors of this document π
1.2. SUMMARY OF CHANGES β¨
okay bestie, here's what changed since the very first SNMP-DPI definition π some of these came from comparing the SMUX [6] and DPI [7] protocols π§
- Documentation glow-up π the doc got cleaned up and way more specific. Among other things:
- integers are defined to be in network byte order
- the character set used for strings is defined
- how DisplayStrings are handled is defined
- the DPI20 MIB definition is included
- The Programming API is gone from the document π
- New DPI packet types just dropped π¦
SNMP_DPI_OPENlets a sub-agent open a "connection" with the DPI SNMP capable agent. The sub-agent has to identify itself now, and it can optionally give a "password" for the connection πSNMP_DPI_CLOSElets the agent or sub-agent close the connection in a graceful way πΈSNMP_DPI_ARE_YOU_THERElets the sub-agent check that the agent still knows about it πSNMP_DPI_UNREGISTERlets the agent or sub-agent end the registration of a MIB variable or MIB sub-tree π«ΆSNMP_DPI_COMMITtells the sub-agent to actually commit a previousSNMP_DPI_SETrequest. Together with UNDO, this means DPI sub-agents can be compliant with SNMP in the sense that we can now handle the "as if simultaneous" requirement πSNMP_DPI_UNDOtells the sub-agent to UNDO a SET or COMMIT if it's needed π
- Changes to DPI packets π
- multiple varBinds can now be exchanged in one DPI packet (for GET, GETNEXT, SET, TRAP). The sub-agent can say the maximum it wants to handle per packet π¦
- the packet headers now carry a packet-ID (kind of like the SNMP request ID in an SNMP PDU). This lets RESPONSE packets get matched to REQUESTS, which is a big deal for UDP based DPI-connections π§©
- the
SNMP_DPI_REGISTERpacket has new fields for time_out and for requested priority β±οΈ - the
SNMP_DPI_TRAPpacket lets you specify an enterprise OID. On top of that, the generic and specific trap types are now 4 octets, so the types can be passed through correctly π - overall, the packets have a more consistent layout β¨
- The agent now sends a RESPONSE to a REGISTER request π
- SNMPv2 error codes and value types were added π
2. THEORY OF OPERATION π§
2.1. CONNECTION ESTABLISHMENT AND TERMINATION π
okay so communication between the SNMP Agent and its clients (sub-agents) happens over a communication mechanism. That mechanism can be a logical stream connection (like TCP, for instance) or an unreliable datagram connection (like UDP, for instance). It should be noted that other stream oriented transport communication mechanisms can be used too! For example, the VM SNMP agent allows DPI connections over IUCV (Inter-User Communications Vehicle) [9, 10]. Apart from the connection establishment procedure, the protocol is identical in all of these environments π
Now, the lowkey tricky part π In Unix, the number of processes is limited by how many file-descriptors can be opened. Every TCP socket is a file-descriptor, so if the SNMP-DPI protocol was TCP only, it would cap how many sub-agents an agent could support. That's why some SNMP-DPI agents support both TCP and UDP socket type communication mechanisms for the protocol π«§
Quick note: in the rest of this text, the SNMP-DPI agent is just called the agent. Easy peasy π
Once the transport connection is set up, the sub-agent also has to initialize the logical connection with the agent. To do that, it sends an OPEN request to the agent. In that request, the sub-agent uniquely identifies itself and passes some other parameters, like the maximum number of varBinds per interaction it's prepared to handle, and the timeout the agent should use when it's waiting for a response from the sub-agent β³
When the sub-agent is about to stop or cease operations, it first issues a CLOSE to shut down the logical connection with the agent, and only then closes the transport connection πͺπ
2.2. REGISTRATION π
A sub-agent supports a collection of MIB variables or object identifiers (object IDs) that together make up its MIB (sub)tree. Each of these object IDs is made of a group ID and an instance ID. The group ID is the root of the MIB tree the sub-agent supports, and it's the point of registration into the agent's MIB tree π³. The instance ID is the piece of the Object Identifier that comes after the group ID (registration point), so it is NOT an instance in the SNMP sense of the word. Plot twist π
No matter which transport mechanism is used, after the sub-agent connects to the agent, it registers a branch (group ID) to the Agent's MIB tree. With the registration request, the sub-agent passes some parameters, like requested priority and a timeout value for that specific sub-tree π―
The agent sends back a response to say whether the registration request worked or didn't β β
2.3. NORMAL OPERATION πΈ
Once the sub-agent has set up both the physical and logical connection to the agent, and once it has successfully registered the sub-tree(s) of the MIB(s) it supports, it just waits for requests from the SNMP agent or generates traps as required. Main character energy ππ¦
2.4. DPI ARCHITECTURE
Okay so, these are the requests the SNMP agent can start on its own π
GET, GETNEXT, GETBULK, SET, COMMIT, UNDO, UNREGISTER, and CLOSE.
The first four are basically the SNMP requests a network management station can send β¨ (by default, the agent turns a GETBULK into a bunch of GETNEXT requests, but a sub-agent can ask for the GETBULK to be passed straight to it π§). COMMIT, UNDO, UNREGISTER, ARE_YOU_THERE and CLOSE are SNMP-DPI-specific requests π. The sub-agent usually answers with a RESPONSE packet. CLOSE is the plot twist π because the sub-agent just closes the physical connection instead.
Now here are the requests a sub-agent can start π¦
OPEN, REGISTER, TRAP, UNREGISTER, ARE_YOU_THERE and CLOSE.
The agent answers OPEN, REGISTER, UNREGISTER and ARE_YOU_THERE with a RESPONSE packet π. A TRAP packet is just accepted and forwarded by the agent, and the agent doesn't send any info back to the sub-agent πΈ. A CLOSE packet is also just accepted, and then the agent closes the physical connection π₯.
Check out Figure 1 for the big-picture DPI packet flow π
-------------------------------------------------------------------
*---------------------------------*
| |
| SNMP Network |
| Management Station |
| |
|---------------------------------|
| SNMP Protocol |
*---------------------------------*
A | Get A
| | GetNext | GetResponse
Trap | | GetBulk |
| | Set |
| V |
*------------------------------* *-------------------*
| SNMP Protocol | | DPI Interface |
|------------------------------| Response | *--------------|
| | |<----------->| | |
| | | | | |
| SNMP Agent | | | | |
| | | Get,GetNext | | |
| | | (GetBulk) | | Client |
| | | Set,Commit | | |
| A *-----------+-> | Undo | | |
| | | Get/Set | |------------>| | or |
| Trap| | info | | | | |
| | | | SNMP | | | |
|-----+-----+-------* | | trap | | SNMP |
| | V | | DPI |<------------| | Sub-Agent |
| | | | | | |
| Statically Linked | | | | | |
| Instrumentation | | | | | |
| (like MIB II) | | | | | |
| | | | close | | |
| A | | | unregister | | |
|-------+-----------| | |<----------->| | |
| V | | | | | |
| | | | | | |
| | | | AreYouThere | | |
| TCP/IP layers | | | open | | |
| Kernel | | | register | | |
| | | |<------------| | |
*------------------------------* *-------------------*
-------------------------------------------------------------------
Figure 1. SNMP DPI overview
Here's the tea on Figure 1 β
- The SNMP agent talks to the SNMP manager using the regular SNMP protocol π
- The SNMP agent talks to some statically linked-in instrumentation (probably MIB II π§), which then talks to the TCP/IP layers and the kernel (the operating system) in an implementation-dependent way π
- A SNMP sub-agent runs as its own separate process (it could even be on another machine πΈ) and can set up a connection with the agent. The sub-agent can talk to the SNMP agent over UDP or TCP sockets, or even other mechanisms π¦
- Once the connection is up, the sub-agent sends a DPI OPEN and one or more REGISTER requests to register one or more MIB sub-trees with the SNMP agent π
- The SNMP agent answers DPI OPEN and REGISTER requests with a RESPONSE packet, saying whether it worked or not β¨
- The SNMP agent decodes SNMP packets π. If a packet has a Get or GetNext request for an object in a sub-tree that a sub-agent registered, the agent sends a matching DPI packet to that sub-agent π. If the request is a GetBulk, the agent turns it into multiple DPI GETNEXT packets and sends those to the sub-agent. The sub-agent can ask (in the REGISTER packet) for GETBULK to be passed to it instead π. If the request is a Set, the agent uses a 2-phase commit scheme and sends the sub-agent a sequence of SET/COMMIT, SET/UNDO or SET/COMMIT/UNDO DPI packets π₯
- The SNMP sub-agent sends its responses back in a RESPONSE packet π
- The SNMP agent then encodes the reply into an SNMP packet and sends it back to the manager that asked π¨
- If the sub-agent wants to report an important state change π¨, it sends a DPI TRAP packet to the SNMP agent, which encodes it into an SNMP trap packet and sends it to the manager(s) π«Ά
- If the sub-agent wants to stop operating π, it sends a DPI UNREGISTER and a DPI CLOSE packet to the agent. The agent sends a response to the UNREGISTER πΈ
- There's no RESPONSE to a CLOSE. The agent just closes the DPI connection π₯. A CLOSE implies an UNREGISTER for every registration that exists on the DPI connection being closed π
- The agent can send a DPI UNREGISTER (for example, if a higher priority registration comes in, or for other reasons) to the sub-agent, and the sub-agent then responds with a DPI RESPONSE packet π
- The agent can also send a DPI CLOSE, for whatever reason, to say it's ending the DPI connection π
- A sub-agent can send an ARE_YOU_THERE to check that the "connection" is still open. If it is, the agent sends a RESPONSE with no error. Otherwise, the agent may send a RESPONSE with an error indication, or it may not react at all π§
3. SNMP DPI PROTOCOL β¨
This section is where we get into the actual protocol that the SNMP agent and sub-agents use to talk to each other π.
3.1. CONNECTION ESTABLISHMENT
Okay, so in a TCP/IP setup, the SNMP agent listens on an arbitrary TCP/UDP port for a connection request from a sub-agent π¦. Here's the important bit: there's no well-known port. Every time the SNMP agent starts up, it could end up using a different TCP/UDP port π.
So a sub-agent has to figure out which port to use before it can connect π. It finds out by sending the agent one conventional SNMP get-request PDU. The port numbers are stored by the SNMP agent as the objects with these identifiers π :
1.3.6.1.4.1.2.2.1.1.0 dpiPort.0 (old DPI 1.x form)
1.3.6.1.4.1.2.2.1.1.1.0 dpiPortForTCP.0
1.3.6.1.4.1.2.2.1.1.2.0 dpiPortForUDP.0
These variables are registered under the IBM enterprise-specific tree π. Check out "4, DPI 2.0 MIB definition" for more details π. The SNMP agent replies with a conventional SNMP response PDU that has the port number to use π. The sub-agent looks at that response, pulls out the port number, and then connects to that port π«Ά.
It looks like this means the sub-agent has to be able to build and parse SNMP packets, but nope, that's not the case π ββοΈ. A DPI Application Programming Interface (API) usually gives you a library routine called query_DPI_port(), which does the generating and parsing of the required SNMP packets for you β¨. It's a tiny routine (under 100 lines of C) and doesn't really make any sub-agent much bigger π.
NOTE: This RFC doesn't define an API, so the actual code of, and the interface to, a query_DPI_port() type of function depends on the implementation π.
For completeness, the byte-by-byte descriptions of the packets that an SNMP DPI API routine called query_DPI_port() generates are included below π§. Honestly, most readers won't find this super interesting, and reading the source of a query_DPI_port() function gives you pretty much the same info π .
3.1.1 SNMP PDU TO GET THE AGENT'S DPI PORT π
okay so, like I said earlier, before a TCP/UDP connection to the SNMP agent can happen, the sub-agent has to figure out which port the agent is listening on π. to do that, it can send an SNMP GET for the variable dpiPortForTCP.0 (1.3.6.1.4.1.2.2.1.1.1.0) or dpiPortForUDP.0 (1.3.6.1.4.1.2.2.1.1.2.0) π.
the SNMP PDU gets built like this. it must be sent to UDP port 161 on the host where the agent runs (probably the same host where the sub-agent runs) π§.
the (SNMPv1) packet below is for the TCP port π¦.
+-----------------------------------------------------------------+
| Table 1 (Page 1 of 2). SNMP GET PDU for dpiPortForTCP.0 |
+---------------+----------------+--------------------------------+
| OFFSET | VALUE | FIELD |
+---------------+----------------+--------------------------------+
| 0 | 0x30 | ASN.1 header |
+---------------+----------------+--------------------------------+
| 1 | 37 + len | PDU_length, see formula below |
+---------------+----------------+--------------------------------+
| 2 | 0x02 0x01 0x00 | SNMP version: |
| | | (integer,length=1,value=0) |
+---------------+----------------+--------------------------------+
| 5 | 0x04 | community name (string) |
+---------------+----------------+--------------------------------+
| 6 | len | length of community name |
+---------------+----------------+--------------------------------+
| 7 | community name | varies |
+---------------+----------------+--------------------------------+
| 7 + len | 0xa0 0x1c | SNMP GET request: |
| | | request_type=0xa0,length=0x1c |
+---------------+----------------+--------------------------------+
| 7 + len + 2 | 0x02 0x01 0x01 | SNMP request ID: |
| | | integer,length=1,ID=1 |
+---------------+----------------+--------------------------------+
| 7 + len + 5 | 0x02 0x01 0x00 | SNMP error status: |
| | | integer,length=1,error=0 |
+---------------+----------------+--------------------------------+
| 7 + len + 8 | 0x02 0x01 0x00 | SNMP index: |
| | | integer,length=1,index=0 |
+---------------+----------------+--------------------------------+
| 7 + len + 11 | 0x30 0x11 | varBind list, length=0x11 |
+---------------+----------------+--------------------------------+
| 7 + len + 13 | 0x30 0x0f | varBind, length=0x0f |
+---------------+----------------+--------------------------------+
| 7 + len + 15 | 0x06 0x0b | Object ID, length=0x0b |
+---------------+----------------+--------------------------------+
+-----------------------------------------------------------------+
| Table 1 (Page 2 of 2). SNMP GET PDU for dpiPortForTCP.0 |
+---------------+----------------+--------------------------------+
| OFFSET | VALUE | FIELD |
+---------------+----------------+--------------------------------+
| 7 + len + 17 | 0x2b 0x06 0x01 | Object-ID: |
| | 0x04 0x01 0x02 | 1.3.6.1.4.1.2.2.1.1.1 |
| | 0x02 0x01 0x01 | Object-instance: 0 |
| | 0x01 0x00 | |
+---------------+----------------+--------------------------------+
| 7 + len + 28 | 0x05 0x00 | null value, length=0 |
+---------------+----------------+--------------------------------+
| NOTE: Formula to calculate "PDU_length": |
| |
| PDU_length = length of version field and string tag (4 bytes)|
| + length of community length field (1 byte) |
| + length of community name (depends...) |
| + length of SNMP GET request (32 bytes) |
| |
| = 37 + length of community name |
+-----------------------------------------------------------------+
3.1.2 SNMP PDU CONTAINING THE RESPONSE TO THE GET πΈ
if no errors happened, the port comes back in the last few octets of the received packet π. in the simple case, where the port number is between 1024 and 16,385, the packet looks like the table below π.
Note: in practice, the port number can be any positive number in the range from 1 through 65,535 β¨. a port number of 0 means that the agent does not have a dpiPort defined for the requested protocol π. so the actual port value may be in the last 1, 2 or 3 octets π«Ά. the sample implementation code shows how to handle the response to cover all those cases, including error conditions π .
Note: the (SNMPv1) packet below is for the TCP port π.
+-----------------------------------------------------------------+
| Table 2 (Page 1 of 3). SNMP RESPONSE PDU for dpiPortForTCP.0 |
+---------------+----------------+--------------------------------+
| OFFSET | VALUE | FIELD |
+---------------+----------------+--------------------------------+
| 0 | 0x30 | ASN.1 header |
+---------------+----------------+--------------------------------+
| 1 | 39 + len | length, see formula below |
+---------------+----------------+--------------------------------+
+-----------------------------------------------------------------+
| Table 2 (Page 2 of 3). SNMP RESPONSE PDU for dpiPortForTCP.0 |
+---------------+----------------+--------------------------------+
| OFFSET | VALUE | FIELD |
+---------------+----------------+--------------------------------+
| 2 | 0x02 0x01 0x00 | version |
| | | (integer,length=1,value=0) |
+---------------+----------------+--------------------------------+
| 5 | 0x04 | community name (string) |
+---------------+----------------+--------------------------------+
| 6 | len | length of community name |
+---------------+----------------+--------------------------------+
| 7 | community name | |
+---------------+----------------+--------------------------------+
| 7 + len | 0xa2 0x1e | SNMP RESPONSE: |
| | | request_type=0xa2,length=0x1e |
+---------------+----------------+--------------------------------+
| 7 + len + 2 | 0x02 0x01 0x01 | SNMP request ID: |
| | | integer,length=1,ID=1 |
+---------------+----------------+--------------------------------+
| 7 + len + 5 | 0x02 0x01 0x00 | SNMP error status: |
| | | integer,length=1,error=0 |
+---------------+----------------+--------------------------------+
| 7 + len + 8 | 0x02 0x01 0x00 | SNMP index: |
| | | integer,length=1,index=0 |
+---------------+----------------+--------------------------------+
| 7 + len + 11 | 0x30 0x13 | varBind list, length=0x13 |
+---------------+----------------+--------------------------------+
| 7 + len + 13 | 0x30 0x11 | varBind, length=0x11 |
+---------------+----------------+--------------------------------+
| 7 + len + 15 | 0x06 0x0b | Object ID, length=0x0b |
+---------------+----------------+--------------------------------+
| 7 + len + 17 | 0x2b 0x06 0x01 | Object-ID: |
| | 0x04 0x01 0x02 | 1.3.6.1.4.1.2.2.1.1.1 |
| | 0x02 0x01 0x01 | Object-instance: 0 |
| | 0x01 0x00 | |
+---------------+----------------+--------------------------------+
| 7 + len + 28 | 0x02 0x02 | integer, length=2 |
+---------------+----------------+--------------------------------+
| 7 + len + 30 | MSB LSB | port number (MSB, LSB) |
+---------------+----------------+--------------------------------+
+-----------------------------------------------------------------+
| Table 2 (Page 3 of 3). SNMP RESPONSE PDU for dpiPortForTCP.0 |
+---------------+----------------+--------------------------------+
| NOTE: Formula to calculate "PDU_length": |
| |
| PDU_length = length of version field and string tag (4 bytes)|
| + length of community length field (1 byte) |
| + length of community name (depends...) |
| + length of SNMP RESPONSE (34 bytes) |
| |
| = 39 + length of community name |
+-----------------------------------------------------------------+
3.2 SNMP DPI PACKET FORMATS π
every request going to the agent or sub-agent, and every response coming back, gets built as a "packet" and written to the stream π.
each packet starts with the length of the data left in the packet π. the length is stored in network byte order, with the most significant byte (MSB) first and the least significant byte (LSB) last π§ . if we're looking at a stream connection (like TCP), the receiving side reads the packet by doing something similar to this π:
unsigned char len_bfr[2];
unsigned char *bfr;
int len;
read(fd,len_bfr,2);
len = len_bfr[0] * 256 + len_bfr[1];
bfr = malloc(len);
read(fd,bfr,len);
Note: the example above makes no provisions for error handling or a read returning less than the requested amount of data,and it is not intended to be used literally π.
3.2.1. DPI PACKET HEADER β¨
okay so every single packet starts with the same little header, bestie π it tells you which application protocol is being used and some version info. The protocol major version is meant to show, in broad terms, which version of the protocol is in use. The protocol minor version is meant to identify major incompatible versions of the protocol π and the protocol release is for incremental modifications. The valid constants for these fields are defined in Table 15 π
next up, the packet ID, which shows up in every packet π¦ it's packet identification that helps an agent or sub-agent match responses with requests. this is super useful with UDP connections, where packets can get lost π the packet ID is a monotonically increasing unsigned 16-bit integer that wraps back around at its maximum value. iconic cycling energy π
then there's the packet type, also in every packet πΈ it tells you what kind of packet you're dealing with: OPEN, REGISTER, GET, GETNEXT, GETBULK, SET, COMMIT, UNDO, TRAP, RESPONSE, UNREGISTER, or CLOSE. the allowed values for this field are defined in Table 16 π
+-----------------------------------------------------------------+
| Table 3. SNMP DPI packet header. Present in all packets. |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type |
+------------+----------------------------------------------------+
from this point on, the contents of the packet are defined by whichever protocol is being used π§ the rest of this section covers:
- Layout of packets for the SNMP DPI protocol, version 2.0. π
- Constants as defined with this version of the protocol. β¨
3.2.2. OPEN
okay bestie, so before a sub-agent can talk to a DPI capable SNMP agent, it must first send an SNMP DPI OPEN request to the agent to set up the "connection" π it's giving first impressions π
this packet has the standard SNMP DPI header plus some OPEN-specific data. that data includes:
- a timeout value (in seconds). π this is the timeout the sub-agent is requesting for all requests on objects that don't have a timeout specified for the sub-tree they're registered under. if you send a zero timeout value, the agent uses its own default timeout value. if you want something bigger than the default, you can ask for it here π but the agent may have a maximum value that you can never go over. if you ask for more than that maximum, the agent sets it to the maximum it accepts π
- the maximum number of varBinds per DPI packet that the sub-agent is prepared to handle. π
- the selected character set for the representation of the OBJECT ID strings and DisplayStrings. the choices are the native character set (0) or the ASCII character set (1). see 3.3.5, "Character set selection" for more info on character set selection π an agent may choose to support only the native character set, so be prepared π
- a null terminated sub-agent ID, which is a unique ASN.1 OBJECT identifier, written in dotted ASN.1 notation. this string is represented in the selected character set π¦
- a null terminated sub-agent description, which is a DisplayString describing the sub-agent. this string is represented in the selected character set. it can be the null-string if there's no description π
- optionally, a password that the agent uses to validate the sub-agent. whether a password is required depends on the agent implementation π if no password is passed, the length must be specified as zero.
the sub-agent must expect a response that indicates success or failure π«Ά see Table 19 for the valid codes in a DPI RESPONSE to a DPI OPEN request.
if the error_code in the RESPONSE is not SNMP_ERROR_DPI_noError, the agent closes the connection. π
+-----------------------------------------------------------------+
| Table 4. Layout SNMP DPI OPEN packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_OPEN |
+------------+----------------------------------------------------+
| 8 | requested overall timeout (seconds, MSB to LSB) |
+------------+----------------------------------------------------+
| 10 | max varBinds per DPI packet (MSB to LSB) |
+------------+----------------------------------------------------+
| 12 | Selected character set (0=Native, 1=ASCII) |
+------------+----------------------------------------------------+
| 13 | null terminated sub-agent ID (OID) |
+------------+----------------------------------------------------+
| 13+L1 | null terminated sub-agent Description |
+------------+----------------------------------------------------+
| 13+L2 | password length (zero if no password, MSB to LSB) |
+------------+----------------------------------------------------+
| 15+L2 | password (if any) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = strlen(sub-agent ID) + 1 |
| o L2 = L1 + strlen(sub-agent Description) + 1 |
| o OID and Description strings use selected character set |
+-----------------------------------------------------------------+
3.2.3. CLOSE
so when a sub-agent wants to close the "connection" with the DPI capable SNMP agent, it must send an SNMP DPI CLOSE request to the agent π the agent won't send a response. it just closes the physical connection and implicitly unregisters any sub-trees tied to that connection πΈ
the agent can also send the sub-agent an SNMP DPI CLOSE packet, which has the standard SNMP DPI header plus CLOSE-specific data. that data includes:
- a reason code for closing. see Table 21 for a list of valid reason codes. π₯
+-----------------------------------------------------------------+
| Table 5. Layout SNMP DPI CLOSE packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_CLOSE |
+------------+----------------------------------------------------+
| 8 | reason code (1 octet) |
+------------+----------------------------------------------------+
3.2.4. ARE_YOU_THERE
okay so the ARE_YOU_THERE packet lets a sub-agent check whether it still has a DPI connection with the agent π this one is necessary because a sub-agent just sits there passively waiting for requests, so it normally won't notice connection problems in a timely way π© the agent is the one that catches sub-agent connection problems quickly, because it sets a timeout when it sends a request π
a sub-agent can send an SNMP DPI ARE_YOU_THERE packet to an agent, and the agent will send back a RESPONSE with a zero error code and a zero error index if the connection is healthy β¨ otherwise, the agent may return a RESPONSE with an error indication. and if the connection is broken, the sub-agent sees no response at all π
an ARE_YOU_THERE packet is just the standard SNMP DPI header with no additional data π«§
+-----------------------------------------------------------------+
| Table 6. Layout SNMP DPI ARE_YOU_THERE packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_ARE_YOU_THERE |
+------------+----------------------------------------------------+
3.2.5 REGISTER π
okay so, when a sub-agent wants a branch of the MIB tree to be registered, it sends an SNMP DPI REGISTER packet to the agent π«Ά
This packet has the standard SNMP DPI header plus REGISTER specific data. That data is made up of:
- a requested priority. There are 2 special values, namely minus one (-1, requests best available priority) and zero (0, requests next better priority than the highest priority in use). Any other value requests a specific priority or the next best priority if already in use). The lower the number, the better the priority. An agent will send requests to only the one sub-agent that has registered with the best priority. The agent returns the actual priority assigned in the RESPONSE packet in the error_index field.
- a requested timeout. If a zero value is specified, then the agent uses the timeout value specified in the DPI OPEN request. If you want a shorter or longer timeout value for this specific sub-tree, then you specify it here. The agent has a maximum timeout it will allow in this field. The agent will use this value (or its maximum) to await a response to requests for this sub-tree.
- an indication as to whether the sub-agent wishes to handle MIB view selection (SNMPv1 community string authentication) in subsequent GET, GETNEXT or SET, COMMIT, UNDO requests. Not all DPI capable agents need to support this feature, but they must at least recognize this indication and give an appropriate response if they do not support it.
- an indication as to whether the sub-agent wishes to handle the GETBULK itself. If not, then the agent will translate a GETBULK into multiple GETNEXT requests. Not all DPI capable agents need to support this feature. They may opt to always translate a GETBULK into multiple GETNEXT requests. In this case the agent will send the appropriate RESPONSE to indicate this.
- the group ID (sub-tree) to be registered (with trailing dot). The group ID is represented in the selected character set as specified in DPI OPEN packet.
The agent will respond with an SNMP DPI RESPONSE packet indicating registration error or success. The packet ID of the response will be the same as that for the REGISTER request to which this is a response.
The group ID will be the same as that specified in the REGISTER request. There will be no instance returned (e.g. NULL string for instance ID). The value will be an SNMP_TYPE_NULL value with a zero length.
+-----------------------------------------------------------------+
| Table 7. Layout SNMP DPI REGISTER packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_REGISTER |
+------------+----------------------------------------------------+
| 8 | requested priority (MSB to LSB) |
+------------+----------------------------------------------------+
| 12 | timeout in seconds (MSB to LSB) |
+------------+----------------------------------------------------+
| 14 | view selection (0 = you (agent) do, 1 = I do) |
+------------+----------------------------------------------------+
| 15 | getbulk selection (0=use GetNext, 1=use GetBulk) |
+------------+----------------------------------------------------+
| 16 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o group ID string uses selected character set |
+-----------------------------------------------------------------+
3.2.6 UNREGISTER π¦
when a sub-agent wants to take its branch of the MIB tree back off the table, it sends an SNMP DPI UNREGISTER packet to the agent π
This packet has the standard SNMP DPI header plus UNREGISTER specific data: a null terminated string (represented in the selected character set) representing the group ID in ASN.1 dotted notation, and an indication as to the reason for the unregister (see table 14).
The agent will respond with an SNMP DPI RESPONSE packet indicating error or success. The packet ID of the response will be the same as that for the UNREGISTER request to which this is a response.
The group ID will be the same as that specified in the UNREGISTER request. There will be no instance returned (e.g. NULL string for instance ID). The value will be an SNMP_TYPE_NULL value with a zero length.
+-----------------------------------------------------------------+
| Table 8. Layout SNMP DPI UNREGISTER packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_UNREGISTER |
+------------+----------------------------------------------------+
| 8 | reason code |
+------------+----------------------------------------------------+
| 9 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o group ID string uses selected character set |
+-----------------------------------------------------------------+
3.2.7 GET β¨
when the SNMP agent gets a PDU with an SNMP GET request for a variable that lives in a sub-tree registered by a sub-agent, it passes an SNMP DPI GET packet to that sub-agent π§
This packet has the standard SNMP DPI header plus GET specific data:
- the community name used in the SNMP PDU. The length is zero unless view handling was selected by the sub-agent. The length is also zero if the SNMP PDU was not in SNMPv1 format.
- per varBind two null terminated strings (in the selected character set) representing the group and instance ID in ASN.1 dotted notation.
+-----------------------------------------------------------------+
| Table 9. Layout SNMP DPI GET packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_GET |
+------------+----------------------------------------------------+
| 8 | community name length (MSB to LSB) |
+------------+----------------------------------------------------+
| 10 | community name (if any) |
+------------+----------------------------------------------------+
| 10+L1 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 10+L2 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 10+L3 | optionally more varBinds (group/instance ID pairs) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = length of community name |
| o L2 = L1 + strlen(group ID) + 1 |
| o L3 = L2 + strlen(instance ID) + 1 |
| o group and instance ID strings use selected character set |
+-----------------------------------------------------------------+
3.2.8. GETNEXT π¦
okay so, when the SNMP agent gets a PDU with an SNMP GETNEXT request for a variable that a sub-agent might be authoritative for, it passes an SNMP DPI GETNEXT packet along to that sub-agent π
The packet has the standard SNMP DPI header, plus some GETNEXT-specific stuff:
- the community name from the SNMP PDU. The length is zero unless the sub-agent picked view handling. It's also zero if the SNMP PDU wasn't SNMPv1 format π
- for each varBind, two null terminated strings (in the selected character set) holding the group and instance ID in ASN.1 dotted notation β¨
Here's the full layout π
+-----------------------------------------------------------------+
| Table 10. Layout SNMP DPI GETNEXT packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_GETNEXT |
+------------+----------------------------------------------------+
| 8 | community name length (MSB to LSB) |
+------------+----------------------------------------------------+
| 10 | community name |
+------------+----------------------------------------------------+
| 10+L1 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 10+L2 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 10+L3 | optionally more varBinds (group/instance ID pairs) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = length of community name |
| o L2 = L1 + strlen(group ID) + 1 |
| o L3 = L2 + strlen(instance ID) + 1 |
| o group and instance ID strings use selected character set |
+-----------------------------------------------------------------+
3.2.9. GETBULK πΈ
so when the SNMP agent gets a PDU with an SNMP GETBULK request that includes variables a sub-agent might be authoritative for, it checks whether that sub-agent wants to handle the GETBULK itself (this is set at registration time) π§ If it does, the agent sends an SNMP DPI GETBULK packet over to the sub-agent.
The packet has the standard SNMP DPI header, plus GETBULK-specific data:
- non-repeaters
- max repetitions
- for each varBind, two null terminated strings (in the selected character set) holding the group and instance ID in ASN.1 dotted notation π
+-----------------------------------------------------------------+
| Table 11. Layout SNMP DPI GETBULK packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_GETBULK |
+------------+----------------------------------------------------+
| 8 | non-repeaters (4 octets, MSB to LSB) |
+------------+----------------------------------------------------+
| 12 | max-repetitions (4 octets, MSB to LSB) |
+------------+----------------------------------------------------+
| 16 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 16+L1 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 16+L2 | optionally more varBinds (group/instance ID pairs) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = strlen(group ID) + 1 |
| o L2 = L1 + strlen(instance ID) + 1 |
| o group and instance ID strings use selected character set |
+-----------------------------------------------------------------+
3.2.10. SET, COMMIT AND UNDO π
when the SNMP agent gets a PDU with an SNMP SET request for a variable inside a sub-tree that a sub-agent registered, it hands the sub-agent one of three sequences of SNMP DPI packets π
SET, COMMITis the normal flow β¨ The SET request is phase one, and the sub-agent has to check that the SET is valid and that the resources it needs are available. Then the COMMIT request comes in, and now the sub-agent must actually carry out the SET.SET, UNDOis for when one SNMP packet has a SET request covering several varBinds in different sub-trees. The agent sends a SET to all the sub-agents first. If any sub-agent comes back with an error on the SET, the agent sends UNDO to the sub-agents that didn't error, which cancels the SET π ββοΈSET, COMMIT, UNDOis the very rare one π It happens when every sub-agent replied error-free to the SET, but one of them fails to do the COMMIT. Then the agent sends an UNDO to every sub-agent involved, including the ones that already finished their COMMIT. Sub-agents should try, as best they can, to never let a commit fail, and to undo an already committed set if they're asked to.
the agent's SET flow only works if everyone plays fair, so sub-agents really should do their absolute best to never fail a COMMIT π
The packets have the standard SNMP DPI header, plus SET-specific data:
- the community name from the SNMP PDU. The length is zero unless the sub-agent picked view handling. It's also zero if the SNMP PDU wasn't SNMPv1 format.
- for each varBind:
- two null terminated strings (in the selected character set) holding the group and instance ID in ASN.1 dotted notation
- the type, value length, and value to be set
The permitted types for the type field are defined in Table 17.
See 3.3.4, "Value Representation" for how the value data is represented in the packet value field π
+-----------------------------------------------------------------+
| Table 12. Layout SNMP DPI SET, COMMIT, UNDO packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_SET/COMMIT/UNDO |
+------------+----------------------------------------------------+
| 8 | community name length (MSB to LSB) |
+------------+----------------------------------------------------+
| 10 | community name |
+------------+----------------------------------------------------+
| 10+L1 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 10+L2 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 10+L3 | SNMP Variable Type Value |
+------------+----------------------------------------------------+
| 10+L3+1 | Length of value (2 octets, MSB to LSB) |
+------------+----------------------------------------------------+
| 10+L3+3 | Value |
+------------+----------------------------------------------------+
| 10+L4 | optionally more varBinds (sequences of group ID, |
| | instance ID, Type, Length and Value) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = length of community name |
| o L2 = L1 + strlen(group ID) + 1 |
| o L3 = L2 + strlen(instance ID) + 1 |
| o L4 = L3 + 3 + length of value |
| o group and instance ID strings use selected character set |
| o OID and DisplayString values use selected character set |
| o Integer values are in network byte order |
+-----------------------------------------------------------------+
3.2.11. RESPONSE π
okay so an SNMP sub-agent must respond to a GET, GETNEXT, GETBULK, SET, COMMIT, UNDO or UNREGISTER request it got from the agent (unless it fails or has a bug ;-)) π. To do that, it sends an SNMP DPI RESPONSE packet back to the agent β¨.
Such a packet has the standard SNMP DPI header plus RESPONSE-specific data:
- an error_code,
- an error_index,
- plus, for a successful GET, GETNEXT, or GETBULK, the name/type/length/value tuple(s) representing the returned object(s). For each varBind this is described as:
- two null terminated strings (in the selected character set) representing the group and instance ID in ASN.1 dotted notation.
- the type, value length and value of the object that is returned.
The permitted types for the type field are defined in Table 17 π .
See 3.3.4, "Value Representation" for information on how the value data is represented in the packet value field π«Ά.
For an unsuccessful GET, GETNEXT or GETBULK, the sub-agent doesn't need to send back any name/type/length/value tuple(s), because by definition the varBind info is the same as in the request it's responding to, and the agent still has that info π§.
The group ID and the packet ID must always be the same as the corresponding fields in the request PDU that prompted the RESPONSE π₯.
If the response is to a SET, COMMIT or UNDO request, there's no need to return any varBind info, because by definition it's the same as in the request, and the agent still has it π.
If the response is to a REGISTER or UNREGISTER, no variable (instance) is being returned, so the instance ID is the NULL string (one 0x00 byte) πΈ. In the response to a REGISTER request indicating success, the error index contains the priority assigned by the agent π.
If the response is to an OPEN, ARE_YOU_THERE or CLOSE, no varBind data gets passed, so no group ID, instance ID or value data. The packet only includes the header, the error code and the error index π.
+-----------------------------------------------------------------+
| Table 13. Layout SNMP DPI RESPONSE packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type = SNMP_DPI_RESPONSE |
+------------+----------------------------------------------------+
| 8 | error code (1 octet) |
+------------+----------------------------------------------------+
| 9 | error index (4 octets, MSB to LSB) |
+------------+----------------------------------------------------+
| 15 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 15+L1 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 15+L2 | SNMP Variable Type Value |
+------------+----------------------------------------------------+
| 15+L2+1 | Length of value (MSB to LSB) |
+------------+----------------------------------------------------+
| 15+L2+3 | Value |
+------------+----------------------------------------------------+
| 15+L3 | optionally more varBinds (sequences of group ID, |
| | instance ID, Type, Length and Value) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = strlen(group ID) + 1 |
| o L2 = L1 + strlen(instance ID) + 1 |
| o L3 = L2 + 3 + length of value |
| o group and instance ID strings use selected character set |
| o OID and DisplayString values use selected character set |
| o Integer values are in network byte order |
+-----------------------------------------------------------------+
3.2.12. TRAP π¦
so an SNMP sub-agent can ask the agent to generate an SNMPv1 or SNMPv2 TRAP (depending on the trap destinations defined at the agent) by sending an SNMP DPI TRAP packet to the agent π£.
Such a packet has the standard SNMP DPI header plus TRAP-specific data:
- the generic and specific trap codes
- optionally a null terminated string (in the selected character set) representing the enterprise ID in ASN.1 dotted notation. This enterprise ID will be sent with the TRAP. If the null string is passed, then the agent uses the sub-agent Identifier (OID as passed with the DPI OPEN packet) as the Enterprise ID π.
- optionally a set of one or more name/type/length/value tuples, representing varBinds to be sent with the trap. Each varBind consists of:
- two null terminated strings (in the selected character set) representing the group and instance ID in ASN.1 dotted notation.
- the type, value length and value of the object that is returned.
The permitted types for the type field are defined in Table 17 π .
See 3.3.4, "Value Representation" for information on how the value data is represented in the packet value field π«Ά.
+-----------------------------------------------------------------+
| Table 14. Layout SNMP DPI TRAP packet |
+------------+----------------------------------------------------+
| OFFSET | FIELD |
+------------+----------------------------------------------------+
| 0 | packet length to follow (MSB to LSB) |
+------------+----------------------------------------------------+
| 2 | protocol major version |
+------------+----------------------------------------------------+
| 3 | protocol minor version |
+------------+----------------------------------------------------+
| 4 | protocol release |
+------------+----------------------------------------------------+
| 5 | packet id (MSB to LSB) |
+------------+----------------------------------------------------+
| 7 | packet type - SNMP_DPI_TRAP |
+------------+----------------------------------------------------+
| 8 | SNMP generic trap code |
+------------+----------------------------------------------------+
| 12 | SNMP specific trap code |
+------------+----------------------------------------------------+
| 14 | null terminated enterprise ID (no trailing dot) |
+------------+----------------------------------------------------+
| 14+L1 | null terminated group ID (with trailing dot) |
+------------+----------------------------------------------------+
| 14+L2 | null terminated instance ID (no trailing dot) |
+------------+----------------------------------------------------+
| 14+L3 | SNMP Variable Type Value |
+------------+----------------------------------------------------+
| 14+L3+1 | Length of value (MSB to LSB) |
+------------+----------------------------------------------------+
| 14+L3+3 | Value |
+------------+----------------------------------------------------+
| 14+L4 | optionally more varBinds (sequences of group ID, |
| | instance ID, Type, Length and Value) |
+------------+----------------------------------------------------+
| NOTE: |
| |
| o L1 = strlen(enterprise ID) + 1 |
| o L2 = L1 + strlen(group ID) + 1 |
| o L3 = L1 + L2 + strlen(instance ID) + 1 |
| o L4 = L1 + L2 + L3 + 3 + length of Value |
| o enterprise, group and instance ID strings use selected |
| character set |
| o OID and DisplayString values use selected character set |
| o Integer values are in network byte order |
+-----------------------------------------------------------------+
3.3. CONSTANTS AND VALUES π
this section describes the constants that have been defined for this version of the SNMP DPI Protocol π.
3.3.1. PROTOCOL VERSION AND RELEASE VALUES β¨
+-----------------------------------------------------------------+
| Table 15. Protocol version and release values |
+--------------------------------+--------------------------------+
| FIELD | VALUE |
+--------------------------------+--------------------------------+
| protocol major version | 2 (SNMP DPI protocol) |
+--------------------------------+--------------------------------+
| protocol minor version | 2 (version 2) |
+--------------------------------+--------------------------------+
| protocol release | 0 (release 0) |
+--------------------------------+--------------------------------+
previous versions of this protocol exist and should preferably be supported by an agent:
- version 1, release 0, described in [7]
previous internal versions of this protocol exist and may or may not be supported by an agent:
- version 1, release 1, experimental within IBM.
- version 1, release 2, experimental within BNR.
3.3.2 PACKET TYPE VALUES β¨
okay so the packet type field is literally how we know what kind of DPI packet we're looking at π«Ά here's the whole cast, bestie π
+-----------------------------------------------------------------+
| Table 16. Valid values for the packet type field |
+-------+---------------------------------------------------------+
| VALUE | PACKET TYPE |
+-------+---------------------------------------------------------+
| 1 | SNMP_DPI_GET |
+-------+---------------------------------------------------------+
| 2 | SNMP_DPI_GETNEXT |
+-------+---------------------------------------------------------+
| 3 | SNMP_DPI_SET |
+-------+---------------------------------------------------------+
| 4 | SNMP_DPI_TRAP |
+-------+---------------------------------------------------------+
| 5 | SNMP_DPI_RESPONSE |
+-------+---------------------------------------------------------+
| 6 | SNMP_DPI_REGISTER |
+-------+---------------------------------------------------------+
| 7 | SNMP_DPI_UNREGISTER |
+-------+---------------------------------------------------------+
| 8 | SNMP_DPI_OPEN |
+-------+---------------------------------------------------------+
| 9 | SNMP_DPI_CLOSE |
+-------+---------------------------------------------------------+
| 10 | SNMP_DPI_COMMIT |
+-------+---------------------------------------------------------+
| 11 | SNMP_DPI_UNDO |
+-------+---------------------------------------------------------+
| 12 | SNMP_DPI_GETBULK |
+-------+---------------------------------------------------------+
| 13 | SNMP_DPI_TRAPV2 (not yet used) |
+-------+---------------------------------------------------------+
| 14 | SNMP_DPI_INFORM (not yet used) |
+-------+---------------------------------------------------------+
| 15 | SNMP_DPI_ARE_YOU_THERE |
+-------+---------------------------------------------------------+
3.3.3 VARIABLE TYPE VALUES π
next up is the Value Type field, which tells you what flavour of data is riding along in a variable π check out the full list:
+-----------------------------------------------------------------+
| Table 17. Valid values for the Value Type field |
+-------+---------------------------------------------------------+
| VALUE | VALUE TYPE |
+-------+---------------------------------------------------------+
| 129 | SNMP_TYPE_Integer32 |
+-------+---------------------------------------------------------+
| 2 | SNMP_TYPE_OCTET_STRING |
+-------+---------------------------------------------------------+
| 3 | SNMP_TYPE_OBJECT_IDENTIFIER |
+-------+---------------------------------------------------------+
| 4 | SNMP_TYPE_NULL (empty, no value) |
+-------+---------------------------------------------------------+
| 5 | SNMP_TYPE_IpAddress |
+-------+---------------------------------------------------------+
| 134 | SNMP_TYPE_Counter32 |
+-------+---------------------------------------------------------+
| 135 | SNMP_TYPE_Gauge32 |
+-------+---------------------------------------------------------+
| 136 | SNMP_TYPE_TimeTicks (1/100ths seconds) |
+-------+---------------------------------------------------------+
| 9 | SNMP_TYPE_DisplayString |
+-------+---------------------------------------------------------+
| 10 | SNMP_TYPE_BIT_STRING |
+-------+---------------------------------------------------------+
| 11 | SNMP_TYPE_NsapAddress |
+-------+---------------------------------------------------------+
| 140 | SNMP_TYPE_UInteger32 |
+-------+---------------------------------------------------------+
| 13 | SNMP_TYPE_Counter64 |
+-------+---------------------------------------------------------+
| 14 | SNMP_TYPE_Opaque |
+-------+---------------------------------------------------------+
| 15 | SNMP_TYPE_noSuchObject |
+-------+---------------------------------------------------------+
| 16 | SNMP_TYPE_noSuchInstance |
+-------+---------------------------------------------------------+
| 17 | SNMP_TYPE_endOfMibView |
+-------+---------------------------------------------------------+
Notes:
- ngl this one's a bit of a mouthful π a 32-bit integer value has its base base type ORed with 128. so 129 is Integer32, 140 is UInteger32, and so on π§
- DisplayString is a textual convention πΈ an SNMP PDU shows a type of OCTET_STRING for the value. an agent can handle such an object as DisplayString if the object is included in some form of a compiled MIB for the agent. if not, the agent passes the value as an OCTET_STRING. the vibe is "check the MIB first" π
3.3.4 VALUE REPRESENTATION π
so how do values actually look inside a DPI packet? here's the tea π«
- 32-bit integers are 4-byte elements in network byte order, MSB (most significant byte) first, LSB (least significant byte) last. Example:
'00000001'hrepresents 1. π₯ - 64-bit integers are 8-byte elements in network byte order, MSB first, LSB last. Example:
'0000000100000001'hrepresents 4,294,967,297. π - Object Identifiers are NULL terminated strings in the selected character set, representing the OID in ASN.1 dotted notation. The length includes the terminating NULL.
- Example ASCII:
'312e332e362e312e322e312e312e312e3000'hrepresents "1.3.6.1.2.1.1.1.0" which is sysDescr.0. - Example EBCDIC:
'f14bf34bf64bf14bf24bf14bf14bf14bf000'hrepresents "1.3.6.1.2.1.1.1.0" which is sysDescr.0.
- Example ASCII:
- DisplayStrings are in the selected character set. The length specifies the length of the string.
- Example ASCII:
'6162630d0a'hrepresents "abc\r\n", no NULL. - Example EBCDIC:
'8182830d25'hrepresents "abc\r\n", no NULL.
- Example ASCII:
- IpAddress, NsapAddress and Opaque are implicit OCTET_STRING, so they are octets (e.g. IpAddress in network byte order). π¦
- NULL has a zero length for the value, no value data. π
- noSuchObject, noSuchInstance and endOfMibView are implicit NULL and represented as such. π
- BIT_STRING is an OCTET_STRING of the form
uubbbb...bb, where the first octet (uu) is 0x00-0x07 and indicates the number of unused bits in the last octet (bb). The bb octets represent the bit string itself, where bit zero (0) comes first and so on. β¨
3.3.5 CHARACTER SET SELECTION πΈ
in the DPI OPEN packet, the sub-agent gets to pick the character set for a few things, and this is giving main character energy π
- group and instance ID in the DPI REGISTER, UNREGISTER, GET, GETNEXT, GETBULK, SET, UNDO, COMMIT, RESPONSE and TRAP packets.
- sub-agent ID and sub-agent Description in DPI OPEN packet.
- Object Identifiers in the value field for a value of type SNMP_TYPE_OBJECT_IDENTIFIER.
- DisplayString in the value field for a value of type SNMP_TYPE_DPI_DisplayString.
the choice is the native character set or the ASCII character set. π
the native set is the set native to the platform where the agent runs. if the native set is ASCII, then character set selection is a moot point π«Ά on non-ASCII based platforms, the agent must convert between native and ASCII if the native character set is chosen. that's the whole saga β¨
3.3.6. ERROR CODE VALUES FOR SNMP DPI RESPONSE PACKETS β¨
okay so when a RESPONSE packet is answering a GET, GETNEXT, GETBULK, SET, COMMIT, or UNDO, its error code can be one of these values π
+-----------------------------------------------------------------+
| Table 18. Valid SNMP_ERROR values for RESPONSE error code |
+-------+---------------------------------------------------------+
| VALUE | ERROR CODE |
+-------+---------------------------------------------------------+
| 0 | SNMP_ERROR_noError |
+-------+---------------------------------------------------------+
| 1 | SNMP_ERROR_tooBig |
+-------+---------------------------------------------------------+
| 2 | SNMP_ERROR_noSuchName (SNMPv1, do not use) |
+-------+---------------------------------------------------------+
| 3 | SNMP_ERROR_badValue (SNMPv1, do not use) |
+-------+---------------------------------------------------------+
| 4 | SNMP_ERROR_readOnly (SNMPv1 do not use) |
+-------+---------------------------------------------------------+
| 5 | SNMP_ERROR_genErr |
+-------+---------------------------------------------------------+
| 6 | SNMP_ERROR_noAccess |
+-------+---------------------------------------------------------+
| 7 | SNMP_ERROR_wrongType |
+-------+---------------------------------------------------------+
| 8 | SNMP_ERROR_wrongLength |
+-------+---------------------------------------------------------+
| 9 | SNMP_ERROR_wrongEncoding |
+-------+---------------------------------------------------------+
| 10 | SNMP_ERROR_wrongValue |
+-------+---------------------------------------------------------+
| 11 | SNMP_ERROR_noCreation |
+-------+---------------------------------------------------------+
| 12 | SNMP_ERROR_inconsistentValue |
+-------+---------------------------------------------------------+
| 13 | SNMP_ERROR_resourceUnavailable |
+-------+---------------------------------------------------------+
| 14 | SNMP_ERROR_commitFailed |
+-------+---------------------------------------------------------+
| 15 | SNMP_ERROR_undoFailed |
+-------+---------------------------------------------------------+
| 16 | SNMP_ERROR_authorizationError |
+-------+---------------------------------------------------------+
| 17 | SNMP_ERROR_notWritable |
+-------+---------------------------------------------------------+
| 18 | SNMP_ERROR_inconsistentName |
+-------+---------------------------------------------------------+
and when the RESPONSE packet is answering an OPEN, REGISTER or UNREGISTER, the error code picks from this list instead π§
+-----------------------------------------------------------------+
| Table 19. Valid SNMP_ERROR_DPI values for RESPONSE error code |
+-------+---------------------------------------------------------+
| VALUE | ERROR CODE |
+-------+---------------------------------------------------------+
| 0 | SNMP_ERROR_DPI_noError |
+-------+---------------------------------------------------------+
| 101 | SNMP_ERROR_DPI_otherError |
+-------+---------------------------------------------------------+
| 102 | SNMP_ERROR_DPI_notFound |
+-------+---------------------------------------------------------+
| 103 | SNMP_ERROR_DPI_alreadyRegistered |
+-------+---------------------------------------------------------+
| 104 | SNMP_ERROR_DPI_higherPriorityRegistered |
+-------+---------------------------------------------------------+
| 105 | SNMP_ERROR_DPI_mustOpenFirst |
+-------+---------------------------------------------------------+
| 106 | SNMP_ERROR_DPI_notAuthorized |
+-------+---------------------------------------------------------+
| 107 | SNMP_ERROR_DPI_viewSelectionNotSupported |
+-------+---------------------------------------------------------+
| 108 | SNMP_ERROR_DPI_getBulkSelectionNotSupported |
+-------+---------------------------------------------------------+
| 109 | SNMP_ERROR_DPI_duplicateSubAgentIdentifier |
+-------+---------------------------------------------------------+
| 110 | SNMP_ERROR_DPI_invalidDisplayString |
+-------+---------------------------------------------------------+
| 111 | SNMP_ERROR_DPI_characterSetSelectionNotSupported |
+-------+---------------------------------------------------------+
3.3.7. UNREGISTER REASON CODES π¦
these are the valid reason codes you can put in an UNREGISTER packet, bestie π«Ά
+-----------------------------------------------------------------+
| Table 20. Valid UNREGISTER reason codes |
+-------+---------------------------------------------------------+
| VALUE | REASON CODE |
+-------+---------------------------------------------------------+
| 1 | SNMP_UNREGISTER_otherReason |
+-------+---------------------------------------------------------+
| 2 | SNMP_UNREGISTER_goingDown |
+-------+---------------------------------------------------------+
| 3 | SNMP_UNREGISTER_justUnregister |
+-------+---------------------------------------------------------+
| 4 | SNMP_UNREGISTER_newRegistration |
+-------+---------------------------------------------------------+
| 5 | SNMP_UNREGISTER_higherPriorityRegistered |
+-------+---------------------------------------------------------+
| 6 | SNMP_UNREGISTER_byManager |
+-------+---------------------------------------------------------+
| 7 | SNMP_UNREGISTER_timeout |
+-------+---------------------------------------------------------+
3.3.8. CLOSE REASON CODES π
and these are the valid reason codes for a CLOSE packet πΈ
+-----------------------------------------------------------------+
| Table 21. Valid CLOSE reason codes |
+-------+---------------------------------------------------------+
| VALUE | REASON CODE |
+-------+---------------------------------------------------------+
| 1 | SNMP_CLOSE_otherReason |
+-------+---------------------------------------------------------+
| 2 | SNMP_CLOSE_goingDown |
+-------+---------------------------------------------------------+
| 3 | SNMP_CLOSE_unsupportedVersion |
+-------+---------------------------------------------------------+
| 4 | SNMP_CLOSE_protocolError |
+-------+---------------------------------------------------------+
| 5 | SNMP_CLOSE_authenticationFailure |
+-------+---------------------------------------------------------+
| 6 | SNMP_CLOSE_byManager |
+-------+---------------------------------------------------------+
| 7 | SNMP_CLOSE_timeout |
+-------+---------------------------------------------------------+
| 8 | SNMP_CLOSE_openError |
+-------+---------------------------------------------------------+
4. DPI 2.0 MIB DEFINITION π
okay this is the MIB module itself π the text says the objects in this MIB are implemented in the local SNMP agent, so here's the whole thing, verbatim:
DPI20-MIB DEFINITIONS ::= BEGIN
-- Objects in this MIB are implemented in the local SNMP agent.
IMPORTS
MODULE-IDENTITY, OBJECT-TYPE, snmpModules, enterprises
FROM SNMPv2-SMI
ibm OBJECT IDENTIFIER ::= { enterprises 2 }
ibmDPI OBJECT IDENTIFIER ::= { ibm 2 }
dpi20MIB OBJECT IDENTIFIER ::= { ibmDPI 1 }
-- dpi20MIB MODULE-IDENTITY
-- LAST-UPDATED "9401210000Z"
-- ORGANIZATION "IBM Research - T.J. Watson Research Center"
-- CONTACT-INFO " Bert Wijnen
-- Postal: IBM International Operations
-- Watsonweg 2
-- 1423 ND Uithoorn
-- The Netherlands
-- Tel: +31 2975 53316
-- Fax: +31 2975 62468
-- E-mail: wijnen@vnet.ibm.com"
-- DESCRIPTION "MIB module describing DPI objects."
-- ::= { snmpModules x }
dpiPort OBJECT IDENTIFIER ::= { dpi20MIB 1 }
dpiPortForTCP OBJECT-TYPE
SYNTAX INTEGER (0..65535)
ACCESS read-only
STATUS mandatory
DESCRIPTION "The TCP port number on which the agent
listens for DPI connections. A zero value
means the agent has no DPI TCP port."
::= { dpiPort 1 }
dpiPortForUDP OBJECT-TYPE
SYNTAX INTEGER (0..65535)
ACCESS read-only
STATUS mandatory
DESCRIPTION "The UDP port number on which the agent
listens for DPI packets. A zero value
means the agent has no DPI UDP port."
::= { dpiPort 2 }
END
5. SUBAGENT CONSIDERATIONS β¨
okay bestie, this is the part where we talk about sub-agents, and it's giving "do it right or don't do it at all" π when you build one, it is strongly recommended that you use the DPI version 2 approach (the one based on SNMPv2) π here's the vibe:
- Use SNMPv2 error codes only π ββοΈ (yes, the old SNMPv1 error codes are still defined, but we are not going there)
- Do implement SET, COMMIT, and UNDO processing properly π₯ no half-baked vibes allowed
- For GET requests, follow the SNMPv2 approach and pass back a noSuchInstance or noSuchObject value when that's the situation. Keep going and process all the remaining varBinds too π
- For GETNEXT, follow the SNMPv2 approach and pass back an endOfMibView value when that's the situation. Again, keep processing all the remaining varBinds π¦
- When you're handling a request from the agent (GET, GETNEXT, GETBULK, SET, COMMIT, or UNDO), you're supposed to respond within the timeout period. You can set that timeout in the OPEN and REGISTER packets β° If you miss the window, the agent will most probably close your DPI connection and throw out your RESPONSE packet if it shows up late π If you can tell the response won't make it in time, you might choose to abort the request and send back an SNMP_ERROR_genErr in the RESPONSE π
- If you're a UDP "connected" sub-agent, or you use some other unreliable protocol, you may want to send an SNMP DPI ARE_YOU_THERE request every once in a while. This makes sure the agent is still alive and still knows you exist π«Ά
- If you're running on an EBCDIC based machine and you use the (default) native character set, then all OID strings (like the group ID, instance ID, Enterprise ID, and sub-agent ID) plus all variable values of type OBJECT_IDENTIFIER or DisplayString get passed to you in EBCDIC format. When you send a response, you should also use EBCDIC FORMAT πΈ
- If you're running on an EBCDIC based machine and you use the ASCII character set (specified in DPI OPEN), then all OID strings (like the group ID, instance ID, Enterprise ID, and sub-agent ID) plus all variable values of type OBJECT_IDENTIFIER or DisplayString get passed to you in ASCII format. When you send a response, you should also use ASCII FORMAT π§
- If you're running on an ASCII machine, then character set selection is basically moot for you π The exception is when you connect to an EBCDIC based agent. In that case, you may want to specify the ASCII character set in the DPI OPEN packet. After that, it's all transparent to you, and the conversion burden falls on the EBCDIC based agent π
- Please realize that DisplayString is only a textual convention β In the SNMP PDU (the SNMP packet), the type is just an OCTET_STRING, so it isn't clear whether the data is a DisplayString or any arbitrary data. That means the agent can only know an object is a DisplayString if the object is included in some sort of compiled MIB. If it is, the agent will use SNMP_TYPE_DisplayString in the type field of the varBind in a DPI SET packet. When you send a DisplayString in a RESPONSE packet, the agent handles it as such (for example, translating EBCDIC to ASCII if needed) π
5.1. DPI API
the main goal of this document is to specify the SNMP DPI, which is the protocol that lets sub-agents swap SNMP related information with an agent π¦ you could imagine one or possibly many Application Programming Interfaces sitting on top of it, but those aren't covered here.
that said, to get an environment that's more or less platform independent, we strongly suggest also defining a DPI API β¨ we have a sample DPI API available. See 9, "Sample Sources for Anonymous FTP" for a place to grab it π
5.2. OVERVIEW OF REQUEST PROCESSING
5.2.1. GET PROCESSING
a GET request is the easiest one to process π§ The DPI GET packet holds one or more varBinds that the sub-agent has taken responsibility for.
if the sub-agent runs into an error while processing the request, it creates a DPI RESPONSE packet with an appropriate error indication in the error_code field, and it sets the error_index to the position of the varBind where the error happened (the first varBind is index 1, the second is index 2, and so on) β You don't need to include any name/type/length/value information here, because by definition the varBind info is the same as in the request this is responding to, and the agent still has that info π
if there are no errors, the sub-agent creates a DPI RESPONSE packet where the error_code is set to SNMP_ERROR_noError (zero) and the error_index is set to zero β The packet also has to include the name/type/length/value of each varBind that was requested π when you get a request for an object that doesn't exist, or for an instance of an object that doesn't exist, you must return a NULL value with a type of SNMP_TYPE_noSuchObject or SNMP_TYPE_noSuchInstance respectively π
these two values aren't considered errors, so the error_code and error_index should be zero π«Ά
the DPI RESPONSE packet then gets sent back to the agent π¬
5.2.2. SET PROCESSING
processing a DPI SET request is way harder than a DPI GET request, ngl π With a DPI SET packet, you get extra info, namely the value type, the value length, and the value to be set π₯
if the sub-agent runs into an error while processing the request, it creates a DPI RESPONSE packet with an appropriate error indication in the error_code field, and an error_index that lists the position of the varBind where the error happened (first varBind is index 1, second is index 2, and so on) β No name/type/length/value information needs to be provided, because by definition the varBind info is the same as in the request this is answering, and the agent still has it π
if there are no errors, the sub-agent creates a DPI RESPONSE packet where the error_code is set to SNMP_ERROR_noError (zero) and the error_index is set to zero β You don't need any name/type/length/value info. By definition, the RESPONSE to a SET should contain exactly the same varBind data as the request, so the agent can just use the values it already has π§ (this means the agent has to keep state information, and yes, it does, because it needs that anyway so it can pass the data later with a DPI COMMIT or DPI UNDO packet π¦) The sub-agent must have allocated the required resources and gotten itself ready for the SET. It does not effectuate the set yet. That happens at COMMIT time π
the sub-agent sends a DPI RESPONSE packet (showing success or failure for the preparation phase) back to the agent π¬
then the agent issues a SET request for all the other varBinds in the same original SNMP request it received. Those might go to the same sub-agent or to one or more different sub-agents π§ Once every SET request has come back with a "no error" condition, the agent starts sending DPI COMMIT packets to the sub-agent(s). If any SET request returns an error, the agent sends DPI UNDO packets to those sub-agents that said their SET preparation went fine π
when the sub-agent receives the DPI COMMIT packet, all the varBind info is available in the packet again π«Ά Now the sub-agent can effectuate the SET request π₯
if the sub-agent runs into an error while processing the COMMIT request, it creates a DPI RESPONSE packet with the value SNMP_ERROR_commitFailed in the error_code field, and an error_index that lists which varBind the error happened at (first varBind is index 1, and so on) π No name/type/length/value information is needed. Just because a commitFailed error exists doesn't mean it should be returned easily π« A sub-agent should do everything that's possible to make a COMMIT succeed πͺ
if there are no errors, and the SET/COMMIT was effectuated successfully, the sub-agent creates a DPI RESPONSE packet where the error_code is set to SNMP_ERROR_noError (zero) and the error_index is set to zero. No name/type/length/value information is needed β¨
so far we've talked about the SET, COMMIT sequence, which is what happens when all goes well π· But after a successful SET, the sub-agent may still get a DPI UNDO packet. When that happens, the sub-agent must undo any preparations it made during SET processing (like freeing allocated memory and such) π§Ή Even after a COMMIT, a sub-agent may still receive a DPI UNDO packet. That's the case if some other sub-agent couldn't complete its COMMIT request. Because of the SNMP requirement that all varBinds in a single SNMP SET request must be changed "as if simultaneous," all committed changes must be undone if any of the COMMIT requests fail. In that case, the sub-agent must try to undo the committed SET operation π±
if the sub-agent runs into an error while processing the UNDO request, it creates a DPI RESPONSE packet with the value SNMP_ERROR_undoFailed in the error_code field, and an error_index that lists which varBind the error happened at (first varBind is index 1, and so on) π No name/type/length/value information is needed. Just because an undoFailed error exists doesn't mean it should be returned easily π« A sub-agent should do everything that's possible to make an UNDO succeed πͺ
if there are no errors, and the UNDO was effectuated successfully, the sub-agent creates a DPI RESPONSE packet where the error_code is set to SNMP_ERROR_noError (zero) and the error_index is set to zero. No name/type/length/value information is needed π
5.2.3 GETNEXT PROCESSING β¨
okay so GETNEXT requests are a bit more complicated to process than a GET π«Ά. The DPI GETNEXT packet holds the object(s) the GETNEXT operation has to be performed on. The vibe is that the sub-agent has to return the name/type/length/value of the next variable it supports, the one whose (ASN.1) name comes lexicographically after the one passed in the group ID (sub-tree) and instance ID π .
The instance ID might not be present (NULL) here, which means the NEXT object has to be the first instance of the first object in the sub-tree that was registered π§.
It's really important to realize that a sub-agent can support several discontiguous sections of the MIB tree π. In that situation, jumping from one section to another would be incorrect π . This is handled properly by looking at the group ID in the DPI packet. The group ID is the "reason" the sub-agent is being called, and it holds the prefix of the tree that the sub-agent registered.
If the next variable the sub-agent supports does not begin with that prefix, the sub-agent must return the same object instance as in the request (group ID and instance ID) with a value of SNMP_TYPE_endOfMibView (implied NULL value). This endOfMibView is not considered an error, so the error_code and error_index should be zero πΈ. If it's needed, the SNMP agent will call the sub-agent again, but pass it a different group ID (prefix). The example below shows exactly how that goes π.
Let's say there are two sub-agents. The first sub-agent registers two distinct sections of the tree, A and C. Realistically, that sub-agent only supports variables A.1 and A.2, but it correctly registers the minimal prefix needed to uniquely identify the variable class it supports π¦.
The second sub-agent registers a different section, B, which sits between the two sections the first agent registered π.
If a management station starts dumping the MIB from A, the sequence of queries of the form get-next(group ID, instance ID) would be:
Sub-agent 1 gets called:
get-next(A,none) = A.1
get-next(A,1) = A.2
get-next(A,2) = endOfMibView
Sub-agent 2 is then called:
get-next(B,none) = B.1
get-next(B,1) = endOfMibView
Sub-agent 1 gets called again:
get-next(C,none) = C.1
5.2.4 GETBULK PROCESSING β¨
You can ask the agent to translate GETBULK requests into multiple GETNEXT requests π. This is basically the default, and it's specified in the DPI REGISTER packet. Honestly, we expect most DPI sub-agents to run on the same machine as the agent (or, otherwise, on the same physical network), so repetitive GETNEXT requests stay local and in general shouldn't be a problem π.
If experience tells us otherwise, the sub-agent can tell the agent to pass on a DPI GETBULK packet π«£.
When a GETBULK request comes in, the sub-agent must process the request and send a RESPONSE that sends back as many varBinds as requested, as long as they fit within the buffers π¦.
GETBULK needs similar processing to a GETNEXT when it comes to endOfMibView handling π·.
5.2.5 OPEN REQUEST β¨
As the very first step, a DPI sub-agent must open a "connection" with the agent π. To do that, it must send a DPI OPEN packet in which the following things must be specified:
- The max timeout value in seconds. The agent is requested to wait this long for a response to any request for an object being handled by this sub-agent. The agent may have an absolute maximum timeout value, which will be used if the sub-agent asks for a timeout that's too big. A value of zero can be used to indicate that the agent's own default timeout value should be used. A sub-agent is advised to use a reasonably short interval, like a few seconds or so. If a specific sub-tree needs a (much) longer time, a specific REGISTER can be done for that sub-tree with a longer timeout value β°.
- The maximum number of varBinds that the sub-agent is prepared to handle per DPI packet. Specifying 1 would result in DPI version 1 behavior, which is one varBind per DPI packet sent from the agent to the sub-agent π.
- The character set you want to use. By default (value 0), this is the native character set of the machine (platform) where the agent runs.
Since the sub-agent and agent normally run on the same system or platform, you want to use the native character set (which on many platforms is ASCII anyway). If your platform is EBCDIC based, using the native EBCDIC character set makes it easy to recognize the string representations of fields like group ID, instance ID, and so on π§ .
At the same time, the agent will translate the value from ASCII NVT to EBCDIC (and vice versa) for objects that it knows (from a compiled MIB) to have a textual convention of DisplayString. Be aware that this can't be determined from the SNMP PDU encoding, because in the PDU the object is only known to be an OCTET_STRING π³.
If your sub-agent runs on an ASCII based platform and the agent runs on an EBCDIC based platform (or the other way around), you can specify that you want to use the ASCII character set, so you both know how to handle the string-based data. Beware that not all agents need to support anything other than native character set selection. See 5, "Subagent Considerations" and 3.3.5, "Character set selection" for more information on character set usage π.
- The sub-agent ID. This is an ASN.1 Object Identifier that uniquely identifies the sub-agent. This OID is represented as a null terminated string using the selected character set.
Example: "1.3.5.1.2.3.4.5".
- The sub-agent Description. This is a DisplayString describing the sub-agent. It's a character string using the selected character set.
Example: "DPI sample sub-agent version 2.0" π.
Once a sub-agent has sent a DPI OPEN packet to an agent, it should expect a DPI RESPONSE packet telling it the result of the request π¬. The packet ID of the RESPONSE packet should be the same as the packet ID of the OPEN request it's responding to. See Table 19 for a list of valid DPI RESPONSE error codes that may be expected. If you get an error RESPONSE on the OPEN packet, you'll also receive a DPI CLOSE packet with an SNMP_CLOSE_openError code, and then the agent closes the "connection" π.
If the OPEN is accepted, the next step is to REGISTER one or more MIB sub-trees π.
5.2.6 CLOSE REQUEST β¨
When a sub-agent is finished and wants to terminate, it should first UNREGISTER its sub-trees and then close the "connection" with the agent π. To do that, it must send a DPI CLOSE packet that specifies a reason for the closing. See Table 21 for a list of valid CLOSE reason codes. You should not expect a response to the CLOSE request π.
A sub-agent should also be prepared to handle an incoming DPI CLOSE packet from the agent. Again, the packet will contain a reason code for the CLOSE request. A sub-agent need not send a response to a CLOSE request. The agent just assumes that the sub-agent will handle it appropriately. The close takes place no matter what the sub-agent does with it π« .
5.2.7 REGISTER REQUEST β¨
Before a sub-agent will receive any requests for MIB variables, it must first register the variables or sub-tree it supports with the SNMP agent π. The sub-agent must specify a number of things in the REGISTER request:
- The sub-tree to be registered. This is a null terminated string in the selected character set. The sub-tree must have a trailing dot (example:
"1.3.6.1.2.3.4.5."). - The requested priority for the registration, which is one of:
-1 Request for best available priority.
0 Request for next better available priority than highest
priority currently registered for this sub-tree.
NNN Any other positive value requests that specific priority if
available or the first worse priority that is available.
- The max timeout value in seconds. The agent is requested to wait this long for a response to any request for an object in this sub-tree. The agent may have an absolute maximum timeout value, which will be used if the sub-agent asks for a timeout that's too big. A value of zero can be used to indicate that the DPI OPEN value should be used for the timeout β³.
- A specification of whether the sub-agent wants to do view selection. If it does, then the community name (from SNMPv1 packets) will be passed in the DPI GET, GETNEXT, and SET packets π.
- A specification of whether the sub-agent wants to receive GETBULK packets, or whether it just prefers that the agent converts a GETBULK into multiple GETNEXT requests π―.
Once a sub-agent has sent a DPI REGISTER packet to the agent, it should expect a DPI RESPONSE packet telling it the result of the request. The packet ID of the RESPONSE packet should be the same as the packet ID of the REGISTER packet it's responding to. If the response indicates success, then the error_index field in the RESPONSE packet contains the priority the agent assigned to the sub-tree registration π₯. See Table 19 for a list of valid DPI RESPONSE error codes that may be expected.
5.2.8 UNREGISTER REQUEST β¨
A sub-agent may unregister a previously registered sub-tree π§Ή. The sub-agent must specify a few things in the UNREGISTER request:
- The sub-tree to be unregistered. This is a null terminated string in the selected character set. The sub-tree must have a trailing dot (example:
"1.3.6.1.2.3.4.5."). - The reason for the unregister. See Table 20 for a list of valid reason codes.
Once a sub-agent has sent a DPI UNREGISTER packet to the agent, it should expect a DPI RESPONSE packet telling it the result of the request. The packet ID of the RESPONSE packet should be the same as the packet ID of the REGISTER packet it's responding to. See Table 19 for a list of valid DPI RESPONSE error codes that may be expected.
A sub-agent should also be prepared to handle incoming DPI UNREGISTER packets from the agent. Again, the DPI packet will contain a reason code for the UNREGISTER. A sub-agent need not send a response to an UNREGISTER request. The agent just assumes that the sub-agent will handle it appropriately. The registration is removed no matter what the sub-agent returns ποΈ.
5.2.9 TRAP REQUEST β¨
A sub-agent can request that the SNMP agent generate a trap for it π¨. The sub-agent must provide the desired values for the generic and specific parameters of the trap. It may optionally provide a set of one or more name/type/length/value tuples that will be included in the trap packet. It may also optionally specify an Enterprise ID (Object Identifier) for the trap to be generated. If a NULL value is specified for the Enterprise ID, then the agent will use the sub-agent Identifier (from the DPI OPEN packet) as the Enterprise ID sent with the trap π.
5.2.10. ARE_YOU_THERE REQUEST π¦
okay so a sub-agent can send an ARE_YOU_THERE packet to the agent π this is lowkey so useful if your DPI "connection" is running over an unreliable transport protocol (like UDP), because you can check that the connection is still alive π«Ά
if the "connection" is healthy, the agent replies with a RESPONSE packet carrying SNMP_ERROR_DPI_noError β¨ iconic, no notes
if the "connection" is NOT healthy π, the agent may send back a RESPONSE packet with an error indication. BUT the agent might not react at all, which means you'd just sit there and timeout while waiting for a reply π so be ready for silence, bestie
5.2.11. HOW TO QUERY THE DPI PORT. π§
the DPI API implementations are encouraged to give sub-agent programmers a facility that dynamically finds the port the agent is using for the TCP and/or UDP DPI port(s) π it's giving helpful, no cap. a suggested name for that function is query_DPI_port() π
6. REFERENCES π
[1] Case, J., Fedor, M., Schoffstall M., and J. Davin, "Simple Network Management Protocol (SNMP)", STD 15, RFC 1157, SNMP Research, Performance Systems International, MIT Laboratory for Computer Science, May 1990.
[2] Information processing systems - Open Systems Interconnection, "Specification of Abstract Syntax Notation One (ASN.1)", International Organization for Standardization, International Standard 8824, December 1987.
[3] Information processing systems - Open Systems Interconnection, "Specification of Basic Encoding Rules for Abstract Syntax Notation One (ASN.1)", International Organization for Standardization, International Standard 8825, December 1987.
[4] McCloghrie, K., and M. Rose, "Management Information Base for Network Management of TCP/IP-based internets: MIB II", STD 17, RFC 1213, Hughes LAN Systems, Performance Systems International, March 1991.
[5] Rose, M., and K. McCloghrie, "Structure and Identification of Management Information for TCP/IP-based internets", STD 16, RFC 1155, Performance Systems International, Hughes LAN Systems, May 1990.
[6] Rose, M., "SNMP MUX Protocol and MIB", RFC 1227, Performance Systems International, RFC 1227, May 1991.
[7] Carpenter G., and B. Wijnen, "SNMP-DPI, Simple Network Management Protocol Distributed Program Interface", RFC 1228, International Business Machines, Inc., May 1991.
[8] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "SNMPv2 RFCs (RFC 1441 through RFC 1452)", SNMP Research Inc, Hughes LAN Systems, Dover Beach Consulting Inc, Carnegie Mellon University, Trusted Information Systems, April 1993.
[9] International Business Machines, Inc., TCP/IP for VM: Programmer's Reference, SC31-6084-0, 1990.
[10] International Business Machines, Inc., Virtual Machine System Facilities for Programming, Release 6, SC24-5288-01, 1988.
7. SECURITY CONSIDERATIONS π
security issues are not discussed in this memo π so nothing to see here from this doc itself, but stay curious and keep your guard up out there, fr fr π
8. AUTHORS' ADDRESSES π
Bert Wijnen
IBM International Operations
Watsonweg 2
1423 ND Uithoorn
The Netherlands
Phone: +31-2975-53316
Fax: +31-2975-62468
EMail: wijnen@vnet.ibm.com
Geoffrey C. Carpenter
IBM T.J. Watson Research Center
P.O. Box 218
Yorktown Heights, NY 10598
USA
Phone: +1-914-945-1970
EMail: gcc@watson.ibm.com
Kim Curran
Bell Northern Research Ltd.
P.O. Box 3511 Station C
Ottawa, Ontario K1Y 4HY
Canada
Phone: +1-613-763-5283
EMail: kcurran@bnr.ca
Aditya Sehgal
Bell Northern Research Ltd.
P. O. Box 3511 Station C
Ottawa, Ontario K1Y 4HY
Canada
Phone: +1-613-763-8821
EMail: asehgal@bnr.ca
Glen Waters
Bell Northern Research Ltd.
P.O. Box 3511 Station C
Ottawa, Ontario K1Y 4HY
Canada
Phone: +1-613-763-3933
EMail: gwaters@bnr.ca
9. SAMPLE SOURCES FOR ANONYMOUS FTP π¦
an implementation sample of a DPI API (as used at the agent and sub-agent side) plus sample sub-agent code and documentation are available for anonymous FTP from:
software.watson.ibm.com (129.34.139.5)
to get the source, do these steps, bestie π
ftp software.watson.ibm.com
user: anonymous
password: your_e-mail_address
cd /public/dpi
get README
binary
get dpi_api.tar (or compressed dpi_api.tar.Z)
quit
π¦ where this page comes from
- ietf: rfc1592 1994-03
- π girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms