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 <stdlib.h> 27 #include <stdio.h> 28 #include <errno.h> 29 #include <err.h> 30 #include <fcntl.h> 31 #include <unistd.h> 32 #include <sys/types.h> 33 #include <sys/time.h> 34 #include <sys/ioctl.h> 35 #include <sys/uio.h> 36 #include <net/bpf.h> 37 #include <sys/socket.h> 38 #include <net/if.h> 39 #include <net/if_media.h> 40 #include <string.h> 41 #include <net80211/ieee80211.h> 42 #include <net80211/ieee80211_ioctl.h> 43 #include <net80211/ieee80211_freebsd.h> 44 #include <net80211/ieee80211_radiotap.h> 45 #include <sys/endian.h> 46 #include <assert.h> 47 48 void setup_if(char *dev, int chan) { 49 int s; 50 struct ifreq ifr; 51 unsigned int flags; 52 struct ifmediareq ifmr; 53 int *mwords; 54 struct ieee80211req ireq; 55 56 if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1) 57 err(1, "socket()"); 58 59 /* chan */ 60 memset(&ireq, 0, sizeof(ireq)); 61 snprintf(ireq.i_name, sizeof(ireq.i_name), "%s", dev); 62 ireq.i_type = IEEE80211_IOC_CHANNEL; 63 ireq.i_val = chan; 64 if (ioctl(s, SIOCS80211, &ireq) == -1) 65 err(1, "ioctl(SIOCS80211)"); 66 67 /* UP & PROMISC */ 68 memset(&ifr, 0, sizeof(ifr)); 69 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", dev); 70 if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) 71 err(1, "ioctl(SIOCGIFFLAGS)"); 72 flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16); 73 flags |= IFF_UP | IFF_PPROMISC; 74 ifr.ifr_flags = flags & 0xffff; 75 ifr.ifr_flagshigh = flags >> 16; 76 if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) 77 err(1, "ioctl(SIOCSIFFLAGS)"); 78 79 close(s); 80 } 81 82 int open_bpf(char *dev) 83 { 84 char buf[64]; 85 int i; 86 int fd; 87 struct ifreq ifr; 88 unsigned int dlt = DLT_IEEE802_11_RADIO; 89 90 for (i = 0; i < 64; i++) { 91 sprintf(buf, "/dev/bpf%d", i); 92 93 fd = open(buf, O_RDWR); 94 if (fd != -1) 95 break; 96 else if (errno != EBUSY) 97 err(1, "open()"); 98 } 99 if (fd == -1) { 100 printf("Can't find bpf\n"); 101 exit(1); 102 } 103 104 memset(&ifr, 0, sizeof(ifr)); 105 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", dev); 106 if (ioctl(fd, BIOCSETIF, &ifr) == -1) 107 err(1, "ioctl(BIOCSETIF)"); 108 109 if (ioctl(fd, BIOCSDLT, &dlt) == -1) 110 err(1, "ioctl(BIOCSDLT)"); 111 112 i = 1; 113 if (ioctl(fd, BIOCIMMEDIATE, &i) == -1) 114 err(1, "ioctl(BIOCIMMEDIATE)"); 115 116 return fd; 117 } 118 119 void inject(int fd, void *buf, int buflen, struct ieee80211_bpf_params *p) 120 { 121 struct iovec iov[2]; 122 int totlen; 123 int rc; 124 125 iov[0].iov_base = p; 126 iov[0].iov_len = p->ibp_len; 127 128 iov[1].iov_base = buf; 129 iov[1].iov_len = buflen; 130 totlen = iov[0].iov_len + iov[1].iov_len; 131 132 rc = writev(fd, iov, sizeof(iov)/sizeof(struct iovec)); 133 if (rc == -1) 134 err(1, "writev()"); 135 if (rc != totlen) { 136 printf("Wrote only %d/%d\n", rc, totlen); 137 exit(1); 138 } 139 } 140 141 void usage(char *progname) 142 { 143 printf("Usage: %s <opts>\n" 144 "Physical:\n" 145 "\t-i\t<iface>\n" 146 "\t-c\t<chan>\n" 147 "\t-N\tno ack\n" 148 "\t-V\t<iface> [verify via iface whether packet was mangled]\n" 149 "\t-W\tWME AC\n" 150 "\t-X\ttransmit rate (Mbps)\n" 151 "\t-P\ttransmit power (device units)\n" 152 "802.11:\n" 153 "\t-h\tthis lame message\n" 154 "\t-v\t<version>\n" 155 "\t-t\t<type>\n" 156 "\t-s\t<subtype>\n" 157 "\t-T\tto ds\n" 158 "\t-F\tfrom ds\n" 159 "\t-m\tmore frags\n" 160 "\t-r\tretry\n" 161 "\t-p\tpower\n" 162 "\t-d\tmore data\n" 163 "\t-w\twep\n" 164 "\t-o\torder\n" 165 "\t-u\t<duration>\n" 166 "\t-1\t<addr 1>\n" 167 "\t-2\t<addr 2>\n" 168 "\t-3\t<addr 3>\n" 169 "\t-n\t<seqno>\n" 170 "\t-f\t<fragno>\n" 171 "\t-4\t<addr 4>\n" 172 "\t-b\t<payload file>\n" 173 "\t-l\t<len>\n" 174 "Management:\n" 175 "\t-e\t<info element [hex digits 010203... first is type]>\n" 176 "\t-S\t<SSID>\n" 177 "\t-a\t<algo no>\n" 178 "\t-A\t<transaction>\n" 179 "\t-C\t<status code>\n" 180 "\t-R\tstandard rates\n" 181 , progname); 182 exit(1); 183 } 184 185 int str2type(const char *type) 186 { 187 #define equal(a,b) (strcasecmp(a,b) == 0) 188 if (equal(type, "mgt")) 189 return IEEE80211_FC0_TYPE_MGT >> IEEE80211_FC0_TYPE_SHIFT; 190 else if (equal(type, "ctl")) 191 return IEEE80211_FC0_TYPE_CTL >> IEEE80211_FC0_TYPE_SHIFT; 192 else if (equal(type, "data")) 193 return IEEE80211_FC0_TYPE_DATA >> IEEE80211_FC0_TYPE_SHIFT; 194 195 return atoi(type) & 3; 196 #undef equal 197 } 198 199 int str2subtype(const char *subtype) 200 { 201 #define equal(a,b) (strcasecmp(a,b) == 0) 202 if (equal(subtype, "preq") || equal(subtype, "probereq")) 203 return IEEE80211_FC0_SUBTYPE_PROBE_REQ >> 204 IEEE80211_FC0_SUBTYPE_SHIFT; 205 else if (equal(subtype, "auth")) 206 return IEEE80211_FC0_SUBTYPE_AUTH >> 207 IEEE80211_FC0_SUBTYPE_SHIFT; 208 else if (equal(subtype, "areq") || equal(subtype, "assocreq")) 209 return IEEE80211_FC0_SUBTYPE_ASSOC_REQ >> 210 IEEE80211_FC0_SUBTYPE_SHIFT; 211 else if (equal(subtype, "data")) 212 return IEEE80211_FC0_SUBTYPE_DATA >> 213 IEEE80211_FC0_SUBTYPE_SHIFT; 214 215 return atoi(subtype) & 0xf; 216 #undef equal 217 } 218 219 void str2mac(unsigned char *mac, char *str) 220 { 221 unsigned int macf[6]; 222 int i; 223 224 if (sscanf(str, "%x:%x:%x:%x:%x:%x", 225 &macf[0], &macf[1], &macf[2], 226 &macf[3], &macf[4], &macf[5]) != 6) { 227 printf("can't parse mac %s\n", str); 228 exit(1); 229 } 230 231 for (i = 0; i < 6; i++) 232 *mac++ = (unsigned char) macf[i]; 233 } 234 235 int str2wmeac(const char *ac) 236 { 237 #define equal(a,b) (strcasecmp(a,b) == 0) 238 if (equal(ac, "ac_be") || equal(ac, "be")) 239 return WME_AC_BE; 240 if (equal(ac, "ac_bk") || equal(ac, "bk")) 241 return WME_AC_BK; 242 if (equal(ac, "ac_vi") || equal(ac, "vi")) 243 return WME_AC_VI; 244 if (equal(ac, "ac_vo") || equal(ac, "vo")) 245 return WME_AC_VO; 246 errx(1, "unknown wme access class %s", ac); 247 #undef equal 248 } 249 250 int str2rate(const char *rate) 251 { 252 switch (atoi(rate)) { 253 case 54: return 54*2; 254 case 48: return 48*2; 255 case 36: return 36*2; 256 case 24: return 24*2; 257 case 18: return 18*2; 258 case 12: return 12*2; 259 case 9: return 9*2; 260 case 6: return 6*2; 261 case 11: return 11*2; 262 case 5: return 11; 263 case 2: return 2*2; 264 case 1: return 1*2; 265 } 266 errx(1, "unknown transmit rate %s", rate); 267 } 268 269 const char *rate2str(int rate) 270 { 271 static char buf[30]; 272 273 if (rate == 11) 274 return "5.5"; 275 snprintf(buf, sizeof(buf), "%u", rate/2); 276 return buf; 277 } 278 279 int load_payload(char *fname, void *buf, int len) 280 { 281 int fd; 282 int rc; 283 284 if ((fd = open(fname, O_RDONLY)) == -1) 285 err(1, "open()"); 286 287 if ((rc = read(fd, buf, len)) == -1) 288 err(1, "read()"); 289 290 close(fd); 291 printf("Read %d bytes from %s\n", rc, fname); 292 return rc; 293 } 294 295 int header_len(struct ieee80211_frame *wh) 296 { 297 int len = sizeof(*wh); 298 299 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { 300 case IEEE80211_FC0_TYPE_MGT: 301 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 302 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: 303 len += 2 + 2; /* capa & listen */ 304 break; 305 306 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: 307 len += 2 + 2 + 2; /* capa & status & assoc */ 308 break; 309 310 case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: 311 len += 2 + 2 + 6; /* capa & listen & AP */ 312 break; 313 314 case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: 315 len += 2 + 2 + 2; /* capa & status & assoc */ 316 break; 317 318 case IEEE80211_FC0_SUBTYPE_PROBE_REQ: 319 case IEEE80211_FC0_SUBTYPE_ATIM: 320 break; 321 322 case IEEE80211_FC0_SUBTYPE_PROBE_RESP: 323 case IEEE80211_FC0_SUBTYPE_BEACON: 324 len += 8 + 2 + 2; /* time & bint & capa */ 325 break; 326 327 case IEEE80211_FC0_SUBTYPE_DISASSOC: 328 len += 2; /* reason */ 329 break; 330 331 case IEEE80211_FC0_SUBTYPE_AUTH: 332 len += 2 + 2 + 2; /* algo & seq & status */ 333 break; 334 335 case IEEE80211_FC0_SUBTYPE_DEAUTH: 336 len += 2; /* reason */ 337 break; 338 339 default: 340 errx(1, "Unknown MGT subtype 0x%x", 341 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 342 } 343 break; 344 345 case IEEE80211_FC0_TYPE_CTL: 346 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) { 347 case IEEE80211_FC0_SUBTYPE_PS_POLL: 348 len = sizeof(struct ieee80211_frame_pspoll); 349 break; 350 351 case IEEE80211_FC0_SUBTYPE_RTS: 352 len = sizeof(struct ieee80211_frame_rts); 353 break; 354 355 case IEEE80211_FC0_SUBTYPE_CTS: 356 len = sizeof(struct ieee80211_frame_cts); 357 break; 358 359 case IEEE80211_FC0_SUBTYPE_ACK: 360 len = sizeof(struct ieee80211_frame_ack); 361 break; 362 363 case IEEE80211_FC0_SUBTYPE_CF_END_ACK: 364 case IEEE80211_FC0_SUBTYPE_CF_END: 365 len = sizeof(struct ieee80211_frame_cfend); 366 break; 367 368 default: 369 errx(1, "Unknown CTL subtype 0x%x", 370 wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); 371 } 372 break; 373 374 case IEEE80211_FC0_TYPE_DATA: 375 if (wh->i_fc[1] & IEEE80211_FC1_DIR_DSTODS) 376 len += sizeof(wh->i_addr1); 377 break; 378 379 default: 380 errx(1, "Unknown type 0x%x", 381 wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); 382 exit(1); 383 } 384 385 return len; 386 } 387 388 int parse_ie(char *str, unsigned char *ie, int len) 389 { 390 int digits = 0; 391 char num[3]; 392 int conv = 0; 393 int ielen; 394 395 ielen = strlen(str)/2; 396 if (ielen < 1 || (strlen(str) % 2)) { 397 printf("Invalid IE %s\n", str); 398 exit(1); 399 } 400 401 num[2] = 0; 402 while (ielen) { 403 num[digits++] = *str; 404 str++; 405 if (digits == 2) { 406 unsigned int x; 407 408 sscanf(num, "%x", &x); 409 410 if (len <= 0) { 411 printf("No space for IE\n"); 412 exit(1); 413 } 414 415 *ie++ = (unsigned char) x; 416 len--; 417 ielen--; 418 419 /* first char */ 420 if (conv == 0) { 421 if (len == 0) { 422 printf("No space for IE\n"); 423 exit(1); 424 } 425 *ie++ = (unsigned char) ielen; 426 len--; 427 conv++; 428 } 429 conv++; 430 digits = 0; 431 } 432 } 433 434 return conv; 435 } 436 437 int possible_match(struct ieee80211_frame *sent, int slen, 438 struct ieee80211_frame *got, int glen) 439 { 440 if (slen != glen) 441 return 0; 442 443 if (memcmp(sent->i_addr1, got->i_addr1, 6) != 0) 444 printf("Addr1 doesn't match\n"); 445 446 if ((sent->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != 447 (got->i_fc[0] & IEEE80211_FC0_TYPE_MASK)) 448 return 0; 449 450 if ((sent->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) != 451 (got->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)) 452 return 0; 453 454 /* Good enough for CTL frames I guess */ 455 if ((got->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL) 456 return 1; 457 458 if (memcmp(sent->i_addr2, got->i_addr2, 6) == 0 && 459 memcmp(sent->i_addr3, got->i_addr3, 6) == 0) 460 return 1; 461 462 return 0; 463 } 464 465 int do_verify(struct ieee80211_frame *sent, int slen, void *got, int glen) 466 { 467 #define BIT(n) (1<<(n)) 468 struct bpf_hdr *bpfh = got; 469 struct ieee80211_frame *wh; 470 struct ieee80211_radiotap_header *rth; 471 int i; 472 unsigned char *ptr, *ptr2; 473 uint32_t present; 474 uint8_t rflags; 475 476 /* get the 802.11 header */ 477 glen -= bpfh->bh_hdrlen; 478 assert(glen > 0); 479 if (bpfh->bh_caplen != glen) { 480 abort(); 481 } 482 rth = (struct ieee80211_radiotap_header*) 483 ((char*) bpfh + bpfh->bh_hdrlen); 484 glen -= rth->it_len; 485 assert(glen > 0); 486 wh = (struct ieee80211_frame*) ((char*)rth + rth->it_len); 487 488 /* check if FCS/CRC is included in packet */ 489 present = le32toh(rth->it_present); 490 if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) { 491 if (present & BIT(IEEE80211_RADIOTAP_TSFT)) 492 rflags = ((const uint8_t *)rth)[8]; 493 else 494 rflags = ((const uint8_t *)rth)[0]; 495 } else 496 rflags = 0; 497 if (rflags & IEEE80211_RADIOTAP_F_FCS) 498 glen -= IEEE80211_CRC_LEN; 499 assert(glen > 0); 500 501 /* did we receive the packet we sent? */ 502 if (!possible_match(sent, slen, wh, glen)) 503 return 0; 504 505 /* check if it got mangled */ 506 if (memcmp(sent, wh, slen) == 0) { 507 printf("No mangling---got it perfect\n"); 508 return 1; 509 } 510 511 /* print differences */ 512 printf("Got mangled:\n"); 513 ptr = (unsigned char*) sent; 514 ptr2 = (unsigned char *) wh; 515 for (i = 0; i < slen; i++, ptr++, ptr2++) { 516 if (*ptr != *ptr2) 517 printf("Position: %d Was: %.2X Got: %.2X\n", 518 i, *ptr, *ptr2); 519 } 520 return -1; 521 #undef BIT 522 } 523 524 int main(int argc, char *argv[]) 525 { 526 int fd, fd2; 527 char *iface = "wlan0"; 528 char *verify = NULL; 529 int chan = 1; 530 struct { 531 struct ieee80211_frame w; 532 unsigned char buf[2048]; 533 } __packed u; 534 int len = 0; 535 int ch; 536 struct ieee80211_bpf_params params; 537 struct ieee80211_frame *wh = &u.w; 538 unsigned char *body = u.buf; 539 540 memset(&u, 0, sizeof(u)); 541 memset(¶ms, 0, sizeof(params)); 542 params.ibp_vers = IEEE80211_BPF_VERSION; 543 params.ibp_len = sizeof(struct ieee80211_bpf_params) - 6, 544 params.ibp_rate0 = 2; /* 1 MB/s XXX */ 545 params.ibp_try0 = 1; /* no retransmits */ 546 params.ibp_power = 100; /* nominal max */ 547 params.ibp_pri = WME_AC_VO; /* high priority */ 548 549 while ((ch = getopt(argc, argv, 550 "hv:t:s:TFmpdwou:1:2:3:4:b:i:c:l:n:f:e:S:a:A:C:NRV:W:X:P:")) != -1) { 551 switch (ch) { 552 case 'i': 553 iface = optarg; 554 break; 555 556 case 'c': 557 chan = atoi(optarg); 558 break; 559 560 case 'v': 561 wh->i_fc[0] |= atoi(optarg)& IEEE80211_FC0_VERSION_MASK; 562 break; 563 564 case 't': 565 wh->i_fc[0] |= str2type(optarg) << 566 IEEE80211_FC0_TYPE_SHIFT; 567 break; 568 569 case 's': 570 wh->i_fc[0] |= str2subtype(optarg) << 571 IEEE80211_FC0_SUBTYPE_SHIFT; 572 len = header_len(wh); 573 body += len; 574 break; 575 576 case 'T': 577 wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS; 578 break; 579 580 case 'F': 581 wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS; 582 break; 583 584 case 'm': 585 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG; 586 break; 587 588 case 'r': 589 wh->i_fc[1] |= IEEE80211_FC1_RETRY; 590 break; 591 592 case 'p': 593 wh->i_fc[1] |= IEEE80211_FC1_PWR_MGT; 594 break; 595 596 case 'd': 597 wh->i_fc[1] |= IEEE80211_FC1_MORE_DATA; 598 break; 599 600 case 'w': 601 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED; 602 break; 603 604 case 'o': 605 wh->i_fc[1] |= IEEE80211_FC1_ORDER; 606 break; 607 608 case 'u': 609 *(uint16_t*)wh->i_dur = htole16(atoi(optarg)); 610 break; 611 612 case '1': 613 str2mac(wh->i_addr1, optarg); 614 break; 615 616 case '2': 617 str2mac(wh->i_addr2, optarg); 618 break; 619 620 case '3': 621 str2mac(wh->i_addr3, optarg); 622 break; 623 624 case '4': 625 str2mac(body, optarg); 626 break; 627 628 case 'n': 629 *(uint16_t*)wh->i_seq |= htole16((atoi(optarg) & 0xfff) 630 << IEEE80211_SEQ_SEQ_SHIFT); 631 break; 632 633 case 'f': 634 wh->i_seq[0] |= atoi(optarg) & 0xf; 635 break; 636 637 case 'b': 638 len += load_payload(optarg, body, 639 u.buf + sizeof(u.buf) - body); 640 break; 641 642 case 'l': 643 len = atoi(optarg); 644 break; 645 646 case 'e': 647 do { 648 int ln; 649 650 ln = parse_ie(optarg, body, 651 u.buf + sizeof(u.buf) - body); 652 len += ln; 653 body += ln; 654 } while(0); 655 break; 656 657 case 'S': 658 do { 659 int ln; 660 int left = u.buf + sizeof(u.buf) - body; 661 662 ln = strlen(optarg) & 0xff; 663 if ((ln + 2) > left) { 664 printf("No space for SSID\n"); 665 exit(1); 666 } 667 668 *body++ = 0; 669 *body++ = ln; 670 memcpy(body, optarg, ln); 671 body += ln; 672 len += ln + 2; 673 } while(0); 674 break; 675 676 case 'R': 677 do { 678 unsigned char rates[] = "\x1\x4\x82\x84\xb\x16"; 679 int left = u.buf + sizeof(u.buf) - body; 680 681 if ((sizeof(rates) - 1) > left) { 682 printf("No space for rates\n"); 683 exit(1); 684 } 685 686 memcpy(body, rates, sizeof(rates) - 1); 687 body += sizeof(rates) - 1; 688 len += sizeof(rates) - 1; 689 } while(0); 690 break; 691 692 case 'a': 693 do { 694 uint16_t *x = (uint16_t*) (wh+1); 695 *x = htole16(atoi(optarg)); 696 } while(0); 697 break; 698 699 case 'A': 700 do { 701 uint16_t *x = (uint16_t*) (wh+1); 702 x += 1; 703 *x = htole16(atoi(optarg)); 704 } while(0); 705 break; 706 707 case 'C': 708 do { 709 uint16_t *x = (uint16_t*) (wh+1); 710 711 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) 712 == IEEE80211_FC0_SUBTYPE_AUTH) 713 x += 1; 714 x += 1; 715 *x = htole16(atoi(optarg)); 716 } while(0); 717 break; 718 719 case 'N': 720 params.ibp_flags |= IEEE80211_BPF_NOACK; 721 break; 722 723 case 'V': 724 verify = optarg; 725 break; 726 727 case 'W': 728 params.ibp_pri = str2wmeac(optarg); 729 break; 730 731 case 'X': 732 params.ibp_rate0 = str2rate(optarg); 733 break; 734 735 case 'P': 736 params.ibp_power = atoi(optarg); 737 break; 738 739 case 'h': 740 default: 741 usage(argv[0]); 742 break; 743 } 744 } 745 746 if (!len) { 747 usage(argv[0]); 748 exit(1); 749 } 750 751 printf("Using interface %s on chan %d, transmit at %s Mbp/s\n", 752 iface, chan, rate2str(params.ibp_rate0)); 753 setup_if(iface, chan); 754 fd = open_bpf(iface); 755 printf("Dose: %db\n", len); 756 757 if (verify) { 758 setup_if(verify, chan); 759 fd2 = open_bpf(verify); 760 } 761 inject(fd, wh, len, ¶ms); 762 close(fd); 763 if (verify) { 764 char buf2[4096]; 765 int rc; 766 int max = 10; 767 int timeout = 2; 768 fd_set fds; 769 struct timeval tv; 770 time_t start; 771 772 printf("Verifying via %s\n", verify); 773 start = time(NULL); 774 while (max--) { 775 FD_ZERO(&fds); 776 FD_SET(fd2, &fds); 777 778 tv.tv_usec = 0; 779 tv.tv_sec = time(NULL) - start; 780 if (tv.tv_sec >= timeout) { 781 timeout = 0; 782 break; 783 } 784 tv.tv_sec = timeout - tv.tv_sec; 785 if (select(fd2+1, &fds, NULL, NULL, &tv) == -1) 786 err(1, "select()"); 787 if (!FD_ISSET(fd2, &fds)) 788 continue; 789 790 if ((rc = read(fd2, buf2, sizeof(buf2))) == -1) 791 err(1, "read()"); 792 793 if (do_verify(wh, len, buf2, rc)) { 794 max = 666; 795 break; 796 } 797 } 798 if (max != 666 || !timeout) 799 printf("No luck\n"); 800 close(fd2); 801 } 802 803 exit(0); 804 } 805