RFC 1067

Simple Network Management Protocol

๐Ÿ“… published August 1988, from ietf

A Simple Network Management Protocol ๐ŸŽ€

okay bestie, meet RFC 1067 ๐Ÿ’– It's from August 1988 and it's titled A Simple Network Management Protocol ๐ŸŒธ Four authors wrote it:

  • J. Case, University of Tennessee at Knoxville
  • M. Fedor, NYSERNet, Inc.
  • M. Schoffstall, Rensselaer Polytechnic Institute
  • J. Davin, Proteon, Inc.

It came out of the Network Working Group ๐Ÿงš The title block doesn't list anything it obsoletes or updates, and there's no separate category line up top. Section 1 tells us it's a draft standard for the Internet community ๐Ÿฆ‹

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 โœจ

This memo is a simple protocol ๐Ÿ’… that lets management information for a network element be inspected or altered by logically remote users, meaning people who aren't sitting at the box. Together with its companion memos, one describing how management information is structured and one with the initial management information base, it gives you a simple, workable architecture and system for managing TCP/IP-based internets and especially the Internet ๐ŸŒˆ

This memo specifies a draft standard for the Internet community ๐Ÿ“œ TCP/IP implementations in the Internet that are network manageable are expected to adopt and implement this specification ๐Ÿซถ

Distribution of this memo is unlimited. ๐ŸŒ


2. Introduction โ˜•

So here's the tea. As reported 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 create two new working groups for network management ๐Ÿงš One group is in charge of specifying and defining what goes in the Management Information Base (MIB). The other is in charge of changing the Simple Network Management Protocol (SNMP) to cover the short-term needs of the network vendor and operations communities, and to line up with what the MIB group puts out.

The MIB working group made two memos. The first defines a Structure for Management Information (SMI) [2] for the managed objects in the MIB. The second [3] defines the list of managed objects ๐Ÿ“‹

The SNMP Extensions working group's output is this memo โœจ It includes the changes to the initial SNMP definition [4] that were needed to line up with the MIB group's output. The changes should be minimal, because the IAB said the working groups had to be "extremely sensitive to the need to keep the SNMP simple." ๐Ÿ™ˆ A lot of care and debate went into these changes, but the protocol here is not backwardly-compatible with its predecessor, the Simple Gateway Monitoring Protocol (SGMP) [5]. The syntax got altered, but the original philosophy, design decisions, and architecture are still intact ๐Ÿ’œ To avoid confusion, new UDP ports have been allocated for this protocol ๐Ÿฆ‹


3. The SNMP Architecture ๐Ÿ—๏ธ

Okay, so the SNMP architecture is built on a collection of network management stations and network elements. Management stations run management applications that monitor and control network elements. Network elements are things like hosts, gateways, terminal servers, and the like, and they have management agents that carry out the management functions the stations ask for. SNMP is the protocol used to pass management information between the stations and the agents in the network elements ๐Ÿ“ก

3.1. Goals of the Architecture ๐ŸŽฏ

SNMP goes out of its way to keep the number and complexity of management functions that the management agent itself has to do as small as possible ๐Ÿค That's a big deal for at least four reasons:

  1. The development cost for management agent software needed to support the protocol goes down. ๐Ÿ’ธ
  2. The degree of management function that is remotely supported goes up, so you get to make the fullest use of internet resources for the management task. ๐ŸŒ
  3. The degree of management function that is remotely supported goes up, which means the fewest possible restrictions on the form and sophistication of management tools. ๐Ÿ› ๏ธ
  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 be sufficiently extensible to handle additional, possibly unanticipated, aspects of network operation and management ๐Ÿ”ฎ

A third goal is that the architecture be, 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 tackles the network management problem by looking at six things:

  1. the scope of the management information communicated by the protocol,
  2. the representation of the management information communicated by the protocol,
  3. operations on management information supported by the protocol,
  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 that SNMP communicates is exactly what's represented by instances of all non-aggregate object types, either defined in the Internet-standard MIB or defined elsewhere under the conventions set out in the Internet-standard SMI [2].

Support for aggregate object types in the MIB is neither required for conformance with the SMI nor realized by SNMP. ๐Ÿ™…โ€โ™€๏ธ

3.2.2. Representation of Management Information ๐ŸŽ€

