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

# Content
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