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