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