RFC 1903

Textual Conventions for Version 2 of the Simple Network Management Protocol (SNMPv2)

πŸ“… published January 1996, from ietf

Textual Conventions for Version 2 of the Simple Network Management Protocol (SNMPv2) πŸŽ€

Okay bestie, this is RFC 1903 πŸ¦‹, and it's all about textual conventions for SNMPv2. It was published in January 1996 by the SNMPv2 Working Group of the Network Working Group πŸ’–. The four authors are J. Case from SNMP Research, Inc., K. McCloghrie from Cisco Systems, Inc., M. Rose from Dover Beach Consulting, Inc., and S. Waldbusser from International Network Services. It's on the Standards Track πŸ”₯, and it obsoletes RFC 1443 πŸ’…. It doesn't update any other RFC.


Status of This Memo πŸ“œ

So this doc is an Internet standards track protocol for the Internet community, and it's literally asking for discussion and suggestions for improvements πŸ’¬. If you want to know where this protocol stands in standardization, check the "Internet Official Protocol Standards" (STD 1) for the current edition 🧐. Distribution of this memo is unlimited 🌈.

Table of Contents πŸ—‚οΈ

1. Introduction ................................................    1
1.1 A Note on Terminology ......................................    2
2. Definitions .................................................    3
3. Mapping of the TEXTUAL-CONVENTION macro .....................   19
3.1 Mapping of the DISPLAY-HINT clause .........................   19
3.2 Mapping of the STATUS clause ...............................   21
3.3 Mapping of the DESCRIPTION clause ..........................   21
3.4 Mapping of the REFERENCE clause ............................   21
3.5 Mapping of the SYNTAX clause ...............................   22
4. Security Considerations .....................................   22
5. Editor's Address ............................................   22
6. Acknowledgements ............................................   22
7. References ..................................................   23

1. Introduction ✨

Let's set the scene 🎬. A management system has a few parts. First there are several (potentially many) nodes, and each one has a processing entity called an agent, which can get to the management instrumentation πŸ› οΈ. Then there's at least one management station, plus a management protocol that carries management information back and forth between the agents and the stations πŸ“‘. All of this runs under an administrative framework that decides how authentication, authorization, access control, and privacy work πŸ”.

Management stations run management applications that watch over and control managed elements. Managed elements are things like hosts, routers, terminal servers, and so on, and you monitor and control them by getting at their management information πŸ‘€.

The management information is treated as a bunch of managed objects living in a virtual information store called the Management Information Base (MIB) πŸ—ƒοΈ. Related objects get grouped together into MIB modules. Those modules are written in a subset of OSI's Abstract Syntax Notation One (ASN.1) [1], and that subset is called the Structure of Management Information (SMI) [2] 🧩.

Sometimes when you're writing a MIB module, you want to make brand new types that look a lot like the ones the SMI already has πŸ’­. Compared to an SMI type, these new ones have a different name and a similar syntax, but a more precise meaning. They're called textual conventions, and they exist mostly so that humans reading the MIB module can understand it easier πŸ“–. The whole point of this document is to define the first set of textual conventions that every MIB module can use πŸŽ‰.

Objects defined with a textual convention are always encoded using the rules for their primitive type πŸ”’. But textual conventions often come with extra special meaning, so there's an ASN.1 macro, TEXTUAL-CONVENTION, that quickly describes both the syntax and the semantics of a textual convention πŸͺ„.

Here are the naming rules. For every textual convention in an information module, the name has to be unique and mnemonic, and it can't be more than 64 characters long. (Names longer than 32 characters are not recommended, though πŸ™ˆ.) Every name used for a textual convention in all "standard" information modules has to be unique too πŸ’œ.

1.1. A Note on Terminology πŸ“š

For the sake of explaining things, the original Internet-standard Network Management Framework, described in RFCs 1155 (STD 16), 1157 (STD 15), and 1212 (STD 16), gets called the SNMP version 1 framework (SNMPv1) πŸ•°οΈ. The current framework is called the SNMP version 2 framework (SNMPv2) ✨.


2. Definitions πŸ“

Here's the actual module, so copy it exactly, babe πŸ’…:

SNMPv2-TC DEFINITIONS ::= BEGIN

IMPORTS
    ObjectSyntax, TimeTicks
        FROM SNMPv2-SMI;


-- definition of textual conventions

