1 /*-
2 * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: src/tools/tools/net80211/stumbler/stumbler.c,v 1.2 2009/07/24 15:31:22 sam Exp $
27 */
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #include <sys/select.h>
32 #include <sys/time.h>
33 #include <net/if.h>
34 #include <net/if_media.h>
35 #include <net/bpf.h>
36 #include <netproto/802_11/ieee80211_ioctl.h>
37 #include <netproto/802_11/ieee80211.h>
38 #include <net/ethernet.h>
39 #include <netproto/802_11/ieee80211_radiotap.h>
40 #include <sys/endian.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <curses.h>
47 #include <signal.h>
48 #include <unistd.h>
49 #include <assert.h>
50
51 //int hopfreq = 3*1000; // ms
52 int hopfreq = 500; // ms
53 int sig_reset = 1*1000; // ms
54
55
56 int ioctl_s = -1;
57 int bpf_s = -1;
58
59 struct chan_info {
60 int locked;
61 int chan;
62 struct ieee80211req ireq;
63 struct timeval last_hop;
64 } chaninfo;
65
66
67 #define CRYPT_NONE 0
68 #define CRYPT_WEP 1
69 #define CRYPT_WPA1 2
70 #define CRYPT_WPA 3
71 #define CRYPT_WPA1_TKIP 4
72 #define CRYPT_WPA1_TKIP_PSK 5
73 #define CRYPT_WPA1_CCMP 6
74 #define CRYPT_WPA1_CCMP_PSK 7
75 #define CRYPT_80211i 8
76 #define CRYPT_80211i_TKIP 9
77 #define CRYPT_80211i_TKIP_PSK 10
78
79 struct node_info {
80 unsigned char mac[6];
81 int signal;
82 int noise;
83 int max;
84 unsigned char ssid[256];
85 int chan;
86 int wep;
87 int pos;
88 int ap;
89
90 struct timeval seen;
91
92 struct node_info* prev;
93 struct node_info* next;
94 } *nodes = NULL;
95
clean_crap()96 void clean_crap() {
97 struct node_info* next;
98
99 if (ioctl_s != -1)
100 close(ioctl_s);
101 if (bpf_s != -1)
102 close(bpf_s);
103
104 while (nodes) {
105 next = nodes->next;
106 free(nodes);
107 nodes = next;
108 }
109 }
110
mac2str(unsigned char * mac)111 char* mac2str(unsigned char* mac) {
112 static char ret[6*3];
113
114 sprintf(ret, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
115 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
116
117 return ret;
118 }
119
wep2str(int w)120 char* wep2str(int w) {
121 char* wep = NULL;
122 static char res[14];
123
124 switch (w) {
125 case CRYPT_NONE:
126 wep = "";
127 break;
128
129 case CRYPT_WEP:
130 wep = "WEP";
131 break;
132
133 case CRYPT_WPA1:
134 wep = "WPA1";
135 break;
136
137 case CRYPT_WPA:
138 wep = "WPA?";
139 break;
140
141 case CRYPT_WPA1_TKIP:
142 wep = "WPA1-TKIP";
143 break;
144
145 case CRYPT_WPA1_TKIP_PSK:
146 wep = "WPA1-TKIP-PSK";
147 break;
148
149 case CRYPT_WPA1_CCMP:
150 wep = "WPA1-CCMP";
151 break;
152
153 case CRYPT_WPA1_CCMP_PSK:
154 wep = "WPA1-CCMP-PSK";
155 break;
156
157 case CRYPT_80211i:
158 wep = "i";
159 break;
160
161 case CRYPT_80211i_TKIP:
162 wep = "11i-TKIP";
163 break;
164
165 case CRYPT_80211i_TKIP_PSK:
166 wep = "11i-TKIP-PSK";
167 break;
168
169 default:
170 wep = "FIXME!";
171 break;
172 }
173
174 memset(res, ' ', sizeof(res));
175 assert(strlen(wep) < sizeof(res));
176 memcpy(res, wep, strlen(wep));
177 res[sizeof(res)-1] = 0;
178 return res;
179 }
180
ssid2str(struct node_info * node)181 char* ssid2str(struct node_info* node) {
182 static char res[24];
183
184 memset(res, ' ', sizeof(res));
185 res[0] = '[';
186 strcpy(&res[sizeof(res)-2], "]");
187
188 if (node->ap) {
189 int left = sizeof(res) - 3;
190
191 if (strlen(node->ssid) < left)
192 left = strlen(node->ssid);
193 memcpy(&res[1], node->ssid, left);
194 }
195 else {
196 memcpy(&res[1], "<client>", 8);
197 }
198 return res;
199 }
200
save_state()201 void save_state() {
202 FILE* f;
203 struct node_info* node = nodes;
204
205 f = fopen("stumbler.log", "w");
206 if (!f) {
207 perror("fopen()");
208 exit(1);
209 }
210
211 while (node) {
212 struct tm* t;
213 char tim[16];
214
215 t = localtime( (time_t*) &node->seen.tv_sec);
216 if (!t) {
217 perror("localtime()");
218 exit(1);
219 }
220 tim[0] = 0;
221 strftime(tim, sizeof(tim), "%H:%M:%S", t);
222
223 fprintf(f, "%s %s %s %2d %s 0x%.2x\n", tim,
224 mac2str(node->mac), wep2str(node->wep),
225 node->chan, ssid2str(node), node->max);
226
227 node = node->next;
228 }
229
230 fclose(f);
231 }
232
cleanup(int x)233 void cleanup(int x) {
234 endwin();
235 clean_crap();
236 exit(0);
237 }
238
die(int p,char * msg)239 void die(int p, char* msg) {
240 endwin();
241 if (p)
242 perror(msg);
243 else
244 printf("%s\n", msg);
245 clean_crap();
246 exit(1);
247 }
248
display_chan()249 void display_chan() {
250 int x, y;
251 char tmp[3];
252
253 x = COLS - 2;
254 y = LINES - 1;
255
256 snprintf(tmp, sizeof(tmp), "%.2d", chaninfo.chan);
257 mvaddstr(y, x, tmp);
258 refresh();
259 }
260
set_chan(int c)261 void set_chan(int c) {
262 chaninfo.ireq.i_val = c;
263
264 if (ioctl(ioctl_s, SIOCS80211, &chaninfo.ireq) == -1)
265 die(1, "ioctl(SIOCS80211) [chan]");
266
267 chaninfo.chan = c;
268
269 if (gettimeofday(&chaninfo.last_hop, NULL) == -1)
270 die(1, "gettimeofday()");
271
272 display_chan();
273 }
274
setup_if(char * dev)275 void setup_if(char *dev) {
276 struct ifreq ifr;
277 unsigned int flags;
278
279 // set chan
280 memset(&chaninfo.ireq, 0, sizeof(chaninfo.ireq));
281 strcpy(chaninfo.ireq.i_name, dev);
282 chaninfo.ireq.i_type = IEEE80211_IOC_CHANNEL;
283
284 set_chan(1);
285
286 // set iface up and promisc
287 memset(&ifr, 0, sizeof(ifr));
288 strcpy(ifr.ifr_name, dev);
289 if (ioctl(ioctl_s, SIOCGIFFLAGS, &ifr) == -1)
290 die(1, "ioctl(SIOCGIFFLAGS)");
291
292 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
293 flags |= IFF_UP | IFF_PPROMISC;
294
295 memset(&ifr, 0, sizeof(ifr));
296 strcpy(ifr.ifr_name, dev);
297 ifr.ifr_flags = flags & 0xffff;
298 ifr.ifr_flagshigh = flags >> 16;
299 if (ioctl(ioctl_s, SIOCSIFFLAGS, &ifr) == -1)
300 die(1, "ioctl(SIOCSIFFLAGS)");
301 }
302
open_bpf(char * dev,int dlt)303 void open_bpf(char *dev, int dlt) {
304 int i;
305 char buf[64];
306 int fd = -1;
307 struct ifreq ifr;
308
309 for(i = 0;i < 16; i++) {
310 sprintf(buf, "/dev/bpf%d", i);
311
312 fd = open(buf, O_RDWR);
313 if(fd < 0) {
314 if(errno != EBUSY)
315 die(1,"can't open /dev/bpf");
316 continue;
317 }
318 else
319 break;
320 }
321
322 if(fd < 0)
323 die(1, "can't open /dev/bpf");
324
325 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
326 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
327
328 if(ioctl(fd, BIOCSETIF, &ifr) < 0)
329 die(1, "ioctl(BIOCSETIF)");
330
331 if (ioctl(fd, BIOCSDLT, &dlt) < 0)
332 die(1, "ioctl(BIOCSDLT)");
333
334 i = 1;
335 if(ioctl(fd, BIOCIMMEDIATE, &i) < 0)
336 die(1, "ioctl(BIOCIMMEDIATE)");
337
338 bpf_s = fd;
339 }
340
user_input()341 void user_input() {
342 static char chan[3];
343 static int pos = 0;
344 int c;
345
346 c = getch();
347
348 switch (c) {
349 case 'w':
350 save_state();
351 break;
352
353 case 'q':
354 cleanup(0);
355 break;
356
357 case 'c':
358 chaninfo.locked = !chaninfo.locked;
359 break;
360
361 case ERR:
362 die(0, "getch()");
363 break;
364
365 case '0':
366 case '1':
367 case '2':
368 case '3':
369 case '4':
370 case '5':
371 case '6':
372 case '7':
373 case '8':
374 case '9':
375 chan[pos++] = c;
376 if (pos == 2) {
377 int ch = atoi(chan);
378 if (ch <= 11 && ch >= 1) {
379 set_chan(atoi(chan));
380 chaninfo.locked = 1;
381 }
382 pos = 0;
383 }
384 break;
385
386 default:
387 pos = 0;
388 break;
389 }
390 }
391
display_node(struct node_info * node)392 void display_node(struct node_info* node) {
393 int x = 0;
394 int y = 0;
395 int i;
396 char chan[3];
397 char* ssid = NULL;
398 int sig, max, left, noise;
399 char* wep = NULL;
400
401 y = node->pos;
402 if (y == -1) // offscreen
403 return;
404
405 assert(y < LINES);
406
407 // MAC
408 mvaddstr(y, x, mac2str(node->mac));
409 x += 6*3;
410
411 // WEP
412 wep = wep2str(node->wep);
413 assert(wep);
414 mvaddstr(y, x, wep);
415 x += strlen(wep);
416 x++;
417
418 // CHAN
419 sprintf(chan, "%.2d", node->chan);
420 mvaddstr(y, x, chan);
421 x += 3;
422
423 // ssid
424 ssid = ssid2str(node);
425 assert(ssid);
426 mvaddstr(y, x, ssid);
427 x += strlen(ssid);
428 x++;
429
430 left = COLS - x - 1;
431
432 sig = (int) ( ((double)node->signal)*left/100.0 );
433 noise=(int) ( ((double)node->noise)*left/100.0 );
434 max = (int) ( ((double)node->max)*left/100.0 );
435
436 // SIGNAL BAR
437 for (i = 0; i < noise; i++)
438 mvaddch(y, x++, 'N');
439
440 for (; i < sig; i++)
441 mvaddch(y,x++, 'X');
442
443 for (; i < max; i++)
444 mvaddch(y,x++, ' ');
445 mvaddch(y,x++, '|');
446
447 for (; x < COLS-1; x++)
448 mvaddch(y, x, ' ');
449
450 assert (x <= COLS);
451 }
452
update_node(struct node_info * data)453 void update_node(struct node_info* data) {
454 struct node_info* node;
455 int sort = 0;
456
457 assert(data->signal <= 100);
458
459 node = nodes;
460
461 // first time [virgin]
462 if (!node) {
463 node = (struct node_info*) malloc(sizeof(struct node_info));
464 if (!node)
465 die(1, "malloc()");
466
467 memset(node, 0, sizeof(*node));
468 memcpy(node->mac, data->mac, 6);
469 nodes = node;
470 }
471
472 while (node) {
473 // found it
474 if (memcmp(node->mac, data->mac, 6) == 0)
475 break;
476
477 // end of chain
478 if (!node->next) {
479 node->next = (struct node_info*)
480 malloc(sizeof(struct node_info));
481 if (!node->next)
482 die(1, "malloc()");
483
484 memset(node->next, 0, sizeof(*node->next));
485 memcpy(node->next->mac, data->mac, 6);
486 node->next->prev = node;
487 node->next->pos = node->pos+1;
488
489 node = node->next;
490 if (node->pos == LINES)
491 sort = 1;
492 break;
493 }
494
495 node = node->next;
496 }
497 assert(node);
498
499 // too many nodes for screen
500 if (sort) {
501 struct node_info* ni = nodes;
502
503 while (ni) {
504 if (ni->pos != -1)
505 ni->pos--;
506
507 display_node(ni);
508 ni = ni->next;
509 }
510 }
511
512 node->signal = data->signal;
513 if (data->signal > node->max)
514 node->max = data->signal;
515
516 if (gettimeofday(&node->seen, NULL) == -1)
517 die(1, "gettimeofday()");
518
519 if (data->ssid[0] != 0)
520 strcpy(node->ssid, data->ssid);
521 if (data->chan != -1)
522 node->chan = data->chan;
523 if (data->wep != -1) {
524 // XXX LAME --- won't detect if AP changes WEP mode in
525 // beacons...
526 if (node->wep != CRYPT_WEP &&
527 node->wep != CRYPT_NONE &&
528 data->wep == CRYPT_WEP) {
529 }
530 else
531 node->wep = data->wep;
532 }
533 if (data->ap != -1)
534 node->ap = data->ap;
535
536 display_node(node);
537 refresh();
538 }
539
get_beacon_info(unsigned char * data,int rd,struct node_info * node)540 void get_beacon_info(unsigned char* data, int rd,
541 struct node_info* node) {
542
543 int blen = 8 + 2 + 2;
544
545 strcpy(node->ssid, "<hidden>");
546 node->chan = 0;
547 node->wep = CRYPT_NONE;
548
549 assert(rd >= blen);
550
551 if (IEEE80211_BEACON_CAPABILITY(data) & IEEE80211_CAPINFO_PRIVACY)
552 node->wep = CRYPT_WEP;
553
554 data += blen;
555 rd -= blen;
556
557 while (rd > 2) {
558 int eid, elen;
559
560 eid = *data;
561 data++;
562 elen = *data;
563 data++;
564 rd -= 2;
565
566 // short!
567 if (rd < elen) {
568 return;
569 }
570
571 // ssid
572 if (eid == 0) {
573 if (elen == 1 && data[0] == 0) {
574 // hidden
575 }
576 else {
577 memcpy(node->ssid, data, elen);
578 node->ssid[elen] = 0;
579 }
580 }
581 // chan
582 else if(eid == 3) {
583 // weird chan!
584 if( elen != 1)
585 goto next;
586
587 node->chan = *data;
588 }
589 // WPA
590 else if (eid == 221 && node->wep == CRYPT_WEP) {
591 struct ieee80211_ie_wpa* wpa;
592
593 wpa = (struct ieee80211_ie_wpa*) data;
594 if (elen < 6)
595 goto next;
596
597 if (!memcmp(wpa->wpa_oui, "\x00\x50\xf2", 3)) {
598 // node->wep = CRYPT_WPA;
599 }
600 else
601 goto next;
602
603 if (wpa->wpa_type == WPA_OUI_TYPE &&
604 le16toh(wpa->wpa_version) == WPA_VERSION) {
605 int cipher, auth;
606 unsigned char* ptr;
607
608 node->wep = CRYPT_WPA1;
609
610 if (elen < 12)
611 goto next;
612
613 cipher = ((unsigned char*) wpa->wpa_mcipher)[3];
614
615 ptr = (unsigned char*)wpa + 12 +
616 4 * le16toh(wpa->wpa_uciphercnt);
617
618 if (elen < (ptr - data + 6))
619 goto next;
620
621 if ( *((unsigned short*) ptr) == 0)
622 goto next;
623
624 ptr += 2 + 3;
625 auth = *ptr;
626
627 if (cipher == WPA_CSE_TKIP) {
628 node->wep = CRYPT_WPA1_TKIP;
629
630 if (auth == WPA_ASE_8021X_PSK)
631 node->wep = CRYPT_WPA1_TKIP_PSK;
632 }
633
634 if (cipher == WPA_CSE_CCMP) {
635 node->wep = CRYPT_WPA1_CCMP;
636
637 if (auth == WPA_ASE_8021X_PSK)
638 node->wep = CRYPT_WPA1_CCMP_PSK;
639 }
640 }
641 }
642 else if (eid == 48 && node->wep == CRYPT_WEP) {
643 unsigned char* ptr;
644
645 // XXX no bounds checking
646 ptr = data;
647
648 if (ptr[0] == 1 && ptr[1] == 0) {
649 unsigned short* count;
650 int cipher = 0;
651
652 ptr += 2;
653 node->wep = CRYPT_80211i;
654
655 if (!memcmp(ptr, "\x00\x0f\xac\x02", 4)) {
656 node->wep = CRYPT_80211i_TKIP;
657 cipher = 1;
658 }
659
660 ptr += 4;
661 count = (unsigned short*) ptr;
662 ptr +=2 + *count*4;
663
664 count = (unsigned short*) ptr;
665 if (*count) {
666 ptr += 2;
667
668 if (!memcmp(ptr,"\x00\x0f\xac\x02", 4)) {
669 if (cipher)
670 node->wep = CRYPT_80211i_TKIP_PSK;
671 }
672 }
673 }
674 }
675
676 next:
677 data += elen;
678 rd -= elen;
679 }
680 }
681
get_packet_info(struct ieee80211_frame * wh,unsigned char * body,int bodylen,struct node_info * node)682 int get_packet_info(struct ieee80211_frame* wh,
683 unsigned char* body, int bodylen,
684 struct node_info* node) {
685
686 int type, stype;
687
688 node->chan = chaninfo.chan;
689 node->wep = -1;
690 node->ssid[0] = 0;
691 node->ap = -1;
692
693 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
694
695 if (type == IEEE80211_FC0_TYPE_CTL)
696 return 0;
697 #if 0
698 if (wh->i_addr2[0] != 0) {
699 mvprintw(30,30,"%s %x",mac2str(wh->i_addr2), wh->i_fc[0]);
700 }
701 #endif
702
703 stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
704
705 if (type == IEEE80211_FC0_TYPE_MGT &&
706 stype == IEEE80211_FC0_SUBTYPE_BEACON) {
707 get_beacon_info(body, bodylen, node);
708 node->ap = 1;
709 }
710
711 else if (type == IEEE80211_FC0_TYPE_DATA &&
712 stype == IEEE80211_FC0_SUBTYPE_DATA) {
713
714 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
715 unsigned char* iv;
716
717 node->wep = CRYPT_WEP;
718
719 iv = body;
720 iv += 3;
721
722 // extended IV?
723 if (*iv & (1 << 1)) {
724 #if 0
725 node->wep = CRYPT_WPA;
726 mvprintw(20,20, "shei");
727 exit(1);
728 #endif
729 }
730 }
731
732 if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
733 node->ap = 1;
734 else
735 node->ap = 0;
736 }
737
738 memcpy(node->mac, wh->i_addr2, 6);
739 return 1;
740 }
741
radiotap(unsigned char * data,int rd)742 void radiotap(unsigned char* data, int rd) {
743 struct ieee80211_radiotap_header* rth;
744 struct ieee80211_frame* wh;
745 char* body;
746 struct node_info node;
747 int8_t signal_dbm, noise_dbm;
748 uint8_t signal_db, noise_db;
749 int dbm = 0;
750 int signal = 0;
751 int i;
752
753 rd -= 4; // 802.11 CRC
754
755 // radiotap
756 rth = (struct ieee80211_radiotap_header*) data;
757
758 // 802.11
759 wh = (struct ieee80211_frame*)
760 ((char*)rth + rth->it_len);
761 rd -= rth->it_len;
762
763 assert (rd >= 0);
764
765 // body
766 body = (char*) wh + sizeof(*wh);
767 rd -= sizeof(*wh);
768
769 if (!get_packet_info(wh, body, rd, &node))
770 return;
771
772 // signal and noise
773 body = (char*) rth + sizeof(*rth);
774 signal_dbm = noise_dbm = signal_db = noise_db = 0;
775
776 for (i = IEEE80211_RADIOTAP_TSFT; i <= IEEE80211_RADIOTAP_EXT; i++) {
777 if (!(rth->it_present & (1 << i)))
778 continue;
779
780 switch (i) {
781 case IEEE80211_RADIOTAP_TSFT:
782 body += sizeof(uint64_t);
783 break;
784
785 case IEEE80211_RADIOTAP_FLAGS:
786 case IEEE80211_RADIOTAP_RATE:
787 body += sizeof(uint8_t);
788 break;
789
790 case IEEE80211_RADIOTAP_CHANNEL:
791 body += sizeof(uint16_t)*2;
792 break;
793
794 case IEEE80211_RADIOTAP_FHSS:
795 body += sizeof(uint16_t);
796 break;
797
798 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
799 signal_dbm = *body;
800 body++;
801 dbm = 1;
802 break;
803
804 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
805 noise_dbm = *body;
806 body++;
807 break;
808
809 case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
810 signal_db = *((unsigned char*)body);
811 body++;
812 break;
813
814 case IEEE80211_RADIOTAP_DB_ANTNOISE:
815 noise_db = *((unsigned char*)body);
816 body++;
817 break;
818
819 case IEEE80211_RADIOTAP_EXT:
820 abort();
821 break;
822 }
823 }
824 if (dbm) {
825 signal = signal_dbm - noise_dbm;
826 }
827 else {
828 signal = signal_db - noise_db;
829 }
830 if (signal < 0)
831 signal = 0;
832
833 node.signal = signal;
834 #if 0
835 if (node.signal > 100 || node.signal < 0) {
836 mvprintw(25,25, "sig=%d", node.signal);
837 }
838 #else
839 assert (node.signal <= 100 && node.signal >= 0);
840 #endif
841
842 update_node(&node);
843 }
844
bpf_input()845 void bpf_input() {
846 static unsigned char buf[4096];
847 int rd;
848 struct bpf_hdr* bpfh;
849 unsigned char* data;
850
851 rd = read(bpf_s, buf, sizeof(buf));
852 if (rd == -1)
853 die(1,"read()");
854
855 bpfh = (struct bpf_hdr*) buf;
856 rd -= bpfh->bh_hdrlen;
857
858 if (rd != bpfh->bh_caplen) {
859 assert( rd > bpfh->bh_caplen);
860 rd = bpfh->bh_caplen;
861 }
862
863 data = (unsigned char*) bpfh + bpfh->bh_hdrlen;
864 radiotap(data, rd);
865 }
866
elapsed_ms(struct timeval * now,struct timeval * prev)867 unsigned long elapsed_ms(struct timeval* now, struct timeval* prev) {
868 unsigned long elapsed = 0;
869
870 if (now->tv_sec > prev->tv_sec)
871 elapsed = 1000*1000 - prev->tv_usec +
872 now->tv_usec;
873 else {
874 assert(now->tv_sec == prev->tv_sec);
875 elapsed = now->tv_usec - prev->tv_usec;
876 }
877 elapsed /= 1000; //ms
878
879 elapsed += (now->tv_sec - prev->tv_sec)*1000;
880 return elapsed;
881 }
882
chanhop(struct timeval * tv)883 void chanhop(struct timeval* tv) {
884 unsigned long elapsed = 0;
885
886 if (gettimeofday(tv, NULL) == -1)
887 die(1, "gettimeofday()");
888
889
890 elapsed = elapsed_ms(tv, &chaninfo.last_hop);
891
892 // need to chan hop
893 if (elapsed >= hopfreq) {
894 int c;
895
896 c = chaninfo.chan + 1;
897
898 if (c > 11)
899 c = 1;
900
901 set_chan(c);
902
903 elapsed = hopfreq;
904 }
905 // how much can we sleep?
906 else {
907 elapsed = hopfreq - elapsed;
908 }
909
910 // ok calculate sleeping time...
911 tv->tv_sec = elapsed/1000;
912 tv->tv_usec = (elapsed - tv->tv_sec*1000)*1000;
913 }
914
check_seen(struct timeval * tv)915 void check_seen(struct timeval* tv) {
916 unsigned long elapsed = 0;
917 struct timeval now;
918 int need_refresh = 0;
919 unsigned long min_wait = 0;
920 unsigned long will_wait;
921
922 will_wait = tv->tv_sec*1000+tv->tv_usec/1000;
923 min_wait = will_wait;
924
925 struct node_info* node = nodes;
926
927 if (gettimeofday(&now, NULL) == -1)
928 die(1, "gettimeofday()");
929
930 while(node) {
931 if (node->signal) {
932 elapsed = elapsed_ms(&now, &node->seen);
933
934 // node is dead...
935 if (elapsed >= sig_reset) {
936 node->signal = 0;
937 display_node(node);
938 need_refresh = 1;
939 }
940
941 // need to check soon possibly...
942 else {
943 unsigned long left;
944
945 left = sig_reset - elapsed;
946 if (left < min_wait)
947 left = min_wait;
948 }
949 }
950 node = node->next;
951 }
952
953 if (need_refresh)
954 refresh();
955
956 // need to sleep for less...
957 if (min_wait < will_wait) {
958 tv->tv_sec = min_wait/1000;
959 tv->tv_usec = (min_wait - tv->tv_sec*1000)*1000;
960 }
961 }
962
own(char * ifname)963 void own(char* ifname) {
964 int rd;
965 fd_set fds;
966 struct timeval tv;
967 int dlt = DLT_IEEE802_11_RADIO;
968
969 hopfreq = 1000;
970
971 setup_if(ifname);
972 open_bpf(ifname, dlt);
973
974 while(1) {
975 // XXX innefficient all of this...
976 if (!chaninfo.locked)
977 chanhop(&tv);
978 else {
979 tv.tv_sec = 1;
980 tv.tv_usec = 0;
981 }
982
983 // especially this...
984 check_seen(&tv);
985
986 FD_ZERO(&fds);
987 FD_SET(0, &fds);
988 FD_SET(bpf_s, &fds);
989
990 rd = select(bpf_s+1, &fds,NULL , NULL, &tv);
991 if (rd == -1)
992 die(1, "select()");
993 if (FD_ISSET(0, &fds))
994 user_input();
995 if (FD_ISSET(bpf_s, &fds))
996 bpf_input();
997 }
998 }
999
init_globals()1000 void init_globals() {
1001 ioctl_s = socket(PF_INET, SOCK_DGRAM, 0);
1002 if (ioctl_s == -1) {
1003 perror("socket()");
1004 exit(1);
1005 }
1006
1007 chaninfo.locked = 0;
1008 chaninfo.chan = 0;
1009 }
1010
main(int argc,char * argv[])1011 int main(int argc, char *argv[]) {
1012
1013
1014 if (argc < 2) {
1015 printf("Usage: %s <iface>\n", argv[0]);
1016 exit(1);
1017 }
1018
1019 init_globals();
1020
1021 initscr(); cbreak(); noecho();
1022
1023 nonl();
1024 intrflush(stdscr, FALSE);
1025 keypad(stdscr, TRUE);
1026
1027 curs_set(0);
1028
1029 clear();
1030 refresh();
1031
1032 signal(SIGINT, cleanup);
1033 signal(SIGTERM, cleanup);
1034
1035 own(argv[1]);
1036
1037 cleanup(0);
1038 exit(0);
1039 }
1040