RFC 1098

Simple Network Management Protocol (SNMP)

πŸ“… published April 1989, from ietf

RFC 1098: A Simple Network Management Protocol (SNMP) πŸŽ€

okay bestie, so this is RFC 1098 ✨, from the Network Working Group, and it's titled A Simple Network Management Protocol (SNMP). The authors are J. Case (University of Tennessee at Knoxville), M. Fedor (NYSERNet, Inc.), M. Schoffstall (Rensselaer Polytechnic Institute), and C. Davin (MIT Laboratory for Computer Science). It's dated April 1989 πŸ“…. It obsoletes RFC 1067 πŸ’€, so 1098 is the replacement, iykyk. The header doesn't have an "Updates" entry. Its status lives in Section 1, which says it's a re-release of RFC 1067 with a changed "Status of this Memo" section πŸ’….

Table of Contents πŸ“š

   1. Status of this Memo ...................................    2
   2. Introduction ..........................................    2
   3. The SNMP Architecture .................................    4
   3.1 Goals of the Architecture ............................    4
   3.2 Elements of the Architecture .........................    4
   3.2.1 Scope of Management Information ....................    5
   3.2.2 Representation of Management Information ...........    5
   3.2.3 Operations Supported on Management Information .....    6
   3.2.4 Form and Meaning of Protocol Exchanges .............    7
   3.2.5 Definition of Administrative Relationships .........    7
   3.2.6 Form and Meaning of References to Managed Objects ..   11
   3.2.6.1 Resolution of Ambiguous MIB References ...........   11
   3.2.6.2 Resolution of References across MIB Versions......   11
   3.2.6.3 Identification of Object Instances ...............   11
   3.2.6.3.1 ifTable Object Type Names ......................   12
   3.2.6.3.2 atTable Object Type Names ......................   12
   3.2.6.3.3 ipAddrTable Object Type Names ..................   13
   3.2.6.3.4 ipRoutingTable Object Type Names ...............   13
   3.2.6.3.5 tcpConnTable Object Type Names .................   13
   3.2.6.3.6 egpNeighTable Object Type Names ................   14
   4. Protocol Specification ................................   15
   4.1 Elements of Procedure ................................   16
   4.1.1 Common Constructs ..................................   18
   4.1.2 The GetRequest-PDU .................................   19
   4.1.3 The GetNextRequest-PDU .............................   20
   4.1.3.1 Example of Table Traversal .......................   22
   4.1.4 The GetResponse-PDU ................................   23
   4.1.5 The SetRequest-PDU .................................   24
   4.1.6 The Trap-PDU .......................................   26
   4.1.6.1 The coldStart Trap ...............................   27
   4.1.6.2 The warmStart Trap ...............................   27
   4.1.6.3 The linkDown Trap ................................   27
   4.1.6.4 The linkUp Trap ..................................   27
   4.1.6.5 The authenticationFailure Trap ...................   27
   4.1.6.6 The egpNeighborLoss Trap .........................   27
   4.1.6.7 The enterpriseSpecific Trap ......................   28
   5. Definitions ...........................................   29
   6. Acknowledgements ......................................   32
   7. References ............................................   33

1. Status of this Memo ✨

okay so this RFC is basically a re-release of RFC 1067, just with a glow-up to the "Status of this Memo" section πŸ’…. It defines a simple protocol that lets management info for a network element be looked at or changed by users who are logically remote 🧚. Together with its companion memos (the ones that describe how management info is structured, plus the initial management information base), it gives you a simple, workable architecture and system for managing TCP/IP-based internets and, like, the Internet itself 🌐.

The Internet Activities Board (IAB) has designated two different network management protocols with the same status of "Draft Standard" and "Recommended" 🫢. The two are the Common Management Information Services and Protocol over TCP/IP (CMOT) [9], and the Simple Network Management Protocol (SNMP), which is this memo.

The IAB wants implementers and experimenters to pay attention to both protocols, and it's asking system builders and users for reports of their experience with them πŸ”₯.

By this action, the IAB recommends that all IP and TCP implementations be network manageable (e.g., implement the Internet MIB [3]). It also expects the network manageable implementations to adopt and implement at least one of these two Internet Draft Standards πŸ’œ.

Distribution of this memo is unlimited 🌸.

2. Introduction πŸ¦‹

so back in RFC 1052, IAB Recommendations for the Development of Internet Network Management Standards [1], the Internet Activities Board told the Internet Engineering Task Force (IETF) to make two new working groups for network management 🧚. One group handles the specifics of what goes in the Management Information Base (MIB). The other one tweaks the Simple Network Management Protocol (SNMP) to meet the short-term needs of the network vendor and operations communities, and to line up with what the MIB working group produces πŸ’….

The MIB working group has already delivered two memos πŸ“š. One defines a Structure for Management Information (SMI) [2] for use by the managed objects in the MIB. The other [3] defines the list of managed objects.

This memo is what the SNMP Extensions working group produced πŸ’–. It bundles in changes to the initial SNMP definition [4] so it lines up with the MIB group's output. The IAB said the changes should be minimal, and that the working groups should be "extremely sensitive to the need to keep the SNMP simple." 🫢

Real talk, though: this protocol is not backwardly-compatible with its predecessor, the Simple Gateway Monitoring Protocol (SGMP) [5] πŸ’€. A lot of care and debate went into the changes, but the syntax is different now while the original philosophy, design decisions, and architecture all stayed intact πŸ’œ. To avoid confusion, new UDP ports got allocated for the protocol described in this memo πŸ”Œ.

3. The SNMP Architecture 🏰

the SNMP architectural model is basically a crew of network management stations and network elements 🧚. Stations run management applications that monitor and control the elements. Elements are things like hosts, gateways, terminal servers, and the like, and each one has a management agent that carries out the management functions the stations ask for. SNMP is what carries management information between the stations and those agents πŸ“‘.

3.1. Goals of the Architecture 🎯

