RFC 2262

Message Processing and Dispatching for the Simple Network Management Protocol (SNMP)

πŸ“… published January 1998, from ietf

Message Processing and Dispatching for the Simple Network Management Protocol (SNMP) πŸŽ€

Okay bestie, this is RFC 2262 πŸ’– It's a Standards Track document, so it's an official Internet standard, not just a suggestion. It was published in January 1998 and was written by four people: J. Case (SNMP Research, Inc.), D. Harrington (Cabletron Systems, Inc.), R. Presuhn (BMC Software, Inc.), and B. Wijnen (IBM T. J. Watson Research). The title block doesn't list any documents it obsoletes or updates, so it's not replacing anything. ✨

Status of this Memo

This document is an Internet standards track protocol for the Internet community, and it asks for discussion and suggestions for improvements πŸ¦‹ For the standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1). Distribution of this memo is unlimited 🌸

Copyright (C) The Internet Society (1997). All Rights Reserved. πŸ’œ

Abstract

This doc explains Message Processing and Dispatching for SNMP messages inside the SNMP architecture [RFC2261] 🧚 It covers how the system sends potentially many different versions of SNMP messages to the right SNMP Message Processing Models, and how it dispatches PDUs to SNMP applications. It also describes one Message Processing Model: the SNMPv3 Message Processing Model πŸ‘‘

Table of Contents

1. Introduction ...............................................    2
2. Overview ...................................................    3
2.1. The Dispatcher. ..........................................    5
2.2. Message Processing Subsystem .............................    5
3. Elements of Message Processing and Dispatching .............    6
3.1. messageProcessingModel ...................................    6
3.2. pduVersion ...............................................    6
3.3. pduType ..................................................    7
3.4. sendPduHandle ............................................    7
4. Dispatcher Elements of Procedure ...........................    7
4.1. Sending an SNMP Message to the Network ...................    7
4.1.1. Sending a Request or Notification ......................    7
4.1.2. Sending a Response to the Network ......................    9
4.2. Receiving an SNMP Message from the Network ...............   10
4.2.1. Message Dispatching of received SNMP Messages ..........   10
4.2.2. PDU Dispatching for Incoming Messages ..................   11
4.2.2.1. Incoming Requests and Notifications ..................   12
4.2.2.2. Incoming Responses ...................................   13
4.3. Application Registration for Handling PDU types ..........   14
4.4. Application Unregistration for Handling PDU Types ........   14
5. Definitions ................................................   15
5.1. Definitions for SNMP Message Processing and Dispatching ..   15
6. The SNMPv3 Message Format ..................................   18
6.1. msgVersion ...............................................   19
6.2. msgID ....................................................   19
6.3. msgMaxSize ...............................................   19
6.4. msgFlags .................................................   20
6.5. msgSecurityModel .........................................   22
6.6. msgSecurityParameters ....................................   22
6.7. scopedPduData ............................................   22
6.8. scopedPDU ................................................   22
6.8.1. contextEngineID ........................................   22
6.8.2. contextName ............................................   23
6.8.3. data ...................................................   23
7. Elements of Procedure for v3MP .............................   23
7.1. Prepare an Outgoing SNMP Message .........................   24
7.2. Prepare Data Elements from an Incoming SNMP Message ......   29
8. Intellectual Property ......................................   34
9. Acknowledgements ...........................................   35
10. Security Considerations ...................................   36
11. References ................................................   36
12. Editors' Addresses ........................................   38
13. Full Copyright Statement ..................................   39

1. Introduction ✨

The Architecture for describing Internet Management Frameworks [RFC2261] says an SNMP engine is made up of four things:

1) a Dispatcher
2) a Message Processing Subsystem,
3) a Security Subsystem, and
4) an Access Control Subsystem.

Applications use the services of these subsystems πŸ’…

To get where the Message Processing Subsystem and the Dispatcher from this document fit in, and how they talk to everything else, you really need to understand the SNMP architecture and its terminology first. It's assumed you've already read and understood the description of the SNMP architecture in [RFC2261] πŸ“š

The Dispatcher in the SNMP engine sends and receives SNMP messages, and it also dispatches SNMP PDUs to SNMP applications. When an SNMP message needs to be prepared, or data needs to be pulled out of one, the Dispatcher hands that job off to a message version-specific Message Processing Model inside the Message Processing Subsystem πŸ¦‹

A Message Processing Model is responsible for processing a version-specific SNMP message. It also coordinates with the Security Subsystem so the message being handled gets proper security applied πŸ”

Interactions between the Dispatcher, the Message Processing Subsystem, and applications are modeled with abstract data elements and abstract service interface primitives, which are defined by the SNMP architecture. The interactions between the Message Processing Subsystem and the Security Subsystem work the same way, using abstract data elements and abstract service interface primitives defined by the SNMP architecture 🌈

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119. Those are the official BCP 14 words, so pay attention to them 🫢

2. Overview 🌸

Here's a picture of how Message Processing relates to SNMP applications, the Security Subsystem, and Transport Mappings. It's giving architecture diagram energy 🧚

+-------------------------------------------------------------------+
| SNMP Entity                                                       |
|                                                                   |
| +---------------------------------------------------------------+ |
| | Applications                                                  | |
| | +-----------+  +--------------+                               | |
| | | Command   |  | Notification |                               | |
| | | Generator |  | Originator   | +-----------+ +--------------+| |
| | +-----------+  +--------------+ | Proxy     | | Other         | |
| | +-----------+  +--------------+ | Forwarder | |Application(s)|| |
| | | Command   |  | Notification | +-----------+ +--------------+| |
| | | Responder |  | Receiver     |                               | |
| | +-----------+  +--------------+                               | |
| +---------------------------------------------------------------+ |
|        ^                ^               ^           ^             |
|        |                |               |           |             |
|        v                v               v           v             |
|        +--------+-------+---------------+-----------+             |
|                 ^                                                 |
|                 |    +---------------------+  +-----------------+ |
|                 |    | Message Processing  |  | Security        | |
| Dispatcher      v    | Subsystem           |  | Subsystem       | |
| +------------------+ |     +------------+  |  |                 | |
| | PDU Dispatcher   | |  +->| v1MP     * |<--->| +-------------+ | |
| |                  | |  |  +------------+  |  | | Other       | | |
| |                  | |  |  +------------+  |  | | Security    | | |
| |                  | |  +->| v2cMP    * |<--->| | Model       | | |
| | Message          | |  |  +------------+  |  | +-------------+ | |
| | Dispatcher  <-------->+                  |  |                 | |
| |                  | |  |  +------------+  |  | +-------------+ | |
| |                  | |  +->| v3MP     * |<--->| | User-based  | | |
| | Transport        | |  |  +------------+  |  | | Security    | | |
| | Mapping          | |  |  +------------+  |  | | Model       | | |
| | (e.g RFC1906)    | |  +->| otherMP  * |<--->| +-------------+ | |
| +------------------+ |     +------------+  |  |                 | |
|          ^           +---------------------+  +-----------------+ |
|          |                                                        |
+----------|--------------------------------------------------------+
           v
  +------------------+
  |   Network        |
  +------------------+

2.1. The Dispatcher.

The Dispatcher is a key piece of an SNMP engine πŸ”‘ There is only one in an SNMP engine, and its whole job is to dispatch tasks to the multiple version-specific Message Processing Models, and to dispatch PDUs to the various applications πŸ’–

For outgoing messages, an application provides the PDU to be sent, along with the data needed to prepare and send the message. The application also specifies which version-specific Message Processing Model will be used to prepare the message with the desired security processing. Once the message is prepared, the Dispatcher sends it off ✈️

For incoming messages, the Dispatcher figures out the SNMP version of the incoming message and passes it to the version-specific Message Processing Model. That model extracts the components of the message and coordinates the processing of security services for it. After the version-specific processing is done, the PDU Dispatcher decides which application, if any, should receive the PDU for processing, and forwards it there πŸŽ€

