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