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