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