indentation
[oweals/gnunet.git] / src / transport / gnunet-transport-wlan-helper.c
index 15fe21cfd4b602afbff1638132f26ce5842733da..1cfcf2c4e167a509b7a628043769930c5e3774f9 100644 (file)
@@ -1,22 +1,22 @@
 /*
    This file is part of GNUnet.
    (C) 2010 Christian Grothoff (and other contributing authors)
-
    GNUnet is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published
    by the Free Software Foundation; either version 3, or (at your
    option) any later version.
-
    GNUnet is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
-
    You should have received a copy of the GNU General Public License
    along with GNUnet; see the file COPYING.  If not, write to the
    Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.
-*/
+ This file is part of GNUnet.
(C) 2010, 2011 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
 
 /**
  * @file src/transport/gnunet-transport-wlan-helper.c
  * gnunet
  */
 
+#define _GNU_SOURCE
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <netpacket/packet.h>
+#include <linux/if_ether.h>
+#include <linux/if.h>
+#include <linux/wireless.h>
+#include <netinet/in.h>
+#include <linux/if_tun.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+//#include <sys/utsname.h>
+#include <sys/param.h>
 
-#include "platform.h"
+/*
+ //#include <resolv.h>
+ #include <string.h>
+ #include <utime.h>
+ #include <getopt.h>
+ */
+//#include "platform.h"
 #include "gnunet_constants.h"
 #include "gnunet_os_lib.h"
 #include "gnunet_transport_plugin.h"
 #include "gnunet_common.h"
 #include "gnunet-transport-wlan-helper.h"
 #include "gnunet_crypto_lib.h"
-#include "ieee80211_radiotap.h"
-#include <pcap.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-
 
+#include "wlan/radiotap-parser.h"
+/* radiotap-parser defines types like u8 that
+ * ieee80211_radiotap.h needs
+ *
+ * we use our local copy of ieee80211_radiotap.h
+ *
+ * - since we can't support extensions we don't understand
+ * - since linux does not include it in userspace headers
+ */
+#include "wlan/ieee80211_radiotap.h"
+#include "wlan/crctable_osdep.h"
+#include "wlan/loopback_helper.h"
+#include "wlan/ieee80211.h"
 
+#define ARPHRD_IEEE80211        801
+#define ARPHRD_IEEE80211_PRISM  802
+#define ARPHRD_IEEE80211_FULL   803
 
-//#include "radiotap.h"
+#include "wlan/loopback_helper.h"
 
-// mac of this node
-char mac[] =
-  { 0x13, 0x22, 0x33, 0x44, 0x55, 0x66 };
+#define DEBUG 1
 
-/* wifi bitrate to use in 500kHz units */
+#define MAC_ADDR_SIZE 6
 
-static const u8 u8aRatesToUse[] = {
+struct Hardware_Infos
+{
 
-       54*2,
-       48*2,
-       36*2,
-       24*2,
-       18*2,
-       12*2,
-       9*2,
-       11*2,
-       11, // 5.5
-       2*2,
-       1*2
+  struct sendbuf write_pout;
+  int fd_raw;
+  int arptype_in;
+
+  /**
+   * Name of the interface, not necessarily 0-terminated (!).
+   */
+  char iface[IFNAMSIZ];
+  unsigned char pl_mac[MAC_ADDR_SIZE];
 };
 
-#define        OFFSET_FLAGS 0x10
-#define        OFFSET_RATE 0x11
+// FIXME: inline?
+int getChannelFromFrequency (int frequency);
 
-// this is where we store a summary of the
-// information from the radiotap header
+// FIXME: make nice...
+static unsigned long
+calc_crc_osdep (unsigned char *buf, int len)
+{
+  unsigned long crc = 0xFFFFFFFF;
 
-typedef struct  {
-       int m_nChannel;
-       int m_nChannelFlags;
-       int m_nRate;
-       int m_nAntenna;
-       int m_nRadiotapFlags;
-} __attribute__((packed)) PENUMBRA_RADIOTAP_DATA;
+  for (; len > 0; len--, buf++)
+    crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
 
-void
-Dump(u8 * pu8, int nLength)
-{
-       char sz[256], szBuf[512], szChar[17], *buf, fFirst = 1;
-       unsigned char baaLast[2][16];
-       uint n, nPos = 0, nStart = 0, nLine = 0, nSameCount = 0;
-
-       buf = szBuf;
-       szChar[0] = '\0';
-
-       for (n = 0; n < nLength; n++) {
-               baaLast[(nLine&1)^1][n&0xf] = pu8[n];
-               if ((pu8[n] < 32) || (pu8[n] >= 0x7f))
-                       szChar[n&0xf] = '.';
-               else
-                       szChar[n&0xf] = pu8[n];
-               szChar[(n&0xf)+1] = '\0';
-               nPos += sprintf(&sz[nPos], "%02X ",
-                       baaLast[(nLine&1)^1][n&0xf]);
-               if ((n&15) != 15)
-                       continue;
-               if ((memcmp(baaLast[0], baaLast[1], 16) == 0) && (!fFirst)) {
-                       nSameCount++;
-               } else {
-                       if (nSameCount)
-                               buf += sprintf(buf, "(repeated %d times)\n",
-                                       nSameCount);
-                       buf += sprintf(buf, "%04x: %s %s\n",
-                               nStart, sz, szChar);
-                       nSameCount = 0;
-                       printf("%s", szBuf);
-                       buf = szBuf;
-               }
-               nPos = 0; nStart = n+1; nLine++;
-               fFirst = 0; sz[0] = '\0'; szChar[0] = '\0';
-       }
-       if (nSameCount)
-               buf += sprintf(buf, "(repeated %d times)\n", nSameCount);
-
-       buf += sprintf(buf, "%04x: %s", nStart, sz);
-       if (n & 0xf) {
-               *buf++ = ' ';
-               while (n & 0xf) {
-                       buf += sprintf(buf, "   ");
-                       n++;
-               }
-       }
-       buf += sprintf(buf, "%s\n", szChar);
-       printf("%s", szBuf);
+  return (~crc);
 }
 
+/* CRC checksum verification routine */
 
-void
-usage()
+// FIXME: make nice...
+static int
+check_crc_buf_osdep (unsigned char *buf, int len)
 {
-       printf(
-           "Usage: wlan-hwd [options] <interface>\n\nOptions\n"
-           "-f/--fcs           Mark as having FCS (CRC) already\n"
-           "                   (pkt ends with 4 x sacrificial - chars)\n"
-           "Example:\n"
-           "  echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n"
-           "  iwconfig mon0 mode monitor\n"
-           "  ifconfig mon0 up\n"
-           "  wlan-hwd mon0        Spam down mon0 with\n"
-           "                       radiotap header first\n"
-           "\n");
-       exit(1);
-}
+  unsigned long crc;
 
-int flagHelp = 0, flagMarkWithFCS = 0;
-int flagVerbose = 0;
+  if (0 > len)
+    return 0;
 
+  crc = calc_crc_osdep (buf, len);
+  buf += len;
+  return (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && ((crc
+                                                                         >> 16)
+                                                                        & 0xFF)
+          == buf[2] && ((crc >> 24) & 0xFF) == buf[3]);
+}
 
-/*
- * Radiotap parser
- *
- * Copyright 2007              Andy Green <andy@warmcat.com>
- */
-
-/**
- * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
- * @param iterator: radiotap_iterator to initialize
- * @param radiotap_header: radiotap header to parse
- * @param max_length: total length we can parse into (eg, whole packet length)
- *
- * @return 0 or a negative error code if there is a problem.
- *
- * This function initializes an opaque iterator struct which can then
- * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
- * argument which is present in the header.  It knows about extended
- * present headers and handles them.
- *
- * How to use:
- * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
- * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
- * checking for a good 0 return code.  Then loop calling
- * __ieee80211_radiotap_iterator_next()... it returns either 0,
- * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
- * The iterator's this_arg member points to the start of the argument
- * associated with the current argument index that is present, which can be
- * found in the iterator's this_arg_index member.  This arg index corresponds
- * to the IEEE80211_RADIOTAP_... defines.
- *
- * Radiotap header length:
- * You can find the CPU-endian total radiotap header length in
- * iterator->max_length after executing ieee80211_radiotap_iterator_init()
- * successfully.
- *
- * Example code:
- * See Documentation/networking/radiotap-headers.txt
- */
 
-int ieee80211_radiotap_iterator_init(
-    struct ieee80211_radiotap_iterator *iterator,
-    struct ieee80211_radiotap_header *radiotap_header,
-    int max_length)
+// FIXME: make nice...
+static int
+linux_get_channel (struct Hardware_Infos *dev)
 {
-       /* Linux only supports version 0 radiotap format */
-       if (radiotap_header->it_version)
-               return -EINVAL;
-
-       /* sanity check for allowed length and radiotap length field */
-       if (max_length < le16_to_cpu(radiotap_header->it_len))
-               return -EINVAL;
-
-       iterator->rtheader = radiotap_header;
-       iterator->max_length = le16_to_cpu(radiotap_header->it_len);
-       iterator->arg_index = 0;
-       iterator->bitmap_shifter = le32_to_cpu(radiotap_header->it_present);
-       iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header);
-       iterator->this_arg = 0;
-
-       /* find payload start allowing for extended bitmap(s) */
-
-       if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) {
-               while (le32_to_cpu(*((u32 *)iterator->arg)) &
-                                  (1<<IEEE80211_RADIOTAP_EXT)) {
-                       iterator->arg += sizeof(u32);
-
-                       /*
-                        * check for insanity where the present bitmaps
-                        * keep claiming to extend up to or even beyond the
-                        * stated radiotap header length
-                        */
-
-                       if (((ulong)iterator->arg -
-                            (ulong)iterator->rtheader) > iterator->max_length)
-                               return -EINVAL;
-               }
-
-               iterator->arg += sizeof(u32);
-
-               /*
-                * no need to check again for blowing past stated radiotap
-                * header length, because ieee80211_radiotap_iterator_next
-                * checks it before it is dereferenced
-                */
-       }
-
-       /* we are all initialized happily */
-
-       return 0;
-}
+  struct iwreq wrq;
+  int fd, frequency;
+  int chan = 0;
 
