#!/usr/bin/perl # # Kismetaclient # # Kis Metaclient? Kis met a client? Kismet "A" client? You choose. # # WARNING: Not to be taken internally. May cause nausea or drowsiness # amongst *real* perl programmers. If affected, do not drive or operate # machinery. # # Parts of this code are adapted from a pop3 client by Steffen Ullrich, # which I have been using and occasionally hacking since Tim Berners-Lee # was in short trousers. (Almost.) # # You may do what you like with this code, after all, you can't make it # any worse. Just so long as you don't criticize my perl programming # skills (and *certainly* not my sense of humour, should you detect any). # # (End of legal stuff) # # This is an incredibly simple, dumb, and amazingly stupid client for # Kismet, the wireless monitoring tool to be found at # www.kismetwireless.net # # Current versions of Kismet (Kismet-2007-01-R1b) do not allow capture of # status info to a file. Kismetaclient collects that info and writes it to # stdout, from whence you can easily redirect to a file. # # Should run under any Perl v4 or 5. On Windoze, suggest you use Cygwin # (www.cygwin.com) or any other free perl distro. # sub usage { &version; print STDERR "usage: kismetaclient.pl []\n"; print STDERR "-a Alerts\n"; print STDERR "-s Status\n"; print STDERR "-g String\n"; print STDERR "-t Prefix output with time stamp\n"; print STDERR "-l [] Lock source n (default: 0) to channel c, and exit\n"; print STDERR "-h [] Allow source n (default: 0) to channel-hop, and exit\n"; print STDERR "-v Output debug info\n"; print STDERR "-P Specify port number (default 2501)\n"; print STDERR "-S Specify server (default: localhost)\n"; print STDERR "-V Display version and exit\n"; print STDERR "(Default is -asg)\n"; exit(-1); } sub version { print STDERR "kismetaclient.pl version 0.1\n"; } # # signal handling # sub killme { print STDERR "killed\n"; exit(-1); } foreach (('HUP','INT','TERM')) { $SIG{$_}='killme'; } # # handle commandline # $0="kismetaclient.pl"; require 'getopts.pl'; &Getopts('S:P:agstlhvV'); &version,exit(0) if ($opt_V); if (! ($opt_a || $opt_g || $opt_s)) { $opt_a = true; $opt_g = true; $opt_s = true; } $opt_S = "localhost" unless ($opt_S); $opt_P = 2501 unless ($opt_P); $them = $opt_S; # # all the socket stuff # require 'socket.ph'; $port=$opt_P; $sockaddr = 'S n C4 x8'; ($name, $aliases, $proto) = getprotobyname('tcp'); die "getprotobyname: $!" unless $name; (($name, $aliases, $port) = getservbyname($port, 'tcp')) unless $port =~ /^\d+$/; chop($hostname = `hostname`); $hostname = "localhost"; ($name, $aliases, $type, $len, @thisaddr) = gethostbyname($hostname); die "gethostbyname: $!" unless $name; @thisbytes = unpack("C4", $thisaddr[0]); print STDERR "DBG: hostname=", $hostname, "; thisbytes=", $thisbytes[0], ".", $thisbytes[1], ".", $thisbytes[2], ".", $thisbytes[3], "\n" if ($opt_v); if (($them =~ /^\d+\./)) { @thatbytes = split(/\./, $them); } else { ($name, $aliases, $type, $len, @thataddr) = gethostbyname($them); die "gethostbyname: $!" unless $name; @thatbytes = unpack("C4", $thataddr[0]); } printf(STDERR "DBG: Them=%s; Name=%s; alias=%s;\nDBG: type=%d; len=%d; thataddr=%d.%d.%d.%d;\n", $them, $name, $aliases, $type, $len, @thatbytes) if ($opt_v); $this = pack($sockaddr, &AF_INET, 0, @thisbytes); $that = pack($sockaddr, &AF_INET, $port, @thatbytes); # # start connection # print STDERR "DBG: creating socket af=", &AF_INET, " type=", &SOCK_STREAM, " proto=", $proto, "\n" if ($opt_v); socket(S, &AF_INET, &SOCK_STREAM, $proto) || die "socket: $!"; # Bind not needed, may cause problems with AllowedHosts #printf STDERR "DBG: binding to port %d on %d.%d.%d.%d addr fam %d\n", # 0, (unpack(C4, $thisaddr[0])), &AF_INET if ($opt_v); #die "bind: $!" unless bind(S, $this); printf STDERR "DBG: connecting to port %d on %d.%d.%d.%d\n", $port, (unpack(C4, $thataddr[0])) if ($opt_v); $timeout=60; $SIG{'ALRM'}='timeout'; alarm($timeout); die "connect: $!" unless connect(S, $that); alarm(0); select(STDOUT); $| = 1; select(STDERR); $| = 1; select(S); $| = 1; while (!($line=&checkAnswer("KISMET"))) { } while (!($line=&checkAnswer("PROTOCOLS"))) { } if (! $opt_t) { print S "!1 REMOVE TIME\n"; print STDERR "DBG: < !1 REMOVE TIME\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } } if ($opt_l) { print STDERR "$#ARGV\n"; &usage if ($#ARGV < 0); $ARGV[1] = 0 if ($#ARGV == 0); print S "!1 CHANLOCK $ARGV[1] $ARGV[0]\n"; print STDERR "$#ARGV\n"; print STDERR "DBG: < !1 CHANLOCK $ARGV[1] $ARGV[0]\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } exit; } if ($opt_h) { $ARGV[0] = 0 if ($#ARGV < 0); print S "!1 CHANHOP $ARGV[0]\n"; print STDERR "DBG: < !1 CHANHOP $ARGV[0]\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } exit; } if ($opt_a) { print S "!2 ENABLE ALERT *\n"; print STDERR "DBG: < !2 ENABLE ALERT *\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } } if ($opt_s) { print S "!3 ENABLE STATUS *\n"; print STDERR "DBG: < !3 ENABLE STATUS *\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } } if ($opt_g) { print S "!4 ENABLE STRING *\n"; print STDERR "DBG: < !4 ENABLE STRING *\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } } print S "!5 ENABLE TERMINATE *\n"; print STDERR "DBG: < !5 ENABLE TERMINATE *\n" if ($opt_v); while (!($line=&checkAnswer("ACK"))) { } while (true) { if (!($line=)) { print STDERR "> EOF\n" if ($opt_v); exit(-1); } next if ($line=~/^\*STATUS: Saving data files/); if (($t) = ($line =~ /^\*TIME:\s*(\d+)/)) { # print STDERR "DBG: Time> $line\n" if ($opt_v); if ($opt_t) { ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime($t); $mon = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[$mon]; $wday = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")[$wday]; $year = $year + 1900; $time = sprintf("%3s %3s %2d %4d %02d:%02d:%02d ", $wday, $mon, $mday, $year, $hour, $min, $sec); } next; } print STDOUT "${time}$line"; } exit; ################################################################################ sub checkAnswer { print STDERR "DBG: waiting for $_[0] from kismet\n" if ($opt_v); local($line); if (!($line=)) { print STDERR "> EOF\n" if ($opt_v); exit(-1); } print STDERR "DBG: > $line\n" if ($opt_v); return $line if ($line=~/^\*$_[0]/); print(STDERR "> $line"),exit(-1) if ($line=~/^\*ERROR/); return ''; } sub timeout { print STDERR "connection timed out\n"; exit(-1); }