… | |
… | |
3 | use Event; |
3 | use Event; |
4 | use Time::HiRes qw(time); |
4 | use Time::HiRes qw(time); |
5 | use Curses; |
5 | use Curses; |
6 | use Socket; |
6 | use Socket; |
7 | use Storable; |
7 | use Storable; |
8 | use GPS; |
|
|
9 | |
|
|
10 | my $GPS = eval { new GPS }; |
|
|
11 | |
8 | |
12 | $DEV = "eth1"; |
9 | $DEV = "eth1"; |
13 | $RAWDEV = "wifi0"; |
10 | $RAWDEV = "wifi0"; |
14 | $PROC = "/proc/driver/aironet/$DEV"; |
11 | $PROC = "/proc/driver/aironet/$DEV"; |
15 | $STOREFILE = "wvsniff.dat"; |
12 | $STOREFILE = "wvsniff.dat"; |
|
|
13 | |
|
|
14 | my $GPS = eval { require GPSx; new GPS }; |
16 | |
15 | |
17 | $SIG{INT} = |
16 | $SIG{INT} = |
18 | $SIG{TERM} = |
17 | $SIG{TERM} = |
19 | $SIG{HUP} = sub { exit }; |
18 | $SIG{HUP} = sub { exit }; |
20 | |
19 | |
… | |
… | |
145 | my $ifidx = pack "a16 I", $RAWDEV; |
144 | my $ifidx = pack "a16 I", $RAWDEV; |
146 | ioctl $cap, SIOCGIFINDEX, $ifidx |
145 | ioctl $cap, SIOCGIFINDEX, $ifidx |
147 | or die "can't get index of interface $RAWDEV: $!"; |
146 | or die "can't get index of interface $RAWDEV: $!"; |
148 | $ifidx = unpack "x16 I", $ifidx; |
147 | $ifidx = unpack "x16 I", $ifidx; |
149 | |
148 | |
150 | bind $cap, pack "S! S! I S! C C a8", PF_PACKET, (unpack "s", pack "n", ETH_P_ALL), $ifidx |
149 | $::sockaddr = pack "S! S! I S! C C a8", PF_PACKET, (unpack "s", pack "n", ETH_P_ALL), $ifidx; |
|
|
150 | bind $cap, $::sockaddr |
151 | or die "unable to bind to interface: $!"; |
151 | or die "unable to bind to interface: $!"; |
152 | |
152 | |
153 | $cap; |
153 | $cap; |
|
|
154 | } |
|
|
155 | |
|
|
156 | sub escape($) { |
|
|
157 | local $_ = $_[0]; |
|
|
158 | s/([^\x20-\x7e])/sprintf "\\%03o", ord $1/ge; |
|
|
159 | $_; |
154 | } |
160 | } |
155 | |
161 | |
156 | sub e2h($) { |
162 | sub e2h($) { |
157 | join ":", map unpack("H*", $_), split //, $_[0]; |
163 | join ":", map unpack("H*", $_), split //, $_[0]; |
158 | } |
164 | } |
… | |
… | |
169 | |
175 | |
170 | my $s = "AGE(" . int(time - $bss->{ts}) . ") " |
176 | my $s = "AGE(" . int(time - $bss->{ts}) . ") " |
171 | . "IP($bss->{ip}) " |
177 | . "IP($bss->{ip}) " |
172 | . "ARP($bss->{arp}) "; |
178 | . "ARP($bss->{arp}) "; |
173 | while (my ($k, $v) = each %{$bss->{ap}}) { |
179 | while (my ($k, $v) = each %{$bss->{ap}}) { |
174 | $s .= "(" . e2h($k) . " $v->{mode} '$v->{essid}') "; |
180 | $s .= "(" . e2h($k) . " $v->{mode} '".escape($v->{essid})."') "; |
175 | } |
181 | } |
176 | $s; |
182 | $s; |
177 | } |
183 | } |
178 | |
184 | |
179 | sub show_map { |
185 | sub show_map { |
180 | my ($map, $w, $h) = @_; |
186 | my ($map, $w, $h) = @_; |
181 | |
187 | |
182 | my $data = $GPS->data; |
188 | my $data = $GPS->data; |
183 | |
|
|
184 | local $map->{"$data->{lat};$data->{long}"} = 0; |
189 | local $map->{"$data->{lat};$data->{long}"} = 0; |
185 | |
190 | |
186 | my @data = (("-" x $w) x $h); |
191 | my @data = (("-" x $w) x $h); |
187 | |
192 | |
188 | my ($x1, $y1, $x2, $y2) = (1e6, 1e6, 1e-6, 1e-6); |
193 | my ($x1, $y1, $x2, $y2) = (1e6, 1e6, 1e-6, 1e-6); |
… | |
… | |
204 | my ($y, $x) = split /;/, $k; |
209 | my ($y, $x) = split /;/, $k; |
205 | |
210 | |
206 | $y = ($y - $y1) * $y2; |
211 | $y = ($y - $y1) * $y2; |
207 | $x = ($x - $x1) * $x2; |
212 | $x = ($x - $x1) * $x2; |
208 | |
213 | |
209 | substr $data[$y], $x, 1, int($map->{$k} * 9 / $level); |
214 | substr $data[$h-1-int $y], $x, 1, int($map->{$k} * 9 / $level); |
210 | } |
215 | } |
211 | |
216 | |
212 | for (@data) { |
217 | for (@data) { |
213 | addstr $_ . "\n"; |
218 | addstr $_ . "\n"; |
214 | } |
219 | } |
… | |
… | |
223 | |
228 | |
224 | addstr "\naccess points\n"; |
229 | addstr "\naccess points\n"; |
225 | |
230 | |
226 | while (my ($k, $v) = each %{$bss->{ap}}) { |
231 | while (my ($k, $v) = each %{$bss->{ap}}) { |
227 | addstr " " . e2h($k) . "\n"; |
232 | addstr " " . e2h($k) . "\n"; |
228 | addstr " mode $v->{mode}; channel $v->{channel}; essid '$v->{essid}'; beacon frames $v->{beacon}\n"; |
233 | addstr " mode $v->{mode}; channel $v->{channel}; essid '".escape($v->{essid})."'; beacon frames $v->{beacon}\n"; |
229 | } |
234 | } |
230 | |
235 | |
231 | addstr "\nstations\n"; |
236 | addstr "\nstations\n"; |
232 | |
237 | |
233 | while (my ($k, $v) = each %{$bss->{station}}) { |
238 | while (my ($k, $v) = each %{$bss->{station}}) { |
… | |
… | |
246 | } |
251 | } |
247 | } |
252 | } |
248 | |
253 | |
249 | sub menu_bss_list { |
254 | sub menu_bss_list { |
250 | my @menu; |
255 | my @menu; |
251 | for my $k (sort { int $db->{$b}{ts} <=> int $db->{$a}{ts} } keys %$db) { |
256 | #for my $k (sort { int $db->{$b}{ts} <=> int $db->{$a}{ts} } keys %$db) { |
|
|
257 | for my $k (keys %$db) { |
252 | my $v = $db->{$k}; |
258 | my $v = $db->{$k}; |
253 | add_menu e2h($k) . " " . bss2string($v), |
259 | add_menu e2h($k) . " " . bss2string($v), |
254 | sub { display_bss $v }, |
260 | sub { display_bss $v }, |
255 | sub { |
261 | sub { |
256 | if ($_[0] eq KEY_LEFT or $_[0] eq "h") { |
262 | if ($_[0] eq KEY_LEFT or $_[0] eq "h") { |
… | |
… | |
287 | |
293 | |
288 | printf LOG "%s\n", unpack "H*", $pkt; |
294 | printf LOG "%s\n", unpack "H*", $pkt; |
289 | |
295 | |
290 | my ($fc1, $fc2, $sid, $a1, $a2, $a3, $sc, $pkt) |
296 | my ($fc1, $fc2, $sid, $a1, $a2, $a3, $sc, $pkt) |
291 | = unpack "C C n a6 a6 a6 S a*", $pkt; |
297 | = unpack "C C n a6 a6 a6 S a*", $pkt; |
|
|
298 | |
|
|
299 | send $cap, (pack "C C n a6 a6 a6 S a*", $fc1, $fc2, $sid, $a2, $a1, $a3, $sc, $pkt), 0, $::sockaddr; |
292 | |
300 | |
293 | my $a4; |
301 | my $a4; |
294 | |
302 | |
295 | if ($fc2 & 0x03 == 0x03) { |
303 | if ($fc2 & 0x03 == 0x03) { |
296 | $a4 = substr $pkt, 0, 6; |
304 | $a4 = substr $pkt, 0, 6; |