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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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(&params, 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, &params);
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