2 This file is part of GNUnet.
3 (C) 2010 Christian Grothoff (and other contributing authors)
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.
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.
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.
22 * @file src/transport/gnunet-transport-wlan-helper.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
27 * This program serves as the mediator between the wlan interface and
33 #include "gnunet_constants.h"
34 #include "gnunet_os_lib.h"
35 #include "gnunet_transport_plugin.h"
36 #include "transport.h"
37 #include "gnunet_util_lib.h"
38 #include "plugin_transport_wlan.h"
39 #include "gnunet_common.h"
40 #include "gnunet-transport-wlan-helper.h"
41 #include "gnunet_crypto_lib.h"
42 #include "ieee80211_radiotap.h"
52 //#include "radiotap.h"
56 { 0x13, 0x22, 0x33, 0x44, 0x55, 0x66 };
58 /* wifi bitrate to use in 500kHz units */
60 static const u8 u8aRatesToUse[] = {
75 #define OFFSET_FLAGS 0x10
76 #define OFFSET_RATE 0x11
78 // this is where we store a summary of the
79 // information from the radiotap header
87 } __attribute__((packed)) PENUMBRA_RADIOTAP_DATA;
90 Dump(u8 * pu8, int nLength)
92 char sz[256], szBuf[512], szChar[17], *buf, fFirst = 1;
93 unsigned char baaLast[2][16];
94 uint n, nPos = 0, nStart = 0, nLine = 0, nSameCount = 0;
99 for (n = 0; n < nLength; n++) {
100 baaLast[(nLine&1)^1][n&0xf] = pu8[n];
101 if ((pu8[n] < 32) || (pu8[n] >= 0x7f))
104 szChar[n&0xf] = pu8[n];
105 szChar[(n&0xf)+1] = '\0';
106 nPos += sprintf(&sz[nPos], "%02X ",
107 baaLast[(nLine&1)^1][n&0xf]);
110 if ((memcmp(baaLast[0], baaLast[1], 16) == 0) && (!fFirst)) {
114 buf += sprintf(buf, "(repeated %d times)\n",
116 buf += sprintf(buf, "%04x: %s %s\n",
122 nPos = 0; nStart = n+1; nLine++;
123 fFirst = 0; sz[0] = '\0'; szChar[0] = '\0';
126 buf += sprintf(buf, "(repeated %d times)\n", nSameCount);
128 buf += sprintf(buf, "%04x: %s", nStart, sz);
132 buf += sprintf(buf, " ");
136 buf += sprintf(buf, "%s\n", szChar);
145 "Usage: wlan-hwd [options] <interface>\n\nOptions\n"
146 "-f/--fcs Mark as having FCS (CRC) already\n"
147 " (pkt ends with 4 x sacrificial - chars)\n"
149 " echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
150 " iwconfig mon0 mode monitor\n"
151 " ifconfig mon0 up\n"
152 " wlan-hwd mon0 Spam down mon0 with\n"
153 " radiotap header first\n"
158 int flagHelp = 0, flagMarkWithFCS = 0;
165 * Copyright 2007 Andy Green <andy@warmcat.com>
169 * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
170 * @param iterator: radiotap_iterator to initialize
171 * @param radiotap_header: radiotap header to parse
172 * @param max_length: total length we can parse into (eg, whole packet length)
174 * @return 0 or a negative error code if there is a problem.
176 * This function initializes an opaque iterator struct which can then
177 * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
178 * argument which is present in the header. It knows about extended
179 * present headers and handles them.
182 * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
183 * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
184 * checking for a good 0 return code. Then loop calling
185 * __ieee80211_radiotap_iterator_next()... it returns either 0,
186 * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
187 * The iterator's this_arg member points to the start of the argument
188 * associated with the current argument index that is present, which can be
189 * found in the iterator's this_arg_index member. This arg index corresponds
190 * to the IEEE80211_RADIOTAP_... defines.
192 * Radiotap header length:
193 * You can find the CPU-endian total radiotap header length in
194 * iterator->max_length after executing ieee80211_radiotap_iterator_init()
198 * See Documentation/networking/radiotap-headers.txt
201 int ieee80211_radiotap_iterator_init(
202 struct ieee80211_radiotap_iterator *iterator,
203 struct ieee80211_radiotap_header *radiotap_header,
206 /* Linux only supports version 0 radiotap format */
207 if (radiotap_header->it_version)
210 /* sanity check for allowed length and radiotap length field */
211 if (max_length < le16_to_cpu(radiotap_header->it_len))
214 iterator->rtheader = radiotap_header;
215 iterator->max_length = le16_to_cpu(radiotap_header->it_len);
216 iterator->arg_index = 0;
217 iterator->bitmap_shifter = le32_to_cpu(radiotap_header->it_present);
218 iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
219 iterator->this_arg = 0;
221 /* find payload start allowing for extended bitmap(s) */
223 if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
224 while (le32_to_cpu(*((u32 *)iterator->arg)) &
225 (1<<IEEE80211_RADIOTAP_EXT)) {
226 iterator->arg += sizeof(u32);
229 * check for insanity where the present bitmaps
230 * keep claiming to extend up to or even beyond the
231 * stated radiotap header length
234 if (((ulong)iterator->arg -
235 (ulong)iterator->rtheader) > iterator->max_length)
239 iterator->arg += sizeof(u32);
242 * no need to check again for blowing past stated radiotap
243 * header length, because ieee80211_radiotap_iterator_next
244 * checks it before it is dereferenced
248 /* we are all initialized happily */
255 * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
256 * @param iterator: radiotap_iterator to move to next arg (if any)
258 * @return 0 if there is an argument to handle,
259 * -ENOENT if there are no more args or -EINVAL
260 * if there is something else wrong.
262 * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
263 * in this_arg_index and sets this_arg to point to the
264 * payload for the field. It takes care of alignment handling and extended
265 * present fields. this_arg can be changed by the caller (eg,
266 * incremented to move inside a compound argument like
267 * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
268 * little-endian format whatever the endianess of your CPU.
271 int ieee80211_radiotap_iterator_next(
272 struct ieee80211_radiotap_iterator *iterator)
276 * small length lookup table for all radiotap types we heard of
277 * starting from b0 in the bitmap, so we can walk the payload
278 * area of the radiotap header
280 * There is a requirement to pad args, so that args
281 * of a given length must begin at a boundary of that length
282 * -- but note that compound args are allowed (eg, 2 x u16
283 * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
284 * a reliable indicator of alignment requirement.
286 * upper nybble: content alignment for arg
287 * lower nybble: content length for arg
290 static const u8 rt_sizes[] = {
291 [IEEE80211_RADIOTAP_TSFT] = 0x88,
292 [IEEE80211_RADIOTAP_FLAGS] = 0x11,
293 [IEEE80211_RADIOTAP_RATE] = 0x11,
294 [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
295 [IEEE80211_RADIOTAP_FHSS] = 0x22,
296 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
297 [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
298 [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
299 [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
300 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
301 [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
302 [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
303 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
304 [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11
306 * add more here as they are defined in
307 * include/net/ieee80211_radiotap.h
312 * for every radiotap entry we can at
313 * least skip (by knowing the length)...
316 while (iterator->arg_index < sizeof(rt_sizes)) {
320 if (!(iterator->bitmap_shifter & 1))
321 goto next_entry; /* arg not present */
324 * arg is present, account for alignment padding
325 * 8-bit args can be at any alignment
326 * 16-bit args must start on 16-bit boundary
327 * 32-bit args must start on 32-bit boundary
328 * 64-bit args must start on 64-bit boundary
330 * note that total arg size can differ from alignment of
331 * elements inside arg, so we use upper nybble of length
332 * table to base alignment on
334 * also note: these alignments are ** relative to the
335 * start of the radiotap header **. There is no guarantee
336 * that the radiotap header itself is aligned on any
340 pad = (((ulong)iterator->arg) -
341 ((ulong)iterator->rtheader)) &
342 ((rt_sizes[iterator->arg_index] >> 4) - 1);
345 iterator->arg_index +=
346 (rt_sizes[iterator->arg_index] >> 4) - pad;
349 * this is what we will return to user, but we need to
350 * move on first so next call has something fresh to test
352 iterator->this_arg_index = iterator->arg_index;
353 iterator->this_arg = iterator->arg;
356 /* internally move on the size of this arg */
357 iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
360 * check for insanity where we are given a bitmap that
361 * claims to have more arg content than the length of the
362 * radiotap section. We will normally end up equalling this
363 * max_length on the last arg, never exceeding it.
366 if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
367 iterator->max_length)
371 iterator->arg_index++;
372 if (unlikely((iterator->arg_index & 31) == 0)) {
373 /* completed current u32 bitmap */
374 if (iterator->bitmap_shifter & 1) {
375 /* b31 was set, there is more */
376 /* move to next u32 bitmap */
377 iterator->bitmap_shifter =
378 le32_to_cpu(*iterator->next_bitmap);
379 iterator->next_bitmap++;
381 /* no more bitmaps: end */
382 iterator->arg_index = sizeof(rt_sizes);
384 } else { /* just try the next bit */
385 iterator->bitmap_shifter >>= 1;
388 /* if we found a valid arg earlier, return it now */
393 /* we don't know how to handle any more args, we're done */
397 #define FIFO_FILE1 "/tmp/MYFIFOin"
398 #define FIFO_FILE2 "/tmp/MYFIFOout"
402 static int closeprog;
415 char buf[MAXLINE * 2];
419 stdin_send (void *cls,
421 const struct GNUNET_MessageHeader *hdr)
423 struct sendbuf *write_pout = cls;
425 struct GNUNET_MessageHeader newheader;
429 sendsize = ntohs(hdr->size) - sizeof(struct RadiotapHeader) ;
432 if(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type)){
433 fprintf(stderr, "Function stdin_send: wrong packet type\n");
436 if((sendsize + write_pout->size) > MAXLINE * 2){
437 fprintf(stderr, "Function stdin_send: Packet too big for buffer\n");
442 newheader.size = htons(sendsize);
443 newheader.type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
446 to = write_pout->buf + write_pout->size;
447 memcpy(to, &newheader, sizeof(struct GNUNET_MessageHeader));
448 write_pout->size += sizeof(struct GNUNET_MessageHeader);
450 from = ((char *) hdr) + sizeof(struct RadiotapHeader) + sizeof(struct GNUNET_MessageHeader);
451 to = write_pout->buf + write_pout->size;
452 memcpy(to, from, sendsize - sizeof(struct GNUNET_MessageHeader));
453 write_pout->size += sendsize - sizeof(struct GNUNET_MessageHeader);
457 file_in_send (void *cls,
459 const struct GNUNET_MessageHeader *hdr)
461 struct sendbuf * write_std = cls;
464 sendsize = ntohs(hdr->size);
466 if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type))
469 "Function file_in_send: wrong packet type\n");
472 if((sendsize + write_std->size) > MAXLINE * 2){
473 fprintf(stderr, "Function file_in_send: Packet too big for buffer\n");
477 memcpy(write_std->buf + write_std->size, hdr, sendsize);
478 write_std->size += sendsize;
482 testmode(int argc, char *argv[])
493 //make the fifos if needed
494 if (0 != stat(FIFO_FILE1, &st))
496 if (0 == stat(FIFO_FILE2, &st))
498 fprintf(stderr, "FIFO_FILE2 exists, but FIFO_FILE1 not\n");
503 erg = mknod(FIFO_FILE1, S_IFIFO | 0666, 0);
504 erg = mknod(FIFO_FILE2, S_IFIFO | 0666, 0);
510 if (0 != stat(FIFO_FILE2, &st))
512 fprintf(stderr, "FIFO_FILE1 exists, but FIFO_FILE2 not\n");
518 if (strstr(argv[2], "1"))
520 //fprintf(stderr, "First\n");
522 fpin = fopen(FIFO_FILE1, "r");
525 fprintf(stderr, "fopen of read FIFO_FILE1\n");
528 if (NULL == (fpout = fopen(FIFO_FILE2, "w")))
530 fprintf(stderr, "fopen of write FIFO_FILE2\n");
538 //fprintf(stderr, "Second\n");
539 if (NULL == (fpout = fopen(FIFO_FILE1, "w")))
541 fprintf(stderr, "fopen of write FIFO_FILE1\n");
544 if (NULL == (fpin = fopen(FIFO_FILE2, "r")))
546 fprintf(stderr, "fopen of read FIFO_FILE2\n");
552 fdpin = fileno(fpin);
553 if (fdpin >= FD_SETSIZE)
555 fprintf(stderr, "File fdpin number too large (%d > %u)\n", fdpin,
556 (unsigned int) FD_SETSIZE);
561 fdpout = fileno(fpout);
562 if (fdpout >= FD_SETSIZE)
564 fprintf(stderr, "File fdpout number too large (%d > %u)\n", fdpout,
565 (unsigned int) FD_SETSIZE);
571 signal(SIGINT, &sigfunc);
572 signal(SIGTERM, &sigfunc);
574 char readbuf[MAXLINE];
576 struct sendbuf write_std;
580 struct sendbuf write_pout;
594 struct GNUNET_SERVER_MessageStreamTokenizer * stdin_mst;
595 struct GNUNET_SERVER_MessageStreamTokenizer * file_in_mst;
597 stdin_mst = GNUNET_SERVER_mst_create(&stdin_send, &write_pout);
598 file_in_mst = GNUNET_SERVER_mst_create(&file_in_send, &write_std);
602 struct Wlan_Helper_Control_Message macmsg;
604 //Send random mac address
605 macmsg.mac.mac[0] = 0x13;
606 macmsg.mac.mac[1] = 0x22;
607 macmsg.mac.mac[2] = 0x33;
608 macmsg.mac.mac[3] = 0x44;
609 macmsg.mac.mac[4] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 256);
610 macmsg.mac.mac[5] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, 256);
611 macmsg.hdr.size = htons(sizeof(struct Wlan_Helper_Control_Message));
612 macmsg.hdr.type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
614 memcpy(&write_std.buf, &macmsg, sizeof(struct Wlan_Helper_Control_Message));
615 write_std.size = sizeof(struct Wlan_Helper_Control_Message);
621 retval = select(0, NULL, NULL, NULL, &tv);
626 // if there is something to write
628 FD_SET(STDOUT_FILENO, &wfds);
630 retval = select(STDOUT_FILENO + 1, NULL, &wfds, NULL, &tv);
632 if (FD_ISSET(STDOUT_FILENO, &wfds))
634 ret = write(STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size
640 fprintf(stderr, "Write ERROR to STDOUT");
645 write_std.pos += ret;
647 if (write_std.pos == write_std.size)
655 memcpy(&write_std.buf, &macmsg, sizeof(struct Wlan_Helper_Control_Message));
656 write_std.size = sizeof(struct Wlan_Helper_Control_Message);
662 retval = select(0, NULL, NULL, NULL, &tv);
664 while (0 == closeprog)
674 // if output queue is empty
675 if (0 == write_pout.size)
677 FD_SET(STDIN_FILENO, &rfds);
680 if (0 == write_std.size)
682 FD_SET(fdpin, &rfds);
686 // if there is something to write
687 if (0 < write_std.size){
688 FD_SET(STDOUT_FILENO, &wfds);
689 maxfd = MAX(maxfd, STDOUT_FILENO);
692 if (0 < write_pout.size){
693 FD_SET(fdpout, &wfds);
694 maxfd = MAX(maxfd, fdpout);
698 retval = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
700 if (-1 == retval && EINTR == errno)
706 fprintf(stderr, "select failed: %s\n", strerror(errno));
710 if (FD_ISSET(STDOUT_FILENO, &wfds))
712 ret = write(STDOUT_FILENO, write_std.buf + write_std.pos,
713 write_std.size - write_std.pos);
718 fprintf(stderr, "Write ERROR to STDOUT\n");
723 write_std.pos += ret;
725 if (write_std.pos == write_std.size)
733 if (FD_ISSET(fdpout, &wfds))
735 ret = write(fdpout, write_pout.buf + write_pout.pos, write_pout.size
741 fprintf(stderr, "Write ERROR to fdpout\n");
745 write_pout.pos += ret;
747 if (write_pout.pos == write_pout.size)
755 if (FD_ISSET(STDIN_FILENO, &rfds))
757 readsize = read(STDIN_FILENO, readbuf, sizeof(readbuf));
762 fprintf(stderr, "Read ERROR to STDIN_FILENO\n");
764 else if (0 < readsize)
766 GNUNET_SERVER_mst_receive(stdin_mst, NULL, readbuf, readsize,
767 GNUNET_NO, GNUNET_NO);
777 if (FD_ISSET(fdpin, &rfds))
779 readsize = read(fdpin, readbuf, sizeof(readbuf));
784 fprintf(stderr, "Read ERROR to fdpin: %s\n", strerror(errno));
787 else if (0 < readsize)
789 GNUNET_SERVER_mst_receive(file_in_mst, NULL, readbuf, readsize,
790 GNUNET_NO, GNUNET_NO);
817 main(int argc, char *argv[])
823 "This program must be started with the interface and the operating mode as argument.\n");
827 if (strstr(argv[2], "1") || strstr(argv[2], "2"))
830 return testmode(argc, argv);
834 u8 u8aSendBuffer[500];
835 char szErrbuf[PCAP_ERRBUF_SIZE];
836 int nCaptureHeaderLength = 0, n80211HeaderLength = 0, nLinkEncap = 0;
837 int nOrdinal = 0, r, nDelay = 100000;
838 int nRateIndex = 0, retval, bytes;
839 pcap_t *ppcap = NULL;
840 struct bpf_program bpfprogram;
841 char * szProgram = "", fBrokenSocket = 0;
843 char szHostname[PATH_MAX];
845 if (gethostname(szHostname, sizeof (szHostname) - 1)) {
846 perror("unable to get hostname");
848 szHostname[sizeof (szHostname) - 1] = '\0';
851 printf("Packetspammer (c)2007 Andy Green <andy@warmcat.com> GPL2\n");
855 static const struct option optiona[] = {
856 { "delay", required_argument, NULL, 'd' },
857 { "fcs", no_argument, &flagMarkWithFCS, 1 },
858 { "help", no_argument, &flagHelp, 1 },
859 { "verbose", no_argument, &flagVerbose, 1},
862 int c = getopt_long(argc, argv, "d:hf",
863 optiona, &nOptionIndex);
868 case 0: // long option
875 nDelay = atoi(optarg);
878 case 'f': // mark as FCS attached
882 case 'v': //Verbose / readable output to cout
887 printf("unknown switch %c\n", c);
897 // open the interface in pcap
900 ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
902 printf("Unable to open interface %s in pcap: %s\n",
903 argv[optind], szErrbuf);
907 //get mac from interface
912 sock=socket(PF_INET, SOCK_STREAM, 0);
914 perror("can not open socket\n");
918 if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
919 perror("ioctl(SIOCGIFHWADDR) ");
922 for (j=0, k=0; j<6; j++) {
923 k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X",
924 (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
926 mac[sizeof(mac)-1]='\0';
930 nLinkEncap = pcap_datalink(ppcap);
931 nCaptureHeaderLength = 0;home/mwachs/gnb/bin/
933 switch (nLinkEncap) {
935 case DLT_PRISM_HEADER:
936 printf("DLT_PRISM_HEADER Encap\n");
937 nCaptureHeaderLength = 0x40;
938 n80211HeaderLength = 0x20; // ieee80211 comes after this
939 szProgram = "radio[0x4a:4]==0x13223344";
942 case DLT_IEEE802_11_RADIO:
943 printf("DLT_IEEE802_11_RADIO Encap\n");
944 nCaptureHeaderLength = 0x40;
945 n80211HeaderLength = 0x18; // ieee80211 comes after this
946 szProgram = "ether[0x0a:4]==0x13223344";
950 printf("!!! unknown encapsulation on %s !\n", argv[1]);
955 if (pcap_compile(ppcap, &bpfprogram, szProgram, 1, 0) == -1) {
957 puts(pcap_geterr(ppcap));
960 if (pcap_setfilter(ppcap, &bpfprogram) == -1) {
962 puts(pcap_geterr(ppcap));
964 printf("RX Filter applied\n");
966 pcap_freecode(&bpfprogram);
969 pcap_setnonblock(ppcap, 1, szErrbuf);
971 printf(" (delay between packets %dus)\n", nDelay);
973 memset(u8aSendBuffer, 0, sizeof (u8aSendBuffer));
975 while (!fBrokenSocket) {
976 u8 * pu8 = u8aSendBuffer;
977 struct pcap_pkthdr * ppcapPacketHeader = NULL;
978 struct ieee80211_radiotap_iterator rti;
979 PENUMBRA_RADIOTAP_DATA prd;
982 prd.m_nChannel = 255;
983 prd.m_nAntenna = 255;
984 prd.m_nRadiotapFlags = 255;
985 u8 * pu8Payload = u8aSendBuffer;
990 retval = pcap_next_ex(ppcap, &ppcapPacketHeader,
991 (const u_char**)&pu8Payload);
1001 u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8));
1004 Dump(pu8Payload, u16HeaderLen);
1006 if (ppcapPacketHeader->len <
1007 (u16HeaderLen + n80211HeaderLength))
1010 bytes = ppcapPacketHeader->len -
1011 (u16HeaderLen + n80211HeaderLength);
1015 if (ieee80211_radiotap_iterator_init(&rti,
1016 (struct ieee80211_radiotap_header *)pu8Payload,
1020 while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) {
1022 switch (rti.this_arg_index) {
1023 case IEEE80211_RADIOTAP_RATE:
1024 prd.m_nRate = (*rti.this_arg);
1027 case IEEE80211_RADIOTAP_CHANNEL:
1029 le16_to_cpu(*((u16 *)rti.this_arg));
1030 prd.m_nChannelFlags =
1031 le16_to_cpu(*((u16 *)(rti.this_arg + 2)));
1034 case IEEE80211_RADIOTAP_ANTENNA:
1035 prd.m_nAntenna = (*rti.this_arg) + 1;
1038 case IEEE80211_RADIOTAP_FLAGS:
1039 prd.m_nRadiotapFlags = *rti.this_arg;
1045 pu8Payload += u16HeaderLen + n80211HeaderLength;
1047 if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
1050 printf("RX: Rate: %2d.%dMbps, Freq: %d.%dGHz, "
1051 "Ant: %d, Flags: 0x%X\n",
1052 prd.m_nRate / 2, 5 * (prd.m_nRate & 1),
1053 prd.m_nChannel / 1000,
1054 prd.m_nChannel - ((prd.m_nChannel / 1000) * 1000),
1056 prd.m_nRadiotapFlags);
1058 Dump(pu8Payload, bytes);
1064 memcpy(u8aSendBuffer, u8aRadiotapHeader,
1065 sizeof (u8aRadiotapHeader));
1066 if (flagMarkWithFCS)
1067 pu8[OFFSET_FLAGS] |= IEEE80211_RADIOTAP_F_FCS;
1068 nRate = pu8[OFFSET_RATE] = u8aRatesToUse[nRateIndex++];
1069 if (nRateIndex >= sizeof (u8aRatesToUse))
1071 pu8 += sizeof (u8aRadiotapHeader);
1073 memcpy(pu8, u8aIeeeHeader, sizeof (u8aIeeeHeader));
1074 pu8 += sizeof (u8aIeeeHeader);
1076 pu8 += sprintf((char *)u8aSendBuffer,
1077 "Packetspammer %02d"
1079 "#%05d -- :-D --%s ----",
1080 nRate/2, nOrdinal++, szHostname);
1081 r = pcap_inject(ppcap, u8aSendBuffer, pu8 - u8aSendBuffer);
1082 if (r != (pu8-u8aSendBuffer)) {
1083 perror("Trouble injecting packet");