The Dispatcher collects statistics while it sends and receives SNMP messages, plus stats about how the SNMP engine behaves. It stores these in managed objects so remote SNMP entities can access them. This document defines those managed objects, the MIB module that contains them, and how they might be used to provide useful management πŸ“Š

2.2. Message Processing Subsystem πŸŽ€

okay so the Message Processing Subsystem is the bit of an SNMP engine that talks to the Dispatcher to handle the version-specific SNMP messages πŸ’… and it can hold one or more Message Processing Models ✨

this document describes ONE Message Processing Model, the SNMPv3 Message Processing Model, in Section 6 πŸ¦‹ it gets its own separate section on purpose so that multiple (independent) Message Processing Models can exist at the same time, and so they can be described in different documents 🌸 the SNMPv3 one can be replaced or supplemented with other Message Processing Models later on πŸ’– two that are expected to be developed in the future are the SNMPv1 message format [RFC1157] and the SNMPv2c message format [RFC1901] 🧚 and others may be developed as needed, obviously πŸ’œ

  1. Elements of Message Processing and Dispatching ✨

literally go read [RFC2261] for the definitions of these:

contextEngineID
contextName
scopedPDU
maxSizeResponseScopedPDU
securityModel
securityName
securityLevel
messageProcessingModel

for incoming messages, a version-specific message processing module hands these values to the Dispatcher πŸ“¨ and for outgoing messages, an application hands these values to the Dispatcher 🫢

for some version-specific processing the values might get pulled out of received messages πŸ” and for other versions they might be figured out by an algorithm, or by an implementation-defined mechanism πŸ€·β€β™€οΈ but the Dispatcher doesn't care HOW the value was determined, periodt πŸ’…

the following additional or expanded definitions are for use within the Dispatcher πŸŽ€

3.1. messageProcessingModel πŸ¦‹

the value of messageProcessingModel identifies a Message Processing Model πŸ’– and a Message Processing Model describes the version-specific procedures for extracting data from messages, generating messages, and calling upon a securityModel to apply its security services to messages 🌈 it also handles converting data from a version-specific message format into a generic format the Dispatcher can use, and converting data from Dispatcher format back into a version-specific message format πŸ”₯

3.2. pduVersion 🌸

the value of pduVersion represents a specific version of protocol operation and its associated PDU formats, like SNMPv1 or SNMPv2 [RFC1905] ✨ the values are specific to the version of the PDU inside a message, and the PDUs that applications process πŸ’œ the Dispatcher does NOT use the value of pduVersion directly πŸ™ˆ

an application specifies the pduVersion when it asks the PDU Dispatcher to send a PDU to another SNMP engine πŸ“€ the Dispatcher then passes the pduVersion to a Message Processing Model, so that model knows how to handle the PDU properly πŸ’…

for incoming messages, pduVersion gets handed to the Dispatcher by a version-specific Message Processing module πŸ“₯ and the PDU Dispatcher passes the pduVersion on to the application so it knows how to handle the PDU properly 🫢 for example, a command responder application needs to know whether to use [RFC1905] elements of procedure and syntax instead of the ones specified for SNMPv1 😭

3.3. pduType 🧚

a value of pduType represents a specific type of protocol operation πŸ’– the values are specific to the version of the PDU inside a message ✨

applications register to support particular pduTypes for particular contextEngineIDs πŸ“

for incoming messages, pduType gets handed to the Dispatcher by a version-specific Message Processing module πŸ“¨ and then it's used to dispatch the PDU to the application that registered for that pduType for the contextEngineID of the associated scopedPDU 🎯

3.4. sendPduHandle 🌈

this handle is generated to coordinate the processing of requests and responses between the SNMP engine and an application πŸ¦‹ the handle MUST be unique across all version-specific Message Processing Models, and it is of local significance only πŸ”’

  1. Dispatcher Elements of Procedure πŸ‘‘

this section describes the procedures the Dispatcher follows when it generates and processes SNMP messages πŸ’…

4.1. Sending an SNMP Message to the Network πŸ“€

this section describes the procedure an SNMP engine follows whenever it sends an SNMP message πŸš€

4.1.1. Sending a Request or Notification πŸ’Œ

the following procedures are followed by the Dispatcher when an application wants to send an SNMP PDU to another (remote) application, i.e., to start a conversation by originating a message, like one containing a request or a trap πŸ—£οΈ

  1. the application requests this using the abstract service primitive:
statusInformation =              -- sendPduHandle if success
                                 -- errorIndication if failure
  sendPdu(
  IN   transportDomain           -- transport domain to be used
  IN   transportAddress          -- destination network address
  IN   messageProcessingModel    -- typically, SNMP version
  IN   securityModel             -- Security Model to use
  IN   securityName              -- on behalf of this principal
  IN   securityLevel             -- Level of Security requested
  IN   contextEngineID           -- data from/at this entity
  IN   contextName               -- data from/in this context
  IN   pduVersion                -- the version of the PDU
  IN   PDU                       -- SNMP Protocol Data Unit
  IN   expectResponse            -- TRUE or FALSE
       )
  1. if the messageProcessingModel value does NOT represent a Message Processing Model known to the Dispatcher, then an errorIndication (implementation-dependent) is returned to the calling application πŸ™…β€β™€οΈ no further processing happens βœ‹
  2. the Dispatcher generates a sendPduHandle to coordinate subsequent processing 🎟️
  3. the Message Dispatcher sends the request to the version-specific Message Processing module identified by messageProcessingModel using the abstract service primitive:
statusInformation =              - success or error indication
  prepareOutgoingMessage(
  IN   transportDomain           -- as specified by application
  IN   transportAddress          -- as specified by application
  IN   messageProcessingModel    -- as specified by application
  IN   securityModel             -- as specified by application
  IN   securityName              -- as specified by application
  IN   securityLevel             -- as specified by application
  IN   contextEngineID           -- as specified by application
  IN   contextName               -- as specified by application
  IN   pduVersion                -- the version of the PDU
  IN   PDU                       -- as specified by application
  IN   expectResponse            -- as specified by application
  IN   sendPduHandle             -- as determined in step 3.
  OUT  destTransportDomain       -- destination transport domain
  OUT  destTransportAddress      -- destination transport address
  OUT  outgoingMessage           -- the message to send
  OUT  outgoingMessageLength     -- the message length
       )
  1. if the statusInformation indicates an error, the errorIndication is returned to the calling application 😬 no further processing happens βœ‹
  2. if the statusInformation indicates success, the sendPduHandle is returned to the application, and the outgoingMessage is sent via the transport specified by the transportDomain to the address specified by the transportAddress πŸŽ‰

Outgoing Message Processing is complete 🏁✨

4.1.2. Sending a Response to the Network πŸŽ€

the following procedure is followed when an application wants to send a response back to the originator of an SNMP Request πŸ’•

  1. an application can request this using the abstract service primitive:
returnResponsePDU(
 IN   messageProcessingModel   -- typically, SNMP version
 IN   securityModel            -- Security Model in use
 IN   securityName             -- on behalf of this principal
 IN   securityLevel            -- same as on incoming request
 IN   contextEngineID          -- data from/at this SNMP entity
 IN   contextName              -- data from/in this context
 IN   pduVersion               -- the version of the PDU
 IN   PDU                      -- SNMP Protocol Data Unit
 IN   maxSizeResponseScopedPDU -- maximum size of Response PDU
 IN   stateReference           -- reference to state information
                               -- as presented with the request
 IN   statusInformation        -- success or errorIndication
 )                             -- (error counter OID and value
                               -- when errorIndication)
  1. the Message Dispatcher sends the request to the appropriate Message Processing Model indicated by the received value of messageProcessingModel using the abstract service primitive:
