ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/wvsniff/wvsniff
Revision: 1.1
Committed: Fri Apr 26 21:46:20 2002 UTC (22 years, 1 month ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/usr/bin/perl
2    
3     use Event;
4     use Time::HiRes qw(time);
5     use Curses;
6     use Socket;
7    
8     $DEV = "eth1";
9     $RAWDEV = "wifi0";
10     $PROC = "/proc/driver/aironet/$DEV";
11    
12     $SIG{INT} =
13     $SIG{TERM} =
14     $SIG{HUP} = sub { exit };
15    
16     sub config {
17     open my $config, ">$PROC/Config"
18     or die "$PROC/Config: $!";
19     print $config $_[0];
20     }
21    
22     config "Mode: yna\n";
23     system "ifconfig", $DEV, "up";
24     system "ifconfig", $RAWDEV, "up";
25    
26     my $initscr;
27     sub init_screen {
28     initscr;
29     $initscr = 1;
30     start_color;
31     cbreak; noecho;
32     immedok 0; nonl; raw; intrflush 0; keypad 1;
33     idlok 1; scrollok 0; leaveok 0;
34     }
35    
36     sub end_win {
37     endwin if $initscr--;
38     }
39    
40     init_screen;
41    
42     my $refresh = Event->idle(nice => -5, parked => 1, min => 0.01, max => 1, repeat => 0, cb => sub {
43     @menu = ();
44     &$curmenu;
45    
46     $menu_idx += @menu if $menu_idx < 0;
47     $menu_idx -= @menu if $menu_idx >= @menu;
48    
49     erase;
50    
51     move 0, 0;
52     addstr $frame++;
53    
54     for my $idx (0 .. $#menu) {
55     move 1 + $idx, 0;
56     standout if $idx == $menu_idx;
57     addstr $menu[$idx][0];
58     standend if $idx == $menu_idx;
59     }
60    
61     move 2 + scalar@menu, 0;
62     eval {
63     $menu[$menu_idx][1]->();
64     };
65    
66     refresh;
67     });
68    
69     Event->io(fd => \*STDIN, poll => 'r', cb => sub {
70     my $ch = getch;
71     if ($ch eq "\x1b" or $ch eq "q") {
72     Event::unloop;
73     } elsif ($ch eq KEY_DOWN or $ch eq "j") {
74     $menu_idx++;
75     } elsif ($ch eq KEY_UP or $ch eq "k") {
76     $menu_idx--;
77     } else {
78     eval {
79     $menu[$menu_idx][2]->($ch);
80     };
81     }
82     $refresh->start;
83     });
84    
85     END {
86     end_win;
87     config "Mode: adhoc\n";
88     }
89    
90     sub decode_tags {
91     my $pkt = shift;
92     my %tag;
93    
94     while ($pkt) {
95     my ($id, $len) = unpack "C C", $pkt;
96     my $data = substr $pkt, 2, $len;
97     $pkt = substr $pkt, 2 + $len;
98    
99     $id = ({
100     0 => SSID,
101     1 => rates,
102     2 => FH,
103     3 => DS,
104     4 => CF,
105     5 => TIM,
106     6 => IBSS,
107     16 => challenge,
108     })->{$id};
109     $tag{$id} = $data;
110     }
111    
112     %tag;
113     }
114    
115     sub PF_PACKET (){ 17 }
116     sub SOCK_RAW (){ 3 }
117     sub ETH_P_ALL (){ 0x0003 }
118     sub SIOCGIFINDEX (){ 0x000008933 }
119    
120     sub open_pcap_socket {
121     socket my $cap, PF_PACKET, SOCK_RAW, (unpack "s", pack "n", ETH_P_ALL)
122     or die "unable to open packet socket: $!";
123    
124     my $ifidx = pack "a16 I", $RAWDEV;
125     ioctl $cap, SIOCGIFINDEX, $ifidx
126     or die "can't get index of interface $RAWDEV: $!";
127     $ifidx = unpack "x16 I", $ifidx;
128    
129     bind $cap, pack "S! S! I S! C C a8", PF_PACKET, (unpack "s", pack "n", ETH_P_ALL), $ifidx
130     or die "unable to bind to interface: $!";
131    
132     $cap;
133     }
134    
135     sub e2h($) {
136     join ":", map unpack("H*", $_), split //, $_[0];
137     }
138    
139     sub add_menu {
140     my ($title, $display, $select) = @_;
141     push @menu, [$title, $display, $select];
142     }
143    
144     $curmenu = \&menu_bss_list;
145    
146     sub bss2string {
147     my $bss = shift;
148    
149     my $s = "AGE(" . int(time - $bss->{ts}) . ") "
150     . "IP($bss->{ip}) "
151     . "ARP($bss->{arp}) ";
152     while (my ($k, $v) = each %{$bss->{ap}}) {
153     $s .= "(" . e2h($k) . " $v->{mode} '$v->{essid}') ";
154     }
155     $s;
156     }
157    
158     sub display_bss {
159     my $bss = shift;
160    
161     addstr "TS: $bss->{ts}\n";
162     addstr "ARP/IP packets received: $bss->{arp}/$bss->{ip}\n";
163    
164     addstr "\naccess points\n";
165    
166     while (my ($k, $v) = each %{$bss->{ap}}) {
167     addstr " " . e2h($k) . "\n";
168     addstr " mode $v->{mode}, channel $v->{channel}, essid '$v->{essid}'\n";
169     addstr " beacon frames received $v->{beacon}\n";
170     }
171    
172     addstr "\nstations\n";
173    
174     while (my ($k, $v) = each %{$bss->{station}}) {
175     addstr " " . e2h($k);
176     while (my ($k, $v) = each %$v) {
177     addstr " " . (inet_ntoa $k) . "($v)";
178     }
179     addstr "\n";
180     }
181     }
182    
183     sub menu_bss_list {
184     my @menu;
185     while (my ($k, $v) = each %$db) {
186     add_menu e2h($k) . " " . bss2string($v),
187     sub { display_bss $v },
188     sub {
189     if ($_[0] eq KEY_LEFT or $_[0] eq "h") {
190     Event::unloop;
191     } elsif ($_[0] eq KEY_RIGHT or $_[0] eq "l") {
192     #$curmenu = sub { display_bss $k };
193     }
194     } for 1..3;
195     }
196     }
197    
198     sub activity {
199     $db->{$_[0]}->{ts} = time;
200     #print "activity ", e2h $_[0]; print "\n";
201     $refresh->start;
202     }
203    
204     sub reg_ip {
205     my ($bssid, $ip, $ether) = @_;
206     $db->{$bssid}{station}{$ether}{$ip}++;
207     activity $bssid;
208     }
209    
210     {
211     my $cap = open_pcap_socket;
212     my $pkt;
213    
214     Event->io(fd => $cap, poll => 'r', cb => sub {
215     sysread $$cap, $pkt, 120;
216    
217     my ($fc1, $fc2, $sid, $a1, $a2, $a3, $sc, $pkt)
218     = unpack "C C n a6 a6 a6 S a*", $pkt;
219    
220     $pkt = substr $pkt, 6 if $fc2 & 0x03 == 0x03; # skip A4
221    
222     if ($fc1 == 0x80 or $fc1 == 0x50) {
223     my ($ts1, $ts2, $bi, $cf, $pkt)
224     = unpack "L L S S a*", $pkt;
225    
226     my %tag = decode_tags $pkt;
227    
228     my $ap = $db->{$a3}{ap}{$a2} ||= {};
229     $ap->{mode} = ($cf & 3) == 1 ? "AP" : "adhoc";
230     $ap->{essid} = $tag{SSID};
231     $ap->{channel} = ord $tag{DS};
232     $ap->{beacon}++;
233    
234     activity $a3;
235     } elsif ($fc1 == 0x08) {
236     my $bssid = ($a3, $a2, $a1)[$fc2 & 3];
237    
238     my ($llc, $et, $pkt) = unpack "a6 n a*", $pkt;
239     if ($llc eq "\xaa\xaa\x03\x00\x00\x00") { # SNAP/UI/ENCAP_ETHER
240     if ($et == 0x0800) {
241     my ($vhl, $tos, $len, $id, $off, $ttl, $prot, $sum, $src, $dst, $pkt)
242     = unpack "C C n n n C C n a4 a4 a*", $pkt;
243     if ($vhl & 0x40 == 0x40) {
244     $db->{$bssid}{ip}++;
245     reg_ip $bssid, $src, $a2;
246     reg_ip $bssid, $dst, $a1;
247     0 &&
248     printf "IP: %02x %02x %04x %04x: %s %s> %s %s %02x \n",
249     $fc1, $fc2, $sid, $sc,
250     (unpack "H*", $a2), (inet_ntoa $src),
251     (unpack "H*", $a1), (inet_ntoa $dst),
252     $prot;
253     }
254     } elsif ($et == 0x0806) {
255     my ($hrd, $pro, $hln, $pln, $op, $src_hw, $src, $dst_hw, $dst)
256     = unpack "n n C C n a6 a4 a6 a4", $pkt;
257     if ($hrd == 1 and $hln == 6 and $pln == 4) {
258     reg_ip $bssid, $src, $src_hw;
259     reg_ip $bssid, $dst, $dst_hw if $op != 1;
260     $db->{$bssid}{arp}++;
261     0 &&
262     printf "ARP: %04x> %s %s : %s %s\n",
263     $op,
264     (unpack "H*", $src_hw), (inet_ntoa $src),
265     (unpack "H*", $dst_hw), (inet_ntoa $dst);
266     }
267     }
268     } else {
269     0 &&
270     printf "?? %02x %02x %04x %04x: %s.%s \n", $fc1, $fc2, $sid, $sc, (unpack "H*", $llc), unpack "H*", $pkt;
271     }
272     } elsif ($fc1 != 0x40 and $fc1 != 0x10 and $fc1 != 0x00 and $fc1 != 0xb0) {
273     0 &&
274     printf "%02x %02x %04x %04x: %s \n", $fc1, $fc2, $sid, $sc, unpack "H*", $pkt;
275     }
276     });
277     }
278    
279     Event::loop;
280    
281