# SNMP BER question

I realize I'm asking a lot, but I am writing an SNMP agent for a different processor (not Arduino), so I wouldn't be surprised if I get kicked out, but I DO use Arduino sometimes.

I'm confused about the BER rules for the various data types. Could someone please help me? I don't know where else to turn.

As I understand it -

If I send an integer that is 0x7F or smaller, I send one byte.
If it is 0x80, I would send two bytes, the first being 0x00, the second would be 0x80.
If it is 0xFF, I would send two bytes, the first being 0x00, the second being 0xFF.
If I want to send 0x7FFF, I would send two bytes, the first being 0x7F, the second 0xFF.
If I want to send 0x8000,I would send three bytes, the first being 0x00, the second 0x80, and the third 0x00

Is this correct? If not, what is the answer?

And are timer ticks encoded in the same manner?

On the Arduino, a byte is 8 bits. It can hold a value from 0 to 255 (0x00 to 0xFF).

If I send an integer that is 0x7F or smaller, I send one byte.

Yes.

If it is 0x80, I would send two bytes, the first being 0x00, the second would be 0x80.

No.

If it is 0xFF, I would send two bytes, the first being 0x00, the second being 0xFF.

No.

An int is 4 bytes. It can hold a value from -32767 to 32767. An unsigned int is 4 bytes, and can hold a value from 0 to 65535 (0x0000 to 0xFFFF).

If I want to send 0x7FFF, I would send two bytes, the first being 0x7F, the second 0xFF.

Yes.

If I want to send 0x8000,I would send three bytes, the first being 0x00, the second 0x80, and the third 0x00

No.

I understand the relationship between Bytes, Words, and Longs. But those rules do not apply to SNMP.

Check out

http://luca.ntop.org/Teaching/Appunti/asn1.html

And note that the rules apply no matter what processor you are using - AVR or Apple A5 or Intel. They are part of the SNMP protocol.

I can't understand this well enough to find the answer myself. I was hoping one of the people on the Agentuino project could

There are way better places to find guidance on ASN.1 and BER. Than in Arduino forums. Google for one.

In BER, integers are (typically) encoded as:

Tag 0x02
Length (one octet)
Integer value (some number of octets).
The value is encoded MSB first.

Generally the minimum number of octets should be used, though I have seen working implementations that just always use the number of octets in their machine word.

Some examples:

Integer

``````value	BER encoding
0	02 01 00
127	02 01 7F
128	02 02 00 80
256	02 02 01 00
-128	02 01 80
-129	02 02 FF 7F
``````

I agree, and I saw the scheme you posted above, but it doesn't seem to work for timer ticks.

Desperate people start looking everywhere there could possibly be help.

from RFC2578

-- hundredths of seconds since an epoch
TimeTicks ::=
[APPLICATION 3]
IMPLICIT INTEGER (0..4294967295)

so your tag is 0x43
and length and value are encoded as implicit INTEGER
i.e. MSoctet first, minimal number of octets, two's complement

the minimum number of octets should be used,

Really? Not even the number of octets needed to hold the range defined in the MIB?

Eww!

From ITU-T X.690

``````8.3        Encoding of an integer value
8.3.1      The encoding of an integer value shall be primitive. The contents octets shall consist of one or more octets.
8.3.2      If the contents octets of an integer value encoding consist of more than one octet, then the bits of the first octet
and bit 8 of the second octet:
a)     shall not all be ones; and
b)     shall not all be zero.
NOTE – These rules ensure that an integer value is always encoded in the smallest possible number of octets.
``````

(I’ll just add it to my list of “things I don’t like about SNMP.”)
((minimizing packet size. How … quaint.))

This has got me thinking...

punk:
From ITU-T X.690

`````` NOTE – These rules ensure that an integer value is always encoded in the smallest possible number of octets.
``````

I definitely recall something bogus in the specs that allows you to encode things in way more bytes than is actually needed. I had to look it up....

From ITU-T X.690

``````8.1.3.3 For the definite form, the length octets shall consist of one or more octets, and shall represent the number of
octets in the contents octets using either the short form (see 8.1.3.4) or the long form (see 8.1.3.5) as a sender's option.
:
8.1.3.5 In the long form, the length octets shall consist of an initial octet and one or more subsequent octets.
:
NOTE 2 – In the long form, it is a sender's option whether to use more length octets than the minimum necessary.
``````

So it is legal to use 2, 3 or 100 octets to describe the length of a 3-octet integer.

Where this is actually of use is where you can carry out a long nested encoding, possibly of a constructed type and correctly determine all the lengths, then go back and update the length octets accordingly. This only works if you can know in advance how many octets are needed to encode the lengths, and so it is common to leave 2 or 3 octet lengths to then be filled in later.

I thought I had wrung all this garbage from my brain, but it all comes rushing back. This is why my encoder used a depth-first right-to-left approach, so I never had to go back and adjust length fields -- I could always encode the length near the end, after all the content was encoded.