+  memset (&wrq, 0, sizeof (struct iwreq));
 
-/**
- * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
- * @param iterator: radiotap_iterator to move to next arg (if any)
- *
- * @return 0 if there is an argument to handle,
- * -ENOENT if there are no more args or -EINVAL
- * if there is something else wrong.
- *
- * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
- * in this_arg_index and sets this_arg to point to the
- * payload for the field.  It takes care of alignment handling and extended
- * present fields.  this_arg can be changed by the caller (eg,
- * incremented to move inside a compound argument like
- * IEEE80211_RADIOTAP_CHANNEL).  The args pointed to are in
- * little-endian format whatever the endianess of your CPU.
- */
+  strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
 
-int ieee80211_radiotap_iterator_next(
-    struct ieee80211_radiotap_iterator *iterator)
-{
+  fd = dev->fd_raw;
+  if (0 > ioctl (fd, SIOCGIWFREQ, &wrq))
+    return (-1);
 
-       /*
-        * small length lookup table for all radiotap types we heard of
-        * starting from b0 in the bitmap, so we can walk the payload
-        * area of the radiotap header
-        *
-        * There is a requirement to pad args, so that args
-        * of a given length must begin at a boundary of that length
-        * -- but note that compound args are allowed (eg, 2 x u16
-        * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not
-        * a reliable indicator of alignment requirement.
-        *
-        * upper nybble: content alignment for arg
-        * lower nybble: content length for arg
-        */
-
-       static const u8 rt_sizes[] = {
-               [IEEE80211_RADIOTAP_TSFT] = 0x88,
-               [IEEE80211_RADIOTAP_FLAGS] = 0x11,
-               [IEEE80211_RADIOTAP_RATE] = 0x11,
-               [IEEE80211_RADIOTAP_CHANNEL] = 0x24,
-               [IEEE80211_RADIOTAP_FHSS] = 0x22,
-               [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11,
-               [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11,
-               [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22,
-               [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22,
-               [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22,
-               [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11,
-               [IEEE80211_RADIOTAP_ANTENNA] = 0x11,
-               [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11,
-               [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11
-               /*
-                * add more here as they are defined in
-                * include/net/ieee80211_radiotap.h
-                */
-       };
-
-       /*
-        * for every radiotap entry we can at
-        * least skip (by knowing the length)...
-        */
-
-       while (iterator->arg_index < sizeof(rt_sizes)) {
-               int hit = 0;
-               int pad;
-
-               if (!(iterator->bitmap_shifter & 1))
-                       goto next_entry; /* arg not present */
-
-               /*
-                * arg is present, account for alignment padding
-                *  8-bit args can be at any alignment
-                * 16-bit args must start on 16-bit boundary
-                * 32-bit args must start on 32-bit boundary
-                * 64-bit args must start on 64-bit boundary
-                *
-                * note that total arg size can differ from alignment of
-                * elements inside arg, so we use upper nybble of length
-                * table to base alignment on
-                *
-                * also note: these alignments are ** relative to the
-                * start of the radiotap header **.  There is no guarantee
-                * that the radiotap header itself is aligned on any
-                * kind of boundary.
-                */
-
-               pad = (((ulong)iterator->arg) -
-                       ((ulong)iterator->rtheader)) &
-                       ((rt_sizes[iterator->arg_index] >> 4) - 1);
-
-               if (pad)
-                       iterator->arg_index +=
-                               (rt_sizes[iterator->arg_index] >> 4) - pad;
-
-               /*
-                * this is what we will return to user, but we need to
-                * move on first so next call has something fresh to test
-                */
-               iterator->this_arg_index = iterator->arg_index;
-               iterator->this_arg = iterator->arg;
-               hit = 1;
-
-               /* internally move on the size of this arg */
-               iterator->arg += rt_sizes[iterator->arg_index] & 0x0f;
-
-               /*
-                * check for insanity where we are given a bitmap that
-                * claims to have more arg content than the length of the
-                * radiotap section.  We will normally end up equalling this
-                * max_length on the last arg, never exceeding it.
-                */
-
-               if (((ulong)iterator->arg - (ulong)iterator->rtheader) >
-                   iterator->max_length)
-                       return -EINVAL;
-
-       next_entry:
-               iterator->arg_index++;
-               if (unlikely((iterator->arg_index & 31) == 0)) {
-                       /* completed current u32 bitmap */
-                       if (iterator->bitmap_shifter & 1) {
-                               /* b31 was set, there is more */
-                               /* move to next u32 bitmap */
-                               iterator->bitmap_shifter =
-                                   le32_to_cpu(*iterator->next_bitmap);
-                               iterator->next_bitmap++;
-                       } else {
-                               /* no more bitmaps: end */
-                               iterator->arg_index = sizeof(rt_sizes);
-                       }
-               } else { /* just try the next bit */
-                       iterator->bitmap_shifter >>= 1;
-               }
-
-               /* if we found a valid arg earlier, return it now */
-               if (hit)
-                       return 0;
-       }
-
-       /* we don't know how to handle any more args, we're done */
-       return -ENOENT;
-}
+  frequency = wrq.u.freq.m;
+  if (100000000 < frequency)
+    frequency /= 100000;
+  else if (1000000 < frequency)
+    frequency /= 1000;
 
-#define FIFO_FILE1       "/tmp/MYFIFOin"
-#define FIFO_FILE2       "/tmp/MYFIFOout"
-#define MAXLINE         4096
-
-static int first;
-static int closeprog;
+  if (1000 < frequency)
+    chan = getChannelFromFrequency (frequency);
+  else
+    chan = frequency;
 
-static void 
-sigfunc(int sig)
-{
-  closeprog = 1;  
-  unlink(FIFO_FILE1);
-  unlink(FIFO_FILE2);
+  return chan;
 }
 
-struct sendbuf {
-  int pos;
-  int size;
-  char buf[MAXLINE * 2];
-};
 
-static void
-stdin_send (void *cls,
-                      void *client,
-                      const struct GNUNET_MessageHeader *hdr)
+// FIXME: make nice...
+static ssize_t
+linux_read (struct Hardware_Infos *dev, unsigned char *buf,     /* FIXME: void*? */
+            size_t buf_size, struct Radiotap_rx *ri)
 {
-  struct sendbuf *write_pout = cls;
-  int sendsize;
-  struct GNUNET_MessageHeader newheader;
-  char * from;
-  char * to;
-
-  sendsize = ntohs(hdr->size) - sizeof(struct RadiotapHeader) ;
-
-
-  if(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type)){
-    fprintf(stderr, "Function stdin_send: wrong packet type\n");
-    exit(1);
-  }
-  if((sendsize + write_pout->size) > MAXLINE * 2){
-    fprintf(stderr, "Function stdin_send: Packet too big for buffer\n");
-    exit(1);
+  unsigned char tmpbuf[buf_size];
+  ssize_t caplen;
+  int n, got_signal, got_noise, got_channel, fcs_removed;
+
+  n = got_signal = got_noise = got_channel = fcs_removed = 0;
+
+  caplen = read (dev->fd_raw, tmpbuf, buf_size);
+  if (0 > caplen)
+  {
+    if (EAGAIN == errno)
+      return 0;
+    fprintf (stderr, "Failed to read from RAW socket: %s\n", strerror (errno));
+    return -1;
   }
 
+  memset (buf, 0, buf_size);
+  memset (ri, 0, sizeof (*ri));
 
-  newheader.size = htons(sendsize);
-  newheader.type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
-
-
-  to = write_pout->buf + write_pout->size;
-  memcpy(to, &newheader, sizeof(struct GNUNET_MessageHeader));
-  write_pout->size += sizeof(struct GNUNET_MessageHeader);
-
-  from = (char *) hdr + sizeof(struct RadiotapHeader) + sizeof(struct GNUNET_MessageHeader);
-  to = write_pout->buf + write_pout->size;
-  memcpy(to, from, sendsize - sizeof(struct GNUNET_MessageHeader));
-  write_pout->size += sendsize - sizeof(struct GNUNET_MessageHeader);
-}
-
-static void
-file_in_send (void *cls,
-                      void *client,
-                      const struct GNUNET_MessageHeader *hdr)
-{
-  struct sendbuf * write_std = cls;
-  int sendsize;
-
-  sendsize = ntohs(hdr->size);
+  switch (dev->arptype_in)
+  {
+  case ARPHRD_IEEE80211_PRISM:
+  {
+    /* skip the prism header */
+    if (tmpbuf[7] == 0x40)
+    {
+      /* prism54 uses a different format */
+      ri->ri_power = tmpbuf[0x33];
+      ri->ri_noise = *(unsigned int *) (tmpbuf + 0x33 + 12);
+      ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x33 + 24)) * 500000;
+      got_signal = 1;
+      got_noise = 1;
+      n = 0x40;
+    }
+    else
+    {
+      ri->ri_mactime = *(u_int64_t *) (tmpbuf + 0x5C - 48);
+      ri->ri_channel = *(unsigned int *) (tmpbuf + 0x5C - 36);
+      ri->ri_power = *(unsigned int *) (tmpbuf + 0x5C);
+      ri->ri_noise = *(unsigned int *) (tmpbuf + 0x5C + 12);
+      ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x5C + 24)) * 500000;
+      got_channel = 1;
+      got_signal = 1;
+      got_noise = 1;
+      n = *(int *) (tmpbuf + 4);
+    }
 
-  if(GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs(hdr->type)){
-    fprintf(stderr, "Function file_in_send: wrong packet type\n");
-    exit(1);
-  }
-  if((sendsize + write_std->size) > MAXLINE * 2){
-    fprintf(stderr, "Function file_in_send: Packet too big for buffer\n");
-    exit(1);
+    if (n < 8 || n >= caplen)
+      return (0);
   }
+    break;
 
-  memcpy(write_std->buf + write_std->size, hdr, sendsize);
-  write_std->size += sendsize;
-}
+  case ARPHRD_IEEE80211_FULL:
+  {
+    struct ieee80211_radiotap_iterator iterator;
+    struct ieee80211_radiotap_header *rthdr;
 
-int
-testmode(int argc, char *argv[])
-{
-  struct stat st;
-  int erg;
+    rthdr = (struct ieee80211_radiotap_header *) tmpbuf;
 
-  FILE *fpin;
-  FILE *fpout;
+    if (ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen) < 0)
+      return (0);
 
-  int fdpin;
-  int fdpout;
+    /* go through the radiotap arguments we have been given
+     * by the driver
+     */
 
-  //make the fifos if needed
-  if (0 != stat(FIFO_FILE1, &st))
+    while (ieee80211_radiotap_iterator_next (&iterator) >= 0)
     {
-      if (0 == stat(FIFO_FILE2, &st))
-        {
-        fprintf(stderr, "FIFO_FILE2 exists, but FIFO_FILE1 not\n");
-          exit(1);
-        }
 
-      umask(0);
-      erg = mknod(FIFO_FILE1, S_IFIFO | 0666, 0);
-      erg = mknod(FIFO_FILE2, S_IFIFO | 0666, 0);
+      switch (iterator.this_arg_index)
+      {
 
-    }
-  else
-    {
+      case IEEE80211_RADIOTAP_TSFT:
+        ri->ri_mactime = le64_to_cpu (*((uint64_t *) iterator.this_arg));
+        break;
 
-      if (0 != stat(FIFO_FILE2, &st))
+      case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
+        if (!got_signal)
         {
-        fprintf(stderr, "FIFO_FILE1 exists, but FIFO_FILE2 not\n");
-          exit(1);
-        }
+          if (*iterator.this_arg < 127)
+            ri->ri_power = *iterator.this_arg;
+          else
+            ri->ri_power = *iterator.this_arg - 255;
 
-    }
+          got_signal = 1;
+        }
+        break;
 
-  if (strstr(argv[2], "1"))
-    {
-      //fprintf(stderr, "First\n");
-      first = 1;
-      fpin = fopen(FIFO_FILE1, "r");
-      if (NULL == fpin)
+      case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
+        if (!got_signal)
         {
-        fprintf(stderr, "fopen of read FIFO_FILE1\n");
-          exit(1);
+          if (*iterator.this_arg < 127)
+            ri->ri_power = *iterator.this_arg;
+          else
+            ri->ri_power = *iterator.this_arg - 255;
+
+          got_signal = 1;
         }
-      if (NULL == (fpout = fopen(FIFO_FILE2, "w")))
+        break;
+
+      case IEEE80211_RADIOTAP_DBM_ANTNOISE:
+        if (!got_noise)
         {
-        fprintf(stderr, "fopen of write FIFO_FILE2\n");
-          exit(1);
+          if (*iterator.this_arg < 127)
+            ri->ri_noise = *iterator.this_arg;
+          else
+            ri->ri_noise = *iterator.this_arg - 255;
+
+          got_noise = 1;
         }
+        break;
 
-    }
-  else
-    {
-      first = 0;
-      //fprintf(stderr, "Second\n");
-      if (NULL == (fpout = fopen(FIFO_FILE1, "w")))
+      case IEEE80211_RADIOTAP_DB_ANTNOISE:
+        if (!got_noise)
         {
-        fprintf(stderr, "fopen of write FIFO_FILE1\n");
-          exit(1);
+          if (*iterator.this_arg < 127)
+            ri->ri_noise = *iterator.this_arg;
+          else
+            ri->ri_noise = *iterator.this_arg - 255;
+
+          got_noise = 1;
         }
-      if (NULL == (fpin = fopen(FIFO_FILE2, "r")))
+        break;
+
+      case IEEE80211_RADIOTAP_ANTENNA:
+        ri->ri_antenna = *iterator.this_arg;
+        break;
+
+      case IEEE80211_RADIOTAP_CHANNEL:
+        ri->ri_channel = *iterator.this_arg;
+        got_channel = 1;
+        break;
+
+      case IEEE80211_RADIOTAP_RATE:
+        ri->ri_rate = (*iterator.this_arg) * 500000;
+        break;
+
+      case IEEE80211_RADIOTAP_FLAGS:
+        /* is the CRC visible at the end?
+         * remove
+         */
+        if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS)
         {
-        fprintf(stderr, "fopen of read FIFO_FILE2\n");
-          exit(1);
+          fcs_removed = 1;
+          caplen -= 4;
         }
 
-    }
+        if (*iterator.this_arg & IEEE80211_RADIOTAP_F_RX_BADFCS)
+          return (0);
 
-  fdpin = fileno(fpin);
-  if (fdpin >= FD_SETSIZE)
-    {
-      fprintf(stderr, "File fdpin number too large (%d > %u)\n", fdpin,
-          (unsigned int) FD_SETSIZE);
-      close(fdpin);
-      return -1;
+        break;
+      }
     }
+    n = le16_to_cpu (rthdr->it_len);
+    if (n <= 0 || n >= caplen)
+      return 0;
+  }
+    break;
+  case ARPHRD_IEEE80211:
+    /* do nothing? */
+    break;
+  default:
+    errno = ENOTSUP;
+    return -1;
+  }
 
-  fdpout = fileno(fpout);
-  if (fdpout >= FD_SETSIZE)
-    {
-      fprintf(stderr, "File fdpout number too large (%d > %u)\n", fdpout,
-          (unsigned int) FD_SETSIZE);
-      close(fdpout);
-      return -1;
-
-    }
+  caplen -= n;
 
-  signal(SIGINT, &sigfunc);
-  signal(SIGTERM, &sigfunc);
+  //detect fcs at the end, even if the flag wasn't set and remove it
+  if ((0 == fcs_removed) && (1 == check_crc_buf_osdep (tmpbuf + n, caplen - 4)))
+  {
+    caplen -= 4;
+  }
+  memcpy (buf, tmpbuf + n, caplen);
+  if (!got_channel)
+    ri->ri_channel = linux_get_channel (dev);
 
-  char readbuf[MAXLINE];
-  int readsize = 0;
-  struct sendbuf write_std;
-  write_std.size = 0;
-  write_std.pos = 0;
+  return caplen;
+}
 
-  struct sendbuf write_pout;
-  write_pout.size = 0;
-  write_pout.pos = 0;
 
-  int ret = 0;
-  int maxfd = 0;
+/**
+ * @return 0 on success
+ */
+static int
+openraw (struct Hardware_Infos *dev)
+{
+  struct ifreq ifr;
+  struct iwreq wrq;
+  struct packet_mreq mr;
+  struct sockaddr_ll sll;
+
+  /* find the interface index */
+  memset (&ifr, 0, sizeof (ifr));
+  strncpy (ifr.ifr_name, dev->iface, IFNAMSIZ);
+  if (-1 == ioctl (dev->fd_raw, SIOCGIFINDEX, &ifr))
+  {
+    fprintf (stderr,
+             "Line: 381 ioctl(SIOCGIFINDEX) on interface `%.*s' failed: %s\n",
+             IFNAMSIZ, dev->iface, strerror (errno));
+    return 1;
+  }
 
-  fd_set rfds;
-  fd_set wfds;
-  struct timeval tv;
-  int retval;
+  /* lookup the hardware type */
+  memset (&sll, 0, sizeof (sll));
+  sll.sll_family = AF_PACKET;
+  sll.sll_ifindex = ifr.ifr_ifindex;
+  sll.sll_protocol = htons (ETH_P_ALL);
+  if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr))
+  {
+    fprintf (stderr,
+             "ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n",
+             IFNAMSIZ, dev->iface, strerror (errno));
+    return 1;
+  }
 
+  /* lookup iw mode */
+  memset (&wrq, 0, sizeof (struct iwreq));
+  strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
+  if (-1 == ioctl (dev->fd_raw, SIOCGIWMODE, &wrq))
+  {
+    /* most probably not supported (ie for rtap ipw interface) *
+     * so just assume its correctly set...                     */
+    wrq.u.mode = IW_MODE_MONITOR;
+  }
 
+  if (((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) &&
+       (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) &&
+       (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) ||
+      (wrq.u.mode != IW_MODE_MONITOR))
+  {
+    fprintf (stderr,
+             "Error: interface `%.*s' is not in monitor mode\n",
+             IFNAMSIZ, dev->iface);
+    return 1;
+  }
 
-  struct GNUNET_SERVER_MessageStreamTokenizer * stdin_mst;
-  struct GNUNET_SERVER_MessageStreamTokenizer * file_in_mst;
+  /* Is interface st to up, broadcast & running ? */
+  if ((ifr.ifr_flags | IFF_UP | IFF_BROADCAST | IFF_RUNNING) != ifr.ifr_flags)
+  {
+    /* Bring interface up */
+    ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING;
 
-  stdin_mst = GNUNET_SERVER_mst_create(&stdin_send, &write_pout);
-  file_in_mst = GNUNET_SERVER_mst_create(&file_in_send, &write_std);
+    if (-1 == ioctl (dev->fd_raw, SIOCSIFFLAGS, &ifr))
+    {
+      fprintf (stderr,
+               "Line: 434 ioctl(SIOCSIFFLAGS) on interface `%.*s' failed: %s\n",
+               IFNAMSIZ, dev->iface, strerror (errno));
+      return 1;
+    }
+  }
 
-  //send mac first
+  /* bind the raw socket to the interface */
+  if (-1 == bind (dev->fd_raw, (struct sockaddr *) &sll, sizeof (sll)))
+  {
+    fprintf (stderr,
+             "Failed to bind interface `%.*s': %s\n",
+             IFNAMSIZ, dev->iface, strerror (errno));
+    return 1;
+  }
 
-  struct Wlan_Helper_Control_Message macmsg;
+  /* lookup the hardware type */
+  if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr))
+  {
+    fprintf (stderr,
+             "Line: 457 ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n",
+             IFNAMSIZ, dev->iface, strerror (errno));
+    return 1;
+  }
 
