hunting bugs
[oweals/gnunet.git] / src / transport / gnunet-transport-wlan-sender.c
1 /*
2  This file is part of GNUnet
3  (C) 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 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 "gnunet_protocols.h"
28 #include "plugin_transport_wlan.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   int pos;
105   long long count;
106   double bytes_per_s;
107   time_t start;
108   time_t akt;
109   int i;
110
111   if (4 != argc)
112   {
113     fprintf (stderr,
114              "This program must be started with the interface and the targets and source mac as argument.\n");
115     fprintf (stderr,
116              "Usage: interface-name mac-target mac-source\n"
117              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
118     return 1;
119   }
120   if (6 !=
121       SSCANF (argv[3], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
122               &temp[3], &temp[4], &temp[5]))
123   {
124     fprintf (stderr,
125              "Usage: interface-name mac-target mac-source\n"
126              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
127     return 1;
128   }
129   for (i = 0; i < 6; i++)
130     outmac.mac[i] = temp[i];
131   if (6 !=
132       SSCANF (argv[2], "%x-%x-%x-%x-%x-%x", &temp[0], &temp[1], &temp[2],
133               &temp[3], &temp[4], &temp[5]))
134   {
135     fprintf (stderr,
136              "Usage: interface-name mac-target mac-source\n"
137              "e.g. mon0 11-22-33-44-55-66 12-34-56-78-90-ab\n");
138     return 1;
139   }
140   for (i = 0; i < 6; i++)
141     inmac.mac[i] = temp[i];
142
143   pid_t pid;
144   int commpipe[2];              /* This holds the fd for the input & output of the pipe */
145
146   /* Setup communication pipeline first */
147   if (pipe (commpipe))
148   {
149     fprintf (stderr, 
150              "Failed to create pipe: %s\n",
151              STRERROR (errno));
152     exit (1);
153   }
154
155   /* Attempt to fork and check for errors */
156   if ((pid = fork ()) == -1)
157   {
158     fprintf (stderr, "Failed to fork: %s\n", 
159              STRERROR (errno));    
160     exit (1);
161   }
162
163   if (pid)
164   {
165     /* A positive (non-negative) PID indicates the parent process */
166     if (0 != close (commpipe[0]))        /* Close unused side of pipe (in side) */
167       fprintf (stderr,
168                "Failed to close fd: %s\n",
169                strerror (errno));
170     setvbuf (stdout, (char *) NULL, _IONBF, 0); /* Set non-buffered output on stdout */
171
172
173     radiotap = (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) msg_buf;
174     getRadiotapHeader (radiotap, WLAN_MTU);
175     pos = 0;
176     getWlanHeader (&radiotap->frame, &outmac, &inmac,
177                    WLAN_MTU);
178     start = time (NULL);
179     count = 0;
180     while (1)
181     {
182       pos += write (commpipe[1], msg_buf, WLAN_MTU - pos);
183       if (pos % WLAN_MTU == 0)
184       {
185         pos = 0;
186         count++;
187
188         if (count % 1000 == 0)
189         {
190           akt = time (NULL);
191           bytes_per_s = count * WLAN_MTU / (akt - start);
192           bytes_per_s /= 1024;
193           printf ("send %f kbytes/s\n", bytes_per_s);
194         }
195       }
196
197     }
198   }
199   else
200   {
201     /* A zero PID indicates that this is the child process */
202     (void) close (0);
203     if (-1 == dup2 (commpipe[0], 0))    /* Replace stdin with the in side of the pipe */
204       fprintf (stderr, "dup2 failed: %s\n", strerror (errno));
205     (void) close (commpipe[1]); /* Close unused side of pipe (out side) */
206     /* Replace the child fork with a new process */
207     if (execl
208         ("gnunet-helper-transport-wlan", "gnunet-helper-transport-wlan",
209          argv[1], NULL) == -1)
210     {
211       fprintf (stderr, "Could not start gnunet-helper-transport-wlan!");
212       _exit (1);
213     }
214   }
215   return 0;
216 }