0

RFC1155, 3.2.3.2 defines an IpAddress as:

This application-wide type represents a 32-bit internet address. It
is represented as an OCTET STRING of length 4, in network byte-order.

And again, in section 6

IpAddress ::=
     [APPLICATION 0] -- in network-byte order
        IMPLICIT OCTET STRING (SIZE (4))

Also RFC 1156, 5.4.1 defines an ipAddrEntry as a SEQUENCE containing an ipAdEntAddr as an IpAddress.

Okay then, backpedaling through this "(NOT)Simple Network Message Protocol", it should be clear that an IPAddress is 4 byte, network byte order (Big Endian)

RFC1156, 5.4.1 defines an ipAddrEntry to be a SEQUENCE containing among other things, ipAdEntAddr as an IpAddress... Which was defined in the last RFC.

Why then, in Wireshark, when I examine the OID request, the IP address 192.168.1.21 is encoded as

81  40  81  28  01  15

enter image description here

Which isn't 4 octets. It's not even TLV encoding. It's some other 7 bit encoding where the 8th bit is used to indicate "Not the last octet" (I think it's VLQ? )

1000 0001 0100 0000  =>  1100 0000
1000 0001 0010 1000  =>  1010 1000

If it is supposed to be VLQ, where is that documented?

Why is what I read on Wireshark not what I read in the RFCs?

SpacemanScott
  • 953
  • 9
  • 21

2 Answers2

1

SNMP protocol and Wireshark are both correct, but you misunderstand the basic concept of SNMP table and OIDs.

While from the text, you might see 192.168.1.21 anywhere in Wireshark's decoded tree view, you must be aware of its actual entity so as to understand how it was encoded.

In the screen shot you can see that 192.168.1.21 highlighted was part of an OID 1.3.6.1.2.1.4.20.1.2.192.168.1.21. This is a typical OID pattern used in tables, where the index 192.168.1.21 is combined with the table column OID 1.3.6.1.2.1.4.20.1.2 to represent the actual cell.

Thus, its bytes are encoded following BER like any other OIDs, not IpAddress,

How does ASN.1 encode an object identifier?

That's why the bytes look different from your initial thought.

Lex Li
  • 60,503
  • 9
  • 116
  • 147
  • The difference is between the "Value" being sent or returned, and the OID entity itself. This is an OID, not a "value", even though it looks like one. I was looking at it like an IP value. This protocol is anything but "simple". But I do find it annoying. – SpacemanScott Feb 17 '23 at 20:04
0

you may remember my last answer, in which I explained that every instance of an object has a "name" and an INDEX. I referenced ifTable to show how ifIndex was used to refer to each instance of a row. While many (if not most) SNMP tables use a single INTEGER as the INDEX, it's actually possible to use any combination of primitive data types (there are tables that include an OID in the index, giving you an OID within an OID). The important thing is that the INDEX be unique for each row.

Based on the OID in your screenshot, it looks like you are dealing with ipAdEntIfIndex (from RFC 1213's IP-MIB). If you consult the MIB, you will find this definition for ipAddrEntry (representing a row in ipAddrTable):

ipAddrEntry OBJECT-TYPE
    SYNTAX     IpAddrEntry
    MAX-ACCESS not-accessible
    STATUS     deprecated
    DESCRIPTION
           "The addressing information for one of this entity's IPv4
            addresses."
    INDEX      { ipAdEntAddr }
    ::= { ipAddrTable 1 }

IpAddrEntry ::= SEQUENCE {
        ipAdEntAddr          IpAddress,
        ipAdEntIfIndex       INTEGER,
        ipAdEntNetMask       IpAddress,
        ipAdEntBcastAddr     INTEGER,
        ipAdEntReasmMaxSize  INTEGER
    }

You can see here that it uses ipAdEntAddr as the INDEX, and that ipAdEntAddr is an IpAddress. The reason that the encoding in your screenshot looks funny is that it's encoded as part of an OID, not as an OctetString, as an IpAddress would normally be.

There are two different specifications that are relevant here. The first is the specification for the ASN.1 Basic Encoding Rules, which is not publicly available for free, but basically says that OID sub-identifiers can only use the lower 7 bits of each byte, and that the MSB is a flag indicating whether there are additional bytes in that sub-identifier. Hence the 0x01 in 0x81 gives bit 7, and 0x40 gives bits 0-6. If you put them together, you get 0xc0, which is 192.

The second specification is RFC 2578 (section 7.7), which defines how an INDEX is encoded within an OID:

   The syntax of the objects in the INDEX clause indicate how to form
   the instance-identifier:

(1)  integer-valued (i.e., having INTEGER as its underlying primitive
     type):  a single sub-identifier taking the integer value (this
     works only for non-negative integers);

(2)  string-valued, fixed-length strings (or variable-length preceded by
     the IMPLIED keyword):  `n' sub-identifiers, where `n' is the length
     of the string (each octet of the string is encoded in a separate
     sub-identifier);

(3)  string-valued, variable-length strings (not preceded by the IMPLIED
     keyword):  `n+1' sub-identifiers, where `n' is the length of the
     string (the first sub-identifier is `n' itself, following this,
     each octet of the string is encoded in a separate sub-identifier);

(4)  object identifier-valued (when preceded by the IMPLIED keyword):
     `n' sub-identifiers, where `n' is the number of sub-identifiers in
     the value (each sub-identifier of the value is copied into a
     separate sub-identifier);

(5)  object identifier-valued (when not preceded by the IMPLIED
     keyword):  `n+1' sub-identifiers, where `n' is the number of sub-
     identifiers in the value (the first sub-identifier is `n' itself,
     following this, each sub-identifier in the value is copied);

(6)  IpAddress-valued:  4 sub-identifiers, in the familiar a.b.c.d
     notation.

An IpAddress is simple, because it's represented as dot-separated integers, just like an OID.

TallChuck
  • 1,725
  • 11
  • 28