-  //Send random mac address
-  macmsg.mac.mac[0] = 0x13;
-  macmsg.mac.mac[1] = 0x22;
-  macmsg.mac.mac[2] = 0x33;
-  macmsg.mac.mac[3] = 0x44;
-  macmsg.mac.mac[4] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_STRONG, 256);
-  macmsg.mac.mac[5] = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_NONCE, 256);
-  macmsg.hdr.size = htons(sizeof(struct Wlan_Helper_Control_Message));
-  macmsg.hdr.type = htons(GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
+  memcpy (dev->pl_mac, ifr.ifr_hwaddr.sa_data, MAC_ADDR_SIZE);
+  dev->arptype_in = ifr.ifr_hwaddr.sa_family;
+  if ((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) &&
+      (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) &&
+      (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL))
+  {
+    fprintf (stderr,
+             "Unsupported hardware link type %d on interface `%.*s'\n",
+             ifr.ifr_hwaddr.sa_family, IFNAMSIZ, dev->iface);
+    return 1;
+  }
 
-  memcpy(&write_std.buf, &macmsg, sizeof(struct Wlan_Helper_Control_Message));
-  write_std.size = sizeof(struct Wlan_Helper_Control_Message);
+  /* enable promiscuous mode */
+  memset (&mr, 0, sizeof (mr));
+  mr.mr_ifindex = sll.sll_ifindex;
+  mr.mr_type = PACKET_MR_PROMISC;
+  if (0 !=
+      setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
+                  sizeof (mr)))
+  {
+    fprintf (stderr,
+             "Failed to enable promiscuous mode on interface `%.*s'\n",
+             IFNAMSIZ, dev->iface);
+    return 1;
+  }
 
