Merge "Implement if_nameindex(3)/if_freenameindex(3)."
diff --git a/libc/Android.mk b/libc/Android.mk
index bf4be8c..04941f1 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -44,8 +44,6 @@
bionic/ether_ntoa.c \
bionic/fts.c \
bionic/getpriority.c \
- bionic/if_indextoname.c \
- bionic/if_nametoindex.c \
bionic/initgroups.c \
bionic/isatty.c \
bionic/memmem.c \
@@ -107,6 +105,7 @@
bionic/arpa_inet.cpp \
bionic/assert.cpp \
bionic/atof.cpp \
+ bionic/bionic_netlink.cpp \
bionic/bionic_systrace.cpp \
bionic/bionic_time_conversions.cpp \
bionic/brk.cpp \
@@ -173,6 +172,7 @@
bionic/mntent.cpp \
bionic/mremap.cpp \
bionic/NetdClientDispatch.cpp \
+ bionic/net_if.cpp \
bionic/open.cpp \
bionic/pathconf.cpp \
bionic/pause.cpp \
diff --git a/libc/bionic/bionic_netlink.cpp b/libc/bionic/bionic_netlink.cpp
new file mode 100644
index 0000000..19ca88d
--- /dev/null
+++ b/libc/bionic/bionic_netlink.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "bionic_netlink.h"
+
+#include <errno.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "private/ErrnoRestorer.h"
+
+NetlinkConnection::NetlinkConnection() {
+ fd_ = -1;
+
+ // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),
+ // but that's a bit too large to go on the stack.
+ size_ = 8192;
+ data_ = new char[size_];
+}
+
+NetlinkConnection::~NetlinkConnection() {
+ ErrnoRestorer errno_restorer;
+ if (fd_ != -1) close(fd_);
+ delete[] data_;
+}
+
+bool NetlinkConnection::SendRequest(int type) {
+ // Rather than force all callers to check for the unlikely event of being
+ // unable to allocate 8KiB, check here.
+ if (data_ == nullptr) return false;
+
+ // Did we open a netlink socket yet?
+ if (fd_ == -1) {
+ fd_ = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
+ }
+
+ // Construct and send the message.
+ struct NetlinkMessage {
+ nlmsghdr hdr;
+ rtgenmsg msg;
+ } request;
+ memset(&request, 0, sizeof(request));
+ request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+ request.hdr.nlmsg_type = type;
+ request.hdr.nlmsg_len = sizeof(request);
+ request.msg.rtgen_family = AF_UNSPEC; // All families.
+ return (TEMP_FAILURE_RETRY(send(fd_, &request, sizeof(request), 0)) == sizeof(request));
+}
+
+bool NetlinkConnection::ReadResponses(void callback(void*, nlmsghdr*), void* context) {
+ // Read through all the responses, handing interesting ones to the callback.
+ ssize_t bytes_read;
+ while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd_, data_, size_, 0))) > 0) {
+ nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(data_);
+ for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
+ if (hdr->nlmsg_type == NLMSG_DONE) return true;
+ if (hdr->nlmsg_type == NLMSG_ERROR) return false;
+ callback(context, hdr);
+ }
+ }
+
+ // We only get here if recv fails before we see a NLMSG_DONE.
+ return false;
+}
diff --git a/libc/bionic/if_nametoindex.c b/libc/bionic/bionic_netlink.h
similarity index 63%
rename from libc/bionic/if_nametoindex.c
rename to libc/bionic/bionic_netlink.h
index d670e43..4b103f3 100644
--- a/libc/bionic/if_nametoindex.c
+++ b/libc/bionic/bionic_netlink.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,33 +26,34 @@
* SUCH DAMAGE.
*/
-#include <string.h>
-#include <unistd.h>
-#include <linux/sockios.h>
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
+#ifndef BIONIC_NETLINK_H
+#define BIONIC_NETLINK_H
-/*
- * Map an interface name into its corresponding index.
- * Returns 0 on error, as 0 is not a valid index.
- */
-unsigned int if_nametoindex(const char *ifname)
-{
- int index;
- int ctl_sock;
- struct ifreq ifr;
+#include <sys/types.h>
- memset(&ifr, 0, sizeof(struct ifreq));
- strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
- ifr.ifr_name[IFNAMSIZ - 1] = 0;
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
- index = 0;
- if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
- if (ioctl(ctl_sock, SIOCGIFINDEX, &ifr) >= 0) {
- index = ifr.ifr_ifindex;
- }
- close(ctl_sock);
- }
- return index;
-}
+struct nlmsghdr;
+
+class NetlinkConnection {
+ public:
+ NetlinkConnection();
+ ~NetlinkConnection();
+
+ bool SendRequest(int type);
+ bool ReadResponses(void callback(void*, nlmsghdr*), void* context);
+
+ private:
+ int fd_;
+ char* data_;
+ size_t size_;
+};
+
+#if !defined(__clang__)
+// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style
+// cast is from a system header and should be ignored.
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+
+#endif
diff --git a/libc/bionic/if_indextoname.c b/libc/bionic/if_indextoname.c
deleted file mode 100644
index f0db512..0000000
--- a/libc/bionic/if_indextoname.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <string.h>
-#include <unistd.h>
-#include <linux/sockios.h>
-#include <net/if.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <errno.h>
-
-/*
- * Map an interface index into its name.
- * Returns NULL on error.
- */
-char*
-if_indextoname(unsigned ifindex, char *ifname)
-{
- int ctl_sock;
- struct ifreq ifr;
- char* ret = NULL;
-
- memset(&ifr, 0, sizeof(struct ifreq));
- ifr.ifr_ifindex = ifindex;
-
- if ((ctl_sock = socket(AF_INET, SOCK_DGRAM, 0)) >= 0) {
- if (ioctl(ctl_sock, SIOCGIFNAME, &ifr) >= 0) {
- ret = strncpy (ifname, ifr.ifr_name, IFNAMSIZ);
- } else {
- /* Posix requires ENXIO */
- if (errno == ENODEV)
- errno = ENXIO;
- }
- close(ctl_sock);
- }
- return ret;
-}
diff --git a/libc/bionic/ifaddrs.cpp b/libc/bionic/ifaddrs.cpp
index b66883e..d03d76f 100644
--- a/libc/bionic/ifaddrs.cpp
+++ b/libc/bionic/ifaddrs.cpp
@@ -30,8 +30,6 @@
#include <errno.h>
#include <linux/if_packet.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdint.h>
@@ -40,6 +38,10 @@
#include <string.h>
#include <unistd.h>
+#include "private/ErrnoRestorer.h"
+
+#include "bionic_netlink.h"
+
// The public ifaddrs struct is full of pointers. Rather than track several
// different allocations, we use a maximally-sized structure with the public
// part at offset 0, and pointers into its hidden tail.
@@ -119,13 +121,9 @@
}
};
-#if !defined(__clang__)
-// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style
-// cast is from a system header and should be ignored.
-#pragma GCC diagnostic ignored "-Wold-style-cast"
-#endif
+static void __getifaddrs_callback(void* context, nlmsghdr* hdr) {
+ ifaddrs** out = reinterpret_cast<ifaddrs**>(context);
-static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {
if (hdr->nlmsg_type == RTM_NEWLINK) {
ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
@@ -195,62 +193,22 @@
}
}
-static bool __send_netlink_request(int fd, int type) {
- struct NetlinkMessage {
- nlmsghdr hdr;
- rtgenmsg msg;
- } request;
- memset(&request, 0, sizeof(request));
- request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
- request.hdr.nlmsg_type = type;
- request.hdr.nlmsg_len = sizeof(request);
- request.msg.rtgen_family = AF_UNSPEC; // All families.
- return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request));
-}
-
-static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) {
- ssize_t bytes_read;
- // Read through all the responses, handing interesting ones to __handle_netlink_response.
- while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) {
- nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf);
- for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
- if (hdr->nlmsg_type == NLMSG_DONE) return true;
- if (hdr->nlmsg_type == NLMSG_ERROR) return false;
- __handle_netlink_response(out, hdr);
- }
- }
- // We only get here if recv fails before we see a NLMSG_DONE.
- return false;
-}
-
int getifaddrs(ifaddrs** out) {
- // Make cleanup easy.
+ // We construct the result directly into `out`, so terminate the list.
*out = nullptr;
- // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),
- // but that's a bit too large to go on the stack.
- size_t buf_len = 8192;
- char* buf = new char[buf_len];
- if (buf == nullptr) return -1;
-
// Open the netlink socket and ask for all the links and addresses.
- int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
- bool okay = fd != -1 &&
- __send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) &&
- __send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len);
-
+ NetlinkConnection nc;
+ bool okay = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__getifaddrs_callback, out) &&
+ nc.SendRequest(RTM_GETADDR) && nc.ReadResponses(__getifaddrs_callback, out);
if (!okay) {
freeifaddrs(*out);
// Ensure that callers crash if they forget to check for success.
*out = nullptr;
+ return -1;
}
- {
- int saved_errno = errno;
- close(fd);
- delete[] buf;
- errno = saved_errno;
- }
- return okay ? 0 : -1;
+
+ return 0;
}
void freeifaddrs(ifaddrs* list) {
diff --git a/libc/bionic/net_if.cpp b/libc/bionic/net_if.cpp
new file mode 100644
index 0000000..a6b896e
--- /dev/null
+++ b/libc/bionic/net_if.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <net/if.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <linux/if_packet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/sockios.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "private/ErrnoRestorer.h"
+
+#include "bionic_netlink.h"
+
+char* if_indextoname(unsigned ifindex, char* ifname) {
+ int s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (s == -1) return nullptr;
+
+ struct ifreq ifr = {};
+ ifr.ifr_ifindex = ifindex;
+
+ int rc = ioctl(s, SIOCGIFNAME, &ifr);
+ ErrnoRestorer errno_restorer;
+ close(s);
+ return (rc == -1) ? nullptr : strncpy(ifname, ifr.ifr_name, IFNAMSIZ);
+}
+
+unsigned if_nametoindex(const char* ifname) {
+ int s = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (s == -1) return 0;
+
+ struct ifreq ifr = {};
+ strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_name[IFNAMSIZ - 1] = 0;
+
+ int rc = ioctl(s, SIOCGIFINDEX, &ifr);
+ ErrnoRestorer errno_restorer;
+ close(s);
+ return (rc == -1) ? 0 : ifr.ifr_ifindex;
+}
+
+struct if_list {
+ if_list* next;
+ struct if_nameindex data;
+
+ if_list(if_list** list) {
+ // push_front onto `list`.
+ next = *list;
+ *list = this;
+ }
+
+ static void Free(if_list* list, bool names_too) {
+ while (list) {
+ if_list* it = list;
+ list = it->next;
+ if (names_too) free(it->data.if_name);
+ free(it);
+ }
+ }
+};
+
+static void __if_nameindex_callback(void* context, nlmsghdr* hdr) {
+ if_list** list = reinterpret_cast<if_list**>(context);
+ if (hdr->nlmsg_type == RTM_NEWLINK) {
+ ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
+
+ // Create a new entry and set the interface index.
+ if_list* new_link = new if_list(list);
+ new_link->data.if_index = ifi->ifi_index;
+
+ // Go through the various bits of information and find the name.
+ rtattr* rta = IFLA_RTA(ifi);
+ size_t rta_len = IFLA_PAYLOAD(hdr);
+ while (RTA_OK(rta, rta_len)) {
+ if (rta->rta_type == IFLA_IFNAME) {
+ new_link->data.if_name = strndup(reinterpret_cast<char*>(RTA_DATA(rta)), RTA_PAYLOAD(rta));
+ }
+ rta = RTA_NEXT(rta, rta_len);
+ }
+ }
+}
+
+struct if_nameindex* if_nameindex() {
+ if_list* list = nullptr;
+
+ // Open the netlink socket and ask for all the links;
+ NetlinkConnection nc;
+ bool okay = nc.SendRequest(RTM_GETLINK) && nc.ReadResponses(__if_nameindex_callback, &list);
+ if (!okay) {
+ if_list::Free(list, true);
+ return nullptr;
+ }
+
+ // Count the interfaces.
+ size_t interface_count = 0;
+ for (if_list* it = list; it != nullptr; it = it->next) {
+ ++interface_count;
+ }
+
+ // Build the array POSIX requires us to return.
+ struct if_nameindex* result = new struct if_nameindex[interface_count + 1];
+ if (result) {
+ struct if_nameindex* out = result;
+ for (if_list* it = list; it != nullptr; it = it->next) {
+ out->if_index = it->data.if_index;
+ out->if_name = it->data.if_name;
+ ++out;
+ }
+ out->if_index = 0;
+ out->if_name = nullptr;
+ }
+
+ // Free temporary storage.
+ if_list::Free(list, false);
+
+ return result;
+}
+
+void if_freenameindex(struct if_nameindex* array) {
+ if (array == nullptr) return;
+
+ struct if_nameindex* ptr = array;
+ while (ptr->if_index != 0 || ptr->if_name != nullptr) {
+ free(ptr->if_name);
+ ++ptr;
+ }
+
+ delete[] array;
+}
diff --git a/libc/include/net/if.h b/libc/include/net/if.h
index 0efbf7f..aa4c19e 100644
--- a/libc/include/net/if.h
+++ b/libc/include/net/if.h
@@ -39,11 +39,15 @@
__BEGIN_DECLS
-/*
- * Map an interface name into its corresponding index.
- */
-extern unsigned int if_nametoindex(const char *);
-extern char* if_indextoname(unsigned ifindex, char *ifname);
+struct if_nameindex {
+ unsigned if_index;
+ char* if_name;
+};
+
+char* if_indextoname(unsigned, char*);
+unsigned if_nametoindex(const char*);
+struct if_nameindex* if_nameindex(void);
+void if_freenameindex(struct if_nameindex*);
__END_DECLS
diff --git a/libc/libc.arm.brillo.map b/libc/libc.arm.brillo.map
index c51b7e1..9cef643 100644
--- a/libc/libc.arm.brillo.map
+++ b/libc/libc.arm.brillo.map
@@ -1236,6 +1236,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 6297fd1..c9f8708 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1237,6 +1237,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index fea1759..e5933ae 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1157,6 +1157,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
pthread_barrierattr_destroy;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 258ff48..b1322a2 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1264,6 +1264,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.mips.brillo.map b/libc/libc.mips.brillo.map
index 67e1c05..965927a 100644
--- a/libc/libc.mips.brillo.map
+++ b/libc/libc.mips.brillo.map
@@ -1221,6 +1221,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index b82ef0f..59ea26b 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1222,6 +1222,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index fea1759..e5933ae 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1157,6 +1157,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
pthread_barrierattr_destroy;
diff --git a/libc/libc.x86.brillo.map b/libc/libc.x86.brillo.map
index 71390b7..c19e797 100644
--- a/libc/libc.x86.brillo.map
+++ b/libc/libc.x86.brillo.map
@@ -1220,6 +1220,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index 6905ff8..51f617e 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1221,6 +1221,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
prlimit; # arm mips x86
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index fea1759..e5933ae 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1157,6 +1157,8 @@
getgrgid_r;
getgrnam_r;
getifaddrs;
+ if_freenameindex;
+ if_nameindex;
preadv;
preadv64;
pthread_barrierattr_destroy;
diff --git a/tests/ifaddrs_test.cpp b/tests/ifaddrs_test.cpp
index 0c32332..8c45947 100644
--- a/tests/ifaddrs_test.cpp
+++ b/tests/ifaddrs_test.cpp
@@ -162,7 +162,7 @@
static void print_sockaddr_ll(const char* what, const sockaddr* p) {
const sockaddr_ll* s = reinterpret_cast<const sockaddr_ll*>(p);
- printf("\t%s\t", what);
+ printf("\t\t%s\t", what);
for (int i = 0; i < s->sll_halen; ++i) {
if (i > 0) printf(":");
printf("%02X", s->sll_addr[i]);
@@ -180,7 +180,7 @@
printf("%d getnameinfo() failed: %s\n", family, gai_strerror(error));
strcpy(host, "???");
}
- printf("\t%s: <%s>\n", what, host);
+ printf("\t\t%s: <%s>\n", what, host);
}
static const char* family_to_name(int family) {
@@ -200,7 +200,8 @@
int family = ifa->ifa_addr ? ifa->ifa_addr->sa_family :
ifa->ifa_broadaddr ? ifa->ifa_broadaddr->sa_family : AF_UNSPEC;
- printf("%s\n\t%s (%d) flags=%#x\n",
+ printf("\t%s\n"
+ "\t\t%s (%d) flags=%#x\n",
ifa->ifa_name, family_to_name(family), family, ifa->ifa_flags);
if (family == AF_PACKET) {
diff --git a/tests/net_if_test.cpp b/tests/net_if_test.cpp
index 9f38411..caaed5f 100644
--- a/tests/net_if_test.cpp
+++ b/tests/net_if_test.cpp
@@ -17,6 +17,7 @@
#include <net/if.h>
#include <errno.h>
+#include <ifaddrs.h>
#include <gtest/gtest.h>
@@ -34,3 +35,39 @@
unsigned index = if_nametoindex("this-interface-does-not-exist");
ASSERT_EQ(0U, index);
}
+
+TEST(net_if, if_nameindex) {
+ struct if_nameindex* list = if_nameindex();
+ ASSERT_TRUE(list != nullptr);
+
+ ASSERT_TRUE(list->if_index != 0);
+
+ std::set<std::string> if_nameindex_names;
+ char buf[IF_NAMESIZE] = {};
+ bool saw_lo = false;
+ for (struct if_nameindex* it = list; it->if_index != 0; ++it) {
+ fprintf(stderr, "\t%d\t%s\n", it->if_index, it->if_name);
+ if_nameindex_names.insert(it->if_name);
+ EXPECT_EQ(it->if_index, if_nametoindex(it->if_name));
+ EXPECT_STREQ(it->if_name, if_indextoname(it->if_index, buf));
+ if (strcmp(it->if_name, "lo") == 0) saw_lo = true;
+ }
+ ASSERT_TRUE(saw_lo);
+ if_freenameindex(list);
+
+ std::set<std::string> getifaddrs_names;
+ ifaddrs* ifa;
+ ASSERT_EQ(0, getifaddrs(&ifa));
+ for (ifaddrs* it = ifa; it != nullptr; it = it->ifa_next) {
+ getifaddrs_names.insert(it->ifa_name);
+ }
+ freeifaddrs(ifa);
+
+ ASSERT_EQ(getifaddrs_names, if_nameindex_names);
+}
+
+TEST(net_if, if_freenameindex_nullptr) {
+#if defined(__BIONIC__)
+ if_freenameindex(nullptr);
+#endif
+}