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$
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
40struct client {
41	char mac[6];
42	int seq;
43
44	struct client *next;
45};
46
47struct 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
78void 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
92void 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
105void 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
119int 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
153void 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
187void 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
209void 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
235void 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
262void 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
285void 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
321void 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
352void 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
382void 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
398void 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
406void 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
412void 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
437int 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
447void 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
465void 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
495void 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_PROTECTED) {
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
548void 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
566struct 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
580void 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
595int 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
642void 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
653void 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
706void 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_PROTECTED;
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
770int 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
789void 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
847int 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