-  /*
-  //wait
-  tv.tv_sec = 2;
-  tv.tv_usec = 0;
-  retval = select(0, NULL, NULL, NULL, &tv);
+  return 0;
+}
 
+/**
+ * @return 0 on success
+ */
+static int
+wlaninit (struct Hardware_Infos *dev, const char *iface)
+{
+  char strbuf[512];
+  struct stat sbuf;
+  int ret;
+
+  dev->fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
+  if (0 > dev->fd_raw)
+  {
+    fprintf (stderr, "Failed to create raw socket: %s\n", strerror (errno));
+    return 1;
+  }
+  if (dev->fd_raw >= FD_SETSIZE)
+  {
+    fprintf (stderr,
+             "File descriptor too large for select (%d > %d)\n",
+             dev->fd_raw, FD_SETSIZE);
+    close (dev->fd_raw);
+    return 1;
+  }
 
-  tv.tv_sec = 3;
-  tv.tv_usec = 0;
-  // if there is something to write
-  FD_ZERO(&wfds);
-  FD_SET(STDOUT_FILENO, &wfds);
+  /* mac80211 stack detection */
+  ret = snprintf (strbuf,
+                  sizeof (strbuf),
+                  "/sys/class/net/%s/phy80211/subsystem", iface);
+  if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
+  {
+    fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", iface);
+    close (dev->fd_raw);
+    return 1;
+  }
+  strncpy (dev->iface, iface, IFNAMSIZ);
+  if (0 != openraw (dev))
+  {
+    close (dev->fd_raw);
+    return 1;
+  }
+  return 0;
+}
 
