1160996Ssam/*-
2160996Ssam * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3160996Ssam * All rights reserved.
4160996Ssam *
5160996Ssam * Redistribution and use in source and binary forms, with or without
6160996Ssam * modification, are permitted provided that the following conditions
7160996Ssam * are met:
8160996Ssam * 1. Redistributions of source code must retain the above copyright
9160996Ssam *    notice, this list of conditions and the following disclaimer.
10160996Ssam * 2. Redistributions in binary form must reproduce the above copyright
11160996Ssam *    notice, this list of conditions and the following disclaimer in the
12160996Ssam *    documentation and/or other materials provided with the distribution.
13160996Ssam *
14160996Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15160996Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16160996Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17160996Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18160996Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19160996Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20160996Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21160996Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22160996Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23160996Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24160996Ssam * SUCH DAMAGE.
25160996Ssam *
26160996Ssam * $FreeBSD$
27160996Ssam */
28160996Ssam#include <stdio.h>
29160996Ssam#include <assert.h>
30160996Ssam#include <fcntl.h>
31160996Ssam#include <errno.h>
32160996Ssam#include <sys/socket.h>
33160996Ssam#include <sys/types.h>
34160996Ssam#include <sys/endian.h>
35160996Ssam#include <sys/uio.h>
36160996Ssam#include <unistd.h>
37160996Ssam#include <net/if.h>
38160996Ssam#include <string.h>
39160996Ssam#include <sys/ioctl.h>
40160996Ssam#include <net/bpf.h>
41160996Ssam#include <net80211/ieee80211_radiotap.h>
42160996Ssam#include <net80211/ieee80211.h>
43160996Ssam#include <openssl/rc4.h>
44160996Ssam#include <zlib.h>
45160996Ssam#include "w00t.h"
46160996Ssam
47160996Ssamint str2mac(char *mac, char *str)
48160996Ssam{
49160996Ssam	unsigned int macf[6];
50160996Ssam	int i;
51160996Ssam
52160996Ssam	if (sscanf(str, "%x:%x:%x:%x:%x:%x",
53160996Ssam		   &macf[0], &macf[1], &macf[2],
54160996Ssam		   &macf[3], &macf[4], &macf[5]) != 6)
55160996Ssam		return -1;
56160996Ssam
57160996Ssam	for (i = 0; i < 6; i++)
58160996Ssam		*mac++ = (char) macf[i];
59160996Ssam
60160996Ssam	return 0;
61160996Ssam}
62160996Ssam
63160996Ssamvoid mac2str(char *str, char* m)
64160996Ssam{
65160996Ssam	unsigned char *mac = m;
66160996Ssam	sprintf(str, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
67160996Ssam		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
68160996Ssam}
69160996Ssam
70160996Ssamshort seqfn(unsigned short seq, unsigned short fn)
71160996Ssam{
72160996Ssam	unsigned short r = 0;
73160996Ssam
74160996Ssam	assert(fn < 16);
75160996Ssam
76160996Ssam	r = fn;
77160996Ssam	r |=  ( (seq % 4096) << IEEE80211_SEQ_SEQ_SHIFT);
78160996Ssam	return r;
79160996Ssam}
80160996Ssam
81160996Ssamunsigned short seqno(struct ieee80211_frame *wh)
82160996Ssam{
83160996Ssam	unsigned short *s = (unsigned short*) wh->i_seq;
84160996Ssam
85160996Ssam	return (*s & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
86160996Ssam}
87160996Ssam
88160996Ssamint open_bpf(char *dev, int dlt)
89160996Ssam{
90160996Ssam	int i;
91160996Ssam	char buf[64];
92160996Ssam	int fd = -1;
93160996Ssam	struct ifreq ifr;
94160996Ssam
95160996Ssam	for(i = 0;i < 16; i++) {
96160996Ssam		sprintf(buf, "/dev/bpf%d", i);
97160996Ssam
98160996Ssam		fd = open(buf, O_RDWR);
99160996Ssam		if(fd == -1) {
100160996Ssam			if(errno != EBUSY)
101160996Ssam				return -1;
102160996Ssam			continue;
103160996Ssam		}
104160996Ssam		else
105160996Ssam			break;
106160996Ssam	}
107160996Ssam
108160996Ssam	if(fd == -1)
109160996Ssam		return -1;
110160996Ssam
111160996Ssam	strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
112160996Ssam	ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
113160996Ssam
114160996Ssam	if(ioctl(fd, BIOCSETIF, &ifr) < 0)
115160996Ssam		return -1;
116160996Ssam
117160996Ssam	if (ioctl(fd, BIOCSDLT, &dlt) < 0)
118160996Ssam		return -1;
119160996Ssam
120160996Ssam	i = 1;
121160996Ssam	if (ioctl(fd, BIOCIMMEDIATE, &i) < 0)
122160996Ssam		return -1;
123160996Ssam
124160996Ssam	return fd;
125160996Ssam}
126160996Ssam
127160996Ssamint open_tx(char *iface)
128160996Ssam{
129160996Ssam	return open_bpf(iface, DLT_IEEE802_11_RADIO);
130160996Ssam}
131160996Ssam
132160996Ssamint open_rx(char *iface)
133160996Ssam{
134160996Ssam	return open_bpf(iface, DLT_IEEE802_11_RADIO);
135160996Ssam}
136160996Ssam
137160996Ssamint open_rxtx(char *iface, int *rx, int *tx)
138160996Ssam{
139160996Ssam	*rx = open_bpf(iface, DLT_IEEE802_11_RADIO);
140160996Ssam	*tx = *rx;
141160996Ssam
142160996Ssam	return *rx;
143160996Ssam}
144160996Ssam
145160996Ssamint inject(int fd, void *buf, int len)
146160996Ssam{
147160996Ssam	return inject_params(fd, buf, len, NULL);
148160996Ssam}
149160996Ssam
150160996Ssamint inject_params(int fd, void *buf, int len,
151160996Ssam		  struct ieee80211_bpf_params *params)
152160996Ssam{
153160996Ssam	static struct ieee80211_bpf_params defaults = {
154160996Ssam		.ibp_vers = IEEE80211_BPF_VERSION,
155160996Ssam		/* NB: no need to pass series 2-4 rate+try */
156160996Ssam		.ibp_len = sizeof(struct ieee80211_bpf_params) - 6,
157161029Ssam		.ibp_rate0 = 2,		/* 1 MB/s XXX */
158161029Ssam		.ibp_try0 = 1,		/* no retransmits */
159160996Ssam		.ibp_flags = IEEE80211_BPF_NOACK,
160160996Ssam		.ibp_power = 100,	/* nominal max */
161160996Ssam		.ibp_pri = WME_AC_VO,	/* high priority */
162160996Ssam	};
163160996Ssam	struct iovec iov[2];
164160996Ssam	int rc;
165160996Ssam
166160996Ssam	if (params == NULL)
167160996Ssam		params = &defaults;
168160996Ssam	iov[0].iov_base = params;
169160996Ssam	iov[0].iov_len = params->ibp_len;
170160996Ssam	iov[1].iov_base = buf;
171160996Ssam	iov[1].iov_len = len;
172160996Ssam
173160996Ssam	rc = writev(fd, iov, 2);
174160996Ssam	if (rc == -1)
175160996Ssam		return rc;
176160996Ssam
177160996Ssam	rc -= iov[0].iov_len; /* XXX could be negative */
178160996Ssam	return rc;
179160996Ssam}
180160996Ssam
181160996Ssamint sniff(int fd, void *buf, int len)
182160996Ssam{
183160996Ssam	return read(fd, buf, len);
184160996Ssam}
185160996Ssam
186160996Ssamvoid *get_wifi(void *buf, int *len)
187160996Ssam{
188160996Ssam#define	BIT(n)	(1<<(n))
189160996Ssam	struct bpf_hdr* bpfh = (struct bpf_hdr*) buf;
190160996Ssam	struct ieee80211_radiotap_header* rth;
191160996Ssam	uint32_t present;
192160996Ssam	uint8_t rflags;
193160996Ssam	void *ptr;
194160996Ssam
195160996Ssam	/* bpf */
196160996Ssam	*len -= bpfh->bh_hdrlen;
197160996Ssam
198160996Ssam	if (bpfh->bh_caplen != *len) {
199160996Ssam		assert(bpfh->bh_caplen < *len);
200160996Ssam		*len = bpfh->bh_caplen;
201160996Ssam	}
202160996Ssam	assert(bpfh->bh_caplen == *len);
203160996Ssam
204160996Ssam	/* radiotap */
205160996Ssam	rth = (struct ieee80211_radiotap_header*)
206160996Ssam	      ((char*)bpfh + bpfh->bh_hdrlen);
207160996Ssam	/* XXX cache; drivers won't change this per-packet */
208160996Ssam	/* check if FCS/CRC is included in packet */
209160996Ssam	present = le32toh(rth->it_present);
210160996Ssam	if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) {
211160996Ssam		if (present & BIT(IEEE80211_RADIOTAP_TSFT))
212160996Ssam			rflags = ((const uint8_t *)rth)[8];
213160996Ssam		else
214160996Ssam			rflags = ((const uint8_t *)rth)[0];
215160996Ssam	} else
216160996Ssam		rflags = 0;
217160996Ssam	*len -= rth->it_len;
218160996Ssam
219160996Ssam	/* 802.11 CRC */
220160996Ssam	if (rflags & IEEE80211_RADIOTAP_F_FCS)
221160996Ssam		*len -= IEEE80211_CRC_LEN;
222160996Ssam
223160996Ssam	ptr = (char*)rth + rth->it_len;
224160996Ssam	return ptr;
225160996Ssam#undef BIT
226160996Ssam}
227160996Ssam
228160996Ssamint send_ack(int fd, char *mac)
229160996Ssam{
230160996Ssam	static char buf[2+2+6];
231160996Ssam	static char *p = 0;
232160996Ssam	int rc;
233160996Ssam
234160996Ssam	if (!p) {
235160996Ssam		memset(buf, 0, sizeof(buf));
236160996Ssam		buf[0] |= IEEE80211_FC0_TYPE_CTL | IEEE80211_FC0_SUBTYPE_ACK;
237160996Ssam		p = &buf[4];
238160996Ssam	}
239160996Ssam
240160996Ssam	memcpy(p, mac, 6);
241160996Ssam
242160996Ssam	rc = inject(fd, buf, sizeof(buf));
243160996Ssam	return rc;
244160996Ssam}
245160996Ssam
246160996Ssamint open_tap(char *iface)
247160996Ssam{
248160996Ssam	char buf[64];
249160996Ssam
250160996Ssam	snprintf(buf, sizeof(buf), "/dev/%s", iface);
251160996Ssam	return open(buf, O_RDWR);
252160996Ssam}
253160996Ssam
254160996Ssamint set_iface_mac(char *iface, char *mac)
255160996Ssam{
256160996Ssam	int s, rc;
257160996Ssam	struct ifreq ifr;
258160996Ssam
259160996Ssam	s = socket(PF_INET, SOCK_DGRAM, 0);
260160996Ssam	if (s == -1)
261160996Ssam		return -1;
262160996Ssam
263160996Ssam	memset(&ifr, 0, sizeof(ifr));
264160996Ssam	strcpy(ifr.ifr_name, iface);
265160996Ssam
266160996Ssam	ifr.ifr_addr.sa_family = AF_LINK;
267160996Ssam	ifr.ifr_addr.sa_len = 6;
268160996Ssam	memcpy(ifr.ifr_addr.sa_data, mac, 6);
269160996Ssam
270160996Ssam	rc = ioctl(s, SIOCSIFLLADDR, &ifr);
271160996Ssam
272160996Ssam	close(s);
273160996Ssam
274160996Ssam	return rc;
275160996Ssam}
276160996Ssam
277160996Ssamint str2wep(char *wep, int *len, char *str)
278160996Ssam{
279160996Ssam	int klen;
280160996Ssam
281160996Ssam	klen = strlen(str);
282160996Ssam	if (klen % 2)
283160996Ssam		return -1;
284160996Ssam	klen /= 2;
285160996Ssam
286160996Ssam	if (klen != 5 && klen != 13)
287160996Ssam		return -1;
288160996Ssam
289160996Ssam	*len = klen;
290160996Ssam
291160996Ssam	while (klen--) {
292160996Ssam		unsigned int x;
293160996Ssam
294160996Ssam		if (sscanf(str, "%2x", &x) != 1)
295160996Ssam			return -1;
296160996Ssam
297160996Ssam		*wep = (unsigned char) x;
298160996Ssam		wep++;
299160996Ssam		str += 2;
300160996Ssam	}
301160996Ssam
302160996Ssam	return 0;
303160996Ssam}
304160996Ssam
305160996Ssamint wep_decrypt(struct ieee80211_frame *wh, int len, char *key, int klen)
306160996Ssam{
307160996Ssam	RC4_KEY k;
308160996Ssam	char seed[64];
309160996Ssam	char *p = (char*) (wh+1);
310160996Ssam	uLong crc = crc32(0L, Z_NULL, 0);
311160996Ssam	uLong *pcrc;
312160996Ssam
313160996Ssam	assert(sizeof(seed) >= klen + 3);
314160996Ssam	memcpy(seed, p, 3);
315160996Ssam	memcpy(&seed[3], key, klen);
316160996Ssam
317160996Ssam	RC4_set_key(&k, klen+3, seed);
318160996Ssam
319160996Ssam	len -= sizeof(*wh);
320160996Ssam	len -= 4;
321160996Ssam	p += 4;
322160996Ssam	RC4(&k, len, p, p);
323160996Ssam
324160996Ssam	crc = crc32(crc, p, len - 4);
325160996Ssam	pcrc = (uLong*) (p+len-4);
326160996Ssam
327160996Ssam	if (*pcrc == crc)
328160996Ssam		return 0;
329160996Ssam
330160996Ssam	return -1;
331160996Ssam}
332160996Ssam
333160996Ssamvoid wep_encrypt(struct ieee80211_frame *wh, int len, char *key, int klen)
334160996Ssam{
335160996Ssam	RC4_KEY k;
336160996Ssam	char seed[64];
337160996Ssam	char *p = (char*) (wh+1);
338160996Ssam	uLong crc = crc32(0L, Z_NULL, 0);
339160996Ssam	uLong *pcrc;
340160996Ssam
341160996Ssam	assert(sizeof(seed) >= klen + 3);
342160996Ssam	memcpy(seed, p, 3);
343160996Ssam	memcpy(&seed[3], key, klen);
344160996Ssam
345160996Ssam	RC4_set_key(&k, klen+3, seed);
346160996Ssam
347160996Ssam	len -= sizeof(*wh);
348160996Ssam	p += 4;
349160996Ssam	crc = crc32(crc, p, len - 4);
350160996Ssam	pcrc = (uLong*) (p+len-4);
351160996Ssam	*pcrc = crc;
352160996Ssam
353160996Ssam	RC4(&k, len, p, p);
354160996Ssam}
355160996Ssam
356160996Ssamint frame_type(struct ieee80211_frame *wh, int type, int stype)
357160996Ssam{
358160996Ssam        if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != type)
359160996Ssam                return 0;
360160996Ssam
361160996Ssam        if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) != stype)
362160996Ssam                return 0;
363160996Ssam
364160996Ssam        return 1;
365160996Ssam}
366160996Ssam
367160996Ssamvoid hexdump(void *b, int len)
368160996Ssam{
369160996Ssam	unsigned char *p = (unsigned char*) b;
370160996Ssam
371160996Ssam	while (len--)
372160996Ssam		printf("%.2X ", *p++);
373160996Ssam	printf("\n");
374160996Ssam}
375160996Ssam
376160996Ssamint elapsed(struct timeval *past, struct timeval *now)
377160996Ssam{
378160996Ssam        int el;
379160996Ssam
380160996Ssam        el = now->tv_sec - past->tv_sec;
381160996Ssam        assert(el >= 0);
382160996Ssam        if (el == 0) {
383160996Ssam                el = now->tv_usec - past->tv_usec;
384160996Ssam        } else {
385160996Ssam                el = (el - 1)*1000*1000;
386160996Ssam                el += 1000*1000-past->tv_usec;
387160996Ssam                el += now->tv_usec;
388160996Ssam        }
389160996Ssam
390160996Ssam        return el;
391160996Ssam}
392160996Ssam
393160996Ssamstatic int is_arp(struct ieee80211_frame *wh, int len)
394160996Ssam{
395160996Ssam        /* XXX */
396160996Ssam        if (len > (sizeof(*wh) + 4 + 4 + 39))
397160996Ssam                return 0;
398160996Ssam
399160996Ssam        return 1;
400160996Ssam}
401160996Ssam
402160996Ssamchar *known_pt(struct ieee80211_frame *wh, int *len)
403160996Ssam{
404160996Ssam	static char *known_pt_arp = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
405160996Ssam	static char *known_pt_ip = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
406160996Ssam	int arp;
407160996Ssam
408160996Ssam	arp = is_arp(wh, *len);
409160996Ssam	*len = 8;
410160996Ssam	if (arp)
411160996Ssam		return known_pt_arp;
412160996Ssam	else
413160996Ssam		return known_pt_ip;
414160996Ssam}
415