result =                        -- SUCCESS or errorIndication
 prepareResponseMessage(
 IN   messageProcessingModel   -- specified by application
 IN   securityModel            -- specified by application
 IN   securityName             -- specified by application
 IN   securityLevel            -- specified by application
 IN   contextEngineID          -- specified by application
 IN   contextName              -- specified by application
 IN   pduVersion               -- specified by application
 IN   PDU                      -- specified by application
 IN   maxSizeResponseScopedPDU -- specified by application
 IN   stateReference           -- specified by application
 IN   statusInformation        -- specified by application
 OUT  destTransportDomain      -- destination transport domain
 OUT  destTransportAddress     -- destination transport address
 OUT  outgoingMessage          -- the message to send
 OUT  outgoingMessageLength    -- the message length
      )
  1. if the result is an errorIndication, the errorIndication is returned to the calling application 😬 no further processing happens βœ‹
  2. if the result is success, the outgoingMessage is sent over the transport specified by the transportDomain to the address specified by the transportAddress πŸš€

Message Processing is complete 🏁

4.2. Receiving an SNMP Message from the Network πŸ“₯

this section describes the procedure an SNMP engine follows whenever it receives an SNMP message πŸ‘€

please note, for the sake of clarity and so this doesn't get even longer and more complicated πŸ™ƒ, some details were left out of the steps below 🫣 in particular, the elements of procedure do not always explicitly say when state information needs to be released πŸ—‘οΈ the general rule is that if state information is available when a message is to be "discarded without further processing", then the state information MUST also be released at that same time πŸ’€βœ¨

4.2.1. Message Dispatching of received SNMP Messages ✨

okay bestie, this is where a received message gets sorted out πŸ’… here's the step-by-step:

  1. The snmpInPkts counter [RFC1907] gets incremented πŸ“ˆ
  2. The version of the SNMP message is figured out in an implementation-dependent way πŸ”. If the packet can't be parsed enough to find the version, the snmpInASNParseErrs [RFC1907] counter gets incremented and the message is discarded without further processing πŸ’€. If the version isn't supported, the snmpInBadVersions [RFC1907] counter gets incremented and the message is discarded without further processing πŸ™ˆ.
  3. The origin transportDomain and origin transportAddress get determined πŸ—ΊοΈ
  4. The message gets passed to the version-specific Message Processing Model, which hands back the abstract data elements the Dispatcher needs 🧚. This happens through this abstract service primitive:
result =                        -- SUCCESS or errorIndication
  prepareDataElements(
  IN   transportDomain          -- origin as determined in step 3.
  IN   transportAddress         -- origin as determined in step 3.
  IN   wholeMsg                 -- as received from the network
  IN   wholeMsgLength           -- as received from the network
  OUT  messageProcessingModel   -- typically, SNMP version
  OUT  securityModel            -- Security Model to use
  OUT  securityName             -- on behalf of this principal
  OUT  securityLevel            -- Level of Security requested
  OUT  contextEngineID          -- data from/at this entity
  OUT  contextName              -- data from/in this context
  OUT  pduVersion               -- the version of the PDU
  OUT  PDU                      -- SNMP Protocol Data Unit
  OUT  pduType                  -- SNMP PDU type
  OUT  sendPduHandle            -- handle for a matched request
  OUT  maxSizeResponseScopedPDU -- maximum size of Response PDU
  OUT  statusInformation        -- success or errorIndication
                                -- (error counter OID and value
                                -- when errorIndication)
  OUT  stateReference           -- reference to state information
                                -- to be used for a possible
       )                        -- Response
  1. If the result is a FAILURE errorIndication, the message is discarded without further processing πŸ—‘οΈ
  2. At this point the abstract data elements are all prepped, and processing carries on as described in Section 4.2.2, PDU Dispatching for Incoming Messages ✨

4.2.2. PDU Dispatching for Incoming Messages πŸŽ€

ngl this part is all about sendPduHandle. The dispatching rules depend on what its value is πŸ‘‘. If sendPduHandle is <none>, then it's a request or notification, and the procedures in Section 4.2.2.1 apply. If the value of snmpPduHandle is not <none>, then it's a response, and the procedures in Section 4.2.2.2 apply πŸ¦‹.

4.2.2.1. Incoming Requests and Notifications πŸ’Œ

These are the procedures for dispatching PDUs when sendPduHandle is <none>, which means it's a request or notification.

  1. The combination of contextEngineID and pduType is used to figure out which application has registered for this request or notification πŸ”Ž
  2. If no application has registered for that combination, then:
    • a) The snmpUnknownPDUHandlers counter gets incremented.
    • b) A Response message gets generated using this abstract service primitive:
result =                         -- SUCCESS or FAILURE
prepareResponseMessage(
IN   messageProcessingModel    -- as provided by MP module
IN   securityModel             -- as provided by MP module
IN   securityName              -- as provided by MP module
IN   securityLevel             -- as provided by MP module
IN   contextEngineID           -- as provided by MP module
IN   contextName               -- as provided by MP module
IN   pduVersion                -- as provided by MP module
IN   PDU                       -- as provided by MP module
IN   maxSizeResponseScopedPDU  -- as provided by MP module
IN   stateReference            -- as provided by MP module
IN   statusInformation         -- errorIndication plus
                                -- snmpUnknownPDUHandlers OID
                                -- value pair.
OUT  transportDomain           -- destination transportDomain
OUT  transportAddress          -- destination transportAddress
OUT  outgoingMessage           -- the message to send
OUT  outgoingMessageLength     -- its length
)
  • c) If the result is SUCCESS, the prepared message gets sent back to the originator of the request, as identified by the transportDomain and transportAddress πŸ“¨
  • d) The incoming message is discarded without further processing. Message Processing for this message is complete πŸ’…
  1. The PDU gets dispatched to the application using this abstract service primitive:
processPdu(                     -- process Request/Notification
  IN   messageProcessingModel   -- as provided by MP module
  IN   securityModel            -- as provided by MP module
  IN   securityName             -- as provided by MP module
  IN   securityLevel            -- as provided by MP module
  IN   contextEngineID          -- as provided by MP module
  IN   contextName              -- as provided by MP module
  IN   pduVersion               -- as provided by MP module
  IN   PDU                      -- as provided by MP module
  IN   maxSizeResponseScopedPDU -- as provided by MP module
  IN   stateReference           -- as provided by MP module
                                -- needed when sending response
       )

Message processing for this message is complete ✨

4.2.2.2. Incoming Responses πŸ“¬

These are the procedures for dispatching PDUs when sendPduHandle is not <none>, which means it's a response.

  1. The value of sendPduHandle is used to work out, in an implementation-defined manner, which application is waiting for a response PDU linked to that sendPduHandle πŸ•΅οΈβ€β™€οΈ
  2. If no waiting application is found, the message is discarded without further processing, and the stateReference is released. The snmpUnknownPDUHandlers counter gets incremented. Message Processing is complete for this message πŸ₯€
  3. Any cached information about the message, including the stateReference, is discarded 🧹
  4. The response gets dispatched to the application using this abstract service primitive:
processResponsePdu(              -- process Response PDU
  IN   messageProcessingModel    -- provided by the MP module
  IN   securityModel             -- provided by the MP module
  IN   securityName              -- provided by the MP module
  IN   securityLevel             -- provided by the MP module
  IN   contextEngineID           -- provided by the MP module
  IN   contextName               -- provided by the MP module
  IN   pduVersion                -- provided by the MP module
  IN   PDU                       -- provided by the MP module
  IN   statusInformation         -- provided by the MP module
  IN   sendPduHandle             -- provided by the MP module
       )

Message Processing is complete for this message 🌸


4.3. Application Registration for Handling PDU types πŸ¦‹

okay so applications that want to process certain PDUs must register with the PDU Dispatcher 🧚. Applications pick the combination of contextEngineID and pduType(s) they want to take responsibility for πŸ’–

  1. An application registers using this abstract interface primitive:
statusInformation =           -- success or errorIndication
  registerContextEngineID(
  IN   contextEngineID        -- take responsibility for this one
  IN   pduType                -- the pduType(s) to be registered
       )

