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 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 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 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 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 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 231 void cleanup(int x) { 232 endwin(); 233 clean_crap(); 234 exit(0); 235 } 236 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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