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/time.h>
272137fdb5SSam Leffler #include <stdlib.h>
282137fdb5SSam Leffler #include <stdio.h>
292137fdb5SSam Leffler #include <unistd.h>
302137fdb5SSam Leffler #include <string.h>
312137fdb5SSam Leffler #include <errno.h>
322137fdb5SSam Leffler #include <err.h>
332137fdb5SSam Leffler #include <net80211/ieee80211.h>
342137fdb5SSam Leffler #include <sys/endian.h>
352137fdb5SSam Leffler #include "w00t.h"
362137fdb5SSam Leffler
372137fdb5SSam Leffler enum {
382137fdb5SSam Leffler S_START = 0,
392137fdb5SSam Leffler S_SEND_PROBE_REQ,
402137fdb5SSam Leffler S_WAIT_PROBE_RES,
412137fdb5SSam Leffler S_SEND_AUTH,
422137fdb5SSam Leffler S_WAIT_AUTH,
432137fdb5SSam Leffler S_SEND_ASSOC,
442137fdb5SSam Leffler S_WAIT_ASSOC,
452137fdb5SSam Leffler S_ASSOCIATED,
462137fdb5SSam Leffler S_SEND_DATA,
472137fdb5SSam Leffler S_WAIT_ACK
482137fdb5SSam Leffler };
492137fdb5SSam Leffler
502137fdb5SSam Leffler struct params {
512137fdb5SSam Leffler int seq;
522137fdb5SSam Leffler int seq_rx;
532137fdb5SSam Leffler char *mac;
542137fdb5SSam Leffler char *ssid;
552137fdb5SSam Leffler char bssid[6];
562137fdb5SSam Leffler char ap[6];
572137fdb5SSam Leffler int tx;
582137fdb5SSam Leffler int rx;
592137fdb5SSam Leffler int tap;
602137fdb5SSam Leffler int aid;
612137fdb5SSam Leffler char packet[4096];
622137fdb5SSam Leffler int packet_len;
632137fdb5SSam Leffler int state;
642137fdb5SSam Leffler char wep_key[13];
652137fdb5SSam Leffler int wep_iv;
662137fdb5SSam Leffler int wep_len;
672137fdb5SSam Leffler };
682137fdb5SSam Leffler
usage(char * pname)692137fdb5SSam Leffler void usage(char *pname)
702137fdb5SSam Leffler {
712137fdb5SSam Leffler printf("Usage: %s <opts>\n"
722137fdb5SSam Leffler "-m\t<source mac>\n"
732137fdb5SSam Leffler "-s\t<ssid>\n"
742137fdb5SSam Leffler "-h\tusage\n"
752137fdb5SSam Leffler "-i\t<iface>\n"
762137fdb5SSam Leffler "-w\t<wep key>\n"
772137fdb5SSam Leffler "-t\t<tap>\n"
782137fdb5SSam Leffler "-b\t<bssid>\n"
792137fdb5SSam Leffler , pname);
802137fdb5SSam Leffler exit(0);
812137fdb5SSam Leffler }
822137fdb5SSam Leffler
fill_basic(struct ieee80211_frame * wh,struct params * p)832137fdb5SSam Leffler void fill_basic(struct ieee80211_frame *wh, struct params *p)
842137fdb5SSam Leffler {
852137fdb5SSam Leffler short *seq;
862137fdb5SSam Leffler
872137fdb5SSam Leffler wh->i_dur[0] = 0x69;
882137fdb5SSam Leffler wh->i_dur[1] = 0x00;
892137fdb5SSam Leffler
902137fdb5SSam Leffler memcpy(wh->i_addr1, p->ap, 6);
912137fdb5SSam Leffler memcpy(wh->i_addr2, p->mac, 6);
922137fdb5SSam Leffler memcpy(wh->i_addr3, p->bssid, 6);
932137fdb5SSam Leffler
942137fdb5SSam Leffler seq = (short*)wh->i_seq;
952137fdb5SSam Leffler *seq = seqfn(p->seq, 0);
962137fdb5SSam Leffler }
972137fdb5SSam Leffler
send_frame(struct params * p,void * buf,int len)982137fdb5SSam Leffler void send_frame(struct params *p, void *buf, int len)
992137fdb5SSam Leffler {
1002137fdb5SSam Leffler int rc;
1012137fdb5SSam Leffler
1022137fdb5SSam Leffler rc = inject(p->tx, buf, len);
1032137fdb5SSam Leffler if (rc == -1) {
1042137fdb5SSam Leffler if (errno == EMSGSIZE)
1052137fdb5SSam Leffler warnx("inject(len %d)", len);
1062137fdb5SSam Leffler else
1072137fdb5SSam Leffler err(1, "inject(len %d)", len);
1082137fdb5SSam Leffler } else if (rc != len)
1092137fdb5SSam Leffler errx(1, "injected %d but only %d sent", rc, len);
1102137fdb5SSam Leffler p->seq++;
1112137fdb5SSam Leffler }
1122137fdb5SSam Leffler
send_probe_request(struct params * p)1132137fdb5SSam Leffler void send_probe_request(struct params *p)
1142137fdb5SSam Leffler {
1152137fdb5SSam Leffler char buf[2048];
1162137fdb5SSam Leffler struct ieee80211_frame *wh;
1172137fdb5SSam Leffler char *data;
1182137fdb5SSam Leffler int len;
1192137fdb5SSam Leffler
1202137fdb5SSam Leffler memset(buf, 0, sizeof(buf));
1212137fdb5SSam Leffler
1222137fdb5SSam Leffler wh = (struct ieee80211_frame*) buf;
1232137fdb5SSam Leffler fill_basic(wh, p);
1242137fdb5SSam Leffler wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ;
1252137fdb5SSam Leffler
1262137fdb5SSam Leffler memset(wh->i_addr1, 0xFF, 6);
1272137fdb5SSam Leffler memset(wh->i_addr3, 0xFF, 6);
1282137fdb5SSam Leffler
1292137fdb5SSam Leffler data = (char*) (wh + 1);
1302137fdb5SSam Leffler *data++ = 0; /* SSID */
1312137fdb5SSam Leffler *data++ = strlen(p->ssid);
1322137fdb5SSam Leffler strcpy(data, p->ssid);
1332137fdb5SSam Leffler data += strlen(p->ssid);
1342137fdb5SSam Leffler
1352137fdb5SSam Leffler *data++ = 1; /* rates */
1362137fdb5SSam Leffler *data++ = 4;
1372137fdb5SSam Leffler *data++ = 2 | 0x80;
1382137fdb5SSam Leffler *data++ = 4 | 0x80;
1392137fdb5SSam Leffler *data++ = 11;
1402137fdb5SSam Leffler *data++ = 22;
1412137fdb5SSam Leffler
1422137fdb5SSam Leffler len = data - (char*)wh;
1432137fdb5SSam Leffler
1442137fdb5SSam Leffler send_frame(p, buf, len);
1452137fdb5SSam Leffler }
1462137fdb5SSam Leffler
send_auth(struct params * p)1472137fdb5SSam Leffler void send_auth(struct params *p)
1482137fdb5SSam Leffler {
1492137fdb5SSam Leffler char buf[2048];
1502137fdb5SSam Leffler struct ieee80211_frame *wh;
1512137fdb5SSam Leffler char *data;
1522137fdb5SSam Leffler int len;
1532137fdb5SSam Leffler
1542137fdb5SSam Leffler memset(buf, 0, sizeof(buf));
1552137fdb5SSam Leffler
1562137fdb5SSam Leffler wh = (struct ieee80211_frame*) buf;
1572137fdb5SSam Leffler fill_basic(wh, p);
1582137fdb5SSam Leffler wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH;
1592137fdb5SSam Leffler
1602137fdb5SSam Leffler data = (char*) (wh + 1);
1612137fdb5SSam Leffler
1622137fdb5SSam Leffler /* algo */
1632137fdb5SSam Leffler *data++ = 0;
1642137fdb5SSam Leffler *data++ = 0;
1652137fdb5SSam Leffler
1662137fdb5SSam Leffler /* transaction no. */
1672137fdb5SSam Leffler *data++ = 1;
1682137fdb5SSam Leffler *data++ = 0;
1692137fdb5SSam Leffler
1702137fdb5SSam Leffler /* status code */
1712137fdb5SSam Leffler *data++ = 0;
1722137fdb5SSam Leffler *data++ = 0;
1732137fdb5SSam Leffler
1742137fdb5SSam Leffler len = data - (char*)wh;
1752137fdb5SSam Leffler
1762137fdb5SSam Leffler send_frame(p, buf, len);
1772137fdb5SSam Leffler }
1782137fdb5SSam Leffler
1792137fdb5SSam Leffler /*
1802137fdb5SSam Leffler * Add an ssid element to a frame.
1812137fdb5SSam Leffler */
1822137fdb5SSam Leffler static u_int8_t *
ieee80211_add_ssid(u_int8_t * frm,const u_int8_t * ssid,u_int len)1832137fdb5SSam Leffler ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
1842137fdb5SSam Leffler {
1852137fdb5SSam Leffler *frm++ = IEEE80211_ELEMID_SSID;
1862137fdb5SSam Leffler *frm++ = len;
1872137fdb5SSam Leffler memcpy(frm, ssid, len);
1882137fdb5SSam Leffler return frm + len;
1892137fdb5SSam Leffler }
1902137fdb5SSam Leffler
send_assoc(struct params * p)1912137fdb5SSam Leffler void send_assoc(struct params *p)
1922137fdb5SSam Leffler {
1932137fdb5SSam Leffler union {
1942137fdb5SSam Leffler struct ieee80211_frame w;
1952137fdb5SSam Leffler char buf[2048];
1962137fdb5SSam Leffler } u;
1972137fdb5SSam Leffler struct ieee80211_frame *wh;
1982137fdb5SSam Leffler char *data;
1992137fdb5SSam Leffler int len, capinfo, lintval;
2002137fdb5SSam Leffler
2012137fdb5SSam Leffler memset(&u, 0, sizeof(u));
2022137fdb5SSam Leffler
2032137fdb5SSam Leffler wh = (struct ieee80211_frame*) &u.w;
2042137fdb5SSam Leffler fill_basic(wh, p);
2052137fdb5SSam Leffler wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
2062137fdb5SSam Leffler
2072137fdb5SSam Leffler data = (char*) (wh + 1);
2082137fdb5SSam Leffler
2092137fdb5SSam Leffler /* capability */
2102137fdb5SSam Leffler capinfo = IEEE80211_CAPINFO_ESS;
2112137fdb5SSam Leffler if (p->wep_len)
2122137fdb5SSam Leffler capinfo |= IEEE80211_CAPINFO_PRIVACY;
2132137fdb5SSam Leffler *(uint16_t *)data = htole16(capinfo);
2142137fdb5SSam Leffler data += 2;
2152137fdb5SSam Leffler
2162137fdb5SSam Leffler /* listen interval */
2172137fdb5SSam Leffler *(uint16_t *)data = htole16(100);
2182137fdb5SSam Leffler data += 2;
2192137fdb5SSam Leffler
2202137fdb5SSam Leffler data = ieee80211_add_ssid(data, p->ssid, strlen(p->ssid));
2212137fdb5SSam Leffler
2222137fdb5SSam Leffler *data++ = 1; /* rates */
2232137fdb5SSam Leffler *data++ = 4;
2242137fdb5SSam Leffler *data++ = 2 | 0x80;
2252137fdb5SSam Leffler *data++ = 4 | 0x80;
2262137fdb5SSam Leffler *data++ = 11;
2272137fdb5SSam Leffler *data++ = 22;
2282137fdb5SSam Leffler
2292137fdb5SSam Leffler len = data - (char*)wh;
2302137fdb5SSam Leffler
2312137fdb5SSam Leffler send_frame(p, u.buf, len);
2322137fdb5SSam Leffler }
2332137fdb5SSam Leffler
for_me(struct ieee80211_frame * wh,char * mac)2342137fdb5SSam Leffler int for_me(struct ieee80211_frame *wh, char *mac)
2352137fdb5SSam Leffler {
2362137fdb5SSam Leffler return memcmp(wh->i_addr1, mac, 6) == 0;
2372137fdb5SSam Leffler }
2382137fdb5SSam Leffler
from_ap(struct ieee80211_frame * wh,char * mac)2392137fdb5SSam Leffler int from_ap(struct ieee80211_frame *wh, char *mac)
2402137fdb5SSam Leffler {
2412137fdb5SSam Leffler return memcmp(wh->i_addr2, mac, 6) == 0;
2422137fdb5SSam Leffler }
2432137fdb5SSam Leffler
ack(struct params * p,struct ieee80211_frame * wh)2442137fdb5SSam Leffler void ack(struct params *p, struct ieee80211_frame *wh)
2452137fdb5SSam Leffler {
2462137fdb5SSam Leffler if (memcmp(wh->i_addr1, p->mac, 6) != 0)
2472137fdb5SSam Leffler return;
2482137fdb5SSam Leffler
2492137fdb5SSam Leffler if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
2502137fdb5SSam Leffler return;
2512137fdb5SSam Leffler
2522137fdb5SSam Leffler send_ack(p->tx, wh->i_addr2);
2532137fdb5SSam Leffler }
2542137fdb5SSam Leffler
generic_process(struct ieee80211_frame * wh,struct params * p,int len)2552137fdb5SSam Leffler void generic_process(struct ieee80211_frame *wh, struct params *p, int len)
2562137fdb5SSam Leffler {
2572137fdb5SSam Leffler int type, stype;
2582137fdb5SSam Leffler int dup = 0;
2592137fdb5SSam Leffler
2602137fdb5SSam Leffler #if 0
2612137fdb5SSam Leffler ack(p, wh);
2622137fdb5SSam Leffler #endif
2632137fdb5SSam Leffler
2642137fdb5SSam Leffler #if 0
2652137fdb5SSam Leffler if (!for_me(wh, p->mac))
2662137fdb5SSam Leffler return;
2672137fdb5SSam Leffler #endif
2682137fdb5SSam Leffler /* ignore my own shit */
2692137fdb5SSam Leffler if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
2702137fdb5SSam Leffler return;
2712137fdb5SSam Leffler }
2722137fdb5SSam Leffler
2732137fdb5SSam Leffler type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
2742137fdb5SSam Leffler stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2752137fdb5SSam Leffler
2762137fdb5SSam Leffler if (for_me(wh, p->mac) && type == IEEE80211_FC0_TYPE_DATA) {
2772137fdb5SSam Leffler /* sequence number & dups */
2782137fdb5SSam Leffler if (p->seq_rx == -1)
2792137fdb5SSam Leffler p->seq_rx = seqno(wh);
2802137fdb5SSam Leffler else {
2812137fdb5SSam Leffler int s = seqno(wh);
2822137fdb5SSam Leffler
2832137fdb5SSam Leffler if (s > p->seq_rx) {
2842137fdb5SSam Leffler /* normal case */
2852137fdb5SSam Leffler if (p->seq_rx + 1 == s) {
2862137fdb5SSam Leffler #if 0
2872137fdb5SSam Leffler printf("S=%d\n", s);
2882137fdb5SSam Leffler #endif
2892137fdb5SSam Leffler p->seq_rx = s;
2902137fdb5SSam Leffler }
2912137fdb5SSam Leffler else { /* future */
2922137fdb5SSam Leffler #if 0
2932137fdb5SSam Leffler printf("Got seq %d, prev %d\n",
2942137fdb5SSam Leffler s, p->seq_rx);
2952137fdb5SSam Leffler #endif
2962137fdb5SSam Leffler p->seq_rx = s;
2972137fdb5SSam Leffler }
2982137fdb5SSam Leffler } else { /* we got pas stuff... */
2992137fdb5SSam Leffler if (p->seq_rx - s > 1000) {
3002137fdb5SSam Leffler #if 0
3012137fdb5SSam Leffler printf("Seqno wrap seq %d, last %d\n",
3022137fdb5SSam Leffler s, p->seq_rx);
3032137fdb5SSam Leffler #endif
3042137fdb5SSam Leffler /* seqno wrapping ? */
3052137fdb5SSam Leffler p->seq_rx = 0;
3062137fdb5SSam Leffler }
3072137fdb5SSam Leffler else { /* dup */
3082137fdb5SSam Leffler dup = 1;
3092137fdb5SSam Leffler #if 0
3102137fdb5SSam Leffler printf("Got dup seq %d, last %d\n",
3112137fdb5SSam Leffler s, p->seq_rx);
3122137fdb5SSam Leffler #endif
3132137fdb5SSam Leffler }
3142137fdb5SSam Leffler }
3152137fdb5SSam Leffler }
3162137fdb5SSam Leffler }
3172137fdb5SSam Leffler #if 0
3182137fdb5SSam Leffler if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
3192137fdb5SSam Leffler printf("Got retry\n");
3202137fdb5SSam Leffler }
3212137fdb5SSam Leffler #endif
3222137fdb5SSam Leffler #if 0
3232137fdb5SSam Leffler if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
3242137fdb5SSam Leffler int rc = send_ack(p->tx, wh->i_addr2);
3252137fdb5SSam Leffler if (rc == -1)
3262137fdb5SSam Leffler err(1, "send_ack()");
3272137fdb5SSam Leffler if (rc != 10) {
3282137fdb5SSam Leffler printf("Wrote ACK %d/%d\n", rc, 10);
3292137fdb5SSam Leffler exit(1);
3302137fdb5SSam Leffler }
3312137fdb5SSam Leffler }
3322137fdb5SSam Leffler #endif
3332137fdb5SSam Leffler
3342137fdb5SSam Leffler /* data frames */
3352137fdb5SSam Leffler if (type == IEEE80211_FC0_TYPE_DATA && !dup) {
3362137fdb5SSam Leffler char *ptr;
3372137fdb5SSam Leffler char src[6], dst[6];
3382137fdb5SSam Leffler int rc;
3392137fdb5SSam Leffler
3402137fdb5SSam Leffler if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
3412137fdb5SSam Leffler if (memcmp(wh->i_addr2, p->ap, 6) != 0)
3422137fdb5SSam Leffler return;
3432137fdb5SSam Leffler } else {
3442137fdb5SSam Leffler if (memcmp(wh->i_addr1, p->ap, 6) != 0)
3452137fdb5SSam Leffler return;
3462137fdb5SSam Leffler }
3472137fdb5SSam Leffler
3482137fdb5SSam Leffler
3492137fdb5SSam Leffler if (p->state < S_ASSOCIATED) {
3502137fdb5SSam Leffler printf("Got data when not associated!\n");
3512137fdb5SSam Leffler return;
3522137fdb5SSam Leffler }
3532137fdb5SSam Leffler if (stype != IEEE80211_FC0_SUBTYPE_DATA) {
3542137fdb5SSam Leffler printf("Got weird data frame stype=%d\n",
3552137fdb5SSam Leffler stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
3562137fdb5SSam Leffler return;
3572137fdb5SSam Leffler }
3582137fdb5SSam Leffler
3592137fdb5SSam Leffler if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
3602137fdb5SSam Leffler memcpy(src, wh->i_addr3, 6);
3612137fdb5SSam Leffler memcpy(dst, wh->i_addr1, 6);
3622137fdb5SSam Leffler } else {
3632137fdb5SSam Leffler memcpy(src, wh->i_addr2, 6);
3642137fdb5SSam Leffler memcpy(dst, wh->i_addr3, 6);
3652137fdb5SSam Leffler }
3662137fdb5SSam Leffler
3672137fdb5SSam Leffler ptr = (char*) (wh + 1);
3682137fdb5SSam Leffler
369*5945b5f5SKevin Lo if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
3702137fdb5SSam Leffler if (!p->wep_len) {
3712137fdb5SSam Leffler char srca[3*6];
3722137fdb5SSam Leffler char dsta[3*6];
3732137fdb5SSam Leffler
3742137fdb5SSam Leffler mac2str(srca, src);
3752137fdb5SSam Leffler mac2str(dsta, dst);
3762137fdb5SSam Leffler printf("Got wep but i aint wep %s->%s %d\n",
3772137fdb5SSam Leffler srca, dsta, len-sizeof(*wh)-8);
3782137fdb5SSam Leffler return;
3792137fdb5SSam Leffler }
3802137fdb5SSam Leffler
3812137fdb5SSam Leffler if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
3822137fdb5SSam Leffler char srca[3*6];
3832137fdb5SSam Leffler char dsta[3*6];
3842137fdb5SSam Leffler
3852137fdb5SSam Leffler mac2str(srca, src);
3862137fdb5SSam Leffler mac2str(dsta, dst);
3872137fdb5SSam Leffler printf("Can't decrypt %s->%s %d\n", srca, dsta,
3882137fdb5SSam Leffler len-sizeof(*wh)-8);
3892137fdb5SSam Leffler return;
3902137fdb5SSam Leffler }
3912137fdb5SSam Leffler
3922137fdb5SSam Leffler ptr += 4;
3932137fdb5SSam Leffler len -= 8;
3942137fdb5SSam Leffler }
3952137fdb5SSam Leffler
3962137fdb5SSam Leffler /* ether header */
3972137fdb5SSam Leffler ptr += 8 - 2;
3982137fdb5SSam Leffler ptr -= 6;
3992137fdb5SSam Leffler memcpy(ptr, src, 6);
4002137fdb5SSam Leffler ptr -= 6;
4012137fdb5SSam Leffler memcpy(ptr, dst, 6);
4022137fdb5SSam Leffler
4032137fdb5SSam Leffler len -= sizeof(*wh);
4042137fdb5SSam Leffler len -= 8;
4052137fdb5SSam Leffler len += 14;
4062137fdb5SSam Leffler
4072137fdb5SSam Leffler /* send to tap */
4082137fdb5SSam Leffler rc = write(p->tap, ptr, len);
4092137fdb5SSam Leffler if (rc == -1)
4102137fdb5SSam Leffler err(1, "write()");
4112137fdb5SSam Leffler if (rc != len) {
4122137fdb5SSam Leffler printf("Wrote %d/%d\n", rc, len);
4132137fdb5SSam Leffler exit(1);
4142137fdb5SSam Leffler }
4152137fdb5SSam Leffler }
4162137fdb5SSam Leffler }
4172137fdb5SSam Leffler
get_probe_response(struct params * p)4182137fdb5SSam Leffler int get_probe_response(struct params *p)
4192137fdb5SSam Leffler {
4202137fdb5SSam Leffler char buf[4096];
4212137fdb5SSam Leffler int rc;
4222137fdb5SSam Leffler struct ieee80211_frame *wh;
4232137fdb5SSam Leffler char *data;
4242137fdb5SSam Leffler int ess;
4252137fdb5SSam Leffler int wep;
4262137fdb5SSam Leffler char *ssid;
4272137fdb5SSam Leffler char from[18];
4282137fdb5SSam Leffler char bssid[18];
4292137fdb5SSam Leffler
4302137fdb5SSam Leffler rc = sniff(p->rx, buf, sizeof(buf));
4312137fdb5SSam Leffler if (rc == -1)
4322137fdb5SSam Leffler err(1, "sniff()");
4332137fdb5SSam Leffler
4342137fdb5SSam Leffler wh = get_wifi(buf, &rc);
4352137fdb5SSam Leffler if (!wh)
4362137fdb5SSam Leffler return 0;
4372137fdb5SSam Leffler
4382137fdb5SSam Leffler generic_process(wh, p, rc);
4392137fdb5SSam Leffler
4402137fdb5SSam Leffler if (!for_me(wh, p->mac))
4412137fdb5SSam Leffler return 0;
4422137fdb5SSam Leffler
4432137fdb5SSam Leffler if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
4442137fdb5SSam Leffler IEEE80211_FC0_SUBTYPE_PROBE_RESP))
4452137fdb5SSam Leffler return 0;
4462137fdb5SSam Leffler
4472137fdb5SSam Leffler data = (char*) (wh+1);
4482137fdb5SSam Leffler data += 8; /* Timestamp */
4492137fdb5SSam Leffler data += 2; /* Beacon Interval */
4502137fdb5SSam Leffler ess = *data & 1;
4512137fdb5SSam Leffler wep = (*data & IEEE80211_CAPINFO_PRIVACY) ? 1 : 0;
4522137fdb5SSam Leffler data += 2; /* capability */
4532137fdb5SSam Leffler
4542137fdb5SSam Leffler /* ssid */
4552137fdb5SSam Leffler if (*data != 0) {
4562137fdb5SSam Leffler printf("Warning, expecting SSID got %x\n", *data);
4572137fdb5SSam Leffler return 0;
4582137fdb5SSam Leffler }
4592137fdb5SSam Leffler data++;
4602137fdb5SSam Leffler ssid = data+1;
4612137fdb5SSam Leffler data += 1 + *data;
4622137fdb5SSam Leffler if (*data != 1) {
4632137fdb5SSam Leffler printf("Warning, expected rates got %x\n", *data);
4642137fdb5SSam Leffler return 0;
4652137fdb5SSam Leffler }
4662137fdb5SSam Leffler *data = 0;
4672137fdb5SSam Leffler
4682137fdb5SSam Leffler /* rates */
4692137fdb5SSam Leffler data++;
4702137fdb5SSam Leffler
4712137fdb5SSam Leffler mac2str(from, wh->i_addr2);
4722137fdb5SSam Leffler mac2str(bssid, wh->i_addr3);
4732137fdb5SSam Leffler printf("Got response from %s [%s] [%s] ESS=%d WEP=%d\n",
4742137fdb5SSam Leffler from, bssid, ssid, ess, wep);
4752137fdb5SSam Leffler
4762137fdb5SSam Leffler if (strcmp(ssid, p->ssid) != 0)
4772137fdb5SSam Leffler return 0;
4782137fdb5SSam Leffler
4792137fdb5SSam Leffler memcpy(p->ap, wh->i_addr2, 6);
4802137fdb5SSam Leffler memcpy(p->bssid, wh->i_addr3, 6);
4812137fdb5SSam Leffler return 1;
4822137fdb5SSam Leffler }
4832137fdb5SSam Leffler
get_auth(struct params * p)4842137fdb5SSam Leffler int get_auth(struct params *p)
4852137fdb5SSam Leffler {
4862137fdb5SSam Leffler char buf[4096];
4872137fdb5SSam Leffler int rc;
4882137fdb5SSam Leffler struct ieee80211_frame *wh;
4892137fdb5SSam Leffler short *data;
4902137fdb5SSam Leffler
4912137fdb5SSam Leffler rc = sniff(p->rx, buf, sizeof(buf));
4922137fdb5SSam Leffler if (rc == -1)
4932137fdb5SSam Leffler err(1, "sniff()");
4942137fdb5SSam Leffler
4952137fdb5SSam Leffler wh = get_wifi(buf, &rc);
4962137fdb5SSam Leffler if (!wh)
4972137fdb5SSam Leffler return 0;
4982137fdb5SSam Leffler
4992137fdb5SSam Leffler generic_process(wh, p, rc);
5002137fdb5SSam Leffler
5012137fdb5SSam Leffler if (!for_me(wh, p->mac))
5022137fdb5SSam Leffler return 0;
5032137fdb5SSam Leffler
5042137fdb5SSam Leffler if (!from_ap(wh, p->ap))
5052137fdb5SSam Leffler return 0;
5062137fdb5SSam Leffler
5072137fdb5SSam Leffler if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
5082137fdb5SSam Leffler IEEE80211_FC0_SUBTYPE_AUTH))
5092137fdb5SSam Leffler return 0;
5102137fdb5SSam Leffler
5112137fdb5SSam Leffler data = (short*) (wh+1);
5122137fdb5SSam Leffler
5132137fdb5SSam Leffler /* algo */
5142137fdb5SSam Leffler if (le16toh(*data) != 0) {
5152137fdb5SSam Leffler printf("Not open-system %d!\n", le16toh(*data));
5162137fdb5SSam Leffler return 0;
5172137fdb5SSam Leffler }
5182137fdb5SSam Leffler data++;
5192137fdb5SSam Leffler
5202137fdb5SSam Leffler /* transaction no. */
5212137fdb5SSam Leffler if (le16toh(*data) != 2) {
5222137fdb5SSam Leffler printf("Got transaction %d!\n", le16toh(*data));
5232137fdb5SSam Leffler return 0;
5242137fdb5SSam Leffler }
5252137fdb5SSam Leffler data++;
5262137fdb5SSam Leffler
5272137fdb5SSam Leffler /* status code */
5282137fdb5SSam Leffler rc = le16toh(*data);
5292137fdb5SSam Leffler if (rc == 0) {
5302137fdb5SSam Leffler printf("Authenticated\n");
5312137fdb5SSam Leffler return 1;
5322137fdb5SSam Leffler }
5332137fdb5SSam Leffler
5342137fdb5SSam Leffler printf("Authentication failed code=%d\n", rc);
5352137fdb5SSam Leffler return 0;
5362137fdb5SSam Leffler }
5372137fdb5SSam Leffler
get_assoc(struct params * p)5382137fdb5SSam Leffler int get_assoc(struct params *p)
5392137fdb5SSam Leffler {
5402137fdb5SSam Leffler char buf[4096];
5412137fdb5SSam Leffler int rc;
5422137fdb5SSam Leffler struct ieee80211_frame *wh;
5432137fdb5SSam Leffler unsigned short *data;
5442137fdb5SSam Leffler
5452137fdb5SSam Leffler rc = sniff(p->rx, buf, sizeof(buf));
5462137fdb5SSam Leffler if (rc == -1)
5472137fdb5SSam Leffler err(1, "sniff()");
5482137fdb5SSam Leffler
5492137fdb5SSam Leffler wh = get_wifi(buf, &rc);
5502137fdb5SSam Leffler if (!wh)
5512137fdb5SSam Leffler return 0;
5522137fdb5SSam Leffler
5532137fdb5SSam Leffler generic_process(wh, p, rc);
5542137fdb5SSam Leffler
5552137fdb5SSam Leffler if (!for_me(wh, p->mac))
5562137fdb5SSam Leffler return 0;
5572137fdb5SSam Leffler
5582137fdb5SSam Leffler if (!from_ap(wh, p->ap))
5592137fdb5SSam Leffler return 0;
5602137fdb5SSam Leffler
5612137fdb5SSam Leffler if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
5622137fdb5SSam Leffler IEEE80211_FC0_SUBTYPE_ASSOC_RESP))
5632137fdb5SSam Leffler return 0;
5642137fdb5SSam Leffler
5652137fdb5SSam Leffler
5662137fdb5SSam Leffler data = (unsigned short*) (wh+1);
5672137fdb5SSam Leffler
5682137fdb5SSam Leffler data++; /* caps */
5692137fdb5SSam Leffler
5702137fdb5SSam Leffler /* status */
5712137fdb5SSam Leffler rc = le16toh(*data++);
5722137fdb5SSam Leffler if (rc != 0) {
5732137fdb5SSam Leffler printf("Assoc failed code %d\n", rc);
5742137fdb5SSam Leffler return 0;
5752137fdb5SSam Leffler }
5762137fdb5SSam Leffler
5772137fdb5SSam Leffler /* aid */
5782137fdb5SSam Leffler p->aid = le16toh(*data & ~( (1 << 15) | (1 << 14)));
5792137fdb5SSam Leffler printf("Association ID=%d\n", p->aid);
5802137fdb5SSam Leffler
5812137fdb5SSam Leffler return 1;
5822137fdb5SSam Leffler }
5832137fdb5SSam Leffler
read_wifi(struct params * p)5842137fdb5SSam Leffler void read_wifi(struct params *p)
5852137fdb5SSam Leffler {
5862137fdb5SSam Leffler char buf[4096];
5872137fdb5SSam Leffler int rc;
5882137fdb5SSam Leffler struct ieee80211_frame *wh;
5892137fdb5SSam Leffler int type, stype;
5902137fdb5SSam Leffler
5912137fdb5SSam Leffler rc = sniff(p->rx, buf, sizeof(buf));
5922137fdb5SSam Leffler if (rc == -1)
5932137fdb5SSam Leffler err(1, "sniff()");
5942137fdb5SSam Leffler
5952137fdb5SSam Leffler wh = get_wifi(buf, &rc);
5962137fdb5SSam Leffler if (!wh)
5972137fdb5SSam Leffler return;
5982137fdb5SSam Leffler
5992137fdb5SSam Leffler generic_process(wh, p, rc);
6002137fdb5SSam Leffler
6012137fdb5SSam Leffler if (!for_me(wh, p->mac))
6022137fdb5SSam Leffler return;
6032137fdb5SSam Leffler
6042137fdb5SSam Leffler type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
6052137fdb5SSam Leffler stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
6062137fdb5SSam Leffler
6072137fdb5SSam Leffler /* control frames */
6082137fdb5SSam Leffler if (type == IEEE80211_FC0_TYPE_CTL) {
6092137fdb5SSam Leffler switch (stype) {
6102137fdb5SSam Leffler case IEEE80211_FC0_SUBTYPE_ACK:
6112137fdb5SSam Leffler if (p->state == S_WAIT_ACK)
6122137fdb5SSam Leffler p->state = S_ASSOCIATED;
6132137fdb5SSam Leffler break;
6142137fdb5SSam Leffler
6152137fdb5SSam Leffler case IEEE80211_FC0_SUBTYPE_RTS:
6162137fdb5SSam Leffler #if 0
6172137fdb5SSam Leffler printf("Got RTS\n");
6182137fdb5SSam Leffler #endif
6192137fdb5SSam Leffler break;
6202137fdb5SSam Leffler
6212137fdb5SSam Leffler default:
6222137fdb5SSam Leffler printf("Unknown CTL frame %d\n",
6232137fdb5SSam Leffler stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
6242137fdb5SSam Leffler abort();
6252137fdb5SSam Leffler break;
6262137fdb5SSam Leffler }
6272137fdb5SSam Leffler return;
6282137fdb5SSam Leffler }
6292137fdb5SSam Leffler
6302137fdb5SSam Leffler if (!from_ap(wh, p->ap))
6312137fdb5SSam Leffler return;
6322137fdb5SSam Leffler
6332137fdb5SSam Leffler if (type != IEEE80211_FC0_TYPE_MGT)
6342137fdb5SSam Leffler return;
6352137fdb5SSam Leffler
6362137fdb5SSam Leffler if (stype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
6372137fdb5SSam Leffler stype == IEEE80211_FC0_SUBTYPE_DISASSOC) {
6382137fdb5SSam Leffler printf("Got management! %d\n",
6392137fdb5SSam Leffler stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
6402137fdb5SSam Leffler p->seq_rx = -1;
6412137fdb5SSam Leffler p->state = S_START;
6422137fdb5SSam Leffler }
6432137fdb5SSam Leffler
6442137fdb5SSam Leffler return;
6452137fdb5SSam Leffler }
6462137fdb5SSam Leffler
read_tap(struct params * p)6472137fdb5SSam Leffler void read_tap(struct params *p)
6482137fdb5SSam Leffler {
6492137fdb5SSam Leffler char *ptr;
6502137fdb5SSam Leffler int len = sizeof(p->packet);
6512137fdb5SSam Leffler int offset;
6522137fdb5SSam Leffler char mac[6];
6532137fdb5SSam Leffler struct ieee80211_frame *wh;
6542137fdb5SSam Leffler
6552137fdb5SSam Leffler ptr = p->packet;
6562137fdb5SSam Leffler offset = sizeof(struct ieee80211_frame) + 8 - 14;
6572137fdb5SSam Leffler if (p->wep_len)
6582137fdb5SSam Leffler offset += 4;
6592137fdb5SSam Leffler
6602137fdb5SSam Leffler ptr += offset;
6612137fdb5SSam Leffler len -= offset;
6622137fdb5SSam Leffler
6632137fdb5SSam Leffler /* read packet */
6642137fdb5SSam Leffler memset(p->packet, 0, sizeof(p->packet));
6652137fdb5SSam Leffler p->packet_len = read(p->tap, ptr, len);
6662137fdb5SSam Leffler if (p->packet_len == -1)
6672137fdb5SSam Leffler err(1, "read()");
6682137fdb5SSam Leffler
6692137fdb5SSam Leffler /* 802.11 header */
6702137fdb5SSam Leffler wh = (struct ieee80211_frame*) p->packet;
6712137fdb5SSam Leffler memcpy(mac, ptr, sizeof(mac));
6722137fdb5SSam Leffler fill_basic(wh, p);
6732137fdb5SSam Leffler memcpy(wh->i_addr3, mac, sizeof(wh->i_addr3));
6742137fdb5SSam Leffler wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
6752137fdb5SSam Leffler wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
6762137fdb5SSam Leffler if (p->wep_len)
677*5945b5f5SKevin Lo wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
6782137fdb5SSam Leffler
6792137fdb5SSam Leffler /* LLC & SNAP */
6802137fdb5SSam Leffler ptr = (char*) (wh+1);
6812137fdb5SSam Leffler if (p->wep_len)
6822137fdb5SSam Leffler ptr += 4;
6832137fdb5SSam Leffler *ptr++ = 0xAA;
6842137fdb5SSam Leffler *ptr++ = 0xAA;
6852137fdb5SSam Leffler *ptr++ = 0x03;
6862137fdb5SSam Leffler *ptr++ = 0x00;
6872137fdb5SSam Leffler *ptr++ = 0x00;
6882137fdb5SSam Leffler *ptr++ = 0x00;
6892137fdb5SSam Leffler /* ether type overlaps w00t */
6902137fdb5SSam Leffler
6912137fdb5SSam Leffler p->packet_len += offset;
6922137fdb5SSam Leffler
6932137fdb5SSam Leffler /* WEP */
6942137fdb5SSam Leffler if (p->wep_len) {
6952137fdb5SSam Leffler ptr = (char*) (wh+1);
6962137fdb5SSam Leffler memcpy(ptr, &p->wep_iv, 3);
6972137fdb5SSam Leffler ptr[3] = 0;
6982137fdb5SSam Leffler p->wep_iv++;
6992137fdb5SSam Leffler
7002137fdb5SSam Leffler wep_encrypt(wh, p->packet_len, p->wep_key, p->wep_len);
7012137fdb5SSam Leffler p->packet_len += 4; /* ICV */
7022137fdb5SSam Leffler }
7032137fdb5SSam Leffler }
7042137fdb5SSam Leffler
main(int argc,char * argv[])7052137fdb5SSam Leffler int main(int argc, char *argv[])
7062137fdb5SSam Leffler {
7072137fdb5SSam Leffler char* ssid = 0;
7082137fdb5SSam Leffler char mac[] = { 0x00, 0x00, 0xde, 0xfa, 0xce, 0xd };
7092137fdb5SSam Leffler int ch;
7102137fdb5SSam Leffler struct params p;
7112c4e7faeSSam Leffler char *iface = "wlan0";
7122137fdb5SSam Leffler char *tap = "tap0";
7132137fdb5SSam Leffler int timeout = 50*1000;
7142137fdb5SSam Leffler struct timeval start;
7152137fdb5SSam Leffler
7162137fdb5SSam Leffler memset(&p, 0, sizeof(p));
7172137fdb5SSam Leffler p.wep_len = 0;
7182137fdb5SSam Leffler p.wep_iv = 0;
7192137fdb5SSam Leffler p.state = S_START;
7202137fdb5SSam Leffler
7212137fdb5SSam Leffler while ((ch = getopt(argc, argv, "hm:s:i:w:t:b:")) != -1) {
7222137fdb5SSam Leffler switch (ch) {
7232137fdb5SSam Leffler case 'b':
7242137fdb5SSam Leffler if (str2mac(p.bssid, optarg)) {
7252137fdb5SSam Leffler printf("Error parsing BSSID\n");
7262137fdb5SSam Leffler exit(1);
7272137fdb5SSam Leffler }
7282137fdb5SSam Leffler memcpy(p.ap, p.bssid, sizeof(p.ap));
7292137fdb5SSam Leffler p.state = S_SEND_AUTH;
7302137fdb5SSam Leffler break;
7312137fdb5SSam Leffler
7322137fdb5SSam Leffler case 's':
7332137fdb5SSam Leffler ssid = optarg;
7342137fdb5SSam Leffler break;
7352137fdb5SSam Leffler
7362137fdb5SSam Leffler case 'm':
7372137fdb5SSam Leffler if (str2mac(mac, optarg)) {
7382137fdb5SSam Leffler printf("Error parsing MAC\n");
7392137fdb5SSam Leffler exit(1);
7402137fdb5SSam Leffler }
7412137fdb5SSam Leffler break;
7422137fdb5SSam Leffler
7432137fdb5SSam Leffler case 'i':
7442137fdb5SSam Leffler iface = optarg;
7452137fdb5SSam Leffler break;
7462137fdb5SSam Leffler
7472137fdb5SSam Leffler case 'w':
7482137fdb5SSam Leffler if (str2wep(p.wep_key, &p.wep_len, optarg)) {
7492137fdb5SSam Leffler printf("Error parsing WEP key\n");
7502137fdb5SSam Leffler exit(1);
7512137fdb5SSam Leffler }
7522137fdb5SSam Leffler break;
7532137fdb5SSam Leffler
7542137fdb5SSam Leffler case 't':
7552137fdb5SSam Leffler tap = optarg;
7562137fdb5SSam Leffler break;
7572137fdb5SSam Leffler
7582137fdb5SSam Leffler case 'h':
7592137fdb5SSam Leffler default:
7602137fdb5SSam Leffler usage(argv[0]);
7612137fdb5SSam Leffler break;
7622137fdb5SSam Leffler }
7632137fdb5SSam Leffler }
7642137fdb5SSam Leffler
7652137fdb5SSam Leffler if (!ssid)
7662137fdb5SSam Leffler usage(argv[0]);
7672137fdb5SSam Leffler
7682137fdb5SSam Leffler p.mac = mac;
7692137fdb5SSam Leffler p.ssid = ssid;
7702137fdb5SSam Leffler p.seq = getpid();
7712137fdb5SSam Leffler p.seq_rx = -1;
7722137fdb5SSam Leffler if (open_rxtx(iface, &p.rx, &p.tx) == -1)
7732137fdb5SSam Leffler err(1, "open_rxtx()");
7742137fdb5SSam Leffler p.tap = open_tap(tap);
7752137fdb5SSam Leffler if (p.tap == -1)
7762137fdb5SSam Leffler err(1, "open_tap()");
7772137fdb5SSam Leffler if (set_iface_mac(tap, mac) == -1)
7782137fdb5SSam Leffler err(1, "set_iface_mac()");
7792137fdb5SSam Leffler
7802137fdb5SSam Leffler while (1) {
7812137fdb5SSam Leffler /* check for timeouts */
7822137fdb5SSam Leffler switch (p.state) {
7832137fdb5SSam Leffler case S_WAIT_PROBE_RES:
7842137fdb5SSam Leffler case S_WAIT_AUTH:
7852137fdb5SSam Leffler case S_WAIT_ASSOC:
7862137fdb5SSam Leffler case S_WAIT_ACK:
7872137fdb5SSam Leffler do {
7882137fdb5SSam Leffler int rc;
7892137fdb5SSam Leffler struct timeval tv;
7902137fdb5SSam Leffler int elapsed = 0;
7912137fdb5SSam Leffler
7922137fdb5SSam Leffler /* check timeout */
7932137fdb5SSam Leffler if (gettimeofday(&tv, NULL) == -1)
7942137fdb5SSam Leffler err(1, "gettimeofday()");
7952137fdb5SSam Leffler elapsed = tv.tv_sec - start.tv_sec;
7962137fdb5SSam Leffler if (elapsed == 0) {
7972137fdb5SSam Leffler elapsed = tv.tv_usec - start.tv_usec;
7982137fdb5SSam Leffler } else {
7992137fdb5SSam Leffler elapsed *= (elapsed-1)*1000*1000;
8002137fdb5SSam Leffler elapsed += 1000*1000 - start.tv_usec;
8012137fdb5SSam Leffler elapsed += tv.tv_usec;
8022137fdb5SSam Leffler }
8032137fdb5SSam Leffler if (elapsed >= timeout)
8042137fdb5SSam Leffler rc = 0;
8052137fdb5SSam Leffler else {
8062137fdb5SSam Leffler fd_set fds;
8072137fdb5SSam Leffler
8082137fdb5SSam Leffler FD_ZERO(&fds);
8092137fdb5SSam Leffler FD_SET(p.rx, &fds);
8102137fdb5SSam Leffler
8112137fdb5SSam Leffler elapsed = timeout - elapsed;
8122137fdb5SSam Leffler tv.tv_sec = elapsed/1000/1000;
8132137fdb5SSam Leffler elapsed -= tv.tv_sec*1000*1000;
8142137fdb5SSam Leffler tv.tv_usec = elapsed;
8152137fdb5SSam Leffler
8162137fdb5SSam Leffler rc = select(p.rx+1, &fds, NULL,
8172137fdb5SSam Leffler NULL, &tv);
8182137fdb5SSam Leffler if (rc == -1)
8192137fdb5SSam Leffler err(1, "select()");
8202137fdb5SSam Leffler }
8212137fdb5SSam Leffler
8222137fdb5SSam Leffler /* timeout */
8232137fdb5SSam Leffler if (!rc) {
8242137fdb5SSam Leffler #if 0
8252137fdb5SSam Leffler printf("Timeout\n");
8262137fdb5SSam Leffler #endif
8272137fdb5SSam Leffler p.state--;
8282137fdb5SSam Leffler }
8292137fdb5SSam Leffler
8302137fdb5SSam Leffler } while(0);
8312137fdb5SSam Leffler break;
8322137fdb5SSam Leffler }
8332137fdb5SSam Leffler
8342137fdb5SSam Leffler switch (p.state) {
8352137fdb5SSam Leffler case S_START:
8362137fdb5SSam Leffler p.state = S_SEND_PROBE_REQ;
8372137fdb5SSam Leffler break;
8382137fdb5SSam Leffler
8392137fdb5SSam Leffler case S_SEND_PROBE_REQ:
8402137fdb5SSam Leffler printf("Sending probe request for %s\n", ssid);
8412137fdb5SSam Leffler send_probe_request(&p);
8422137fdb5SSam Leffler p.state = S_WAIT_PROBE_RES;
8432137fdb5SSam Leffler if (gettimeofday(&start, NULL) == -1)
8442137fdb5SSam Leffler err(1, "gettimeofday()");
8452137fdb5SSam Leffler break;
8462137fdb5SSam Leffler
8472137fdb5SSam Leffler case S_WAIT_PROBE_RES:
8482137fdb5SSam Leffler if (get_probe_response(&p)) {
8492137fdb5SSam Leffler p.state = S_SEND_AUTH;
8502137fdb5SSam Leffler }
8512137fdb5SSam Leffler break;
8522137fdb5SSam Leffler
8532137fdb5SSam Leffler case S_SEND_AUTH:
8542137fdb5SSam Leffler do {
8552137fdb5SSam Leffler char apmac[18];
8562137fdb5SSam Leffler
8572137fdb5SSam Leffler mac2str(apmac, p.ap);
8582137fdb5SSam Leffler printf("Sending auth to %s\n", apmac);
8592137fdb5SSam Leffler send_auth(&p);
8602137fdb5SSam Leffler p.state = S_WAIT_AUTH;
8612137fdb5SSam Leffler if (gettimeofday(&start, NULL) == -1)
8622137fdb5SSam Leffler err(1, "gettimeofday()");
8632137fdb5SSam Leffler } while(0);
8642137fdb5SSam Leffler break;
8652137fdb5SSam Leffler
8662137fdb5SSam Leffler case S_WAIT_AUTH:
8672137fdb5SSam Leffler if (get_auth(&p)) {
8682137fdb5SSam Leffler p.state = S_SEND_ASSOC;
8692137fdb5SSam Leffler }
8702137fdb5SSam Leffler break;
8712137fdb5SSam Leffler
8722137fdb5SSam Leffler case S_SEND_ASSOC:
8732137fdb5SSam Leffler printf("Sending assoc\n");
8742137fdb5SSam Leffler send_assoc(&p);
8752137fdb5SSam Leffler p.state = S_WAIT_ASSOC;
8762137fdb5SSam Leffler if (gettimeofday(&start, NULL) == -1)
8772137fdb5SSam Leffler err(1, "gettimeofday()");
8782137fdb5SSam Leffler break;
8792137fdb5SSam Leffler
8802137fdb5SSam Leffler case S_WAIT_ASSOC:
8812137fdb5SSam Leffler if (get_assoc(&p)) {
8822137fdb5SSam Leffler printf("Associated\n");
8832137fdb5SSam Leffler p.state = S_ASSOCIATED;
8842137fdb5SSam Leffler }
8852137fdb5SSam Leffler break;
8862137fdb5SSam Leffler
8872137fdb5SSam Leffler case S_ASSOCIATED:
8882137fdb5SSam Leffler do {
8892137fdb5SSam Leffler fd_set fds;
8902137fdb5SSam Leffler int max;
8912137fdb5SSam Leffler
8922137fdb5SSam Leffler FD_ZERO(&fds);
8932137fdb5SSam Leffler FD_SET(p.rx, &fds);
8942137fdb5SSam Leffler FD_SET(p.tap, &fds);
8952137fdb5SSam Leffler max = (p.rx > p.tap) ? p.rx : p.tap;
8962137fdb5SSam Leffler
8972137fdb5SSam Leffler max = select(max+1, &fds, NULL, NULL, NULL);
8982137fdb5SSam Leffler if (max == -1)
8992137fdb5SSam Leffler err(1, "select()");
9002137fdb5SSam Leffler
9012137fdb5SSam Leffler if (FD_ISSET(p.tap, &fds)) {
9022137fdb5SSam Leffler read_tap(&p);
9032137fdb5SSam Leffler p.state = S_SEND_DATA;
9042137fdb5SSam Leffler }
9052137fdb5SSam Leffler if (FD_ISSET(p.rx, &fds)) {
9062137fdb5SSam Leffler read_wifi(&p);
9072137fdb5SSam Leffler }
9082137fdb5SSam Leffler } while(0);
9092137fdb5SSam Leffler break;
9102137fdb5SSam Leffler
9112137fdb5SSam Leffler case S_SEND_DATA:
9122137fdb5SSam Leffler send_frame(&p, p.packet, p.packet_len);
9132137fdb5SSam Leffler do {
9142137fdb5SSam Leffler struct ieee80211_frame *wh;
9152137fdb5SSam Leffler
9162137fdb5SSam Leffler wh = (struct ieee80211_frame*) p.packet;
9172137fdb5SSam Leffler wh->i_fc[1] |= IEEE80211_FC1_RETRY;
9182137fdb5SSam Leffler } while (0);
9192137fdb5SSam Leffler p.state = S_WAIT_ACK;
9202137fdb5SSam Leffler if (gettimeofday(&start, NULL) == -1)
9212137fdb5SSam Leffler err(1, "gettimeofday()");
9222137fdb5SSam Leffler break;
9232137fdb5SSam Leffler
9242137fdb5SSam Leffler case S_WAIT_ACK:
9252137fdb5SSam Leffler read_wifi(&p);
9262137fdb5SSam Leffler break;
9272137fdb5SSam Leffler
9282137fdb5SSam Leffler default:
9292137fdb5SSam Leffler printf("Unknown state %d\n", p.state);
9302137fdb5SSam Leffler abort();
9312137fdb5SSam Leffler break;
9322137fdb5SSam Leffler }
9332137fdb5SSam Leffler }
9342137fdb5SSam Leffler
9352137fdb5SSam Leffler exit(0);
9362137fdb5SSam Leffler }
937