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