2 * Copyright 2013-2015 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 #include <NetworkRoute.h>
10 #include <sys/sockio.h>
12 #include <AutoDeleter.h>
15 BNetworkRoute::BNetworkRoute()
17 memset(&fRouteEntry
, 0, sizeof(route_entry
));
21 BNetworkRoute::~BNetworkRoute()
31 BNetworkRoute::SetTo(const BNetworkRoute
& other
)
33 return SetTo(other
.RouteEntry());
38 BNetworkRoute::SetTo(const route_entry
& routeEntry
)
40 #define SET_ADDRESS(address, setFunction) \
41 if (routeEntry.address != NULL) { \
42 result = setFunction(*routeEntry.address); \
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
);
60 BNetworkRoute::Adopt(BNetworkRoute
& other
)
62 memcpy(&fRouteEntry
, &other
.fRouteEntry
, sizeof(route_entry
));
63 memset(&other
.fRouteEntry
, 0, sizeof(route_entry
));
68 BNetworkRoute::RouteEntry() const
75 BNetworkRoute::Destination() const
77 return fRouteEntry
.destination
;
82 BNetworkRoute::SetDestination(const sockaddr
& destination
)
84 return _AllocateAndSetAddress(destination
, fRouteEntry
.destination
);
89 BNetworkRoute::UnsetDestination()
91 _FreeAndUnsetAddress(fRouteEntry
.destination
);
96 BNetworkRoute::Mask() const
98 return fRouteEntry
.mask
;
103 BNetworkRoute::SetMask(const sockaddr
& mask
)
105 return _AllocateAndSetAddress(mask
, fRouteEntry
.mask
);
110 BNetworkRoute::UnsetMask()
112 _FreeAndUnsetAddress(fRouteEntry
.mask
);
117 BNetworkRoute::Gateway() const
119 return fRouteEntry
.gateway
;
124 BNetworkRoute::SetGateway(const sockaddr
& gateway
)
126 return _AllocateAndSetAddress(gateway
, fRouteEntry
.gateway
);
131 BNetworkRoute::UnsetGateway()
133 _FreeAndUnsetAddress(fRouteEntry
.gateway
);
138 BNetworkRoute::Source() const
140 return fRouteEntry
.source
;
145 BNetworkRoute::SetSource(const sockaddr
& source
)
147 return _AllocateAndSetAddress(source
, fRouteEntry
.source
);
152 BNetworkRoute::UnsetSource()
154 _FreeAndUnsetAddress(fRouteEntry
.source
);
159 BNetworkRoute::Flags() const
161 return fRouteEntry
.flags
;
166 BNetworkRoute::SetFlags(uint32 flags
)
168 fRouteEntry
.flags
= flags
;
173 BNetworkRoute::MTU() const
175 return fRouteEntry
.mtu
;
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
)
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
);
213 if (routes
.CountItems() == 0)
214 return B_ENTRY_NOT_FOUND
;
216 route
.Adopt(*routes
.ItemAt(0));
222 BNetworkRoute::GetDefaultGateway(int family
, const char* interfaceName
,
226 status_t result
= GetDefaultRoute(family
, interfaceName
, route
);
230 const sockaddr
* defaultGateway
= route
.Gateway();
231 if (defaultGateway
== NULL
)
232 return B_ENTRY_NOT_FOUND
;
234 memcpy(&gateway
, defaultGateway
, defaultGateway
->sa_len
);
240 BNetworkRoute::GetRoutes(int family
, BObjectList
<BNetworkRoute
>& routes
)
242 return GetRoutes(family
, NULL
, 0, routes
);
247 BNetworkRoute::GetRoutes(int family
, const char* interfaceName
,
248 BObjectList
<BNetworkRoute
>& routes
)
250 return GetRoutes(family
, interfaceName
, 0, routes
);
255 BNetworkRoute::GetRoutes(int family
, const char* interfaceName
,
256 uint32 filterFlags
, BObjectList
<BNetworkRoute
>& routes
)
258 int socket
= ::socket(family
, SOCK_DGRAM
, 0);
262 FileDescriptorCloser
fdCloser(socket
);
265 config
.ifc_len
= sizeof(config
.ifc_value
);
266 if (ioctl(socket
, SIOCGRTSIZE
, &config
, sizeof(struct ifconf
)) < 0)
269 uint32 size
= (uint32
)config
.ifc_value
;
273 void* buffer
= malloc(size
);
277 MemoryDeleter
bufferDeleter(buffer
);
278 config
.ifc_len
= size
;
279 config
.ifc_buf
= buffer
;
281 if (ioctl(socket
, SIOCGRTTABLE
, &config
, sizeof(struct ifconf
)) < 0)
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
;
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
) {
307 if (!routes
.AddItem(route
)) {
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
);
330 BNetworkRoute::_AllocateAndSetAddress(const sockaddr
& from
,
333 if (from
.sa_len
> sizeof(sockaddr_storage
))
337 to
= (sockaddr
*)malloc(sizeof(sockaddr_storage
));
342 memcpy(to
, &from
, from
.sa_len
);
348 BNetworkRoute::_FreeAndUnsetAddress(sockaddr
*& address
)