-  retval = select(STDOUT_FILENO + 1, NULL, &wfds, NULL, &tv);
 
-  if (FD_ISSET(STDOUT_FILENO, &wfds))
-    {
-      ret = write(STDOUT_FILENO, write_std.buf + write_std.pos, write_std.size
-          - write_std.pos);
+/**
+ * Function to test incoming packets mac for being our own.
+ *
+ * @param u8aIeeeHeader buffer of the packet
+ * @param dev the Hardware_Infos struct
+ * @return 0 if mac belongs to us, 1 if mac is for another target
+ */
+static int
+mac_test (const struct ieee80211_frame *u8aIeeeHeader,
+          const struct Hardware_Infos *dev)
+{
+  if (0 != memcmp (u8aIeeeHeader->i_addr3, &mac_bssid, MAC_ADDR_SIZE))
+    return 1;
+  if (0 == memcmp (u8aIeeeHeader->i_addr1, dev->pl_mac, MAC_ADDR_SIZE))
+    return 0;
+  if (0 == memcmp (u8aIeeeHeader->i_addr1, &bc_all_mac, MAC_ADDR_SIZE))
+    return 0;
+  return 1;
+}
 
-      if (0 > ret)
-        {
-          closeprog = 1;
-          fprintf(stderr, "Write ERROR to STDOUT");
-          exit(1);
-        }
-      else
-        {
-          write_std.pos += ret;
-          // check if finished
-          if (write_std.pos == write_std.size)
-            {
-              write_std.pos = 0;
-              write_std.size = 0;
-            }
-        }
-    }
 
-  memcpy(&write_std.buf, &macmsg, sizeof(struct Wlan_Helper_Control_Message));
-  write_std.size = sizeof(struct Wlan_Helper_Control_Message);
-  */
+/**
+ * function to set the wlan header to make attacks more difficult
+ * @param buf buffer of the packet
+ * @param dev pointer to the Hardware_Infos struct
+ */
+static void
+mac_set (struct ieee80211_frame *u8aIeeeHeader,
+         const struct Hardware_Infos *dev)
+{
+  u8aIeeeHeader->i_fc[0] = 0x08;
+  u8aIeeeHeader->i_fc[1] = 0x00;
+  memcpy (u8aIeeeHeader->i_addr2, dev->pl_mac, MAC_ADDR_SIZE);
+  memcpy (u8aIeeeHeader->i_addr3, &mac_bssid, MAC_ADDR_SIZE);
 
-  //wait
-  tv.tv_sec = 2;
-  tv.tv_usec = 0;
-  retval = select(0, NULL, NULL, NULL, &tv);
+}
 
-  while (0 == closeprog)
-    {
+struct RadioTapheader
+{
+  struct ieee80211_radiotap_header header;
+  u8 rate;
+  u8 pad1;
+  u16 txflags;
+};
 
-      maxfd = 0;
+static void
+stdin_send_hw (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
+{
+  struct Hardware_Infos *dev = cls;
+  struct sendbuf *write_pout = &dev->write_pout;
+  struct Radiotap_Send *header = (struct Radiotap_Send *) &hdr[1];
+  struct ieee80211_frame *wlanheader;
+  size_t sendsize;
+
+  // struct? // FIXME: make nice...
+  struct RadioTapheader rtheader;
+
+  rtheader.header.it_version = 0;
+  rtheader.header.it_len = htole16 (0x0c);
+  rtheader.header.it_present = htole32 (0x00008004);
+  rtheader.rate = 0x00;
+  rtheader.txflags =
+      htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ);
+
+  /*  { 0x00, 0x00, <-- radiotap version
+   * 0x0c, 0x00, <- radiotap header length
+   * 0x04, 0x80, 0x00, 0x00,  <-- bitmap
+   * 0x00,  <-- rate
+   * 0x00,  <-- padding for natural alignment
+   * 0x18, 0x00,  <-- TX flags
+   * }; */
+
+  sendsize = ntohs (hdr->size);
+  if (sendsize <
+      sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader))
+  {
+    fprintf (stderr, "Function stdin_send_hw: mailformed packet (too small)\n");
+    exit (1);
+  }
+  sendsize -=
+      sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader);
 
-      //set timeout
-      tv.tv_sec = 5;
-      tv.tv_usec = 0;
+  if (MAXLINE < sendsize)
+  {
+    fprintf (stderr, "Function stdin_send_hw: Packet too big for buffer\n");
+    exit (1);
+  }
+  if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type))
+  {
+    fprintf (stderr, "Function stdin_send: wrong packet type\n");
+    exit (1);
+  }
 
-      FD_ZERO(&rfds);
-      // if output queue is empty
-      if (0 == write_pout.size)
-        {
-          FD_SET(STDIN_FILENO, &rfds);
+  rtheader.header.it_len = htole16 (sizeof (rtheader));
+  rtheader.rate = header->rate;
+  memcpy (write_pout->buf, &rtheader, sizeof (rtheader));
+  memcpy (write_pout->buf + sizeof (rtheader), &header[1], sendsize);
+  /* payload contains MAC address, but we don't trust it, so we'll 
+   * overwrite it with OUR MAC address again to prevent mischief */
+  wlanheader = (struct ieee80211_frame *) (write_pout->buf + sizeof (rtheader));
+  mac_set (wlanheader, dev);
+  write_pout->size = sendsize + sizeof (rtheader);
+}
 
