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 = 0; 95 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 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 120 char* wep2str(int w) { 121 char* wep = 0; 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 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 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 233 void cleanup(int x) { 234 endwin(); 235 clean_crap(); 236 exit(0); 237 } 238 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 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 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 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 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 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 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 = 0; 398 int sig, max, left, noise; 399 char* wep = 0; 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 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 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 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 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 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 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 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 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 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 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 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