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