Note: implementations may provide a way to request registration for multiple contextEngineID values at once (e.g., all contextEngineID values), and may also provide ways to request simultaneous registration for multiple values of pduType 🫢

  1. The parameters may be checked for validity. If they aren't valid, an errorIndication (invalidParameter) is returned to the application πŸ™…β€β™€οΈ
  2. Each combination of contextEngineID and pduType can only be registered once. If another application has already registered for the specified combination, then an errorIndication (alreadyRegistered) is returned to the application 🚫
  3. Otherwise, the registration is saved so SNMP PDUs can be dispatched to this application πŸŽ‰

4.4. Application Unregistration for Handling PDU Types πŸ‘‹

applications that don't want to process certain PDUs anymore must unregister with the PDU Dispatcher πŸ₯Ί

  1. An application unregisters using this abstract service primitive:
unregisterContextEngineID(
 IN   contextEngineID        -- give up responsibility for this
 IN   pduType                -- the pduType(s) to be unregistered
       )

Note: implementations may provide ways to request unregistration for multiple contextEngineID values at once (e.g., all contextEngineID values), and may also provide ways to request simultaneous unregistration for multiple values of pduType πŸ’œ

  1. If the contextEngineID and pduType combination has been registered, the registration is deleted 🧼. If no such registration exists, the request is ignored πŸ€·β€β™€οΈ

5. Definitions 🌈

5.1. Definitions for SNMP Message Processing and Dispatching πŸ“šβœ¨

Okay bestie, this is the MIB module for the message processing and dispatching stuff, called SNMP-MPD-MIB. It's giving very organised energy πŸ’…

   SNMP-MPD-MIB DEFINITIONS ::= BEGIN

   IMPORTS
       MODULE-COMPLIANCE, OBJECT-GROUP         FROM SNMPv2-CONF
       MODULE-IDENTITY, OBJECT-TYPE,
       snmpModules, Counter32                  FROM SNMPv2-SMI;

   snmpMPDMIB MODULE-IDENTITY
       LAST-UPDATED "9711200000Z"              -- 20 November 1997
       ORGANIZATION "SNMPv3 Working Group"
       CONTACT-INFO "WG-email:   snmpv3@tis.com
                     Subscribe:  majordomo@tis.com
                                 In message body:  subscribe snmpv3

                     Chair:      Russ Mundy
                                 Trusted Information Systems
                     postal:     3060 Washington Road
                                 Glenwood, MD 21738
                                 USA
                     email:      mundy@tis.com
                     phone:      +1 301-854-6889

                     Co-editor:  Jeffrey Case
                                 SNMP Research, Inc.
                     postal:     3001 Kimberlin Heights Road
                                 Knoxville, TN 37920-9716
                                 USA
                     email:      case@snmp.com
                     phone:      +1 423-573-1434
                     Co-editor   Dave Harrington
                                 Cabletron Systems, Inc.
                     postal:     Post Office Box 5005
                                 MailStop: Durham
                                 35 Industrial Way
                                 Rochester, NH 03867-5005
                                 USA
                     email:      dbh@ctron.com
                     phone:      +1 603-337-7357

                     Co-editor:  Randy Presuhn
                                 BMC Software, Inc.
                     postal:     1190 Saratoga Ave, Suite 190
                                 San Jose, CA 95120
                                 USA
                     email:      rpresuhn@bmc.com
                     phone:      +1 408-556-0720

                     Co-editor:  Bert Wijnen
                                 IBM T. J. Watson Research
                     postal:     Schagen 33
                                 3461 GL Linschoten
                                 Netherlands
                     email:      wijnen@vnet.ibm.com
                     phone:      +31 348-432-794

                    "
       DESCRIPTION  "The MIB for Message Processing and Dispatching"
       ::= { snmpModules 3 }

   -- Administrative assignments ***************************************

   snmpMPDAdmin           OBJECT IDENTIFIER ::= { snmpMPDMIB 1 }
   snmpMPDMIBObjects      OBJECT IDENTIFIER ::= { snmpMPDMIB 2 }
   snmpMPDMIBConformance  OBJECT IDENTIFIER ::= { snmpMPDMIB 3 }

   -- Statistics for SNMP Messages *************************************

   snmpMPDStats           OBJECT IDENTIFIER ::= { snmpMPDMIBObjects 1 }

   snmpUnknownSecurityModels OBJECT-TYPE
       SYNTAX       Counter32
       MAX-ACCESS   read-only
       STATUS       current
       DESCRIPTION "The total number of packets received by the SNMP
                    engine which were dropped because they referenced a
                    securityModel that was not known to or supported by
                    the SNMP engine.

                   "
       ::= { snmpMPDStats 1 }

   snmpInvalidMsgs OBJECT-TYPE
       SYNTAX       Counter32
       MAX-ACCESS   read-only
       STATUS       current
       DESCRIPTION "The total number of packets received by the SNMP
                    engine which were dropped because there were invalid
                    or inconsistent components in the SNMP message.
                   "
       ::= { snmpMPDStats 2 }

   snmpUnknownPDUHandlers OBJECT-TYPE
       SYNTAX       Counter32
       MAX-ACCESS   read-only
       STATUS       current
       DESCRIPTION "The total number of packets received by the SNMP
                    engine which were dropped because the PDU contained
                    in the packet could not be passed to an application
                    responsible for handling the pduType, e.g. no SNMP
                    application had registered for the proper
                    combination of the contextEngineID and the pduType.
                   "
       ::= { snmpMPDStats 3 }

   -- Conformance information ******************************************

   snmpMPDMIBCompliances OBJECT IDENTIFIER ::= {snmpMPDMIBConformance 1}
   snmpMPDMIBGroups      OBJECT IDENTIFIER ::= {snmpMPDMIBConformance 2}

   -- Compliance statements

   snmpMPDCompliance MODULE-COMPLIANCE
       STATUS       current
       DESCRIPTION "The compliance statement for SNMP entities which
                    implement the SNMP-MPD-MIB.
                   "

       MODULE    -- this module

           MANDATORY-GROUPS { snmpMPDGroup }

       ::= { snmpMPDMIBCompliances 1 }

   snmpMPDGroup OBJECT-GROUP
       OBJECTS {
                 snmpUnknownSecurityModels,
                 snmpInvalidMsgs,
                 snmpUnknownPDUHandlers
               }
       STATUS       current
       DESCRIPTION "A collection of objects providing for remote
                    monitoring of the SNMP Message Processing and
                    Dispatching process.
                   "
       ::= { snmpMPDMIBGroups 1 }

   END

6. The SNMPv3 Message Format πŸŽ€

This section is where we define the SNMPv3 message format, plus the SNMP version 3 Message Processing Model (v3MP) that goes with it πŸ¦‹

   SNMPv3MessageSyntax DEFINITIONS IMPLICIT TAGS ::= BEGIN

       SNMPv3Message ::= SEQUENCE {
           -- identify the layout of the SNMPv3Message
           -- this element is in same position as in SNMPv1
           -- and SNMPv2c, allowing recognition
           msgVersion INTEGER { snmpv3 (3) },
           -- administrative parameters
           msgGlobalData HeaderData,
           -- security model-specific parameters
           -- format defined by Security Model
           msgSecurityParameters OCTET STRING,
           msgData  ScopedPduData
       }

       HeaderData ::= SEQUENCE {
           msgID      INTEGER (0..2147483647),
           msgMaxSize INTEGER (484..2147483647),

           msgFlags   OCTET STRING (SIZE(1)),
                      --  .... ...1   authFlag
                      --  .... ..1.   privFlag
                      --  .... .1..   reportableFlag
                      --              Please observe:
                      --  .... ..00   is OK, means noAuthNoPriv
                      --  .... ..01   is OK, means authNoPriv
                      --  .... ..10   reserved, must NOT be used.
                      --  .... ..11   is OK, means authPriv

           msgSecurityModel INTEGER (0..2147483647)
       }
       ScopedPduData ::= CHOICE {
           plaintext    ScopedPDU,
           encryptedPDU OCTET STRING  -- encrypted scopedPDU value
       }

       ScopedPDU ::= SEQUENCE {
           contextEngineID  OCTET STRING,
           contextName      OCTET STRING,
           data             ANY -- e.g., PDUs as defined in RFC1905
       }
   END

