ASHでは、技術評論社のSoftwareDesign誌(2002年4月号)のプログラミングで理解するSNMPを執筆しました。
このページでは、執筆時のプログラムを公開しています。コピー&ペーストすることにより利用できます。
プログラムの詳細は、技術評論社のSoftwareDesign誌を読んでください。
なお、記事についての質問などがありましたら、ASHの掲示板でも受け付けます。
下記のソースを一括ダウンロードできます。
snmpget.lzh(LZH圧縮形式のダウンロード) snmpget.tar.gz(tar+gzip圧縮形式のダウンロード) |
perl版のsnmpgetコマンドです。 disp.plも必要です。
snmpget.pl |
---|
#!/usr/bin/perl use Socket; use strict; require 'disp.pl'; my ($host,$cname,$oid); # 入力パラメータ格納用変数 my @oid; # OIDの数値を格納する配列 my $pd; # パケットデータ(pack前) my ($port,$ip,$addr); # ポート、IPアドレス、両者をまとめた構造体 my ($snd,$rcv,$rin); # 送信データ、受信データ、selct()に渡すビットマスク #入力パラメータから、ホスト名、コミニュティ名、OIDを取得 ($host,$cname,$oid) = @ARGV; #パラメータが3つなければエラー $oid or die "ERROR."; #GETリクエスト(16進文字列)作成処理 if ($oid !~ /^\./){ $oid = '.1.3.6.1.2.1.' . $oid; } @oid = split(/\./,$oid); shift(@oid); $pd = sprintf("%02x", (shift(@oid)*40 + shift(@oid)) ); foreach (@oid){ $pd .= sprintf("%02x", $_); } $pd = '06' . sprintf("%02x",(length($pd) / 2)) . $pd . '0500'; $pd = '30' . sprintf("%02x",(length($pd) / 2)) . $pd; $pd = '30' . sprintf("%02x",(length($pd) / 2)) . $pd; $pd = '020101020100020100' . $pd; $pd = 'a0' . sprintf("%02x",(length($pd) / 2)) . $pd; $pd = sprintf("%02x",length($cname)) . unpack("H*",$cname) . $pd; $pd = '02010004' . $pd; $pd = '30' . sprintf("%02x",(length($pd) / 2)) . $pd; #GETリクエスト確定処理 $snd = pack "H*", $pd; #ソケット作成処理 socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('udp')) or die "Socket error.\n"; bind(SOCKET, sockaddr_in(0, INADDR_ANY)) or die "Bind error.\n"; #送信内容表示 print "snd.\n"; &disp($pd); print "\n"; #送信 $port = 161; $ip = inet_aton($host); $addr = sockaddr_in($port, $ip); send(SOCKET,$snd,0,$addr); #タイムアウト処理(5秒) $rin = ''; vec($rin,fileno(SOCKET),1) = 1; select($rin, undef, undef, 5) or die "Request timeout.\n"; #受信 recv(SOCKET,$rcv,1000,0); #ソケットclose close(SOCKET); #受信内容表示 print "rcv.\n"; &disp(unpack "H*", $rcv); #終了 exit; |
perl版のSNMPパケットをダンプするスクリプトです。 disp.plも必要です。
snmp_dump.pl |
---|
#!/usr/bin/perl use Socket; use strict; require 'disp.pl'; my $rcv; # 受信データ格納用変数 my $port = 161; # ポート番号 #ソケット作成処理 socket(SOCKET, PF_INET, SOCK_DGRAM, getprotobyname('udp')) or die "Socket error.\n"; bind(SOCKET, sockaddr_in($port, INADDR_ANY)) or die "Bind error.\n"; #受信 recv(SOCKET,$rcv,1000,0); #ソケットclose close(SOCKET); #受信内容表示 &disp(unpack "H*", $rcv); #終了 exit; |
16進ダンプ表示用のサブルーチンです。 snmpget.pl、snmp_dump.plで利用しています。
disp.pl |
---|
#ダンプ表示用サブルーチン sub disp{ my $str = $_[0]; my $len = length($str) / 2; my ($line,$lstr,$lchr,$i,$b); for ($line = 0; 1 ; $line++){ $lstr = substr($str,$line*32,32) or last; printf "%04x : ",($line * 16); $lchr = ''; for ($i = 0;$i < 16 ;$i++){ $b = substr($lstr, $i*2 , 2) || '--'; if ($b ge '20' and $b le '7e'){ $lchr .= pack("H*", $b); }elsif ($b ne '--'){ $lchr .= '_'; } print "$b "; print " " if $i == 7; } print ": $lchr\n"; } } 1; |