ScanTool do Orinoco

29 wrzesień 2008 | Kategorie: Administracja, Perl, WiFi

Do oprogramowania dla Access Pointów Orinoco AP2000/AP2500, dołączany jest mały programik o nazwie ScanTool (Windows), który pozwala na podstawowe operacje na AP: ustawienie statycznego adresu IP, aktualizację oprogramowania. Pozwala także na wyszukanie “zaginionego” AP, gdy nie znamy jego adresu IP. Potrzebowałem narzędzia, które “znajdzie” mi Orinoco wprost z konsoli, bez dostępu do X+Wine a tym bardziej do Windows. Skrypt jedynie wykrywa Orinoco w lokalnej sieci. Nie pozwala na modyfikacje czegokolwiek. Po uruchomieniu skryptu, na konsoli otrzymujemy:

root@XXXXX:~# ./tools/scan-tool.pl
Dev   MAC Address        IP Address      s/d  Uptime        System Description
--------------------------------------------------------------------------------
eth2:
      00:20:A6:4A:XX:XX  192.168.XXX.XXX  s   013:00:12:22  AP-2000 v2.4.11(821)
      00:20:A6:4A:XX:XX  192.168.XXX.XXX  s   025:19:06:36  AP-2000 v2.4.11(821)

--------------------------------------------------------------------------------
eth0:
      00:02:2D:71:XX:XX  10.XXX.XXX.XXX   s   014:07:07:49  AP-2000 v2.4.11(821)
      00:02:2D:48:XX:XX  10.XXX.XXX.XXX   s   005:22:34:29  AP-2000 v2.4.11(821)

root@XXXXX:~#

Skrypt nie zawsze działa poprawnie, gdy na danym interfejsie mamy ustawiony więcej niż jeden adres IP z tej samej podsieci. Po uruchomieniu ./scan-tool.pl -v otrzymamy więcej informacji na konsoli.

Pobierz scan-tool.pl
#!/usr/bin/perl -w
 
###############################################################################
#
# scan_tool v.1.0.0
#
# scan utility for orinoco ap
#
# panther@mindc.net
# 2008-04-11
###############################################################################
 
use strict;
use IO::Socket;
use Data::Dumper;
use Time::HiRes qw( usleep );
 
use constant ST_BROADCAST => 'ab010000';
use constant ST_STATIC => 'ab03070f';
use constant ST_DYNAMIC => 'ab03040b';
use constant ST_BROADCAST_RESPONSE => 'ac0207ff';
use constant ST_RESPONSE => 'ac0407fe';
use constant ST_ERROR => 'acff0001';
use constant ST_PORT => 2719;
use constant FORMAT => "%-4s  %-17s  %-15s%3s  %-12s  %sn";
 
my $LPORT = 1000 + int rand 2000;
my %LADDR;
my $orinoco = { };
 
my $param = $ARGV[0] || '';
my $verbose = 0;$verbose = 1 if $param =~ m/^(-v|--verbose)$/;
my $debug = 0;$debug = 1 if $param =~ m/^(-d|--debug)$/;
 
foreach( reverse `/sbin/ip a`) {
    $LADDR{$2} = $1 if m/inets+(S+)/.*s(ethd+)(?:s|:)/;
}
 
printf FORMAT,'Dev','MAC Address','IP Address','s/d','Uptime','System Description';
 
foreach my $dev ( keys %LADDR ) {
    unless (fork) {
        if (fork) {
            my $socket = IO::Socket::INET->new( Proto => 'UDP',
                                                PeerPort => ST_PORT,
                                                LocalAddr => $LADDR{$dev},
                                                LocalPort => $LPORT,
                                                Reuse => 1) or die "cannot bind socket $!n";
            local $SIG{ALRM} = sub { close $socket;end($dev) };
            eval {
                alarm 1;
                while ( $socket->recv(my $data, 612) ) {
                    my ( $signature,$echo,$mac,undef, $ipaddr, $name, $uptime, $sysname, $tftpipaddr, $tftpfilename, $ipsubmask, $ipgw, $ipaddrtype) = unpack("H8 Z32 H12 H4 H8 Z32 N1 Z256 H8 Z256 H8 H8 L1",$data);
                    next if $signature ne ST_BROADCAST_RESPONSE;
                    $mac = uc join(':',unpack('H2' x 6,pack("H12",$mac)));
                    $orinoco->{$mac}{'signature'} = $signature;
                    $orinoco->{$mac}{'echo'} = $echo;
                    $orinoco->{$mac}{'ip'} = join('.',unpack("C4",pack("H8",$ipaddr)));
                    $orinoco->{$mac}{'name'} = $name;
                    $orinoco->{$mac}{'uptime'} = $uptime/100;
                    $orinoco->{$mac}{'desc'} = $sysname;
                    $orinoco->{$mac}{'tftp-ip'} = join('.',unpack("C4",pack("H8",$tftpipaddr)));
                    $orinoco->{$mac}{'tftp-filename'} = $tftpfilename;
                    $orinoco->{$mac}{'mask'} = join('.',unpack("C4",pack("H8",$ipsubmask)));;
                    $orinoco->{$mac}{'gateway'} = join('.',unpack("C4",pack("H8",$ipgw)));;
                    $orinoco->{$mac}{'dhcp'} = $ipaddrtype - 1;
                }
                alarm 0;
            };
            close $socket;
            end($dev);
        }
        else {
            my $socket = IO::Socket::INET->new( Proto => 'UDP',
                                                PeerPort => ST_PORT,
                                                PeerAddr => inet_ntoa(INADDR_BROADCAST),
                                                LocalAddr => $LADDR{$dev},
                                                LocalPort => $LPORT,
                                                Broadcast => 1,
                                                Reuse => 1) or die "cannot bind socket $!n";
            for (1..3) {
                usleep(200000);
                $socket->send(pack("H*",ST_BROADCAST . '00' x 608));
            }
            close $socket;
            exit;
        }
    }
}
 
1 while ( wait() != -1);
 
exit;
 
sub end {
    my $dev = shift;
    if ( my @aps = keys %$orinoco ) {
        print '-' x 80,"n";
        print "$dev:n";
        foreach ( @aps ) {
            my $d = $orinoco->{$_}{'dhcp'} ? ' d ' : ' s ';
            my $desc = $orinoco->{$_}{'desc'};
            $desc =~ s/(.*)s+SN.*/$1/ unless $verbose;
            printf FORMAT,'',$_,$orinoco->{$_}{'ip'},$d,uptime($orinoco->{$_}{'uptime'}),$desc;
            printf FORMAT,'','',$orinoco->{$_}{'mask'},'','',$orinoco->{$_}{'name'} if $verbose;
            printf FORMAT,'','',$orinoco->{$_}{'gateway'},'','','' if $verbose;
            print "n" if $verbose;
        }
        print Data::Dumper->Dump([$orinoco],[$dev]) if $param =~ m/^(--debug|-d)$/;
        print "n" unless $verbose;
    }
#    else {
#        printf FORMAT,'','-','-',' - ','-','-';
#    }
    exit;
}
 
sub uptime {
    my $time = shift;
    return sprintf "%03d:%02d:%02d:%02d",
        int($time/60/60/24),
        $time/60/60%24,
        $time/60%60,
        $time%60;
}
Nie ma jeszcze komentarzy.