TEXTUAL-CONVENTION MACRO ::=
BEGIN
    TYPE NOTATION ::=
                  DisplayPart
                  "STATUS" Status
                  "DESCRIPTION" Text
                  ReferPart
                  "SYNTAX" Syntax

    VALUE NOTATION ::=
                  value(VALUE Syntax)

    DisplayPart ::=
                  "DISPLAY-HINT" Text
                | empty

    Status ::=
                  "current"
                | "deprecated"
                | "obsolete"

    ReferPart ::=
                  "REFERENCE" Text
                | empty

    -- uses the NVT ASCII character set
    Text ::= """" string """"

    Syntax ::=
                  type(ObjectSyntax)
                | "BITS" "{" Kibbles "}"
    Kibbles ::=
                  Kibble
                | Kibbles "," Kibble
    Kibble ::=
                  identifier "(" nonNegativeNumber ")"

END


DisplayString ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "255a"
    STATUS       current
    DESCRIPTION
            "Represents textual information taken from the NVT ASCII
            character set, as defined in pages 4, 10-11 of RFC 854.

            To summarize RFC 854, the NVT ASCII repertoire specifies:

              - the use of character codes 0-127 (decimal)

              - the graphics characters (32-126) are interpreted as
                US ASCII

              - NUL, LF, CR, BEL, BS, HT, VT and FF have the special
                meanings specified in RFC 854

              - the other 25 codes have no standard interpretation

              - the sequence 'CR LF' means newline

              - the sequence 'CR NUL' means carriage-return

              - an 'LF' not preceded by a 'CR' means moving to the
                same column on the next line.

              - the sequence 'CR x' for any x other than LF or NUL is
                illegal.  (Note that this also means that a string may
                end with either 'CR LF' or 'CR NUL', but not with CR.)

            Any object defined using this syntax may not exceed 255
            characters in length."
    SYNTAX       OCTET STRING (SIZE (0..255))


PhysAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "1x:"
    STATUS       current
    DESCRIPTION
            "Represents media- or physical-level addresses."
    SYNTAX       OCTET STRING


MacAddress ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "1x:"
    STATUS       current
    DESCRIPTION
            "Represents an 802 MAC address represented in the
            `canonical' order defined by IEEE 802.1a, i.e., as if it
            were transmitted least significant bit first, even though
            802.5 (in contrast to other 802.x protocols) requires MAC
            addresses to be transmitted most significant bit first."
    SYNTAX       OCTET STRING (SIZE (6))


TruthValue ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents a boolean value."
    SYNTAX       INTEGER { true(1), false(2) }

TestAndIncr ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents integer-valued information used for atomic
            operations.  When the management protocol is used to specify
            that an object instance having this syntax is to be
            modified, the new value supplied via the management protocol
            must precisely match the value presently held by the
            instance.  If not, the management protocol set operation
            fails with an error of `inconsistentValue'.  Otherwise, if
            the current value is the maximum value of 2^31-1 (2147483647
            decimal), then the value held by the instance is wrapped to
            zero; otherwise, the value held by the instance is
            incremented by one.  (Note that regardless of whether the
            management protocol set operation succeeds, the variable-
            binding in the request and response PDUs are identical.)

            The value of the ACCESS clause for objects having this
            syntax is either `read-write' or `read-create'.  When an
            instance of a columnar object having this syntax is created,
            any value may be supplied via the management protocol.

            When the network management portion of the system is re-
            initialized, the value of every object instance having this
            syntax must either be incremented from its value prior to
            the re-initialization, or (if the value prior to the re-
            initialization is unknown) be set to a pseudo-randomly
            generated value."
    SYNTAX       INTEGER (0..2147483647)


AutonomousType ::= TEXTUAL-CONVENTION

    STATUS       current
    DESCRIPTION
            "Represents an independently extensible type identification
            value.  It may, for example, indicate a particular sub-tree
            with further MIB definitions, or define a particular type of
            protocol or hardware."
    SYNTAX       OBJECT IDENTIFIER


InstancePointer ::= TEXTUAL-CONVENTION
    STATUS       obsolete
    DESCRIPTION
            "A pointer to either a specific instance of a MIB object or
            a conceptual row of a MIB table in the managed device.  In
            the latter case, by convention, it is the name of the
            particular instance of the first accessible columnar object
            in the conceptual row.

            The two uses of this textual convention are replaced by
            VariablePointer and RowPointer, respectively."
    SYNTAX       OBJECT IDENTIFIER