SNMP really wants to keep the number and complexity of management functions inside the management agent itself as small as possible. This goal is super attractive for at least four reasons:

  1. The development cost for management agent software needed to support the protocol goes down.
  2. The amount of management function supported remotely goes up, which means the best possible use of internet resources for the management task.
  3. The amount of management function supported remotely goes up, so the form and sophistication of management tools face the fewest possible restrictions.
  4. Simplified sets of management functions are easy for developers of network management tools to understand and use.

A second goal is that the functional paradigm for monitoring and control can stretch to cover extra, maybe unexpected parts of network operation and management 🌈.

A third goal is that the architecture stays, as much as possible, independent of the architecture and mechanisms of particular hosts or particular gateways 🫧.

3.2. Elements of the Architecture 🧩

the SNMP architecture solves the network management problem by looking at six things πŸ’…:

  1. the scope of the management information the protocol communicates,
  2. the representation of that management information,
  3. operations on management information the protocol supports,
  4. the form and meaning of exchanges among management entities,
  5. the definition of administrative relationships among management entities, and
  6. the form and meaning of references to management information.

3.2.1. Scope of Management Information πŸ”

the scope of the management information SNMP communicates is exactly the instances of all non-aggregate object types. Those can be defined in the Internet-standard MIB, or defined elsewhere following the conventions in the Internet-standard SMI [2] πŸ’–.

Aggregate object types in the MIB are neither required for conformance with the SMI nor realized by SNMP πŸ™….

3.2.2. Representation of Management Information πŸ“

management info that SNMP communicates is represented using the subset of the ASN.1 language [6] that's specified for defining non-aggregate types in the SMI πŸ’œ.

SGMP started the tradition of using a well-defined subset of ASN.1 [6]. SNMP continues and extends that tradition by using a moderately more complex subset of ASN.1 to describe managed objects and the protocol data units used to manage those objects ✨. The team also wanted to make an eventual move to OSI-based network management protocols easier, so they defined an Internet-standard Structure of Management Information (SMI) [2] and Management Information Base (MIB) [3] in ASN.1. Using ASN.1 was partly encouraged by how well it worked in earlier efforts, especially SGMP. The SMI's restrictions on ASN.1 help keep things simple, which is exactly what SGMP's experience showed was valuable 🫢.

Also for simplicity, SNMP uses only a subset of the basic encoding rules of ASN.1 [7]. Specifically, every encoding uses the definite-length form. Whenever permissible, non-constructor encodings are used instead of constructor encodings 🌸. This restriction covers all aspects of ASN.1 encoding, for both the top-level protocol data units and the data objects they contain πŸŽ€.

3.2.3. Operations Supported on Management Information

Okay so SNMP treats basically every management agent job as either peeking at a variable or changing one πŸ’… A protocol entity on a logically remote host (possibly the network element itself πŸ€”) talks to the management agent living on the network element to either get or set variables. This has at least two positive consequences:

  1. It limits the number of essential management functions the management agent has to handle to two: one operation to assign a value to a specified configuration or other parameter, and another to retrieve such a value. 🎯
  2. It also keeps imperative management commands out of the protocol definition πŸ™…β€β™€οΈ Those commands keep multiplying in practice, and their semantics are generally arbitrarily complex, which is a whole mess nobody wants.

The strategy SNMP is built on is that monitoring network state at any significant level of detail happens mainly by polling for the right info from the monitoring center(s). A limited number of unsolicited messages (traps) guide the timing and focus of that polling πŸ” Keeping unsolicited messages few fits the goal of simplicity and minimizing the amount of traffic generated by the network management function. Very minimalist, very iconic πŸ¦‹

Excluding imperative commands from the explicitly supported management functions is unlikely to block any desirable management agent operation ✨ Most commands are already requests to set a parameter's value or retrieve it, and the few imperative commands that do exist can be handled just fine in an asynchronous mode with this model. The trick is that an imperative command can be realized as setting a parameter value that then triggers the desired action. For example, instead of building a "reboot command," this action could be invoked by simply setting a parameter that indicates the number of seconds until system reboot. Genius, honestly πŸ§ πŸ’–

3.2.4. Form and Meaning of Protocol Exchanges

The communication of management information among management entities happens in SNMP through the exchange of protocol messages πŸ“¨ The form and meaning of those messages are defined below in Section 4.

Keeping the management agent simple is the vibe here, so the exchange of SNMP messages requires only an unreliable datagram service 🌸 Every message is entirely and independently represented by a single transport datagram. This document specifies the exchange of messages via the UDP protocol [8], but the SNMP mechanisms are generally suitable for use with a wide variety of transport services. Very flexible, very slay πŸ’…

3.2.5. Definition of Administrative Relationships

SNMP architecture admits a variety of administrative relationships among the entities that take part in the protocol πŸ‘‘ The entities residing at management stations and network elements that talk to each other using SNMP are called SNMP application entities. The peer processes that implement SNMP, and therefore support the SNMP application entities, are called protocol entities.

A pairing of an SNMP agent with some arbitrary set of SNMP application entities is called an SNMP community 🫢 Each SNMP community is named by a string of octets, called the community name for said community.

An SNMP message that was originated by an SNMP application entity which actually belongs to the SNMP community named by the community component of said message is called an authentic SNMP message πŸ” The set of rules by which an SNMP message gets identified as an authentic SNMP message for a particular SNMP community is called an authentication scheme. An implementation of a function that identifies authentic SNMP messages according to one or more authentication schemes is called an authentication service.

Clearly, effective management of administrative relationships among SNMP application entities requires authentication services that (by the use of encryption or other techniques) can identify authentic SNMP messages with a high degree of certainty πŸ”’ Some SNMP implementations might want to support only a trivial authentication service that identifies all SNMP messages as authentic. Lowkey a lot, but it's valid πŸ’€

For any network element, a subset of the objects in the MIB that pertain to that element is called an SNMP MIB view πŸ¦„ Note that the names of the object types represented in an SNMP MIB view don't need to belong to a single sub-tree of the object type name space.

