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