VariablePointer ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "A pointer to a specific object instance.  For example,
            sysContact.0 or ifInOctets.3."
    SYNTAX       OBJECT IDENTIFIER


RowPointer ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Represents a pointer to a conceptual row.  The value is the
            name of the instance of the first accessible columnar object
            in the conceptual row.

            For example, ifIndex.3 would point to the 3rd row in the
            ifTable (note that if ifIndex were not-accessible, then
            ifDescr.3 would be used instead)."
    SYNTAX       OBJECT IDENTIFIER

Okay so RowStatus is literally the boss of conceptual rows πŸ’… It's the textual convention that manages creating and deleting them, and it's the value for the status column of a row. Here's the full definition, exactly as written, so you can see every detail πŸŽ€

RowStatus ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "The RowStatus textual convention is used to manage the
            creation and deletion of conceptual rows, and is used as the
            value of the SYNTAX clause for the status column of a
            conceptual row (as described in Section 7.7.1 of [2].)

            The status column has six defined values:

                 - `active', which indicates that the conceptual row is
                 available for use by the managed device;

                 - `notInService', which indicates that the conceptual
                 row exists in the agent, but is unavailable for use by
                 the managed device (see NOTE below);

                 - `notReady', which indicates that the conceptual row
                 exists in the agent, but is missing information
                 necessary in order to be available for use by the
                 managed device;

                 - `createAndGo', which is supplied by a management
                 station wishing to create a new instance of a
                 conceptual row and to have its status automatically set
                 to active, making it available for use by the managed
                 device;

                 - `createAndWait', which is supplied by a management
                 station wishing to create a new instance of a
                 conceptual row (but not make it available for use by
                 the managed device); and,

                 - `destroy', which is supplied by a management station
                 wishing to delete all of the instances associated with
                 an existing conceptual row.

            Whereas five of the six values (all except `notReady') may
            be specified in a management protocol set operation, only
            three values will be returned in response to a management
            protocol retrieval operation:  `notReady', `notInService' or
            `active'.  That is, when queried, an existing conceptual row
            has only three states:  it is either available for use by
            the managed device (the status column has value `active');
            it is not available for use by the managed device, though
            the agent has sufficient information to make it so (the
            status column has value `notInService'); or, it is not
            available for use by the managed device, and an attempt to
            make it so would fail because the agent has insufficient
            information (the state column has value `notReady').

                                     NOTE WELL

                 This textual convention may be used for a MIB table,
                 irrespective of whether the values of that table's
                 conceptual rows are able to be modified while it is
                 active, or whether its conceptual rows must be taken
                 out of service in order to be modified.  That is, it is
                 the responsibility of the DESCRIPTION clause of the
                 status column to specify whether the status column must
                 not be `active' in order for the value of some other
                 column of the same conceptual row to be modified.  If
                 such a specification is made, affected columns may be
                 changed by an SNMP set PDU if the RowStatus would not
                 be equal to `active' either immediately before or after
                 processing the PDU.  In other words, if the PDU also
                 contained a varbind that would change the RowStatus
                 value, the column in question may be changed if the
                 RowStatus was not equal to `active' as the PDU was
                 received, or if the varbind sets the status to a value
                 other than 'active'.


            Also note that whenever any elements of a row exist, the
            RowStatus column must also exist.

            To summarize the effect of having a conceptual row with a
            status column having a SYNTAX clause value of RowStatus,
            consider the following state diagram:


                                         STATE
              +--------------+-----------+-------------+-------------
              |      A       |     B     |      C      |      D
              |              |status col.|status column|
              |status column |    is     |      is     |status column
    ACTION    |does not exist|  notReady | notInService|  is active
--------------+--------------+-----------+-------------+-------------
set status    |noError    ->D|inconsist- |inconsistent-|inconsistent-
column to     |       or     |   entValue|        Value|        Value
createAndGo   |inconsistent- |           |             |
              |         Value|           |             |
--------------+--------------+-----------+-------------+-------------
set status    |noError  see 1|inconsist- |inconsistent-|inconsistent-
column to     |       or     |   entValue|        Value|        Value
createAndWait |wrongValue    |           |             |
--------------+--------------+-----------+-------------+-------------
set status    |inconsistent- |inconsist- |noError      |noError
column to     |         Value|   entValue|             |
active        |              |           |             |
              |              |     or    |             |
              |              |           |             |
              |              |see 2   ->D|          ->D|          ->D
--------------+--------------+-----------+-------------+-------------
set status    |inconsistent- |inconsist- |noError      |noError   ->C
column to     |         Value|   entValue|             |
notInService  |              |           |             |
              |              |     or    |             |      or
              |              |           |             |
              |              |see 3   ->C|          ->C|wrongValue
--------------+--------------+-----------+-------------+-------------
set status    |noError       |noError    |noError      |noError
column to     |              |           |             |
destroy       |           ->A|        ->A|          ->A|          ->A
--------------+--------------+-----------+-------------+-------------
set any other |see 4         |noError    |noError      |see 5
column to some|              |           |             |
value         |              |      see 1|          ->C|          ->D
--------------+--------------+-----------+-------------+-------------

            (1) goto B or C, depending on information available to the
            agent.

            (2) if other variable bindings included in the same PDU,
            provide values for all columns which are missing but
            required, then return noError and goto D.

            (3) if other variable bindings included in the same PDU,
            provide values for all columns which are missing but
            required, then return noError and goto C.

            (4) at the discretion of the agent, the return value may be
            either:

                 inconsistentName:  because the agent does not choose to
                 create such an instance when the corresponding
                 RowStatus instance does not exist, or

                 inconsistentValue:  if the supplied value is
                 inconsistent with the state of some other MIB object's
                 value, or

                 noError: because the agent chooses to create the
                 instance.

            If noError is returned, then the instance of the status
            column must also be created, and the new state is B or C,
            depending on the information available to the agent.  If
            inconsistentName or inconsistentValue is returned, the row
            remains in state A.

            (5) depending on the MIB definition for the column/table,
            either noError or inconsistentValue may be returned.

            NOTE: Other processing of the set request may result in a
            response other than noError being returned, e.g.,
            wrongValue, noCreation, etc.

Conceptual Row Creation πŸŽ€

okay so creating a conceptual row is a whole process, bestie πŸ¦‹ There are four potential interactions: picking an instance-identifier that isn't in use yet, creating the conceptual row, filling in any objects the agent doesn't supply a default for, and finally making the row available for use by the managed device ✨

Interaction 1: Selecting an Instance-Identifier

the way the algorithm works changes for every conceptual row 🌸 Sometimes the instance-identifier actually means something, like the destination address of a route, so the management station picks it based on what it means 🧚

Other times the instance-identifier is just there to tell rows apart, and a management station that doesn't know much about the row might look at the instances that already exist to find an unused one. That approach can work, but it's often highly sub-optimal πŸ™ˆ It's also a questionable practice for a naive management station to try creating a row at all πŸ’€

The MIB module that defines the row might also give you one or more objects that help pick an unused instance-identifier. For example, if the row is indexed by an integer-value, the MIB could define an object with an integer-valued SYNTAX clause for exactly this, so a management station can do a management protocol retrieval on it. To avoid unnecessary collisions between competing management stations, `adjacent' retrievals of this object should be different πŸ’œ

Finally, the management station could pick a pseudo-random number to use as the index. If that index was already in use and an inconsistentValue came back from the management protocol set operation, the station should simply pick a new pseudo-random number and retry πŸ”₯

A MIB designer should choose between the two latter algorithms based on the size of the table, since that's what decides how efficient each one is πŸ‘‘ For tables where a large number of entries is expected, it is recommended that a MIB object be defined that returns an acceptable index for creation. For tables with small numbers of entries, it is recommended that the latter pseudo-random index mechanism be used πŸ“

Interaction 2: Creating the Conceptual Row

once an unused instance-identifier has been selected, the management station figures out whether it wants to create and activate the conceptual row in one transaction, or in a negotiated set of interactions 🫢

Interaction 2a: Creating and Activating the Conceptual Row ✨

The management station has to work out the column requirements first πŸ’…. That means it MUST determine which columns it MUST provide values for and which it MUST NOT provide values for 🧠. Depending on how complicated the table is and how much the management station already knows about the agent, it can figure this out locally 🌸. The other option is to send a management protocol get operation to examine every column in the conceptual row it wants to create. For each column there are three possible outcomes, so pay attention bestie πŸ‘€:

  • A value comes back, which means some other management station already created this conceptual row. We go back to interaction 1 πŸ”
  • The exception noSuchInstance comes back. This means the agent implements the object-type for this column, and this column would be accessible in the MIB view used by the retrieval in at least one conceptual row if the row existed. For the columns the agent gives read-create access to, noSuchInstance tells the management station to supply a value for this column when the conceptual row gets created πŸŽ€
  • The exception noSuchObject comes back. This means the agent doesn't implement the object-type for this column, OR there's no conceptual row where this column would be accessible in the MIB view used by the retrieval. So the management station can NOT issue any management protocol set operations to create an instance of this column πŸ’€

Once the column requirements are sorted, a management protocol set operation gets issued to match them. This operation also sets the new instance of the status column to createAndGo ✨

When the agent processes that set operation, it checks whether it has enough information to make the conceptual row usable by the managed device πŸ” The agent gets its information from two places: the management protocol set operation that creates the row, and implementation-specific defaults the agent supplies. (Note that an agent MUST provide implementation-specific defaults for at least the objects it implements as read-only 🫢.) If there's enough information, the conceptual row gets created, a noError response comes back, the status column is set to active, and nothing else is needed. Interactions 3 and 4 are skipped, no cap πŸ¦‹ If there's NOT enough information, the conceptual row is not created and the set operation fails with an error of inconsistentValue 😭 On that error, the management station can issue a management protocol retrieval operation to find out whether it just forgot to specify a value for a required column, or whether the selected instance of the status column already existed. If it's the second case, we go back to interaction 1. If it's the first case, the management station can re-issue the set operation with the extra information, or start interaction 2 again using createAndWait to negotiate creating the conceptual row 🌈

NOTE WELL πŸ“£ No matter how the column requirements were figured out, the management station might decide a column is necessary when the agent actually won't let that particular columnar instance be created or written. In that case the management protocol set operation fails with an error like noCreation or notWritable. Then the management station decides whether it really needs to set a value for that columnar instance. If it doesn't, it re-issues the management protocol set operation WITHOUT setting a value for that columnar instance. Otherwise, the management station aborts the row creation algorithm πŸ™ˆ

Interaction 2b: Negotiating the Creation of the Conceptual Row

The management station issues a management protocol set operation that sets the desired instance of the status column to createAndWait 🧚 If the agent refuses to process a request like this, the set operation fails with an error of wrongValue. (So as a consequence, such an agent MUST be prepared to accept a single management protocol set operation, which is interaction 2a above, containing ALL of the columns in its column requirements πŸ’œ.) Otherwise, the conceptual row gets created, a noError response comes back, and the status column is immediately set to either notInService or notReady. Which one depends on whether the agent has enough information to make the row usable by the managed device. If there's enough information, the status column is set to notInService. If there's NOT enough information, the status column is set to notReady. Either way, we move on to interaction 3 ⭐

Interaction 3: Initializing non-defaulted Objects

The management station MUST now determine the column requirements πŸ“‹ It issues a management protocol get operation to examine all the columns in the created conceptual row. For each column in the response there are three possible outcomes:

  • A value is returned, which means the agent implements the object-type for this column AND had enough information to provide a value. For the columns the agent gives read-create access to (and whose values the agent lets you change after creation), a returned value tells the management station that it MAY issue additional management protocol set operations, if it wants, to change the value of this column πŸ¦‹
  • The exception noSuchInstance is returned. This means the agent implements the object-type for this column, and this column would be accessible in the MIB view used by the retrieval in at least one conceptual row if the row existed. BUT the agent doesn't have enough info to provide a value, and until a value is provided, the conceptual row may NOT be made available for use by the managed device πŸ₯Ί For the columns the agent gives read-create access to, noSuchInstance tells the management station that it MUST issue additional management protocol set operations to provide a value for this column πŸ”§
  • The exception noSuchObject is returned. This means the agent doesn't implement the object-type for this column, OR there's no conceptual row where this column would be accessible in the MIB view used by the retrieval. So the management station can NOT issue any management protocol set operations to create an instance of this column πŸ™…β€β™€οΈ

If the value of the status column is notReady, the management station MUST first deal with all of the noSuchInstance columns, if there are any 🧩 Once that's done, the status column becomes notInService, and we move on to interaction 4 πŸš€

Interaction 4: Making the Conceptual Row Available

Once the management station is happy with the values of the columns in the conceptual row, it issues a management protocol set operation to set the status column to active πŸŽ‰ If the agent has enough information to make the conceptual row usable by the managed device, the set operation succeeds and a noError response comes back. Otherwise, the set operation fails with an error of inconsistentValue 😀

NOTE WELL πŸ‘€ A conceptual row whose status column is notInService or notReady is unavailable to the managed device. So it's possible for the managed device to create its own instances between the management protocol set operation that sets the status column to createAndWait and the one that sets it to active. In that case, when the set operation setting the status column to active is issued, the values held in the agent SUPERSEDE the ones the managed device used πŸ’…

If the management station gets stuck and can't set the status column to active (for example, because of a management station or network failure), the conceptual row gets left in the notInService or notReady state and keeps eating up resources forever πŸ’€ The agent MUST detect conceptual rows that have been in either of those states for an abnormally long time, and remove them 🧹 It's the job of the DESCRIPTION clause of the status column to say what an abnormally long time actually is. That period SHOULD be long enough to allow for human response time (including think time) between creating the conceptual row and setting the status to active ⏳ If the DESCRIPTION clause doesn't provide that info, it is suggested that this period be approximately 5 minutes long πŸ“ This removal action applies not only to newly-created rows, but also to previously active rows that get set to, and left in, the notInService state for a prolonged period longer than what's considered normal for that kind of conceptual row 🌸

Conceptual Row Suspension

            When a conceptual row is `active', the management station
            may issue a management protocol set operation which sets the
            instance of the status column to `notInService'.  If the
            agent is unwilling to do so, the set operation fails with an
            error of `wrongValue'.  Otherwise, the conceptual row is
            taken out of service, and a `noError' response is returned.
            It is the responsibility of the DESCRIPTION clause of the
            status column to indicate under what circumstances the
            status column should be taken out of service (e.g., in order
            for the value of some other column of the same conceptual
            row to be modified).


                              Conceptual Row Deletion

            For deletion of conceptual rows, a management protocol set
            operation is issued which sets the instance of the status
            column to `destroy'.  This request may be made regardless of
            the current value of the status column (e.g., it is possible
            to delete conceptual rows which are either `notReady',
            `notInService' or `active'.)  If the operation succeeds,
            then all instances associated with the conceptual row are
            immediately removed."


    SYNTAX       INTEGER {
                     -- the following two values are states:
                     -- these values may be read or written
                     active(1),
                     notInService(2),
                     -- the following value is a state:
                     -- this value may be read, but not written
                     notReady(3),

                     -- the following three values are
                     -- actions: these values may be written,
                     --   but are never read
                     createAndGo(4),
                     createAndWait(5),
                     destroy(6)
                 }


TimeStamp ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "The value of the sysUpTime object at which a specific
            occurrence happened.  The specific occurrence must be
            defined in the description of any object defined using this
            type."
    SYNTAX       TimeTicks


TimeInterval ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "A period of time, measured in units of 0.01 seconds."
    SYNTAX       INTEGER (0..2147483647)


DateAndTime ::= TEXTUAL-CONVENTION
    DISPLAY-HINT "2d-1d-1d,1d:1d:1d.1d,1a1d:1d"
    STATUS       current
    DESCRIPTION
            "A date-time specification.

            field  octets  contents                  range
            -----  ------  --------                  -----
              1      1-2   year                      0..65536
              2       3    month                     1..12
              3       4    day                       1..31
              4       5    hour                      0..23
              5       6    minutes                   0..59
              6       7    seconds                   0..60
                           (use 60 for leap-second)
              7       8    deci-seconds              0..9
              8       9    direction from UTC        '+' / '-'
              9      10    hours from UTC            0..11

             10      11    minutes from UTC          0..59

            For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
            displayed as:

                             1992-5-26,13:30:15.0,-4:0

            Note that if only local time is known, then timezone
            information (fields 8-10) is not present."
    SYNTAX       OCTET STRING (SIZE (8 | 11))


StorageType ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
            "Describes the memory realization of a conceptual row.  A
            row which is volatile(2) is lost upon reboot.  A row which
            is either nonVolatile(3), permanent(4) or readOnly(5), is
            backed up by stable storage.  A row which is permanent(4)
            can be changed but not deleted.  A row which is readOnly(5)
            cannot be changed nor deleted.

            If the value of an object with this syntax is either
            permanent(4) or readOnly(5), it cannot be modified.
            Conversely, if the value is either other(1), volatile(2) or
            nonVolatile(3), it cannot be modified to be permanent(4) or
            readOnly(5).

            Every usage of this textual convention is required to
            specify the columnar objects which a permanent(4) row must
            at a minimum allow to be writable."
    SYNTAX       INTEGER {
                     other(1),       -- eh?
                     volatile(2),    -- e.g., in RAM
                     nonVolatile(3), -- e.g., in NVRAM
                     permanent(4),   -- e.g., partially in ROM
                     readOnly(5)     -- e.g., completely in ROM
                 }


TDomain ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
          "Denotes a kind of transport service.

          Some possible values, such as snmpUDPDomain, are defined in
          'Transport Mappings for Version 2 of the Simple Network
          Management Protocol (SNMPv2)'."

    SYNTAX       OBJECT IDENTIFIER


TAddress ::= TEXTUAL-CONVENTION
    STATUS       current
    DESCRIPTION
          "Denotes a transport service address.

          For snmpUDPDomain, a TAddress is 6 octets long, the initial 4
          octets containing the IP-address in network-byte order and the
          last 2 containing the UDP port in network-byte order.  Consult
          'Transport Mappings for Version 2 of the Simple Network
          Management Protocol (SNMPv2)' for further information on
          snmpUDPDomain."
    SYNTAX       OCTET STRING (SIZE (1..255))


END

3. Mapping of the TEXTUAL-CONVENTION macro ✨

The TEXTUAL-CONVENTION macro is the thing that carries the syntax and semantics of a textual convention, bestie πŸ’– It should be noted that expanding the macro is something that happens conceptually during implementation, not at run-time. So no, your agent is not doing this live πŸ™ˆ

Okay, naming rules time πŸ“ For every descriptor in an information module, the descriptor shall be unique and mnemonic, and it shall not go over 64 characters in length. (Descriptors longer than 32 characters are not recommended, though πŸ₯Ί) And the hyphen is not allowed as a character in the name of any textual convention. No dashes in the name, periodt πŸ’…

3.1. Mapping of the DISPLAY-HINT clause πŸŽ€

The DISPLAY-HINT clause doesn't need to be there. It's just a hint for how a value might get displayed πŸ‘€ It may be present if and only if the syntax has an underlying primitive type of INTEGER or OCTET STRING. (Note, however, that the semantics of a particular syntax can make DISPLAY-HINT pointless for that syntax, e.g., for Counter32 [2]. Iconic of it to notice 🧐)

When the syntax is based on INTEGER, the hint has two parts πŸ”’ The first part is one character that suggests a display format: x for hexadecimal, d for decimal, o for octal, or b for binary. The second part is always left out for x, o and b, and it doesn't need to be there for d. If it is there, it starts with a hyphen, followed by a decimal number that tells you where the implied decimal point goes when the value gets rendered. For example:

     Hundredths ::= TEXTUAL-CONVENTION
         DISPLAY-HINT "d-2"
         ...
         SYNTAX     INTEGER (0..10000)

So a Hundredths value of 1234 is supposed to be rendered as "12.34" πŸ“

When the syntax is based on OCTET STRING, the hint is one or more octet-format specifications 🧚 Each one has five parts. Every part uses up zero or more of the next octets from the value and makes zero or more characters to display. The octets get processed in order of significance, most significant first, which is giving very big-end-first energy πŸ‘‘

The five parts of an octet-format specification are:

  1. The (optional) repeat indicator. If it's there, it's a *, and it means the current octet of the value is used as the repeat count. The repeat count is an unsigned integer (which may be zero) that says how many times the rest of this octet-format specification gets applied in a row. If the repeat indicator isn't there, the repeat count is one.
  2. The octet length: one or more decimal digits saying how many octets of the value this octet-specification uses and formats. The octet length can be zero. If fewer octets than that are left in the value, only the leftover ones get used.
  3. The display format, which is one of: x for hexadecimal, d for decimal, o for octal, or a for ascii. If the octet length part is greater than one and the display format is a numeric one, then network-byte ordering (big-endian encoding) is used when interpreting the octets in the value 🌸
  4. The (optional) display separator character. If it's there, it's a single character that gets displayed after each application of this octet-specification. BUT it isn't displayed if it would come right before the repeat terminator character for this octet-specification. This character can be any character except a decimal digit and a *.
  5. The (optional) repeat terminator character. It can only be there if the display separator character is there and this octet-specification begins with a repeat indicator. If it's there, it's a single character that gets displayed after all the zero or more repeated applications (as given by the repeat count) of this octet-specification. It can be any character except a decimal digit and a *.

Output of a display separator character or a repeat terminator character is suppressed if it would be the last character of the display. Lowkey important, so don't forget it πŸ™ˆ

If the octets of the value run out before all the octet-format specifications have been used, then the extra specifications get ignored. If there are still octets left in the value after going through all the octet-format specifications, then the last octet-format specification gets re-interpreted to process the extra octets, until no octets remain in the value. ✨

3.2. Mapping of the STATUS clause πŸ¦‹

The STATUS clause must be present, and it tells you whether this definition is current or historic. The values "current" and "obsolete" are self-explanatory, bestie πŸ’… The "deprecated" value means the definition is obsolete, but an implementor may want to keep supporting this textual convention so it plays nicely with older implementations 🫢

3.3. Mapping of the DESCRIPTION clause πŸ“–

The DESCRIPTION clause must be present, and it holds a textual definition of the textual convention. It gives all the semantic definitions you need to implement it, and it should carry any information that would otherwise be shared in any ASN.1 commentary annotations attached to the object. Main character energy for the DESCRIPTION clause, honestly πŸ‘‘

Heads up: to stay legal ASN.1, the whole value of this clause has to be wrapped in double quotation marks. That means it can't contain double quotation marks itself, though the value can span multiple lines. Don't get caught out 😭

3.4. Mapping of the REFERENCE clause ✨

okay so the REFERENCE clause is totally optional, it doesn't have to show up πŸ’… it's basically a little pointer that says "hey, go check this related thing that's defined in some other published work" πŸ“š like a bestie dropping a link in the chat πŸ”—

3.5. Mapping of the SYNTAX clause πŸŽ€

the SYNTAX clause is the one that's NOT optional, it must be present 😀 its whole job is to define the abstract data structure that goes with the textual convention 🧠 and the data structure must be one of the alternatives defined in the ObjectSyntax CHOICE or the BITS construct (see section 7.1 in [2]). so no freelancing, it has to be one of those options πŸ™…β€β™€οΈ

4. Security Considerations 🚨

Security issues are not discussed in this memo.

yes this memo doesn't cover security at all 😭 so don't go assuming it has you covered. ngl that's a whole vibe check πŸ’€

5. Editor's Address πŸ¦‹

Keith McCloghrie Cisco Systems, Inc. 170 West Tasman Drive San Jose, CA 95134-1706 US

Phone: +1 408 526 5260 EMail: kzm@cisco.com

6. Acknowledgements 🫢

this document is the result of significant work by the four major contributors πŸ‘‘ literally the MVPs:

  • Jeffrey D. Case (SNMP Research, case@snmp.com)
  • Keith McCloghrie (Cisco Systems, kzm@cisco.com)
  • Marshall T. Rose (Dover Beach Consulting, mrose@dbc.mtview.ca.us)
  • Steven Waldbusser (International Network Services, stevew@uni.ins.com)

and the SNMPv2 Working Group's contributions are acknowledged too 🌸 a special thanks goes to these legends πŸ’–:

  • Alexander I. Alten (Novell)
  • Dave Arneson (Cabletron)
  • Uri Blumenthal (IBM)
  • Doug Book (Chipcom)
  • Kim Curran (Bell-Northern Research)
  • Jim Galvin (Trusted Information Systems)
  • Maria Greene (Ascom Timeplex)
  • Iain Hanson (Digital)
  • Dave Harrington (Cabletron)
  • Nguyen Hien (IBM)
  • Jeff Johnson (Cisco Systems)
  • Michael Kornegay (Object Quest)
  • Deirdre Kostick (AT&T Bell Labs)
  • David Levi (SNMP Research)
  • Daniel Mahoney (Cabletron)
  • Bob Natale (ACE*COMM)
  • Brian O'Keefe (Hewlett Packard)
  • Andrew Pearson (SNMP Research)
  • Dave Perkins (Peer Networks)
  • Randy Presuhn (Peer Networks)
  • Aleksey Romanov (Quality Quorum)
  • Shawn Routhier (Epilogue)
  • Jon Saperia (BGS Systems)
  • Bob Stewart (Cisco Systems, bstewart@cisco.com), chair πŸ‘‘
  • Kaj Tesink (Bellcore)
  • Glenn Waters (Bell-Northern Research)
  • Bert Wijnen (IBM)

all of you are iconic, no notes 🌈✨

7. References πŸ“š

[1] Information processing systems - Open Systems Interconnection - Specification of Abstract Syntax Notation One (ASN.1), International Organization for Standardization. International Standard 8824, (December, 1987).

[2] SNMPv2 Working Group, 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.


that's the whole thing bestie πŸ¦‹πŸ’œ go read RFC 1902 next, it's the one the SYNTAX clause is literally pointing at 🧚

πŸ“¦ where this page comes from