-        }
-      if (0 == write_std.size)
-        {
-          FD_SET(fdpin, &rfds);
-          maxfd = fdpin;
-        }
-      FD_ZERO(&wfds);
-      // if there is something to write
-      if (0 < write_std.size){
-        FD_SET(STDOUT_FILENO, &wfds);
-        maxfd = MAX(maxfd, STDOUT_FILENO);
-      }
+#if 0
+static int
+maketest (unsigned char *buf, struct Hardware_Infos *dev)
+{
+  uint16_t *tmp16;
+  static uint16_t seqenz = 0;
+  static int first = 0;
+
+  const int rate = 11000000;
+  static const char
+      txt[] =
+      "Hallo1Hallo2 Hallo3 Hallo4...998877665544332211Hallo1Hallo2 Hallo3 Hallo4...998877665544332211";
+
+  unsigned char u8aRadiotap[] = { 0x00, 0x00,   // <-- radiotap version
+    0x00, 0x00,                 // <- radiotap header length
+    0x04, 0x80, 0x02, 0x00,     // <-- bitmap
+    0x00,                       // <-- rate
+    0x00,                       // <-- padding for natural alignment
+    0x10, 0x00,                 // <-- TX flags
+    0x04                        //retries
+  };
+
+  /*uint8_t u8aRadiotap[] =
+   * {
+   * 0x00, 0x00, // <-- radiotap version
+   * 0x19, 0x00, // <- radiotap header length
+   * 0x6f, 0x08, 0x00, 0x00, // <-- bitmap
+   * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
+   * 0x00, // <-- flags (Offset +0x10)
+   * 0x6c, // <-- rate (0ffset +0x11)
+   * 0x71, 0x09, 0xc0, 0x00, // <-- channel
+   * 0xde, // <-- antsignal
+   * 0x00, // <-- antnoise
+   * 0x01, // <-- antenna
+   * }; */
+
+  u8aRadiotap[8] = (rate / 500000);
+  u8aRadiotap[2] = htole16 (sizeof (u8aRadiotap));
+
+  static struct ieee80211_frame u8aIeeeHeader;
+
+  uint8_t u8aIeeeHeader_def[] = { 0x08, 0x00,   // Frame Control 0x08= 00001000 -> | b1,2 = 0 -> Version 0;
+    //      b3,4 = 10 -> Data; b5-8 = 0 -> Normal Data
+    //      0x01 = 00000001 -> | b1 = 1 to DS; b2 = 0 not from DS;
+    0x00, 0x00,                 // Duration/ID
+
+    //0x00, 0x1f, 0x3f, 0xd1, 0x8e, 0xe6, // mac1 - in this case receiver
+    0x00, 0x1d, 0xe0, 0xb0, 0x17, 0xdf, // mac1 - in this case receiver
+    0xC0, 0x3F, 0x0E, 0x44, 0x2D, 0x51, // mac2 - in this case sender
+    //0x02, 0x1d, 0xe0, 0x00, 0x01, 0xc4,
+    0x13, 0x22, 0x33, 0x44, 0x55, 0x66, // mac3 - in this case bssid
+    0x10, 0x86,                 //Sequence Control
+  };
+  if (0 == first)
+  {
+    memcpy (&u8aIeeeHeader, u8aIeeeHeader_def, sizeof (struct ieee80211_frame));
+    memcpy (u8aIeeeHeader.i_addr2, dev->pl_mac, MAC_ADDR_SIZE);
+    first = 1;
+  }
 
-      if (0 < write_pout.size){
-        FD_SET(fdpout, &wfds);
-        maxfd = MAX(maxfd, fdpout);
-      }
+  tmp16 = (uint16_t *) u8aIeeeHeader.i_dur;
+  *tmp16
+      =
+      (uint16_t)
+      htole16 ((sizeof (txt) +
+                sizeof (struct ieee80211_frame) * 1000000) / rate + 290);
+  tmp16 = (uint16_t *) u8aIeeeHeader.i_seq;
+  *tmp16 = (*tmp16 & IEEE80211_SEQ_FRAG_MASK) | (htole16 (seqenz)
+                                                 << IEEE80211_SEQ_SEQ_SHIFT);
+  seqenz++;
+
+  memcpy (buf, u8aRadiotap, sizeof (u8aRadiotap));
+  memcpy (buf + sizeof (u8aRadiotap), &u8aIeeeHeader, sizeof (u8aIeeeHeader));
+  memcpy (buf + sizeof (u8aRadiotap) + sizeof (u8aIeeeHeader), txt,
+          sizeof (txt));
+  return sizeof (u8aRadiotap) + sizeof (u8aIeeeHeader) + sizeof (txt);
 
+}
+#endif
 
-      retval = select(maxfd + 1, &rfds, &wfds, NULL, &tv);
 
-      if (-1 == retval && EINTR == errno)
-        {
-          continue;
-        }
-      if (0 > retval)
-        {
-          fprintf(stderr, "select failed: %s\n", strerror(errno));
-          exit(1);
-        }
+/**
+ * function to create GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL message for plugin
+ * @param buffer pointer to buffer for the message
+ * @param mac pointer to the mac address
+ * @return number of bytes written
+ */
+// FIXME: use 'struct MacAddress' for 'mac' (everywhere in this file)
+static int
+send_mac_to_plugin (char *buffer, uint8_t * mac)
+{
+  struct Wlan_Helper_Control_Message macmsg;
 
-      if (FD_ISSET(STDOUT_FILENO, &wfds))
-        {
-          ret = write(STDOUT_FILENO, write_std.buf + write_std.pos,
-              write_std.size - write_std.pos);
-
-          if (0 > ret)
-            {
-              closeprog = 1;
-              fprintf(stderr, "Write ERROR to STDOUT\n");
-              exit(1);
-            }
-          else
-            {
-              write_std.pos += ret;
-              // check if finished
-              if (write_std.pos == write_std.size)
-                {
-                  write_std.pos = 0;
-                  write_std.size = 0;
-                }
-            }
-        }
+  macmsg.hdr.size = htons (sizeof (struct Wlan_Helper_Control_Message));
+  macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
+  memcpy (macmsg.mac.mac, mac, sizeof (struct MacAddress));
+  memcpy (buffer, &macmsg, sizeof (struct Wlan_Helper_Control_Message));
+  return sizeof (struct Wlan_Helper_Control_Message);
+}
 
-      if (FD_ISSET(fdpout, &wfds))
-        {
-          ret = write(fdpout, write_pout.buf + write_pout.pos, write_pout.size
-              - write_pout.pos);
-
-          if (0 > ret)
-            {
-              closeprog = 1;
-              fprintf(stderr, "Write ERROR to fdpout\n");
-              exit(1);
-            }
-          else
-            {
-              write_pout.pos += ret;
-              // check if finished
-              if (write_pout.pos == write_pout.size)
-                {
-                  write_pout.pos = 0;
-                  write_pout.size = 0;
-                }
-            }
-        }
 
