Network route API: Second try (WIP).
Implement BNetworkRoster::GetRoutes() and BNetworkInterface::GetRoutes(). Also implement BNetworkInterface::GetDefaultGateway(). There is code duplication at the moment, and the api only supports IPV4.
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_types.h>
|
#include <net/if_types.h>
|
||||||
|
|
||||||
#include <List.h>
|
#include <ObjectList.h>
|
||||||
#include <NetworkAddress.h>
|
#include <NetworkAddress.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -106,6 +106,8 @@ public:
|
|||||||
status_t RemoveRoute(int family,
|
status_t RemoveRoute(int family,
|
||||||
const route_entry& route);
|
const route_entry& route);
|
||||||
status_t RemoveDefaultRoute(int family);
|
status_t RemoveDefaultRoute(int family);
|
||||||
|
status_t GetRoutes(BObjectList<route_entry>& routes) const;
|
||||||
|
status_t GetDefaultRoute(BNetworkAddress& gateway) const;
|
||||||
|
|
||||||
status_t AutoConfigure(int family);
|
status_t AutoConfigure(int family);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include <Locker.h>
|
#include <Locker.h>
|
||||||
#include <NetworkNotifications.h>
|
#include <NetworkNotifications.h>
|
||||||
|
#include <ObjectList.h>
|
||||||
|
|
||||||
class BMessenger;
|
class BMessenger;
|
||||||
class BNetworkInterface;
|
class BNetworkInterface;
|
||||||
@@ -31,9 +31,7 @@ public:
|
|||||||
status_t RemoveInterface(
|
status_t RemoveInterface(
|
||||||
const BNetworkInterface& interface);
|
const BNetworkInterface& interface);
|
||||||
|
|
||||||
status_t GetNextRoute(uint32* cookie,
|
status_t GetRoutes(BObjectList<route_entry>& routes) const;
|
||||||
route_entry& entry,
|
|
||||||
const char* interface = NULL) const;
|
|
||||||
|
|
||||||
int32 CountPersistentNetworks() const;
|
int32 CountPersistentNetworks() const;
|
||||||
status_t GetNextPersistentNetwork(uint32* cookie,
|
status_t GetNextPersistentNetwork(uint32* cookie,
|
||||||
|
|||||||
@@ -566,6 +566,91 @@ BNetworkInterface::RemoveDefaultRoute(int family)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkInterface::GetRoutes(BObjectList<route_entry>& routes) const
|
||||||
|
{
|
||||||
|
// TODO: Code duplication between this method
|
||||||
|
// and BNetworkRoster::GetRoutes(). Move code into
|
||||||
|
// common function
|
||||||
|
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (socket < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
FileDescriptorCloser fdCloser(socket);
|
||||||
|
|
||||||
|
// Obtain gateway
|
||||||
|
ifconf config;
|
||||||
|
config.ifc_len = sizeof(config.ifc_value);
|
||||||
|
if (ioctl(socket, SIOCGRTSIZE, &config, sizeof(struct ifconf)) < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
uint32 size = (uint32)config.ifc_value;
|
||||||
|
if (size == 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
void* buffer = malloc(size);
|
||||||
|
if (buffer == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
MemoryDeleter bufferDeleter(buffer);
|
||||||
|
config.ifc_len = size;
|
||||||
|
config.ifc_buf = buffer;
|
||||||
|
|
||||||
|
if (ioctl(socket, SIOCGRTTABLE, &config, sizeof(struct ifconf)) < 0)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
ifreq* interface = (ifreq*)buffer;
|
||||||
|
ifreq* end = (ifreq*)((uint8*)buffer + size);
|
||||||
|
|
||||||
|
while (interface < end) {
|
||||||
|
route_entry& route = interface->ifr_route;
|
||||||
|
if (!strcmp(interface->ifr_name, Name())) {
|
||||||
|
route_entry* newRoute = new (std::nothrow) route_entry;
|
||||||
|
if (newRoute == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
memcpy(newRoute, &interface->ifr_route, sizeof(route_entry));
|
||||||
|
if (!routes.AddItem(newRoute)) {
|
||||||
|
delete newRoute;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 addressSize = 0;
|
||||||
|
if (route.destination != NULL)
|
||||||
|
addressSize += route.destination->sa_len;
|
||||||
|
if (route.mask != NULL)
|
||||||
|
addressSize += route.mask->sa_len;
|
||||||
|
if (route.gateway != NULL)
|
||||||
|
addressSize += route.gateway->sa_len;
|
||||||
|
|
||||||
|
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
||||||
|
+ sizeof(route_entry) + addressSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BNetworkInterface::GetDefaultRoute(BNetworkAddress& gateway) const
|
||||||
|
{
|
||||||
|
BObjectList<route_entry> routes(1, true);
|
||||||
|
status_t status = GetRoutes(routes);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
for (int32 i = routes.CountItems() - 1; i >= 0; i--) {
|
||||||
|
route_entry* entry = routes.ItemAt(i);
|
||||||
|
if (entry->flags & RTF_DEFAULT) {
|
||||||
|
gateway.SetTo(*entry->gateway);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNetworkInterface::AutoConfigure(int family)
|
BNetworkInterface::AutoConfigure(int family)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,37 +17,6 @@
|
|||||||
#include <NetServer.h>
|
#include <NetServer.h>
|
||||||
|
|
||||||
|
|
||||||
enum preferredPrefixFormat {
|
|
||||||
PREFIX_PREFER_NETMASK = 0,
|
|
||||||
PREFIX_PREFER_CIDR,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct address_family {
|
|
||||||
int family;
|
|
||||||
const char* name;
|
|
||||||
const char* identifiers[4];
|
|
||||||
int maxAddressLength;
|
|
||||||
int preferredPrefixFormat;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const address_family kFamilies[] = {
|
|
||||||
{
|
|
||||||
AF_INET,
|
|
||||||
"IPv4",
|
|
||||||
{"AF_INET", "inet", "ipv4", NULL},
|
|
||||||
15,
|
|
||||||
PREFIX_PREFER_NETMASK,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
AF_INET6,
|
|
||||||
"IPv6",
|
|
||||||
{"AF_INET6", "inet6", "ipv6", NULL},
|
|
||||||
39,
|
|
||||||
PREFIX_PREFER_CIDR,
|
|
||||||
},
|
|
||||||
{ -1, NULL, {NULL}, -1, -1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO: using AF_INET for the socket isn't really a smart idea, as one
|
// TODO: using AF_INET for the socket isn't really a smart idea, as one
|
||||||
// could completely remove IPv4 support from the stack easily.
|
// could completely remove IPv4 support from the stack easily.
|
||||||
// Since in the stack, device_interfaces are pretty much interfaces now, we
|
// Since in the stack, device_interfaces are pretty much interfaces now, we
|
||||||
@@ -194,14 +163,8 @@ BNetworkRoster::RemoveInterface(const BNetworkInterface& interface)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
BNetworkRoster::GetNextRoute(uint32* cookie, route_entry& entry,
|
BNetworkRoster::GetRoutes(BObjectList<route_entry>& routes) const
|
||||||
const char* interfaceName) const
|
|
||||||
{
|
{
|
||||||
// TODO: Cache the routes ?
|
|
||||||
|
|
||||||
if (cookie == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
int socket = ::socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (socket < 0)
|
if (socket < 0)
|
||||||
return errno;
|
return errno;
|
||||||
@@ -232,32 +195,30 @@ BNetworkRoster::GetNextRoute(uint32* cookie, route_entry& entry,
|
|||||||
ifreq* interface = (ifreq*)buffer;
|
ifreq* interface = (ifreq*)buffer;
|
||||||
ifreq* end = (ifreq*)((uint8*)buffer + size);
|
ifreq* end = (ifreq*)((uint8*)buffer + size);
|
||||||
|
|
||||||
uint32 index = 0;
|
|
||||||
while (interface < end) {
|
while (interface < end) {
|
||||||
route_entry& route = interface->ifr_route;
|
route_entry* route = new (std::nothrow) route_entry;
|
||||||
// Filter by interface name
|
if (route == NULL)
|
||||||
if (interfaceName == NULL
|
return B_NO_MEMORY;
|
||||||
|| !strcmp(interfaceName, interface->ifr_name)) {
|
|
||||||
if (index == *cookie) {
|
memcpy(route, &interface->ifr_route, sizeof(route_entry));
|
||||||
entry = route;
|
if (!routes.AddItem(route)) {
|
||||||
return B_OK;
|
delete route;
|
||||||
}
|
return B_NO_MEMORY;
|
||||||
index++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 addressSize = 0;
|
int32 addressSize = 0;
|
||||||
if (route.destination != NULL)
|
if (route->destination != NULL)
|
||||||
addressSize += route.destination->sa_len;
|
addressSize += route->destination->sa_len;
|
||||||
if (route.mask != NULL)
|
if (route->mask != NULL)
|
||||||
addressSize += route.mask->sa_len;
|
addressSize += route->mask->sa_len;
|
||||||
if (route.gateway != NULL)
|
if (route->gateway != NULL)
|
||||||
addressSize += route.gateway->sa_len;
|
addressSize += route->gateway->sa_len;
|
||||||
|
|
||||||
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
interface = (ifreq *)((addr_t)interface + IF_NAMESIZE
|
||||||
+ sizeof(route_entry) + addressSize);
|
+ sizeof(route_entry) + addressSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_BAD_VALUE;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -36,25 +36,6 @@
|
|||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
GetDefaultGateway(const char* name, BString& gateway)
|
|
||||||
{
|
|
||||||
uint32 index = 0;
|
|
||||||
BNetworkRoster& roster = BNetworkRoster::Default();
|
|
||||||
route_entry routeEntry;
|
|
||||||
while (roster.GetNextRoute(&index, routeEntry, name) == B_OK) {
|
|
||||||
if ((routeEntry.flags & RTF_GATEWAY) != 0) {
|
|
||||||
sockaddr_in* inetAddress = (sockaddr_in*)routeEntry.gateway;
|
|
||||||
gateway = inet_ntoa(inetAddress->sin_addr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
@@ -106,9 +87,12 @@ Settings::ReadConfiguration()
|
|||||||
fIP = address.Address().ToString();
|
fIP = address.Address().ToString();
|
||||||
fNetmask = address.Mask().ToString();
|
fNetmask = address.Mask().ToString();
|
||||||
|
|
||||||
if (GetDefaultGateway(fName.String(), fGateway) != B_OK)
|
BNetworkAddress gatewayAddress;
|
||||||
|
if (interface.GetDefaultRoute(gatewayAddress) != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fGateway = gatewayAddress.ToString();
|
||||||
|
|
||||||
uint32 flags = interface.Flags();
|
uint32 flags = interface.Flags();
|
||||||
|
|
||||||
fAuto = (flags & (IFF_AUTO_CONFIGURED | IFF_CONFIGURING)) != 0;
|
fAuto = (flags & (IFF_AUTO_CONFIGURED | IFF_CONFIGURING)) != 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user