Bug Summary

File:/tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/tap-bridge/model/tap-creator.cc
Location:line 251, column 20
Description:Access to field 'cmsg_level' results in a dereference of a null pointer (loaded from variable 'cmsg')

Annotated Source Code

1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2009 University of Washington
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19#include <unistd.h>
20#include <stdint.h>
21#include <string>
22#include <cstring> // for strerror
23#include <iostream>
24#include <iomanip>
25#include <sstream>
26#include <cstdlib>
27#include <cerrno>
28#include <fcntl.h>
29#include <sys/ioctl.h>
30#include <sys/types.h>
31#include <sys/socket.h>
32#include <sys/un.h>
33#include <net/if.h>
34#include <linux/if_tun.h>
35#include <net/route.h>
36#include <netinet/in.h>
37
38#include "tap-encode-decode.h"
39
40#define TAP_MAGIC95549 95549
41
42static int gVerbose = 0; // Set to true to turn on logging messages.
43
44#define LOG(msg)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< msg << std::endl; }
\
45 if (gVerbose) \
46 { \
47 std::cout << __FUNCTION__ << "(): " << msg << std::endl; \
48 }
49
50#define ABORT(msg, printErrno)std::cout << "../src/tap-bridge/model/tap-creator.cc" <<
": fatal error at line " << 50 << ": " << __FUNCTION__
<< "(): " << msg << std::endl; if (printErrno
) { std::cout << " errno = " << (*__errno_location
()) << " (" << std::strerror ((*__errno_location
())) << ")" << std::endl; } std::exit (-1);
\
51 std::cout << __FILE__"../src/tap-bridge/model/tap-creator.cc" << ": fatal error at line " << __LINE__51 << ": " << __FUNCTION__ << "(): " << msg << std::endl; \
52 if (printErrno) \
53 { \
54 std::cout << " errno = " << errno(*__errno_location ()) << " (" << std::strerror (errno(*__errno_location ())) << ")" << std::endl; \
55 } \
56 std::exit (-1);
57
58#define ABORT_IF(cond, msg, printErrno)if (cond) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 58 << ": " <<
__FUNCTION__ << "(): " << msg << std::endl
; if (printErrno) { std::cout << " errno = " <<
(*__errno_location ()) << " (" << std::strerror (
(*__errno_location ())) << ")" << std::endl; } std
::exit (-1);; }
\
59 if (cond) \
60 { \
61 ABORT (msg, printErrno)std::cout << "../src/tap-bridge/model/tap-creator.cc" <<
": fatal error at line " << 61 << ": " << __FUNCTION__
<< "(): " << msg << std::endl; if (printErrno
) { std::cout << " errno = " << (*__errno_location
()) << " (" << std::strerror ((*__errno_location
())) << ")" << std::endl; } std::exit (-1);
; \
62 }
63
64//
65// Lots of the following helper code taken from corresponding functions in src/node.
66//
67#define ASCII_DOT(0x2e) (0x2e)
68#define ASCII_ZERO(0x30) (0x30)
69#define ASCII_a(0x41) (0x41)
70#define ASCII_z(0x5a) (0x5a)
71#define ASCII_A(0x61) (0x61)
72#define ASCII_Z(0x7a) (0x7a)
73#define ASCII_COLON(0x3a) (0x3a)
74#define ASCII_ZERO(0x30) (0x30)
75
76static char
77AsciiToLowCase (char c)
78{
79 if (c >= ASCII_a(0x41) && c <= ASCII_z(0x5a)) {
80 return c;
81 } else if (c >= ASCII_A(0x61) && c <= ASCII_Z(0x7a)) {
82 return c + (ASCII_a(0x41) - ASCII_A(0x61));
83 } else {
84 return c;
85 }
86}
87
88static uint32_t
89AsciiToIpv4 (const char *address)
90{
91 uint32_t host = 0;
92 while (true) {
93 uint8_t byte = 0;
94 while (*address != ASCII_DOT(0x2e) &&
95 *address != 0) {
96 byte *= 10;
97 byte += *address - ASCII_ZERO(0x30);
98 address++;
99 }
100 host <<= 8;
101 host |= byte;
102 if (*address == 0) {
103 break;
104 }
105 address++;
106 }
107 return host;
108}
109
110static void
111AsciiToMac48 (const char *str, uint8_t addr[6])
112{
113 int i = 0;
114 while (*str != 0 && i < 6)
115 {
116 uint8_t byte = 0;
117 while (*str != ASCII_COLON(0x3a) && *str != 0)
118 {
119 byte <<= 4;
120 char low = AsciiToLowCase (*str);
121 if (low >= ASCII_a(0x41))
122 {
123 byte |= low - ASCII_a(0x41) + 10;
124 }
125 else
126 {
127 byte |= low - ASCII_ZERO(0x30);
128 }
129 str++;
130 }
131 addr[i] = byte;
132 i++;
133 if (*str == 0)
134 {
135 break;
136 }
137 str++;
138 }
139}
140
141static sockaddr
142CreateInetAddress (uint32_t networkOrder)
143{
144 union {
145 struct sockaddr any_socket;
146 struct sockaddr_in si;
147 } s;
148 s.si.sin_family = AF_INET2;
149 s.si.sin_port = 0; // unused
150 s.si.sin_addr.s_addr = htonl (networkOrder);
151 return s.any_socket;
152}
153
154static void
155SendSocket (const char *path, int fd)
156{
157 //
158 // Open a Unix (local interprocess) socket to call back to the tap bridge
159 //
160 LOG ("Create Unix socket")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Create Unix socket" << std::endl; }
;
161 int sock = socket (PF_UNIX1, SOCK_DGRAMSOCK_DGRAM, 0);
162 ABORT_IF (sock == -1, "Unable to open socket", 1)if (sock == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 162 << ": "
<< __FUNCTION__ << "(): " << "Unable to open socket"
<< std::endl; if (1) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
163
164 //
165 // We have this string called path, which is really a hex representation
166 // of the endpoint that the tap bridge created. It used a forward encoding
167 // method (TapBufferToString) to take the sockaddr_un it made and passed
168 // the resulting string to us. So we need to take the inverse method
169 // (TapStringToBuffer) and build the same sockaddr_un over here.
170 //
171 socklen_t clientAddrLen;
172 struct sockaddr_un clientAddr;
173
174 LOG ("Decode address " << path)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Decode address " << path << std::endl;
}
;
175 bool rc = ns3::TapStringToBuffer (path, (uint8_t *)&clientAddr, &clientAddrLen);
176 ABORT_IF (rc == false, "Unable to decode path", 0)if (rc == false) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 176 << ": "
<< __FUNCTION__ << "(): " << "Unable to decode path"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
177
178 LOG ("Connect")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Connect" << std::endl; }
;
179 int status = connect (sock, (struct sockaddr*)&clientAddr, clientAddrLen);
180 ABORT_IF (status == -1, "Unable to connect to tap bridge", 1)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 180 << ": "
<< __FUNCTION__ << "(): " << "Unable to connect to tap bridge"
<< std::endl; if (1) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
181
182 LOG ("Connected")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Connected" << std::endl; }
;
183
184 //
185 // This is arcane enough that a few words are worthwhile to explain what's
186 // going on here.
187 //
188 // The interesting information (the socket FD) is going to go back to the
189 // tap bridge as an integer of ancillary data. Ancillary data is bits
190 // that are not a part a socket payload (out-of-band data). We're also
191 // going to send one integer back. It's just initialized to a magic number
192 // we use to make sure that the tap bridge is talking to the tap socket
193 // creator and not some other creator process (emu, specifically)
194 //
195 // The struct iovec below is part of a scatter-gather list. It describes a
196 // buffer. In this case, it describes a buffer (an integer) containing the
197 // data that we're going to send back to the tap bridge (that magic number).
198 //
199 struct iovec iov;
200 uint32_t magic = TAP_MAGIC95549;
201 iov.iov_base = &magic;
202 iov.iov_len = sizeof(magic);
203
204 //
205 // The CMSG macros you'll see below are used to create and access control
206 // messages (which is another name for ancillary data). The ancillary
207 // data is made up of pairs of struct cmsghdr structures and associated
208 // data arrays.
209 //
210 // First, we're going to allocate a buffer on the stack to contain our
211 // data array (that contains the socket). Sometimes you'll see this called
212 // an "ancillary element" but the msghdr uses the control message termimology
213 // so we call it "control."
214 //
215 size_t msg_size = sizeof(int);
216 char control[CMSG_SPACE (msg_size)((((msg_size) + sizeof (size_t) - 1) & (size_t) ~(sizeof (
size_t) - 1)) + (((sizeof (struct cmsghdr)) + sizeof (size_t)
- 1) & (size_t) ~(sizeof (size_t) - 1)))
];
217
218 //
219 // There is a msghdr that is used to minimize the number of parameters
220 // passed to sendmsg (which we will use to send our ancillary data). This
221 // structure uses terminology corresponding to control messages, so you'll
222 // see msg_control, which is the pointer to the ancillary data and controllen
223 // which is the size of the ancillary data array.
224 //
225 // So, initialize the message header that describes our ancillary/control data
226 // and point it to the control message/ancillary data we just allocated space
227 // for.
228 //
229 struct msghdr msg;
230 msg.msg_name = 0;
231 msg.msg_namelen = 0;
232 msg.msg_iov = &iov;
233 msg.msg_iovlen = 1;
234 msg.msg_control = control;
235 msg.msg_controllen = sizeof (control);
236 msg.msg_flags = 0;
237
238 //
239 // A cmsghdr contains a length field that is the length of the header and
240 // the data. It has a cmsg_level field corresponding to the originating
241 // protocol. This takes values which are legal levels for getsockopt and
242 // setsockopt (here SOL_SOCKET). We're going to use the SCM_RIGHTS type of
243 // cmsg, that indicates that the ancillary data array contains access rights
244 // that we are sending back to the tap bridge.
245 //
246 // We have to put together the first (and only) cmsghdr that will describe
247 // the whole package we're sending.
248 //
249 struct cmsghdr *cmsg;
250 cmsg = CMSG_FIRSTHDR (&msg)((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr
) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr
*) 0)
;
1
Null pointer value stored to 'cmsg'
251 cmsg->cmsg_level = SOL_SOCKET1;
2
Access to field 'cmsg_level' results in a dereference of a null pointer (loaded from variable 'cmsg')
252 cmsg->cmsg_type = SCM_RIGHTSSCM_RIGHTS;
253 cmsg->cmsg_len = CMSG_LEN (msg_size)((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t
) ~(sizeof (size_t) - 1)) + (msg_size))
;
254 //
255 // We also have to update the controllen in case other stuff is actually
256 // in there we may not be aware of (due to macros).
257 //
258 msg.msg_controllen = cmsg->cmsg_len;
259
260 //
261 // Finally, we get a pointer to the start of the ancillary data array and
262 // put our file descriptor in.
263 //
264 int *fdptr = (int*)(CMSG_DATA (cmsg)((unsigned char *) ((struct cmsghdr *) (cmsg) + 1)));
265 *fdptr = fd; //
266
267 //
268 // Actually send the file descriptor back to the tap bridge.
269 //
270 ssize_t len = sendmsg (sock, &msg, 0);
271 ABORT_IF (len == -1, "Could not send socket back to tap bridge", 1)if (len == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 271 << ": "
<< __FUNCTION__ << "(): " << "Could not send socket back to tap bridge"
<< std::endl; if (1) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
272
273 LOG ("sendmsg complete")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "sendmsg complete" << std::endl; }
;
274}
275
276static int
277CreateTap (const char *dev, const char *gw, const char *ip, const char *mac, const char *mode, const char *netmask)
278{
279 //
280 // Creation and management of Tap devices is done via the tun device
281 //
282 int tap = open ("/dev/net/tun", O_RDWR02);
283 ABORT_IF (tap == -1, "Could not open /dev/net/tun", true)if (tap == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 283 << ": "
<< __FUNCTION__ << "(): " << "Could not open /dev/net/tun"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
284
285 //
286 // Allocate a tap device, making sure that it will not send the tun_pi header.
287 // If we provide a null name to the ifr.ifr_name, we tell the kernel to pick
288 // a name for us (i.e., tapn where n = 0..255.
289 //
290 // If the device does not already exist, the system will create one.
291 //
292 struct ifreq ifr;
293 ifr.ifr_flagsifr_ifru.ifru_flags = IFF_TAP0x0002 | IFF_NO_PI0x1000;
294 strcpy (ifr.ifr_nameifr_ifrn.ifrn_name, dev);
295 int status = ioctl (tap, TUNSETIFF(((1U) << (((0 +8)+8)+14)) | ((('T')) << (0 +8)) |
(((202)) << 0) | ((((sizeof(int)))) << ((0 +8)+8
)))
, (void *) &ifr);
296 ABORT_IF (status == -1, "Could not allocate tap device", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 296 << ": "
<< __FUNCTION__ << "(): " << "Could not allocate tap device"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
297
298 std::string tapDeviceName = (char *)ifr.ifr_nameifr_ifrn.ifrn_name;
299 LOG ("Allocated TAP device " << tapDeviceName)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Allocated TAP device " << tapDeviceName <<
std::endl; }
;
300
301 //
302 // Operating mode "2" corresponds to USE_LOCAL and "3" to USE_BRIDGE mode.
303 // This means that we expect that the user will have named, created and
304 // configured a network tap that we are just going to use. So don't mess
305 // up his hard work by changing anything, just return the tap fd.
306 //
307 if (strcmp (mode, "2") == 0 || strcmp (mode, "3") == 0)
308 {
309 LOG ("Returning precreated tap ")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Returning precreated tap " << std::endl; }
;
310 return tap;
311 }
312
313 //
314 // Set the hardware (MAC) address of the new device
315 //
316 ifr.ifr_hwaddrifr_ifru.ifru_hwaddr.sa_family = 1; // this is ARPHRD_ETHER from if_arp.h
317 AsciiToMac48 (mac, (uint8_t*)ifr.ifr_hwaddrifr_ifru.ifru_hwaddr.sa_data);
318 status = ioctl (tap, SIOCSIFHWADDR0x8924, &ifr);
319 ABORT_IF (status == -1, "Could not set MAC address", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 319 << ": "
<< __FUNCTION__ << "(): " << "Could not set MAC address"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
320 LOG ("Set device MAC address to " << mac)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Set device MAC address to " << mac << std
::endl; }
;
321
322 int fd = socket (AF_INET2, SOCK_DGRAMSOCK_DGRAM, 0);
323
324 //
325 // Bring the interface up.
326 //
327 status = ioctl (fd, SIOCGIFFLAGS0x8913, &ifr);
328 ABORT_IF (status == -1, "Could not get flags for interface", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 328 << ": "
<< __FUNCTION__ << "(): " << "Could not get flags for interface"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
329 ifr.ifr_flagsifr_ifru.ifru_flags |= IFF_UPIFF_UP | IFF_RUNNINGIFF_RUNNING;
330 status = ioctl (fd, SIOCSIFFLAGS0x8914, &ifr);
331 ABORT_IF (status == -1, "Could not bring interface up", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 331 << ": "
<< __FUNCTION__ << "(): " << "Could not bring interface up"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
332 LOG ("Device is up")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Device is up" << std::endl; }
;
333
334 //
335 // Set the IP address of the new interface/device.
336 //
337 ifr.ifr_addrifr_ifru.ifru_addr = CreateInetAddress (AsciiToIpv4 (ip));
338 status = ioctl (fd, SIOCSIFADDR0x8916, &ifr);
339 ABORT_IF (status == -1, "Could not set IP address", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 339 << ": "
<< __FUNCTION__ << "(): " << "Could not set IP address"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
340 LOG ("Set device IP address to " << ip)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Set device IP address to " << ip << std
::endl; }
;
341
342 //
343 // Set the net mask of the new interface/device
344 //
345 ifr.ifr_netmaskifr_ifru.ifru_netmask = CreateInetAddress (AsciiToIpv4 (netmask));
346 status = ioctl (fd, SIOCSIFNETMASK0x891c, &ifr);
347 ABORT_IF (status == -1, "Could not set net mask", true)if (status == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 347 << ": "
<< __FUNCTION__ << "(): " << "Could not set net mask"
<< std::endl; if (true) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
348 LOG ("Set device Net Mask to " << netmask)if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Set device Net Mask to " << netmask <<
std::endl; }
;
349
350 return tap;
351}
352
353int
354main (int argc, char *argv[])
355{
356 int c;
357 char *dev = (char *)"";
358 char *gw = NULL__null;
359 char *ip = NULL__null;
360 char *mac = NULL__null;
361 char *netmask = NULL__null;
362 char *operatingMode = NULL__null;
363 char *path = NULL__null;
364
365 opterr = 0;
366
367 while ((c = getopt (argc, argv, "vd:g:i:m:n:o:p:")) != -1)
368 {
369 switch (c)
370 {
371 case 'd':
372 dev = optarg; // name of the new tap device
373 break;
374 case 'g':
375 gw = optarg; // gateway address for the new device
376 break;
377 case 'i':
378 ip = optarg; // ip address of the new device
379 break;
380 case 'm':
381 mac = optarg; // mac address of the new device
382 break;
383 case 'n':
384 netmask = optarg; // net mask for the new device
385 break;
386 case 'o':
387 operatingMode = optarg; // operating mode of tap bridge
388 break;
389 case 'p':
390 path = optarg; // path back to the tap bridge
391 break;
392 case 'v':
393 gVerbose = true;
394 break;
395 }
396 }
397
398 //
399 // We have got to be able to coordinate the name of the tap device we are
400 // going to create and or open with the device that an external Linux host
401 // will use. If this name is provided we use it. If not we let the system
402 // create the device for us. This name is given in dev
403 //
404 LOG ("Provided Device Name is \"" << dev << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided Device Name is \"" << dev << "\""
<< std::endl; }
;
405
406 //
407 // We have got to be able to provide a gateway to the external Linux host
408 // so it can talk to the ns-3 network. This ip address is provided in
409 // gw.
410 //
411 ABORT_IF (gw == NULL, "Gateway Address is a required argument", 0)if (gw == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 411 << ": "
<< __FUNCTION__ << "(): " << "Gateway Address is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
412 LOG ("Provided Gateway Address is \"" << gw << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided Gateway Address is \"" << gw <<
"\"" << std::endl; }
;
413
414 //
415 // We have got to be able to assign an IP address to the tap device we are
416 // allocating. This address is allocated in the simulation and assigned to
417 // the tap bridge. This address is given in ip.
418 //
419 ABORT_IF (ip == NULL, "IP Address is a required argument", 0)if (ip == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 419 << ": "
<< __FUNCTION__ << "(): " << "IP Address is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
420 LOG ("Provided IP Address is \"" << ip << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided IP Address is \"" << ip << "\""
<< std::endl; }
;
421
422 //
423 // We have got to be able to assign a Mac address to the tap device we are
424 // allocating. This address is allocated in the simulation and assigned to
425 // the bridged device. This allows packets addressed to the bridged device
426 // to appear in the Linux host as if they were received there.
427 //
428 ABORT_IF (mac == NULL, "MAC Address is a required argument", 0)if (mac == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 428 << ": "
<< __FUNCTION__ << "(): " << "MAC Address is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
429 LOG ("Provided MAC Address is \"" << mac << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided MAC Address is \"" << mac << "\""
<< std::endl; }
;
430
431 //
432 // We have got to be able to assign a net mask to the tap device we are
433 // allocating. This mask is allocated in the simulation and given to
434 // the bridged device.
435 //
436 ABORT_IF (netmask == NULL, "Net Mask is a required argument", 0)if (netmask == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 436 << ": "
<< __FUNCTION__ << "(): " << "Net Mask is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
437 LOG ("Provided Net Mask is \"" << netmask << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided Net Mask is \"" << netmask <<
"\"" << std::endl; }
;
438
439 //
440 // We have got to know whether or not to create the TAP.
441 //
442 ABORT_IF (operatingMode == NULL, "Operating Mode is a required argument", 0)if (operatingMode == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 442 << ": "
<< __FUNCTION__ << "(): " << "Operating Mode is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
443 LOG ("Provided Operating Mode is \"" << operatingMode << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided Operating Mode is \"" << operatingMode
<< "\"" << std::endl; }
;
444
445 //
446 // This program is spawned by a tap bridge running in a simulation. It
447 // wants to create a socket as described below. We are going to do the
448 // work here since we're running suid root. Once we create the socket,
449 // we have to send it back to the tap bridge. We do that over a Unix
450 // (local interprocess) socket. The tap bridge created a socket to
451 // listen for our response on, and it is expected to have encoded the address
452 // information as a string and to have passed that string as an argument to
453 // us. We see it here as the "path" string. We can't do anything useful
454 // unless we have that string.
455 //
456 ABORT_IF (path == NULL, "path is a required argument", 0)if (path == __null) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 456 << ": "
<< __FUNCTION__ << "(): " << "path is a required argument"
<< std::endl; if (0) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
457 LOG ("Provided path is \"" << path << "\"")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Provided path is \"" << path << "\"" <<
std::endl; }
;
458
459 //
460 // The whole reason for all of the hoops we went through to call out to this
461 // program will pay off here. We created this program to run as suid root
462 // in order to keep the main simulation program from having to be run with
463 // root privileges. We need root privileges to be able to futz with the
464 // Tap device underlying all of this. So all of these hoops are to allow
465 // us to exeucte the following code:
466 //
467 LOG ("Creating Tap")if (gVerbose) { std::cout << __FUNCTION__ << "(): "
<< "Creating Tap" << std::endl; }
;
468 int sock = CreateTap (dev, gw, ip, mac, operatingMode, netmask);
469 ABORT_IF (sock == -1, "main(): Unable to create tap socket", 1)if (sock == -1) { std::cout << "../src/tap-bridge/model/tap-creator.cc"
<< ": fatal error at line " << 469 << ": "
<< __FUNCTION__ << "(): " << "main(): Unable to create tap socket"
<< std::endl; if (1) { std::cout << " errno = "
<< (*__errno_location ()) << " (" << std::
strerror ((*__errno_location ())) << ")" << std::
endl; } std::exit (-1);; }
;
470
471 //
472 // Send the socket back to the tap net device so it can go about its business
473 //
474 SendSocket (path, sock);
475
476 return 0;
477}