Management information communicated by SNMP 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 habit of using a well-defined subset of the ASN.1 language [6]. SNMP keeps that tradition going and extends it by using a moderately more complex subset of ASN.1 to describe managed objects and the protocol data units used to manage them. The desire to make an eventual move to OSI-based network management protocols easier also led to defining, in ASN.1, an Internet-standard Structure of Management Information (SMI) [2] and Management Information Base (MIB) [3]. Using ASN.1 was partly encouraged by how well it worked in earlier efforts, especially SGMP. The ASN.1 restrictions that are part of the SMI add to the simplicity that SGMP's experience backed up ๐Ÿ’œ

Also for simplicity, SNMP uses only a subset of the basic encoding rules of ASN.1 [7]. Namely, all encodings use the definite-length form. Further, whenever it's permissible, non-constructor encodings are used rather than constructor encodings. This restriction applies to all aspects of ASN.1 encoding, both for 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 everything a management agent does as just looking at or changing variables ๐Ÿง ๐Ÿ’…. A protocol entity on some logically remote host (which could even be the network element itself ๐Ÿ‘€) talks to the management agent on the network element to either get (read) or set (alter) variables. This choice has at least two big perks:

  1. It limits the essential management functions the management agent has to realize to just 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 ๐Ÿ™…โ€โ™€๏ธ. The number of those commands is in practice ever-increasing, and their semantics are in general arbitrarily complex, so ngl, no thank you ๐Ÿ’€.

The SNMP strategy is that watching network state at any real level of detail happens mostly by polling, done by the monitoring center(s) ๐Ÿ”. A limited number of unsolicited messages (traps) just guide the timing and focus of that polling ๐ŸŽฏ. Keeping unsolicited messages few fits the goal of simplicity and of minimizing the traffic generated by network management ๐ŸŒธ.

Leaving imperative commands out of the explicitly supported functions is unlikely to rule out any desirable management agent operation ๐Ÿคทโ€โ™€๏ธ. Most commands are either setting a parameter or retrieving one, and the few imperative commands that exist can be handled easily in an asynchronous mode with this model ๐Ÿงš. An imperative command might be realized as setting a parameter value that then triggers the desired action. So instead of a "reboot command," this action might be invoked by simply setting a parameter indicating the number of seconds until system reboot โฐ.

3.2.4. Form and Meaning of Protocol Exchanges

Communicating management information between management entities happens through the exchange of protocol messages ๐Ÿ’Œ. The form and meaning of those messages get defined below in Section 4 ๐Ÿ“–.

Since keeping the management agent's complexity down is the goal ๐Ÿง˜, exchanging SNMP messages only requires 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 SNMP's mechanisms are generally suitable for use with a wide variety of transport services ๐Ÿฆ‹.

3.2.5. Definition of Administrative Relationships

The SNMP architecture allows a whole variety of administrative relationships among the entities in the protocol ๐Ÿ‘‘. The entities 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 that community ๐Ÿท๏ธ.

An SNMP message originated by an SNMP application entity that actually belongs to the SNMP community named by the community component of that message is called an authentic SNMP message โœ…. The set of rules for identifying an SNMP message 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 can identify authentic SNMP messages with a high degree of certainty, whether through encryption or other techniques ๐Ÿ˜ค. Some SNMP implementations may wish to support only a trivial authentication service that identifies all SNMP messages as authentic SNMP messages ๐Ÿ™ƒ.

For any network element, a subset of the objects in the MIB that pertain to that element is called an SNMP MIB view ๐Ÿ‘€. Heads up: the names of the object types 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 ๐Ÿ’œ. An SNMP community profile represents specified access privileges to variables in a specified MIB view. For every variable in the MIB view of a given SNMP community profile, access to that variable is represented by the profile according to these conventions:

  1. if the variable is defined in the MIB with Access: of none, it is unavailable as an operand for any operator ๐Ÿšซ;
  2. if the 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, the 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 afforded by the SNMP agent of a specified SNMP community to other members of that community ๐ŸŽ. All administrative relationships among SNMP application entities are architecturally defined in terms of SNMP access policies ๐Ÿ›๏ธ.

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 that are otherwise not addressable using the management protocol and the transport protocol ๐Ÿ“ก. A proxy agent may provide a protocol conversion function, letting a management station apply a consistent management framework to all network elements, including devices like 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, so diverse subsets of variables within the MIB are accessible to different management stations without increasing the complexity of the network element ๐Ÿงฉ.

