xref: /dragonfly/tools/tools/net80211/w00t/ap/ap.c (revision 3d33658b)
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[1] = 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 }
917