2010年07月17日

実践SNMP+Java DisplayString

GetNext/Walkに関する記事で紹介したコードを使って、ifTable.ifEntry.ifDescrを取得すると、次のような:で分割されたHexStringが表示される場合があります。
(大部分のケースでは正しいインタフェースの名称が表示されます)

何故でしょうか?

<実行結果>

1.3.6.1.2.1.2.2.1.2.1 -> 4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65:00
1.3.6.1.2.1.2.2.1.2.2 -> 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:38:00
1.3.6.1.2.1.2.2.1.2.3 -> 56:4d:77:61:72:65:20:56:69:72:74:75:61:6c:20:45:74:68:65:72:6e:65:74:20:41:64:61:70:74:65:72:20:66:6f:72:20:56:4d:6e:65:74:31:00
1.3.6.1.2.1.2.2.1.2.4 -> 42:72:6f:61:64:63:6f:6d:20:34:34:30:78:20:31:30:2f:31:30:30:20:49:6e:74:65:67:72:61:74:65:64:20:43:6f:6e:74:72:6f:6c:6c:65:72:20:2d:20:83:70:83:50:83:62:83:67:20:83:58:83:50:83:57:83:85:81:5b:83:89:20:83:7e:83:6a:83:7c:81:5b:83:67:00
1.3.6.1.2.1.2.2.1.2.5 -> 49:6e:74:65:6c:28:52:29:20:50:52:4f:2f:57:69:72:65:6c:65:73:73:20:33:39:34:35:41:42:47:20:4e:65:74:77:6f:72:6b:20:43:6f:6e:6e:65:63:74:69:6f:6e:20:2d:20:83:70:83:50:83:62:83:67:20:83:58:83:50:83:57:83:85:81:5b:83:89:20:83:7e:83:6a:83:7c:81:5b:83:67:00
out of sub tree!
1.3.6.1.2.1.2.2.1.3.1 -> 24

ちなみに、この実行結果は、僕のPC(WindowsXP)から取得した値です。
僕のPCにはネットワーク・インタフェースは複数認識されており、
 
 network_adapter


これを見るとBroadcom・・・とか出てきて欲しいところなんですが、人が読める状態ではありません。

まず、MIB定義ファイルからifDescrのデータ型(Syntax)を確認すると、DisplayString  ( SIZE ( 0 .. 255  ) ) となっています。

RFC1213によればDisplayStringは、OctetStringを基底とするデータ型で、表示可能な文字列がNVT ASCII character setに変換されています。

さらに、このメールをみると分かるのですがSNMP4JではMIBパーサを含んでいない為、レスポンス内のバーバインド部分で定義されているOctetStringという型情報以外は判断できず、OctetStringクラスのtoString()メソッド内で、printable(印字可能)か否かを判定しているようです。
 
実際にOctetStringクラスの中身を見ると、確かにisPrintable()がfalseになる場合には、toHexString()の値を戻しています。
 
僕のWindows PCでいうと、00がnot printableな為にHexString値が表示されていたのです。
 
  - - - OctetString.java - - -
  private static final char DEFAULT_HEX_DELIMITER = ':';
 
  public String toString() {
    if (isPrintable()) {
      return new String(value);
    }
    return toHexString();
  }
 
  public String toHexString() {
    return toHexString(DEFAULT_HEX_DELIMITER);
  }
 
  public String toHexString(char separator) {
    return toString(separator, 16);
  }
 
  /**
   * Determines whether this octet string contains non ISO control characters
   * only.
   * @return
   *    <code>false</code> if this octet string contains any ISO control
   *    characters as defined by <code>Character.isISOControl(char)</code>
   *    except if these ISO control characters are all whitespace characters
   *    as defined by <code>Character.isWhitespace(char)</code>.
   */
  public boolean isPrintable() {
    for (int i=0; i<value.length; i++) {
      char c = (char)value[i];
      if ((Character.isISOControl(c) ||
          ((value[i] & 0xFF) >= 0x80)) && (!Character.isWhitespace(c))) {
        return false;
      }
    }
    return true;
  }
  - - - OctetString.java - - -

 
対策として、この文字列をデリミタ(:)でスプリットして、各16進数文字列をbyteに変換したbyte配列を作り、これからStringオブジェクトを作成すればよさそうです。
#この時WindowsのSNMPエージェントはnon-printableな(意味のある文字には変換できない)
#’00(NULL文字)’ も含むので削除する。

SNMP4Jに含まれるクラスを使って実装すると次のようなコードになります。

<Javaコード>

  1. // 行末の’00’を削除しておく。
  2. String hexString = "4d:53:20:54:43:50:20:4c:6f:6f:70:62:61:63:6b:20:69:6e:74:65:72:66:61:63:65";
  3. OctetString os = OctetString.fromHexString(hexString);
  4. String printable = new String(os.getValue());
  5. System.out.println(printable);

<実行結果>

1.3.6.1.2.1.2.2.1.2.1 -> MS TCP Loopback interface
1.3.6.1.2.1.2.2.1.2.2 -> VMware Virtual Ethernet Adapter for VMnet8
1.3.6.1.2.1.2.2.1.2.3 -> VMware Virtual Ethernet Adapter for VMnet1
1.3.6.1.2.1.2.2.1.2.4 -> Broadcom 440x 10/100 Integrated Controller - パケット スケジューラ ミニポート
1.3.6.1.2.1.2.2.1.2.5 -> Intel(R) PRO/Wireless 3945ABG Network Connection - パケット スケジューラ ミニポート
 
※さらにひどいことにWindowsのSNMPエージェントはローカル(エージェント側)のエンコーディング
   (ここではSJIS)で生成したマルチバイト文字列を戻してきます。
   SNMPマネージャ側にエンコーディングを判断させるという考え方が酷いです。

WindowsのSNMPエージェントを使って説明すると余計な説明が増えますね。


 
入門SNMP
入門SNMP
posted with amazlet at 13.01.12
ダグラス・R. マウロ ケビン・J. シュミット
オライリー・ジャパン
売り上げランキング: 257,278

Java ネットワーク プログラミング 基礎からわかる 完全入門
永嶋 浩
技術評論社
売り上げランキング: 228,941

Posted by netbuffalo at 20:19│TrackBack(0)実践SNMP+Java 


この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/netbuffalo/357447