ASH | サーバ | セキュリティ | Linux | FreeBSD | DB | Web | CGI | Perl | Java | XML | プログラム | ネットワーク | 標準 | Tips集

プログラミングで理解するSNMP

 ASHでは、技術評論社SoftwareDesign誌(2002年4月号)のプログラミングで理解するSNMPを執筆しました。 このページでは、執筆時のプログラムを公開しています。コピー&ペーストすることにより利用できます。
 プログラムの詳細は、技術評論社のSoftwareDesign誌を読んでください。
 なお、記事についての質問などがありましたら、ASHの掲示板でも受け付けます。

サンプルソースのダウンロード

 下記のソースを一括ダウンロードできます。

snmpget.lzh(LZH圧縮形式のダウンロード)
snmpget.tar.gz(tar+gzip圧縮形式のダウンロード)

snmpget.pl

 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;

snmp_dump.pl

 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;

disp.pl

 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;


Copyright (C)1995-2002 ASH multimedia lab.
mail : info@ash.jp