By way of example, Figure 1 shows the relationship between management stations, proxy agents, and management agents ๐Ÿ—บ๏ธ. In this example, the proxy agent is a normal Internet Network Operations Center (INOC) of some administrative domain, which 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) 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 ๐Ÿ”โœจ.

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 that version of the Internet-Standard MIB ๐Ÿ™…โ€โ™€๏ธ, except in the case that the requested operation is get-next and the specified object name is lexicographically last among the names of all objects presented as part of that version of the Internet-Standard MIB ๐Ÿ”š.

3.2.6.3. Identification of Object Instances โœจ

okay bestie, every object type in the MIB has an explicit name, either in the Internet-standard MIB or in other docs that follow the SMI naming conventions ๐Ÿ’…. The SMI needs conformant management protocols to come with mechanisms for picking out individual instances of those object types on a particular network element ๐Ÿฆ‹.

Each instance of any object type in the MIB gets a unique name in SNMP operations called its "variable name" ๐ŸŽ€. In general, an SNMP variable name 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 picks out the instance you want, in a way that depends on that specific object type ๐Ÿงš.

This naming strategy is literally built to make GetNextRequest-PDU shine (see Section 4) โœจ. Related variables get names that sit right next to each other in the lexicographical ordering of every variable name in the MIB, so walking through them is smooth ๐ŸŒˆ.

The type-specific naming of object instances is defined below for a bunch of object type classes ๐Ÿ“. Any instance of an object type that none of these naming conventions apply to gets named by an OBJECT IDENTIFIER of the form x.0, where x is that object type's name in the MIB definition ๐ŸŒธ.

For example, say you want to identify an instance of the variable sysDescr ๐Ÿ‘€. Its object class looks like this:

             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 tack on an instance sub-identifier of 0. That means 1.3.6.1.2.1.1.1.0 identifies the one and only instance of sysDescr ๐Ÿ‘‘.

3.2.6.3.1. ifTable Object Type Names

The name of a subnet interface, s, is an OBJECT IDENTIFIER of the form i, where i has 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 gives information about ๐Ÿ’–.

For example, say you want the instance of the variable ifType associated with interface 2. Then ifType.2 is the one you're looking for ๐ŸŽ€.

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. Here s is the value of that instance of the atIndex object type associated with e, and 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 gives information about โœจ.

For example, say you want the physical address of an entry in the address translation table (ARP cache) tied to the IP address 89.1.1.42 on interface 3. Then atPhysAddress.3.1.89.1.1.42 is the instance you want ๐Ÿ’….

3.2.6.3.3. ipAddrTable Object Type Names

The name of an IP-addressable network element, x, is an OBJECT IDENTIFIER of the form a.b.c.d, where 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 gives information about ๐Ÿ’œ.

For example, say you want the network mask of an entry in the IP interface table tied to the IP address 89.1.1.42. Then ipAdEntNetMask.89.1.1.42 is the instance you're after ๐Ÿฆ‹.

3.2.6.3.4. ipRoutingTable Object Type Names

The name of an IP route, x, is an OBJECT IDENTIFIER of the form a.b.c.d, where 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 gives information about ๐ŸŒธ.

For example, say you want the next hop of an entry in the IP routing table tied to the destination 89.1.1.42. Then ipRouteNextHop.89.1.1.42 is the instance you need ๐Ÿงš.

3.2.6.3.5. tcpConnTable Object Type Names

okay this one is a whole vibe ๐Ÿ’– The name of a TCP connection, x, is an OBJECT IDENTIFIER of the form a.b.c.d.e.f.g.h.i.j. Here a.b.c.d is the value (in the familiar "dot" notation) of that instance of the tcpConnLocalAddress object type associated with x. f.g.h.i is the value (in the familiar "dot" notation) 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. And 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 gives information about ๐ŸŽ€.

For example, say you want 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. Then tcpConnState.89.1.1.42.21.10.0.0.51.2059 is the instance you want ๐Ÿ‘‘.

3.2.6.3.6. egpNeighTable Object Type Names

The name of an EGP neighbor, x, is an OBJECT IDENTIFIER of the form a.b.c.d, where 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 gives information about ๐Ÿ’œ.

