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