#!/usr/local/bin/perl
###############################################################################
#
# NetGenesis4 接続・切断・状態確認・時刻設定 CGI (1999.07.31)
# nwg4con2.cgi
# Copyright(C) 1999 M.Okamura (anb@y7.net)
# http://hp.vector.co.jp/authors/VA008536/
#
# 動作確認(通信プロトコルは独自解析のものです。)
# Firmware Version : 2.313 (PS1)
# Perl for Win32
# ActivePerl
# Linuxの Perl5
# Macの Perl5
#
# 改変は自由です。もっと使いやすくしてください。
# CGIな処理(引数とか)の部分をカットすればコマンドライン版にもできますね。
# マルチアカウント機能に対応しました。
# Firmware 2.313以前での動作も考慮してあります。
#
# NetGenesis4は株式会社マイクロ総合研究所(http://www.mrl.co.jp/)の製品です。
#
###############################################################################
# NetGenesis4のIPアドレスとシリアルポート(各自の環境で書き換えてください)####
$them = '192.168.0.1';
$serial = 1;
$cgi = 'nwg4con2.cgi';
$debug = 0;
# for test(一つだけコメントアウトすると、コマンドラインから確認できます) ####
#$ENV{'QUERY_STRING'} = 'connect=1&default=0&isp=0';
#$ENV{'QUERY_STRING'} = 'disconnect=1';
#$ENV{'QUERY_STRING'} = 'time=1';
#$ENV{'QUERY_STRING'} = 'status=1';
#$ENV{'QUERY_STRING'} = 'set=1';
# コマンド固有バイト列 ########################################################
$time = "\x41\x0B";
$set = "\x41\x04";
if( $serial == 1 ) {
$connect = "\x01\x6A"; # SERIAL 1
$disconnect = "\x01\x68"; # SERIAL 1
$status = "\x01\x64"; # SERIAL 1
$dial = "\x01\x6E"; # SERIAL 1
} else {
$connect = "\x01\x6B"; # SERIAL 2
$disconnect = "\x01\x69"; # SERIAL 2
$status = "\x01\x65"; # SERIAL 2
$dial = "\x01\x6F"; # SERIAL 2
}
# CGI引数解析 #################################################################
if ($ENV{'REQUEST_METHOD'} eq "POST") {
read( STDIN , $buffer , $ENV{'CONTENT_LENGTH'} );
}
else {
$buffer = $ENV{'QUERY_STRING'};
}
@pairs = split( /&/ , $buffer );
foreach $pair ( @pairs ) {
( $name , $value ) = split( /=/ , $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$form{$name} = $value;
}
# 引数から使用するコマンド決定 ################################################
$cmd = '';
$cmd = $dial if( $form{'isp'} ne '' );
$cmd = $connect if( $form{'connect'} ne '' );
$cmd = $disconnect if( $form{'disconnect'} ne '' );
$cmd = $time if( $form{'time'} ne '' );
$cmd = $status if( $form{'status'} ne '' );
$cmd = $set if( $form{'set'} ne '' );
# ヘッダ出力 ##################################################################
print "Content-type: text/html\n\n";
print "\n";
# 通信初期化 ##################################################################
use Socket;
# IPアドレスをバイト列に変換
#$ipaddress = inet_aton($them);
if( $them =~ /^(\d+).(\d+).(\d+).(\d+)$/ ) {
$ipaddress = pack( "C4",$1,$2,$3,$4 );
} else {
&error("IPアドレス $them");
}
$proto = getprotobyname('udp');
socket(S, AF_INET, SOCK_DGRAM, $proto) || &error("ソケット生成");
binmode S;
# コマンドが未定義の場合は、メニュー表示 ######################################
&menu( $ipaddress ) if( $cmd eq '' );
# 通信処理 ####################################################################
# 時刻設定の場合の時刻データ
if( $cmd eq $time ) {
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
$cmd2 = pack( "n3", $hour, $min, $sec );
} elsif ( $cmd eq $status ) {
$cmd2 = "\x00\x00\x00\x00";
} else {
$cmd2 = '';
}
# 接続コマンドで現在と違うアカウントの場合、接続先設定コマンド送信
if( $cmd eq $dial || ($cmd eq $connect && $form{'default'} ne $form{'isp'}) ) {
$data = &nwg( $ipaddress, $dial, pack( "n", $form{'isp'} ) );
$stat = unpack( "n", substr( $data, 0x10, 2 ) );
print "エラー:接続先設定
\n" if($stat);
&menu( $ipaddress ) if($cmd eq $dial);
exit(1) if($stat);
print "接続先設定コマンドを送信しました。
\n";
}
# コマンド送信、データ受信
$data = &nwg( $ipaddress, $cmd, $cmd2 );
# 結果処理 ####################################################################
if( $cmd eq $connect ) {
print "接続コマンドを送信しました。
\n";
&check( $ipaddress );
}elsif( $cmd eq $disconnect ) {
print "切断コマンドを送信しました。
\n";
&check( $ipaddress );
}elsif( $cmd eq $time ) {
printf("時刻設定コマンドを送信しました。%02d:%02d:%02d
\n",
$hour, $min, $sec );
}elsif( $cmd eq $status ) {
if( unpack( "n", substr( $data, 0x06, 2 ) ) < 0x164 ) {
$stat = unpack( "n", substr( $data, 0x14, 2 ) );
print "切断
\n" if( $stat == 3 );
print "処理中
\n" if( $stat == 4 );
print "接続
\n" if( $stat == 5 );
}else {
$stat = unpack( "n", substr( $data, 0x22, 2 ) );
print "切断
\n" if( $stat == 3 );
print "処理中
\n" if( $stat == 4 );
printf( "接続 My IP=%d.%d.%d.%d
\n",
unpack( "C", substr( $data, 0x13c , 1) ),
unpack( "C", substr( $data, 0x13d , 1) ),
unpack( "C", substr( $data, 0x13e , 1) ),
unpack( "C", substr( $data, 0x13f , 1) )
) if( $stat == 5 )
}
}elsif( $cmd eq $set ) {
}else {
&error("応答無し");
}
&menu( $ipaddress );
exit(0);
# メニュー ####################################################################
sub menu
{
my $ipaddr = $_[0];
# 状態確認コマンド
my $data = &nwg( $ipaddr, $status, "\x00\x00\x00\x00" );
# データ長
my $len = unpack( "n", substr( $data, 0x06, 2 ) );
my $condition = "無効";
my $stat;
if( $len < 0x164 ) {
$stat = unpack( "n", substr( $data, 0x14, 2 ) );
$condition = "切断" if( $stat == 3 );
$condition = "処理中" if( $stat == 4 );
$condition = "接続" if( $stat == 5 );
} else {
$stat = unpack( "n", substr( $data, 0x22, 2 ) );
$condition = "切断" if( $stat == 3 );
$condition = "処理中" if( $stat == 4 );
$condition = sprintf( "接続 My IP=%d.%d.%d.%d",
unpack( "C", substr( $data, 0x13c , 1) ),
unpack( "C", substr( $data, 0x13d , 1) ),
unpack( "C", substr( $data, 0x13e , 1) ),
unpack( "C", substr( $data, 0x13f , 1) )
) if( $stat == 5 );
}
my $default;
my @isp;
my @name;
if( $len < 0xA8 ) {
# データが足りないので、マルチアカウントは無効
$default = 0;
$isp[0] = 1;
$isp[1] = 0;
$isp[2] = 0;
$isp[3] = 0;
$name[0] = "ISP";
} elsif( $len < 0x164 ) {
# 現在の接続先番号
$default = unpack( "n", substr( $data, 0x1C, 2 ) );
# 接続先有効フラグ
$isp[0] = unpack( "n", substr( $data, 0x30, 2 ) );
$isp[1] = unpack( "n", substr( $data, 0x32, 2 ) );
$isp[2] = unpack( "n", substr( $data, 0x34, 2 ) );
$isp[3] = unpack( "n", substr( $data, 0x36, 2 ) );
# 接続先名
($name[0]) = split( /\x00/, substr( $data, 0x38, 32 ) );
($name[1]) = split( /\x00/, substr( $data, 0x58, 32 ) );
($name[2]) = split( /\x00/, substr( $data, 0x78, 32 ) );
($name[3]) = split( /\x00/, substr( $data, 0x98, 32 ) );
} else {
# 現在の接続先番号
$default = unpack( "n", substr( $data, 0x2A, 2 ) );
# 接続先有効フラグ
$isp[0] = unpack( "n", substr( $data, 0x2C, 2 ) );
$isp[1] = unpack( "n", substr( $data, 0x2E, 2 ) );
$isp[2] = unpack( "n", substr( $data, 0x30, 2 ) );
$isp[3] = unpack( "n", substr( $data, 0x32, 2 ) );
# 接続先名
($name[0]) = split( /\x00/, substr( $data, 0x34, 32 ) );
($name[1]) = split( /\x00/, substr( $data, 0x54, 32 ) );
($name[2]) = split( /\x00/, substr( $data, 0x74, 32 ) );
($name[3]) = split( /\x00/, substr( $data, 0x94, 32 ) );
}
my $hidden = '';
$hidden = '' if($debug);
print <<"_MENU1_";