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