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