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
38struct client {
39	char mac[6];
40	int seq;
41
42	struct client *next;
43};
44
45struct 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
76void 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
90void 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
103void 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
117int 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
151void 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
185void 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
207void 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
233void 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
260void 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
283void 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
319void 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
350void 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
380void 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
396void 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
404void 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
410void 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
435int 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
445void 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
463void 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
493void 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
546void 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
564struct 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
578void 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
593int 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
640void 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
651void 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
704void 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
768int 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
787void 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
845int 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