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