File: | /tmp/asd-nat/home/nat/Work/ns-3-dev-git/build/../src/fd-net-device/helper/creator-utils.cc |
Location: | line 152, 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) 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 <string> | |||
21 | #include <cstring> | |||
22 | #include <iostream> | |||
23 | #include <iomanip> | |||
24 | #include <sstream> | |||
25 | #include <stdlib.h> | |||
26 | #include <errno(*__errno_location ()).h> | |||
27 | ||||
28 | #include <sys/socket.h> | |||
29 | #include <sys/un.h> | |||
30 | #include <sys/ioctl.h> | |||
31 | #include <net/ethernet.h> | |||
32 | #include <net/if.h> | |||
33 | #include <netinet/in.h> | |||
34 | #include <arpa/inet.h> | |||
35 | ||||
36 | #include "creator-utils.h" | |||
37 | #include "encode-decode.h" | |||
38 | ||||
39 | namespace ns3 { | |||
40 | ||||
41 | /// Flag to enable / disable verbose log mode | |||
42 | int gVerbose = 0; | |||
43 | ||||
44 | /** | |||
45 | * \brief Send the file descriptor back to the code that invoked the creation. | |||
46 | * | |||
47 | * \param path The socket address information from the Unix socket we use | |||
48 | * to send the created socket back to. | |||
49 | * \param fd The file descriptor we're going to send. | |||
50 | * \param magic_number A verification number to verify the caller is talking to the | |||
51 | * right process. | |||
52 | */ | |||
53 | void | |||
54 | SendSocket (const char *path, int fd, const int magic_number) | |||
55 | { | |||
56 | // | |||
57 | // Open a Unix (local interprocess) socket to call back to the emu net | |||
58 | // device. | |||
59 | // | |||
60 | LOG ("Create Unix socket")if (gVerbose) { std::cout << __FUNCTION__ << "(): " << "Create Unix socket" << std::endl; }; | |||
61 | int sock = socket (PF_UNIX1, SOCK_DGRAMSOCK_DGRAM, 0); | |||
62 | ABORT_IF (sock == -1, "Unable to open socket", 1)if (sock == -1) { std::cout << "../src/fd-net-device/helper/creator-utils.cc" << ": fatal error at line " << 62 << ": " << __FUNCTION__ << "(): " << "Unable to open socket" << std::endl; if (1) { std::cout << " errno = " << (*__errno_location ()) << " (" << strerror ((*__errno_location ())) << ")" << std::endl; } exit (-1);; }; | |||
63 | ||||
64 | // | |||
65 | // We have this string called path, which is really a hex representation | |||
66 | // of the endpoint that the net device created. It used a forward encoding | |||
67 | // method (BufferToString) to take the sockaddr_un it made and passed | |||
68 | // the resulting string to us. So we need to take the inverse method | |||
69 | // (StringToBuffer) and build the same sockaddr_un over here. | |||
70 | // | |||
71 | socklen_t clientAddrLen; | |||
72 | struct sockaddr_un clientAddr; | |||
73 | ||||
74 | LOG ("Decode address " << path)if (gVerbose) { std::cout << __FUNCTION__ << "(): " << "Decode address " << path << std::endl; }; | |||
75 | bool rc = ns3::StringToBuffer (path, (uint8_t *)&clientAddr, &clientAddrLen); | |||
76 | ABORT_IF (rc == false, "Unable to decode path", 0)if (rc == false) { std::cout << "../src/fd-net-device/helper/creator-utils.cc" << ": fatal error at line " << 76 << ": " << __FUNCTION__ << "(): " << "Unable to decode path" << std::endl; if (0) { std::cout << " errno = " << (*__errno_location ()) << " (" << strerror ((*__errno_location ())) << ")" << std::endl; } exit (-1);; }; | |||
77 | ||||
78 | LOG ("Connect")if (gVerbose) { std::cout << __FUNCTION__ << "(): " << "Connect" << std::endl; }; | |||
79 | int status = connect (sock, (struct sockaddr*)&clientAddr, clientAddrLen); | |||
80 | ABORT_IF (status == -1, "Unable to connect to emu device", 1)if (status == -1) { std::cout << "../src/fd-net-device/helper/creator-utils.cc" << ": fatal error at line " << 80 << ": " << __FUNCTION__ << "(): " << "Unable to connect to emu device" << std::endl; if (1) { std::cout << " errno = " << (*__errno_location ()) << " (" << strerror ((*__errno_location ())) << ")" << std::endl; } exit (-1);; }; | |||
81 | ||||
82 | LOG ("Connected")if (gVerbose) { std::cout << __FUNCTION__ << "(): " << "Connected" << std::endl; }; | |||
83 | ||||
84 | // | |||
85 | // This is arcane enough that a few words are worthwhile to explain what's | |||
86 | // going on here. | |||
87 | // | |||
88 | // The interesting information (the socket FD) is going to go back to the | |||
89 | // fd net device as an integer of ancillary data. Ancillary data is bits | |||
90 | // that are not a part a socket payload (out-of-band data). We're also | |||
91 | // going to send one integer back. It's just initialized to a magic number | |||
92 | // we use to make sure that the fd device is talking to the emu socket | |||
93 | // creator and not some other creator process. | |||
94 | // | |||
95 | // The struct iovec below is part of a scatter-gather list. It describes a | |||
96 | // buffer. In this case, it describes a buffer (an integer) containing the | |||
97 | // data that we're going to send back to the emu net device (that magic | |||
98 | // number). | |||
99 | // | |||
100 | struct iovec iov; | |||
101 | uint32_t magic = magic_number; | |||
102 | iov.iov_base = &magic; | |||
103 | iov.iov_len = sizeof(magic); | |||
104 | ||||
105 | // | |||
106 | // The CMSG macros you'll see below are used to create and access control | |||
107 | // messages (which is another name for ancillary data). The ancillary | |||
108 | // data is made up of pairs of struct cmsghdr structures and associated | |||
109 | // data arrays. | |||
110 | // | |||
111 | // First, we're going to allocate a buffer on the stack to contain our | |||
112 | // data array (that contains the socket). Sometimes you'll see this called | |||
113 | // an "ancillary element" but the msghdr uses the control message termimology | |||
114 | // so we call it "control." | |||
115 | // | |||
116 | size_t msg_size = sizeof(int); | |||
117 | 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)))]; | |||
118 | ||||
119 | // | |||
120 | // There is a msghdr that is used to minimize the number of parameters | |||
121 | // passed to sendmsg (which we will use to send our ancillary data). This | |||
122 | // structure uses terminology corresponding to control messages, so you'll | |||
123 | // see msg_control, which is the pointer to the ancillary data and controllen | |||
124 | // which is the size of the ancillary data array. | |||
125 | // | |||
126 | // So, initialize the message header that describes our ancillary/control data | |||
127 | // and point it to the control message/ancillary data we just allocated space | |||
128 | // for. | |||
129 | // | |||
130 | struct msghdr msg; | |||
131 | msg.msg_name = 0; | |||
132 | msg.msg_namelen = 0; | |||
133 | msg.msg_iov = &iov; | |||
134 | msg.msg_iovlen = 1; | |||
135 | msg.msg_control = control; | |||
136 | msg.msg_controllen = sizeof (control); | |||
137 | msg.msg_flags = 0; | |||
138 | ||||
139 | // | |||
140 | // A cmsghdr contains a length field that is the length of the header and | |||
141 | // the data. It has a cmsg_level field corresponding to the originating | |||
142 | // protocol. This takes values which are legal levels for getsockopt and | |||
143 | // setsockopt (here SOL_SOCKET). We're going to use the SCM_RIGHTS type of | |||
144 | // cmsg, that indicates that the ancillary data array contains access rights | |||
145 | // that we are sending back to the emu net device. | |||
146 | // | |||
147 | // We have to put together the first (and only) cmsghdr that will describe | |||
148 | // the whole package we're sending. | |||
149 | // | |||
150 | struct cmsghdr *cmsg; | |||
151 | cmsg = CMSG_FIRSTHDR (&msg)((size_t) (&msg)->msg_controllen >= sizeof (struct cmsghdr ) ? (struct cmsghdr *) (&msg)->msg_control : (struct cmsghdr *) 0); | |||
| ||||
152 | cmsg->cmsg_level = SOL_SOCKET1; | |||
| ||||
153 | cmsg->cmsg_type = SCM_RIGHTSSCM_RIGHTS; | |||
154 | cmsg->cmsg_len = CMSG_LEN (msg_size)((((sizeof (struct cmsghdr)) + sizeof (size_t) - 1) & (size_t ) ~(sizeof (size_t) - 1)) + (msg_size)); | |||
155 | // | |||
156 | // We also have to update the controllen in case other stuff is actually | |||
157 | // in there we may not be aware of (due to macros). | |||
158 | // | |||
159 | msg.msg_controllen = cmsg->cmsg_len; | |||
160 | ||||
161 | // | |||
162 | // Finally, we get a pointer to the start of the ancillary data array and | |||
163 | // put our file descriptor in. | |||
164 | // | |||
165 | int *fdptr = (int*)(CMSG_DATA (cmsg)((unsigned char *) ((struct cmsghdr *) (cmsg) + 1))); | |||
166 | *fdptr = fd; // | |||
167 | ||||
168 | // | |||
169 | // Actually send the file descriptor back to the emulated net device. | |||
170 | // | |||
171 | ssize_t len = sendmsg (sock, &msg, 0); | |||
172 | ABORT_IF (len == -1, "Could not send socket back to emu net device", 1)if (len == -1) { std::cout << "../src/fd-net-device/helper/creator-utils.cc" << ": fatal error at line " << 172 << ": " << __FUNCTION__ << "(): " << "Could not send socket back to emu net device" << std::endl; if (1) { std::cout << " errno = " << (*__errno_location ()) << " (" << strerror ((*__errno_location ())) << ")" << std::endl; } exit (-1);; }; | |||
173 | ||||
174 | LOG ("sendmsg complete")if (gVerbose) { std::cout << __FUNCTION__ << "(): " << "sendmsg complete" << std::endl; }; | |||
175 | } | |||
176 | ||||
177 | } // namespace ns3 |