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: src/tools/tools/net80211/wlaninject/wlaninject.c,v 1.3 2009/07/24 15:31:22 sam Exp $
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 <netproto/802_11/ieee80211.h>
44 #include <netproto/802_11/ieee80211_ioctl.h>
45 #include <netproto/802_11/ieee80211_dragonfly.h>
46 #include <netproto/802_11/ieee80211_radiotap.h>
47 #include <sys/endian.h>
48 #include <assert.h>
49
setup_if(char * dev,int chan)50 void 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
open_bpf(char * dev)84 int 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
inject(int fd,void * buf,int buflen,struct ieee80211_bpf_params * p)121 void 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
usage(char * progname)143 void 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
str2type(const char * type)187 int 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
str2subtype(const char * subtype)201 int 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
str2mac(unsigned char * mac,char * str)221 void 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
str2wmeac(const char * ac)237 int 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
str2rate(const char * rate)252 int 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
rate2str(int rate)271 const 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
load_payload(char * fname,void * buf,int len)281 int 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
header_len(struct ieee80211_frame * wh)297 int 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
parse_ie(char * str,unsigned char * ie,int len)390 int 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
possible_match(struct ieee80211_frame * sent,int slen,struct ieee80211_frame * got,int glen)439 int 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
do_verify(struct ieee80211_frame * sent,int slen,void * got,int glen)467 int 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
main(int argc,char * argv[])526 int 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_WEP;
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