For example, say you want the neighbor state for the IP address 89.1.1.42. Then egpNeighState.89.1.1.42 identifies the instance you're looking for ๐Ÿฆ‹.

4. Protocol Specification โœจ

okay so this is the part where the protocol actually gets going ๐Ÿ”ฅ. The network management protocol is an application protocol that lets you inspect or change the variables in an agent's MIB ๐Ÿ’….

Entities talk to each other by swapping messages ๐Ÿ’Œ. Each message is entirely and independently packed into a single UDP datagram, using the basic encoding rules of ASN.1 (as discussed in Section 3.2.2) ๐Ÿงš. A message has three parts: a version identifier, an SNMP community name, and a protocol data unit (PDU) ๐ŸŽ€.

here's where people get mixed up ๐Ÿ™ˆ A protocol entity receives messages on UDP port 161 on the host it's associated with, for all messages except the ones that report traps (i.e., all messages except those containing the Trap-PDU) ๐Ÿฆ‹. Messages that report traps should be received on UDP port 162 for further processing ๐ŸŒธ. An implementation of this protocol doesn't need to accept messages longer than 484 octets, but it is recommended that implementations support larger datagrams whenever feasible ๐Ÿ“.

It is mandatory that all implementations of SNMP support the five PDUs: GetRequest-PDU, GetNextRequest-PDU, GetResponse-PDU, SetRequest-PDU, and Trap-PDU ๐Ÿ‘‘. Here's the ASN.1 module that ties it all together ๐Ÿ’–:

    RFC1067-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 bestie, this is the part where we get into what a protocol entity (the bit of software doing the SNMP stuff ๐Ÿ’…) actually does. It's giving step-by-step recipe energy. ngl the RFC is also being super clear that it's not trying to dictate how your implementation is built on the inside ๐Ÿ™ˆ. It only describes the actions.

In the text that follows, the term transport address is used. For UDP, a transport address is an IP address plus a UDP port ๐Ÿฆ‹. Other transport services MAY be used to support SNMP. If that happens, the definition of a transport address SHOULD be made to match that transport.

The top-level actions of a protocol entity that generates a message go like this:

  1. It first builds the right PDU (like a GetRequest-PDU) as an ASN.1 object ๐Ÿงš.
  2. It then hands that ASN.1 object, along with a community name, its source transport address, and the destination transport address, to the service that does the authentication scheme. That service sends back another ASN.1 object ๐Ÿ”.
  3. The protocol entity then builds an ASN.1 Message object using the community name and that returned ASN.1 object ๐Ÿ’œ.
  4. This new ASN.1 object gets serialized with the basic encoding rules of ASN.1, then sent to the peer protocol entity over a transport service ๐Ÿš€.

Now the top-level actions of a protocol entity that receives a message are kind of the mirror image ๐Ÿชž:

  1. It does a rudimentary parse of the incoming datagram to build an ASN.1 object that matches an ASN.1 Message object. If the parse fails, it discards the datagram and does nothing else. โŒ
  2. It then checks the version number of the SNMP message. If there's a mismatch, it discards the datagram and does nothing else. ๐Ÿ™…
  3. The protocol entity passes the community name and user data from the ASN.1 Message object, plus the datagram's source and destination transport addresses, to the authentication service. That service either returns another ASN.1 object or signals an authentication failure. If it's a failure, the protocol entity notes the failure, (possibly) generates a trap, discards the datagram, and does nothing else. ๐Ÿ˜ค
  4. The protocol entity does a rudimentary parse on the ASN.1 object returned by the authentication service, to build an ASN.1 object that matches an ASN.1 PDUs object. If the parse fails, it discards the datagram and does nothing else. Otherwise, using the named SNMP community, it selects the appropriate profile and processes the PDU accordingly. If that processing returns a message, the source transport address the response is sent from SHALL be identical to the destination transport address the original request was sent to. This part is so important ๐Ÿ‘‘.

4.1.1. Common Constructs ๐ŸŒธ

Before we get into the six PDU types, it's only right to look at some of the ASN.1 constructs that show up a lot:

                  -- 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 we tell outstanding requests apart ๐Ÿ”. Thanks to the RequestID, an SNMP application entity can match incoming responses to the requests they belong to. When you're using an unreliable datagram service, the RequestID also gives you a simple way to spot messages that got duplicated by the network. Iconic. ๐Ÿ˜ญ

