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') |
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 | ||||
42 | static 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 | ||||
76 | static char | |||
77 | AsciiToLowCase (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 | ||||
88 | static uint32_t | |||
89 | AsciiToIpv4 (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 | ||||
110 | static void | |||
111 | AsciiToMac48 (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 | ||||
141 | static sockaddr | |||
142 | CreateInetAddress (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 | ||||
154 | static void | |||
155 | SendSocket (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); | |||
| ||||
251 | cmsg->cmsg_level = SOL_SOCKET1; | |||
| ||||
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 | ||||
276 | static int | |||
277 | CreateTap (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 | ||||
353 | int | |||
354 | main (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 | } |