An element of the set { READ-ONLY, READ-WRITE } is called an SNMP access mode πŸŽ€

A pairing of an SNMP access mode with an SNMP MIB view is called an SNMP community profile. A SNMP community profile represents specified access privileges to variables in a specified MIB view. For every variable in the MIB view in a given SNMP community profile, access to that variable is represented by the profile according to the following conventions:

  1. If said variable is defined in the MIB with Access: of none, it is unavailable as an operand for any operator. 🚫
  2. If said variable is defined in the MIB with Access: of read-write or write-only and the access mode of the given profile is READ-WRITE, that variable is available as an operand for the get, set, and trap operations. ✍️
  3. Otherwise, the variable is available as an operand for the get and trap operations. πŸ‘€
  4. In those cases where a write-only variable is an operand used for the get or trap operations, the value given for the variable is implementation-specific. πŸ€·β€β™€οΈ

A pairing of an SNMP community with an SNMP community profile is called an SNMP access policy πŸ“œ An access policy represents a specified community profile that the SNMP agent of a specified SNMP community grants to other members of that community. All administrative relationships among SNMP application entities are architecturally defined in terms of SNMP access policies. Main character energy for policies, fr fr 🌈

For every SNMP access policy, if the network element on which the SNMP agent for the specified SNMP community resides is not the one the MIB view for the specified profile pertains to, then that policy is called an SNMP proxy access policy πŸͺž The SNMP agent associated with a proxy access policy is called an SNMP proxy agent. Careless definition of proxy access policies can result in management loops, but prudent definition of proxy policies is useful in at least two ways:

  1. It permits the monitoring and control of network elements which are otherwise not addressable using the management protocol and the transport protocol. In other words, a proxy agent may provide a protocol conversion function, letting a management station apply a consistent management framework to all network elements, including devices such as modems, multiplexors, and other devices that support different management frameworks. πŸ”„βœ¨
  2. It potentially shields network elements from elaborate access control policies. For example, a proxy agent may implement sophisticated access control, whereby diverse subsets of variables within the MIB are made accessible to different management stations without increasing the complexity of the network element. Very protective, very bestie πŸ›‘οΈπŸ«Ά

By way of example, Figure 1 shows the relationship between management stations, proxy agents, and management agents πŸ—ΊοΈ In this example, the proxy agent is envisioned to be a normal Internet Network Operations Center (INOC) of some administrative domain that has a standard managerial relationship with a set of management agents.

   +------------------+       +----------------+      +----------------+
   |  Region #1 INOC  |       |Region #2 INOC  |      |PC in Region #3 |
   |                  |       |                |      |                |
   |Domain=Region #1  |       |Domain=Region #2|      |Domain=Region #3|
   |CPU=super-mini-1  |       |CPU=super-mini-1|      |CPU=Clone-1     |
   |PCommunity=pub    |       |PCommunity=pub  |      |PCommunity=slate|
   |                  |       |                |      |                |
   +------------------+       +----------------+      +----------------+
          /|\                      /|\                     /|\
           |                        |                       |
           |                        |                       |
           |                       \|/                      |
           |               +-----------------+              |
           +-------------->| Region #3 INOC  |<-------------+
                           |                 |
                           |Domain=Region #3 |
                           |CPU=super-mini-2 |
                           |PCommunity=pub,  |
                           |         slate   |
                           |DCommunity=secret|
           +-------------->|                 |<-------------+
           |               +-----------------+              |
           |                       /|\                      |
           |                        |                       |
           |                        |                       |
          \|/                      \|/                     \|/
   +-----------------+     +-----------------+       +-----------------+
   |Domain=Region#3  |     |Domain=Region#3  |       |Domain=Region#3  |
   |CPU=router-1     |     |CPU=mainframe-1  |       |CPU=modem-1      |
   |DCommunity=secret|     |DCommunity=secret|       |DCommunity=secret|
   +-----------------+     +-----------------+       +-----------------+


   Domain:  the administrative domain of the element
   PCommunity:  the name of a community utilizing a proxy agent
   DCommunity:  the name of a direct community


                                 Figure 1
                 Example Network Management Configuration

3.2.6. Form and Meaning of References to Managed Objects

The SMI requires that the definition of a conformant management protocol address:

  1. the resolution of ambiguous MIB references,
  2. the resolution of MIB references in the presence of multiple MIB versions, and
  3. the identification of particular instances of object types defined in the MIB. πŸ”Ž

3.2.6.1. Resolution of Ambiguous MIB References

Because the scope of any SNMP operation is conceptually confined to objects relevant to a single network element, and because all SNMP references to MIB objects are (implicitly or explicitly) made by unique variable names, there is no possibility that any SNMP reference to any object type defined in the MIB could resolve to multiple instances of that type. No confusion, no drama, periodt πŸ’…πŸŒΈ

3.2.6.2. Resolution of References across MIB Versions

The object instance referred to by any SNMP operation is exactly the one specified as part of the operation request or, in the case of a get-next operation, its immediate successor in the MIB as a whole 🧚 In particular, a reference to an object as part of some version of the Internet-standard MIB does not resolve to any object that is not part of said version of the Internet-standard MIB. The one exception is when the requested operation is get-next and the specified object name is lexicographically last among the names of all objects presented as part of said version of the Internet-Standard MIB. That's the only plot twist, and it's a big one 😭🫢

3.2.6.3. Identification of Object Instances ✨

Okay bestie, so every object type in the MIB gets its name spelled out explicitly πŸ“–, either in the Internet-standard MIB or in other docs that follow the SMI naming conventions πŸ’…. The SMI is strict that any conformant management protocol has to define mechanisms for picking out individual instances of those object types for a particular network element. Lowkey essential.

Each instance of any object type in the MIB gets identified in SNMP operations by a unique name called its "variable name." πŸ¦‹ Generally, the name of an SNMP variable is an OBJECT IDENTIFIER that looks like x.y, where x is the name of a non-aggregate object type defined in the MIB, and y is an OBJECT IDENTIFIER fragment that, in a way specific to that object type, pinpoints the instance you want.

