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