skip to content

An SNMP walk of a device's vendor subtree prints only numeric OIDs under 1.3.6.1.4.1.32473; how do you resolve them to named objects and decode their instances?

level: seniorimportance: should knowfreq 28%

answer

  1. who owns this enterprise number
  2. sysObjectID points at the product
  3. load the module and its imports
  4. longest registered prefix wins
  5. the remainder is the instance

basics

~20 s

Identify the organisation from the IANA enterprise number, use sysObjectID and sysDescr to pick the matching module revision, load it with every module it imports, then match each OID's longest registered prefix and decode the remainder as .0 or INDEX values.

solid answer

~40 s

The arc after `1.3.6.1.4.1` is an IANA-assigned **private enterprise number**; `32473` is the one IANA reserves for documentation, standing in for a real vendor. Read `sysObjectID.0`, which RFC 3418 says points into the enterprises subtree to say what kind of box this is, and `sysDescr.0` for the software version, then obtain that organisation's MIB modules for that release. Load each module **with every module it imports**: the standard SNMPv2-SMI, SNMPv2-TC and SNMPv2-CONF and the vendor's own root and textual-convention modules, or nothing below the vendor root resolves. For each OID, find the **longest prefix** registered by an `OBJECT-TYPE`; the remaining sub-identifiers are the instance, `.0` for a scalar or the row's `INDEX` values. Without the module you still see each value's SMI type, but never its name, units or meaning.

code

pseudocode · 11 lines
pseudocode
function resolve(oid, registry):
    # registry maps registered OIDs to OBJECT-TYPE definitions
    for cut in range(len(oid), 0, -1):
        prefix = oid[0:cut]
        if prefix in registry and registry[prefix].isObjectType:
            obj = registry[prefix]
            rest = oid[cut:]
            if obj.isScalar:
                return (obj.name, "scalar" if rest == [0] else "bad instance")
            return (obj.name, decodeIndex(rest, obj.row.indexClause))
    return (oid, "unresolved: load the module and its imports")

go deeper

for a junior

Recognise 1.3.6.1.4.1 as the enterprises arc and know that the next number names the organisation, assigned by IANA.

for a middle

Walk through the procedure: sysObjectID, the right module, its imports, then longest-prefix matching with the remainder decoded as .0 or index values.

for a senior

Match module revisions to software releases, explain why a missing import leaves everything numeric, and refuse to alert on an object whose meaning is only inferred.

for a principal

Treat vendor modules as versioned dependencies of the monitoring platform: track them per release and budget for estates where some boxes ship no usable module.

