glitch in the license text detected by hyazinthe, thank you!
[oweals/gnunet.git] / src / transport / gnunet-transport-wlan-sender.c
1 /*
2  This file is part of GNUnet
3  Copyright (C) 2011 GNUnet e.V.
4
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your 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  Affero General Public License for more details.
14  */
15
16 /**
17  * @file transport/gnunet-transport-wlan-sender.c
18  * @brief program to send via WLAN as much as possible (to test physical/theoretical throughput)
19  * @author David Brodski
20  */
21 #include "platform.h"
22 #include "plugin_transport_wlan.h"
23 #include "gnunet_protocols.h"
24
25 #define WLAN_MTU 1500
26
27 /**
28  * LLC fields for better compatibility
29  */
30 #define WLAN_LLC_DSAP_FIELD 0x1f
31 #define WLAN_LLC_SSAP_FIELD 0x1f
32
33 #define IEEE80211_ADDR_LEN      6       /* size of 802.11 address */
34
35 #define IEEE80211_FC0_VERSION_MASK              0x03
36 #define IEEE80211_FC0_VERSION_SHIFT             0
37 #define IEEE80211_FC0_VERSION_0                 0x00
38 #define IEEE80211_FC0_TYPE_MASK                 0x0c
39 #define IEEE80211_FC0_TYPE_SHIFT                2
40 #define IEEE80211_FC0_TYPE_MGT                  0x00
41 #define IEEE80211_FC0_TYPE_CTL                  0x04
42 #define IEEE80211_FC0_TYPE_DATA                 0x08
43
44
45 /**
46  * function to fill the radiotap header
47  * @param header pointer to the radiotap header
48  * @param size total message size
49  * @return GNUNET_YES at success
50  */
51 static int
52 getRadiotapHeader (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header,
53                    uint16_t size)
54 {
55   header->header.size = htons (size);
56   header->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER);
57   header->rate = 255;
58   header->tx_power = 0;
59   header->antenna = 0;
60   return GNUNET_YES;
61 }
62
63 /**
64  * function to generate the wlan hardware header for one packet
65  * @param Header address to write the header to
66  * @param to_mac_addr pointer to the address of the recipient
67  * @param mac pointer to the mac address to send from (normally overwritten over by helper)
68  * @param size size of the whole packet, needed to calculate the time to send the packet
69  * @return GNUNET_YES if there was no error
70  */
71 static int
72 getWlanHeader (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *Header,
73                const struct GNUNET_TRANSPORT_WLAN_MacAddress *to_mac_addr,
74                const struct GNUNET_TRANSPORT_WLAN_MacAddress *mac, unsigned int size)
75 {
76   const int rate = 11000000;
77
78   Header->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
79   Header->addr3 = mac_bssid_gnunet;
80   Header->addr2 = *mac;
81   Header->addr1 = *to_mac_addr;
82   Header->duration = GNUNET_htole16 ((size * 1000000) / rate + 290);
83   Header->llc[0] = WLAN_LLC_DSAP_FIELD;
84   Header->llc[1] = WLAN_LLC_SSAP_FIELD;
85   Header->llc[2] = 0; // FIXME
86   Header->llc[3] = 0; // FIXME
87   return GNUNET_YES;
88 }
89
90
91 int
92 main (int argc, char *argv[])
93 {
94   char msg_buf[WLAN_MTU];
95   struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *radiotap;
96   unsigned int temp[6];
97   struct GNUNET_TRANSPORT_WLAN_MacAddress inmac;
98   struct GNUNET_TRANSPORT_WLAN_MacAddress outmac;
99   struct GNUNET_TRANSPORT_WLAN_HelperControlMessage hcm;
100   unsigned long long count;
101   double bytes_per_s;
102   time_t start;
103   time_t akt;
104   int i;
105   ssize_t ret;
106   pid_t pid;
107   int commpipe[2];              /* This holds the fd for the input & output of the pipe */
108   int macpipe[2];              /* This holds the fd for the input & output of the pipe */
109
110   if (4 != argc)
111   {
112     fprintf (stderr,
113              "This program must be started with the interface and the targets and source mac as argument.\n");
114     fprintf (stderr,
115              "Usage: interface-name mac-DST mac-SRC\n"
116              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
117     return 1;
118   }
119   if (6 !=
120       SSCANF (argv[2], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
121               &temp[3], &temp[4], &temp[5]))
122   {
123     fprintf (stderr,
124              "Usage: interface-name mac-DST mac-SRC\n"
125              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
126     return 1;
127   }
128   for (i = 0; i < 6; i++)
129     outmac.mac[i] = temp[i];
130   if (6 !=
131       SSCANF (argv[3], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
132               &temp[3], &temp[4], &temp[5]))
133   {
134     fprintf (stderr,
135              "Usage: interface-name mac-DST mac-SRC\n"
136              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
137     return 1;
138   }
139   for (i = 0; i < 6; i++)
140     inmac.mac[i] = temp[i];
141
142
143   /* Setup communication pipeline first */
144   if (pipe (commpipe))
145   {
146     fprintf (stderr,
147              "Failed to create pipe: %s\n",
148              STRERROR (errno));
149     exit (1);
150   }
151   if (pipe (macpipe))
152   {
153     fprintf (stderr,
154              "Failed to create pipe: %s\n",
155              STRERROR (errno));
156     exit (1);
157   }
158
159   /* Attempt to fork and check for errors */
160   if ((pid = fork ()) == -1)
161   {
162     fprintf (stderr, "Failed to fork: %s\n",
163              STRERROR (errno));
164     exit (1);
165   }
166   memset (msg_buf, 0x42, sizeof (msg_buf));
167   if (pid)
168   {
169     /* A positive (non-negative) PID indicates the parent process */
170     if (0 != close (commpipe[0]))        /* Close unused side of pipe (in side) */
171       fprintf (stderr,
172                "Failed to close fd: %s\n",
173                strerror (errno));
174     setvbuf (stdout, (char *) NULL, _IONBF, 0); /* Set non-buffered output on stdout */
175
176     if (0 != close (macpipe[1]))
177       fprintf (stderr,
178                "Failed to close fd: %s\n",
179                strerror (errno));
180     if (sizeof (hcm) != read (macpipe[0], &hcm, sizeof (hcm)))
181       fprintf (stderr,
182                "Failed to read hcm...\n");
183     fprintf (stderr,
184              "Got MAC %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n",
185              hcm.mac.mac[0], hcm.mac.mac[1],
186              hcm.mac.mac[2], hcm.mac.mac[3], hcm.mac.mac[4], hcm.mac.mac[5]);                           
187     radiotap = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) msg_buf;
188     getRadiotapHeader (radiotap, WLAN_MTU);
189     getWlanHeader (&radiotap->frame, &outmac, &inmac,
190                    WLAN_MTU);
191     start = time (NULL);
192     count = 0;
193     while (1)
194     {
195       ret = write (commpipe[1], msg_buf, WLAN_MTU);
196       if (0 > ret)
197       {
198         fprintf (stderr, "write failed: %s\n", strerror (errno));
199         break;
200       }
201       count += ret;
202       akt =  time (NULL);
203       if (akt - start > 30)
204       {
205         bytes_per_s = count / (akt - start);
206         bytes_per_s /= 1024;
207         printf ("send %f kbytes/s\n", bytes_per_s);
208         start = akt;
209         count = 0;
210       }
211     }
212   }
213   else
214   {
215     /* A zero PID indicates that this is the child process */
216     (void) close (0);
217     (void) close (1);
218     if (-1 == dup2 (commpipe[0], 0))    /* Replace stdin with the in side of the pipe */
219       fprintf (stderr, "dup2 failed: %s\n", strerror (errno));
220     if (-1 == dup2 (macpipe[1], 1))    /* Replace stdout with the out side of the pipe */
221       fprintf (stderr, "dup2 failed: %s\n", strerror (errno));
222     (void) close (commpipe[1]); /* Close unused side of pipe (out side) */
223     (void) close (macpipe[0]); /* Close unused side of pipe (in side) */
224     /* Replace the child fork with a new process */
225     if (execlp
226         ("gnunet-helper-transport-wlan", "gnunet-helper-transport-wlan",
227          argv[1], NULL) == -1)
228     {
229       fprintf (stderr, "Could not start gnunet-helper-transport-wlan!");
230       _exit (1);
231     }
232   }
233   return 0;
234 }