以前、以下の記事のコードを書いた時、SNMPのOIDの BER(Basic Encoding Rule)形式でのエンコード処理について勉強した。
今回は、その時に勉強した内容を書く。
SNMPのOIDのエンコードで面倒なのは、OIDの数値が128以上の場合である。というのは、OIDの数値が128以上の場合、1バイトではなく複数バイトで表現することになっており、それら複数バイトの最後の1バイト以外は先頭bitを立てる必要があるからである。文章だけでは分かりにくいと思うので、例を挙げて説明する。
例えば、OIDの中に 9999 という数値があったとする。まず、128 進数として分解すると以下になる。
9999 = (128^1 * 78) + (128^0 * 15)
エンコードする際、最後の1バイト以外は先頭ビットを立てるので、以下にようになる。(見やすくするために変換結果は16進で表現している。)
78 = 0100 1110--(先頭bitを立てる)--> 1100 1110 = 0xCE
15 = 0x0F
以上により、9999 のエンコード結果は CE0F となる。
複数バイトに分けた際、どこまでが一纏まりなのか判別するために上記の仕様になっていると考えている。
また、OIDの先頭部分は、「最初のOIDの数値×40 + 二つ目のOIDの数値」として1バイトに纏めることになっているので、例えば、OIDの先頭が .1.3 だったら、1×40+3=43 となり、16進では 2B となる。最初の数値と二つ目の数値についてこうした変換をしている理由は分かっていないが、おそらく1バイトに纏めて通信量を減らすためだと思われる。
以上を踏まえると、例えば、「.1.3.6.1.4.1.9999」というOIDをBER形式でエンコードすると、 「2B 06 01 04 01 CE 0F」となる。