hrev48684 adds 1 changeset to branch 'master' old head: 23f1ce0756ffcde7835b8d5d9a42cb3eff54318f new head: e2fc7cd3c7be1918e8de18e984d10acb5ea2626d overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e2fc7cd3c7be+%5E23f1ce0756ff ---------------------------------------------------------------------------- e2fc7cd3c7be: Implement getifaddrs. This is a BSD extension also available in glibc, but is not POSIX. Fixes #6279. [ Adrien Destugues <pulkomandy@xxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev48684 Commit: e2fc7cd3c7be1918e8de18e984d10acb5ea2626d URL: http://cgit.haiku-os.org/haiku/commit/?id=e2fc7cd3c7be Author: Adrien Destugues <pulkomandy@xxxxxxxxx> Date: Fri Jan 16 12:06:48 2015 UTC Ticket: https://dev.haiku-os.org/ticket/6279 ---------------------------------------------------------------------------- 2 files changed, 98 insertions(+), 1 deletion(-) headers/compatibility/bsd/ifaddrs.h | 25 +++++++++++ src/kits/network/interfaces.cpp | 74 ++++++++++++++++++++++++++++++++- ---------------------------------------------------------------------------- diff --git a/headers/compatibility/bsd/ifaddrs.h b/headers/compatibility/bsd/ifaddrs.h new file mode 100644 index 0000000..7169d0c --- /dev/null +++ b/headers/compatibility/bsd/ifaddrs.h @@ -0,0 +1,25 @@ +/* + * Copyright 2015, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef _IFADDRS_H +#define _IFADDRS_H + + +struct ifaddrs { + struct ifaddrs *ifa_next; /* Next item in list */ + const char *ifa_name; /* Name of interface */ + unsigned int ifa_flags; /* Flags from SIOCGIFFLAGS */ + struct sockaddr *ifa_addr; /* Address of interface */ + struct sockaddr *ifa_netmask; /* Netmask of interface */ + struct sockaddr *ifa_dstaddr; + #define ifa_broadaddr ifa_dstaddr + void *ifa_data; /* Address-specific data */ +}; + + +int getifaddrs(struct ifaddrs **ifap); +void freeifaddrs(struct ifaddrs *ifa); + + +#endif diff --git a/src/kits/network/interfaces.cpp b/src/kits/network/interfaces.cpp index f0a7faf..42a043d 100644 --- a/src/kits/network/interfaces.cpp +++ b/src/kits/network/interfaces.cpp @@ -1,12 +1,14 @@ /* - * Copyright 2006-2010, Haiku, Inc. All Rights Reserved. + * Copyright 2006-2015, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Axel Dörfler, axeld@xxxxxxxxxxxxxxxx + * Adrien Destugues, pulkomandy@xxxxxxxxxxxxx */ +#include <errno.h> #include <net/if.h> #include <sys/socket.h> #include <sys/sockio.h> @@ -15,6 +17,11 @@ #include <unistd.h> #include <AutoDeleter.h> +#include <NetworkAddress.h> +#include <NetworkInterface.h> +#include <NetworkRoster.h> + +#include "compatibility/bsd/ifaddrs.h" namespace BPrivate { @@ -141,3 +148,68 @@ if_freenameindex(struct if_nameindex *interfaceArray) free(interfaceArray); } + +int getifaddrs(struct ifaddrs **ifap) +{ + if (ifap == NULL) { + errno = B_BAD_VALUE; + return -1; + } + + BNetworkRoster& roster = BNetworkRoster::Default(); + + uint32 cookie; + + struct ifaddrs* previous = NULL; + struct ifaddrs* current = NULL; + BNetworkInterface* interface = new BNetworkInterface(); + + while (roster.GetNextInterface(&cookie, *interface) == B_OK) { + BNetworkInterfaceAddress address; + int32 i = 0; + while (interface->GetAddressAt(i++, address) == B_OK) { + current = new ifaddrs(); + + // Chain this interface with the next one + current->ifa_next = previous; + previous = current; + + current->ifa_data = interface; + current->ifa_name = interface->Name(); + // Points to the name in the BNetworkInterface instance, which + // is added as ifa_data so freeifaddrs can release it. + current->ifa_flags = address.Flags(); + current->ifa_addr = new sockaddr(address.Address().SockAddr()); + current->ifa_netmask = new sockaddr(address.Mask().SockAddr()); + current->ifa_dstaddr = new sockaddr(address.Destination().SockAddr()); + } + + interface = new BNetworkInterface(); + } + + delete interface; + *ifap = current; + + return 0; +} + + +void freeifaddrs(struct ifaddrs *ifa) +{ + struct ifaddrs* next; + BNetworkInterface* interface = NULL; + while (ifa != NULL) { + if (ifa->ifa_data != interface) { + interface = (BNetworkInterface*)ifa->ifa_data; + delete interface; + } + + delete ifa->ifa_addr; + delete ifa->ifa_netmask; + delete ifa->ifa_dstaddr; + + next = ifa->ifa_next; + delete ifa; + ifa = next; + } +}