This naming strategy gives maximum GetNextRequest-PDU energy (see Section 4) πŸ”₯, because related variables get names that sit right next to each other in the lexicographical ordering of every variable name known in the MIB.

The type-specific naming of instances is defined below for a bunch of classes of object types. Instances of an object type that none of the following naming conventions apply to get named by OBJECT IDENTIFIERs of the form x.0, where x is the name of that object type in the MIB definition. 🌈

Let's do an example with sysDescr πŸ“. The object class for sysDescr is:

             iso org dod internet mgmt mib system sysDescr
              1   3   6     1      2    1    1       1

So the object type (x) is 1.3.6.1.2.1.1.1, and you slap an instance sub-identifier of 0 on the end. That means 1.3.6.1.2.1.1.1.0 identifies the one and only instance of sysDescr. Iconic πŸ‘‘.

3.2.6.3.1. ifTable Object Type Names 🌸

The name of a subnet interface, s, is the OBJECT IDENTIFIER value of the form i, where i is the value of that instance of the ifIndex object type associated with s.

For each object type, t, whose defined name, n, has a prefix of ifEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.s, where s is the name of the subnet interface that i represents information about.

Example time 🎯: say you want the instance of ifType tied to interface 2. Then ifType.2 identifies the instance you want.

3.2.6.3.2. atTable Object Type Names 🧚

The name of an AT-cached network address, x, is an OBJECT IDENTIFIER of the form 1.a.b.c.d, where a.b.c.d is the value (in the familiar "dot" notation) of the atNetAddress object type associated with x.

The name of an address translation equivalence, e, is an OBJECT IDENTIFIER value of the form s.w, such that s is the value of that instance of the atIndex object type associated with e, and such that w is the name of the AT-cached network address associated with e.

For each object type, t, whose defined name, n, has a prefix of atEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.y, where y is the name of the address translation equivalence that i represents information about.

For example, say you wanna find the physical address of an entry in the address translation table (ARP cache) associated with the IP address 89.1.1.42 and interface 3. That's atPhysAddress.3.1.89.1.1.42 πŸ™ˆ.

3.2.6.3.3. ipAddrTable Object Type Names πŸ’œ

The name of an IP-addressable network element, x, is the OBJECT IDENTIFIER of the form a.b.c.d, such that a.b.c.d is the value (in the familiar "dot" notation) of that instance of the ipAdEntAddr object type associated with x.

For each object type, t, whose defined name, n, has a prefix of ipAddrEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.y, where y is the name of the IP-addressable network element that i represents information about.

For example, say you wanna find the network mask of an entry in the IP interface table associated with the IP address 89.1.1.42. That's ipAdEntNetMask.89.1.1.42 πŸ’….

3.2.6.3.4. ipRoutingTable Object Type Names πŸ¦‹

The name of an IP route, x, is the OBJECT IDENTIFIER of the form a.b.c.d, such that a.b.c.d is the value (in the familiar "dot" notation) of that instance of the ipRouteDest object type associated with x.

For each object type, t, whose defined name, n, has a prefix of ipRoutingEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.y, where y is the name of the IP route that i represents information about.

For example, say you wanna find the next hop of an entry in the IP routing table associated with the destination 89.1.1.42. That's ipRouteNextHop.89.1.1.42 πŸ”₯.

3.2.6.3.5. tcpConnTable Object Type Names 🌈

The name of a TCP connection, x, is the OBJECT IDENTIFIER of the form a.b.c.d.e.f.g.h.i.j, and it's built like this:

  • a.b.c.d is the dot-notation value of that instance of the tcpConnLocalAddress object type associated with x.
  • f.g.h.i is the dot-notation value of that instance of the tcpConnRemoteAddress object type associated with x.
  • e is the value of that instance of the tcpConnLocalPort object type associated with x.
  • j is the value of that instance of the tcpConnRemotePort object type associated with x.

For each object type, t, whose defined name, n, has a prefix of tcpConnEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.y, where y is the name of the TCP connection that i represents information about.

For example, say you wanna find the state of a TCP connection between the local address 89.1.1.42 on TCP port 21 and the remote address 10.0.0.51 on TCP port 2059. That's tcpConnState.89.1.1.42.21.10.0.0.51.2059 πŸŽ€.

3.2.6.3.6. egpNeighTable Object Type Names πŸ“

The name of an EGP neighbor, x, is the OBJECT IDENTIFIER of the form a.b.c.d, such that a.b.c.d is the value (in the familiar "dot" notation) of that instance of the egpNeighAddr object type associated with x.

For each object type, t, whose defined name, n, has a prefix of egpNeighEntry, an instance, i, of t is named by an OBJECT IDENTIFIER of the form n.y, where y is the name of the EGP neighbor that i represents information about.

For example, say you wanna find the neighbor state for the IP address 89.1.1.42. That's egpNeighState.89.1.1.42 πŸ‘‘.


4. Protocol Specification πŸŽ€

The network management protocol is an application protocol by which the variables of an agent's MIB may be inspected or altered. πŸ’–

Protocol entities talk to each other by swapping messages, and each message is entirely and independently represented within a single UDP datagram, using the basic encoding rules of ASN.1 (as discussed in Section 3.2.2) 🧚. A message consists of a version identifier, an SNMP community name, and a protocol data unit (PDU).

A protocol entity receives messages at UDP port 161 on the host it's associated with, for all messages except those which report traps (i.e., all messages except those which contain the Trap-PDU). Messages which report traps should be received on UDP port 162 for further processing. ✨ An implementation of this protocol need not accept messages longer than 484 octets. However, it is recommended that implementations support larger datagrams whenever feasible. πŸ¦‹

It is mandatory that all implementations of the SNMP support the five PDUs: GetRequest-PDU, GetNextRequest-PDU, GetResponse-PDU, SetRequest-PDU, and Trap-PDU. πŸ”₯