## The situation A walk of a device returns lines such as `1.3.6.1.4.1.32473.2.1.1.3.7 = Gauge32: 41`. Every OID begins `1.3.6.1.4.1`, which is `iso.org.dod.internet.private.enterprises`: the part of the tree where organisations define objects unilaterally (RFC 2578 section 4). The manager prints numbers because it has no module registering anything below that point. Resolving them is a mechanical procedure, not guesswork. ## Step 1: identify the organisation The sub-identifier right after `enterprises` is a **private enterprise number (PEN)** assigned by IANA. RFC 1155 describes the model: an enterprise requests a node under `enterprises` and may then define its own objects and register its products beneath it. IANA keeps the registry of who holds each number. `32473` is the value IANA reserves for use in documentation (RFC 5424 uses it throughout), so here it stands in for whichever vendor built the box. The same number appears elsewhere: the first four octets of many SNMP engine IDs (RFC 3411), the `@` part of syslog structured-data IDs (RFC 5424), enterprise-specific IPFIX information elements (RFC 7011). One PEN identifies one organisation across all of them. ## Step 2: find out which product and which release - **`sysObjectID.0`** (`1.3.6.1.2.1.1.2.0`) returns an OID that RFC 3418 says is allocated within the enterprises subtree and identifies "what kind of box" is being managed. - **`sysDescr.0`** (`1.3.6.1.2.1.1.1.0`) should carry the hardware type and software version. The release matters because vendors revise modules. A module's `MODULE-IDENTITY` carries `LAST-UPDATED` and `REVISION` clauses, so you can match the module to the software that implements it. ## Step 3: load the module and everything it imports An SMIv2 module starts with an `IMPORTS` clause and resolves its own OIDs relative to symbols it imports. A vendor module typically imports: 1. **SNMPv2-SMI** (RFC 2578), for `enterprises`, the base types and the macros; 2. **SNMPv2-TC** (RFC 2579), for textual conventions such as `DisplayString`; 3. **SNMPv2-CONF** (RFC 2580), for `OBJECT-GROUP` and `MODULE-COMPLIANCE`; 4. the vendor's own **root module**, which assigns the arcs under the enterprise number, and often a vendor textual-convention module. If any import is missing, the chain from `enterprises` down to the object is broken and the whole module fails to resolve. That is the most common reason a freshly loaded module still prints numbers. ## Step 4: split name from instance A returned OID is an **object name** followed by an **instance identifier**. No module registers instances, so an exact lookup fails; resolution means finding the **longest prefix that a module registers** with an `OBJECT-TYPE`, then decoding what is left: - If the object is a scalar, the remainder must be exactly `.0`. - If it is a column, the object name has the shape `table.1.column`, and the remainder is the row's `INDEX` values, encoded by RFC 2578 section 7.7: one sub-identifier per integer, four for an `IpAddress`, a length followed by octets for a variable-length string unless `IMPLIED`. In the example, if the module registers a table at `32473.2.1` whose rows are indexed by one integer, then `.2.1.1.3.7` reads as column 3 of row 7. ## Step 5: read the definition, not just the name A name is not yet meaning. The `SYNTAX` says whether to gauge the value or compute a rate, `UNITS` and `DESCRIPTION` say what it measures, and `STATUS` warns if the object is deprecated. A textual convention adds a display rule, for example rendering an `OCTET STRING` as text. Two traps sit here: an object marked `deprecated` may already have a replacement you should poll instead, and a module that began under `experimental(3)` may have been republished under `mgmt(2)` with new OIDs, so an old module and a new agent can disagree about where the same idea lives. ## When no module can be found The wire still tells you something, because each value carries its SMI type: | Visible on the wire | Not visible without the module | |---|---| | `Counter32` versus `Counter64` versus `TimeTicks` | the descriptor (name) | | `OCTET STRING` versus `OBJECT IDENTIFIER` | units and scaling | | `IpAddress` | the textual convention in use | | the numeric OID structure | what the index values stand for | Two limits apply even to the types: `Gauge32` and `Unsigned32` share one tag, and `Integer32` is indistinguishable from `INTEGER`, so an enumeration's labels are lost. The numeric pattern `x.1.column.index` hints at a table. Treat any meaning inferred this way as a hypothesis until a module or the vendor's documentation confirms it.

  • Why does loading a vendor module sometimes resolve nothing at all?
    Because an SMIv2 module builds its OIDs from symbols it imports. The vendor's root node is usually defined in a separate module relative to `enterprises` from SNMPv2-SMI, and textual conventions come from SNMPv2-TC or a vendor module. If any import is missing, the path from `enterprises` to the objects cannot be built, so every OID in the module stays numeric.
  • Two OIDs under the same vendor prefix return Gauge32 values; can you tell from the wire which is a Gauge32 and which an Unsigned32?
    No. RFC 2578 gives `Gauge32` and `Unsigned32` the same application tag, so the encoding is identical. Only the module's `SYNTAX` clause says whether the value is a gauge that sticks at its bounds or a plain unsigned number, which is one more reason not to build alerts on an object you cannot resolve.

saying these in an interview costs you the question

  • The number after 1.3.6.1.4.1 identifies the device model
  • A module resolves fine even if its IMPORTS are not loaded
  • Without the module you can still read the object's units from the response
  • The whole returned OID should appear verbatim in the MIB module
  • Gauge32 and Unsigned32 can be told apart by their encoding