6.1. msgVersion

The msgVersion field gets set to snmpv3(3), and that's how you know the message is an SNMP version 3 Message 🫢

6.2. msgID

msgID is the ID that two SNMP entities use to match up requests and responses. The v3MP uses it too, to keep track of the message as different subsystem models process it ✨

Values for msgID should be generated in a way that avoids re-using any outstanding values. Doing so gives you protection against some replay attacks πŸ™ˆ One possible strategy is to use the low-order bits of snmpEngineBoots [RFC2261] as the high-order part of the msgID value, and a monotonically increasing integer for the low-order part.

Quick heads up: the request-id in a PDU is what SNMP applications use to identify the PDU, but msgID is what the engine uses to identify the message that carries it. The engine may still need to identify the message even if decrypting the PDU (and request-id) fails. Don't assume msgID and request-id are equivalent πŸ’€

6.3. msgMaxSize

msgMaxSize tells you the maximum message size the sender supports, meaning the biggest message that sender can accept when another SNMP engine sends it an SNMP message (a response or anything else) πŸ“

When a message is generated, the SNMP engine that generates it provides the msgMaxSize. At the receiving engine, msgMaxSize is what determines how big the Response to a Request message can be πŸ‘‘

6.4. msgFlags ✨

okay so msgFlags is where the message keeps its little control bits πŸŽ€ it's giving "read me before you touch anything" energy πŸ’…

When the reportableFlag is one, a Report PDU MUST be returned to the sender under those conditions that can cause Report PDUs to be generated. When the reportableFlag is zero, a Report PDU MUST NOT be sent. The reportableFlag MUST always be zero when the message contains a Report PDU, a response-type PDU (like a Response PDU), or an unacknowledged notification-type PDU (like an SNMPv2-trap PDU). It MUST always be one for a request-type PDU (like a Get PDU) and an acknowledged notification-type PDU (like an Inform PDU) πŸ”₯

If the reportableFlag is one on a message containing a Report PDU, a response-type PDU, or an unacknowledged notification-type PDU, the receiver MUST process it as though the reportableFlag were zero πŸ™ˆ

If the reportableFlag is zero on a message containing a request-type PDU or an acknowledged notification-type PDU, the receiver MUST process it as though the reportableFlag were one πŸ¦‹

Report PDUs are engine-to-engine chats. They get handled directly by the SNMPv3 Message Processing Model and usually don't get passed up to applications, unlike every other PDU type 🧚

Note that the reportableFlag is only a backup helper for deciding whether a Report PDU MUST be sent. It only comes into play when the PDU portion of a message can't be decoded (for example, because of a wrong encryption key). If the PDU can be decoded, the PDU type is what drives the Report PDU decisions 🫢

The authFlag and privFlag bits are set by the sender to show the securityLevel that was applied before the message went out on the wire. The receiver MUST apply that same securityLevel when the message comes in and its contents get processed 🌸

There are three securityLevels: noAuthNoPriv, which is less than authNoPriv, which is less than authPriv. For the full scoop on securityLevel, check the SNMP architecture document [RFC2261] πŸ“š

a) authFlag

If the authFlag is one, the securityModel used by the SNMP engine that sent the message MUST identify the securityName the message was generated for, and MUST provide enough securityModel-specific data for the receiver to authenticate that identity. Generally, this authentication lets the receiver figure out, with reasonable certainty, that the message:

  • was sent on behalf of the principal tied to the securityName,
  • was not redirected,
  • was not modified in transit, and
  • was not replayed.

If the authFlag is zero, the securityModel used by the sending SNMP engine MUST still identify the securityName the message was generated for, but it doesn't need to provide enough data for the receiver to authenticate that identity, because the message doesn't need authenticating in this case πŸ’œ

b) privFlag

If the privFlag is set, the securityModel used by the sending SNMP engine MUST also protect the scopedPDU from disclosure, i.e., MUST encrypt/decrypt the scopedPDU. If the privFlag is zero, the securityModel in use doesn't need to protect the data from disclosure πŸ”

It's an explicit rule of the SNMP architecture that if privacy is selected, authentication is also REQUIRED. So if the privFlag is set, the authFlag MUST also be set to one πŸ‘‘

The authFlag and privFlag bits together make up the Level of Security like this:

   authFlag zero, privFlag zero -> securityLevel is noAuthNoPriv
   authFlag zero, privFlag one  -> invalid combination
   authFlag one,  privFlag zero -> securityLevel is authNoPriv
   authFlag one,  privFlag one  -> securityLevel is authPriv

6.5. msgSecurityModel 🌈

The v3MP supports multiple Security Models existing at the same time to provide security services for SNMPv3 messages. The msgSecurityModel field in an SNMPv3 Message says which Security Model the sender used to generate the message, and therefore which securityModel the receiver has to use to do the security processing. How that maps to the right securityModel implementation inside an SNMP engine is up to each implementation 🧩

6.6. msgSecurityParameters ✨

The msgSecurityParameters field of the SNMPv3 Message is how the Security Model modules on the sending and receiving SNMP engines talk to each other πŸ’¬ Only the Security Model uses the data in this field. Its contents and format are defined by the Security Model. The v3MP doesn't interpret this OCTET STRING at all. It just hands it to the local Security Model implementation named in the msgSecurityModel field πŸŽ€

6.7. scopedPduData πŸ’…

The scopedPduData field holds either the plain text scopedPDU, if the privFlag in the msgFlags is zero, or an encryptedPDU (encoded as an OCTET STRING). That encryptedPDU MUST be decrypted by the securityModel in use to produce a plaintext scopedPDU πŸ”“

6.8. scopedPDU πŸ¦‹

The scopedPDU holds info that identifies an administratively unique context, plus a PDU. The object identifiers in the PDU point at managed objects that are (expected to be) accessible within that context πŸ“

6.8.1. contextEngineID 🌸

The contextEngineID in the SNMPv3 message uniquely identifies, within an administrative domain, an SNMP entity that might realize an instance of a context with a particular contextName 🌍

For incoming messages, the contextEngineID is what decides which application the scopedPDU gets sent to for processing πŸ“¬

For outgoing messages, the v3MP sets the contextEngineID to whatever value the application gave in its request to send a message ✨

6.8.2. contextName 🧁

The contextName field in an SNMPv3 message, together with the contextEngineID field, identifies the particular context linked to the management information in the PDU portion of the message. The contextName is unique within the SNMP entity named by the contextEngineID, which might realize the managed objects the PDU refers to. The application that originates a message supplies the value for the contextName field, and the receiving SNMP Engine's application may use that value while processing 🫢

6.8.3. data 🌈

The data field of the SNMPv3 Message holds the PDU. Among other things, the PDU carries the PDU type the v3MP uses to figure out what kind of SNMP message just came in. The v3MP specifies that the PDU MUST be one of those defined in [RFC1905] πŸ“–

7. Elements of Procedure for v3MP πŸ¦‹

This section walks through what an SNMP engine does when it generates and processes SNMP messages under the SNMPv3 Message Processing Model 🧠

Quick heads up: to keep things clear and stop the text from getting even longer and more confusing, some details got left out of the steps below πŸ™ˆ

a) Some steps say that when certain error conditions come up while processing a received message, a message containing a Report PDU is generated and the received message is discarded without further processing. However, a Report-PDU MUST NOT be generated unless the reportableFlag is set in the received message ‼️

b) The elements of procedure don't always spell out when state information needs to be released. The general rule is this: if state information is available when a message is about to be "discarded without further processing", then the state information MUST also be released at that same moment πŸ’–

7.1. Prepare an Outgoing SNMP Message ✨

okay so this section is the recipe for building an SNMPv3 message πŸ“ starting from the bits the Message Dispatcher hands over. let's go step by step bestie πŸ’…

1) the Message Dispatcher can ask for an SNMPv3 message carrying a GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU, SetRequest-PDU, InformRequest-PDU, or SNMPv2-Trap-PDU to get prepared for sending πŸ“¨