Here's the skeleton of the ASN.1 module, the whole blueprint πŸ’…:

    RFC1098-SNMP DEFINITIONS ::= BEGIN

     IMPORTS
          ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks
                  FROM RFC1065-SMI;


     -- top-level message

             Message ::=
                     SEQUENCE {
                          version        -- version-1 for this RFC
                             INTEGER {
                                 version-1(0)
                             },

                         community      -- community name
                             OCTET STRING,

                         data           -- e.g., PDUs if trivial
                             ANY        -- authentication is being used
                     }

     -- protocol data units

             PDUs ::=
                     CHOICE {
                         get-request
                             GetRequest-PDU,

                         get-next-request
                             GetNextRequest-PDU,

                         get-response
                             GetResponse-PDU,

                         set-request
                             SetRequest-PDU,

                         trap
                             Trap-PDU
                          }

     -- the individual PDUs and commonly used
     -- data types will be defined later

     END

4.1. Elements of Procedure

okay so this part is all about what a protocol entity actually does when it's SNMP-ing πŸ’… It's not bossing around how your code is built inside, so do your thing bestie ✨

Heads up, we're gonna use the term transport address a lot. For UDP, a transport address is an IP address plus a UDP port πŸ¦‹ Other transport services can support SNMP too, and in those cases the definition of a transport address SHOULD be made accordingly.

The top-level actions when an entity generates a message go like this:

  1. First it builds the right PDU, like the GetRequest-PDU, as an ASN.1 object.
  2. Then it hands that ASN.1 object, along with the community name, the source transport address, and the destination transport address, to the service running the auth scheme you picked. That service gives back another ASN.1 object.
  3. The entity builds an ASN.1 Message object using the community name and that resulting ASN.1 object.
  4. That new ASN.1 object gets serialized with the basic encoding rules of ASN.1, then sent to the peer entity over a transport service.

Now the receiving side, which is giving detective energy πŸ•΅οΈβ€β™€οΈ

  1. It does a rudimentary parse of the incoming datagram to build an ASN.1 object for an ASN.1 Message object. If the parse fails, it discards the datagram and that's the end of it πŸ™ˆ
  2. It checks the SNMP version number. If there's a mismatch, it discards the datagram and stops there.
  3. It passes the community name and user data from the ASN.1 Message object, plus the datagram's source and destination transport addresses, to the auth service. That service either returns another ASN.1 object or signals an authentication failure. If it's a failure, the entity notes it, (possibly) generates a trap, discards the datagram, and performs no further actions πŸ’€
  4. It does a rudimentary parse on the ASN.1 object the auth service returned, to build an ASN.1 PDUs object. If that parse fails, it discards the datagram and stops. Otherwise, using the named SNMP community, it selects the appropriate profile and processes the PDU accordingly. If that processing returns a message, then the source transport address the response is sent from SHALL be identical to the destination transport address the original request was sent to πŸ‘‘

4.1.1. Common Constructs

before we meet the six PDU types, we need to talk about some ASN.1 constructs that show up literally everywhere 🧚

-- request/response information

RequestID ::=
        INTEGER

ErrorStatus ::=
        INTEGER {
            noError(0),
            tooBig(1),
            noSuchName(2),
            badValue(3),
            readOnly(4)
            genErr(5)
        }

ErrorIndex ::=
        INTEGER


-- variable bindings

VarBind ::=
        SEQUENCE {
            name
                ObjectName,

            value
                ObjectSyntax
        }

VarBindList ::=
        SEQUENCE OF
            VarBind

RequestIDs are how you tell apart outstanding requests πŸŽ€ Because of that, an SNMP application entity can match incoming responses to the requests they answer. When you're using an unreliable datagram service, the RequestID also helps you spot messages the network duplicated, which is such a clever trick ✨

A non-zero ErrorStatus means an exception happened while processing a request. In those cases, ErrorIndex can tell you which variable in the list caused the exception 😭

The word variable means an instance of a managed object πŸ“ A variable binding, or VarBind, is just the pairing of a variable's name with its value. A VarBindList is a simple list of variable names and their values. Some PDUs only care about the name and not the value (the GetRequest-PDU is one of these). For those, the protocol entity ignores the value portion of the binding. Even so, that value portion MUST still have valid ASN.1 syntax and encoding, so it's not an excuse to be messy πŸ’… It is RECOMMENDED that the ASN.1 value NULL be used for the value portion of such bindings 🌸


4.1.2. The GetRequest-PDU

this is the form of the GetRequest-PDU, and yes it's giving very structured πŸ’œ

GetRequest-PDU ::=
    [0]
        IMPLICIT SEQUENCE {
            request-id
                RequestID,

            error-status        -- always 0
                ErrorStatus,

            error-index         -- always 0
                ErrorIndex,

            variable-bindings
                VarBindList
        }

A protocol entity only generates a GetRequest-PDU when its SNMP application entity asks it to 🫢

When the receiving protocol entity gets a GetRequest-PDU, it responds according to whichever rule in this list applies:

  1. If, for any object named in the variable-bindings field, the object's name doesn't exactly match the name of some object available for get operations in the relevant MIB view, then the receiving entity sends the originator a GetResponse-PDU of identical form. The only changes are that error-status is noSuchName, and error-index is the index of that object name component in the received message πŸ™ˆ
  2. If, for any object named in the variable-bindings field, the object is an aggregate type (as defined in the SMI), then the receiving entity sends the originator a GetResponse-PDU of identical form. Again, error-status is noSuchName, and error-index is the index of that object name component in the received message.
  3. If the size of the GetResponse-PDU generated as described below would go over a local limitation, then the receiving entity sends the originator a GetResponse-PDU of identical form, except error-status is tooBig and error-index is zero πŸ“¦
  4. If, for any object named in the variable-bindings field, the value of the object can't be retrieved for reasons not covered by any of the rules above, then the receiving entity sends the originator a GetResponse-PDU of identical form, except error-status is genErr and error-index is the index of that object name component in the received message πŸ’€

