vfs: check userland buffers before reading them.
[haiku.git] / src / kits / network / libnetapi / NetworkRoute.cpp
blob8dde3108f0899e633348194854904e13dbb6352e
1 /*
2 * Copyright 2013-2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 */
6 #include <NetworkRoute.h>
8 #include <errno.h>
9 #include <net/if.h>
10 #include <sys/sockio.h>
12 #include <AutoDeleter.h>
15 BNetworkRoute::BNetworkRoute()
17 memset(&fRouteEntry, 0, sizeof(route_entry));
21 BNetworkRoute::~BNetworkRoute()
23 UnsetDestination();
24 UnsetMask();
25 UnsetGateway();
26 UnsetSource();
30 status_t
31 BNetworkRoute::SetTo(const BNetworkRoute& other)
33 return SetTo(other.RouteEntry());
37 status_t
38 BNetworkRoute::SetTo(const route_entry& routeEntry)
40 #define SET_ADDRESS(address, setFunction) \
41 if (routeEntry.address != NULL) { \
42 result = setFunction(*routeEntry.address); \
43 if (result != B_OK) \
44 return result; \
47 status_t result;
48 SET_ADDRESS(destination, SetDestination)
49 SET_ADDRESS(mask, SetMask)
50 SET_ADDRESS(gateway, SetGateway)
51 SET_ADDRESS(source, SetSource)
53 SetFlags(routeEntry.flags);
54 SetMTU(routeEntry.mtu);
55 return B_OK;
59 void
60 BNetworkRoute::Adopt(BNetworkRoute& other)
62 memcpy(&fRouteEntry, &other.fRouteEntry, sizeof(route_entry));
63 memset(&other.fRouteEntry, 0, sizeof(route_entry));
67 const route_entry&
68 BNetworkRoute::RouteEntry() const
70 return fRouteEntry;
74 const sockaddr*
75 BNetworkRoute::Destination() const
77 return fRouteEntry.destination;
81 status_t
82 BNetworkRoute::SetDestination(const sockaddr& destination)
84 return _AllocateAndSetAddress(destination, fRouteEntry.destination);
88 void
89 BNetworkRoute::UnsetDestination()
91 _FreeAndUnsetAddress(fRouteEntry.destination);
95 const sockaddr*
96 BNetworkRoute::Mask() const
98 return fRouteEntry.mask;
102 status_t
103 BNetworkRoute::SetMask(const sockaddr& mask)
105 return _AllocateAndSetAddress(mask, fRouteEntry.mask);
109 void
110 BNetworkRoute::UnsetMask()
112 _FreeAndUnsetAddress(fRouteEntry.mask);
116 const sockaddr*
117 BNetworkRoute::Gateway() const
119 return fRouteEntry.gateway;
123 status_t
124 BNetworkRoute::SetGateway(const sockaddr& gateway)
126 return _AllocateAndSetAddress(gateway, fRouteEntry.gateway);
130 void
131 BNetworkRoute::UnsetGateway()
133 _FreeAndUnsetAddress(fRouteEntry.gateway);
137 const sockaddr*
138 BNetworkRoute::Source() const
140 return fRouteEntry.source;
144 status_t
145 BNetworkRoute::SetSource(const sockaddr& source)
147 return _AllocateAndSetAddress(source, fRouteEntry.source);
151 void
152 BNetworkRoute::UnsetSource()
154 _FreeAndUnsetAddress(fRouteEntry.source);
158 uint32
159 BNetworkRoute::Flags() const
161 return fRouteEntry.flags;
165 void
166 BNetworkRoute::SetFlags(uint32 flags)
168 fRouteEntry.flags = flags;
172 uint32
173 BNetworkRoute::MTU() const
175 return fRouteEntry.mtu;
179 void
180 BNetworkRoute::SetMTU(uint32 mtu)
182 fRouteEntry.mtu = mtu;
187 BNetworkRoute::AddressFamily() const
189 #define RETURN_FAMILY_IF_SET(address) \
190 if (fRouteEntry.address != NULL \
191 && fRouteEntry.address->sa_family != AF_UNSPEC) { \
192 return fRouteEntry.address->sa_family; \
195 RETURN_FAMILY_IF_SET(destination)
196 RETURN_FAMILY_IF_SET(mask)
197 RETURN_FAMILY_IF_SET(gateway)
198 RETURN_FAMILY_IF_SET(source)
200 return AF_UNSPEC;
204 status_t
205 BNetworkRoute::GetDefaultRoute(int family, const char* interfaceName,
206 BNetworkRoute& route)
208 BObjectList<BNetworkRoute> routes(1, true);
209 status_t result = GetRoutes(family, interfaceName, RTF_DEFAULT, routes);
210 if (result != B_OK)
211 return result;
213 if (routes.CountItems() == 0)
214 return B_ENTRY_NOT_FOUND;
216 route.Adopt(*routes.ItemAt(0));
217 return B_OK;
221 status_t
222 BNetworkRoute::GetDefaultGateway(int family, const char* interfaceName,
223 sockaddr& gateway)
225 BNetworkRoute route;
226 status_t result = GetDefaultRoute(family, interfaceName, route);
227 if (result != B_OK)
228 return result;
230 const sockaddr* defaultGateway = route.Gateway();
231 if (defaultGateway == NULL)
232 return B_ENTRY_NOT_FOUND;
234 memcpy(&gateway, defaultGateway, defaultGateway->sa_len);
235 return B_OK;
239 status_t
240 BNetworkRoute::GetRoutes(int family, BObjectList<BNetworkRoute>& routes)
242 return GetRoutes(family, NULL, 0, routes);
246 status_t
247 BNetworkRoute::GetRoutes(int family, const char* interfaceName,
248 BObjectList<BNetworkRoute>& routes)
250 return GetRoutes(family, interfaceName, 0, routes);
254 status_t
255 BNetworkRoute::GetRoutes(int family, const char* interfaceName,
256 uint32 filterFlags, BObjectList<BNetworkRoute>& routes)
258 int socket = ::socket(family, SOCK_DGRAM, 0);
259 if (socket < 0)
260 return errno;
262 FileDescriptorCloser fdCloser(socket);
264 ifconf config;
265 config.ifc_len = sizeof(config.ifc_value);
266 if (ioctl(socket, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
267 return errno;
269 uint32 size = (uint32)config.ifc_value;
270 if (size == 0)
271 return B_OK;
273 void* buffer = malloc(size);
274 if (buffer == NULL)
275 return B_NO_MEMORY;
277 MemoryDeleter bufferDeleter(buffer);
278 config.ifc_len = size;
279 config.ifc_buf = buffer;
281 if (ioctl(socket, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0)
282 return errno;
284 ifreq* interface = (ifreq*)buffer;
285 ifreq* end = (ifreq*)((uint8*)buffer + size);
287 while (interface < end) {
288 route_entry& routeEntry = interface->ifr_route;
290 if ((interfaceName == NULL
291 || strcmp(interface->ifr_name, interfaceName) == 0)
292 && (filterFlags == 0 || (routeEntry.flags & filterFlags) != 0)) {
294 BNetworkRoute* route = new(std::nothrow) BNetworkRoute;
295 if (route == NULL)
296 return B_NO_MEMORY;
298 // Note that source is not provided in the buffer.
299 routeEntry.source = NULL;
301 status_t result = route->SetTo(routeEntry);
302 if (result != B_OK) {
303 delete route;
304 return result;
307 if (!routes.AddItem(route)) {
308 delete route;
309 return B_NO_MEMORY;
313 size_t addressSize = 0;
314 if (routeEntry.destination != NULL)
315 addressSize += routeEntry.destination->sa_len;
316 if (routeEntry.mask != NULL)
317 addressSize += routeEntry.mask->sa_len;
318 if (routeEntry.gateway != NULL)
319 addressSize += routeEntry.gateway->sa_len;
321 interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
322 + sizeof(route_entry) + addressSize);
325 return B_OK;
329 status_t
330 BNetworkRoute::_AllocateAndSetAddress(const sockaddr& from,
331 sockaddr*& to)
333 if (from.sa_len > sizeof(sockaddr_storage))
334 return B_BAD_VALUE;
336 if (to == NULL) {
337 to = (sockaddr*)malloc(sizeof(sockaddr_storage));
338 if (to == NULL)
339 return B_NO_MEMORY;
342 memcpy(to, &from, from.sa_len);
343 return B_OK;
347 void
348 BNetworkRoute::_FreeAndUnsetAddress(sockaddr*& address)
350 free(address);
351 address = NULL;