From 0074cea3988073da94edcc4879cebce67e0fa163 Mon Sep 17 00:00:00 2001 From: Stefano Ceccherini Date: Fri, 15 Nov 2013 21:57:57 +0100 Subject: [PATCH] Implement BNetworkRoster::GetNextRoute() Implement BNetworkRoster::GetNextRoute() and used it in Network preflet. --- headers/os/net/NetworkRoster.h | 5 + src/kits/network/libnetapi/NetworkRoster.cpp | 99 ++++++++++++++++++++ src/preferences/network/Settings.cpp | 63 +++---------- 3 files changed, 116 insertions(+), 51 deletions(-) diff --git a/headers/os/net/NetworkRoster.h b/headers/os/net/NetworkRoster.h index 4d66365df9..4ac76e7902 100644 --- a/headers/os/net/NetworkRoster.h +++ b/headers/os/net/NetworkRoster.h @@ -12,6 +12,7 @@ class BMessenger; class BNetworkInterface; +struct route_entry; struct wireless_network; @@ -30,6 +31,10 @@ public: status_t RemoveInterface( const BNetworkInterface& interface); + status_t GetNextRoute(uint32* cookie, + route_entry& entry, + const char* interface = NULL) const; + int32 CountPersistentNetworks() const; status_t GetNextPersistentNetwork(uint32* cookie, wireless_network& network) const; diff --git a/src/kits/network/libnetapi/NetworkRoster.cpp b/src/kits/network/libnetapi/NetworkRoster.cpp index 3171aaffaf..2f0c7fb2bf 100644 --- a/src/kits/network/libnetapi/NetworkRoster.cpp +++ b/src/kits/network/libnetapi/NetworkRoster.cpp @@ -17,6 +17,37 @@ #include +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 // could completely remove IPv4 support from the stack easily. // Since in the stack, device_interfaces are pretty much interfaces now, we @@ -162,6 +193,74 @@ BNetworkRoster::RemoveInterface(const BNetworkInterface& interface) } +status_t +BNetworkRoster::GetNextRoute(uint32* cookie, route_entry& entry, + const char* interfaceName) const +{ + // TODO: Cache the routes ? + + if (cookie == NULL) + return B_BAD_VALUE; + + 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); + + uint32 index = 0; + while (interface < end) { + route_entry& route = interface->ifr_route; + // Filter by interface name + if (interfaceName == NULL + || !strcmp(interfaceName, interface->ifr_name)) { + if (index == *cookie) { + entry = route; + return B_OK; + } + index++; + } + + 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_BAD_VALUE; +} + + int32 BNetworkRoster::CountPersistentNetworks() const { diff --git a/src/preferences/network/Settings.cpp b/src/preferences/network/Settings.cpp index 48438119a4..9bf5103192 100644 --- a/src/preferences/network/Settings.cpp +++ b/src/preferences/network/Settings.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -35,59 +37,18 @@ static status_t -GetDefaultGateway(BString& gateway) +GetDefaultGateway(const char* name, BString& gateway) { - // TODO: This method is here because BNetworkInterface - // doesn't yet have any route getting methods - - 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 ((route.flags & RTF_GATEWAY) != 0) { - sockaddr_in* inetAddress = (sockaddr_in*)route.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; } - - 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); + index++; } return B_OK; @@ -145,7 +106,7 @@ Settings::ReadConfiguration() fIP = address.Address().ToString(); fNetmask = address.Mask().ToString(); - if (GetDefaultGateway(fGateway) != B_OK) + if (GetDefaultGateway(fName.String(), fGateway) != B_OK) return; uint32 flags = interface.Flags();