A non-zero ErrorStatus means an exception happened while a request was being processed ๐Ÿšจ. In those cases, ErrorIndex MAY give extra info by pointing at which variable in a list caused the exception.

The word "variable" means an instance of a managed object ๐Ÿฆ‹. A variable binding (VarBind) is the pairing of a variable's name with its value. A VarBindList is just a simple list of variable names and their values. Some PDUs only care about the name of a variable and not its value (the GetRequest-PDU is one of these ๐Ÿ‘€). In that case, the protocol entity ignores the value portion of the binding. BUT the value portion MUST still have valid ASN.1 syntax and encoding, no skipping that! It is RECOMMENDED that the ASN.1 value NULL be used for the value portion of such bindings. ๐Ÿ’–


4.1.2. The GetRequest-PDU ๐ŸŽ€

The form of the GetRequest-PDU is:

                  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 the GetRequest-PDU when its SNMP application entity asks it to ๐Ÿ™Œ.

When the GetRequest-PDU is received, the receiving protocol entity responds according to whichever rule in the list below applies:

  1. If, for any object named in the variable-bindings field, the object's name doesn't exactly match the name of an object that's available for get operations in the relevant MIB view, then the receiving entity sends the originator of the received message a GetResponse-PDU of identical form. The difference is that the error-status field is noSuchName, and the error-index field 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. This time the error-status field is noSuchName, and the error-index field 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. The error-status field is tooBig, and the error-index field is 0. ๐Ÿ“ฆ
  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. The error-status field is genErr, and the error-index field 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 of the received message a GetResponse-PDU. 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 0. The request-id field of the GetResponse-PDU is the same as the one in the received message. Periodt. โœจ

4.1.3. The GetNextRequest-PDU โœจ

okay so the GetNextRequest-PDU is literally a twin of the GetRequest-PDU ๐Ÿ‘ฏโ€โ™€๏ธ the only thing that changes is the PDU type tag. here's the ASN.1, bestie:

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

                              error-status        -- always 0
                                  ErrorStatus,

                              error-index         -- always 0
                                  ErrorIndex,

                              variable-bindings
                                  VarBindList
                          }

only a protocol entity makes a GetNextRequest-PDU, and it only does that when its SNMP application entity asks for one ๐Ÿซถ

when a GetNextRequest-PDU shows up, the receiving protocol entity picks whichever of these rules applies:

(1) rule one ๐Ÿ™…โ€โ™€๏ธ: 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 receiver sends the originator a GetResponse-PDU in the same form, except the error-status is noSuchName and the error-index is the index of that object name component in the received message.

(2) rule two ๐Ÿ“ฆ: if the size of the GetResponse-PDU built as described below would go over a local limitation, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is tooBig and the error-index is zero.

(3) rule three ๐Ÿ’€: if, for any object named in the variable-bindings field, the value of the lexicographical successor to that object can't be retrieved for reasons not covered by the rules above, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is genErr and the 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 name in the variable-bindings field of the received message, the matching component of the GetResponse-PDU represents the name and value of the object that comes right after that name in the lexicographical ordering of all objects available for get operations in the relevant MIB view. the error-status of that GetResponse-PDU is noError, the errorindex is zero, and the request-id is the same as the received message's โœจ

4.1.3.1. Example of Table Traversal ๐Ÿฆ‹

the GetNextRequest-PDU is the MVP for walking through conceptual tables in the MIB ๐Ÿ—บ๏ธ the semantics of this SNMP message, plus the protocol-specific ways of identifying individual instances of object types, let you reach related objects as if they were laid out in a table.

so picture an SNMP application entity pulling the destination address and next hop gateway for each entry in one network element's routing table. say this 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

the management station sends the SNMP agent a GetNextRequest-PDU with 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 )

and 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 )

once there are no more entries in the table, the SNMP agent returns the objects that come next in the lexicographical ordering of the known object names. that response is how the management station knows the routing table is over ๐Ÿ

4.1.4. The GetResponse-PDU ๐ŸŽ€

the GetResponse-PDU looks just like the GetRequest-PDU, the only difference being the PDU type tag. here's the ASN.1 tea:

              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, a GetNextRequest-PDU, or a SetRequest-PDU, as described elsewhere in this document ๐Ÿ’Œ

