ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/wvsniff/wvsniff
Revision: 1.4
Committed: Fri Apr 26 22:03:29 2002 UTC (22 years, 1 month ago) by root
Branch: MAIN
Changes since 1.3: +2 -3 lines
Log Message:
*** empty log message ***

File Contents

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