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/types.h>
27 #include <sys/select.h>
28 #include <sys/time.h>
29 #include <sys/endian.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <err.h>
35 #include <assert.h>
36 #include "w00t.h"
37
38 struct client {
39 char mac[6];
40 int seq;
41
42 struct client *next;
43 };
44
45 struct params {
46 /* fds */
47 int tx;
48 int rx;
49 int tap;
50
51 /* ap params */
52 char mac[6];
53 char ssid[256];
54 int chan;
55
56 /* beacon */
57 int bint;
58 struct timeval blast;
59
60 int seq;
61
62 /* wep */
63 int wep_len;
64 char wep_key[13];
65 int wep_iv;
66
67 struct client *clients;
68
69 /* lame window */
70 char packet[4096];
71 int packet_len;
72 int packet_try;
73 struct timeval plast;
74 };
75
usage(char * name)76 void usage(char *name)
77 {
78 printf("Usage: %s <opts>\n"
79 "-h\thelp\n"
80 "-i\t<iface>\n"
81 "-s\t<ssid>\n"
82 "-m\t<mac>\n"
83 "-w\t<wep key>\n"
84 "-c\t<chan>\n"
85 "-t\t<tap>\n"
86 , name);
87 exit(0);
88 }
89
fill_basic(struct ieee80211_frame * wh,struct params * p)90 void fill_basic(struct ieee80211_frame *wh, struct params *p)
91 {
92 short *seq;
93
94 wh->i_dur[0] = 0x69;
95 wh->i_dur[1] = 0x00;
96
97 memcpy(wh->i_addr2, p->mac, 6);
98
99 seq = (short*)wh->i_seq;
100 *seq = seqfn(p->seq, 0);
101 }
102
send_frame(struct params * p,void * buf,int len)103 void send_frame(struct params *p, void *buf, int len)
104 {
105 int rc;
106
107 rc = inject(p->tx, buf, len);
108 if (rc == -1)
109 err(1, "inject()");
110 if (rc != len) {
111 printf("injected %d/%d\n", rc, len);
112 exit(1);
113 }
114 p->seq++;
115 }
116
fill_beacon(struct params * p,struct ieee80211_frame * wh)117 int fill_beacon(struct params *p, struct ieee80211_frame *wh)
118 {
119 int len;
120 char *ptr;
121
122 ptr = (char*) (wh+1);
123 ptr += 8; /* timestamp */
124 ptr += 2; /* bint */
125 *ptr |= IEEE80211_CAPINFO_ESS;
126 ptr += 2; /* capa */
127
128 /* ssid */
129 len = strlen(p->ssid);
130 *ptr++ = 0;
131 *ptr++ = len;
132 memcpy(ptr, p->ssid, len);
133 ptr += len;
134
135 /* rates */
136 *ptr++ = 1;
137 *ptr++ = 4;
138 *ptr++ = 2 | 0x80;
139 *ptr++ = 4 | 0x80;
140 *ptr++ = 11;
141 *ptr++ = 22;
142
143 /* ds param */
144 *ptr++ = 3;
145 *ptr++ = 1;
146 *ptr++ = p->chan;
147
148 return ptr - ((char*) wh);
149 }
150
send_beacon(struct params * p)151 void send_beacon(struct params *p)
152 {
153 char buf[4096];
154 struct ieee80211_frame *wh;
155 int len;
156 char *ptr;
157
158 wh = (struct ieee80211_frame*) buf;
159
160 memset(buf, 0, sizeof(buf));
161 fill_basic(wh, p);
162 memset(wh->i_addr1, 0xff, 6);
163 memcpy(wh->i_addr3, p->mac, 6);
164
165 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
166 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_BEACON;
167
168 len = fill_beacon(p, wh);
169
170 /* TIM */
171 ptr = (char*)wh + len;
172 *ptr++ = 5;
173 *ptr++ = 4;
174 len += 2+4;
175 #if 0
176 printf("sending beacon\n");
177 #endif
178 send_frame(p, wh, len);
179
180 if (gettimeofday(&p->blast, NULL) == -1)
181 err(1, "gettimeofday()");
182 }
183
184
send_pres(struct params * p,char * mac)185 void send_pres(struct params *p, char *mac)
186 {
187 char buf[4096];
188 struct ieee80211_frame *wh;
189 int len;
190
191 wh = (struct ieee80211_frame*) buf;
192
193 memset(buf, 0, sizeof(buf));
194 fill_basic(wh, p);
195 memcpy(wh->i_addr1, mac, 6);
196 memcpy(wh->i_addr3, p->mac, 6);
197
198 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
199 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_PROBE_RESP;
200
201 len = fill_beacon(p, wh);
202
203 printf("sending probe response\n");
204 send_frame(p, wh, len);
205 }
206
read_preq(struct params * p,struct ieee80211_frame * wh,int len)207 void read_preq(struct params *p, struct ieee80211_frame *wh, int len)
208 {
209 unsigned char *ptr;
210 unsigned char *end;
211 unsigned char macs[6*3];
212
213 ptr = (unsigned char*) (wh+1);
214
215 /* ssid */
216 if (*ptr != 0) {
217 printf("weird pr %x\n", *ptr);
218 return;
219 }
220 ptr++;
221
222 end = ptr + (*ptr) + 1;
223 *end = 0;
224 ptr++;
225
226 mac2str(macs, wh->i_addr2);
227 printf("Probe request for [%s] from %s\n", ptr, macs);
228
229 if ((strcmp(ptr, "") == 0) || (strcmp(ptr, p->ssid) == 0))
230 send_pres(p, wh->i_addr2);
231 }
232
send_auth(struct params * p,char * mac)233 void send_auth(struct params* p, char *mac)
234 {
235 char buf[4096];
236 struct ieee80211_frame *wh;
237 unsigned short *ptr;
238 int len;
239
240 wh = (struct ieee80211_frame*) buf;
241
242 memset(buf, 0, sizeof(buf));
243 fill_basic(wh, p);
244 memcpy(wh->i_addr1, mac, 6);
245 memcpy(wh->i_addr3, p->mac, 6);
246
247 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
248 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_AUTH;
249
250 ptr = (unsigned short*) (wh+1);
251 *ptr++ = htole16(0);
252 *ptr++ = htole16(2);
253 *ptr++ = htole16(0);
254
255 len = ((char*)ptr) - ((char*) wh);
256 printf("sending auth\n");
257 send_frame(p, wh, len);
258 }
259
read_auth(struct params * p,struct ieee80211_frame * wh,int len)260 void read_auth(struct params *p, struct ieee80211_frame *wh, int len)
261 {
262 unsigned short *ptr;
263 char mac[6*3];
264
265 if (memcmp(wh->i_addr1, p->mac, 6) != 0)
266 return;
267
268 ptr = (unsigned short*) (wh+1);
269 if (le16toh(*ptr) != 0) {
270 printf("Unknown auth algo %d\n", le16toh(*ptr));
271 return;
272 }
273 ptr++;
274 if (le16toh(*ptr) == 1) {
275 mac2str(mac, wh->i_addr2);
276 printf("Got auth from %s\n", mac);
277 send_auth(p, wh->i_addr2);
278 } else {
279 printf("Weird seq in auth %d\n", le16toh(*ptr));
280 }
281 }
282
send_assoc(struct params * p,char * mac)283 void send_assoc(struct params *p, char *mac)
284 {
285 char buf[4096];
286 struct ieee80211_frame *wh;
287 char *ptr;
288 int len;
289
290 wh = (struct ieee80211_frame*) buf;
291
292 memset(buf, 0, sizeof(buf));
293 fill_basic(wh, p);
294 memcpy(wh->i_addr1, mac, 6);
295 memcpy(wh->i_addr3, p->mac, 6);
296
297 wh->i_fc[0] |= IEEE80211_FC0_TYPE_MGT;
298 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_ASSOC_RESP;
299
300 ptr = (char*) (wh+1);
301 *ptr |= IEEE80211_CAPINFO_ESS;
302 ptr += 2; /* cap */
303 ptr += 2; /* status */
304 ptr += 2; /* aid */
305
306 /* rates */
307 *ptr++ = 1;
308 *ptr++ = 4;
309 *ptr++ = 2 | 0x80;
310 *ptr++ = 4 | 0x80;
311 *ptr++ = 11;
312 *ptr++ = 22;
313
314 len = ptr - ((char*) wh);
315 printf("sending assoc response\n");
316 send_frame(p, wh, len);
317 }
318
read_assoc(struct params * p,struct ieee80211_frame * wh,int len)319 void read_assoc(struct params *p, struct ieee80211_frame *wh, int len)
320 {
321 unsigned char *ptr;
322 unsigned char *end;
323 unsigned char macs[6*3];
324
325 if (memcmp(wh->i_addr1, p->mac, 6) != 0)
326 return;
327
328 ptr = (unsigned char*) (wh+1);
329 ptr += 2; /* capa */
330 ptr += 2; /* list interval */
331
332 /* ssid */
333 if (*ptr != 0) {
334 printf("weird pr %x\n", *ptr);
335 return;
336 }
337 ptr++;
338
339 end = ptr + (*ptr) + 1;
340 *end = 0;
341 ptr++;
342
343 mac2str(macs, wh->i_addr2);
344 printf("Assoc request for [%s] from %s\n", ptr, macs);
345
346 if (strcmp(ptr, p->ssid) == 0)
347 send_assoc(p, wh->i_addr2);
348 }
349
read_mgt(struct params * p,struct ieee80211_frame * wh,int len)350 void read_mgt(struct params *p, struct ieee80211_frame *wh, int len)
351 {
352 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
353 case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
354 read_preq(p, wh, len);
355 break;
356
357 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
358 break;
359
360 case IEEE80211_FC0_SUBTYPE_AUTH:
361 read_auth(p, wh, len);
362 break;
363
364 case IEEE80211_FC0_SUBTYPE_ASSOC_REQ:
365 read_assoc(p, wh, len);
366 break;
367
368 case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
369 case IEEE80211_FC0_SUBTYPE_BEACON:
370 break;
371
372 default:
373 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
374 IEEE80211_FC0_SUBTYPE_SHIFT);
375 abort();
376 break;
377 }
378 }
379
send_cts(struct params * p,char * mac)380 void send_cts(struct params *p, char *mac)
381 {
382 char buf[64];
383 struct ieee80211_frame *wh;
384
385 memset(buf, 0, sizeof(buf));
386 wh = (struct ieee80211_frame*) buf;
387 wh->i_fc[0] |= IEEE80211_FC0_TYPE_CTL;
388 wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_CTS;
389 wh->i_dur[0] = 0x69;
390 wh->i_dur[1] = 0x00;
391 memcpy(wh->i_addr1, mac, 6);
392
393 send_frame(p, wh, 10);
394 }
395
read_rts(struct params * p,struct ieee80211_frame * wh,int len)396 void read_rts(struct params *p, struct ieee80211_frame *wh, int len)
397 {
398 if (memcmp(wh->i_addr1, p->mac, 6) != 0)
399 return;
400
401 send_cts(p, wh->i_addr2);
402 }
403
read_ack(struct params * p,struct ieee80211_frame * wh,int len)404 void read_ack(struct params *p, struct ieee80211_frame *wh, int len)
405 {
406 if (memcmp(wh->i_addr1, p->mac, 6) == 0)
407 p->packet_try = 0;
408 }
409
read_ctl(struct params * p,struct ieee80211_frame * wh,int len)410 void read_ctl(struct params *p, struct ieee80211_frame *wh, int len)
411 {
412 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
413 case IEEE80211_FC0_SUBTYPE_RTS:
414 read_rts(p, wh, len);
415 break;
416
417 case IEEE80211_FC0_SUBTYPE_ACK:
418 read_ack(p, wh, len);
419 break;
420
421 case IEEE80211_FC0_SUBTYPE_CTS:
422 break;
423
424 default:
425 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
426 IEEE80211_FC0_SUBTYPE_SHIFT);
427 abort();
428 break;
429 }
430 #if 0
431 printf("ctl\n");
432 #endif
433 }
434
broadcast(struct ieee80211_frame * wh)435 int broadcast(struct ieee80211_frame *wh)
436 {
437 /* XXX multicast */
438
439 if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) == 0)
440 return 1;
441
442 return 0;
443 }
444
enque(struct params * p,struct ieee80211_frame * wh,int len)445 void enque(struct params *p, struct ieee80211_frame *wh, int len)
446 {
447 if (broadcast(wh))
448 return;
449
450 assert(sizeof(p->packet) >= len);
451
452 memcpy(p->packet, wh, len);
453 p->packet_len = len;
454 p->packet_try = 1;
455
456 wh = (struct ieee80211_frame*) p->packet;
457 wh->i_fc[1] |= IEEE80211_FC1_RETRY;
458
459 if (gettimeofday(&p->plast, NULL) == -1)
460 err(1, "gettimeofday()");
461 }
462
relay_data(struct params * p,struct ieee80211_frame * wh,int len)463 void relay_data(struct params *p, struct ieee80211_frame *wh, int len)
464 {
465 char seq[2];
466 char fc[2];
467 unsigned short *ps;
468
469 /* copy crap */
470 memcpy(fc, wh->i_fc, 2);
471 memcpy(seq, wh->i_seq, 2);
472
473 /* relay frame */
474 wh->i_fc[1] &= ~(IEEE80211_FC1_DIR_TODS | IEEE80211_FC1_RETRY);
475 wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
476 memcpy(wh->i_addr1, wh->i_addr3, sizeof(wh->i_addr1));
477 memcpy(wh->i_addr3, wh->i_addr2, sizeof(wh->i_addr3));
478 memcpy(wh->i_addr2, p->mac, sizeof(wh->i_addr2));
479 ps = (unsigned short*)wh->i_seq;
480 *ps = seqfn(p->seq, 0);
481
482 send_frame(p, wh, len);
483 enque(p, wh, len);
484
485 /* restore */
486 memcpy(wh->i_fc, fc, sizeof(fc));
487 memcpy(wh->i_addr2, wh->i_addr3, sizeof(wh->i_addr2));
488 memcpy(wh->i_addr3, wh->i_addr1, sizeof(wh->i_addr2));
489 memcpy(wh->i_addr1, p->mac, sizeof(wh->i_addr1));
490 memcpy(wh->i_seq, seq, sizeof(seq));
491 }
492
read_real_data(struct params * p,struct ieee80211_frame * wh,int len)493 void read_real_data(struct params *p, struct ieee80211_frame *wh, int len)
494 {
495 char dst[6];
496 int rc;
497 char *ptr = (char*) (wh+1);
498
499 /* stuff not for this net */
500 if (memcmp(wh->i_addr1, p->mac, 6) != 0)
501 return;
502
503 /* relay data */
504 if (memcmp(wh->i_addr3, p->mac, 6) != 0)
505 relay_data(p, wh, len);
506
507 memcpy(dst, wh->i_addr3, 6);
508
509
510 if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
511 if (!p->wep_len) {
512 printf("Got wep but i aint wep\n");
513 return;
514 }
515
516 if (wep_decrypt(wh, len, p->wep_key, p->wep_len) == -1){
517 printf("Can't decrypt\n");
518 return;
519 }
520
521 ptr += 4;
522 len -= 8;
523 }
524
525 /* ether header */
526 ptr += 8 - 2;
527 ptr -= 6;
528 memcpy(ptr, wh->i_addr2, 6);
529 ptr -= 6;
530 memcpy(ptr, dst, 6);
531
532 len -= sizeof(*wh);
533 len -= 8;
534 len += 14;
535
536 /* send to tap */
537 rc = write(p->tap, ptr, len);
538 if (rc == -1)
539 err(1, "write()");
540 if (rc != len) {
541 printf("Wrote %d/%d\n", rc, len);
542 exit(1);
543 }
544 }
545
read_data(struct params * p,struct ieee80211_frame * wh,int len)546 void read_data(struct params *p, struct ieee80211_frame *wh, int len)
547 {
548 switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
549 case IEEE80211_FC0_SUBTYPE_DATA:
550 read_real_data(p, wh, len);
551 break;
552
553 case IEEE80211_FC0_SUBTYPE_NODATA:
554 break;
555
556 default:
557 printf("wtf %d\n", (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >>
558 IEEE80211_FC0_SUBTYPE_SHIFT);
559 abort();
560 break;
561 }
562 }
563
client_find(struct params * p,char * mac)564 struct client* client_find(struct params *p, char *mac)
565 {
566 struct client* c = p->clients;
567
568 while (c) {
569 if (memcmp(c->mac, mac, 6) == 0)
570 return c;
571
572 c = c->next;
573 }
574
575 return NULL;
576 }
577
client_insert(struct params * p,struct client * c)578 void client_insert(struct params *p, struct client *c)
579 {
580 #if 1
581 do {
582 char mac[6*3];
583
584 mac2str(mac, c->mac);
585 printf("Adding client %s\n", mac);
586 } while(0);
587 #endif
588
589 c->next = p->clients;
590 p->clients = c;
591 }
592
duplicate(struct params * p,struct ieee80211_frame * wh,int rc)593 int duplicate(struct params *p, struct ieee80211_frame *wh, int rc)
594 {
595 struct client *c;
596 int s;
597
598 if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
599 IEEE80211_FC0_SUBTYPE_DATA))
600 return 0;
601
602 s = seqno(wh);
603
604 c = client_find(p, wh->i_addr2);
605 if (!c) {
606 c = malloc(sizeof(*c));
607 if (!c)
608 err(1, "malloc()");
609
610 memset(c, 0, sizeof(*c));
611 memcpy(c->mac, wh->i_addr2, 6);
612
613 c->seq = s-1;
614 client_insert(p, c);
615 }
616
617 if (wh->i_fc[1] & IEEE80211_FC1_RETRY) {
618 if ( (s <= c->seq) && ((c->seq - s ) < 5)) {
619 #if 0
620 printf("Dup seq %d prev %d\n",
621 s, c->seq);
622 #endif
623 return 1;
624 }
625 }
626
627 #if 0
628 do {
629 char mac[3*6];
630
631 mac2str(mac, c->mac);
632 printf("%s seq %d prev %d\n", mac, s, c->seq);
633 } while (0);
634 #endif
635
636 c->seq = s;
637 return 0;
638 }
639
ack(struct params * p,struct ieee80211_frame * wh)640 void ack(struct params *p, struct ieee80211_frame *wh)
641 {
642 if (memcmp(wh->i_addr1, p->mac, 6) != 0)
643 return;
644
645 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
646 return;
647
648 send_ack(p->tx, wh->i_addr2);
649 }
650
read_wifi(struct params * p)651 void read_wifi(struct params *p)
652 {
653 char buf[4096];
654 int rc;
655 struct ieee80211_frame *wh;
656
657 rc = sniff(p->rx, buf, sizeof(buf));
658 if (rc == -1)
659 err(1, "sniff()");
660
661 wh = get_wifi(buf, &rc);
662 if (!wh)
663 return;
664
665 /* filter my own shit */
666 if (memcmp(wh->i_addr2, p->mac, 6) == 0) {
667 /* XXX CTL frames */
668 if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) !=
669 IEEE80211_FC0_TYPE_CTL)
670 return;
671 }
672
673 #if 1
674 ack(p, wh);
675 #endif
676
677 if (duplicate(p, wh, rc)) {
678 #if 0
679 printf("Dup\n");
680 #endif
681 return;
682 }
683
684 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
685 case IEEE80211_FC0_TYPE_MGT:
686 read_mgt(p, wh, rc);
687 break;
688
689 case IEEE80211_FC0_TYPE_CTL:
690 read_ctl(p, wh, rc);
691 break;
692
693 case IEEE80211_FC0_TYPE_DATA:
694 read_data(p, wh, rc);
695 break;
696
697 default:
698 printf("wtf\n");
699 abort();
700 break;
701 }
702 }
703
read_tap(struct params * p)704 void read_tap(struct params *p)
705 {
706 char buf[4096];
707 char *ptr;
708 int len = sizeof(buf);
709 int offset;
710 char src[6], dst[6];
711 struct ieee80211_frame *wh;
712 int rd;
713
714 ptr = buf;
715 offset = sizeof(struct ieee80211_frame) + 8 - 14;
716 if (p->wep_len)
717 offset += 4;
718
719 ptr += offset;
720 len -= offset;
721
722 /* read packet */
723 memset(buf, 0, sizeof(buf));
724 rd = read(p->tap, ptr, len);
725 if (rd == -1)
726 err(1, "read()");
727
728 /* 802.11 header */
729 wh = (struct ieee80211_frame*) buf;
730 memcpy(dst, ptr, sizeof(dst));
731 memcpy(src, ptr+6, sizeof(src));
732 fill_basic(wh, p);
733 memcpy(wh->i_addr3, src, sizeof(wh->i_addr3));
734 memcpy(wh->i_addr1, dst, sizeof(wh->i_addr1));
735 wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
736 wh->i_fc[1] |= IEEE80211_FC1_DIR_FROMDS;
737 if (p->wep_len)
738 wh->i_fc[1] |= IEEE80211_FC1_PROTECTED;
739
740 /* LLC & SNAP */
741 ptr = (char*) (wh+1);
742 if (p->wep_len)
743 ptr += 4;
744 *ptr++ = 0xAA;
745 *ptr++ = 0xAA;
746 *ptr++ = 0x03;
747 *ptr++ = 0x00;
748 *ptr++ = 0x00;
749 *ptr++ = 0x00;
750 /* ether type overlaps w00t */
751
752 rd += offset;
753
754 /* WEP */
755 if (p->wep_len) {
756 ptr = (char*) (wh+1);
757 memcpy(ptr, &p->wep_iv, 3);
758 ptr[3] = 0;
759 p->wep_iv++;
760
761 wep_encrypt(wh, rd, p->wep_key, p->wep_len);
762 rd += 4; /* ICV */
763 }
764
765 send_frame(p, wh, rd);
766 }
767
retransmit(struct params * p)768 int retransmit(struct params *p)
769 {
770 #if 0
771 printf("RETRANS %d\n", p->packet_try);
772 #endif
773
774 send_frame(p, p->packet, p->packet_len);
775 p->packet_try++;
776
777 if (p->packet_try > 3)
778 p->packet_try = 0;
779 else {
780 if (gettimeofday(&p->plast, NULL) == -1)
781 err(1, "gettimeofday()");
782 }
783
784 return p->packet_try;
785 }
786
next_event(struct params * p)787 void next_event(struct params *p)
788 {
789 struct timeval to, now;
790 int el;
791 int max;
792 fd_set fds;
793 int rtr = 3*1000;
794
795 /* figure out select timeout */
796 if (gettimeofday(&now, NULL) == -1)
797 err(1, "gettimeofday()");
798
799 /* check beacon timeout */
800 el = elapsed(&p->blast, &now);
801 if (el >= p->bint) {
802 send_beacon(p);
803 el = 0;
804 }
805 el = p->bint - el;
806 to.tv_sec = el/1000/1000;
807 to.tv_usec = el - to.tv_sec*1000*1000;
808
809 /* check tx timeout */
810 if (p->packet_try) {
811 el = elapsed(&p->plast, &now);
812 if (el >= rtr) {
813 /* check if we gotta retransmit more */
814 if (retransmit(p)) {
815 el = 0;
816 }
817 else
818 el = -1;
819 }
820
821 /* gotta retransmit in future */
822 if (el != -1) {
823 el = rtr - el;
824 if ((to.tv_sec*1000*1000 + to.tv_usec) > el) {
825 to.tv_sec = el/1000/1000;
826 to.tv_usec = el - to.tv_sec*1000*1000;
827 }
828 }
829 }
830
831 /* select */
832 FD_ZERO(&fds);
833 FD_SET(p->rx, &fds);
834 FD_SET(p->tap, &fds);
835 max = p->rx > p->tap ? p->rx : p->tap;
836 if (select(max+1, &fds, NULL, NULL, &to) == -1)
837 err(1, "select()");
838
839 if (FD_ISSET(p->tap, &fds))
840 read_tap(p);
841 if (FD_ISSET(p->rx, &fds))
842 read_wifi(p);
843 }
844
main(int argc,char * argv[])845 int main(int argc, char *argv[])
846 {
847 char *iface = "wlan0";
848 char *tap = "tap0";
849 struct params p;
850 int ch;
851
852 /* default params */
853 memset(&p, 0, sizeof(p));
854 memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
855 strcpy(p.ssid, "sorbo");
856 p.bint = 500*1000;
857 p.seq = getpid();
858 if (gettimeofday(&p.blast, NULL) == -1)
859 err(1, "gettimeofday()");
860 p.chan = 3;
861
862 while ((ch = getopt(argc, argv, "hi:s:m:w:c:t:")) != -1) {
863 switch (ch) {
864 case 'i':
865 iface = optarg;
866 break;
867 case 't':
868 tap = optarg;
869 break;
870
871 case 'c':
872 p.chan = atoi(optarg);
873 break;
874
875 case 's':
876 strncpy(p.ssid, optarg, sizeof(p.ssid)-1);
877 p.ssid[sizeof(p.ssid)-1] = 0;
878 break;
879
880 case 'm':
881 str2mac(p.mac, optarg);
882 break;
883
884 case 'w':
885 if (str2wep(p.wep_key, &p.wep_len, optarg)) {
886 printf("Error parsing WEP key\n");
887 exit(1);
888 }
889 break;
890
891 case 'h':
892 default:
893 usage(argv[0]);
894 break;
895 }
896 }
897
898 /* init */
899 if ((p.tx = open_tx(iface)) == -1)
900 err(1, "open_tx()");
901 if ((p.rx = open_rx(iface)) == -1)
902 err(1, "open_rx()");
903
904 if ((p.tap = open_tap(tap)) == -1)
905 err(1, "open_tap()");
906 if (set_iface_mac(tap, p.mac) == -1)
907 err(1, "set_iface_mac()");
908
909 while (1) {
910 next_event(&p);
911 }
912
913 exit(0);
914 }
915