If none of the rules above apply, then the receiving protocol entity sends the originator a GetResponse-PDU where, for each object named in the variable-bindings field of the received message, the matching component of the GetResponse-PDU represents that variable's name and value. The error-status field of the GetResponse-PDU is noError and the error-index field is zero. The request-id field of the GetResponse-PDU is the same as the one in the received message πŸŽ‰βœ¨

4.1.3. The GetNextRequest-PDU ➑️✨

okay bestie, the GetNextRequest-PDU is basically the GetRequest-PDU's twin πŸ‘―β€β™€οΈ. The only difference is the PDU type tag. In ASN.1 it looks like this πŸ’–:

                  GetNextRequest-PDU ::=
                      [1]
                          IMPLICIT SEQUENCE {
                              request-id
                                  RequestID,

                              error-status        -- always 0
                                  ErrorStatus,

                              error-index         -- always 0
                                  ErrorIndex,

                              variable-bindings
                                  VarBindList
                          }

The GetNextRequest-PDU only gets generated by a protocol entity when its SNMP application entity asks for it 🫢.

When a receiving protocol entity gets a GetNextRequest-PDU, it checks the list below and follows any rule that applies πŸ‘€:

  1. If, for any object name in the variable-bindings field, that name does not lexicographically precede the name of some object available for get operations in the relevant MIB view, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is noSuchName, and the value of the error-index field is the index of said object name component in the received message. πŸ’€
  2. If the size of the GetResponse-PDU generated as described below would exceed a local limitation, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is tooBig, and the value of the error-index field is zero. πŸ™ˆ
  3. If, for any object named in the variable-bindings field, the value of the lexicographical successor to the named object cannot be retrieved for reasons not covered by any of the foregoing rules, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is genErr and the value of the error-index field is the index of said object name component in the received message. 😭

If none of those rules apply, the receiving protocol entity sends back a GetResponse-PDU πŸŽ€. For each name in the variable-bindings field of the received message, the matching component of the GetResponse-PDU holds the name and value of the object that comes right after the given name in the lexicographical ordering of all objects available for get operations in the relevant MIB view. The error-status field of that GetResponse-PDU is noError, the errorindex field (errorindex) is zero, and the request-id field is copied from the received message ✨.

4.1.3.1. Example of Table Traversal πŸ¦‹

Okay, this is my favourite part. One big reason the GetNextRequest-PDU is so iconic is that you can walk through conceptual tables in the MIB πŸ—ΊοΈ. The semantics of this message type, plus the protocol-specific way of identifying individual object type instances in the MIB, let you reach related objects as if they were laid out in a table πŸ“Š.

Here's a sketch of an SNMP exchange where an SNMP application entity pulls the destination address and next hop gateway for each entry in a network element's routing table 🌸. Say the routing table has three entries:

     Destination                     NextHop         Metric

     10.0.0.99                       89.1.1.42       5
     9.1.2.3                         99.0.0.3        3
     10.0.0.51                       89.1.1.42       5

First, the management station sends the SNMP agent a GetNextRequest-PDU that carries the OBJECT IDENTIFIER values as the requested variable names πŸ’…:

GetNextRequest ( ipRouteDest, ipRouteNextHop, ipRouteMetric1 )

The SNMP agent answers with a GetResponse-PDU 🧚:

GetResponse (( ipRouteDest.9.1.2.3 =  "9.1.2.3" ),
        ( ipRouteNextHop.9.1.2.3 = "99.0.0.3" ),
        ( ipRouteMetric1.9.1.2.3 = 3 ))

The management station keeps going with:

GetNextRequest ( ipRouteDest.9.1.2.3,
        ipRouteNextHop.9.1.2.3,
        ipRouteMetric1.9.1.2.3 )

The SNMP agent responds:

GetResponse (( ipRouteDest.10.0.0.51 = "10.0.0.51" ),
        ( ipRouteNextHop.10.0.0.51 = "89.1.1.42" ),
        ( ipRouteMetric1.10.0.0.51 = 5 ))

The management station continues with:

GetNextRequest ( ipRouteDest.10.0.0.51,
        ipRouteNextHop.10.0.0.51,
        ipRouteMetric1.10.0.0.51 )

The SNMP agent responds:

GetResponse (( ipRouteDest.10.0.0.99 = "10.0.0.99" ),
        ( ipRouteNextHop.10.0.0.99 = "89.1.1.42" ),
        ( ipRouteMetric1.10.0.0.99 = 5 ))

The management station continues with:

GetNextRequest ( ipRouteDest.10.0.0.99,
        ipRouteNextHop.10.0.0.99,
        ipRouteMetric1.10.0.0.99 )

There are no more entries in the table, so the SNMP agent returns whatever objects come next in the lexicographical ordering of the known object names 🏁. That response is how the management station knows it has hit the end of the routing table πŸŽ‰.

4.1.4. The GetResponse-PDU πŸ’œ

The GetResponse-PDU has the same form as the GetRequest-PDU, just with a different PDU type tag. In ASN.1 it looks like this 🌈:

                  GetResponse-PDU ::=
                      [2]
                          IMPLICIT SEQUENCE {
                              request-id
                                  RequestID,

                              error-status
                                  ErrorStatus,

                              error-index
                                  ErrorIndex,

                              variable-bindings
                                  VarBindList
                          }

A protocol entity only generates a GetResponse-PDU after it receives a GetRequest-PDU, GetNextRequest-PDU, or SetRequest-PDU, as described elsewhere in this document πŸ“¬.

When a receiving protocol entity gets a GetResponse-PDU, it hands the contents up to its SNMP application entity πŸŽ€.

4.1.5. The SetRequest-PDU πŸ”₯

The SetRequest-PDU is the same as the GetRequest-PDU except for the PDU type tag. In ASN.1 🫢:

                  SetRequest-PDU ::=
                      [3]
                          IMPLICIT SEQUENCE {
                              request-id
                                  RequestID,

                              error-status        -- always 0
                                  ErrorStatus,

                              error-index         -- always 0
                                  ErrorIndex,

                              variable-bindings
                                  VarBindList
                          }

