First try of the wlan-helper
[oweals/gnunet.git] / src / transport / gnunet-transport-wlan-helper.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file src/transport/gnunet-wlan.c
23  * @brief wlan layer two server; must run as root (SUID will do)
24  *        This code will work under GNU/Linux only.  
25  * @author David Brodski
26  *
27  * This program serves as the mediator between the wlan interface and
28  * gnunet 
29  */
30  
31 #include "gnunet_wlan.h"
32 #include <pcap/pcap.h>
33
34 //#include "radiotap.h"
35
36 // broadcast mac
37 static const char macbc[] = "13223344";
38
39 // mac of this node
40 char mac[] = "13223355";
41
42 /* wifi bitrate to use in 500kHz units */
43
44 static const u8 u8aRatesToUse[] = {
45
46         54*2,
47         48*2,
48         36*2,
49         24*2,
50         18*2,
51         12*2,
52         9*2,
53         11*2,
54         11, // 5.5
55         2*2,
56         1*2
57 };
58
59 /* Penumbra IEEE80211 header */
60 static const u8 u8aIeeeHeader[] = {
61         0x08, 0x01, 0x00, 0x00,
62         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63         0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
64         0x13, 0x22, 0x33, 0x44, 0x55, 0x66,
65         0x10, 0x86,
66 };
67
68 /* this is the template radiotap header we send packets out with */
69
70 static const u8 u8aRadiotapHeader[] = {
71
72         0x00, 0x00, // <-- radiotap version
73         0x19, 0x00, // <- radiotap header length
74         0x6f, 0x08, 0x00, 0x00, // <-- bitmap
75         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
76         0x00, // <-- flags (Offset +0x10)
77         0x6c, // <-- rate (0ffset +0x11)
78         0x71, 0x09, 0xc0, 0x00, // <-- channel
79         0xde, // <-- antsignal
80         0x00, // <-- antnoise
81         0x01, // <-- antenna
82
83 };
84 #define OFFSET_FLAGS 0x10
85 #define OFFSET_RATE 0x11
86
87 // this is where we store a summary of the
88 // information from the radiotap header
89
90 typedef struct  {
91         int m_nChannel;
92         int m_nChannelFlags;
93         int m_nRate;
94         int m_nAntenna;
95         int m_nRadiotapFlags;
96 } __attribute__((packed)) PENUMBRA_RADIOTAP_DATA;
97
98 void
99 Dump(u8 * pu8, int nLength)
100 {
101         char sz[256], szBuf[512], szChar[17], *buf, fFirst = 1;
102         unsigned char baaLast[2][16];
103         uint n, nPos = 0, nStart = 0, nLine = 0, nSameCount = 0;
104
105         buf = szBuf;
106         szChar[0] = '\0';
107
108         for (n = 0; n < nLength; n++) {
109                 baaLast[(nLine&1)^1][n&0xf] = pu8[n];
110                 if ((pu8[n] < 32) || (pu8[n] >= 0x7f))
111                         szChar[n&0xf] = '.';
112                 else
113                         szChar[n&0xf] = pu8[n];
114                 szChar[(n&0xf)+1] = '\0';
115                 nPos += sprintf(&sz[nPos], "%02X ",
116                         baaLast[(nLine&1)^1][n&0xf]);
117                 if ((n&15) != 15)
118                         continue;
119                 if ((memcmp(baaLast[0], baaLast[1], 16) == 0) && (!fFirst)) {
120                         nSameCount++;
121                 } else {
122                         if (nSameCount)
123                                 buf += sprintf(buf, "(repeated %d times)\n",
124                                         nSameCount);
125                         buf += sprintf(buf, "%04x: %s %s\n",
126                                 nStart, sz, szChar);
127                         nSameCount = 0;
128                         printf("%s", szBuf);
129                         buf = szBuf;
130                 }
131                 nPos = 0; nStart = n+1; nLine++;
132                 fFirst = 0; sz[0] = '\0'; szChar[0] = '\0';
133         }
134         if (nSameCount)
135                 buf += sprintf(buf, "(repeated %d times)\n", nSameCount);
136
137         buf += sprintf(buf, "%04x: %s", nStart, sz);
138         if (n & 0xf) {
139                 *buf++ = ' ';
140                 while (n & 0xf) {
141                         buf += sprintf(buf, "   ");
142                         n++;
143                 }
144         }
145         buf += sprintf(buf, "%s\n", szChar);
146         printf("%s", szBuf);
147 }
148
149
150 void
151 usage(void)
152 {
153         printf(
154             "Usage: wlan-hwd [options] <interface>\n\nOptions\n"
155             "-f/--fcs           Mark as having FCS (CRC) already\n"
156             "                   (pkt ends with 4 x sacrificial - chars)\n"
157             "Example:\n"
158             "  echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
159             "  iwconfig mon0 mode monitor\n"
160             "  ifconfig mon0 up\n"
161             "  wlan-hwd mon0        Spam down mon0 with\n"
162             "                       radiotap header first\n"
163             "\n");
164         exit(1);
165 }
166
167 int flagHelp = 0, flagMarkWithFCS = 0;
168 int flagVerbose = 0;
169
170
171 /*
172  * Radiotap parser
173  *
174  * Copyright 2007               Andy Green <andy@warmcat.com>
175  */
176
177 /**
178  * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
179  * @iterator: radiotap_iterator to initialize
180  * @radiotap_header: radiotap header to parse
181  * @max_length: total length we can parse into (eg, whole packet length)
182  *
183  * Returns: 0 or a negative error code if there is a problem.
184  *
185  * This function initializes an opaque iterator struct which can then
186  * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
187  * argument which is present in the header.  It knows about extended
188  * present headers and handles them.
189  *
190  * How to use:
191  * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
192  * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
193  * checking for a good 0 return code.  Then loop calling
194  * __ieee80211_radiotap_iterator_next()... it returns either 0,
195  * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
196  * The iterator's @this_arg member points to the start of the argument
197  * associated with the current argument index that is present, which can be
198  * found in the iterator's @this_arg_index member.  This arg index corresponds
199  * to the IEEE80211_RADIOTAP_... defines.
200  *
201  * Radiotap header length:
202  * You can find the CPU-endian total radiotap header length in
203  * iterator->max_length after executing ieee80211_radiotap_iterator_init()
204  * successfully.
205  *
206  * Example code:
207  * See Documentation/networking/radiotap-headers.txt
208  */
209
210 int ieee80211_radiotap_iterator_init(
211     struct ieee80211_radiotap_iterator *iterator,
212     struct ieee80211_radiotap_header *radiotap_header,
213     int max_length)
214 {
215         /* Linux only supports version 0 radiotap format */
216         if (radiotap_header->it_version)
217                 return -EINVAL;
218
219         /* sanity check for allowed length and radiotap length field */
220         if (max_length < le16_to_cpu(radiotap_header->it_len))
221                 return -EINVAL;
222
223         iterator->rtheader = radiotap_header;
224         iterator->max_length = le16_to_cpu(radiotap_header->it_len);
225         iterator->arg_index = 0;
226         iterator->bitmap_shifter = le32_to_cpu(radiotap_header->it_present);
227         iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
228         iterator->this_arg = 0;
229
230         /* find payload start allowing for extended bitmap(s) */
231
232         if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
233                 while (le32_to_cpu(*((u32 *)iterator->arg)) &
234                                    (1<<IEEE80211_RADIOTAP_EXT)) {
235                         iterator->arg += sizeof(u32);
236
237                         /*
238                          * check for insanity where the present bitmaps
239                          * keep claiming to extend up to or even beyond the
240                          * stated radiotap header length
241                          */
242
243                         if (((ulong)iterator->arg -
244                              (ulong)iterator->rtheader) > iterator->max_length)
245                                 return -EINVAL;
246                 }
247
248                 iterator->arg += sizeof(u32);
249
250                 /*
251                  * no need to check again for blowing past stated radiotap
252                  * header length, because ieee80211_radiotap_iterator_next
253                  * checks it before it is dereferenced
254                  */
255         }
256
257         /* we are all initialized happily */
258
259         return 0;
260 }
261
262
263 /**
264  * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
265  * @iterator: radiotap_iterator to move to next arg (if any)
266  *
267  * Returns: 0 if there is an argument to handle,
268  * -ENOENT if there are no more args or -EINVAL
269  * if there is something else wrong.
270  *
271  * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
272  * in @this_arg_index and sets @this_arg to point to the
273  * payload for the field.  It takes care of alignment handling and extended
274  * present fields.  @this_arg can be changed by the caller (eg,
275  * incremented to move inside a compound argument like
276  * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
277  * little-endian format whatever the endianess of your CPU.
278  */
279
280 int ieee80211_radiotap_iterator_next(
281     struct ieee80211_radiotap_iterator *iterator)
282 {
283
284         /*
285          * small length lookup table for all radiotap types we heard of
286          * starting from b0 in the bitmap, so we can walk the payload
287          * area of the radiotap header
288          *
289          * There is a requirement to pad args, so that args
290          * of a given length must begin at a boundary of that length
291          * -- but note that compound args are allowed (eg, 2 x u16
292          * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
293          * a reliable indicator of alignment requirement.
294          *
295          * upper nybble: content alignment for arg
296          * lower nybble: content length for arg
297          */
298
299         static const u8 rt_sizes[] = {
300                 [IEEE80211_RADIOTAP_TSFT] = 0x88,
301                 [IEEE80211_RADIOTAP_FLAGS] = 0x11,
302                 [IEEE80211_RADIOTAP_RATE] = 0x11,
303                 [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
304                 [IEEE80211_RADIOTAP_FHSS] = 0x22,
305                 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
306                 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
307                 [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
308                 [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
309                 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
310                 [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
311                 [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
312                 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
313                 [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11
314                 /*
315                  * add more here as they are defined in
316                  * include/net/ieee80211_radiotap.h
317                  */
318         };
319
320         /*
321          * for every radiotap entry we can at
322          * least skip (by knowing the length)...
323          */
324
325         while (iterator->arg_index < sizeof(rt_sizes)) {
326                 int hit = 0;
327                 int pad;
328
329                 if (!(iterator->bitmap_shifter & 1))
330                         goto next_entry; /* arg not present */
331
332                 /*
333                  * arg is present, account for alignment padding
334                  *  8-bit args can be at any alignment
335                  * 16-bit args must start on 16-bit boundary
336                  * 32-bit args must start on 32-bit boundary
337                  * 64-bit args must start on 64-bit boundary
338                  *
339                  * note that total arg size can differ from alignment of
340                  * elements inside arg, so we use upper nybble of length
341                  * table to base alignment on
342                  *
343                  * also note: these alignments are ** relative to the
344                  * start of the radiotap header **.  There is no guarantee
345                  * that the radiotap header itself is aligned on any
346                  * kind of boundary.
347                  */
348
349                 pad = (((ulong)iterator->arg) -
350                         ((ulong)iterator->rtheader)) &
351                         ((rt_sizes[iterator->arg_index] >> 4) - 1);
352
353                 if (pad)
354                         iterator->arg_index +=
355                                 (rt_sizes[iterator->arg_index] >> 4) - pad;
356
357                 /*
358                  * this is what we will return to user, but we need to
359                  * move on first so next call has something fresh to test
360                  */
361                 iterator->this_arg_index = iterator->arg_index;
362                 iterator->this_arg = iterator->arg;
363                 hit = 1;
364
365                 /* internally move on the size of this arg */
366                 iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
367
368                 /*
369                  * check for insanity where we are given a bitmap that
370                  * claims to have more arg content than the length of the
371                  * radiotap section.  We will normally end up equalling this
372                  * max_length on the last arg, never exceeding it.
373                  */
374
375                 if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
376                     iterator->max_length)
377                         return -EINVAL;
378
379         next_entry:
380                 iterator->arg_index++;
381                 if (unlikely((iterator->arg_index & 31) == 0)) {
382                         /* completed current u32 bitmap */
383                         if (iterator->bitmap_shifter & 1) {
384                                 /* b31 was set, there is more */
385                                 /* move to next u32 bitmap */
386                                 iterator->bitmap_shifter =
387                                     le32_to_cpu(*iterator->next_bitmap);
388                                 iterator->next_bitmap++;
389                         } else {
390                                 /* no more bitmaps: end */
391                                 iterator->arg_index = sizeof(rt_sizes);
392                         }
393                 } else { /* just try the next bit */
394                         iterator->bitmap_shifter >>= 1;
395                 }
396
397                 /* if we found a valid arg earlier, return it now */
398                 if (hit)
399                         return 0;
400         }
401
402         /* we don't know how to handle any more args, we're done */
403         return -ENOENT;
404 }
405
406
407
408 int
409 main(int argc, char *argv[])
410 {
411         u8 u8aSendBuffer[500];
412         char szErrbuf[PCAP_ERRBUF_SIZE];
413         int nCaptureHeaderLength = 0, n80211HeaderLength = 0, nLinkEncap = 0;
414         int nOrdinal = 0, r, nDelay = 100000;
415         int nRateIndex = 0, retval, bytes;
416         pcap_t *ppcap = NULL;
417         struct bpf_program bpfprogram;
418         char * szProgram = "", fBrokenSocket = 0;
419         u16 u16HeaderLen;
420         char szHostname[PATH_MAX];
421
422         if (gethostname(szHostname, sizeof (szHostname) - 1)) {
423                 perror("unable to get hostname");
424         }
425         szHostname[sizeof (szHostname) - 1] = '\0';
426
427
428         printf("Packetspammer (c)2007 Andy Green <andy@warmcat.com>  GPL2\n");
429
430         while (1) {
431                 int nOptionIndex;
432                 static const struct option optiona[] = {
433                         { "delay", required_argument, NULL, 'd' },
434                         { "fcs", no_argument, &flagMarkWithFCS, 1 },
435                         { "help", no_argument, &flagHelp, 1 },
436                         { "verbose", no_argument, &flagVerbose, 1},
437                         { 0, 0, 0, 0 }
438                 };
439                 int c = getopt_long(argc, argv, "d:hf",
440                         optiona, &nOptionIndex);
441
442                 if (c == -1)
443                         break;
444                 switch (c) {
445                 case 0: // long option
446                         break;
447
448                 case 'h': // help
449                         usage();
450
451                 case 'd': // delay
452                         nDelay = atoi(optarg);
453                         break;
454
455                 case 'f': // mark as FCS attached
456                         flagMarkWithFCS = 1;
457                         break;
458
459                 case 'v': //Verbose / readable output to cout
460                         flagVerbose = 1;
461                         break;
462
463                 default:
464                         printf("unknown switch %c\n", c);
465                         usage();
466                         break;
467                 }
468         }
469
470         if (optind >= argc)
471                 usage();
472
473
474                 // open the interface in pcap
475
476         szErrbuf[0] = '\0';
477         ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
478         if (ppcap == NULL) {
479                 printf("Unable to open interface %s in pcap: %s\n",
480                     argv[optind], szErrbuf);
481                 return (1);
482         }
483
484         //get mac from interface
485
486         /*int sock, j, k;
487         char mac[32];
488
489         sock=socket(PF_INET, SOCK_STREAM, 0);
490         if (-1==sock) {
491                 perror("can not open socket\n");
492                 return 1;
493         }
494
495         if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
496                 perror("ioctl(SIOCGIFHWADDR) ");
497                 return 1;
498         }
499         for (j=0, k=0; j<6; j++) {
500                 k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X",
501                         (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
502         }
503         mac[sizeof(mac)-1]='\0';
504         */
505
506         //get header type
507         nLinkEncap = pcap_datalink(ppcap);
508         nCaptureHeaderLength = 0;
509
510         switch (nLinkEncap) {
511
512                 case DLT_PRISM_HEADER:
513                         printf("DLT_PRISM_HEADER Encap\n");
514                         nCaptureHeaderLength = 0x40;
515                         n80211HeaderLength = 0x20; // ieee80211 comes after this
516                         szProgram = "radio[0x4a:4]==0x13223344";
517                         break;
518
519                 case DLT_IEEE802_11_RADIO:
520                         printf("DLT_IEEE802_11_RADIO Encap\n");
521                         nCaptureHeaderLength = 0x40;
522                         n80211HeaderLength = 0x18; // ieee80211 comes after this
523                         szProgram = "ether[0x0a:4]==0x13223344";
524                         break;
525
526                 default:
527                         printf("!!! unknown encapsulation on %s !\n", argv[1]);
528                         return (1);
529
530         }
531
532         if (pcap_compile(ppcap, &bpfprogram, szProgram, 1, 0) == -1) {
533                 puts(szProgram);
534                 puts(pcap_geterr(ppcap));
535                 return (1);
536         } else {
537                 if (pcap_setfilter(ppcap, &bpfprogram) == -1) {
538                         puts(szProgram);
539                         puts(pcap_geterr(ppcap));
540                 } else {
541                         printf("RX Filter applied\n");
542                 }
543                 pcap_freecode(&bpfprogram);
544         }
545
546         pcap_setnonblock(ppcap, 1, szErrbuf);
547
548         printf("   (delay between packets %dus)\n", nDelay);
549
550         memset(u8aSendBuffer, 0, sizeof (u8aSendBuffer));
551
552         while (!fBrokenSocket) {
553                 u8 * pu8 = u8aSendBuffer;
554                 struct pcap_pkthdr * ppcapPacketHeader = NULL;
555                 struct ieee80211_radiotap_iterator rti;
556                 PENUMBRA_RADIOTAP_DATA prd;
557                 u8 * pu8Payload = u8aSendBuffer;
558                 int n, nRate;
559
560                 // receive
561
562                 retval = pcap_next_ex(ppcap, &ppcapPacketHeader,
563                     (const u_char**)&pu8Payload);
564
565                 if (retval < 0) {
566                         fBrokenSocket = 1;
567                         continue;
568                 }
569
570                 if (retval != 1)
571                         goto do_tx;
572
573                 u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8));
574
575                 printf("rtap: ");
576                 Dump(pu8Payload, u16HeaderLen);
577
578                 if (ppcapPacketHeader->len <
579                     (u16HeaderLen + n80211HeaderLength))
580                         continue;
581
582                 bytes = ppcapPacketHeader->len -
583                         (u16HeaderLen + n80211HeaderLength);
584                 if (bytes < 0)
585                         continue;
586
587                 if (ieee80211_radiotap_iterator_init(&rti,
588                     (struct ieee80211_radiotap_header *)pu8Payload,
589                     bytes) < 0)
590                         continue;
591
592                 while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) {
593
594                         switch (rti.this_arg_index) {
595                         case IEEE80211_RADIOTAP_RATE:
596                                 prd.m_nRate = (*rti.this_arg);
597                                 break;
598
599                         case IEEE80211_RADIOTAP_CHANNEL:
600                                 prd.m_nChannel =
601                                     le16_to_cpu(*((u16 *)rti.this_arg));
602                                 prd.m_nChannelFlags =
603                                     le16_to_cpu(*((u16 *)(rti.this_arg + 2)));
604                                 break;
605
606                         case IEEE80211_RADIOTAP_ANTENNA:
607                                 prd.m_nAntenna = (*rti.this_arg) + 1;
608                                 break;
609
610                         case IEEE80211_RADIOTAP_FLAGS:
611                                 prd.m_nRadiotapFlags = *rti.this_arg;
612                                 break;
613
614                         }
615                 }
616
617                 pu8Payload += u16HeaderLen + n80211HeaderLength;
618
619                 if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
620                         bytes -= 4;
621
622                 printf("RX: Rate: %2d.%dMbps, Freq: %d.%dGHz, "
623                     "Ant: %d, Flags: 0x%X\n",
624                     prd.m_nRate / 2, 5 * (prd.m_nRate & 1),
625                     prd.m_nChannel / 1000,
626                     prd.m_nChannel - ((prd.m_nChannel / 1000) * 1000),
627                     prd.m_nAntenna,
628                     prd.m_nRadiotapFlags);
629
630                 Dump(pu8Payload, bytes);
631
632         do_tx:
633
634                 // transmit
635
636                 memcpy(u8aSendBuffer, u8aRadiotapHeader,
637                         sizeof (u8aRadiotapHeader));
638                 if (flagMarkWithFCS)
639                         pu8[OFFSET_FLAGS] |= IEEE80211_RADIOTAP_F_FCS;
640                 nRate = pu8[OFFSET_RATE] = u8aRatesToUse[nRateIndex++];
641                 if (nRateIndex >= sizeof (u8aRatesToUse))
642                         nRateIndex = 0;
643                 pu8 += sizeof (u8aRadiotapHeader);
644
645                 memcpy(pu8, u8aIeeeHeader, sizeof (u8aIeeeHeader));
646                 pu8 += sizeof (u8aIeeeHeader);
647
648                 pu8 += sprintf((char *)pu8,
649                     "Packetspammer %02d"
650                     "broadcast packet"
651                     "#%05d -- :-D --%s ----",
652                     nRate/2, nOrdinal++, szHostname);
653                 r = pcap_inject(ppcap, u8aSendBuffer, pu8 - u8aSendBuffer);
654                 if (r != (pu8-u8aSendBuffer)) {
655                         perror("Trouble injecting packet");
656                         return (1);
657                 }
658                 if (nDelay)
659                         usleep(nDelay);
660         }
661
662
663
664         return (0);
665 }