a) it asks for that using this abstract service primitive (it's giving very neat little function signature energy 🧚):

statusInformation =           -- success or errorIndication
  prepareOutgoingMessage(
  IN   transportDomain        -- requested transport domain
  IN   transportAddress       -- requested destination address
  IN   messageProcessingModel -- typically, SNMP version
  IN   securityModel          -- Security Model to use
  IN   securityName           -- on behalf of this principal
  IN   securityLevel          -- Level of Security requested
  IN   contextEngineID        -- data from/at this entity
  IN   contextName            -- data from/in this context
  IN   pduVersion             -- version of the PDU
  IN   PDU                    -- SNMP Protocol Data Unit
  IN   expectResponse         -- TRUE or FALSE
  IN   sendPduHandle          -- the handle for matching
                              -- incoming responses
  OUT  destTransportDomain    -- destination transport domain
  OUT  destTransportAddress   -- destination transport address
  OUT  outgoingMessage        -- the message to send
  OUT  outgoingMessageLength  -- the length of the message
  )

b) a unique msgID gets generated πŸ¦‹ the number used for msgID should not have been used recently, and must not be the same as was used for any outstanding request. no repeats in the group chat, periodt πŸ’€

* SNMPv3 does not use the values of expectResponse or pduVersion. so those two just vibe in the background 🫢

2) the Message Dispatcher can also ask for an SNMPv3 message carrying a Response-PDU or Report-PDU to get prepared πŸ’Œ

a) the request goes out through this primitive:

result =                        -- SUCCESS or FAILURE
prepareResponseMessage(
 IN   messageProcessingModel   -- typically, SNMP version
 IN   securityModel            -- same as on incoming request
 IN   securityName             -- same as on incoming request
 IN   securityLevel            -- same as on incoming request
 IN   contextEngineID          -- data from/at this SNMP entity
 IN   contextName              -- data from/in this context
 IN   pduVersion               -- version of the PDU
 IN   PDU                      -- SNMP Protocol Data Unit
 IN   maxSizeResponseScopedPDU -- maximum size of Response PDU
 IN   stateReference           -- reference to state
                               -- information presented with
                               -- the request
 IN   statusInformation        -- success or errorIndication
                               -- error counter OID and value
                               -- when errorIndication
 OUT  transportDomain          -- destination transport domain
 OUT  transportAddress         -- destination transport address
 OUT  outgoingMessage          -- the message to send
 OUT  outgoingMessageLength    -- the length of the message
 )

b) the cached info for the original request gets pulled up using the stateReference πŸ” that includes:

- msgID,
- contextEngineID,
- contextName,
- securityModel,
- securityName,
- securityLevel,
- securityStateReference,
- reportableFlag,
- transportDomain, and
- transportAddress.

the SNMPv3 Message Processing Model does not allow cached data to be overridden, except by error indications as detailed in (3) below. so the cache is sacred unless there's an error indication involved πŸ™ˆ

3) if statusInformation has values for an OID/value combination (it might also have a securityLevel value, contextEngineID value, or contextName value), then 🚨

a) if reportableFlag is zero, the original message is discarded and no further processing happens. a result of FAILURE gets returned, and SNMPv3 Message Processing is complete. bye bye πŸ‘‹

b) if a PDU is provided, it's the PDU from the original request. if possible, extract the request-id πŸ”Ž

c) a Report PDU gets prepared:

1) the varBindList gets set to contain the OID and value from the statusInformation

2) error-status is set to 0

3) error-index is set to 0.

4) request-id is set to the value extracted in step b). Otherwise, request-id is set to 0

d) the errorIndication in statusInformation may come with a securityLevel value, a contextEngineID value, or a contextName value. here's how each one gets handled:

1) if statusInformation has a value for securityLevel, then securityLevel is set to that value. otherwise it's set to noAuthNoPriv.

2) if statusInformation has a value for contextEngineID, then contextEngineID is set to that value. otherwise it's set to the value of this entity's snmpEngineID.

3) if statusInformation has a value for contextName, then contextName is set to that value. otherwise it's set to the default context of "" (zero-length string).

e) PDU is set to refer to the new Report-PDU. the old PDU gets discarded πŸ—‘οΈ

f) processing continues with step 6) below ➑️

4) if contextEngineID isn't determined yet, then it gets determined in an implementation-dependent manner, possibly using the transportDomain and transportAddress 🧭

5) if the contextName isn't determined yet, it gets set to the default context πŸŽ€

6) a scopedPDU gets prepared from the contextEngineID, contextName, and PDU 🎁

7) msgGlobalData gets constructed like this, and it's giving organized queen energy πŸ‘‘

a) the msgVersion field is set to snmpv3(3).

b) msgID is set as determined in step 1 or 2 above.

c) msgMaxSize is set to an implementation-dependent value.

d) msgFlags are set as follows:

- if securityLevel specifies noAuthNoPriv, then authFlag and privFlag are both set to zero.

- if securityLevel specifies authNoPriv, then authFlag is set to one and privFlag is set to zero.

- if securityLevel specifies authPriv, then authFlag is set to one and privFlag is set to one.

- if the PDU is a Response-PDU, Report-PDU or SNMPv2-Trap-PDU, then the reportableFlag is set to zero.

- if the PDU is a GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU, SetRequest-PDU, or InformRequest-PDU then the reportableFlag is set to one.

- all other msgFlags bits are set to zero.

e) msgSecurityModel is set to the value of securityModel πŸ”

8) if the PDU is a Response-PDU or Report-PDU, then πŸ“€

a) the specified Security Model gets called to generate the message using this primitive:

statusInformation =
  generateResponseMsg(
  IN   messageProcessingModel -- SNMPv3 Message Processing
                              -- Model
  IN   globalData             -- msgGlobalData from step 7
  IN   maxMessageSize         -- from msgMaxSize (step 7c)
  IN   securityModel          -- as determined in step 7e
  IN   securityEngineID       -- the value of snmpEngineID
  IN   securityName           -- on behalf of this principal
  IN   securityLevel          -- for the outgoing message
  IN   scopedPDU              -- as prepared in step 6)
  IN   securityStateReference -- as determined in step 2
  OUT  securityParameters     -- filled in by Security Module
  OUT  wholeMsg               -- complete generated message
  OUT  wholeMsgLength         -- length of generated message
  )

if, once the Security Model returns, statusInformation includes an errorIndication, then any cached info about the outstanding request message gets discarded. an errorIndication gets returned so the calling application can see it, and SNMPv3 Message Processing is complete 😭

b) a SUCCESS result gets returned. SNMPv3 Message Processing is complete ✨

9) if the PDU is a GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU, SetRequest-PDU, InformRequest-PDU, or or SNMPv2-Trap-PDU, then πŸš€

a) if the PDU is an SNMPv2-Trap-PDU, then securityEngineID is set to the value of this entity's snmpEngineID.

otherwise, the snmpEngineID of the target entity gets determined in an implementation-dependent manner, possibly using transportDomain and transportAddress. the value of securityEngineID is then set to the value of the target entity's snmpEngineID 🎯

b) the specified Security Model gets called to generate the message using this primitive:

statusInformation =
 generateRequestMsg(
 IN  messageProcessingModel -- SNMPv3 Message Processing Model
 IN  globalData             -- msgGlobalData, from step 7
 IN  maxMessageSize         -- from msgMaxSize in step 7 c)
 IN  securityModel          -- as provided by caller
 IN  securityEngineID       -- authoritative SNMP entity
 IN  securityName           -- as provided by caller
 IN  securityLevel          -- as provided by caller
 IN  snmpEngineID           -- as determined in step 9 a)
 IN  scopedPDU              -- as prepared in step 6
 OUT securityParameters     -- filled in by Security Module
 OUT wholeMsg               -- complete generated message
 OUT wholeMsgLength         -- length of the generated message
 )

