1cfcf2c4e167a509b7a628043769930c5e3774f9
[oweals/gnunet.git] / src / transport / gnunet-transport-wlan-helper.c
1 /*
2  This file is part of GNUnet.
3  (C) 2010, 2011 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-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
26  *
27  * This program serves as the mediator between the wlan interface and
28  * gnunet
29  */
30
31 #define _GNU_SOURCE
32 #include <sys/socket.h>
33 #include <sys/ioctl.h>
34 #include <sys/types.h>
35 #include <unistd.h>
36 #include <sys/wait.h>
37 #include <sys/time.h>
38 #include <sys/stat.h>
39 #include <netpacket/packet.h>
40 #include <linux/if_ether.h>
41 #include <linux/if.h>
42 #include <linux/wireless.h>
43 #include <netinet/in.h>
44 #include <linux/if_tun.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <stdarg.h>
49 #include <fcntl.h>
50 #include <errno.h>
51 #include <dirent.h>
52 //#include <sys/utsname.h>
53 #include <sys/param.h>
54
55 /*
56  //#include <resolv.h>
57  #include <string.h>
58  #include <utime.h>
59  #include <getopt.h>
60  */
61 //#include "platform.h"
62 #include "gnunet_constants.h"
63 #include "gnunet_os_lib.h"
64 #include "gnunet_transport_plugin.h"
65 #include "transport.h"
66 #include "gnunet_util_lib.h"
67 #include "plugin_transport_wlan.h"
68 #include "gnunet_common.h"
69 #include "gnunet-transport-wlan-helper.h"
70 #include "gnunet_crypto_lib.h"
71
72 #include "wlan/radiotap-parser.h"
73 /* radiotap-parser defines types like u8 that
74  * ieee80211_radiotap.h needs
75  *
76  * we use our local copy of ieee80211_radiotap.h
77  *
78  * - since we can't support extensions we don't understand
79  * - since linux does not include it in userspace headers
80  */
81 #include "wlan/ieee80211_radiotap.h"
82 #include "wlan/crctable_osdep.h"
83 #include "wlan/loopback_helper.h"
84 #include "wlan/ieee80211.h"
85
86 #define ARPHRD_IEEE80211        801
87 #define ARPHRD_IEEE80211_PRISM  802
88 #define ARPHRD_IEEE80211_FULL   803
89
90 #include "wlan/loopback_helper.h"
91
92 #define DEBUG 1
93
94 #define MAC_ADDR_SIZE 6
95
96 struct Hardware_Infos
97 {
98
99   struct sendbuf write_pout;
100   int fd_raw;
101   int arptype_in;
102
103   /**
104    * Name of the interface, not necessarily 0-terminated (!).
105    */
106   char iface[IFNAMSIZ];
107   unsigned char pl_mac[MAC_ADDR_SIZE];
108 };
109
110 // FIXME: inline?
111 int getChannelFromFrequency (int frequency);
112
113 // FIXME: make nice...
114 static unsigned long
115 calc_crc_osdep (unsigned char *buf, int len)
116 {
117   unsigned long crc = 0xFFFFFFFF;
118
119   for (; len > 0; len--, buf++)
120     crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
121
122   return (~crc);
123 }
124
125 /* CRC checksum verification routine */
126
127 // FIXME: make nice...
128 static int
129 check_crc_buf_osdep (unsigned char *buf, int len)
130 {
131   unsigned long crc;
132
133   if (0 > len)
134     return 0;
135
136   crc = calc_crc_osdep (buf, len);
137   buf += len;
138   return (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] && ((crc
139                                                                          >> 16)
140                                                                         & 0xFF)
141           == buf[2] && ((crc >> 24) & 0xFF) == buf[3]);
142 }
143
144
145 // FIXME: make nice...
146 static int
147 linux_get_channel (struct Hardware_Infos *dev)
148 {
149   struct iwreq wrq;
150   int fd, frequency;
151   int chan = 0;
152
153   memset (&wrq, 0, sizeof (struct iwreq));
154
155   strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
156
157   fd = dev->fd_raw;
158   if (0 > ioctl (fd, SIOCGIWFREQ, &wrq))
159     return (-1);
160
161   frequency = wrq.u.freq.m;
162   if (100000000 < frequency)
163     frequency /= 100000;
164   else if (1000000 < frequency)
165     frequency /= 1000;
166
167   if (1000 < frequency)
168     chan = getChannelFromFrequency (frequency);
169   else
170     chan = frequency;
171
172   return chan;
173 }
174
175
176 // FIXME: make nice...
177 static ssize_t
178 linux_read (struct Hardware_Infos *dev, unsigned char *buf,     /* FIXME: void*? */
179             size_t buf_size, struct Radiotap_rx *ri)
180 {
181   unsigned char tmpbuf[buf_size];
182   ssize_t caplen;
183   int n, got_signal, got_noise, got_channel, fcs_removed;
184
185   n = got_signal = got_noise = got_channel = fcs_removed = 0;
186
187   caplen = read (dev->fd_raw, tmpbuf, buf_size);
188   if (0 > caplen)
189   {
190     if (EAGAIN == errno)
191       return 0;
192     fprintf (stderr, "Failed to read from RAW socket: %s\n", strerror (errno));
193     return -1;
194   }
195
196   memset (buf, 0, buf_size);
197   memset (ri, 0, sizeof (*ri));
198
199   switch (dev->arptype_in)
200   {
201   case ARPHRD_IEEE80211_PRISM:
202   {
203     /* skip the prism header */
204     if (tmpbuf[7] == 0x40)
205     {
206       /* prism54 uses a different format */
207       ri->ri_power = tmpbuf[0x33];
208       ri->ri_noise = *(unsigned int *) (tmpbuf + 0x33 + 12);
209       ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x33 + 24)) * 500000;
210       got_signal = 1;
211       got_noise = 1;
212       n = 0x40;
213     }
214     else
215     {
216       ri->ri_mactime = *(u_int64_t *) (tmpbuf + 0x5C - 48);
217       ri->ri_channel = *(unsigned int *) (tmpbuf + 0x5C - 36);
218       ri->ri_power = *(unsigned int *) (tmpbuf + 0x5C);
219       ri->ri_noise = *(unsigned int *) (tmpbuf + 0x5C + 12);
220       ri->ri_rate = (*(unsigned int *) (tmpbuf + 0x5C + 24)) * 500000;
221       got_channel = 1;
222       got_signal = 1;
223       got_noise = 1;
224       n = *(int *) (tmpbuf + 4);
225     }
226
227     if (n < 8 || n >= caplen)
228       return (0);
229   }
230     break;
231
232   case ARPHRD_IEEE80211_FULL:
233   {
234     struct ieee80211_radiotap_iterator iterator;
235     struct ieee80211_radiotap_header *rthdr;
236
237     rthdr = (struct ieee80211_radiotap_header *) tmpbuf;
238
239     if (ieee80211_radiotap_iterator_init (&iterator, rthdr, caplen) < 0)
240       return (0);
241
242     /* go through the radiotap arguments we have been given
243      * by the driver
244      */
245
246     while (ieee80211_radiotap_iterator_next (&iterator) >= 0)
247     {
248
249       switch (iterator.this_arg_index)
250       {
251
252       case IEEE80211_RADIOTAP_TSFT:
253         ri->ri_mactime = le64_to_cpu (*((uint64_t *) iterator.this_arg));
254         break;
255
256       case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
257         if (!got_signal)
258         {
259           if (*iterator.this_arg < 127)
260             ri->ri_power = *iterator.this_arg;
261           else
262             ri->ri_power = *iterator.this_arg - 255;
263
264           got_signal = 1;
265         }
266         break;
267
268       case IEEE80211_RADIOTAP_DB_ANTSIGNAL:
269         if (!got_signal)
270         {
271           if (*iterator.this_arg < 127)
272             ri->ri_power = *iterator.this_arg;
273           else
274             ri->ri_power = *iterator.this_arg - 255;
275
276           got_signal = 1;
277         }
278         break;
279
280       case IEEE80211_RADIOTAP_DBM_ANTNOISE:
281         if (!got_noise)
282         {
283           if (*iterator.this_arg < 127)
284             ri->ri_noise = *iterator.this_arg;
285           else
286             ri->ri_noise = *iterator.this_arg - 255;
287
288           got_noise = 1;
289         }
290         break;
291
292       case IEEE80211_RADIOTAP_DB_ANTNOISE:
293         if (!got_noise)
294         {
295           if (*iterator.this_arg < 127)
296             ri->ri_noise = *iterator.this_arg;
297           else
298             ri->ri_noise = *iterator.this_arg - 255;
299
300           got_noise = 1;
301         }
302         break;
303
304       case IEEE80211_RADIOTAP_ANTENNA:
305         ri->ri_antenna = *iterator.this_arg;
306         break;
307
308       case IEEE80211_RADIOTAP_CHANNEL:
309         ri->ri_channel = *iterator.this_arg;
310         got_channel = 1;
311         break;
312
313       case IEEE80211_RADIOTAP_RATE:
314         ri->ri_rate = (*iterator.this_arg) * 500000;
315         break;
316
317       case IEEE80211_RADIOTAP_FLAGS:
318         /* is the CRC visible at the end?
319          * remove
320          */
321         if (*iterator.this_arg & IEEE80211_RADIOTAP_F_FCS)
322         {
323           fcs_removed = 1;
324           caplen -= 4;
325         }
326
327         if (*iterator.this_arg & IEEE80211_RADIOTAP_F_RX_BADFCS)
328           return (0);
329
330         break;
331       }
332     }
333     n = le16_to_cpu (rthdr->it_len);
334     if (n <= 0 || n >= caplen)
335       return 0;
336   }
337     break;
338   case ARPHRD_IEEE80211:
339     /* do nothing? */
340     break;
341   default:
342     errno = ENOTSUP;
343     return -1;
344   }
345
346   caplen -= n;
347
348   //detect fcs at the end, even if the flag wasn't set and remove it
349   if ((0 == fcs_removed) && (1 == check_crc_buf_osdep (tmpbuf + n, caplen - 4)))
350   {
351     caplen -= 4;
352   }
353   memcpy (buf, tmpbuf + n, caplen);
354   if (!got_channel)
355     ri->ri_channel = linux_get_channel (dev);
356
357   return caplen;
358 }
359
360
361 /**
362  * @return 0 on success
363  */
364 static int
365 openraw (struct Hardware_Infos *dev)
366 {
367   struct ifreq ifr;
368   struct iwreq wrq;
369   struct packet_mreq mr;
370   struct sockaddr_ll sll;
371
372   /* find the interface index */
373   memset (&ifr, 0, sizeof (ifr));
374   strncpy (ifr.ifr_name, dev->iface, IFNAMSIZ);
375   if (-1 == ioctl (dev->fd_raw, SIOCGIFINDEX, &ifr))
376   {
377     fprintf (stderr,
378              "Line: 381 ioctl(SIOCGIFINDEX) on interface `%.*s' failed: %s\n",
379              IFNAMSIZ, dev->iface, strerror (errno));
380     return 1;
381   }
382
383   /* lookup the hardware type */
384   memset (&sll, 0, sizeof (sll));
385   sll.sll_family = AF_PACKET;
386   sll.sll_ifindex = ifr.ifr_ifindex;
387   sll.sll_protocol = htons (ETH_P_ALL);
388   if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr))
389   {
390     fprintf (stderr,
391              "ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n",
392              IFNAMSIZ, dev->iface, strerror (errno));
393     return 1;
394   }
395
396   /* lookup iw mode */
397   memset (&wrq, 0, sizeof (struct iwreq));
398   strncpy (wrq.ifr_name, dev->iface, IFNAMSIZ);
399   if (-1 == ioctl (dev->fd_raw, SIOCGIWMODE, &wrq))
400   {
401     /* most probably not supported (ie for rtap ipw interface) *
402      * so just assume its correctly set...                     */
403     wrq.u.mode = IW_MODE_MONITOR;
404   }
405
406   if (((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) &&
407        (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) &&
408        (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL)) ||
409       (wrq.u.mode != IW_MODE_MONITOR))
410   {
411     fprintf (stderr,
412              "Error: interface `%.*s' is not in monitor mode\n",
413              IFNAMSIZ, dev->iface);
414     return 1;
415   }
416
417   /* Is interface st to up, broadcast & running ? */
418   if ((ifr.ifr_flags | IFF_UP | IFF_BROADCAST | IFF_RUNNING) != ifr.ifr_flags)
419   {
420     /* Bring interface up */
421     ifr.ifr_flags |= IFF_UP | IFF_BROADCAST | IFF_RUNNING;
422
423     if (-1 == ioctl (dev->fd_raw, SIOCSIFFLAGS, &ifr))
424     {
425       fprintf (stderr,
426                "Line: 434 ioctl(SIOCSIFFLAGS) on interface `%.*s' failed: %s\n",
427                IFNAMSIZ, dev->iface, strerror (errno));
428       return 1;
429     }
430   }
431
432   /* bind the raw socket to the interface */
433   if (-1 == bind (dev->fd_raw, (struct sockaddr *) &sll, sizeof (sll)))
434   {
435     fprintf (stderr,
436              "Failed to bind interface `%.*s': %s\n",
437              IFNAMSIZ, dev->iface, strerror (errno));
438     return 1;
439   }
440
441   /* lookup the hardware type */
442   if (-1 == ioctl (dev->fd_raw, SIOCGIFHWADDR, &ifr))
443   {
444     fprintf (stderr,
445              "Line: 457 ioctl(SIOCGIFHWADDR) on interface `%.*s' failed: %s\n",
446              IFNAMSIZ, dev->iface, strerror (errno));
447     return 1;
448   }
449
450   memcpy (dev->pl_mac, ifr.ifr_hwaddr.sa_data, MAC_ADDR_SIZE);
451   dev->arptype_in = ifr.ifr_hwaddr.sa_family;
452   if ((ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211) &&
453       (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_PRISM) &&
454       (ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE80211_FULL))
455   {
456     fprintf (stderr,
457              "Unsupported hardware link type %d on interface `%.*s'\n",
458              ifr.ifr_hwaddr.sa_family, IFNAMSIZ, dev->iface);
459     return 1;
460   }
461
462   /* enable promiscuous mode */
463   memset (&mr, 0, sizeof (mr));
464   mr.mr_ifindex = sll.sll_ifindex;
465   mr.mr_type = PACKET_MR_PROMISC;
466   if (0 !=
467       setsockopt (dev->fd_raw, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr,
468                   sizeof (mr)))
469   {
470     fprintf (stderr,
471              "Failed to enable promiscuous mode on interface `%.*s'\n",
472              IFNAMSIZ, dev->iface);
473     return 1;
474   }
475
476   return 0;
477 }
478
479 /**
480  * @return 0 on success
481  */
482 static int
483 wlaninit (struct Hardware_Infos *dev, const char *iface)
484 {
485   char strbuf[512];
486   struct stat sbuf;
487   int ret;
488
489   dev->fd_raw = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL));
490   if (0 > dev->fd_raw)
491   {
492     fprintf (stderr, "Failed to create raw socket: %s\n", strerror (errno));
493     return 1;
494   }
495   if (dev->fd_raw >= FD_SETSIZE)
496   {
497     fprintf (stderr,
498              "File descriptor too large for select (%d > %d)\n",
499              dev->fd_raw, FD_SETSIZE);
500     close (dev->fd_raw);
501     return 1;
502   }
503
504   /* mac80211 stack detection */
505   ret = snprintf (strbuf,
506                   sizeof (strbuf),
507                   "/sys/class/net/%s/phy80211/subsystem", iface);
508   if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
509   {
510     fprintf (stderr, "Did not find 802.11 interface `%s'. Exiting.\n", iface);
511     close (dev->fd_raw);
512     return 1;
513   }
514   strncpy (dev->iface, iface, IFNAMSIZ);
515   if (0 != openraw (dev))
516   {
517     close (dev->fd_raw);
518     return 1;
519   }
520   return 0;
521 }
522
523
524 /**
525  * Function to test incoming packets mac for being our own.
526  *
527  * @param u8aIeeeHeader buffer of the packet
528  * @param dev the Hardware_Infos struct
529  * @return 0 if mac belongs to us, 1 if mac is for another target
530  */
531 static int
532 mac_test (const struct ieee80211_frame *u8aIeeeHeader,
533           const struct Hardware_Infos *dev)
534 {
535   if (0 != memcmp (u8aIeeeHeader->i_addr3, &mac_bssid, MAC_ADDR_SIZE))
536     return 1;
537   if (0 == memcmp (u8aIeeeHeader->i_addr1, dev->pl_mac, MAC_ADDR_SIZE))
538     return 0;
539   if (0 == memcmp (u8aIeeeHeader->i_addr1, &bc_all_mac, MAC_ADDR_SIZE))
540     return 0;
541   return 1;
542 }
543
544
545 /**
546  * function to set the wlan header to make attacks more difficult
547  * @param buf buffer of the packet
548  * @param dev pointer to the Hardware_Infos struct
549  */
550 static void
551 mac_set (struct ieee80211_frame *u8aIeeeHeader,
552          const struct Hardware_Infos *dev)
553 {
554   u8aIeeeHeader->i_fc[0] = 0x08;
555   u8aIeeeHeader->i_fc[1] = 0x00;
556   memcpy (u8aIeeeHeader->i_addr2, dev->pl_mac, MAC_ADDR_SIZE);
557   memcpy (u8aIeeeHeader->i_addr3, &mac_bssid, MAC_ADDR_SIZE);
558
559 }
560
561 struct RadioTapheader
562 {
563   struct ieee80211_radiotap_header header;
564   u8 rate;
565   u8 pad1;
566   u16 txflags;
567 };
568
569 static void
570 stdin_send_hw (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
571 {
572   struct Hardware_Infos *dev = cls;
573   struct sendbuf *write_pout = &dev->write_pout;
574   struct Radiotap_Send *header = (struct Radiotap_Send *) &hdr[1];
575   struct ieee80211_frame *wlanheader;
576   size_t sendsize;
577
578   // struct? // FIXME: make nice...
579   struct RadioTapheader rtheader;
580
581   rtheader.header.it_version = 0;
582   rtheader.header.it_len = htole16 (0x0c);
583   rtheader.header.it_present = htole32 (0x00008004);
584   rtheader.rate = 0x00;
585   rtheader.txflags =
586       htole16 (IEEE80211_RADIOTAP_F_TX_NOACK | IEEE80211_RADIOTAP_F_TX_NOSEQ);
587
588   /*  { 0x00, 0x00, <-- radiotap version
589    * 0x0c, 0x00, <- radiotap header length
590    * 0x04, 0x80, 0x00, 0x00,  <-- bitmap
591    * 0x00,  <-- rate
592    * 0x00,  <-- padding for natural alignment
593    * 0x18, 0x00,  <-- TX flags
594    * }; */
595
596   sendsize = ntohs (hdr->size);
597   if (sendsize <
598       sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader))
599   {
600     fprintf (stderr, "Function stdin_send_hw: mailformed packet (too small)\n");
601     exit (1);
602   }
603   sendsize -=
604       sizeof (struct Radiotap_Send) + sizeof (struct GNUNET_MessageHeader);
605
606   if (MAXLINE < sendsize)
607   {
608     fprintf (stderr, "Function stdin_send_hw: Packet too big for buffer\n");
609     exit (1);
610   }
611   if (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA != ntohs (hdr->type))
612   {
613     fprintf (stderr, "Function stdin_send: wrong packet type\n");
614     exit (1);
615   }
616
617   rtheader.header.it_len = htole16 (sizeof (rtheader));
618   rtheader.rate = header->rate;
619   memcpy (write_pout->buf, &rtheader, sizeof (rtheader));
620   memcpy (write_pout->buf + sizeof (rtheader), &header[1], sendsize);
621   /* payload contains MAC address, but we don't trust it, so we'll 
622    * overwrite it with OUR MAC address again to prevent mischief */
623   wlanheader = (struct ieee80211_frame *) (write_pout->buf + sizeof (rtheader));
624   mac_set (wlanheader, dev);
625   write_pout->size = sendsize + sizeof (rtheader);
626 }
627
628 #if 0
629 static int
630 maketest (unsigned char *buf, struct Hardware_Infos *dev)
631 {
632   uint16_t *tmp16;
633   static uint16_t seqenz = 0;
634   static int first = 0;
635
636   const int rate = 11000000;
637   static const char
638       txt[] =
639       "Hallo1Hallo2 Hallo3 Hallo4...998877665544332211Hallo1Hallo2 Hallo3 Hallo4...998877665544332211";
640
641   unsigned char u8aRadiotap[] = { 0x00, 0x00,   // <-- radiotap version
642     0x00, 0x00,                 // <- radiotap header length
643     0x04, 0x80, 0x02, 0x00,     // <-- bitmap
644     0x00,                       // <-- rate
645     0x00,                       // <-- padding for natural alignment
646     0x10, 0x00,                 // <-- TX flags
647     0x04                        //retries
648   };
649
650   /*uint8_t u8aRadiotap[] =
651    * {
652    * 0x00, 0x00, // <-- radiotap version
653    * 0x19, 0x00, // <- radiotap header length
654    * 0x6f, 0x08, 0x00, 0x00, // <-- bitmap
655    * 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp
656    * 0x00, // <-- flags (Offset +0x10)
657    * 0x6c, // <-- rate (0ffset +0x11)
658    * 0x71, 0x09, 0xc0, 0x00, // <-- channel
659    * 0xde, // <-- antsignal
660    * 0x00, // <-- antnoise
661    * 0x01, // <-- antenna
662    * }; */
663
664   u8aRadiotap[8] = (rate / 500000);
665   u8aRadiotap[2] = htole16 (sizeof (u8aRadiotap));
666
667   static struct ieee80211_frame u8aIeeeHeader;
668
669   uint8_t u8aIeeeHeader_def[] = { 0x08, 0x00,   // Frame Control 0x08= 00001000 -> | b1,2 = 0 -> Version 0;
670     //      b3,4 = 10 -> Data; b5-8 = 0 -> Normal Data
671     //      0x01 = 00000001 -> | b1 = 1 to DS; b2 = 0 not from DS;
672     0x00, 0x00,                 // Duration/ID
673
674     //0x00, 0x1f, 0x3f, 0xd1, 0x8e, 0xe6, // mac1 - in this case receiver
675     0x00, 0x1d, 0xe0, 0xb0, 0x17, 0xdf, // mac1 - in this case receiver
676     0xC0, 0x3F, 0x0E, 0x44, 0x2D, 0x51, // mac2 - in this case sender
677     //0x02, 0x1d, 0xe0, 0x00, 0x01, 0xc4,
678     0x13, 0x22, 0x33, 0x44, 0x55, 0x66, // mac3 - in this case bssid
679     0x10, 0x86,                 //Sequence Control
680   };
681   if (0 == first)
682   {
683     memcpy (&u8aIeeeHeader, u8aIeeeHeader_def, sizeof (struct ieee80211_frame));
684     memcpy (u8aIeeeHeader.i_addr2, dev->pl_mac, MAC_ADDR_SIZE);
685     first = 1;
686   }
687
688   tmp16 = (uint16_t *) u8aIeeeHeader.i_dur;
689   *tmp16
690       =
691       (uint16_t)
692       htole16 ((sizeof (txt) +
693                 sizeof (struct ieee80211_frame) * 1000000) / rate + 290);
694   tmp16 = (uint16_t *) u8aIeeeHeader.i_seq;
695   *tmp16 = (*tmp16 & IEEE80211_SEQ_FRAG_MASK) | (htole16 (seqenz)
696                                                  << IEEE80211_SEQ_SEQ_SHIFT);
697   seqenz++;
698
699   memcpy (buf, u8aRadiotap, sizeof (u8aRadiotap));
700   memcpy (buf + sizeof (u8aRadiotap), &u8aIeeeHeader, sizeof (u8aIeeeHeader));
701   memcpy (buf + sizeof (u8aRadiotap) + sizeof (u8aIeeeHeader), txt,
702           sizeof (txt));
703   return sizeof (u8aRadiotap) + sizeof (u8aIeeeHeader) + sizeof (txt);
704
705 }
706 #endif
707
708
709 /**
710  * function to create GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL message for plugin
711  * @param buffer pointer to buffer for the message
712  * @param mac pointer to the mac address
713  * @return number of bytes written
714  */
715 // FIXME: use 'struct MacAddress' for 'mac' (everywhere in this file)
716 static int
717 send_mac_to_plugin (char *buffer, uint8_t * mac)
718 {
719   struct Wlan_Helper_Control_Message macmsg;
720
721   macmsg.hdr.size = htons (sizeof (struct Wlan_Helper_Control_Message));
722   macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
723   memcpy (macmsg.mac.mac, mac, sizeof (struct MacAddress));
724   memcpy (buffer, &macmsg, sizeof (struct Wlan_Helper_Control_Message));
725   return sizeof (struct Wlan_Helper_Control_Message);
726 }
727
728
729 static int
730 hardwaremode (int argc, char *argv[])
731 {
732   uid_t uid;
733   struct Hardware_Infos dev;
734   char readbuf[MAXLINE];
735   struct sendbuf write_std;
736   ssize_t ret;
737   int maxfd;
738   fd_set rfds;
739   fd_set wfds;
740   int retval;
741   int stdin_open;
742   struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst;
743
744   if (0 != wlaninit (&dev, argv[1]))
745     return 1;
746   uid = getuid ();
747   if (0 != setresuid (uid, uid, uid))
748   {
749     fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
750     /* not critical, continue anyway */
751   }
752
753   dev.write_pout.size = 0;
754   dev.write_pout.pos = 0;
755   stdin_mst = GNUNET_SERVER_mst_create (&stdin_send_hw, &dev);
756
757   /* send mac to STDOUT first */
758   write_std.pos = 0;
759   write_std.size = send_mac_to_plugin ((char *) &write_std.buf, dev.pl_mac);
760   stdin_open = 1;
761
762   while (1)
763   {
764     maxfd = -1;
765     FD_ZERO (&rfds);
766     if ((0 == dev.write_pout.size) && (1 == stdin_open))
767     {
768       FD_SET (STDIN_FILENO, &rfds);
769       maxfd = MAX (maxfd, STDIN_FILENO);
770     }
771     if (0 == write_std.size)
772     {
773       FD_SET (dev.fd_raw, &rfds);
774       maxfd = MAX (maxfd, dev.fd_raw);
775     }
776     FD_ZERO (&wfds);
777     if (0 < write_std.size)
778     {
779       FD_SET (STDOUT_FILENO, &wfds);
780       maxfd = MAX (maxfd, STDOUT_FILENO);
781     }
782     if (0 < dev.write_pout.size)
783     {
784       FD_SET (dev.fd_raw, &wfds);
785       maxfd = MAX (maxfd, dev.fd_raw);
786     }
787     retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
788     if ((-1 == retval) && (EINTR == errno))
789       continue;
790     if (0 > retval)
791     {
792       fprintf (stderr, "select failed: %s\n", strerror (errno));
793       break;
794     }
795
796     if (FD_ISSET (STDOUT_FILENO, &wfds))
797     {
798       ret = write (STDOUT_FILENO,
799                    write_std.buf + write_std.pos,
800                    write_std.size - write_std.pos);
801       if (0 > ret)
802       {
803         fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
804         break;
805       }
806       write_std.pos += ret;
807       if (write_std.pos == write_std.size)
808       {
809         write_std.pos = 0;
810         write_std.size = 0;
811       }
812     }
813
814     if (FD_ISSET (dev.fd_raw, &wfds))
815     {
816       ret = write (dev.fd_raw, dev.write_pout.buf, dev.write_pout.size);
817       if (0 > ret)
818       {
819         fprintf (stderr,
820                  "Line %u: Failed to write to WLAN device: %s, Message-Size: %u\n",
821                  __LINE__, strerror (errno), dev.write_pout.size);
822         break;
823       }
824       dev.write_pout.pos += ret;
825       if ((dev.write_pout.pos != dev.write_pout.size) && (ret != 0))
826       {
827         fprintf (stderr,
828                  "Line %u: Write error, partial send: %u/%u\n", __LINE__,
829                  dev.write_pout.pos, dev.write_pout.size);
830         break;
831       }
832       if (dev.write_pout.pos == dev.write_pout.size)
833       {
834         dev.write_pout.pos = 0;
835         dev.write_pout.size = 0;
836       }
837     }
838
839     if (FD_ISSET (STDIN_FILENO, &rfds))
840     {
841       ret = read (STDIN_FILENO, readbuf, sizeof (readbuf));
842       if (0 > ret)
843       {
844         fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
845         break;
846       }
847       if (0 == ret)
848       {
849         /* stop reading... */
850         stdin_open = 0;
851       }
852       GNUNET_SERVER_mst_receive (stdin_mst, NULL,
853                                  readbuf, ret, GNUNET_NO, GNUNET_NO);
854     }
855
856     if (FD_ISSET (dev.fd_raw, &rfds))
857     {
858       struct GNUNET_MessageHeader *header;
859       struct Radiotap_rx *rxinfo;
860       struct ieee80211_frame *datastart;
861
862       header = (struct GNUNET_MessageHeader *) write_std.buf;
863       rxinfo = (struct Radiotap_rx *) &header[1];
864       datastart = (struct ieee80211_frame *) &rxinfo[1];
865       ret = linux_read (&dev,
866                         (unsigned char *) datastart,
867                         sizeof (write_std.buf) - sizeof (struct Radiotap_rx) -
868                         sizeof (struct GNUNET_MessageHeader), rxinfo);
869       if (0 > ret)
870       {
871         fprintf (stderr, "Read error from raw socket: %s\n", strerror (errno));
872         break;
873       }
874       if ((0 < ret) && (0 == mac_test (datastart, &dev)))
875       {
876         write_std.size =
877             ret + sizeof (struct GNUNET_MessageHeader) +
878             sizeof (struct Radiotap_rx);
879         header->size = htons (write_std.size);
880         header->type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_DATA);
881       }
882     }
883
884   }
885   /* Error handling, try to clean up a bit at least */
886   GNUNET_SERVER_mst_destroy (stdin_mst);
887   close (dev.fd_raw);
888   return 1;
889 }
890
891 int
892 main (int argc, char *argv[])
893 {
894   if (2 != argc)
895   {
896     fprintf (stderr,
897              "This program must be started with the interface as argument.\nThis program was compiled at ----- %s ----\n",
898              __TIMESTAMP__);
899     fprintf (stderr, "Usage: interface-name\n" "\n");
900     return 1;
901   }
902   return hardwaremode (argc, argv);
903 }