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