A protocol entity only generates a SetRequest-PDU when its SNMP application entity asks it to πŸ’….

When a receiving entity gets a SetRequest-PDU, it checks the list below and follows any rule that applies πŸ‘‘:

  1. If, for any object named in the variable-bindings field, the object is not available for set operations in the relevant MIB view, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is noSuchName, and the value of the error-index field is the index of said object name component in the received message. πŸ™ˆ
  2. If, for any object named in the variable-bindings field, the contents of the value field does not, according to the ASN.1 language, manifest a type, length, and value that is consistent with that required for the variable, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is badValue, and the value of the error-index field is the index of said object name in the received message. πŸ’€
  3. If the size of the Get Response type message generated as described below would exceed a local limitation, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is tooBig, and the value of the error-index field is zero. 😭
  4. If, for any object named in the variable-bindings field, the value of the named object cannot be altered for reasons not covered by any of the foregoing rules, then the receiving entity sends to the originator of the received message the GetResponse-PDU of identical form, except that the value of the error-status field is genErr and the value of the error-index field is the index of said object name component in the received message. πŸ₯€

If none of those rules apply, then for each object named in the variable-bindings field of the received message, the matching value gets assigned to the variable πŸ“. Each variable assignment specified by the SetRequest-PDU should be effected as if simultaneously set with respect to all other assignments specified in the same message ✨.

Finally, the receiving entity sends back to the originator of the received message a GetResponse-PDU of identical form, except that the error-status field of the generated message is noError and the error-index field is zero 🌸.

4.1.6. The Trap-PDU ✨

Okay so the Trap-PDU is the one that basically goes "hey, something just happened!" πŸ”” Here's its whole shape:

     Trap-PDU ::=
         [4]

              IMPLICIT SEQUENCE {
                 enterprise          -- type of object generating
                                     -- trap, see sysObjectID in [2]
                     OBJECT IDENTIFIER,

                 agent-addr          -- address of object generating
                     NetworkAddress, -- trap

                 generic-trap        -- generic trap type
                     INTEGER {
                         coldStart(0),
                         warmStart(1),
                         linkDown(2),
                         linkUp(3),
                         authenticationFailure(4),
                         egpNeighborLoss(5),
                         enterpriseSpecific(6)
                     },

                 specific-trap     -- specific code, present even
                     INTEGER,      -- if generic-trap is not
                                   -- enterpriseSpecific

                 time-stamp        -- time elapsed between the last
                   TimeTicks,      -- (re)initialization of the network
                                   -- entity and the generation of the
                                      trap

                 variable-bindings   -- "interesting" information
                      VarBindList
             }

A Trap-PDU only gets generated by a protocol entity when the SNMP application entity asks for it πŸ’… How the SNMP application entity picks the destination addresses of its SNMP application entity buddies is totally implementation-specific πŸ€·β€β™€οΈ

Once it lands, the receiving protocol entity hands the contents straight up to its SNMP application entity πŸ“¬

What the variable-bindings part of the Trap-PDU actually means is also implementation-specific 🫢

Here's how the values of the generic-trap field get read πŸ‘€

4.1.6.1. The coldStart Trap πŸ₯Ά

A coldStart(0) trap basically means the sending protocol entity is restarting itself πŸ”„ The agent's configuration or the protocol entity implementation may be altered along the way.

4.1.6.2. The warmStart Trap 🌸

A warmStart(1) trap also means the sending protocol entity is reinitializing itself, but this time neither the agent configuration nor the protocol entity implementation is altered. Lowkey the chill version 😌

4.1.6.3. The linkDown Trap πŸ’”

A linkDown(2) trap means the sending protocol entity recognizes a failure in one of the communication links represented in the agent's configuration. Oof 😭

A Trap-PDU of type linkDown has the name and value of the ifIndex instance for the affected interface as the first element of its variable-bindings πŸ”Œ

4.1.6.4. The linkUp Trap πŸŽ‰

A linkUp(3) trap means the sending protocol entity recognizes that one of the communication links represented in the agent's configuration has come up. Finally, a glow-up ✨

A Trap-PDU of type linkUp has the name and value of the ifIndex instance for the affected interface as the first element of its variable-bindings πŸ”Œ

4.1.6.5. The authenticationFailure Trap 🚫

An authenticationFailure(4) trap means the sending protocol entity is the addressee of a protocol message that is not properly authenticated. Not me getting a message that didn't pass the vibe check πŸ’€

While implementations of the SNMP must be capable of generating this trap, they must also be capable of suppressing the emission of such traps via an implementation-specific mechanism. So you have to be able to send it, but you also have to be able to mute it πŸ”‡

4.1.6.6. The egpNeighborLoss Trap πŸ“‰

An egpNeighborLoss(5) trap means an EGP neighbor that the sending protocol entity was an EGP peer for has been marked down, and the peer relationship no longer obtains. Ghosted πŸ‘»

A Trap-PDU of type egpNeighborLoss has the name and value of the egpNeighAddr instance for the affected neighbor as the first element of its variable-bindings 🀝

4.1.6.7. The enterpriseSpecific Trap 🧚

An enterpriseSpecific(6) trap means the sending protocol entity recognizes that some enterprise-specific event has occurred ✨ The specific-trap field identifies the particular trap which occurred, so that's where you look to see exactly what happened πŸ”


5. Definitions πŸ“œ