when a GetResponse-PDU arrives, the receiving protocol entity hands its contents up to its SNMP application entity ๐Ÿซง

4.1.5. The SetRequest-PDU ๐ŸŒˆ

same story here: the SetRequest-PDU is identical to the GetRequest-PDU except for the PDU type tag ๐Ÿ‘ฏโ€โ™€๏ธ ASN.1 time:

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

                          error-status        -- always 0
                              ErrorStatus,

                          error-index         -- always 0
                              ErrorIndex,

                          variable-bindings
                              VarBindList
                      }

only a protocol entity makes a SetRequest-PDU, and only when its SNMP application entity requests it ๐Ÿ”ฅ

when a SetRequest-PDU arrives, the receiving entity picks whichever of these rules applies:

(1) rule one ๐Ÿšซ: if, for any object named in the variable-bindings field, the object isn't available for set operations in the relevant MIB view, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is noSuchName and the error-index is the index of that object name component in the received message.

(2) rule two ๐Ÿ™ˆ: if, for any object named in the variable-bindings field, the contents of the value field don't, according to the ASN.1 language, show a type, length, and value that's consistent with what the variable requires, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is badValue and the error-index is the index of that object name in the received message.

(3) rule three ๐Ÿ“ฆ: if the size of the Get Response type message built as described below would go over a local limitation, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is tooBig and the error-index is zero.

(4) rule four ๐Ÿ’€: if, for any object named in the variable-bindings field, the value of the named object can't be altered for reasons not covered by the rules above, then the receiver sends the originator a GetResponse-PDU in the same form, except the error-status is genErr and the error-index is the index of that object name component in the received message.

if none of the rules above 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 carried out as if it were set at the same time as all the other assignments in that same message ๐Ÿงš

after that, the receiving entity sends the originator a GetResponse-PDU in the same form, except the error-status of the generated message is noError and the error-index is zero โœจ

4.1.6. The Trap-PDU โœจ

okay bestie, the Trap-PDU is where the agent gets its main character moment ๐Ÿ’… here's the shape of it:

     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
             }

ok so a Trap-PDU only gets generated by a protocol entity when its SNMP application entity asks for one ๐Ÿซถ how the SNMP application entity picks the destination addresses of the SNMP application entities is implementation-specific, so that's up to whoever builds it โœจ

when a Trap-PDU lands, the receiving protocol entity just hands its contents up to its SNMP application entity ๐Ÿ“ฌ

what the variable-bindings component means is also implementation-specific ๐ŸŽ€

here's what each value of the generic-trap field means ๐ŸŒˆ

4.1.6.1. The coldStart Trap

a coldStart(0) trap means the sending protocol entity is reinitializing itself, so the agent's configuration or the protocol entity implementation may be altered โ„๏ธ

4.1.6.2. The warmStart Trap

a warmStart(1) trap means the sending protocol entity is reinitializing itself, but neither the agent configuration nor the protocol entity implementation is altered ๐ŸŒธ

4.1.6.3. The linkDown Trap

a linkDown(2) trap means the sending protocol entity noticed a failure in one of the communication links represented in the agent's configuration ๐Ÿ“‰

the 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 noticed that one of the communication links represented in the agent's configuration has come back up ๐Ÿ“ˆ

the 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 isn't properly authenticated ๐Ÿ™ˆ implementations of the SNMP must be capable of generating this trap, and they must also be capable of suppressing the emission of such traps via an implementation-specific mechanism. so the sender has to be able to make it, and also be able to mute it ๐Ÿ”‡

4.1.6.6. The egpNeighborLoss Trap

an egpNeighborLoss(5) trap means that an EGP neighbor, for whom the sending protocol entity was an EGP peer, has been marked down and the peer relationship no longer holds ๐Ÿ’”

the 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 noticed that some enterprise-specific event has happened ๐Ÿฆ‹ the specific-trap field tells you which particular trap it was ๐Ÿ”

5. Definitions ๐ŸŽ€

here's the whole MIB module, copied exactly as it appears in the spec:

     RFC1067-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 are the amazing people who helped make it happen ๐Ÿ’œ

             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, Proteon
             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. ๐ŸŒŸ

๐Ÿ“ฆ where this page comes from