aboutsummaryrefslogtreecommitdiff
path: root/src/transport/gnunet-transport-wlan-helper.c
diff options
context:
space:
mode:
authorDavid Brodski <david@brodski.eu>2010-07-28 08:01:56 +0000
committerDavid Brodski <david@brodski.eu>2010-07-28 08:01:56 +0000
commitd4a051f87d9d420ec474d0c15c27d94d8ebe264b (patch)
treedd2c4950e65657865d28c6e58fb440dcb6361d63 /src/transport/gnunet-transport-wlan-helper.c
parent2b2f0a8c002b5c0946cccbdd6bf0012e4f1ad8e2 (diff)
downloadgnunet-d4a051f87d9d420ec474d0c15c27d94d8ebe264b.tar.gz
gnunet-d4a051f87d9d420ec474d0c15c27d94d8ebe264b.zip
First try of the wlan-helper
Diffstat (limited to 'src/transport/gnunet-transport-wlan-helper.c')
-rw-r--r--src/transport/gnunet-transport-wlan-helper.c665
1 files changed, 665 insertions, 0 deletions
diff --git a/src/transport/gnunet-transport-wlan-helper.c b/src/transport/gnunet-transport-wlan-helper.c
new file mode 100644
index 000000000..6ae31a647
--- /dev/null
+++ b/src/transport/gnunet-transport-wlan-helper.c
@@ -0,0 +1,665 @@
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
37static const char macbc[] = "13223344";
38
39// mac of this node
40char mac[] = "13223355";
41
42/* wifi bitrate to use in 500kHz units */
43
44static 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 */
60static 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
70static 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
90typedef 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
98void
99Dump(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
150void
151usage(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
167int flagHelp = 0, flagMarkWithFCS = 0;
168int 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
210int 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
280int 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
408int
409main(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}