-      if (FD_ISSET(STDIN_FILENO, &rfds))
-        {
-          readsize = read(STDIN_FILENO, readbuf, sizeof(readbuf));
-
-          if (0 > readsize)
-            {
-              closeprog = 1;
-              fprintf(stderr, "Read ERROR to STDIN_FILENO\n");
-              exit(1);
-            }
-          else if (0 < readsize)
-            {
-              GNUNET_SERVER_mst_receive(stdin_mst, NULL, readbuf, readsize,
-                  GNUNET_NO, GNUNET_NO);
-
-            }
-        }
+static int
+hardwaremode (int argc, char *argv[])
+{
+  uid_t uid;
+  struct Hardware_Infos dev;
+  char readbuf[MAXLINE];
+  struct sendbuf write_std;
+  ssize_t ret;
+  int maxfd;
+  fd_set rfds;
+  fd_set wfds;
+  int retval;
+  int stdin_open;
+  struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst;
+
+  if (0 != wlaninit (&dev, argv[1]))
+    return 1;
+  uid = getuid ();
+  if (0 != setresuid (uid, uid, uid))
+  {
+    fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
+    /* not critical, continue anyway */
+  }
 
-      if (FD_ISSET(fdpin, &rfds))
-        {
-          readsize = read(fdpin, readbuf, sizeof(readbuf));
-
-          if (0 > readsize)
-            {
-              closeprog = 1;
-              fprintf(stderr, "Read ERROR to fdpin: %s\n", strerror(errno));
-              exit(1);
-            }
-          else if (0 < readsize)
-            {
-              GNUNET_SERVER_mst_receive(file_in_mst, NULL, readbuf, readsize,
-                  GNUNET_NO, GNUNET_NO);
-
-            }
-        }
+  dev.write_pout.size = 0;
+  dev.write_pout.pos = 0;
+  stdin_mst = GNUNET_SERVER_mst_create (&stdin_send_hw, &dev);
 
+  /* send mac to STDOUT first */
+  write_std.pos = 0;
+  write_std.size = send_mac_to_plugin ((char *) &write_std.buf, dev.pl_mac);
+  stdin_open = 1;
+
+  while (1)
+  {
+    maxfd = -1;
+    FD_ZERO (&rfds);
+    if ((0 == dev.write_pout.size) && (1 == stdin_open))
+    {
+      FD_SET (STDIN_FILENO, &rfds);
+      maxfd = MAX (maxfd, STDIN_FILENO);
     }
-
-  //clean up
-  fclose(fpout);
-  fclose(fpin);
-
-  if (1 == first)
+    if (0 == write_std.size)
     {
-      unlink(FIFO_FILE1);
-      unlink(FIFO_FILE2);
+      FD_SET (dev.fd_raw, &rfds);
+      maxfd = MAX (maxfd, dev.fd_raw);
     }
-
-  return (0);
-}
-
-
-int
-main(int argc, char *argv[])
-{
-  if (3 != argc)
+    FD_ZERO (&wfds);
+    if (0 < write_std.size)
     {
-      fprintf(
-          stderr,
-          "This program must be started with the interface and the operating mode as argument.\n");
-      return 1;
+      FD_SET (STDOUT_FILENO, &wfds);
+      maxfd = MAX (maxfd, STDOUT_FILENO);
+    }
+    if (0 < dev.write_pout.size)
+    {
+      FD_SET (dev.fd_raw, &wfds);
+      maxfd = MAX (maxfd, dev.fd_raw);
+    }
+    retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
+    if ((-1 == retval) && (EINTR == errno))
+      continue;
+    if (0 > retval)
+    {
+      fprintf (stderr, "select failed: %s\n", strerror (errno));
+      break;
     }
 
-  if (strstr(argv[2], "1") || strstr(argv[2], "2"))
+    if (FD_ISSET (STDOUT_FILENO, &wfds))
     {
+      ret = write (STDOUT_FILENO,
+                   write_std.buf + write_std.pos,
+                   write_std.size - write_std.pos);
+      if (0 > ret)
+      {
+        fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
+        break;
+      }
+      write_std.pos += ret;
+      if (write_std.pos == write_std.size)
+      {
+        write_std.pos = 0;
+        write_std.size = 0;
+      }
+    }
 
-      return testmode(argc, argv);
+    if (FD_ISSET (dev.fd_raw, &wfds))
+    {
+      ret = write (dev.fd_raw, dev.write_pout.buf, dev.write_pout.size);
+      if (0 > ret)
+      {
+        fprintf (stderr,
+                 "Line %u: Failed to write to WLAN device: %s, Message-Size: %u\n",
+                 __LINE__, strerror (errno), dev.write_pout.size);
+        break;
+      }
+      dev.write_pout.pos += ret;
+      if ((dev.write_pout.pos != dev.write_pout.size) && (ret != 0))
+      {
+        fprintf (stderr,
+                 "Line %u: Write error, partial send: %u/%u\n", __LINE__,
+                 dev.write_pout.pos, dev.write_pout.size);
+        break;
+      }
+      if (dev.write_pout.pos == dev.write_pout.size)
+      {
+        dev.write_pout.pos = 0;
+        dev.write_pout.size = 0;
+      }
     }
 
-#if 0
-       u8 u8aSendBuffer[500];
-       char szErrbuf[PCAP_ERRBUF_SIZE];
-       int nCaptureHeaderLength = 0, n80211HeaderLength = 0, nLinkEncap = 0;
-       int nOrdinal = 0, r, nDelay = 100000;
-       int nRateIndex = 0, retval, bytes;
-       pcap_t *ppcap = NULL;
-       struct bpf_program bpfprogram;
-       char * szProgram = "", fBrokenSocket = 0;
-       u16 u16HeaderLen;
-       char szHostname[PATH_MAX];
-
-       if (gethostname(szHostname, sizeof (szHostname) - 1)) {
-               perror("unable to get hostname");
-       }
-       szHostname[sizeof (szHostname) - 1] = '\0';
-
-
-       printf("Packetspammer (c)2007 Andy Green <andy@warmcat.com>  GPL2\n");
-
-       while (1) {
-               int nOptionIndex;
-               static const struct option optiona[] = {
-                       { "delay", required_argument, NULL, 'd' },
-                       { "fcs", no_argument, &flagMarkWithFCS, 1 },
-                       { "help", no_argument, &flagHelp, 1 },
-                       { "verbose", no_argument, &flagVerbose, 1},
-                       { 0, 0, 0, 0 }
-               };
-               int c = getopt_long(argc, argv, "d:hf",
-                       optiona, &nOptionIndex);
-
-               if (c == -1)
-                       break;
-               switch (c) {
-               case 0: // long option
-                       break;
-
-               case 'h': // help
-                       usage();
-
-               case 'd': // delay
-                       nDelay = atoi(optarg);
-                       break;
-
-               case 'f': // mark as FCS attached
-                       flagMarkWithFCS = 1;
-                       break;
-
-               case 'v': //Verbose / readable output to cout
-                       flagVerbose = 1;
-                       break;
-
-               default:
-                       printf("unknown switch %c\n", c);
-                       usage();
-                       break;
-               }
-       }
-
-       if (optind >= argc)
-               usage();
-
-
-               // open the interface in pcap
-
-       szErrbuf[0] = '\0';
-       ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf);
-       if (ppcap == NULL) {
-               printf("Unable to open interface %s in pcap: %s\n",
-                   argv[optind], szErrbuf);
-               return (1);
-       }
-
-       //get mac from interface
-
-       /*int sock, j, k;
-       char mac[32];
-
-       sock=socket(PF_INET, SOCK_STREAM, 0);
-       if (-1==sock) {
-               perror("can not open socket\n");
-               return 1;
-       }
-
-       if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) {
-               perror("ioctl(SIOCGIFHWADDR) ");
-               return 1;
-       }
-       for (j=0, k=0; j<6; j++) {
-               k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X",
-                       (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]);
-       }
-       mac[sizeof(mac)-1]='\0';
-       */
-
-       //get header type
-       nLinkEncap = pcap_datalink(ppcap);
-       nCaptureHeaderLength = 0;home/mwachs/gnb/bin/
-
-       switch (nLinkEncap) {
-
-               case DLT_PRISM_HEADER:
-                       printf("DLT_PRISM_HEADER Encap\n");
-                       nCaptureHeaderLength = 0x40;
-                       n80211HeaderLength = 0x20; // ieee80211 comes after this
-                       szProgram = "radio[0x4a:4]==0x13223344";
-                       break;
-
-               case DLT_IEEE802_11_RADIO:
-                       printf("DLT_IEEE802_11_RADIO Encap\n");
-                       nCaptureHeaderLength = 0x40;
-                       n80211HeaderLength = 0x18; // ieee80211 comes after this
-                       szProgram = "ether[0x0a:4]==0x13223344";
-                       break;
-
-               default:
-                       printf("!!! unknown encapsulation on %s !\n", argv[1]);
-                       return (1);
-
-       }
-
-       if (pcap_compile(ppcap, &bpfprogram, szProgram, 1, 0) == -1) {
-               puts(szProgram);
-               puts(pcap_geterr(ppcap));
-               return (1);
-       } else {
-               if (pcap_setfilter(ppcap, &bpfprogram) == -1) {
-                       puts(szProgram);
-                       puts(pcap_geterr(ppcap));
-               } else {
-                       printf("RX Filter applied\n");
-               }
-               pcap_freecode(&bpfprogram);
-       }
-
-       pcap_setnonblock(ppcap, 1, szErrbuf);
-
-       printf("   (delay between packets %dus)\n", nDelay);
-
-       memset(u8aSendBuffer, 0, sizeof (u8aSendBuffer));
-
-       while (!fBrokenSocket) {
-               u8 * pu8 = u8aSendBuffer;
-               struct pcap_pkthdr * ppcapPacketHeader = NULL;
-               struct ieee80211_radiotap_iterator rti;
-               PENUMBRA_RADIOTAP_DATA prd;
-               //init of the values
-               prd.m_nRate = 255;
-               prd.m_nChannel = 255;
-               prd.m_nAntenna = 255;
-               prd.m_nRadiotapFlags = 255;
-               u8 * pu8Payload = u8aSendBuffer;
-               int n, nRate;
-
-               // receive
-
-               retval = pcap_next_ex(ppcap, &ppcapPacketHeader,
-                   (const u_char**)&pu8Payload);
-
-               if (retval < 0) {
-                       fBrokenSocket = 1;
-                       continue;
-               }
-
-               if (retval != 1)
-                       goto do_tx;
-
-               u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8));
-
-               printf("rtap: ");
-               Dump(pu8Payload, u16HeaderLen);
-
-               if (ppcapPacketHeader->len <
-                   (u16HeaderLen + n80211HeaderLength))
-                       continue;
-
-               bytes = ppcapPacketHeader->len -
-                       (u16HeaderLen + n80211HeaderLength);
-               if (bytes < 0)
-                       continue;
-
-               if (ieee80211_radiotap_iterator_init(&rti,
-                   (struct ieee80211_radiotap_header *)pu8Payload,
-                   bytes) < 0)
-                       continue;
-
-               while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) {
-
-                       switch (rti.this_arg_index) {
-                       case IEEE80211_RADIOTAP_RATE:
-                               prd.m_nRate = (*rti.this_arg);
-                               break;
-
-                       case IEEE80211_RADIOTAP_CHANNEL:
-                               prd.m_nChannel =
-                                   le16_to_cpu(*((u16 *)rti.this_arg));
-                               prd.m_nChannelFlags =
-                                   le16_to_cpu(*((u16 *)(rti.this_arg + 2)));
-                               break;
-
-                       case IEEE80211_RADIOTAP_ANTENNA:
-                               prd.m_nAntenna = (*rti.this_arg) + 1;
-                               break;
-
-                       case IEEE80211_RADIOTAP_FLAGS:
-                               prd.m_nRadiotapFlags = *rti.this_arg;
-                               break;
-
-                       }
-               }
-
-               pu8Payload += u16HeaderLen + n80211HeaderLength;
-
-               if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS)
-                       bytes -= 4;
-
-               printf("RX: Rate: %2d.%dMbps, Freq: %d.%dGHz, "
-                   "Ant: %d, Flags: 0x%X\n",
-                   prd.m_nRate / 2, 5 * (prd.m_nRate & 1),
-                   prd.m_nChannel / 1000,
-                   prd.m_nChannel - ((prd.m_nChannel / 1000) * 1000),
-                   prd.m_nAntenna,
-                   prd.m_nRadiotapFlags);
-
-               Dump(pu8Payload, bytes);
-
-       do_tx:
-
-               // transmit
-
-               memcpy(u8aSendBuffer, u8aRadiotapHeader,
-                       sizeof (u8aRadiotapHeader));
-               if (flagMarkWithFCS)
-                       pu8[OFFSET_FLAGS] |= IEEE80211_RADIOTAP_F_FCS;
-               nRate = pu8[OFFSET_RATE] = u8aRatesToUse[nRateIndex++];
-               if (nRateIndex >= sizeof (u8aRatesToUse))
-                       nRateIndex = 0;
-               pu8 += sizeof (u8aRadiotapHeader);
-
-               memcpy(pu8, u8aIeeeHeader, sizeof (u8aIeeeHeader));
-               pu8 += sizeof (u8aIeeeHeader);
-
-               pu8 += sprintf((char *)u8aSendBuffer,
-                   "Packetspammer %02d"
-                   "broadcast packet"
-                   "#%05d -- :-D --%s ----",
-                   nRate/2, nOrdinal++, szHostname);
-               r = pcap_inject(ppcap, u8aSendBuffer, pu8 - u8aSendBuffer);
-               if (r != (pu8-u8aSendBuffer)) {
-                       perror("Trouble injecting packet");
-                       return (1);
-               }
-               if (nDelay)
-                       usleep(nDelay);
-       }
+    if (FD_ISSET (STDIN_FILENO, &rfds))
+    {
+      ret = read (STDIN_FILENO, readbuf, sizeof (readbuf));
+      if (0 > ret)
+      {
+        fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
+        break;
+      }
+      if (0 == ret)
+      {
+        /* stop reading... */
+        stdin_open = 0;
+      }
+      GNUNET_SERVER_mst_receive (stdin_mst, NULL,
+                                 readbuf, ret, GNUNET_NO, GNUNET_NO);
+    }
 
