Implement if_nameindex(3)/if_freenameindex(3).

This is just a subset of the recently-implemented getifaddrs(3), though if
we want to handle interfaces (such as "rmnet_*") that don't have an address,
we need to either expose ifaddrs_storage and keep track of which interfaces
we've already seen (which is pretty messy), or refactor the netlink code so
we can reuse it and just extract the information we need for if_nameindex(3).
This patch goes the latter route.

Also clean up if_nametoindex(3) and if_indextoname(3).

Change-Id: I5ffc5df0bab62286cdda2e7af06f032c767119a8
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
+}