Here's the whole module, straight from the source πŸŽ€

     RFC1098-SNMP DEFINITIONS ::= BEGIN

      IMPORTS
          ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks
              FROM RFC1065-SMI;


          -- top-level message

          Message ::=
                  SEQUENCE {
                      version          -- version-1 for this RFC
                          INTEGER {
                              version-1(0)
                          },

                      community        -- community name
                          OCTET STRING,

                      data             -- e.g., PDUs if trivial
                          ANY          -- authentication is being used
                  }


          -- protocol data units

          PDUs ::=
                  CHOICE {
                              get-request
                                  GetRequest-PDU,

                              get-next-request
                                  GetNextRequest-PDU,

                              get-response
                                  GetResponse-PDU,

                              set-request
                                  SetRequest-PDU,

                              trap
                                  Trap-PDU
                          }

          -- PDUs

          GetRequest-PDU ::=
              [0]
                  IMPLICIT PDU

          GetNextRequest-PDU ::=
              [1]
                  IMPLICIT PDU

          GetResponse-PDU ::=
              [2]
                  IMPLICIT PDU

          SetRequest-PDU ::=
              [3]
                  IMPLICIT PDU

          PDU ::=
                  SEQUENCE {
                     request-id
                          INTEGER,

                      error-status      -- sometimes ignored
                          INTEGER {
                              noError(0),
                              tooBig(1),
                              noSuchName(2),
                              badValue(3),
                              readOnly(4),
                              genErr(5)
                          },

                      error-index       -- sometimes ignored
                         INTEGER,

                      variable-bindings -- values are sometimes ignored
                          VarBindList
                  }

          Trap-PDU ::=
              [4]
                 IMPLICIT SEQUENCE {
                      enterprise        -- type of object generating
                                        -- trap, see sysObjectID in [2]


                          OBJECT IDENTIFIER,

                      agent-addr        -- address of object generating
                          NetworkAddress, -- trap

                      generic-trap      -- generic trap type
                          INTEGER {
                              coldStart(0),
                              warmStart(1),
                              linkDown(2),
                              linkUp(3),
                              authenticationFailure(4),
                              egpNeighborLoss(5),
                              enterpriseSpecific(6)
                          },

                      specific-trap  -- specific code, present even
                          INTEGER,   -- if generic-trap is not
                                     -- enterpriseSpecific

                      time-stamp     -- time elapsed between the last
                          TimeTicks, -- (re)initialization of the
                                        network
                                     -- entity and the generation of the
                                        trap

                       variable-bindings -- "interesting" information
                          VarBindList
                  }


          -- variable bindings

          VarBind ::=
                  SEQUENCE {
                      name
                          ObjectName,

                      value
                          ObjectSyntax
                  }

         VarBindList ::=
                  SEQUENCE OF
                     VarBind

         END

6. Acknowledgements 🫢

This memo was influenced by the IETF SNMP Extensions working group, and these legends were a big part of it:

  • Karl Auerbach, Epilogue Technology
  • K. Ramesh Babu, Excelan
  • Amatzia Ben-Artzi, 3Com/Bridge
  • Lawrence Besaw, Hewlett-Packard
  • Jeffrey D. Case, University of Tennessee at Knoxville
  • Anthony Chung, Sytek
  • James Davidson, The Wollongong Group
  • James R. Davin, MIT Laboratory for Computer Science
  • Mark S. Fedor, NYSERNet
  • Phill Gross, The MITRE Corporation
  • Satish Joshi, ACC
  • Dan Lynch, Advanced Computing Environments
  • Keith McCloghrie, The Wollongong Group
  • Marshall T. Rose, The Wollongong Group (chair)
  • Greg Satz, cisco
  • Martin Lee Schoffstall, Rensselaer Polytechnic Institute
  • Wengyik Yeong, NYSERNet

7. References πŸ“š

  • [1] Cerf, V., "IAB Recommendations for the Development of Internet Network Management Standards", RFC 1052, IAB, April 1988.
  • [2] Rose, M., and K. McCloghrie, "Structure and Identification of Management Information for TCP/IP-based internets", RFC 1065, TWG, August 1988.
  • [3] McCloghrie, K., and M. Rose, "Management Information Base for Network Management of TCP/IP-based internets", RFC 1066, TWG, August 1988.
  • [4] Case, J., M. Fedor, M. Schoffstall, and J. Davin, "A Simple Network Management Protocol", Internet Engineering Task Force working note, Network Information Center, SRI International, Menlo Park, California, March 1988.
  • [5] Davin, J., J. Case, M. Fedor, and M. Schoffstall, "A Simple Gateway Monitoring Protocol", RFC 1028, Proteon, University of Tennessee at Knoxville, Cornell University, and Rensselaer Polytechnic Institute, November 1987.
  • [6] Information processing systems - Open Systems Interconnection, "Specification of Abstract Syntax Notation One (ASN.1)", International Organization for Standardization, International Standard 8824, December 1987.
  • [7] Information processing systems - Open Systems Interconnection, "Specification of Basic Encoding Rules for Abstract Notation One (ASN.1)", International Organization for Standardization, International Standard 8825, December 1987.
  • [8] Postel, J., "User Datagram Protocol", RFC 768, USC/Information Sciences Institute, November 1980.
  • [9] Warrier, U., and L. Besaw, "The Common Management Information Services and Protocol over TCP/IP", RFC 1095, Unisys Corporation and Hewlett-Packard, April 1989.

Authors' Addresses πŸ’Œ

  • Jeffrey D. Case
    • University of Tennessee Computing Center
    • Associate Driector
    • 200 Stokely Management Center
    • Knoxville, TN 37996-0520
    • Phone: (615) 974-6721
    • Email: case@UTKUX1.UTK.EDU
  • Mark Fedor
    • Nysernet, Inc.
    • Rensselaer Technology Park
    • 125 Jordan Road
    • Troy, NY 12180
    • Phone: (518) 283-8860
    • Email: fedor@patton.NYSER.NET
  • Martin Lee Schoffstall
    • NYSERNET Inc.
    • Rensselaer Technology Park
    • 165 Jordan Road
    • Troy, NY 12180
    • Phone: (518) 283-8860
    • Email: schoff@NISC.NYSER.NET
  • Chuck Davin
    • MIT Laboratory for Computer Science, NE43-507
    • 545 Technology Square
    • Cambridge, MA 02139
    • Phone: (617) 253-6020
    • EMail: jrd@ptt.lcs.mit.edu
πŸ“¦ where this page comes from