nrelease - fix/improve livecd
[dragonfly.git] / tools / tools / net80211 / wlaninject / wlaninject.c
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 }