2010年07月28日
実践SNMP+Java - Trap/Inform Receiver
SNMP4Jを利用したSNMP Trap/Informの受信について説明します。
そろそろ気がつかれている方もいるかもしれませんが、SNMPv3については説明してきませんでした。
僕自身、実践で利用する機会・ニーズが少ないのが理由です。
SNMP Trap/Inform受信についてもSNMPv3は、多分動くだろう、という程度です。
時間が出来たらv3についてもまとめるつもりです。
早速Javaコードから見ていきましょう。
<Javaコード>
- public class SnmpReceiver implements CommandResponder {
- private Snmp snmp = null;
- public static void main(String[] args) {
- SnmpReceiver receiver = new SnmpReceiver();
- receiver.start();
- }
- public void start() {
- System.out.println("starting snmp trap/inform receiver...");
- MultiThreadedMessageDispatcher dispatcher;
- Address listenAddr;
- ThreadPool pool;
- try {
- // message dispatcher
- int numWorkers = 5;
- pool = ThreadPool.create("workers", numWorkers);
- dispatcher = new MultiThreadedMessageDispatcher(pool, new MessageDispatcherImpl());
- // listen UDP address
- String udpAddr = "udp:0.0.0.0/162"; // choose receiver interface and port.
- listenAddr = GenericAddress.parse( System.getProperty("snmp4j.listenAddress", udpAddr) );
- TransportMapping tm;
- if ( listenAddr instanceof UdpAddress ) {
- tm = new DefaultUdpTransportMapping( (UdpAddress) listenAddr );
- } else {
- tm = new DefaultTcpTransportMapping( (TcpAddress) listenAddr );
- }
- // SNMP operation base object
- snmp = new Snmp(dispatcher, tm);
- // message processing model for SNMPv1
- snmp.getMessageDispatcher().addMessageProcessingModel( new MPv1() );
- // message processing model for SNMPv2c (community based SNMPv2).
- snmp.getMessageDispatcher().addMessageProcessingModel( new MPv2c() );
- // message processing model for SNMPv3
- snmp.getMessageDispatcher().addMessageProcessingModel( new MPv3() );
- USM usm = new USM(SecurityProtocols.getInstance(), new OctetString(MPv3.createLocalEngineID()), 0);
- SecurityModels.getInstance().addSecurityModel(usm);
- // open port
- snmp.listen();
- // register this listener to observer.
- snmp.addCommandResponder(this);
- System.out.println("succeed: start snmp trap/inform receiver.");
- } catch (UnknownHostException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- public void processPdu(CommandResponderEvent snmpEvent) {
- System.out.println("* * * * * * * * * * SNMP TRAP/INFORM EVENT * * * * * * * * * *");
- try {
- // get security name.
- String communityInPDU = null;
- byte[] securityName = snmpEvent.getSecurityName();
- if ( securityName != null ) {
- communityInPDU = OctetString.fromByteArray( snmpEvent.getSecurityName() ).toString();
- }
- // get source UDP address.
- Address address = snmpEvent.getPeerAddress();
- System.out.println("snmp agent addr -> " + address);
- System.out.println("snmp agent community -> " + communityInPDU);
- // get security model
- switch ( snmpEvent.getSecurityModel() ) {
- case SecurityModel.SECURITY_MODEL_SNMPv1:
- System.out.println("security model -> SNMPv1");
- break;
- case SecurityModel.SECURITY_MODEL_SNMPv2c:
- System.out.println("security model -> SNMPv2c");
- break;
- case SecurityModel.SECURITY_MODEL_USM:
- System.out.println("security model -> SNMPv3");
- break;
- }
- // get PDU type.
- PDU receivePDU = snmpEvent.getPDU();
- if ( receivePDU != null ) {
- switch ( receivePDU.getType() ) {
- case PDU.V1TRAP: //v1
- System.out.println("PDU Type -> SNMPv1 Trap PDU");
- PDUv1 v1TrapPDU = (PDUv1) receivePDU;
- System.out.println(" Timestamp -> " + v1TrapPDU.getTimestamp());
- System.out.println(" Enterprise -> " + v1TrapPDU.getEnterprise().toString());
- System.out.println(" GenericType -> " + v1TrapPDU.getGenericTrap());
- System.out.println(" SpecificType -> " + v1TrapPDU.getSpecificTrap());
- break;
- case PDU.TRAP: // v2c|v3
- System.out.println("PDU Type -> SNMP Trap PDU");
- break;
- case PDU.INFORM: // inform
- System.out.println("PDU Type -> SNMP Inform PDU");
- // send inform response.
- PDU responsePDU = snmpEvent.getPDU();
- responsePDU.setErrorIndex(0);
- responsePDU.setErrorStatus(0);
- responsePDU.setType(PDU.RESPONSE);
- /*
- * StatusInformation represents status information of a SNMPv3 message
- * that is needed to return a report message.
- */
- StatusInformation statusInfo = new StatusInformation();
- /*
- * StateReference represents state information associated with SNMP messages.
- * The state reference is used to send response or report (SNMPv3 only).
- * Depending on the security model not all fields may be filled.
- */
- StateReference stateRef = snmpEvent.getStateReference();
- // return response PDU
- snmpEvent.getMessageDispatcher().returnResponsePdu(
- snmpEvent.getMessageProcessingModel(),
- snmpEvent.getSecurityModel(),
- snmpEvent.getSecurityName(),
- snmpEvent.getSecurityLevel(),
- responsePDU,
- snmpEvent.getMaxSizeResponsePDU(),
- stateRef,
- statusInfo
- );
- break;
- default:
- System.out.println("PDU Type -> any other PDU: " + receivePDU.getType());
- break;
- }
- // get variable bindings.
- System.out.println(" - - - - - - - - - - - Variable Bindings - - - - - - - - - - -");
- for (int i=0; i<receivePDU.size(); i++) {
- VariableBinding varbind = receivePDU.get(i);
- System.out.println(i + ": " + varbind.getOid().toString() +" -> "+ varbind.getVariable().toString());
- }
- System.out.println();
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- public void shutdown() {
- try {
- snmp.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
<実行結果>
まず、この受信Javaプログラムを起動します。
starting snmp trap/inform receiver...succeed: start snmp trap/inform receiver.
次にSNMPv1 Trap/SNMPv2 Trap/SNMP Informで作成したプログラムを使って、
受信サーバにSNMPメッセージを送信すると次のような結果が表示されます。
1)SNMPv1 Trap
* * * * * * * * * * SNMP TRAP/INFORM EVENT * * * * * * * * * *
snmp agent addr -> 192.168.0.11/50579
snmp agent community -> public
security model -> SNMPv1
PDU Type -> SNMPv1 Trap PDU
Timestamp -> 8640000
Enterprise -> 1.3.6.1.4.1.99999.1.1.100
AgentAddress -> 127.0.0.1
GenericType -> 6
SpecificType -> 3
- - - - - - - - - - - Variable Bindings - - - - - - - - - - -
0: 1.3.6.1.4.1.99999.1.2.1.0 -> NETBUFFALO SNMPv1 trap
1: 1.3.6.1.4.1.99999.1.2.2.0 -> sample v1 trap
2)SNMPv2 Trap
* * * * * * * * * * SNMP TRAP/INFORM EVENT * * * * * * * * * *
snmp agent addr -> 192.168.0.11/50588
snmp agent community -> public
security model -> SNMPv2c
PDU Type -> SNMP Trap PDU
- - - - - - - - - - - Variable Bindings - - - - - - - - - - -
0: 1.3.6.1.2.1.1.3.0 -> 1 day, 0:00:00.00
1: 1.3.6.1.6.3.1.1.4.1.0 -> 1.3.6.1.4.1.99999.1.1.100.0.1
2: 1.3.6.1.4.1.99999.1.2.1.0 -> NETBUFFALO SNMPv2 trap - varbind 1
3: 1.3.6.1.4.1.99999.1.2.2.0 -> NETBUFFALO SNMPv2 trap - varbind 2
3)SNMPv2 Inform
* * * * * * * * * * SNMP TRAP/INFORM EVENT * * * * * * * * * *
snmp agent addr -> 192.168.0.11/50601
snmp agent community -> public
security model -> SNMPv2c
PDU Type -> SNMP Inform PDU
- - - - - - - - - - - Variable Bindings - - - - - - - - - - -
0: 1.3.6.1.2.1.1.3.0 -> 1 day, 0:00:00.00
1: 1.3.6.1.6.3.1.1.4.1.0 -> 1.3.6.1.4.1.99999.1.1.100.0.1
2: 1.3.6.1.4.1.99999.1.2.1.0 -> NETBUFFALO SNMPv2 Inform - my varbind 1
3: 1.3.6.1.4.1.99999.1.2.2.0 -> NETBUFFALO SNMPv2 Inform - my varbind 2
<説明>
1)オブザーバー・パターン
サンプル・コードでは、CommandResponderインタフェースを実装し、42行目の
snmp.addCommandResponder(this);でSnmpオブジェクトに自身のオブジェクトを
リスナー登録しています。
こうしておくとSnmpオブジェクトがSNMPメッセージを受信した際に、
自身のprocessPdu(CommandResponderEvent snmpEvent)メソッドが呼び出されます。
2)受信サーバの起動
10~49行目でサービスの起動処理を行っています。
17~19行目ではトラップを受信した際にディスパッチする為のワーカー・スレッドの数
(numWorkers)を指定してスレッド・プール及びディスパッチャーを生成しています。
このスレッド数が受信性能に関わってくる訳ですが、数と性能の関係については
別の機会で説明します。
21~30行目ではSNMPマネージャ側の受信アドレスを指定し、Snmpオブジェクトを
生成しています。今回のコードでは、'0.0.0.0'を指定していますが、これは全ての
ネットワーク・インタフェースから受信することを意味しています。
もし、SNMPマネージャの動作するサーバ上に複数のネットワーク・インタフェース
(IPアドレス)が存在し、特定のIPアドレス宛のメッセージのみ受信する場合には、
受信IPアドレスを指定します。
最後に32~40行目でSNMPv1~v3に対応するメッセージ処理モデルを生成・追加後、
メッセージの受信を開始(snmp.listen())しています。
#snmp.addCommandResponder(this)も忘れずに!
3)受信処理
51~142行目がトラップの受信処理です。
まず、CommandResponderEventオブジェクトからエージェント(送信)側の
UDPアドレス情報、コミュニティ名を取り出しています。
もし、コミュニティ名で認証する場合には、この時点で行ないます。
67~77行目のセキュリティ・モデルは参考情報として出力しています。
80~127行目でPDUの情報を出力しています。
まず、PDUタイプを判定し、SNMPv1であればv1 Trap PDU特有の情報を出力しています。
SNMPv2 Informの場合ですが、エージェント(送信)側に受信を表すメッセージを
送信する必要があるので、その処理を113~122行目で行っています。
その送信PDUの中身ですが、簡単に言うと、受信したPDUをそのまま投げ返しています。
もし、データ(バーバインズ)の中身を確認してから送信するなら、コード上、
少し後ろの方で実装すべきかもしれません。
最後に130~134行目で各バーバインドの中身を取り出し、出力しています。
4)停止処理
停止処理を144~150行目で実装していますが、このコードでは呼出される
ことはありません。参考として記載しておきました。
ダグラス・R. マウロ ケビン・J. シュミット
オライリー・ジャパン
売り上げランキング: 257,278
オライリー・ジャパン
売り上げランキング: 257,278
Java ネットワーク プログラミング 基礎からわかる 完全入門
posted with amazlet at 13.01.12
永嶋 浩
技術評論社
売り上げランキング: 228,941
技術評論社
売り上げランキング: 228,941
Posted by netbuffalo at 19:09│TrackBack(0)│
│実践SNMP+Java