Initial import of binutils 2.22 on the new vendor branch
[dragonfly.git] / tools / tools / net80211 / w00t / ap / ap.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/w00t/ap/ap.c,v 1.2 2009/07/24 15:31:22 sam Exp $
27  */
28 #include <sys/types.h>
29 #include <sys/select.h>
30 #include <sys/time.h>
31 #include <sys/endian.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <err.h>
37 #include <assert.h>
38 #include "w00t.h"
39
40 struct client {
41         char mac[6];
42         int seq;
43
44         struct client *next;
45 };
46
47 struct params {
48         /* fds */
49         int tx;
50         int rx;
51         int tap;
52
53         /* ap params */
54         char mac[6];
55         char ssid[256];
56         int chan;
57
58         /* beacon */
59         int bint;
60         struct timeval blast;
61
62         int seq;
63
64         /* wep */
65         int wep_len;
66         char wep_key[13];
67         int wep_iv;
68
69         struct client *clients;
70
71         /* lame window */
72         char packet[4096];
73         int packet_len;
74         int packet_try;
75         struct timeval plast;
76 };
77
78 void usage(char *name)
79 {
80         printf("Usage: %s <opts>\n"
81                "-h\thelp\n"
82                "-i\t<iface>\n"
83                "-s\t<ssid>\n"
84                "-m\t<mac>\n"
85                "-w\t<wep key>\n"
86                "-c\t<chan>\n"
87                "-t\t<tap>\n"
88                , name);
89         exit(0);
90 }
91
92 void fill_basic(struct ieee80211_frame *wh, struct params *p)
93 {
94         short *seq;
95
96         wh->i_dur[0] = 0x69;
97         wh->i_dur[1] = 0x00;
98
99         memcpy(wh->i_addr2, p->mac, 6);
100
101         seq = (short*)wh->i_seq;
102         *seq = seqfn(p->seq, 0);
103 }
104
105 void send_frame(struct params *p, void *buf, int len)
106 {
107         int rc;
108
109         rc = inject(p->tx, buf, len);
110         if (rc == -1)
111                 err(1, "inject()");
112         if (rc != len) {
113                 printf("injected %d/%d\n", rc, len);
114                 exit(1);
115         }
116         p->seq++;
117 }
118
119 int fill_beacon(struct params *p, struct ieee80211_frame *wh)
120 {
121         int len;
122         char *ptr;
123
124         ptr = (char*) (wh+1);
125         ptr += 8; /* timestamp */
126         ptr += 2; /* bint */
127         *ptr |= IEEE80211_CAPINFO_ESS;
128         ptr += 2; /* capa */
129
130         /* ssid */
131         len = strlen(p->ssid);
132         *ptr++ = 0;
133         *ptr++ = len;
134         memcpy(ptr, p->ssid, len);
135         ptr += len;
136
137         /* rates */
138         *ptr++ = 1;
139         *ptr++ = 4;
140         *ptr++ = 2 | 0x80;
141         *ptr++ = 4 | 0x80;
142         *ptr++ = 11;
143         *ptr++ = 22;
144
145         /* ds param */
146         *ptr++ = 3;
147         *ptr++ = 1;
148         *ptr++ = p->chan;
149
150         return ptr - ((char*) wh);
151 }
152
153 void send_beacon(struct params *p)
154 {
155         char buf[4096];
156         struct ieee80211_frame *wh;
157         int len;
158         char *ptr;
159
160         wh = (struct ieee80211_frame*) buf;
161
162         memset(buf, 0, sizeof(buf));
163         fill_basic(wh, p);
164         memset(wh->i_addr1, 0xff, 6);
165         memcpy(wh->i_addr3, p->mac, 6);
166
167         wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
168         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_BEACON;
169
170         len = fill_beacon(p, wh);
171
172         /* TIM */
173         ptr = (char*)wh + len;
174         *ptr++ = 5;
175         *ptr++ = 4;
176         len +=  2+4;
177 #if 0
178         printf("sending beacon\n");
179 #endif
180         send_frame(p, wh, len);
181
182         if (gettimeofday(&p->blast, NULL) == -1)
183                 err(1, "gettimeofday()");
184 }
185
186
187 void send_pres(struct params *p, char *mac)
188 {
189         char buf[4096];
190         struct ieee80211_frame *wh;
191         int len;
192
193         wh = (struct ieee80211_frame*) buf;
194
195         memset(buf, 0, sizeof(buf));
196         fill_basic(wh, p);
197         memcpy(wh->i_addr1, mac, 6);
198         memcpy(wh->i_addr3, p->mac, 6);
199
200         wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
201         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PROBE_RESP;
202
203         len = fill_beacon(p, wh);
204
205         printf("sending probe response\n");
206         send_frame(p, wh, len);
207 }
208
209 void read_preq(struct params *p, struct ieee80211_frame *wh, int len)
210 {
211         unsigned char *ptr;
212         unsigned char *end;
213         unsigned char macs[6*3];
214
215         ptr = (unsigned char*) (wh+1);
216
217         /* ssid */
218         if (*ptr != 0) {
219                 printf("weird pr %x\n", *ptr);
220                 return;
221         }
222         ptr++;
223
224         end = ptr + (*ptr) + 1;
225         *end = 0;
226         ptr++;
227
228         mac2str(macs, wh->i_addr2);
229         printf("Probe request for [%s] from %s\n", ptr, macs);
230
231         if ((strcmp(ptr, "") == 0) || (strcmp(ptr, p->ssid) == 0))
232                 send_pres(p, wh->i_addr2);
233 }
234
235 void send_auth(struct params* p, char *mac)
236 {
237         char buf[4096];
238         struct ieee80211_frame *wh;
239         unsigned short *ptr;
240         int len;
241
242         wh = (struct ieee80211_frame*) buf;
243
244         memset(buf, 0, sizeof(buf));
245         fill_basic(wh, p);
246         memcpy(wh->i_addr1, mac, 6);
247         memcpy(wh->i_addr3, p->mac, 6);
248
249         wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
250         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_AUTH;
251
252         ptr = (unsigned short*) (wh+1);
253         *ptr++ = htole16(0);
254         *ptr++ = htole16(2);
255         *ptr++ = htole16(0);
256
257         len = ((char*)ptr) - ((char*) wh);
258         printf("sending auth\n");
259         send_frame(p, wh, len);
260 }
261
262 void read_auth(struct params *p, struct ieee80211_frame *wh, int len)
263 {
264         unsigned short *ptr;
265         char mac[6*3];
266
267         if (memcmp(wh->i_addr1, p->mac, 6) != 0)
268                 return;
269
270         ptr = (unsigned short*) (wh+1);
271         if (le16toh(*ptr) != 0) {
272                 printf("Unknown auth algo %d\n", le16toh(*ptr));
273                 return;
274         }
275         ptr++;
276         if (le16toh(*ptr) == 1) {
277                 mac2str(mac, wh->i_addr2);
278                 printf("Got auth from %s\n", mac);
279                 send_auth(p, wh->i_addr2);
280         } else {
281                 printf("Weird seq in auth %d\n", le16toh(*ptr));
282         }
283 }
284
285 void send_assoc(struct params *p, char *mac)
286 {
287         char buf[4096];
288         struct ieee80211_frame *wh;
289         char *ptr;
290         int len;
291
292         wh = (struct ieee80211_frame*) buf;
293
294         memset(buf, 0, sizeof(buf));
295         fill_basic(wh, p);
296         memcpy(wh->i_addr1, mac, 6);
297         memcpy(wh->i_addr3, p->mac, 6);
298
299         wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
300         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
301
302         ptr = (char*) (wh+1);
303         *ptr |= IEEE80211_CAPINFO_ESS;
304         ptr += 2; /* cap */
305         ptr += 2; /* status */
306         ptr += 2; /* aid */
307
308         /* rates */
309         *ptr++ = 1;
310         *ptr++ = 4;
311         *ptr++ = 2 | 0x80;
312         *ptr++ = 4 | 0x80;
313         *ptr++ = 11;
314         *ptr++ = 22;
315
316         len = ptr - ((char*) wh);
317         printf("sending assoc response\n");
318         send_frame(p, wh, len);
319 }
320
321 void read_assoc(struct params *p, struct ieee80211_frame *wh, int len)
322 {
323         unsigned char *ptr;
324         unsigned char *end;
325         unsigned char macs[6*3];
326
327         if (memcmp(wh->i_addr1, p->mac, 6) != 0)
328                 return;
329
330         ptr = (unsigned char*) (wh+1);
331         ptr += 2; /* capa */
332         ptr += 2; /* list interval */
333
334         /* ssid */
335         if (*ptr != 0) {
336                 printf("weird pr %x\n", *ptr);
337                 return;
338         }
339         ptr++;
340
341         end = ptr + (*ptr) + 1;
342         *end = 0;
343         ptr++;
344
345         mac2str(macs, wh->i_addr2);
346         printf("Assoc request for [%s] from %s\n", ptr, macs);
347
348         if (strcmp(ptr, p->ssid) == 0)
349                 send_assoc(p, wh->i_addr2);
350 }
351
352 void read_mgt(struct params *p, struct ieee80211_frame *wh, int len)
353 {
354         switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
355         case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
356                 read_preq(p, wh, len);
357                 break;
358
359         case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
360                 break;
361
362         case IEEE80211_FC0_SUBTYPE_AUTH:
363                 read_auth(p, wh, len);
364                 break;
365
366         case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
367                 read_assoc(p, wh, len);
368                 break;
369
370         case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
371         case IEEE80211_FC0_SUBTYPE_BEACON:
372                 break;
373
374         default:
375                 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
376                                    IEEE80211_FC0_SUBTYPE_SHIFT);
377                 abort();
378                 break;
379         }
380 }
381
382 void send_cts(struct params *p, char *mac)
383 {
384         char buf[64];
385         struct ieee80211_frame *wh;
386
387         memset(buf, 0, sizeof(buf));
388         wh = (struct ieee80211_frame*) buf;
389         wh->i_fc[0] |= IEEE80211_FC0_TYPE_CTL;
390         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_CTS;
391         wh->i_dur[0] = 0x69;
392         wh->i_dur[0] = 0x00;
393         memcpy(wh->i_addr1, mac, 6);
394
395         send_frame(p, wh, 10);
396 }
397
398 void read_rts(struct params *p, struct ieee80211_frame *wh, int len)
399 {
400         if (memcmp(wh->i_addr1, p->mac, 6) != 0)
401                 return;
402
403         send_cts(p, wh->i_addr2);
404 }
405
406 void read_ack(struct params *p, struct ieee80211_frame *wh, int len)
407 {
408         if (memcmp(wh->i_addr1, p->mac, 6) == 0)
409                 p->packet_try = 0;
410 }
411
412 void read_ctl(struct params *p, struct ieee80211_frame *wh, int len)
413 {
414         switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
415         case IEEE80211_FC0_SUBTYPE_RTS:
416                 read_rts(p, wh, len);
417                 break;
418
419         case IEEE80211_FC0_SUBTYPE_ACK:
420                 read_ack(p, wh, len);
421                 break;
422
423         case IEEE80211_FC0_SUBTYPE_CTS:
424                 break;
425
426         default:
427                 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
428                        IEEE80211_FC0_SUBTYPE_SHIFT);
429                 abort();
430                 break;
431         }
432 #if 0
433         printf("ctl\n");
434 #endif
435 }
436
437 int broadcast(struct ieee80211_frame *wh)
438 {
439         /* XXX multicast */
440
441         if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0)
442                 return 1;
443
444         return 0;
445 }
446
447 void enque(struct params *p, struct ieee80211_frame *wh, int len)
448 {
449         if (broadcast(wh))
450                 return;
451
452         assert(sizeof(p->packet) >= len);
453
454         memcpy(p->packet, wh, len);
455         p->packet_len = len;
456         p->packet_try = 1;
457
458         wh = (struct ieee80211_frame*) p->packet;
459         wh->i_fc[1] |= IEEE80211_FC1_RETRY;
460
461         if (gettimeofday(&p->plast, NULL) == -1)
462                 err(1, "gettimeofday()");
463 }
464
465 void relay_data(struct params *p, struct ieee80211_frame *wh, int len)
466 {
467         char seq[2];
468         char fc[2];
469         unsigned short *ps;
470
471         /* copy crap */
472         memcpy(fc, wh->i_fc, 2);
473         memcpy(seq, wh->i_seq, 2);
474
475         /* relay frame */
476         wh->i_fc[1] &= ~(IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_RETRY);
477         wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
478         memcpy(wh->i_addr1, wh->i_addr3, sizeof(wh->i_addr1));
479         memcpy(wh->i_addr3, wh->i_addr2, sizeof(wh->i_addr3));
480         memcpy(wh->i_addr2, p->mac, sizeof(wh->i_addr2));
481         ps = (unsigned short*)wh->i_seq;
482         *ps = seqfn(p->seq, 0);
483
484         send_frame(p, wh, len);
485         enque(p, wh, len);
486
487         /* restore */
488         memcpy(wh->i_fc, fc, sizeof(fc));
489         memcpy(wh->i_addr2, wh->i_addr3, sizeof(wh->i_addr2));
490         memcpy(wh->i_addr3, wh->i_addr1, sizeof(wh->i_addr2));
491         memcpy(wh->i_addr1, p->mac, sizeof(wh->i_addr1));
492         memcpy(wh->i_seq, seq, sizeof(seq));
493 }
494
495 void read_real_data(struct params *p, struct ieee80211_frame *wh, int len)
496 {
497         char dst[6];
498         int rc;
499         char *ptr = (char*) (wh+1);
500
501         /* stuff not for this net */
502         if (memcmp(wh->i_addr1, p->mac, 6) != 0)
503                 return;
504
505         /* relay data */
506         if (memcmp(wh->i_addr3, p->mac, 6) != 0)
507                 relay_data(p, wh, len);
508
509         memcpy(dst, wh->i_addr3, 6);
510
511
512         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
513                 if (!p->wep_len) {
514                         printf("Got wep but i aint wep\n");
515                         return;
516                 }
517
518                 if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
519                         printf("Can't decrypt\n");
520                         return;
521                 }
522
523                 ptr += 4;
524                 len -= 8;
525         }
526
527         /* ether header */
528         ptr += 8 - 2;
529         ptr -= 6;
530         memcpy(ptr, wh->i_addr2, 6);
531         ptr -= 6;
532         memcpy(ptr, dst, 6);
533
534         len -= sizeof(*wh);
535         len -= 8;
536         len += 14;
537
538         /* send to tap */
539         rc = write(p->tap, ptr, len);
540         if (rc == -1)
541                 err(1, "write()");
542         if (rc != len) {
543                 printf("Wrote %d/%d\n", rc, len);
544                 exit(1);
545         }
546 }
547
548 void read_data(struct params *p, struct ieee80211_frame *wh, int len)
549 {
550         switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
551         case IEEE80211_FC0_SUBTYPE_DATA:
552                 read_real_data(p, wh, len);
553                 break;
554
555         case IEEE80211_FC0_SUBTYPE_NODATA:
556                 break;
557
558         default:
559                 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
560                                    IEEE80211_FC0_SUBTYPE_SHIFT);
561                 abort();
562                 break;
563         }
564 }
565
566 struct client* client_find(struct params *p, char *mac)
567 {
568         struct client* c = p->clients;
569
570         while (c) {
571                 if (memcmp(c->mac, mac, 6) == 0)
572                         return c;
573
574                 c = c->next;
575         }
576
577         return NULL;
578 }
579
580 void client_insert(struct params *p, struct client *c)
581 {
582 #if 1
583         do {
584                 char mac[6*3];
585
586                 mac2str(mac, c->mac);
587                 printf("Adding client %s\n", mac);
588         } while(0);
589 #endif
590
591         c->next = p->clients;
592         p->clients = c;
593 }
594
595 int duplicate(struct params *p, struct ieee80211_frame *wh, int rc)
596 {
597         struct client *c;
598         int s;
599
600         if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
601                         IEEE80211_FC0_SUBTYPE_DATA))
602                 return 0;
603
604         s = seqno(wh);
605
606         c = client_find(p, wh->i_addr2);
607         if (!c) {
608                 c = malloc(sizeof(*c));
609                 if (!c)
610                         err(1, "malloc()");
611
612                 memset(c, 0, sizeof(*c));
613                 memcpy(c->mac, wh->i_addr2, 6);
614
615                 c->seq = s-1;
616                 client_insert(p, c);
617         }
618
619         if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
620                 if ( (s <= c->seq) && ((c->seq - s ) < 5)) {
621 #if 0
622                         printf("Dup seq %d prev %d\n",
623                                s, c->seq);
624 #endif
625                         return 1;
626                 }
627         }
628
629 #if 0
630         do {
631                 char mac[3*6];
632
633                 mac2str(mac, c->mac);
634                 printf("%s seq %d prev %d\n", mac, s, c->seq);
635         } while (0);
636 #endif
637
638         c->seq = s;
639         return 0;
640 }
641
642 void ack(struct params *p, struct ieee80211_frame *wh)
643 {
644         if (memcmp(wh->i_addr1, p->mac, 6) != 0)
645                 return;
646
647         if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
648                 return;
649
650         send_ack(p->tx, wh->i_addr2);
651 }
652
653 void read_wifi(struct params *p)
654 {
655         char buf[4096];
656         int rc;
657         struct ieee80211_frame *wh;
658
659         rc = sniff(p->rx, buf, sizeof(buf));
660         if (rc == -1)
661                 err(1, "sniff()");
662
663         wh = get_wifi(buf, &rc);
664         if (!wh)
665                 return;
666
667         /* filter my own shit */
668         if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
669                 /* XXX CTL frames */
670                 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
671                     IEEE80211_FC0_TYPE_CTL)
672                         return;
673         }
674
675 #if 1
676         ack(p, wh);
677 #endif
678
679         if (duplicate(p, wh, rc)) {
680 #if 0
681                 printf("Dup\n");
682 #endif
683                 return;
684         }
685
686         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
687         case IEEE80211_FC0_TYPE_MGT:
688                 read_mgt(p, wh, rc);
689                 break;
690
691         case IEEE80211_FC0_TYPE_CTL:
692                 read_ctl(p, wh, rc);
693                 break;
694
695         case IEEE80211_FC0_TYPE_DATA:
696                 read_data(p, wh, rc);
697                 break;
698
699         default:
700                 printf("wtf\n");
701                 abort();
702                 break;
703         }
704 }
705
706 void read_tap(struct params *p)
707 {
708         char buf[4096];
709         char *ptr;
710         int len = sizeof(buf);
711         int offset;
712         char src[6], dst[6];
713         struct ieee80211_frame *wh;
714         int rd;
715
716         ptr = buf;
717         offset = sizeof(struct ieee80211_frame) + 8 - 14;
718         if (p->wep_len)
719                 offset += 4;
720
721         ptr += offset;
722         len -= offset;
723
724         /* read packet */
725         memset(buf, 0, sizeof(buf));
726         rd = read(p->tap, ptr, len);
727         if (rd == -1)
728                 err(1, "read()");
729
730         /* 802.11 header */
731         wh = (struct ieee80211_frame*) buf;
732         memcpy(dst, ptr, sizeof(dst));
733         memcpy(src, ptr+6, sizeof(src));
734         fill_basic(wh, p);
735         memcpy(wh->i_addr3, src, sizeof(wh->i_addr3));
736         memcpy(wh->i_addr1, dst, sizeof(wh->i_addr1));
737         wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
738         wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
739         if (p->wep_len)
740                 wh->i_fc[1] |= IEEE80211_FC1_WEP;
741
742         /* LLC & SNAP */
743         ptr = (char*) (wh+1);
744         if (p->wep_len)
745                 ptr += 4;
746         *ptr++ = 0xAA;
747         *ptr++ = 0xAA;
748         *ptr++ = 0x03;
749         *ptr++ = 0x00;
750         *ptr++ = 0x00;
751         *ptr++ = 0x00;
752         /* ether type overlaps w00t */
753
754         rd += offset;
755
756         /* WEP */
757         if (p->wep_len) {
758                 ptr = (char*) (wh+1);
759                 memcpy(ptr, &p->wep_iv, 3);
760                 ptr[3] = 0;
761                 p->wep_iv++;
762
763                 wep_encrypt(wh, rd, p->wep_key, p->wep_len);
764                 rd += 4; /* ICV */
765         }
766
767         send_frame(p, wh, rd);
768 }
769
770 int retransmit(struct params *p)
771 {
772 #if 0
773         printf("RETRANS %d\n", p->packet_try);
774 #endif
775
776         send_frame(p, p->packet, p->packet_len);
777         p->packet_try++;
778
779         if (p->packet_try > 3)
780                 p->packet_try = 0;
781         else {
782                 if (gettimeofday(&p->plast, NULL) == -1)
783                         err(1, "gettimeofday()");
784         }
785
786         return p->packet_try;
787 }
788
789 void next_event(struct params *p)
790 {
791         struct timeval to, now;
792         int el;
793         int max;
794         fd_set fds;
795         int rtr = 3*1000;
796
797         /* figure out select timeout */
798         if (gettimeofday(&now, NULL) == -1)
799                 err(1, "gettimeofday()");
800
801         /* check beacon timeout */
802         el = elapsed(&p->blast, &now);
803         if (el >= p->bint) {
804                 send_beacon(p);
805                 el = 0;
806         }
807         el = p->bint - el;
808         to.tv_sec = el/1000/1000;
809         to.tv_usec = el - to.tv_sec*1000*1000;
810
811         /* check tx timeout */
812         if (p->packet_try) {
813                 el = elapsed(&p->plast, &now);
814                 if (el >= rtr) {
815                         /* check if we gotta retransmit more */
816                         if (retransmit(p)) {
817                                 el = 0;
818                         }
819                         else
820                                 el = -1;
821                 }
822
823                 /* gotta retransmit in future */
824                 if (el != -1) {
825                         el = rtr - el;
826                         if ((to.tv_sec*1000*1000 + to.tv_usec) > el) {
827                                 to.tv_sec = el/1000/1000;
828                                 to.tv_usec = el - to.tv_sec*1000*1000;
829                         }
830                 }
831         }
832
833         /* select */
834         FD_ZERO(&fds);
835         FD_SET(p->rx, &fds);
836         FD_SET(p->tap, &fds);
837         max = p->rx > p->tap ? p->rx : p->tap;
838         if (select(max+1, &fds, NULL, NULL, &to) == -1)
839                 err(1, "select()");
840
841         if (FD_ISSET(p->tap, &fds))
842                 read_tap(p);
843         if (FD_ISSET(p->rx, &fds))
844                 read_wifi(p);
845 }
846
847 int main(int argc, char *argv[])
848 {
849         char *iface = "wlan0";
850         char *tap = "tap0";
851         struct params p;
852         int ch;
853
854         /* default params */
855         memset(&p, 0, sizeof(p));
856         memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
857         strcpy(p.ssid, "sorbo");
858         p.bint = 500*1000;
859         p.seq = getpid();
860         if (gettimeofday(&p.blast, NULL) == -1)
861                 err(1, "gettimeofday()");
862         p.chan = 3;
863
864         while ((ch = getopt(argc, argv, "hi:s:m:w:c:t:")) != -1) {
865                 switch (ch) {
866                 case 'i':
867                         iface = optarg;
868                         break;
869                 case 't':
870                         tap = optarg;
871                         break;
872
873                 case 'c':
874                         p.chan = atoi(optarg);
875                         break;
876
877                 case 's':
878                         strncpy(p.ssid, optarg, sizeof(p.ssid)-1);
879                         p.ssid[sizeof(p.ssid)-1] = 0;
880                         break;
881
882                 case 'm':
883                         str2mac(p.mac, optarg);
884                         break;
885
886                 case 'w':
887                         if (str2wep(p.wep_key, &p.wep_len, optarg)) {
888                                 printf("Error parsing WEP key\n");
889                                 exit(1);
890                         }
891                         break;
892
893                 case 'h':
894                 default:
895                         usage(argv[0]);
896                         break;
897                 }
898         }
899
900         /* init */
901         if ((p.tx = open_tx(iface)) == -1)
902                 err(1, "open_tx()");
903         if ((p.rx = open_rx(iface)) == -1)
904                 err(1, "open_rx()");
905
906         if ((p.tap = open_tap(tap)) == -1)
907                 err(1, "open_tap()");
908         if (set_iface_mac(tap, p.mac) == -1)
909                 err(1, "set_iface_mac()");
910
911         while (1) {
912                 next_event(&p);
913         }
914
915         exit(0);
916 }