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