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;
|