+    if (FD_ISSET (dev.fd_raw, &rfds))
+    {
+      struct GNUNET_MessageHeader *header;
+      struct Radiotap_rx *rxinfo;
+      struct ieee80211_frame *datastart;
+
+      header = (struct GNUNET_MessageHeader *) write_std.buf;
+      rxinfo = (struct Radiotap_rx *) &header[1];
+      datastart = (struct ieee80211_frame *) &rxinfo[1];
+      ret = linux_read (&dev,
+                        (unsigned char *) datastart,
+                        sizeof (write_std.buf) - sizeof (struct Radiotap_rx) -
+                        sizeof (struct GNUNET_MessageHeader), rxinfo);
+      if (0 > ret)
+      {
+        fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno));
+        break;
+      }
+      if ((0 < ret) && (0 == mac_test (datastart, &dev)))
+      {
+        write_std.size =
+            ret + sizeof (struct GNUNET_MessageHeader) +
+            sizeof (struct Radiotap_rx);
+        header->size = htons (write_std.size);
+        header->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
+      }
+    }
 
-#endif
-       return (0);
+  }
+  /* Error handling, try to clean up a bit at least */
+  GNUNET_SERVER_mst_destroy (stdin_mst);
+  close (dev.fd_raw);
+  return 1;
 }
 
+int
+main (int argc, char *argv[])
+{
+  if (2 != argc)
+  {
+    fprintf (stderr,
+             "This program must be started with the interface as argument.\nThis program was compiled at ----- %s ----\n",
+             __TIMESTAMP__);
+    fprintf (stderr, "Usage: interface-name\n" "\n");
+    return 1;
+  }
+  return hardwaremode (argc, argv);
+}