if, once the Security Model returns, statusInformation includes an errorIndication, then the message is discarded and the errorIndication is returned so the calling application can see it. no further processing happens, and SNMPv3 Message Processing is complete πŸ›‘

c) info about the outgoing message gets cached, and a stateReference is created (implementation-specific) πŸ—‚οΈ the info to cache includes the values of:

- sendPduHandle
- msgID
- snmpEngineID
- securityModel
- securityName
- securityLevel
- contextEngineID
- contextName

d) a SUCCESS result gets returned. SNMPv3 Message Processing is complete πŸŽ‰

7.2. Prepare Data Elements from an Incoming SNMP Message πŸ“₯

okay bestie, this is the part where the Message Dispatcher hands us a raw incoming SNMPv3 message and we turn it into all the neat data elements the rest of the engine needs πŸ’… no cap, it's giving very organized. this section is literally the intake desk 🧚

1) The Message Dispatcher passes the message in using this abstract service primitive, and it's giving whole vibe check 🫢:

result =                         -- SUCCESS or errorIndication
  prepareDataElements(
  IN  transportDomain          -- origin transport domain
  IN  transportAddress         -- origin transport address
  IN  wholeMsg                 -- as received from the network
  IN  wholeMsgLength           -- as received from the network
  OUT messageProcessingModel   -- typically, SNMP version
  OUT securityModel            -- Security Model to use
  OUT securityName             -- on behalf of this principal
  OUT securityLevel            -- Level of Security requested
  OUT contextEngineID          -- data from/at this entity
  OUT contextName              -- data from/in this context
  OUT pduVersion               -- version of the PDU
  OUT PDU                      -- SNMP Protocol Data Unit
  OUT pduType                  -- SNMP PDU type
  OUT sendPduHandle            -- handle for matched request
  OUT maxSizeResponseScopedPDU -- maximum size of Response PDU
  OUT statusInformation        -- success or errorIndication
                               -- error counter OID and value
                               -- when errorIndication
  OUT stateReference           -- reference to state information
                               -- to be used for a possible
  )                            -- Response

2) If the received message is not the serialization (following the conventions of [RFC1906]) of an SNMPv3Message value, then the snmpInASNParseErrs counter [RFC1907] gets incremented, the message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. bye bye message πŸ‘‹πŸ₯€

3) The values for msgVersion, msgID, msgMaxSize, msgFlags, msgSecurityModel, msgSecurityParameters, and msgData get extracted from the message. we're pulling out the good stuff ✨

4) If the value of the msgSecurityModel component does not match a supported securityModel, then the snmpUnknownSecurityModels counter gets incremented, a Report PDU is generated, the message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. not supported?? not today πŸ™…β€β™€οΈ

5) The securityLevel is figured out from the authFlag and the privFlag bits of the msgFlags component, like this πŸ”₯:

a) If the authFlag is not set and the privFlag is not set, then securityLevel is set to noAuthNoPriv.

b) If the authFlag is set and the privFlag is not set, then securityLevel is set to authNoPriv.

c) If the authFlag is set and the privFlag is set, then securityLevel is set to authPriv.

d) If the authFlag is not set and privFlag is set, then the snmpInvalidMsgs counter gets incremented, a Report PDU is generated, the message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. the privacy-without-auth combo is a no-go πŸ’€

6) The security module that implements the Security Model named by the securityModel component gets called for authentication and privacy services. this is done with this abstract service primitive πŸ”:

statusInformation =            -- errorIndication or success
                               -- error counter OID and
                               -- value if error
  processIncomingMsg(
  IN  messageProcessingModel   -- SNMPv3 Message Processing Model
  IN  expectResponse           -- TRUE or FALSE
  IN  maxMessageSize           -- of the sending SNMP entity
  IN  securityParameters       -- for the received message
  IN  securityModel            -- for the received message
  IN  securityLevel            -- Level of Security
  IN  wholeMsg                 -- as received on the wire
  IN  wholeMsgLength           -- length as received on the wire
  OUT securityEngineID         -- authoritative SNMP entity
  OUT securityName             -- identification of the principal
  OUT scopedPDU,               -- message (plaintext) payload
  OUT maxSizeResponseScopedPDU -- maximum size of Response PDU
  OUT securityStateReference   -- reference to security state
  )                            -- information, needed for
                               -- response

If an errorIndication comes back from the security module, then:

a) If statusInformation contains values for an OID/value pair, then a Report PDU is generated.

1) If the scopedPDU has been returned from ProcessIncomingMsg, then determine contextEngineID, contextName, and PDU.

2) Information about the message gets cached and a stateReference is created (this part is implementation-specific 🧠). The info to cache includes the values of:

msgVersion,
msgID,
securityLevel,
msgFlags,
msgMaxSize,
securityModel,
maxSizeResponseScopedPDU,
securityStateReference

3) A Report-PDU gets requested to be prepared and sent, according to this abstract service primitive πŸ“€:

result =                     -- SUCCESS or FAILURE
returnResponsePDU(
IN  messageProcessingModel   -- SNMPv3(3)
IN  securityModel            -- same as on incoming request
IN  securityName             -- from ProcessIncomingMsg
IN  securityLevel            -- same as on incoming request
IN  contextEngineID          -- from step 6 a) 1)
IN  contextName              -- from step 6 a) 1)
IN  pduVersion               -- SNMPv2-PDU
IN  PDU                      -- from step 6 a) 1)
IN  maxSizeResponseScopedPDU -- from ProcessIncomingMsg
IN  stateReference           -- from step 6 a) 2)
IN  statusInformation        -- from ProcessIncomingMsg
OUT transportDomain          -- destination's transport
                             -- domain
OUT transportAddress         -- destination's transport
                             -- address
OUT outgoingMessage          -- the message to send
OUT outgoingMessageLength    -- the length of the message
)

b) The incoming message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. ghosted πŸ‘»

7) The scopedPDU gets parsed to pull out the contextEngineID, the contextName and the PDU. If any parse error happens, then the snmpInASNParseErrs counter [RFC1907] gets incremented, the security state information is discarded, the message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. parse errors are so not it 😭

8) The pduVersion is set to an SNMPv2-PDU. πŸŽ€

9) The pduType is determined, in an implementation-dependent manner, to be one of these:

  • a GetRequest-PDU,
  • a GetNextRequest-PDU,
  • a GetBulkRequest-PDU,
  • a SetRequest-PDU,
  • an InformRequest-PDU,
  • an SNMPv2-Trap-PDU,
  • a Response-PDU, or
  • a Report-PDU.

10) If the pduType is a Response-PDU or Report-PDU, then:

a) The value of the msgID component is used to find the cached information for a corresponding outstanding Request message. If no such outstanding Request message is found, then the security state information is discarded, the message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. no matching request, no entry πŸšͺ

b) sendPduHandle is retrieved from the cached information.

Otherwise, sendPduHandle is set to <none>, an implementation defined value. 🌸

11) If the pduType is a Report-PDU, then:

a) statusInformation is created using the contents of the Report-PDU, in an implementation-dependent manner. This statusInformation will be forwarded to the application associated with the sendPduHandle. πŸ“¬

b) Any cached information about the outstanding Request message gets discarded.

c) The security state information for this incoming message gets discarded.

d) stateReference is set to <none>.

e) A SUCCESS result is returned. SNMPv3 Message Processing is complete. report received, we move 🫢

12) If the pduType is a Response-PDU, then:

a) The cached data for the outstanding request, referred to by stateReference, gets retrieved, including:

  • snmpEngineID
  • securityModel
  • securityName
  • securityLevel
  • contextEngineID
  • contextName

b) If the values extracted from the incoming message differ from the cached data, then the security state information is discarded, any cached information about the outstanding Request message is discarded, the incoming message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. mismatch?? that's a no-go πŸ™…β€β™€οΈ

c) Otherwise, any cached information about the outstanding Request message is discarded, and stateReference is set to <none>.

d) A SUCCESS result is returned. SNMPv3 Message Processing is complete. ✨

