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