xref: /freebsd-src/tools/tools/net80211/w00t/ap/ap.c (revision b3e7694832e81d7a904a10f525f8797b753bf0d3)
12137fdb5SSam Leffler /*-
22137fdb5SSam Leffler  * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
32137fdb5SSam Leffler  * All rights reserved.
42137fdb5SSam Leffler  *
52137fdb5SSam Leffler  * Redistribution and use in source and binary forms, with or without
62137fdb5SSam Leffler  * modification, are permitted provided that the following conditions
72137fdb5SSam Leffler  * are met:
82137fdb5SSam Leffler  * 1. Redistributions of source code must retain the above copyright
92137fdb5SSam Leffler  *    notice, this list of conditions and the following disclaimer.
102137fdb5SSam Leffler  * 2. Redistributions in binary form must reproduce the above copyright
112137fdb5SSam Leffler  *    notice, this list of conditions and the following disclaimer in the
122137fdb5SSam Leffler  *    documentation and/or other materials provided with the distribution.
132137fdb5SSam Leffler  *
142137fdb5SSam Leffler  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
152137fdb5SSam Leffler  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
162137fdb5SSam Leffler  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
172137fdb5SSam Leffler  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
182137fdb5SSam Leffler  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
192137fdb5SSam Leffler  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
202137fdb5SSam Leffler  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
212137fdb5SSam Leffler  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
222137fdb5SSam Leffler  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
232137fdb5SSam Leffler  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
242137fdb5SSam Leffler  * SUCH DAMAGE.
252137fdb5SSam Leffler  */
262137fdb5SSam Leffler #include <sys/types.h>
272137fdb5SSam Leffler #include <sys/select.h>
282137fdb5SSam Leffler #include <sys/time.h>
292137fdb5SSam Leffler #include <sys/endian.h>
302137fdb5SSam Leffler #include <stdio.h>
312137fdb5SSam Leffler #include <stdlib.h>
322137fdb5SSam Leffler #include <string.h>
332137fdb5SSam Leffler #include <unistd.h>
342137fdb5SSam Leffler #include <err.h>
352137fdb5SSam Leffler #include <assert.h>
362137fdb5SSam Leffler #include "w00t.h"
372137fdb5SSam Leffler 
382137fdb5SSam Leffler struct client {
392137fdb5SSam Leffler 	char mac[6];
402137fdb5SSam Leffler 	int seq;
412137fdb5SSam Leffler 
422137fdb5SSam Leffler 	struct client *next;
432137fdb5SSam Leffler };
442137fdb5SSam Leffler 
452137fdb5SSam Leffler struct params {
462137fdb5SSam Leffler 	/* fds */
472137fdb5SSam Leffler 	int tx;
482137fdb5SSam Leffler 	int rx;
492137fdb5SSam Leffler 	int tap;
502137fdb5SSam Leffler 
512137fdb5SSam Leffler 	/* ap params */
522137fdb5SSam Leffler 	char mac[6];
532137fdb5SSam Leffler 	char ssid[256];
542137fdb5SSam Leffler 	int chan;
552137fdb5SSam Leffler 
562137fdb5SSam Leffler 	/* beacon */
572137fdb5SSam Leffler 	int bint;
582137fdb5SSam Leffler 	struct timeval blast;
592137fdb5SSam Leffler 
602137fdb5SSam Leffler 	int seq;
612137fdb5SSam Leffler 
622137fdb5SSam Leffler 	/* wep */
632137fdb5SSam Leffler 	int wep_len;
642137fdb5SSam Leffler 	char wep_key[13];
652137fdb5SSam Leffler 	int wep_iv;
662137fdb5SSam Leffler 
672137fdb5SSam Leffler 	struct client *clients;
682137fdb5SSam Leffler 
692137fdb5SSam Leffler 	/* lame window */
702137fdb5SSam Leffler 	char packet[4096];
712137fdb5SSam Leffler 	int packet_len;
722137fdb5SSam Leffler 	int packet_try;
732137fdb5SSam Leffler 	struct timeval plast;
742137fdb5SSam Leffler };
752137fdb5SSam Leffler 
usage(char * name)762137fdb5SSam Leffler void usage(char *name)
772137fdb5SSam Leffler {
782137fdb5SSam Leffler 	printf("Usage: %s <opts>\n"
792137fdb5SSam Leffler 	       "-h\thelp\n"
802137fdb5SSam Leffler 	       "-i\t<iface>\n"
812137fdb5SSam Leffler 	       "-s\t<ssid>\n"
822137fdb5SSam Leffler 	       "-m\t<mac>\n"
832137fdb5SSam Leffler 	       "-w\t<wep key>\n"
842137fdb5SSam Leffler 	       "-c\t<chan>\n"
852137fdb5SSam Leffler 	       "-t\t<tap>\n"
862137fdb5SSam Leffler 	       , name);
872137fdb5SSam Leffler 	exit(0);
882137fdb5SSam Leffler }
892137fdb5SSam Leffler 
fill_basic(struct ieee80211_frame * wh,struct params * p)902137fdb5SSam Leffler void fill_basic(struct ieee80211_frame *wh, struct params *p)
912137fdb5SSam Leffler {
922137fdb5SSam Leffler         short *seq;
932137fdb5SSam Leffler 
942137fdb5SSam Leffler         wh->i_dur[0] = 0x69;
952137fdb5SSam Leffler         wh->i_dur[1] = 0x00;
962137fdb5SSam Leffler 
972137fdb5SSam Leffler         memcpy(wh->i_addr2, p->mac, 6);
982137fdb5SSam Leffler 
992137fdb5SSam Leffler         seq = (short*)wh->i_seq;
1002137fdb5SSam Leffler         *seq = seqfn(p->seq, 0);
1012137fdb5SSam Leffler }
1022137fdb5SSam Leffler 
send_frame(struct params * p,void * buf,int len)1032137fdb5SSam Leffler void send_frame(struct params *p, void *buf, int len)
1042137fdb5SSam Leffler {
1052137fdb5SSam Leffler         int rc;
1062137fdb5SSam Leffler 
1072137fdb5SSam Leffler         rc = inject(p->tx, buf, len);
1082137fdb5SSam Leffler         if (rc == -1)
1092137fdb5SSam Leffler                 err(1, "inject()");
1102137fdb5SSam Leffler         if (rc != len) {
1112137fdb5SSam Leffler                 printf("injected %d/%d\n", rc, len);
1122137fdb5SSam Leffler                 exit(1);
1132137fdb5SSam Leffler         }
1142137fdb5SSam Leffler         p->seq++;
1152137fdb5SSam Leffler }
1162137fdb5SSam Leffler 
fill_beacon(struct params * p,struct ieee80211_frame * wh)1172137fdb5SSam Leffler int fill_beacon(struct params *p, struct ieee80211_frame *wh)
1182137fdb5SSam Leffler {
1192137fdb5SSam Leffler 	int len;
1202137fdb5SSam Leffler 	char *ptr;
1212137fdb5SSam Leffler 
1222137fdb5SSam Leffler 	ptr = (char*) (wh+1);
1232137fdb5SSam Leffler 	ptr += 8; /* timestamp */
1242137fdb5SSam Leffler 	ptr += 2; /* bint */
1252137fdb5SSam Leffler 	*ptr |= IEEE80211_CAPINFO_ESS;
1262137fdb5SSam Leffler 	ptr += 2; /* capa */
1272137fdb5SSam Leffler 
1282137fdb5SSam Leffler 	/* ssid */
1292137fdb5SSam Leffler 	len = strlen(p->ssid);
1302137fdb5SSam Leffler 	*ptr++ = 0;
1312137fdb5SSam Leffler 	*ptr++ = len;
1322137fdb5SSam Leffler 	memcpy(ptr, p->ssid, len);
1332137fdb5SSam Leffler 	ptr += len;
1342137fdb5SSam Leffler 
1352137fdb5SSam Leffler 	/* rates */
1362137fdb5SSam Leffler         *ptr++ = 1;
1372137fdb5SSam Leffler         *ptr++ = 4;
1382137fdb5SSam Leffler         *ptr++ = 2 | 0x80;
1392137fdb5SSam Leffler         *ptr++ = 4 | 0x80;
1402137fdb5SSam Leffler         *ptr++ = 11;
1412137fdb5SSam Leffler         *ptr++ = 22;
1422137fdb5SSam Leffler 
1432137fdb5SSam Leffler 	/* ds param */
1442137fdb5SSam Leffler 	*ptr++ = 3;
1452137fdb5SSam Leffler 	*ptr++ = 1;
1462137fdb5SSam Leffler 	*ptr++ = p->chan;
1472137fdb5SSam Leffler 
1482137fdb5SSam Leffler 	return ptr - ((char*) wh);
1492137fdb5SSam Leffler }
1502137fdb5SSam Leffler 
send_beacon(struct params * p)1512137fdb5SSam Leffler void send_beacon(struct params *p)
1522137fdb5SSam Leffler {
1532137fdb5SSam Leffler 	char buf[4096];
1542137fdb5SSam Leffler 	struct ieee80211_frame *wh;
1552137fdb5SSam Leffler 	int len;
1562137fdb5SSam Leffler 	char *ptr;
1572137fdb5SSam Leffler 
1582137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
1592137fdb5SSam Leffler 
1602137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
1612137fdb5SSam Leffler 	fill_basic(wh, p);
1622137fdb5SSam Leffler 	memset(wh->i_addr1, 0xff, 6);
1632137fdb5SSam Leffler 	memcpy(wh->i_addr3, p->mac, 6);
1642137fdb5SSam Leffler 
1652137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
1662137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_BEACON;
1672137fdb5SSam Leffler 
1682137fdb5SSam Leffler 	len = fill_beacon(p, wh);
1692137fdb5SSam Leffler 
1702137fdb5SSam Leffler 	/* TIM */
1712137fdb5SSam Leffler 	ptr = (char*)wh + len;
1722137fdb5SSam Leffler 	*ptr++ = 5;
1732137fdb5SSam Leffler 	*ptr++ = 4;
1742137fdb5SSam Leffler 	len +=  2+4;
1752137fdb5SSam Leffler #if 0
1762137fdb5SSam Leffler 	printf("sending beacon\n");
1772137fdb5SSam Leffler #endif
1782137fdb5SSam Leffler 	send_frame(p, wh, len);
1792137fdb5SSam Leffler 
1802137fdb5SSam Leffler 	if (gettimeofday(&p->blast, NULL) == -1)
1812137fdb5SSam Leffler 		err(1, "gettimeofday()");
1822137fdb5SSam Leffler }
1832137fdb5SSam Leffler 
1842137fdb5SSam Leffler 
send_pres(struct params * p,char * mac)1852137fdb5SSam Leffler void send_pres(struct params *p, char *mac)
1862137fdb5SSam Leffler {
1872137fdb5SSam Leffler 	char buf[4096];
1882137fdb5SSam Leffler 	struct ieee80211_frame *wh;
1892137fdb5SSam Leffler 	int len;
1902137fdb5SSam Leffler 
1912137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
1922137fdb5SSam Leffler 
1932137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
1942137fdb5SSam Leffler 	fill_basic(wh, p);
1952137fdb5SSam Leffler 	memcpy(wh->i_addr1, mac, 6);
1962137fdb5SSam Leffler 	memcpy(wh->i_addr3, p->mac, 6);
1972137fdb5SSam Leffler 
1982137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
1992137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PROBE_RESP;
2002137fdb5SSam Leffler 
2012137fdb5SSam Leffler 	len = fill_beacon(p, wh);
2022137fdb5SSam Leffler 
2032137fdb5SSam Leffler 	printf("sending probe response\n");
2042137fdb5SSam Leffler 	send_frame(p, wh, len);
2052137fdb5SSam Leffler }
2062137fdb5SSam Leffler 
read_preq(struct params * p,struct ieee80211_frame * wh,int len)2072137fdb5SSam Leffler void read_preq(struct params *p, struct ieee80211_frame *wh, int len)
2082137fdb5SSam Leffler {
2092137fdb5SSam Leffler 	unsigned char *ptr;
2102137fdb5SSam Leffler 	unsigned char *end;
2112137fdb5SSam Leffler 	unsigned char macs[6*3];
2122137fdb5SSam Leffler 
2132137fdb5SSam Leffler 	ptr = (unsigned char*) (wh+1);
2142137fdb5SSam Leffler 
2152137fdb5SSam Leffler 	/* ssid */
2162137fdb5SSam Leffler 	if (*ptr != 0) {
2172137fdb5SSam Leffler 		printf("weird pr %x\n", *ptr);
2182137fdb5SSam Leffler 		return;
2192137fdb5SSam Leffler 	}
2202137fdb5SSam Leffler 	ptr++;
2212137fdb5SSam Leffler 
2222137fdb5SSam Leffler 	end = ptr + (*ptr) + 1;
2232137fdb5SSam Leffler 	*end = 0;
2242137fdb5SSam Leffler 	ptr++;
2252137fdb5SSam Leffler 
2262137fdb5SSam Leffler 	mac2str(macs, wh->i_addr2);
2272137fdb5SSam Leffler 	printf("Probe request for [%s] from %s\n", ptr, macs);
2282137fdb5SSam Leffler 
2292137fdb5SSam Leffler 	if ((strcmp(ptr, "") == 0) || (strcmp(ptr, p->ssid) == 0))
2302137fdb5SSam Leffler 		send_pres(p, wh->i_addr2);
2312137fdb5SSam Leffler }
2322137fdb5SSam Leffler 
send_auth(struct params * p,char * mac)2332137fdb5SSam Leffler void send_auth(struct params* p, char *mac)
2342137fdb5SSam Leffler {
2352137fdb5SSam Leffler 	char buf[4096];
2362137fdb5SSam Leffler 	struct ieee80211_frame *wh;
2372137fdb5SSam Leffler 	unsigned short *ptr;
2382137fdb5SSam Leffler 	int len;
2392137fdb5SSam Leffler 
2402137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
2412137fdb5SSam Leffler 
2422137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
2432137fdb5SSam Leffler 	fill_basic(wh, p);
2442137fdb5SSam Leffler 	memcpy(wh->i_addr1, mac, 6);
2452137fdb5SSam Leffler 	memcpy(wh->i_addr3, p->mac, 6);
2462137fdb5SSam Leffler 
2472137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
2482137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_AUTH;
2492137fdb5SSam Leffler 
2502137fdb5SSam Leffler 	ptr = (unsigned short*) (wh+1);
2512137fdb5SSam Leffler 	*ptr++ = htole16(0);
2522137fdb5SSam Leffler 	*ptr++ = htole16(2);
2532137fdb5SSam Leffler 	*ptr++ = htole16(0);
2542137fdb5SSam Leffler 
2552137fdb5SSam Leffler 	len = ((char*)ptr) - ((char*) wh);
2562137fdb5SSam Leffler 	printf("sending auth\n");
2572137fdb5SSam Leffler 	send_frame(p, wh, len);
2582137fdb5SSam Leffler }
2592137fdb5SSam Leffler 
read_auth(struct params * p,struct ieee80211_frame * wh,int len)2602137fdb5SSam Leffler void read_auth(struct params *p, struct ieee80211_frame *wh, int len)
2612137fdb5SSam Leffler {
2622137fdb5SSam Leffler 	unsigned short *ptr;
2632137fdb5SSam Leffler 	char mac[6*3];
2642137fdb5SSam Leffler 
2652137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) != 0)
2662137fdb5SSam Leffler 		return;
2672137fdb5SSam Leffler 
2682137fdb5SSam Leffler 	ptr = (unsigned short*) (wh+1);
2692137fdb5SSam Leffler 	if (le16toh(*ptr) != 0) {
2702137fdb5SSam Leffler 		printf("Unknown auth algo %d\n", le16toh(*ptr));
2712137fdb5SSam Leffler 		return;
2722137fdb5SSam Leffler 	}
2732137fdb5SSam Leffler 	ptr++;
2742137fdb5SSam Leffler 	if (le16toh(*ptr) == 1) {
2752137fdb5SSam Leffler 		mac2str(mac, wh->i_addr2);
2762137fdb5SSam Leffler 		printf("Got auth from %s\n", mac);
2772137fdb5SSam Leffler 		send_auth(p, wh->i_addr2);
2782137fdb5SSam Leffler 	} else {
2792137fdb5SSam Leffler 		printf("Weird seq in auth %d\n", le16toh(*ptr));
2802137fdb5SSam Leffler 	}
2812137fdb5SSam Leffler }
2822137fdb5SSam Leffler 
send_assoc(struct params * p,char * mac)2832137fdb5SSam Leffler void send_assoc(struct params *p, char *mac)
2842137fdb5SSam Leffler {
2852137fdb5SSam Leffler 	char buf[4096];
2862137fdb5SSam Leffler 	struct ieee80211_frame *wh;
2872137fdb5SSam Leffler 	char *ptr;
2882137fdb5SSam Leffler 	int len;
2892137fdb5SSam Leffler 
2902137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
2912137fdb5SSam Leffler 
2922137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
2932137fdb5SSam Leffler 	fill_basic(wh, p);
2942137fdb5SSam Leffler 	memcpy(wh->i_addr1, mac, 6);
2952137fdb5SSam Leffler 	memcpy(wh->i_addr3, p->mac, 6);
2962137fdb5SSam Leffler 
2972137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
2982137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
2992137fdb5SSam Leffler 
3002137fdb5SSam Leffler 	ptr = (char*) (wh+1);
3012137fdb5SSam Leffler 	*ptr |= IEEE80211_CAPINFO_ESS;
3022137fdb5SSam Leffler 	ptr += 2; /* cap */
3032137fdb5SSam Leffler 	ptr += 2; /* status */
3042137fdb5SSam Leffler 	ptr += 2; /* aid */
3052137fdb5SSam Leffler 
3062137fdb5SSam Leffler 	/* rates */
3072137fdb5SSam Leffler         *ptr++ = 1;
3082137fdb5SSam Leffler         *ptr++ = 4;
3092137fdb5SSam Leffler         *ptr++ = 2 | 0x80;
3102137fdb5SSam Leffler         *ptr++ = 4 | 0x80;
3112137fdb5SSam Leffler         *ptr++ = 11;
3122137fdb5SSam Leffler         *ptr++ = 22;
3132137fdb5SSam Leffler 
3142137fdb5SSam Leffler 	len = ptr - ((char*) wh);
3152137fdb5SSam Leffler 	printf("sending assoc response\n");
3162137fdb5SSam Leffler 	send_frame(p, wh, len);
3172137fdb5SSam Leffler }
3182137fdb5SSam Leffler 
read_assoc(struct params * p,struct ieee80211_frame * wh,int len)3192137fdb5SSam Leffler void read_assoc(struct params *p, struct ieee80211_frame *wh, int len)
3202137fdb5SSam Leffler {
3212137fdb5SSam Leffler 	unsigned char *ptr;
3222137fdb5SSam Leffler 	unsigned char *end;
3232137fdb5SSam Leffler 	unsigned char macs[6*3];
3242137fdb5SSam Leffler 
3252137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) != 0)
3262137fdb5SSam Leffler 		return;
3272137fdb5SSam Leffler 
3282137fdb5SSam Leffler 	ptr = (unsigned char*) (wh+1);
3292137fdb5SSam Leffler 	ptr += 2; /* capa */
3302137fdb5SSam Leffler 	ptr += 2; /* list interval */
3312137fdb5SSam Leffler 
3322137fdb5SSam Leffler 	/* ssid */
3332137fdb5SSam Leffler 	if (*ptr != 0) {
3342137fdb5SSam Leffler 		printf("weird pr %x\n", *ptr);
3352137fdb5SSam Leffler 		return;
3362137fdb5SSam Leffler 	}
3372137fdb5SSam Leffler 	ptr++;
3382137fdb5SSam Leffler 
3392137fdb5SSam Leffler 	end = ptr + (*ptr) + 1;
3402137fdb5SSam Leffler 	*end = 0;
3412137fdb5SSam Leffler 	ptr++;
3422137fdb5SSam Leffler 
3432137fdb5SSam Leffler 	mac2str(macs, wh->i_addr2);
3442137fdb5SSam Leffler 	printf("Assoc request for [%s] from %s\n", ptr, macs);
3452137fdb5SSam Leffler 
3462137fdb5SSam Leffler 	if (strcmp(ptr, p->ssid) == 0)
3472137fdb5SSam Leffler 		send_assoc(p, wh->i_addr2);
3482137fdb5SSam Leffler }
3492137fdb5SSam Leffler 
read_mgt(struct params * p,struct ieee80211_frame * wh,int len)3502137fdb5SSam Leffler void read_mgt(struct params *p, struct ieee80211_frame *wh, int len)
3512137fdb5SSam Leffler {
3522137fdb5SSam Leffler 	switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
3532137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
3542137fdb5SSam Leffler 		read_preq(p, wh, len);
3552137fdb5SSam Leffler 		break;
3562137fdb5SSam Leffler 
3572137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
3582137fdb5SSam Leffler 		break;
3592137fdb5SSam Leffler 
3602137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_AUTH:
3612137fdb5SSam Leffler 		read_auth(p, wh, len);
3622137fdb5SSam Leffler 		break;
3632137fdb5SSam Leffler 
3642137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
3652137fdb5SSam Leffler 		read_assoc(p, wh, len);
3662137fdb5SSam Leffler 		break;
3672137fdb5SSam Leffler 
3682137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
3692137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_BEACON:
3702137fdb5SSam Leffler 		break;
3712137fdb5SSam Leffler 
3722137fdb5SSam Leffler 	default:
3732137fdb5SSam Leffler 		printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
3742137fdb5SSam Leffler 				   IEEE80211_FC0_SUBTYPE_SHIFT);
3752137fdb5SSam Leffler 		abort();
3762137fdb5SSam Leffler 		break;
3772137fdb5SSam Leffler 	}
3782137fdb5SSam Leffler }
3792137fdb5SSam Leffler 
send_cts(struct params * p,char * mac)3802137fdb5SSam Leffler void send_cts(struct params *p, char *mac)
3812137fdb5SSam Leffler {
3822137fdb5SSam Leffler 	char buf[64];
3832137fdb5SSam Leffler 	struct ieee80211_frame *wh;
3842137fdb5SSam Leffler 
3852137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
3862137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
3872137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_CTL;
3882137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_CTS;
3892137fdb5SSam Leffler 	wh->i_dur[0] = 0x69;
390*1983a232SEitan Adler 	wh->i_dur[1] = 0x00;
3912137fdb5SSam Leffler 	memcpy(wh->i_addr1, mac, 6);
3922137fdb5SSam Leffler 
3932137fdb5SSam Leffler 	send_frame(p, wh, 10);
3942137fdb5SSam Leffler }
3952137fdb5SSam Leffler 
read_rts(struct params * p,struct ieee80211_frame * wh,int len)3962137fdb5SSam Leffler void read_rts(struct params *p, struct ieee80211_frame *wh, int len)
3972137fdb5SSam Leffler {
3982137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) != 0)
3992137fdb5SSam Leffler 		return;
4002137fdb5SSam Leffler 
4012137fdb5SSam Leffler 	send_cts(p, wh->i_addr2);
4022137fdb5SSam Leffler }
4032137fdb5SSam Leffler 
read_ack(struct params * p,struct ieee80211_frame * wh,int len)4042137fdb5SSam Leffler void read_ack(struct params *p, struct ieee80211_frame *wh, int len)
4052137fdb5SSam Leffler {
4062137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) == 0)
4072137fdb5SSam Leffler 		p->packet_try = 0;
4082137fdb5SSam Leffler }
4092137fdb5SSam Leffler 
read_ctl(struct params * p,struct ieee80211_frame * wh,int len)4102137fdb5SSam Leffler void read_ctl(struct params *p, struct ieee80211_frame *wh, int len)
4112137fdb5SSam Leffler {
4122137fdb5SSam Leffler 	switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
4132137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_RTS:
4142137fdb5SSam Leffler 		read_rts(p, wh, len);
4152137fdb5SSam Leffler 		break;
4162137fdb5SSam Leffler 
4172137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_ACK:
4182137fdb5SSam Leffler 		read_ack(p, wh, len);
4192137fdb5SSam Leffler 		break;
4202137fdb5SSam Leffler 
4212137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_CTS:
4222137fdb5SSam Leffler 		break;
4232137fdb5SSam Leffler 
4242137fdb5SSam Leffler 	default:
4252137fdb5SSam Leffler 		printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
4262137fdb5SSam Leffler 		       IEEE80211_FC0_SUBTYPE_SHIFT);
4272137fdb5SSam Leffler 		abort();
4282137fdb5SSam Leffler 		break;
4292137fdb5SSam Leffler 	}
4302137fdb5SSam Leffler #if 0
4312137fdb5SSam Leffler 	printf("ctl\n");
4322137fdb5SSam Leffler #endif
4332137fdb5SSam Leffler }
4342137fdb5SSam Leffler 
broadcast(struct ieee80211_frame * wh)4352137fdb5SSam Leffler int broadcast(struct ieee80211_frame *wh)
4362137fdb5SSam Leffler {
4372137fdb5SSam Leffler 	/* XXX multicast */
4382137fdb5SSam Leffler 
4392137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0)
4402137fdb5SSam Leffler 		return 1;
4412137fdb5SSam Leffler 
4422137fdb5SSam Leffler 	return 0;
4432137fdb5SSam Leffler }
4442137fdb5SSam Leffler 
enque(struct params * p,struct ieee80211_frame * wh,int len)4452137fdb5SSam Leffler void enque(struct params *p, struct ieee80211_frame *wh, int len)
4462137fdb5SSam Leffler {
4472137fdb5SSam Leffler 	if (broadcast(wh))
4482137fdb5SSam Leffler 		return;
4492137fdb5SSam Leffler 
4502137fdb5SSam Leffler 	assert(sizeof(p->packet) >= len);
4512137fdb5SSam Leffler 
4522137fdb5SSam Leffler 	memcpy(p->packet, wh, len);
4532137fdb5SSam Leffler 	p->packet_len = len;
4542137fdb5SSam Leffler 	p->packet_try = 1;
4552137fdb5SSam Leffler 
4562137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) p->packet;
4572137fdb5SSam Leffler 	wh->i_fc[1] |= IEEE80211_FC1_RETRY;
4582137fdb5SSam Leffler 
4592137fdb5SSam Leffler 	if (gettimeofday(&p->plast, NULL) == -1)
4602137fdb5SSam Leffler 		err(1, "gettimeofday()");
4612137fdb5SSam Leffler }
4622137fdb5SSam Leffler 
relay_data(struct params * p,struct ieee80211_frame * wh,int len)4632137fdb5SSam Leffler void relay_data(struct params *p, struct ieee80211_frame *wh, int len)
4642137fdb5SSam Leffler {
4652137fdb5SSam Leffler 	char seq[2];
4662137fdb5SSam Leffler 	char fc[2];
4672137fdb5SSam Leffler 	unsigned short *ps;
4682137fdb5SSam Leffler 
4692137fdb5SSam Leffler 	/* copy crap */
4702137fdb5SSam Leffler 	memcpy(fc, wh->i_fc, 2);
4712137fdb5SSam Leffler 	memcpy(seq, wh->i_seq, 2);
4722137fdb5SSam Leffler 
4732137fdb5SSam Leffler 	/* relay frame */
4742137fdb5SSam Leffler 	wh->i_fc[1] &= ~(IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_RETRY);
4752137fdb5SSam Leffler 	wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
4762137fdb5SSam Leffler 	memcpy(wh->i_addr1, wh->i_addr3, sizeof(wh->i_addr1));
4772137fdb5SSam Leffler 	memcpy(wh->i_addr3, wh->i_addr2, sizeof(wh->i_addr3));
4782137fdb5SSam Leffler 	memcpy(wh->i_addr2, p->mac, sizeof(wh->i_addr2));
4792137fdb5SSam Leffler         ps = (unsigned short*)wh->i_seq;
4802137fdb5SSam Leffler         *ps = seqfn(p->seq, 0);
4812137fdb5SSam Leffler 
4822137fdb5SSam Leffler 	send_frame(p, wh, len);
4832137fdb5SSam Leffler 	enque(p, wh, len);
4842137fdb5SSam Leffler 
4852137fdb5SSam Leffler 	/* restore */
4862137fdb5SSam Leffler 	memcpy(wh->i_fc, fc, sizeof(fc));
4872137fdb5SSam Leffler 	memcpy(wh->i_addr2, wh->i_addr3, sizeof(wh->i_addr2));
4882137fdb5SSam Leffler 	memcpy(wh->i_addr3, wh->i_addr1, sizeof(wh->i_addr2));
4892137fdb5SSam Leffler 	memcpy(wh->i_addr1, p->mac, sizeof(wh->i_addr1));
4902137fdb5SSam Leffler 	memcpy(wh->i_seq, seq, sizeof(seq));
4912137fdb5SSam Leffler }
4922137fdb5SSam Leffler 
read_real_data(struct params * p,struct ieee80211_frame * wh,int len)4932137fdb5SSam Leffler void read_real_data(struct params *p, struct ieee80211_frame *wh, int len)
4942137fdb5SSam Leffler {
4952137fdb5SSam Leffler 	char dst[6];
4962137fdb5SSam Leffler 	int rc;
4972137fdb5SSam Leffler 	char *ptr = (char*) (wh+1);
4982137fdb5SSam Leffler 
4992137fdb5SSam Leffler 	/* stuff not for this net */
5002137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) != 0)
5012137fdb5SSam Leffler 		return;
5022137fdb5SSam Leffler 
5032137fdb5SSam Leffler 	/* relay data */
5042137fdb5SSam Leffler 	if (memcmp(wh->i_addr3, p->mac, 6) != 0)
5052137fdb5SSam Leffler 		relay_data(p, wh, len);
5062137fdb5SSam Leffler 
5072137fdb5SSam Leffler 	memcpy(dst, wh->i_addr3, 6);
5082137fdb5SSam Leffler 
5092137fdb5SSam Leffler 
5105945b5f5SKevin Lo 	if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
5112137fdb5SSam Leffler 		if (!p->wep_len) {
5122137fdb5SSam Leffler 			printf("Got wep but i aint wep\n");
5132137fdb5SSam Leffler 			return;
5142137fdb5SSam Leffler 		}
5152137fdb5SSam Leffler 
5162137fdb5SSam Leffler 		if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
5172137fdb5SSam Leffler 			printf("Can't decrypt\n");
5182137fdb5SSam Leffler 			return;
5192137fdb5SSam Leffler 		}
5202137fdb5SSam Leffler 
5212137fdb5SSam Leffler 		ptr += 4;
5222137fdb5SSam Leffler 		len -= 8;
5232137fdb5SSam Leffler 	}
5242137fdb5SSam Leffler 
5252137fdb5SSam Leffler 	/* ether header */
5262137fdb5SSam Leffler 	ptr += 8 - 2;
5272137fdb5SSam Leffler 	ptr -= 6;
5282137fdb5SSam Leffler 	memcpy(ptr, wh->i_addr2, 6);
5292137fdb5SSam Leffler 	ptr -= 6;
5302137fdb5SSam Leffler 	memcpy(ptr, dst, 6);
5312137fdb5SSam Leffler 
5322137fdb5SSam Leffler 	len -= sizeof(*wh);
5332137fdb5SSam Leffler 	len -= 8;
5342137fdb5SSam Leffler 	len += 14;
5352137fdb5SSam Leffler 
5362137fdb5SSam Leffler 	/* send to tap */
5372137fdb5SSam Leffler 	rc = write(p->tap, ptr, len);
5382137fdb5SSam Leffler 	if (rc == -1)
5392137fdb5SSam Leffler 		err(1, "write()");
5402137fdb5SSam Leffler 	if (rc != len) {
5412137fdb5SSam Leffler 		printf("Wrote %d/%d\n", rc, len);
5422137fdb5SSam Leffler 		exit(1);
5432137fdb5SSam Leffler 	}
5442137fdb5SSam Leffler }
5452137fdb5SSam Leffler 
read_data(struct params * p,struct ieee80211_frame * wh,int len)5462137fdb5SSam Leffler void read_data(struct params *p, struct ieee80211_frame *wh, int len)
5472137fdb5SSam Leffler {
5482137fdb5SSam Leffler 	switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
5492137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_DATA:
5502137fdb5SSam Leffler 		read_real_data(p, wh, len);
5512137fdb5SSam Leffler 		break;
5522137fdb5SSam Leffler 
5532137fdb5SSam Leffler 	case IEEE80211_FC0_SUBTYPE_NODATA:
5542137fdb5SSam Leffler 		break;
5552137fdb5SSam Leffler 
5562137fdb5SSam Leffler 	default:
5572137fdb5SSam Leffler 		printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
5582137fdb5SSam Leffler 				   IEEE80211_FC0_SUBTYPE_SHIFT);
5592137fdb5SSam Leffler 		abort();
5602137fdb5SSam Leffler 		break;
5612137fdb5SSam Leffler 	}
5622137fdb5SSam Leffler }
5632137fdb5SSam Leffler 
client_find(struct params * p,char * mac)5642137fdb5SSam Leffler struct client* client_find(struct params *p, char *mac)
5652137fdb5SSam Leffler {
5662137fdb5SSam Leffler 	struct client* c = p->clients;
5672137fdb5SSam Leffler 
5682137fdb5SSam Leffler 	while (c) {
5692137fdb5SSam Leffler 		if (memcmp(c->mac, mac, 6) == 0)
5702137fdb5SSam Leffler 			return c;
5712137fdb5SSam Leffler 
5722137fdb5SSam Leffler 		c = c->next;
5732137fdb5SSam Leffler 	}
5742137fdb5SSam Leffler 
5752137fdb5SSam Leffler 	return NULL;
5762137fdb5SSam Leffler }
5772137fdb5SSam Leffler 
client_insert(struct params * p,struct client * c)5782137fdb5SSam Leffler void client_insert(struct params *p, struct client *c)
5792137fdb5SSam Leffler {
5802137fdb5SSam Leffler #if 1
5812137fdb5SSam Leffler 	do {
5822137fdb5SSam Leffler 		char mac[6*3];
5832137fdb5SSam Leffler 
5842137fdb5SSam Leffler 		mac2str(mac, c->mac);
5852137fdb5SSam Leffler 		printf("Adding client %s\n", mac);
5862137fdb5SSam Leffler 	} while(0);
5872137fdb5SSam Leffler #endif
5882137fdb5SSam Leffler 
5892137fdb5SSam Leffler 	c->next = p->clients;
5902137fdb5SSam Leffler 	p->clients = c;
5912137fdb5SSam Leffler }
5922137fdb5SSam Leffler 
duplicate(struct params * p,struct ieee80211_frame * wh,int rc)5932137fdb5SSam Leffler int duplicate(struct params *p, struct ieee80211_frame *wh, int rc)
5942137fdb5SSam Leffler {
5952137fdb5SSam Leffler 	struct client *c;
5962137fdb5SSam Leffler 	int s;
5972137fdb5SSam Leffler 
5982137fdb5SSam Leffler 	if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
5992137fdb5SSam Leffler 			IEEE80211_FC0_SUBTYPE_DATA))
6002137fdb5SSam Leffler 		return 0;
6012137fdb5SSam Leffler 
6022137fdb5SSam Leffler 	s = seqno(wh);
6032137fdb5SSam Leffler 
6042137fdb5SSam Leffler 	c = client_find(p, wh->i_addr2);
6052137fdb5SSam Leffler 	if (!c) {
6062137fdb5SSam Leffler 		c = malloc(sizeof(*c));
6072137fdb5SSam Leffler 		if (!c)
6082137fdb5SSam Leffler 			err(1, "malloc()");
6092137fdb5SSam Leffler 
6102137fdb5SSam Leffler 		memset(c, 0, sizeof(*c));
6112137fdb5SSam Leffler 		memcpy(c->mac, wh->i_addr2, 6);
6122137fdb5SSam Leffler 
6132137fdb5SSam Leffler 		c->seq = s-1;
6142137fdb5SSam Leffler 		client_insert(p, c);
6152137fdb5SSam Leffler 	}
6162137fdb5SSam Leffler 
6172137fdb5SSam Leffler 	if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
6182137fdb5SSam Leffler 		if ( (s <= c->seq) && ((c->seq - s ) < 5)) {
6192137fdb5SSam Leffler #if 0
6202137fdb5SSam Leffler 			printf("Dup seq %d prev %d\n",
6212137fdb5SSam Leffler 			       s, c->seq);
6222137fdb5SSam Leffler #endif
6232137fdb5SSam Leffler 			return 1;
6242137fdb5SSam Leffler 		}
6252137fdb5SSam Leffler 	}
6262137fdb5SSam Leffler 
6272137fdb5SSam Leffler #if 0
6282137fdb5SSam Leffler 	do {
6292137fdb5SSam Leffler 		char mac[3*6];
6302137fdb5SSam Leffler 
6312137fdb5SSam Leffler 		mac2str(mac, c->mac);
6322137fdb5SSam Leffler 		printf("%s seq %d prev %d\n", mac, s, c->seq);
6332137fdb5SSam Leffler 	} while (0);
6342137fdb5SSam Leffler #endif
6352137fdb5SSam Leffler 
6362137fdb5SSam Leffler 	c->seq = s;
6372137fdb5SSam Leffler 	return 0;
6382137fdb5SSam Leffler }
6392137fdb5SSam Leffler 
ack(struct params * p,struct ieee80211_frame * wh)6402137fdb5SSam Leffler void ack(struct params *p, struct ieee80211_frame *wh)
6412137fdb5SSam Leffler {
6422137fdb5SSam Leffler 	if (memcmp(wh->i_addr1, p->mac, 6) != 0)
6432137fdb5SSam Leffler 		return;
6442137fdb5SSam Leffler 
6452137fdb5SSam Leffler 	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
6462137fdb5SSam Leffler 		return;
6472137fdb5SSam Leffler 
6482137fdb5SSam Leffler 	send_ack(p->tx, wh->i_addr2);
6492137fdb5SSam Leffler }
6502137fdb5SSam Leffler 
read_wifi(struct params * p)6512137fdb5SSam Leffler void read_wifi(struct params *p)
6522137fdb5SSam Leffler {
6532137fdb5SSam Leffler 	char buf[4096];
6542137fdb5SSam Leffler 	int rc;
6552137fdb5SSam Leffler 	struct ieee80211_frame *wh;
6562137fdb5SSam Leffler 
6572137fdb5SSam Leffler 	rc = sniff(p->rx, buf, sizeof(buf));
6582137fdb5SSam Leffler 	if (rc == -1)
6592137fdb5SSam Leffler 		err(1, "sniff()");
6602137fdb5SSam Leffler 
6612137fdb5SSam Leffler 	wh = get_wifi(buf, &rc);
6622137fdb5SSam Leffler 	if (!wh)
6632137fdb5SSam Leffler 		return;
6642137fdb5SSam Leffler 
6652137fdb5SSam Leffler 	/* filter my own shit */
6662137fdb5SSam Leffler 	if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
6672137fdb5SSam Leffler 		/* XXX CTL frames */
6682137fdb5SSam Leffler 		if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
6692137fdb5SSam Leffler 		    IEEE80211_FC0_TYPE_CTL)
6702137fdb5SSam Leffler 			return;
6712137fdb5SSam Leffler 	}
6722137fdb5SSam Leffler 
6732137fdb5SSam Leffler #if 1
6742137fdb5SSam Leffler 	ack(p, wh);
6752137fdb5SSam Leffler #endif
6762137fdb5SSam Leffler 
6772137fdb5SSam Leffler 	if (duplicate(p, wh, rc)) {
6782137fdb5SSam Leffler #if 0
6792137fdb5SSam Leffler 		printf("Dup\n");
6802137fdb5SSam Leffler #endif
6812137fdb5SSam Leffler 		return;
6822137fdb5SSam Leffler 	}
6832137fdb5SSam Leffler 
6842137fdb5SSam Leffler 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
6852137fdb5SSam Leffler 	case IEEE80211_FC0_TYPE_MGT:
6862137fdb5SSam Leffler 		read_mgt(p, wh, rc);
6872137fdb5SSam Leffler 		break;
6882137fdb5SSam Leffler 
6892137fdb5SSam Leffler 	case IEEE80211_FC0_TYPE_CTL:
6902137fdb5SSam Leffler 		read_ctl(p, wh, rc);
6912137fdb5SSam Leffler 		break;
6922137fdb5SSam Leffler 
6932137fdb5SSam Leffler 	case IEEE80211_FC0_TYPE_DATA:
6942137fdb5SSam Leffler 		read_data(p, wh, rc);
6952137fdb5SSam Leffler 		break;
6962137fdb5SSam Leffler 
6972137fdb5SSam Leffler 	default:
6982137fdb5SSam Leffler 		printf("wtf\n");
6992137fdb5SSam Leffler 		abort();
7002137fdb5SSam Leffler 		break;
7012137fdb5SSam Leffler 	}
7022137fdb5SSam Leffler }
7032137fdb5SSam Leffler 
read_tap(struct params * p)7042137fdb5SSam Leffler void read_tap(struct params *p)
7052137fdb5SSam Leffler {
7062137fdb5SSam Leffler 	char buf[4096];
7072137fdb5SSam Leffler 	char *ptr;
7082137fdb5SSam Leffler 	int len = sizeof(buf);
7092137fdb5SSam Leffler 	int offset;
7102137fdb5SSam Leffler 	char src[6], dst[6];
7112137fdb5SSam Leffler 	struct ieee80211_frame *wh;
7122137fdb5SSam Leffler 	int rd;
7132137fdb5SSam Leffler 
7142137fdb5SSam Leffler 	ptr = buf;
7152137fdb5SSam Leffler 	offset = sizeof(struct ieee80211_frame) + 8 - 14;
7162137fdb5SSam Leffler 	if (p->wep_len)
7172137fdb5SSam Leffler 		offset += 4;
7182137fdb5SSam Leffler 
7192137fdb5SSam Leffler 	ptr += offset;
7202137fdb5SSam Leffler 	len -= offset;
7212137fdb5SSam Leffler 
7222137fdb5SSam Leffler 	/* read packet */
7232137fdb5SSam Leffler 	memset(buf, 0, sizeof(buf));
7242137fdb5SSam Leffler 	rd = read(p->tap, ptr, len);
7252137fdb5SSam Leffler 	if (rd == -1)
7262137fdb5SSam Leffler 		err(1, "read()");
7272137fdb5SSam Leffler 
7282137fdb5SSam Leffler 	/* 802.11 header */
7292137fdb5SSam Leffler 	wh = (struct ieee80211_frame*) buf;
7302137fdb5SSam Leffler 	memcpy(dst, ptr, sizeof(dst));
7312137fdb5SSam Leffler 	memcpy(src, ptr+6, sizeof(src));
7322137fdb5SSam Leffler 	fill_basic(wh, p);
7332137fdb5SSam Leffler 	memcpy(wh->i_addr3, src, sizeof(wh->i_addr3));
7342137fdb5SSam Leffler 	memcpy(wh->i_addr1, dst, sizeof(wh->i_addr1));
7352137fdb5SSam Leffler 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
7362137fdb5SSam Leffler 	wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
7372137fdb5SSam Leffler 	if (p->wep_len)
7385945b5f5SKevin Lo 		wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
7392137fdb5SSam Leffler 
7402137fdb5SSam Leffler 	/* LLC & SNAP */
7412137fdb5SSam Leffler 	ptr = (char*) (wh+1);
7422137fdb5SSam Leffler 	if (p->wep_len)
7432137fdb5SSam Leffler 		ptr += 4;
7442137fdb5SSam Leffler 	*ptr++ = 0xAA;
7452137fdb5SSam Leffler 	*ptr++ = 0xAA;
7462137fdb5SSam Leffler 	*ptr++ = 0x03;
7472137fdb5SSam Leffler 	*ptr++ = 0x00;
7482137fdb5SSam Leffler 	*ptr++ = 0x00;
7492137fdb5SSam Leffler 	*ptr++ = 0x00;
7502137fdb5SSam Leffler 	/* ether type overlaps w00t */
7512137fdb5SSam Leffler 
7522137fdb5SSam Leffler 	rd += offset;
7532137fdb5SSam Leffler 
7542137fdb5SSam Leffler 	/* WEP */
7552137fdb5SSam Leffler 	if (p->wep_len) {
7562137fdb5SSam Leffler 		ptr = (char*) (wh+1);
7572137fdb5SSam Leffler 		memcpy(ptr, &p->wep_iv, 3);
7582137fdb5SSam Leffler 		ptr[3] = 0;
7592137fdb5SSam Leffler 		p->wep_iv++;
7602137fdb5SSam Leffler 
7612137fdb5SSam Leffler 		wep_encrypt(wh, rd, p->wep_key, p->wep_len);
7622137fdb5SSam Leffler 		rd += 4; /* ICV */
7632137fdb5SSam Leffler 	}
7642137fdb5SSam Leffler 
7652137fdb5SSam Leffler 	send_frame(p, wh, rd);
7662137fdb5SSam Leffler }
7672137fdb5SSam Leffler 
retransmit(struct params * p)7682137fdb5SSam Leffler int retransmit(struct params *p)
7692137fdb5SSam Leffler {
7702137fdb5SSam Leffler #if 0
7712137fdb5SSam Leffler 	printf("RETRANS %d\n", p->packet_try);
7722137fdb5SSam Leffler #endif
7732137fdb5SSam Leffler 
7742137fdb5SSam Leffler 	send_frame(p, p->packet, p->packet_len);
7752137fdb5SSam Leffler 	p->packet_try++;
7762137fdb5SSam Leffler 
7772137fdb5SSam Leffler 	if (p->packet_try > 3)
7782137fdb5SSam Leffler 		p->packet_try = 0;
7792137fdb5SSam Leffler 	else {
7802137fdb5SSam Leffler 		if (gettimeofday(&p->plast, NULL) == -1)
7812137fdb5SSam Leffler 			err(1, "gettimeofday()");
7822137fdb5SSam Leffler 	}
7832137fdb5SSam Leffler 
7842137fdb5SSam Leffler 	return p->packet_try;
7852137fdb5SSam Leffler }
7862137fdb5SSam Leffler 
next_event(struct params * p)7872137fdb5SSam Leffler void next_event(struct params *p)
7882137fdb5SSam Leffler {
7892137fdb5SSam Leffler 	struct timeval to, now;
7902137fdb5SSam Leffler 	int el;
7912137fdb5SSam Leffler 	int max;
7922137fdb5SSam Leffler 	fd_set fds;
7932137fdb5SSam Leffler 	int rtr = 3*1000;
7942137fdb5SSam Leffler 
7952137fdb5SSam Leffler 	/* figure out select timeout */
7962137fdb5SSam Leffler 	if (gettimeofday(&now, NULL) == -1)
7972137fdb5SSam Leffler 		err(1, "gettimeofday()");
7982137fdb5SSam Leffler 
7992137fdb5SSam Leffler 	/* check beacon timeout */
8002137fdb5SSam Leffler 	el = elapsed(&p->blast, &now);
8012137fdb5SSam Leffler 	if (el >= p->bint) {
8022137fdb5SSam Leffler 		send_beacon(p);
8032137fdb5SSam Leffler 		el = 0;
8042137fdb5SSam Leffler 	}
8052137fdb5SSam Leffler 	el = p->bint - el;
8062137fdb5SSam Leffler 	to.tv_sec = el/1000/1000;
8072137fdb5SSam Leffler 	to.tv_usec = el - to.tv_sec*1000*1000;
8082137fdb5SSam Leffler 
8092137fdb5SSam Leffler 	/* check tx timeout */
8102137fdb5SSam Leffler 	if (p->packet_try) {
8112137fdb5SSam Leffler 		el = elapsed(&p->plast, &now);
8122137fdb5SSam Leffler 		if (el >= rtr) {
8132137fdb5SSam Leffler 			/* check if we gotta retransmit more */
8142137fdb5SSam Leffler 			if (retransmit(p)) {
8152137fdb5SSam Leffler 				el = 0;
8162137fdb5SSam Leffler 			}
8172137fdb5SSam Leffler 			else
8182137fdb5SSam Leffler 				el = -1;
8192137fdb5SSam Leffler 		}
8202137fdb5SSam Leffler 
8212137fdb5SSam Leffler 		/* gotta retransmit in future */
8222137fdb5SSam Leffler 		if (el != -1) {
8232137fdb5SSam Leffler 			el = rtr - el;
8242137fdb5SSam Leffler 			if ((to.tv_sec*1000*1000 + to.tv_usec) > el) {
8252137fdb5SSam Leffler 				to.tv_sec = el/1000/1000;
8262137fdb5SSam Leffler 				to.tv_usec = el - to.tv_sec*1000*1000;
8272137fdb5SSam Leffler 			}
8282137fdb5SSam Leffler 		}
8292137fdb5SSam Leffler 	}
8302137fdb5SSam Leffler 
8312137fdb5SSam Leffler 	/* select */
8322137fdb5SSam Leffler 	FD_ZERO(&fds);
8332137fdb5SSam Leffler 	FD_SET(p->rx, &fds);
8342137fdb5SSam Leffler 	FD_SET(p->tap, &fds);
8352137fdb5SSam Leffler 	max = p->rx > p->tap ? p->rx : p->tap;
8362137fdb5SSam Leffler 	if (select(max+1, &fds, NULL, NULL, &to) == -1)
8372137fdb5SSam Leffler 		err(1, "select()");
8382137fdb5SSam Leffler 
8392137fdb5SSam Leffler 	if (FD_ISSET(p->tap, &fds))
8402137fdb5SSam Leffler 		read_tap(p);
8412137fdb5SSam Leffler 	if (FD_ISSET(p->rx, &fds))
8422137fdb5SSam Leffler 		read_wifi(p);
8432137fdb5SSam Leffler }
8442137fdb5SSam Leffler 
main(int argc,char * argv[])8452137fdb5SSam Leffler int main(int argc, char *argv[])
8462137fdb5SSam Leffler {
8472c4e7faeSSam Leffler 	char *iface = "wlan0";
8482137fdb5SSam Leffler 	char *tap = "tap0";
8492137fdb5SSam Leffler 	struct params p;
8502137fdb5SSam Leffler 	int ch;
8512137fdb5SSam Leffler 
8522137fdb5SSam Leffler 	/* default params */
8532137fdb5SSam Leffler 	memset(&p, 0, sizeof(p));
8542137fdb5SSam Leffler 	memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
8552137fdb5SSam Leffler 	strcpy(p.ssid, "sorbo");
8562137fdb5SSam Leffler 	p.bint = 500*1000;
8572137fdb5SSam Leffler 	p.seq = getpid();
8582137fdb5SSam Leffler 	if (gettimeofday(&p.blast, NULL) == -1)
8592137fdb5SSam Leffler 		err(1, "gettimeofday()");
8602137fdb5SSam Leffler 	p.chan = 3;
8612137fdb5SSam Leffler 
8622137fdb5SSam Leffler 	while ((ch = getopt(argc, argv, "hi:s:m:w:c:t:")) != -1) {
8632137fdb5SSam Leffler 		switch (ch) {
8642137fdb5SSam Leffler 		case 'i':
8652137fdb5SSam Leffler 			iface = optarg;
8662137fdb5SSam Leffler 			break;
8672137fdb5SSam Leffler 		case 't':
8682137fdb5SSam Leffler 			tap = optarg;
8692137fdb5SSam Leffler 			break;
8702137fdb5SSam Leffler 
8712137fdb5SSam Leffler 		case 'c':
8722137fdb5SSam Leffler 			p.chan = atoi(optarg);
8732137fdb5SSam Leffler 			break;
8742137fdb5SSam Leffler 
8752137fdb5SSam Leffler 		case 's':
8762137fdb5SSam Leffler 			strncpy(p.ssid, optarg, sizeof(p.ssid)-1);
8772137fdb5SSam Leffler 			p.ssid[sizeof(p.ssid)-1] = 0;
8782137fdb5SSam Leffler 			break;
8792137fdb5SSam Leffler 
8802137fdb5SSam Leffler 		case 'm':
8812137fdb5SSam Leffler 			str2mac(p.mac, optarg);
8822137fdb5SSam Leffler 			break;
8832137fdb5SSam Leffler 
8842137fdb5SSam Leffler 		case 'w':
8852137fdb5SSam Leffler 			if (str2wep(p.wep_key, &p.wep_len, optarg)) {
8862137fdb5SSam Leffler 				printf("Error parsing WEP key\n");
8872137fdb5SSam Leffler 				exit(1);
8882137fdb5SSam Leffler 			}
8892137fdb5SSam Leffler 			break;
8902137fdb5SSam Leffler 
8912137fdb5SSam Leffler 		case 'h':
8922137fdb5SSam Leffler 		default:
8932137fdb5SSam Leffler 			usage(argv[0]);
8942137fdb5SSam Leffler 			break;
8952137fdb5SSam Leffler 		}
8962137fdb5SSam Leffler 	}
8972137fdb5SSam Leffler 
8982137fdb5SSam Leffler 	/* init */
8992137fdb5SSam Leffler 	if ((p.tx = open_tx(iface)) == -1)
9002137fdb5SSam Leffler 		err(1, "open_tx()");
9012137fdb5SSam Leffler 	if ((p.rx = open_rx(iface)) == -1)
9022137fdb5SSam Leffler 		err(1, "open_rx()");
9032137fdb5SSam Leffler 
9042137fdb5SSam Leffler 	if ((p.tap = open_tap(tap)) == -1)
9052137fdb5SSam Leffler 		err(1, "open_tap()");
9062137fdb5SSam Leffler 	if (set_iface_mac(tap, p.mac) == -1)
9072137fdb5SSam Leffler 		err(1, "set_iface_mac()");
9082137fdb5SSam Leffler 
9092137fdb5SSam Leffler 	while (1) {
9102137fdb5SSam Leffler 		next_event(&p);
9112137fdb5SSam Leffler 	}
9122137fdb5SSam Leffler 
9132137fdb5SSam Leffler 	exit(0);
9142137fdb5SSam Leffler }
915