13) If the pduType is a GetRequest-PDU, GetNextRequest-PDU, GetBulkRequest-PDU, SetRequest-PDU, or InformRequest-PDU, then:

a) If the value of securityEngineID is not equal to the value of snmpEngineID, then the security state information is discarded, any cached information about the outstanding Request message is discarded, the incoming message is discarded without further processing, and a FAILURE result is returned. SNMPv3 Message Processing is complete. wrong engine, not my problem πŸ™ˆ

b) Information about the message gets cached and a stateReference is created (implementation-specific). The info to cache includes the values of:

msgVersion,
msgID,
securityLevel,
msgFlags,
msgMaxSize,
securityModel,
maxSizeResponseScopedPDU,
securityStateReference

c) A SUCCESS result is returned. SNMPv3 Message Processing is complete. request approved, we're cooking 🍳

14) If the pduType is an SNMPv2-Trap-PDU, then A SUCCESS result is returned. SNMPv3 Message Processing is complete. traps just vibe and we're done πŸ¦‹

8. Intellectual Property ✨

The IETF takes no position on whether any intellectual property or other rights that might be claimed to apply to the implementation or use of the technology in this document are valid or in scope, or on whether any license under those rights might or might not be available. It also doesn't claim to have tried to find any of those rights. Info on the IETF's procedures for rights in standards-track and standards-related docs is in BCP-11 πŸ’…. Copies of rights claims made available for publication, any assurances of licenses that will be made available, or the result of an attempt to get a general license or permission for implementers or users to use these proprietary rights can all be obtained from the IETF Secretariat πŸ“¬.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights which may cover technology that may be required to practice this standard. Send that info to the IETF Executive Director πŸ¦‹.

9. Acknowledgements 🫢

This document is the result of the efforts of the SNMPv3 Working Group, and we owe some seriously special thanks to these SNMPv3 WG members πŸ’œ:

  • Dave Battle (SNMP Research, Inc.)
  • Uri Blumenthal (IBM T.J. Watson Research Center)
  • Jeff Case (SNMP Research, Inc.)
  • John Curran (BBN)
  • T. Max Devlin (Hi-TECH Connections)
  • John Flick (Hewlett Packard)
  • David Harrington (Cabletron Systems Inc.)
  • N.C. Hien (IBM T.J. Watson Research Center)
  • Dave Levi (SNMP Research, Inc.)
  • Louis A Mamakos (UUNET Technologies Inc.)
  • Paul Meyer (Secure Computing Corporation)
  • Keith McCloghrie (Cisco Systems)
  • Russ Mundy (Trusted Information Systems, Inc.)
  • Bob Natale (ACE*COMM Corporation)
  • Mike O'Dell (UUNET Technologies Inc.)
  • Dave Perkins (DeskTalk)
  • Peter Polkinghorne (Brunel University)
  • Randy Presuhn (BMC Software, Inc.)
  • David Reid (SNMP Research, Inc.)
  • Shawn Routhier (Epilogue)
  • Juergen Schoenwaelder (TU Braunschweig)
  • Bob Stewart (Cisco Systems)
  • Bert Wijnen (IBM T.J. Watson Research Center)

The document is based on recommendations from the IETF Security and Administrative Framework Evolution for SNMP Advisory Team 🧚. The members of that Advisory Team were:

  • David Harrington (Cabletron Systems Inc.)
  • Jeff Johnson (Cisco Systems)
  • David Levi (SNMP Research Inc.)
  • John Linn (Openvision)
  • Russ Mundy (Trusted Information Systems) chair
  • Shawn Routhier (Epilogue)
  • Glenn Waters (Nortel)
  • Bert Wijnen (IBM T. J. Watson Research Center)

As recommended by the Advisory Team and the SNMPv3 Working Group Charter, the design pulls in as much as is practical from previous RFCs and drafts πŸ“. That means we're super grateful to the authors of the earlier designs known as SNMPv2u and SNMPv2*:

  • Jeff Case (SNMP Research, Inc.)
  • David Harrington (Cabletron Systems Inc.)
  • David Levi (SNMP Research, Inc.)
  • Keith McCloghrie (Cisco Systems)
  • Brian O'Keefe (Hewlett Packard)
  • Marshall T. Rose (Dover Beach Consulting)
  • Jon Saperia (BGS Systems Inc.)
  • Steve Waldbusser (International Network Services)
  • Glenn W. Waters (Bell-Northern Research Ltd.)

10. Security Considerations πŸ”

⚠️ Okay bestie, this section is SERIOUS. Security is not the place to vibe-check, so read every word πŸ’€.

The Dispatcher coordinates the processing of messages to provide a level of security for management messages and to direct the SNMP PDUs to the proper SNMP application(s) πŸ›‘οΈ.

A Message Processing Model, and in particular the V3MP defined in this document, interacts as part of the Message Processing with Security Models in the Security Subsystem via the abstract service interface primitives defined in [RFC2261] and elaborated above πŸ”—.

The level of security actually provided is mainly decided by the specific Security Model implementation(s) and the specific SNMP application implementation(s) plugged into this framework. Applications have access to data which is not secured 😬. Applications should take reasonable steps to protect the data from disclosure. When they send data across the network, they should obey the securityLevel and call upon the services of an Access Control Model as they apply access control πŸ”’.

The values for the msgID element used in communication between SNMP entities must be chosen to avoid replay attacks 🚫. The values do not need to be unpredictable; it is sufficient that they not repeat ✨.

11. References πŸ“š

[RFC1901] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Introduction to Community-based SNMPv2", RFC 1901, January 1996.

[RFC1902] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Structure of Management Information for Version 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1902, January 1996.

[RFC1905] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Protocol Operations for Version 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1905, January 1996.

[RFC1906] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Transport Mappings for Version 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1906, January 1996.

[RFC1907] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Management Information Base for Version 2 of the Simple Network Management Protocol (SNMPv2)", RFC 1907 January 1996.

[RFC1908] Case, J., McCloghrie, K., Rose, M., and S. Waldbusser, "Coexistence between Version 1 and Version 2 of the Internet-standard Network Management Framework", RFC 1908, January 1996.

[RFC 2028] Hovey, R., and S. Bradner, "The Organizations Involved in the IETF Standards Process", BCP 11, RFC 2028, October 1996.

[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", RFC 2119, BCP 14, March 1997.

[RFC2261] Harrington, D., Presuhn, R., and B. Wijnen, "An Architecture for describing SNMP Management Frameworks", RFC 2261, January 1998.

[RFC2264] Blumenthal, U., and B. Wijnen, "The User-Based Security Model for Version 3 of the Simple Network Management Protocol (SNMPv3)", RFC 2264, January 1998.

[RFC2265] Wijnen, B., Presuhn, R., and K. McCloghrie, "View-based Access Control Model for the Simple Network Management Protocol (SNMP)", RFC 2265, January 1998.

[RFC2263] Levi, D., Meyer, P., and B. Stewart, "SNMPv3 Applications", RFC 2263, January 1998.

12. Editors' Addresses πŸŽ€

Jeffrey Case
SNMP Research, Inc.
3001 Kimberlin Heights Road
Knoxville, TN 37920-9716
USA

Phone:     +1 423-573-1434
EMail:     case@snmp.com


Dave Harrington
Cabletron Systems, Inc
Post Office Box 5005
Mail Stop: Durham
35 Industrial Way
Rochester, NH 03867-5005
USA

Phone:      +1 603-337-7357
EMail:      dbh@ctron.com


Randy Presuhn
BMC Software, Inc.
1190 Saratoga Avenue
Suite 130
San Jose, CA 95129
USA

Phone:      +1 408-556-0720
EMail:      rpresuhn@bmc.com


Bert Wijnen
IBM T. J. Watson Research
Schagen 33
3461 GL Linschoten
Netherlands

Phone:      +31 348-432-794
EMail:      wijnen@vnet.ibm.com

Copyright (C) The Internet Society (1997). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English 🌸.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns πŸ’–.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE πŸ¦‹βœ¨.

πŸ“¦ where this page comes from