stumbler.c revision 160994
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: head/tools/tools/net80211/stumbler/stumbler.c 160994 2006-08-05 05:12:03Z sam $ 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 <net80211/ieee80211_ioctl.h> 37#include <net80211/ieee80211.h> 38#include <net/ethernet.h> 39#include <net80211/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 52int hopfreq = 500; // ms 53int sig_reset = 1*1000; // ms 54 55 56int ioctl_s = -1; 57int bpf_s = -1; 58 59struct 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 79struct 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 96void 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 111char* 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 120char* 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 181char* 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 201void 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 233void cleanup(int x) { 234 endwin(); 235 clean_crap(); 236 exit(0); 237} 238 239void 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 249void 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 261void 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 275void setup_if(char *dev) { 276 struct ifreq ifr; 277 unsigned int flags; 278 struct ifmediareq ifmr; 279 int *mwords; 280 281 // set iface up and promisc 282 memset(&ifr, 0, sizeof(ifr)); 283 strcpy(ifr.ifr_name, dev); 284 if (ioctl(ioctl_s, SIOCGIFFLAGS, &ifr) == -1) 285 die(1, "ioctl(SIOCGIFFLAGS)"); 286 287 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 288 flags |= IFF_UP | IFF_PPROMISC; 289 290 memset(&ifr, 0, sizeof(ifr)); 291 strcpy(ifr.ifr_name, dev); 292 ifr.ifr_flags = flags & 0xffff; 293 ifr.ifr_flagshigh = flags >> 16; 294 if (ioctl(ioctl_s, SIOCSIFFLAGS, &ifr) == -1) 295 die(1, "ioctl(SIOCSIFFLAGS)"); 296 297 // set monitor mode 298 memset(&ifmr, 0, sizeof(ifmr)); 299 strcpy(ifmr.ifm_name, dev); 300 if (ioctl(ioctl_s, SIOCGIFMEDIA, &ifmr) == -1) 301 die(1, "ioctl(SIOCGIFMEDIA)"); 302 303 if (ifmr.ifm_count == 0) 304 die(0, "0 media thinggies...\n"); 305 306 mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); 307 if (!mwords) 308 die(1, "malloc()"); 309 310 ifmr.ifm_ulist = mwords; 311 312 if (ioctl(ioctl_s, SIOCGIFMEDIA, &ifmr) == -1) 313 die(1, "ioctl(SIOCGIFMEDIA)"); 314 315 free(mwords); 316 317 memset(&ifr, 0, sizeof(ifr)); 318 strcpy(ifr.ifr_name, dev); 319 ifr.ifr_media = ifmr.ifm_current | IFM_IEEE80211_MONITOR; 320 if (ioctl(ioctl_s, SIOCSIFMEDIA, &ifr) == -1) 321 die(1, "ioctl(SIOCSIFMEDIA)"); 322 323 // set chan 324 memset(&chaninfo.ireq, 0, sizeof(chaninfo.ireq)); 325 strcpy(chaninfo.ireq.i_name, dev); 326 chaninfo.ireq.i_type = IEEE80211_IOC_CHANNEL; 327 328 set_chan(1); 329} 330 331void open_bpf(char *dev, int dlt) { 332 int i; 333 char buf[64]; 334 int fd = -1; 335 struct ifreq ifr; 336 337 for(i = 0;i < 16; i++) { 338 sprintf(buf, "/dev/bpf%d", i); 339 340 fd = open(buf, O_RDWR); 341 if(fd < 0) { 342 if(errno != EBUSY) 343 die(1,"can't open /dev/bpf"); 344 continue; 345 } 346 else 347 break; 348 } 349 350 if(fd < 0) 351 die(1, "can't open /dev/bpf"); 352 353 strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1); 354 ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0; 355 356 if(ioctl(fd, BIOCSETIF, &ifr) < 0) 357 die(1, "ioctl(BIOCSETIF)"); 358 359 if (ioctl(fd, BIOCSDLT, &dlt) < 0) 360 die(1, "ioctl(BIOCSDLT)"); 361 362 i = 1; 363 if(ioctl(fd, BIOCIMMEDIATE, &i) < 0) 364 die(1, "ioctl(BIOCIMMEDIATE)"); 365 366 bpf_s = fd; 367} 368 369void user_input() { 370 static char chan[3]; 371 static int pos = 0; 372 int c; 373 374 c = getch(); 375 376 switch (c) { 377 case 'w': 378 save_state(); 379 break; 380 381 case 'q': 382 cleanup(0); 383 break; 384 385 case 'c': 386 chaninfo.locked = !chaninfo.locked; 387 break; 388 389 case ERR: 390 die(0, "getch()"); 391 break; 392 393 case '0': 394 case '1': 395 case '2': 396 case '3': 397 case '4': 398 case '5': 399 case '6': 400 case '7': 401 case '8': 402 case '9': 403 chan[pos++] = c; 404 if (pos == 2) { 405 int ch = atoi(chan); 406 if (ch <= 11 && ch >= 1) { 407 set_chan(atoi(chan)); 408 chaninfo.locked = 1; 409 } 410 pos = 0; 411 } 412 break; 413 414 default: 415 pos = 0; 416 break; 417 } 418} 419 420void display_node(struct node_info* node) { 421 int x = 0; 422 int y = 0; 423 int i; 424 char chan[3]; 425 char* ssid = 0; 426 int sig, max, left, noise; 427 char* wep = 0; 428 429 y = node->pos; 430 if (y == -1) // offscreen 431 return; 432 433 assert(y < LINES); 434 435 // MAC 436 mvaddstr(y, x, mac2str(node->mac)); 437 x += 6*3; 438 439 // WEP 440 wep = wep2str(node->wep); 441 assert(wep); 442 mvaddstr(y, x, wep); 443 x += strlen(wep); 444 x++; 445 446 // CHAN 447 sprintf(chan, "%.2d", node->chan); 448 mvaddstr(y, x, chan); 449 x += 3; 450 451 // ssid 452 ssid = ssid2str(node); 453 assert(ssid); 454 mvaddstr(y, x, ssid); 455 x += strlen(ssid); 456 x++; 457 458 left = COLS - x - 1; 459 460 sig = (int) ( ((double)node->signal)*left/100.0 ); 461 noise=(int) ( ((double)node->noise)*left/100.0 ); 462 max = (int) ( ((double)node->max)*left/100.0 ); 463 464 // SIGNAL BAR 465 for (i = 0; i < noise; i++) 466 mvaddch(y, x++, 'N'); 467 468 for (; i < sig; i++) 469 mvaddch(y,x++, 'X'); 470 471 for (; i < max; i++) 472 mvaddch(y,x++, ' '); 473 mvaddch(y,x++, '|'); 474 475 for (; x < COLS-1; x++) 476 mvaddch(y, x, ' '); 477 478 assert (x <= COLS); 479} 480 481void update_node(struct node_info* data) { 482 struct node_info* node; 483 int sort = 0; 484 485 assert(data->signal <= 100); 486 487 node = nodes; 488 489 // first time [virgin] 490 if (!node) { 491 node = (struct node_info*) malloc(sizeof(struct node_info)); 492 if (!node) 493 die(1, "malloc()"); 494 495 memset(node, 0, sizeof(*node)); 496 memcpy(node->mac, data->mac, 6); 497 nodes = node; 498 } 499 500 while (node) { 501 // found it 502 if (memcmp(node->mac, data->mac, 6) == 0) 503 break; 504 505 // end of chain 506 if (!node->next) { 507 node->next = (struct node_info*) 508 malloc(sizeof(struct node_info)); 509 if (!node->next) 510 die(1, "malloc()"); 511 512 memset(node->next, 0, sizeof(*node->next)); 513 memcpy(node->next->mac, data->mac, 6); 514 node->next->prev = node; 515 node->next->pos = node->pos+1; 516 517 node = node->next; 518 if (node->pos == LINES) 519 sort = 1; 520 break; 521 } 522 523 node = node->next; 524 } 525 assert(node); 526 527 // too many nodes for screen 528 if (sort) { 529 struct node_info* ni = nodes; 530 531 while (ni) { 532 if (ni->pos != -1) 533 ni->pos--; 534 535 display_node(ni); 536 ni = ni->next; 537 } 538 } 539 540 node->signal = data->signal; 541 if (data->signal > node->max) 542 node->max = data->signal; 543 544 if (gettimeofday(&node->seen, NULL) == -1) 545 die(1, "gettimeofday()"); 546 547 if (data->ssid[0] != 0) 548 strcpy(node->ssid, data->ssid); 549 if (data->chan != -1) 550 node->chan = data->chan; 551 if (data->wep != -1) { 552 // XXX LAME --- won't detect if AP changes WEP mode in 553 // beacons... 554 if (node->wep != CRYPT_WEP && 555 node->wep != CRYPT_NONE && 556 data->wep == CRYPT_WEP) { 557 } 558 else 559 node->wep = data->wep; 560 } 561 if (data->ap != -1) 562 node->ap = data->ap; 563 564 display_node(node); 565 refresh(); 566} 567 568void get_beacon_info(unsigned char* data, int rd, 569 struct node_info* node) { 570 571 int blen = 8 + 2 + 2; 572 573 strcpy(node->ssid, "<hidden>"); 574 node->chan = 0; 575 node->wep = CRYPT_NONE; 576 577 assert(rd >= blen); 578 579 if (IEEE80211_BEACON_CAPABILITY(data) & IEEE80211_CAPINFO_PRIVACY) 580 node->wep = CRYPT_WEP; 581 582 data += blen; 583 rd -= blen; 584 585 while (rd > 2) { 586 int eid, elen; 587 588 eid = *data; 589 data++; 590 elen = *data; 591 data++; 592 rd -= 2; 593 594 // short! 595 if (rd < elen) { 596 return; 597 } 598 599 // ssid 600 if (eid == 0) { 601 if (elen == 1 && data[0] == 0) { 602 // hidden 603 } 604 else { 605 memcpy(node->ssid, data, elen); 606 node->ssid[elen] = 0; 607 } 608 } 609 // chan 610 else if(eid == 3) { 611 // weird chan! 612 if( elen != 1) 613 goto next; 614 615 node->chan = *data; 616 } 617 // WPA 618 else if (eid == 221 && node->wep == CRYPT_WEP) { 619 struct ieee80211_ie_wpa* wpa; 620 621 wpa = (struct ieee80211_ie_wpa*) data; 622 if (elen < 6) 623 goto next; 624 625 if (!memcmp(wpa->wpa_oui, "\x00\x50\xf2", 3)) { 626 // node->wep = CRYPT_WPA; 627 } 628 else 629 goto next; 630 631 if (wpa->wpa_type == WPA_OUI_TYPE && 632 le16toh(wpa->wpa_version) == WPA_VERSION) { 633 int cipher, auth; 634 unsigned char* ptr; 635 636 node->wep = CRYPT_WPA1; 637 638 if (elen < 12) 639 goto next; 640 641 cipher = ((unsigned char*) wpa->wpa_mcipher)[3]; 642 643 ptr = (unsigned char*)wpa + 12 + 644 4 * le16toh(wpa->wpa_uciphercnt); 645 646 if (elen < (ptr - data + 6)) 647 goto next; 648 649 if ( *((unsigned short*) ptr) == 0) 650 goto next; 651 652 ptr += 2 + 3; 653 auth = *ptr; 654 655 if (cipher == WPA_CSE_TKIP) { 656 node->wep = CRYPT_WPA1_TKIP; 657 658 if (auth == WPA_ASE_8021X_PSK) 659 node->wep = CRYPT_WPA1_TKIP_PSK; 660 } 661 662 if (cipher == WPA_CSE_CCMP) { 663 node->wep = CRYPT_WPA1_CCMP; 664 665 if (auth == WPA_ASE_8021X_PSK) 666 node->wep = CRYPT_WPA1_CCMP_PSK; 667 } 668 } 669 } 670 else if (eid == 48 && node->wep == CRYPT_WEP) { 671 unsigned char* ptr; 672 673 // XXX no bounds checking 674 ptr = data; 675 676 if (ptr[0] == 1 && ptr[1] == 0) { 677 unsigned short* count; 678 int cipher = 0; 679 680 ptr += 2; 681 node->wep = CRYPT_80211i; 682 683 if (!memcmp(ptr, "\x00\x0f\xac\x02", 4)) { 684 node->wep = CRYPT_80211i_TKIP; 685 cipher = 1; 686 } 687 688 ptr += 4; 689 count = (unsigned short*) ptr; 690 ptr +=2 + *count*4; 691 692 count = (unsigned short*) ptr; 693 if (*count) { 694 ptr += 2; 695 696 if (!memcmp(ptr,"\x00\x0f\xac\x02", 4)) { 697 if (cipher) 698 node->wep = CRYPT_80211i_TKIP_PSK; 699 } 700 } 701 } 702 } 703 704next: 705 data += elen; 706 rd -= elen; 707 } 708} 709 710int get_packet_info(struct ieee80211_frame* wh, 711 unsigned char* body, int bodylen, 712 struct node_info* node) { 713 714 int type, stype; 715 716 node->chan = chaninfo.chan; 717 node->wep = -1; 718 node->ssid[0] = 0; 719 node->ap = -1; 720 721 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 722 723 if (type == IEEE80211_FC0_TYPE_CTL) 724 return 0; 725#if 0 726 if (wh->i_addr2[0] != 0) { 727 mvprintw(30,30,"%s %x",mac2str(wh->i_addr2), wh->i_fc[0]); 728 } 729#endif 730 731 stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 732 733 if (type == IEEE80211_FC0_TYPE_MGT && 734 stype == IEEE80211_FC0_SUBTYPE_BEACON) { 735 get_beacon_info(body, bodylen, node); 736 node->ap = 1; 737 } 738 739 else if (type == IEEE80211_FC0_TYPE_DATA && 740 stype == IEEE80211_FC0_SUBTYPE_DATA) { 741 742 if (wh->i_fc[1] & IEEE80211_FC1_WEP) { 743 unsigned char* iv; 744 745 node->wep = CRYPT_WEP; 746 747 iv = body; 748 iv += 3; 749 750 // extended IV? 751 if (*iv & (1 << 1)) { 752#if 0 753 node->wep = CRYPT_WPA; 754 mvprintw(20,20, "shei"); 755 exit(1); 756#endif 757 } 758 } 759 760 if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) 761 node->ap = 1; 762 else 763 node->ap = 0; 764 } 765 766 memcpy(node->mac, wh->i_addr2, 6); 767 return 1; 768} 769 770void radiotap(unsigned char* data, int rd) { 771 struct ieee80211_radiotap_header* rth; 772 struct ieee80211_frame* wh; 773 char* body; 774 struct node_info node; 775 int8_t signal_dbm, noise_dbm; 776 uint8_t signal_db, noise_db; 777 int dbm = 0; 778 int signal = 0; 779 int i; 780 781 rd -= 4; // 802.11 CRC 782 783 // radiotap 784 rth = (struct ieee80211_radiotap_header*) data; 785 786 // 802.11 787 wh = (struct ieee80211_frame*) 788 ((char*)rth + rth->it_len); 789 rd -= rth->it_len; 790 791 assert (rd >= 0); 792 793 // body 794 body = (char*) wh + sizeof(*wh); 795 rd -= sizeof(*wh); 796 797 if (!get_packet_info(wh, body, rd, &node)) 798 return; 799 800 // signal and noise 801 body = (char*) rth + sizeof(*rth); 802 signal_dbm = noise_dbm = signal_db = noise_db = 0; 803 804 for (i = IEEE80211_RADIOTAP_TSFT; i <= IEEE80211_RADIOTAP_EXT; i++) { 805 if (!(rth->it_present & (1 << i))) 806 continue; 807 808 switch (i) { 809 case IEEE80211_RADIOTAP_TSFT: 810 body += sizeof(uint64_t); 811 break; 812 813 case IEEE80211_RADIOTAP_FLAGS: 814 case IEEE80211_RADIOTAP_RATE: 815 body += sizeof(uint8_t); 816 break; 817 818 case IEEE80211_RADIOTAP_CHANNEL: 819 body += sizeof(uint16_t)*2; 820 break; 821 822 case IEEE80211_RADIOTAP_FHSS: 823 body += sizeof(uint16_t); 824 break; 825 826 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: 827 signal_dbm = *body; 828 body++; 829 dbm = 1; 830 break; 831 832 case IEEE80211_RADIOTAP_DBM_ANTNOISE: 833 noise_dbm = *body; 834 body++; 835 break; 836 837 case IEEE80211_RADIOTAP_DB_ANTSIGNAL: 838 signal_db = *((unsigned char*)body); 839 body++; 840 break; 841 842 case IEEE80211_RADIOTAP_DB_ANTNOISE: 843 noise_db = *((unsigned char*)body); 844 body++; 845 break; 846 847 case IEEE80211_RADIOTAP_EXT: 848 abort(); 849 break; 850 } 851 } 852 if (dbm) { 853 signal = signal_dbm - noise_dbm; 854 } 855 else { 856 signal = signal_db - noise_db; 857 } 858 if (signal < 0) 859 signal = 0; 860 861 node.signal = signal; 862#if 0 863 if (node.signal > 100 || node.signal < 0) { 864 mvprintw(25,25, "sig=%d", node.signal); 865 } 866#else 867 assert (node.signal <= 100 && node.signal >= 0); 868#endif 869 870 update_node(&node); 871} 872 873void bpf_input() { 874 static unsigned char buf[4096]; 875 int rd; 876 struct bpf_hdr* bpfh; 877 unsigned char* data; 878 879 rd = read(bpf_s, buf, sizeof(buf)); 880 if (rd == -1) 881 die(1,"read()"); 882 883 bpfh = (struct bpf_hdr*) buf; 884 rd -= bpfh->bh_hdrlen; 885 886 if (rd != bpfh->bh_caplen) { 887 assert( rd > bpfh->bh_caplen); 888 rd = bpfh->bh_caplen; 889 } 890 891 data = (unsigned char*) bpfh + bpfh->bh_hdrlen; 892 radiotap(data, rd); 893} 894 895unsigned long elapsed_ms(struct timeval* now, struct timeval* prev) { 896 unsigned long elapsed = 0; 897 898 if (now->tv_sec > prev->tv_sec) 899 elapsed = 1000*1000 - prev->tv_usec + 900 now->tv_usec; 901 else { 902 assert(now->tv_sec == prev->tv_sec); 903 elapsed = now->tv_usec - prev->tv_usec; 904 } 905 elapsed /= 1000; //ms 906 907 elapsed += (now->tv_sec - prev->tv_sec)*1000; 908 return elapsed; 909} 910 911void chanhop(struct timeval* tv) { 912 unsigned long elapsed = 0; 913 914 if (gettimeofday(tv, NULL) == -1) 915 die(1, "gettimeofday()"); 916 917 918 elapsed = elapsed_ms(tv, &chaninfo.last_hop); 919 920 // need to chan hop 921 if (elapsed >= hopfreq) { 922 int c; 923 924 c = chaninfo.chan + 1; 925 926 if (c > 11) 927 c = 1; 928 929 set_chan(c); 930 931 elapsed = hopfreq; 932 } 933 // how much can we sleep? 934 else { 935 elapsed = hopfreq - elapsed; 936 } 937 938 // ok calculate sleeping time... 939 tv->tv_sec = elapsed/1000; 940 tv->tv_usec = (elapsed - tv->tv_sec*1000)*1000; 941} 942 943void check_seen(struct timeval* tv) { 944 unsigned long elapsed = 0; 945 struct timeval now; 946 int need_refresh = 0; 947 unsigned long min_wait = 0; 948 unsigned long will_wait; 949 950 will_wait = tv->tv_sec*1000+tv->tv_usec/1000; 951 min_wait = will_wait; 952 953 struct node_info* node = nodes; 954 955 if (gettimeofday(&now, NULL) == -1) 956 die(1, "gettimeofday()"); 957 958 while(node) { 959 if (node->signal) { 960 elapsed = elapsed_ms(&now, &node->seen); 961 962 // node is dead... 963 if (elapsed >= sig_reset) { 964 node->signal = 0; 965 display_node(node); 966 need_refresh = 1; 967 } 968 969 // need to check soon possibly... 970 else { 971 unsigned long left; 972 973 left = sig_reset - elapsed; 974 if (left < min_wait) 975 left = min_wait; 976 } 977 } 978 node = node->next; 979 } 980 981 if (need_refresh) 982 refresh(); 983 984 // need to sleep for less... 985 if (min_wait < will_wait) { 986 tv->tv_sec = min_wait/1000; 987 tv->tv_usec = (min_wait - tv->tv_sec*1000)*1000; 988 } 989} 990 991void own(char* ifname) { 992 int rd; 993 fd_set fds; 994 struct timeval tv; 995 int dlt = DLT_IEEE802_11_RADIO; 996 997 hopfreq = 1000; 998 999 setup_if(ifname); 1000 open_bpf(ifname, dlt); 1001 1002 while(1) { 1003 // XXX innefficient all of this... 1004 if (!chaninfo.locked) 1005 chanhop(&tv); 1006 else { 1007 tv.tv_sec = 1; 1008 tv.tv_usec = 0; 1009 } 1010 1011 // especially this... 1012 check_seen(&tv); 1013 1014 FD_ZERO(&fds); 1015 FD_SET(0, &fds); 1016 FD_SET(bpf_s, &fds); 1017 1018 rd = select(bpf_s+1, &fds,NULL , NULL, &tv); 1019 if (rd == -1) 1020 die(1, "select()"); 1021 if (FD_ISSET(0, &fds)) 1022 user_input(); 1023 if (FD_ISSET(bpf_s, &fds)) 1024 bpf_input(); 1025 } 1026} 1027 1028void init_globals() { 1029 ioctl_s = socket(PF_INET, SOCK_DGRAM, 0); 1030 if (ioctl_s == -1) { 1031 perror("socket()"); 1032 exit(1); 1033 } 1034 1035 chaninfo.locked = 0; 1036 chaninfo.chan = 0; 1037} 1038 1039int main(int argc, char *argv[]) { 1040 1041 1042 if (argc < 2) { 1043 printf("Usage: %s <iface>\n", argv[0]); 1044 exit(1); 1045 } 1046 1047 init_globals(); 1048 1049 initscr(); cbreak(); noecho(); 1050 1051 nonl(); 1052 intrflush(stdscr, FALSE); 1053 keypad(stdscr, TRUE); 1054 1055 curs_set(0); 1056 1057 clear(); 1058 refresh(); 1059 1060 signal(SIGINT, cleanup); 1061 signal(SIGTERM, cleanup); 1062 1063 own(argv[1]); 1064 1065 cleanup(0); 1066 exit(0); 1067} 1068