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/time.h> 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <unistd.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <err.h> 33 #include <net80211/ieee80211.h> 34 #include <sys/endian.h> 35 #include "w00t.h" 36 37 enum { 38 S_START = 0, 39 S_SEND_PROBE_REQ, 40 S_WAIT_PROBE_RES, 41 S_SEND_AUTH, 42 S_WAIT_AUTH, 43 S_SEND_ASSOC, 44 S_WAIT_ASSOC, 45 S_ASSOCIATED, 46 S_SEND_DATA, 47 S_WAIT_ACK 48 }; 49 50 struct params { 51 int seq; 52 int seq_rx; 53 char *mac; 54 char *ssid; 55 char bssid[6]; 56 char ap[6]; 57 int tx; 58 int rx; 59 int tap; 60 int aid; 61 char packet[4096]; 62 int packet_len; 63 int state; 64 char wep_key[13]; 65 int wep_iv; 66 int wep_len; 67 }; 68 69 void usage(char *pname) 70 { 71 printf("Usage: %s <opts>\n" 72 "-m\t<source mac>\n" 73 "-s\t<ssid>\n" 74 "-h\tusage\n" 75 "-i\t<iface>\n" 76 "-w\t<wep key>\n" 77 "-t\t<tap>\n" 78 "-b\t<bssid>\n" 79 , pname); 80 exit(0); 81 } 82 83 void fill_basic(struct ieee80211_frame *wh, struct params *p) 84 { 85 short *seq; 86 87 wh->i_dur[0] = 0x69; 88 wh->i_dur[1] = 0x00; 89 90 memcpy(wh->i_addr1, p->ap, 6); 91 memcpy(wh->i_addr2, p->mac, 6); 92 memcpy(wh->i_addr3, p->bssid, 6); 93 94 seq = (short*)wh->i_seq; 95 *seq = seqfn(p->seq, 0); 96 } 97 98 void send_frame(struct params *p, void *buf, int len) 99 { 100 int rc; 101 102 rc = inject(p->tx, buf, len); 103 if (rc == -1) { 104 if (errno == EMSGSIZE) 105 warnx("inject(len %d)", len); 106 else 107 err(1, "inject(len %d)", len); 108 } else if (rc != len) 109 errx(1, "injected %d but only %d sent", rc, len); 110 p->seq++; 111 } 112 113 void send_probe_request(struct params *p) 114 { 115 char buf[2048]; 116 struct ieee80211_frame *wh; 117 char *data; 118 int len; 119 120 memset(buf, 0, sizeof(buf)); 121 122 wh = (struct ieee80211_frame*) buf; 123 fill_basic(wh, p); 124 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ; 125 126 memset(wh->i_addr1, 0xFF, 6); 127 memset(wh->i_addr3, 0xFF, 6); 128 129 data = (char*) (wh + 1); 130 *data++ = 0; /* SSID */ 131 *data++ = strlen(p->ssid); 132 strcpy(data, p->ssid); 133 data += strlen(p->ssid); 134 135 *data++ = 1; /* rates */ 136 *data++ = 4; 137 *data++ = 2 | 0x80; 138 *data++ = 4 | 0x80; 139 *data++ = 11; 140 *data++ = 22; 141 142 len = data - (char*)wh; 143 144 send_frame(p, buf, len); 145 } 146 147 void send_auth(struct params *p) 148 { 149 char buf[2048]; 150 struct ieee80211_frame *wh; 151 char *data; 152 int len; 153 154 memset(buf, 0, sizeof(buf)); 155 156 wh = (struct ieee80211_frame*) buf; 157 fill_basic(wh, p); 158 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH; 159 160 data = (char*) (wh + 1); 161 162 /* algo */ 163 *data++ = 0; 164 *data++ = 0; 165 166 /* transaction no. */ 167 *data++ = 1; 168 *data++ = 0; 169 170 /* status code */ 171 *data++ = 0; 172 *data++ = 0; 173 174 len = data - (char*)wh; 175 176 send_frame(p, buf, len); 177 } 178 179 /* 180 * Add an ssid element to a frame. 181 */ 182 static u_int8_t * 183 ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len) 184 { 185 *frm++ = IEEE80211_ELEMID_SSID; 186 *frm++ = len; 187 memcpy(frm, ssid, len); 188 return frm + len; 189 } 190 191 void send_assoc(struct params *p) 192 { 193 union { 194 struct ieee80211_frame w; 195 char buf[2048]; 196 } u; 197 struct ieee80211_frame *wh; 198 char *data; 199 int len, capinfo, lintval; 200 201 memset(&u, 0, sizeof(u)); 202 203 wh = (struct ieee80211_frame*) &u.w; 204 fill_basic(wh, p); 205 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 206 207 data = (char*) (wh + 1); 208 209 /* capability */ 210 capinfo = IEEE80211_CAPINFO_ESS; 211 if (p->wep_len) 212 capinfo |= IEEE80211_CAPINFO_PRIVACY; 213 *(uint16_t *)data = htole16(capinfo); 214 data += 2; 215 216 /* listen interval */ 217 *(uint16_t *)data = htole16(100); 218 data += 2; 219 220 data = ieee80211_add_ssid(data, p->ssid, strlen(p->ssid)); 221 222 *data++ = 1; /* rates */ 223 *data++ = 4; 224 *data++ = 2 | 0x80; 225 *data++ = 4 | 0x80; 226 *data++ = 11; 227 *data++ = 22; 228 229 len = data - (char*)wh; 230 231 send_frame(p, u.buf, len); 232 } 233 234 int for_me(struct ieee80211_frame *wh, char *mac) 235 { 236 return memcmp(wh->i_addr1, mac, 6) == 0; 237 } 238 239 int from_ap(struct ieee80211_frame *wh, char *mac) 240 { 241 return memcmp(wh->i_addr2, mac, 6) == 0; 242 } 243 244 void ack(struct params *p, struct ieee80211_frame *wh) 245 { 246 if (memcmp(wh->i_addr1, p->mac, 6) != 0) 247 return; 248 249 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) 250 return; 251 252 send_ack(p->tx, wh->i_addr2); 253 } 254 255 void generic_process(struct ieee80211_frame *wh, struct params *p, int len) 256 { 257 int type, stype; 258 int dup = 0; 259 260 #if 0 261 ack(p, wh); 262 #endif 263 264 #if 0 265 if (!for_me(wh, p->mac)) 266 return; 267 #endif 268 /* ignore my own shit */ 269 if (memcmp(wh->i_addr2, p->mac, 6) == 0) { 270 return; 271 } 272 273 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 274 stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 275 276 if (for_me(wh, p->mac) && type == IEEE80211_FC0_TYPE_DATA) { 277 /* sequence number & dups */ 278 if (p->seq_rx == -1) 279 p->seq_rx = seqno(wh); 280 else { 281 int s = seqno(wh); 282 283 if (s > p->seq_rx) { 284 /* normal case */ 285 if (p->seq_rx + 1 == s) { 286 #if 0 287 printf("S=%d\n", s); 288 #endif 289 p->seq_rx = s; 290 } 291 else { /* future */ 292 #if 0 293 printf("Got seq %d, prev %d\n", 294 s, p->seq_rx); 295 #endif 296 p->seq_rx = s; 297 } 298 } else { /* we got pas stuff... */ 299 if (p->seq_rx - s > 1000) { 300 #if 0 301 printf("Seqno wrap seq %d, last %d\n", 302 s, p->seq_rx); 303 #endif 304 /* seqno wrapping ? */ 305 p->seq_rx = 0; 306 } 307 else { /* dup */ 308 dup = 1; 309 #if 0 310 printf("Got dup seq %d, last %d\n", 311 s, p->seq_rx); 312 #endif 313 } 314 } 315 } 316 } 317 #if 0 318 if (wh->i_fc[1] & IEEE80211_FC1_RETRY) { 319 printf("Got retry\n"); 320 } 321 #endif 322 #if 0 323 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) { 324 int rc = send_ack(p->tx, wh->i_addr2); 325 if (rc == -1) 326 err(1, "send_ack()"); 327 if (rc != 10) { 328 printf("Wrote ACK %d/%d\n", rc, 10); 329 exit(1); 330 } 331 } 332 #endif 333 334 /* data frames */ 335 if (type == IEEE80211_FC0_TYPE_DATA && !dup) { 336 char *ptr; 337 char src[6], dst[6]; 338 int rc; 339 340 if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) { 341 if (memcmp(wh->i_addr2, p->ap, 6) != 0) 342 return; 343 } else { 344 if (memcmp(wh->i_addr1, p->ap, 6) != 0) 345 return; 346 } 347 348 349 if (p->state < S_ASSOCIATED) { 350 printf("Got data when not associated!\n"); 351 return; 352 } 353 if (stype != IEEE80211_FC0_SUBTYPE_DATA) { 354 printf("Got weird data frame stype=%d\n", 355 stype >> IEEE80211_FC0_SUBTYPE_SHIFT); 356 return; 357 } 358 359 if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) { 360 memcpy(src, wh->i_addr3, 6); 361 memcpy(dst, wh->i_addr1, 6); 362 } else { 363 memcpy(src, wh->i_addr2, 6); 364 memcpy(dst, wh->i_addr3, 6); 365 } 366 367 ptr = (char*) (wh + 1); 368 369 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { 370 if (!p->wep_len) { 371 char srca[3*6]; 372 char dsta[3*6]; 373 374 mac2str(srca, src); 375 mac2str(dsta, dst); 376 printf("Got wep but i aint wep %s->%s %d\n", 377 srca, dsta, len-sizeof(*wh)-8); 378 return; 379 } 380 381 if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){ 382 char srca[3*6]; 383 char dsta[3*6]; 384 385 mac2str(srca, src); 386 mac2str(dsta, dst); 387 printf("Can't decrypt %s->%s %d\n", srca, dsta, 388 len-sizeof(*wh)-8); 389 return; 390 } 391 392 ptr += 4; 393 len -= 8; 394 } 395 396 /* ether header */ 397 ptr += 8 - 2; 398 ptr -= 6; 399 memcpy(ptr, src, 6); 400 ptr -= 6; 401 memcpy(ptr, dst, 6); 402 403 len -= sizeof(*wh); 404 len -= 8; 405 len += 14; 406 407 /* send to tap */ 408 rc = write(p->tap, ptr, len); 409 if (rc == -1) 410 err(1, "write()"); 411 if (rc != len) { 412 printf("Wrote %d/%d\n", rc, len); 413 exit(1); 414 } 415 } 416 } 417 418 int get_probe_response(struct params *p) 419 { 420 char buf[4096]; 421 int rc; 422 struct ieee80211_frame *wh; 423 char *data; 424 int ess; 425 int wep; 426 char *ssid; 427 char from[18]; 428 char bssid[18]; 429 430 rc = sniff(p->rx, buf, sizeof(buf)); 431 if (rc == -1) 432 err(1, "sniff()"); 433 434 wh = get_wifi(buf, &rc); 435 if (!wh) 436 return 0; 437 438 generic_process(wh, p, rc); 439 440 if (!for_me(wh, p->mac)) 441 return 0; 442 443 if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT, 444 IEEE80211_FC0_SUBTYPE_PROBE_RESP)) 445 return 0; 446 447 data = (char*) (wh+1); 448 data += 8; /* Timestamp */ 449 data += 2; /* Beacon Interval */ 450 ess = *data & 1; 451 wep = (*data & IEEE80211_CAPINFO_PRIVACY) ? 1 : 0; 452 data += 2; /* capability */ 453 454 /* ssid */ 455 if (*data != 0) { 456 printf("Warning, expecting SSID got %x\n", *data); 457 return 0; 458 } 459 data++; 460 ssid = data+1; 461 data += 1 + *data; 462 if (*data != 1) { 463 printf("Warning, expected rates got %x\n", *data); 464 return 0; 465 } 466 *data = 0; 467 468 /* rates */ 469 data++; 470 471 mac2str(from, wh->i_addr2); 472 mac2str(bssid, wh->i_addr3); 473 printf("Got response from %s [%s] [%s] ESS=%d WEP=%d\n", 474 from, bssid, ssid, ess, wep); 475 476 if (strcmp(ssid, p->ssid) != 0) 477 return 0; 478 479 memcpy(p->ap, wh->i_addr2, 6); 480 memcpy(p->bssid, wh->i_addr3, 6); 481 return 1; 482 } 483 484 int get_auth(struct params *p) 485 { 486 char buf[4096]; 487 int rc; 488 struct ieee80211_frame *wh; 489 short *data; 490 491 rc = sniff(p->rx, buf, sizeof(buf)); 492 if (rc == -1) 493 err(1, "sniff()"); 494 495 wh = get_wifi(buf, &rc); 496 if (!wh) 497 return 0; 498 499 generic_process(wh, p, rc); 500 501 if (!for_me(wh, p->mac)) 502 return 0; 503 504 if (!from_ap(wh, p->ap)) 505 return 0; 506 507 if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT, 508 IEEE80211_FC0_SUBTYPE_AUTH)) 509 return 0; 510 511 data = (short*) (wh+1); 512 513 /* algo */ 514 if (le16toh(*data) != 0) { 515 printf("Not open-system %d!\n", le16toh(*data)); 516 return 0; 517 } 518 data++; 519 520 /* transaction no. */ 521 if (le16toh(*data) != 2) { 522 printf("Got transaction %d!\n", le16toh(*data)); 523 return 0; 524 } 525 data++; 526 527 /* status code */ 528 rc = le16toh(*data); 529 if (rc == 0) { 530 printf("Authenticated\n"); 531 return 1; 532 } 533 534 printf("Authentication failed code=%d\n", rc); 535 return 0; 536 } 537 538 int get_assoc(struct params *p) 539 { 540 char buf[4096]; 541 int rc; 542 struct ieee80211_frame *wh; 543 unsigned short *data; 544 545 rc = sniff(p->rx, buf, sizeof(buf)); 546 if (rc == -1) 547 err(1, "sniff()"); 548 549 wh = get_wifi(buf, &rc); 550 if (!wh) 551 return 0; 552 553 generic_process(wh, p, rc); 554 555 if (!for_me(wh, p->mac)) 556 return 0; 557 558 if (!from_ap(wh, p->ap)) 559 return 0; 560 561 if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT, 562 IEEE80211_FC0_SUBTYPE_ASSOC_RESP)) 563 return 0; 564 565 566 data = (unsigned short*) (wh+1); 567 568 data++; /* caps */ 569 570 /* status */ 571 rc = le16toh(*data++); 572 if (rc != 0) { 573 printf("Assoc failed code %d\n", rc); 574 return 0; 575 } 576 577 /* aid */ 578 p->aid = le16toh(*data & ~( (1 << 15) | (1 << 14))); 579 printf("Association ID=%d\n", p->aid); 580 581 return 1; 582 } 583 584 void read_wifi(struct params *p) 585 { 586 char buf[4096]; 587 int rc; 588 struct ieee80211_frame *wh; 589 int type, stype; 590 591 rc = sniff(p->rx, buf, sizeof(buf)); 592 if (rc == -1) 593 err(1, "sniff()"); 594 595 wh = get_wifi(buf, &rc); 596 if (!wh) 597 return; 598 599 generic_process(wh, p, rc); 600 601 if (!for_me(wh, p->mac)) 602 return; 603 604 type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; 605 stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; 606 607 /* control frames */ 608 if (type == IEEE80211_FC0_TYPE_CTL) { 609 switch (stype) { 610 case IEEE80211_FC0_SUBTYPE_ACK: 611 if (p->state == S_WAIT_ACK) 612 p->state = S_ASSOCIATED; 613 break; 614 615 case IEEE80211_FC0_SUBTYPE_RTS: 616 #if 0 617 printf("Got RTS\n"); 618 #endif 619 break; 620 621 default: 622 printf("Unknown CTL frame %d\n", 623 stype >> IEEE80211_FC0_SUBTYPE_SHIFT); 624 abort(); 625 break; 626 } 627 return; 628 } 629 630 if (!from_ap(wh, p->ap)) 631 return; 632 633 if (type != IEEE80211_FC0_TYPE_MGT) 634 return; 635 636 if (stype == IEEE80211_FC0_SUBTYPE_DEAUTH || 637 stype == IEEE80211_FC0_SUBTYPE_DISASSOC) { 638 printf("Got management! %d\n", 639 stype >> IEEE80211_FC0_SUBTYPE_SHIFT); 640 p->seq_rx = -1; 641 p->state = S_START; 642 } 643 644 return; 645 } 646 647 void read_tap(struct params *p) 648 { 649 char *ptr; 650 int len = sizeof(p->packet); 651 int offset; 652 char mac[6]; 653 struct ieee80211_frame *wh; 654 655 ptr = p->packet; 656 offset = sizeof(struct ieee80211_frame) + 8 - 14; 657 if (p->wep_len) 658 offset += 4; 659 660 ptr += offset; 661 len -= offset; 662 663 /* read packet */ 664 memset(p->packet, 0, sizeof(p->packet)); 665 p->packet_len = read(p->tap, ptr, len); 666 if (p->packet_len == -1) 667 err(1, "read()"); 668 669 /* 802.11 header */ 670 wh = (struct ieee80211_frame*) p->packet; 671 memcpy(mac, ptr, sizeof(mac)); 672 fill_basic(wh, p); 673 memcpy(wh->i_addr3, mac, sizeof(wh->i_addr3)); 674 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA; 675 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS; 676 if (p->wep_len) 677 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; 678 679 /* LLC & SNAP */ 680 ptr = (char*) (wh+1); 681 if (p->wep_len) 682 ptr += 4; 683 *ptr++ = 0xAA; 684 *ptr++ = 0xAA; 685 *ptr++ = 0x03; 686 *ptr++ = 0x00; 687 *ptr++ = 0x00; 688 *ptr++ = 0x00; 689 /* ether type overlaps w00t */ 690 691 p->packet_len += offset; 692 693 /* WEP */ 694 if (p->wep_len) { 695 ptr = (char*) (wh+1); 696 memcpy(ptr, &p->wep_iv, 3); 697 ptr[3] = 0; 698 p->wep_iv++; 699 700 wep_encrypt(wh, p->packet_len, p->wep_key, p->wep_len); 701 p->packet_len += 4; /* ICV */ 702 } 703 } 704 705 int main(int argc, char *argv[]) 706 { 707 char* ssid = 0; 708 char mac[] = { 0x00, 0x00, 0xde, 0xfa, 0xce, 0xd }; 709 int ch; 710 struct params p; 711 char *iface = "wlan0"; 712 char *tap = "tap0"; 713 int timeout = 50*1000; 714 struct timeval start; 715 716 memset(&p, 0, sizeof(p)); 717 p.wep_len = 0; 718 p.wep_iv = 0; 719 p.state = S_START; 720 721 while ((ch = getopt(argc, argv, "hm:s:i:w:t:b:")) != -1) { 722 switch (ch) { 723 case 'b': 724 if (str2mac(p.bssid, optarg)) { 725 printf("Error parsing BSSID\n"); 726 exit(1); 727 } 728 memcpy(p.ap, p.bssid, sizeof(p.ap)); 729 p.state = S_SEND_AUTH; 730 break; 731 732 case 's': 733 ssid = optarg; 734 break; 735 736 case 'm': 737 if (str2mac(mac, optarg)) { 738 printf("Error parsing MAC\n"); 739 exit(1); 740 } 741 break; 742 743 case 'i': 744 iface = optarg; 745 break; 746 747 case 'w': 748 if (str2wep(p.wep_key, &p.wep_len, optarg)) { 749 printf("Error parsing WEP key\n"); 750 exit(1); 751 } 752 break; 753 754 case 't': 755 tap = optarg; 756 break; 757 758 case 'h': 759 default: 760 usage(argv[0]); 761 break; 762 } 763 } 764 765 if (!ssid) 766 usage(argv[0]); 767 768 p.mac = mac; 769 p.ssid = ssid; 770 p.seq = getpid(); 771 p.seq_rx = -1; 772 if (open_rxtx(iface, &p.rx, &p.tx) == -1) 773 err(1, "open_rxtx()"); 774 p.tap = open_tap(tap); 775 if (p.tap == -1) 776 err(1, "open_tap()"); 777 if (set_iface_mac(tap, mac) == -1) 778 err(1, "set_iface_mac()"); 779 780 while (1) { 781 /* check for timeouts */ 782 switch (p.state) { 783 case S_WAIT_PROBE_RES: 784 case S_WAIT_AUTH: 785 case S_WAIT_ASSOC: 786 case S_WAIT_ACK: 787 do { 788 int rc; 789 struct timeval tv; 790 int elapsed = 0; 791 792 /* check timeout */ 793 if (gettimeofday(&tv, NULL) == -1) 794 err(1, "gettimeofday()"); 795 elapsed = tv.tv_sec - start.tv_sec; 796 if (elapsed == 0) { 797 elapsed = tv.tv_usec - start.tv_usec; 798 } else { 799 elapsed *= (elapsed-1)*1000*1000; 800 elapsed += 1000*1000 - start.tv_usec; 801 elapsed += tv.tv_usec; 802 } 803 if (elapsed >= timeout) 804 rc = 0; 805 else { 806 fd_set fds; 807 808 FD_ZERO(&fds); 809 FD_SET(p.rx, &fds); 810 811 elapsed = timeout - elapsed; 812 tv.tv_sec = elapsed/1000/1000; 813 elapsed -= tv.tv_sec*1000*1000; 814 tv.tv_usec = elapsed; 815 816 rc = select(p.rx+1, &fds, NULL, 817 NULL, &tv); 818 if (rc == -1) 819 err(1, "select()"); 820 } 821 822 /* timeout */ 823 if (!rc) { 824 #if 0 825 printf("Timeout\n"); 826 #endif 827 p.state--; 828 } 829 830 } while(0); 831 break; 832 } 833 834 switch (p.state) { 835 case S_START: 836 p.state = S_SEND_PROBE_REQ; 837 break; 838 839 case S_SEND_PROBE_REQ: 840 printf("Sending probe request for %s\n", ssid); 841 send_probe_request(&p); 842 p.state = S_WAIT_PROBE_RES; 843 if (gettimeofday(&start, NULL) == -1) 844 err(1, "gettimeofday()"); 845 break; 846 847 case S_WAIT_PROBE_RES: 848 if (get_probe_response(&p)) { 849 p.state = S_SEND_AUTH; 850 } 851 break; 852 853 case S_SEND_AUTH: 854 do { 855 char apmac[18]; 856 857 mac2str(apmac, p.ap); 858 printf("Sending auth to %s\n", apmac); 859 send_auth(&p); 860 p.state = S_WAIT_AUTH; 861 if (gettimeofday(&start, NULL) == -1) 862 err(1, "gettimeofday()"); 863 } while(0); 864 break; 865 866 case S_WAIT_AUTH: 867 if (get_auth(&p)) { 868 p.state = S_SEND_ASSOC; 869 } 870 break; 871 872 case S_SEND_ASSOC: 873 printf("Sending assoc\n"); 874 send_assoc(&p); 875 p.state = S_WAIT_ASSOC; 876 if (gettimeofday(&start, NULL) == -1) 877 err(1, "gettimeofday()"); 878 break; 879 880 case S_WAIT_ASSOC: 881 if (get_assoc(&p)) { 882 printf("Associated\n"); 883 p.state = S_ASSOCIATED; 884 } 885 break; 886 887 case S_ASSOCIATED: 888 do { 889 fd_set fds; 890 int max; 891 892 FD_ZERO(&fds); 893 FD_SET(p.rx, &fds); 894 FD_SET(p.tap, &fds); 895 max = (p.rx > p.tap) ? p.rx : p.tap; 896 897 max = select(max+1, &fds, NULL, NULL, NULL); 898 if (max == -1) 899 err(1, "select()"); 900 901 if (FD_ISSET(p.tap, &fds)) { 902 read_tap(&p); 903 p.state = S_SEND_DATA; 904 } 905 if (FD_ISSET(p.rx, &fds)) { 906 read_wifi(&p); 907 } 908 } while(0); 909 break; 910 911 case S_SEND_DATA: 912 send_frame(&p, p.packet, p.packet_len); 913 do { 914 struct ieee80211_frame *wh; 915 916 wh = (struct ieee80211_frame*) p.packet; 917 wh->i_fc[1] |= IEEE80211_FC1_RETRY; 918 } while (0); 919 p.state = S_WAIT_ACK; 920 if (gettimeofday(&start, NULL) == -1) 921 err(1, "gettimeofday()"); 922 break; 923 924 case S_WAIT_ACK: 925 read_wifi(&p); 926 break; 927 928 default: 929 printf("Unknown state %d\n", p.state); 930 abort(); 931 break; 932 } 933 } 934 935 exit(0); 936 } 937