2010年07月17日
実践SNMP+Java GetNextとWalk
SNMP4Jを利用したSNMP GetNextとWalk操作について説明します。
まずは、シンプルなGetNextコードから説明します。
まずは、シンプルなGetNextコードから説明します。
<Javaコード(GetNext)>
<実行結果(GetNext)>
1.3.6.1.2.1.1.1.0 -> Hardware: x86 Family 6 Model 15 Stepping 6 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)
<説明(GetNext)>
1)GetNextリクエスト送信準備(1~23行目)
ここまではSNMP Getの説明と同じになるので割愛します。
PDUタイプはPDU.GETNEXTに設定しています。
ちなみにGet記事で説明したインスタンス識別子が事前にはわからない場合に
GetNextを使います。
このサンプルでは、String OID = ".1.3.6.1.2.1.1"; // mib-2.systemを問合せ
OIDにしています。
(この次のOID/インスタンスをエージェントに問合せます)
2)GetNextリクエストの送信とレスポンスの受信
こちらもSNMP Getと基本的に同じです。
実行結果を見ると、指定した".1.3.6.1.2.1.1"; // mib-2.systemに対してエージェント側で
その次に管理しているsystem.sysDescr.0(systemグループの先頭)が戻ります。
このあたりの話しになるとMIBファイルとそのブラウザも合わせて使わないとわからなくなってきます。
#その通りだという方は、’MIBブラウザ’で検索し、適当なMIBブラウザをダウンロード、
#インストールしてみて下さい。
以上でGetNextは完了です。
引き続き、SNMP Walkについて説明します。
GetNextは一度にまとめてオブジェクトを取得したい場合には、繰り返し操作になるので、
人が行うには不便です。
ですので、ある条件をもって、GetNextを繰り返し取得することをWalkと言います。
ただ、WalkはSNMPの標準仕様ではありませんので、Snmpクラスにも用意されていません。
次はこのWalkと呼ばれる指定したOIDのサブツリーに含まれる全てオブジェクトを取得する
コードを書いてみます。
<Javaコード(シンプルなWalk)>
<実行結果(Walk)>
1.3.6.1.2.1.1.1.0 -> Hardware: x86 Family 6 Model 15 Stepping 6 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)
<説明(Walk)>
1)Walkの開始(26行目)と終了条件
GetNextのループです。凝った作りにはしておらず、タイムアウト、SNMPエラーが発生した際には
ループを抜けます。あともう一つ抜ける条件がありまして、36行目で評価しているisSubTreeが
falseの場合にも、レスポンスに含まれるOIDが、初期値として指定したルートOIDのサブツリーでは
無くなったと判断して、ループを抜けます。
isSubTreeの実装ですが、一から作らず、[SNMP4J] SnmpWalk Termination Conditionsを
参考にrootOID.leftMostCompare(rootOID.size(), currentOID) != 0で判断しています。
#FrankさんはSNMP4Jの開発者
実際に実行結果を見ると、OID = ".1.3.6.1.2.1.1"; // mib-2.system以下のオブジェクトを
全て終了し、.1.3.6.1.2.1.2.1.0(interfaces.ifNumber.0)になったところで終了しています。
2)最後に
2行目をコメントインして、ifTable.ifEntry.ifDescrを取得するとインタフェース名の
一覧を取得し、結果を表示しますが、Windowsの場合、期待した通りのインタフェース名称が
表示されないことがあります。
#この時点で想像ができる人は鋭いですね。
理由は、ifDescrがDisplayStringでというデータ型(Syntax)で、エージェントから取得した値が
印字可能か否かが影響しているのですが、その対応方法は別記事で説明しようと思います。
(GetNext/WalkはMIBテーブルへのアクセスに利用する事が多く、サンプル・コードを試す場合に、
ifTableはその第一候補かと思いましたので、先に断っておきます)
- String oid = ".1.3.6.1.2.1.1"; // mib-2.system
- //oid = ".1.3.6.1.2.1.2.2.1.2", // ifTable.ifEntry.ifDescr
- // SNMP通信パラメータを設定するクラス。
- CommunityTarget comTgt = new CommunityTarget();
- comTgt.setAddress( new UdpAddress("localhost/161") ); // UDPアドレス(ターゲット・アドレス/SNMPポート)
- comTgt.setCommunity( new OctetString("public") ); // SNMPコミュニティ名
- comTgt.setTimeout(1000); // タイムアウト時間(ミリ秒)
- comTgt.setRetries(1); // リトライ数
- comTgt.setVersion(SnmpConstants.version1); // SNMPバージョン
- // PDUを生成します。
- PDU pdu = new PDU();
- pdu.setType(PDU.GETNEXT);
- // PDUにバーバインドを格納します。
- OID targetOID = new OID(oid);
- pdu.add( new VariableBinding(targetOID) );
- // SNMP操作の基本になるクラス。
- Snmp snmp = null;
- // DefaultTcpTransportMappingクラスもあります
- DefaultUdpTransportMapping utm = null;
- try {
- utm = new DefaultUdpTransportMapping();
- snmp = new Snmp(utm);
- snmp.listen(); // ローカルUDPポートのオープンと待機
- // SNMP GetNext
- ResponseEvent response = snmp.getNext(pdu, comTgt);
- // レスポンスPDU
- PDU resPdu = response.getResponse();
- if ( resPdu != null && resPdu.getErrorStatus() == SnmpConstants.SNMP_ERROR_SUCCESS ) {
- // このサンプルではリクエストPDUに含まれるバーバインドは1つだけだったのでget(0)
- VariableBinding var = resPdu.get(0);
- if ( !var.isException() ) {
- System.out.println(var.getOid() + " -> " + var.getVariable().toString());
- } else {
- System.out.println(var.getOid() + " -> " + "has exception syntax!");
- }
- } else {
- if (resPdu == null) {
- // レスポンスPDUがnullの場合はタイムアウトです。
- System.out.println("request timeout.");
- } else {
- System.out.println(resPdu.getErrorStatus()+"/"+resPdu.getErrorStatusText());
- }
- }
- // ローカルUDPポートのclose
- snmp.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
<実行結果(GetNext)>
1.3.6.1.2.1.1.1.0 -> Hardware: x86 Family 6 Model 15 Stepping 6 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)
<説明(GetNext)>
1)GetNextリクエスト送信準備(1~23行目)
ここまではSNMP Getの説明と同じになるので割愛します。
PDUタイプはPDU.GETNEXTに設定しています。
ちなみにGet記事で説明したインスタンス識別子が事前にはわからない場合に
GetNextを使います。
このサンプルでは、String OID = ".1.3.6.1.2.1.1"; // mib-2.systemを問合せ
OIDにしています。
(この次のOID/インスタンスをエージェントに問合せます)
2)GetNextリクエストの送信とレスポンスの受信
こちらもSNMP Getと基本的に同じです。
実行結果を見ると、指定した".1.3.6.1.2.1.1"; // mib-2.systemに対してエージェント側で
その次に管理しているsystem.sysDescr.0(systemグループの先頭)が戻ります。
このあたりの話しになるとMIBファイルとそのブラウザも合わせて使わないとわからなくなってきます。
#その通りだという方は、’MIBブラウザ’で検索し、適当なMIBブラウザをダウンロード、
#インストールしてみて下さい。
以上でGetNextは完了です。
引き続き、SNMP Walkについて説明します。
GetNextは一度にまとめてオブジェクトを取得したい場合には、繰り返し操作になるので、
人が行うには不便です。
ですので、ある条件をもって、GetNextを繰り返し取得することをWalkと言います。
ただ、WalkはSNMPの標準仕様ではありませんので、Snmpクラスにも用意されていません。
次はこのWalkと呼ばれる指定したOIDのサブツリーに含まれる全てオブジェクトを取得する
コードを書いてみます。
<Javaコード(シンプルなWalk)>
- public void snmpWalk() {
- String oid = ".1.3.6.1.2.1.1"; // mib-2.system
- //oid = ".1.3.6.1.2.1.2.2.1.2"; // ifTable.ifEntry.ifDescr
- // SNMP通信パラメータを設定するクラス。
- CommunityTarget comTgt = new CommunityTarget();
- comTgt.setAddress( new UdpAddress("localhost/161") ); // UDPアドレス(ターゲット・アドレス/SNMPポート)
- comTgt.setCommunity( new OctetString("public") ); // SNMPコミュニティ名
- comTgt.setTimeout(1000); // タイムアウト時間(ミリ秒)
- comTgt.setRetries(1); // リトライ数
- comTgt.setVersion(SnmpConstants.version1); // SNMPバージョン
- // PDUを生成します。
- PDU pdu = new PDU();
- pdu.setType(PDU.GETNEXT);
- // PDUにバーバインドを格納します。
- OID rootOID = new OID(oid);
- pdu.add( new VariableBinding(rootOID) );
- // SNNMP操作の基本になるクラス。
- Snmp snmp = null;
- // DefaultTcpTransportMappingクラスもあります
- DefaultUdpTransportMapping utm = null;
- try {
- utm = new DefaultUdpTransportMapping();
- snmp = new Snmp(utm);
- snmp.listen(); // ローカルUDPポートのオープンと待機
- // SNMP Walk
- while ( true ) {
- // SNMP GetNext
- ResponseEvent response = snmp.getNext(pdu, comTgt);
- // レスポンスPDU
- PDU resPdu = response.getResponse();
- if ( resPdu != null && resPdu.getErrorStatus() == SnmpConstants.SNMP_ERROR_SUCCESS ) {
- // このサンプルではリクエストPDUに含まれるバーバインドは1つだけだったのでget(0)
- VariableBinding var = resPdu.get(0);
- OID currentOID = var.getOid();
- if ( !var.isException() ) {
- if ( isSubTree(rootOID, currentOID) ) {
- System.out.println(currentOID + " -> " + var.getVariable().toString());
- pdu = new PDU();
- pdu.setType(PDU.GETNEXT);
- pdu.addOID( new VariableBinding(currentOID) );
- } else {
- System.out.println("out of sub tree!");
- System.out.println(currentOID + " -> " + var.getVariable().toString());
- break;
- }
- } else {
- System.out.println(currentOID + " -> " + "has exception syntax!");
- break;
- }
- } else {
- if (resPdu == null) {
- // レスポンスPDUがnullの場合はタイムアウトです。
- System.out.println("request timeout.");
- } else {
- System.out.println(resPdu.getErrorStatus()+"/"+resPdu.getErrorStatusText());
- }
- break;
- }
- }
- // ローカルUDPポートのclose
- snmp.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public boolean isSubTree(OID rootOID, OID currentOID) {
- boolean b = true;
- /**
- * Compares the n leftmost sub-identifiers with the given OID in left-to-right direction.
- * 0 if the first n sub-identifiers are the same.
- * <0 if the first n sub-identifiers of this OID are lexicographic less than those of the comparand.
- * >0 if the first n sub-identifiers of this OID are lexicographic greater than those of the comparand
- */
- if ( rootOID.leftMostCompare(rootOID.size(), currentOID) != 0 ) {
- b = false;
- }
- return b;
- }
<実行結果(Walk)>
1.3.6.1.2.1.1.1.0 -> Hardware: x86 Family 6 Model 15 Stepping 6 AT/AT COMPATIBLE - Software: Windows 2000 Version 5.1 (Build 2600 Multiprocessor Free)
1.3.6.1.2.1.1.2.0 -> 1.3.6.1.4.1.311.1.1.3.1.1
1.3.6.1.2.1.1.3.0 -> 1 day, 4:21:14.10
1.3.6.1.2.1.1.4.0 ->
1.3.6.1.2.1.1.5.0 -> PANZERII
1.3.6.1.2.1.1.6.0 ->
1.3.6.1.2.1.1.7.0 -> 76
out of sub tree!
1.3.6.1.2.1.2.1.0 -> 6
<説明(Walk)>
1)Walkの開始(26行目)と終了条件
GetNextのループです。凝った作りにはしておらず、タイムアウト、SNMPエラーが発生した際には
ループを抜けます。あともう一つ抜ける条件がありまして、36行目で評価しているisSubTreeが
falseの場合にも、レスポンスに含まれるOIDが、初期値として指定したルートOIDのサブツリーでは
無くなったと判断して、ループを抜けます。
isSubTreeの実装ですが、一から作らず、[SNMP4J] SnmpWalk Termination Conditionsを
参考にrootOID.leftMostCompare(rootOID.size(), currentOID) != 0で判断しています。
#FrankさんはSNMP4Jの開発者
実際に実行結果を見ると、OID = ".1.3.6.1.2.1.1"; // mib-2.system以下のオブジェクトを
全て終了し、.1.3.6.1.2.1.2.1.0(interfaces.ifNumber.0)になったところで終了しています。
2)最後に
2行目をコメントインして、ifTable.ifEntry.ifDescrを取得するとインタフェース名の
一覧を取得し、結果を表示しますが、Windowsの場合、期待した通りのインタフェース名称が
表示されないことがあります。
#この時点で想像ができる人は鋭いですね。
理由は、ifDescrがDisplayStringでというデータ型(Syntax)で、エージェントから取得した値が
印字可能か否かが影響しているのですが、その対応方法は別記事で説明しようと思います。
(GetNext/WalkはMIBテーブルへのアクセスに利用する事が多く、サンプル・コードを試す場合に、
ifTableはその第一候補かと思いましたので、先に断っておきます)
ダグラス・R. マウロ ケビン・J. シュミット
オライリー・ジャパン
売り上げランキング: 257,278
オライリー・ジャパン
売り上げランキング: 257,278
Java ネットワーク プログラミング 基礎からわかる 完全入門
posted with amazlet at 13.01.12
永嶋 浩
技術評論社
売り上げランキング: 228,941
技術評論社
売り上げランキング: 228,941
Posted by netbuffalo at 17:47│TrackBack(0)│
│実践SNMP+Java