19cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes/* 29cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * Copyright (C) 2015 The Android Open Source Project 39cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * 49cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 59cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * you may not use this file except in compliance with the License. 69cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * You may obtain a copy of the License at 79cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * 89cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 99cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * 109cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * Unless required by applicable law or agreed to in writing, software 119cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 129cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * See the License for the specific language governing permissions and 149cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes * limitations under the License. 159cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes */ 169cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 179cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes#include <gtest/gtest.h> 189cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 199cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes#include <ifaddrs.h> 209cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 2164b481c29b47b9790dee01f7feabd97868a54760Yi Kong#include <dirent.h> 22fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong#include <linux/if_packet.h> 235d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes#include <net/ethernet.h> 245d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes#include <net/if.h> 255d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes#include <netdb.h> 26fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong#include <netinet/in.h> 2764b481c29b47b9790dee01f7feabd97868a54760Yi Kong#include <sys/ioctl.h> 2864b481c29b47b9790dee01f7feabd97868a54760Yi Kong 2964b481c29b47b9790dee01f7feabd97868a54760Yi Kong#include <algorithm> 3064b481c29b47b9790dee01f7feabd97868a54760Yi Kong#include <map> 3164b481c29b47b9790dee01f7feabd97868a54760Yi Kong#include <vector> 32fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong 339cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott HughesTEST(ifaddrs, freeifaddrs_null) { 349cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes freeifaddrs(nullptr); 359cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes} 369cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 3764b481c29b47b9790dee01f7feabd97868a54760Yi Kong// We can't statically say much about what network interfaces are available, but we can be pretty 3864b481c29b47b9790dee01f7feabd97868a54760Yi Kong// sure there's a loopback interface, and that it has IPv4, IPv6, and AF_PACKET entries. 3964b481c29b47b9790dee01f7feabd97868a54760Yi KongTEST(ifaddrs, getifaddrs_lo) { 409cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes ifaddrs* addrs = nullptr; 419cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 429cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes ASSERT_EQ(0, getifaddrs(&addrs)); 439cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes ASSERT_TRUE(addrs != nullptr); 449cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 45fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ifaddrs* lo_inet4 = nullptr; 46fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ifaddrs* lo_inet6 = nullptr; 47fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ifaddrs* lo_packet = nullptr; 489cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes for (ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next) { 49fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong if (addr->ifa_name && strcmp(addr->ifa_name, "lo") == 0) { 50fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong if (addr->ifa_addr && addr->ifa_addr->sa_family == AF_INET) lo_inet4 = addr; 51fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong else if (addr->ifa_addr && addr->ifa_addr->sa_family == AF_INET6) lo_inet6 = addr; 52fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong else if (addr->ifa_addr && addr->ifa_addr->sa_family == AF_PACKET) lo_packet = addr; 53fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong } 549cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes } 55fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong 56fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong // Does the IPv4 entry look right? 57fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_TRUE(lo_inet4 != nullptr); 58fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong const sockaddr_in* sa_inet4 = reinterpret_cast<const sockaddr_in*>(lo_inet4->ifa_addr); 59fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_TRUE(ntohl(sa_inet4->sin_addr.s_addr) == INADDR_LOOPBACK); 60fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong 61fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong // Does the IPv6 entry look right? 62fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_TRUE(lo_inet6 != nullptr); 63fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong const sockaddr_in6* sa_inet6 = reinterpret_cast<const sockaddr_in6*>(lo_inet6->ifa_addr); 64fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_TRUE(IN6_IS_ADDR_LOOPBACK(&sa_inet6->sin6_addr)); 65fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong 66fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong // Does the AF_PACKET entry look right? 67fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_TRUE(lo_packet != nullptr); 68fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong const sockaddr_ll* sa_ll = reinterpret_cast<const sockaddr_ll*>(lo_packet->ifa_addr); 69fdb2963e0a65ececa89837eff64ffd8aca8027d2Yi Kong ASSERT_EQ(6, sa_ll->sll_halen); 709cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes 719cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes freeifaddrs(addrs); 729cddb482b498abd134f7ccfc9933747e8bcb9cc7Elliott Hughes} 735d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 7464b481c29b47b9790dee01f7feabd97868a54760Yi Kong// Check that getifaddrs sees the same list of interfaces as /sys/class/net. 7564b481c29b47b9790dee01f7feabd97868a54760Yi KongTEST(ifaddrs, getifaddrs_interfaces) { 7664b481c29b47b9790dee01f7feabd97868a54760Yi Kong std::vector<std::string> ifaddrs_socks; 7764b481c29b47b9790dee01f7feabd97868a54760Yi Kong { 7864b481c29b47b9790dee01f7feabd97868a54760Yi Kong ifaddrs* addrs; 7964b481c29b47b9790dee01f7feabd97868a54760Yi Kong ASSERT_EQ(0, getifaddrs(&addrs)); 8064b481c29b47b9790dee01f7feabd97868a54760Yi Kong 8164b481c29b47b9790dee01f7feabd97868a54760Yi Kong for (ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next) { 8264b481c29b47b9790dee01f7feabd97868a54760Yi Kong int family = addr->ifa_addr ? addr->ifa_addr->sa_family : 8364b481c29b47b9790dee01f7feabd97868a54760Yi Kong addr->ifa_broadaddr ? addr->ifa_broadaddr->sa_family : 8464b481c29b47b9790dee01f7feabd97868a54760Yi Kong AF_UNSPEC; 8564b481c29b47b9790dee01f7feabd97868a54760Yi Kong 8664b481c29b47b9790dee01f7feabd97868a54760Yi Kong if (family == AF_PACKET || family == AF_UNSPEC) { 8764b481c29b47b9790dee01f7feabd97868a54760Yi Kong ifaddrs_socks.push_back(std::string(addr->ifa_name)); 8864b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 8964b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 9064b481c29b47b9790dee01f7feabd97868a54760Yi Kong 9164b481c29b47b9790dee01f7feabd97868a54760Yi Kong freeifaddrs(addrs); 9264b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 9364b481c29b47b9790dee01f7feabd97868a54760Yi Kong 9464b481c29b47b9790dee01f7feabd97868a54760Yi Kong std::vector<std::string> sys_class_net; 9564b481c29b47b9790dee01f7feabd97868a54760Yi Kong { 9631e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes std::unique_ptr<DIR, decltype(&closedir)> d(opendir("/sys/class/net"), closedir); 9764b481c29b47b9790dee01f7feabd97868a54760Yi Kong ASSERT_TRUE(d != nullptr); 9864b481c29b47b9790dee01f7feabd97868a54760Yi Kong dirent* dir; 9964b481c29b47b9790dee01f7feabd97868a54760Yi Kong while ((dir = readdir(d.get())) != nullptr) { 10064b481c29b47b9790dee01f7feabd97868a54760Yi Kong if (dir->d_type == DT_LNK) { 10164b481c29b47b9790dee01f7feabd97868a54760Yi Kong sys_class_net.push_back(std::string(dir->d_name)); 10264b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 10364b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 10464b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 10564b481c29b47b9790dee01f7feabd97868a54760Yi Kong 10664b481c29b47b9790dee01f7feabd97868a54760Yi Kong ASSERT_TRUE(std::is_permutation(ifaddrs_socks.begin(), ifaddrs_socks.end(), 10764b481c29b47b9790dee01f7feabd97868a54760Yi Kong sys_class_net.begin())); 10864b481c29b47b9790dee01f7feabd97868a54760Yi Kong} 10964b481c29b47b9790dee01f7feabd97868a54760Yi Kong 1102ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughesstatic void CheckAddressIsInSet(const std::string& if_name, bool unicast, 1112ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes const std::set<in_addr_t>& addrs) { 1122ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ifreq ifr; 1132ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes memset(&ifr, 0, sizeof(ifr)); 1142ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ifr.ifr_addr.sa_family = AF_INET; 1152ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if_name.copy(ifr.ifr_name, IFNAMSIZ - 1); 1162ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 1172ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes int fd = socket(AF_INET, SOCK_DGRAM, 0); 1182ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ASSERT_TRUE(fd != -1); 1192ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 1202ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes int request = SIOCGIFADDR; 1212ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if (!unicast) { 1222ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes // For non-unicast, the specific ioctl to use depends on whether the IFF_BROADCAST flag is set. 1232ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ASSERT_EQ(0, ioctl(fd, SIOCGIFFLAGS, &ifr)) << if_name << ' ' << strerror(errno); 1242ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes request = ((ifr.ifr_flags & IFF_BROADCAST) != 0) ? SIOCGIFBRDADDR : SIOCGIFDSTADDR; 1252ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes } 1262ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 1272ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ASSERT_EQ(0, ioctl(fd, request, &ifr)) << if_name << ' ' << strerror(errno); 1282ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes close(fd); 1292ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 1302ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes sockaddr_in* sock = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr); 1312ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes in_addr_t addr = sock->sin_addr.s_addr; 1322ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 1332ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes EXPECT_TRUE(addrs.find(addr) != addrs.end()) << if_name << ' ' << std::hex << ntohl(addr); 1342ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes} 1352ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 13664b481c29b47b9790dee01f7feabd97868a54760Yi KongTEST(ifaddrs, getifaddrs_INET) { 1372ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes std::map<std::string, std::set<in_addr_t>> inet_addrs; 1382ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes std::map<std::string, std::set<in_addr_t>> broad_addrs; 13964b481c29b47b9790dee01f7feabd97868a54760Yi Kong 1402d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes // Collect the IPv4 addresses for each interface. 1412d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes ifaddrs* addrs; 1422d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes ASSERT_EQ(0, getifaddrs(&addrs)); 1432d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes for (ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next) { 1442d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes if (addr->ifa_name && addr->ifa_addr && addr->ifa_addr->sa_family == AF_INET) { 1452d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes auto sock = reinterpret_cast<sockaddr_in*>(addr->ifa_addr); 1462ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes inet_addrs[addr->ifa_name].insert(sock->sin_addr.s_addr); 1472d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes } 1482d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes if (addr->ifa_name && addr->ifa_broadaddr && addr->ifa_broadaddr->sa_family == AF_INET) { 1492d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes auto sock = reinterpret_cast<sockaddr_in*>(addr->ifa_broadaddr); 1502ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes broad_addrs[addr->ifa_name].insert(sock->sin_addr.s_addr); 15164b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 15264b481c29b47b9790dee01f7feabd97868a54760Yi Kong } 1532d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes freeifaddrs(addrs); 15464b481c29b47b9790dee01f7feabd97868a54760Yi Kong 1552ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes // Check that the addresses returned by the SIOCGIFADDR and SIOCGIFBRDADDR/SIOCGIFDSTADDR ioctls 1562d5e21f00d20e72951cc583a1eab0fd9d415594eElliott Hughes // are in our collections. 1572ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes for (const auto& it : inet_addrs) CheckAddressIsInSet(it.first, true, it.second); 1582ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes for (const auto& it : broad_addrs) CheckAddressIsInSet(it.first, false, it.second); 15964b481c29b47b9790dee01f7feabd97868a54760Yi Kong} 16064b481c29b47b9790dee01f7feabd97868a54760Yi Kong 1615d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughesstatic void print_sockaddr_ll(const char* what, const sockaddr* p) { 1625d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes const sockaddr_ll* s = reinterpret_cast<const sockaddr_ll*>(p); 163ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes printf("\t\t%s\t", what); 1645d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes for (int i = 0; i < s->sll_halen; ++i) { 1655d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (i > 0) printf(":"); 1665d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes printf("%02X", s->sll_addr[i]); 1675d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } 1685d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes printf(" (%d bytes)\n", s->sll_halen); 1695d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes} 1705d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 1715d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughesstatic void print_sockaddr_inet(const char* what, const sockaddr* addr) { 1725d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes char host[NI_MAXHOST]; 1735d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes int family = addr->sa_family; 1745d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes int error = getnameinfo(addr, 1755d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes (family == AF_INET) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6), 1765d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes host, NI_MAXHOST, nullptr, 0, NI_NUMERICHOST); 1775d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (error != 0) { 1785d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes printf("%d getnameinfo() failed: %s\n", family, gai_strerror(error)); 1795d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes strcpy(host, "???"); 1805d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } 181ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes printf("\t\t%s: <%s>\n", what, host); 1825d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes} 1835d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 1842ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughesstatic const char* FamilyToName(int family) { 1855d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (family == AF_INET) return "AF_INET"; 1865d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (family == AF_INET6) return "AF_INET6"; 1875d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (family == AF_PACKET) return "AF_PACKET"; 1885d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (family == AF_UNSPEC) return "AF_UNSPEC"; 1895d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes return "?"; 1905d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes} 1915d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 1922ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughesstatic std::string FlagsToString(short flags) { 1932ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes std::string result; 1942ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_UP) != 0) result += " UP"; 1952ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_BROADCAST) != 0) result += " BROADCAST"; 1962ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_DEBUG) != 0) result += " DEBUG"; 1972ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_LOOPBACK) != 0) result += " LOOPBACK"; 1982ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_POINTOPOINT) != 0) result += " POINTOPOINT"; 1992ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_NOTRAILERS) != 0) result += " NOTRAILERS"; 2002ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_RUNNING) != 0) result += " RUNNING"; 2012ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_NOARP) != 0) result += " NOARP"; 2022ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_PROMISC) != 0) result += " PROMISC"; 2032ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_ALLMULTI) != 0) result += " ALLMULTI"; 2042ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_MASTER) != 0) result += " MASTER"; 2052ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_SLAVE) != 0) result += " SLAVE"; 2062ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_MULTICAST) != 0) result += " MULTICAST"; 2072ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_PORTSEL) != 0) result += " PORTSEL"; 2082ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_AUTOMEDIA) != 0) result += " AUTOMEDIA"; 2092ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_DYNAMIC) != 0) result += " DYNAMIC"; 2102ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#if defined(IFF_LOWER_UP) 2112ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_LOWER_UP) != 0) result += " LOWER_UP"; 2122ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#endif 2132ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#if defined(IFF_DORMANT) 2142ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_DORMANT) != 0) result += " DORMANT"; 2152ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#endif 2162ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#if defined(IFF_ECHO) 2172ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes if ((flags & IFF_ECHO) != 0) result += " ECHO"; 2182ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes#endif 2192ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes return result; 2202ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes} 2212ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes 2225d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes// Not really a test, but a useful debugging tool. 2235d84373c69d2c0dbb0234c47920b02443b37421cElliott HughesTEST(ifaddrs, dump) { 2245d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes ifaddrs* addrs; 2255d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes ASSERT_EQ(0, getifaddrs(&addrs)); 2265d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 2275d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes for (ifaddrs* ifa = addrs; ifa != nullptr; ifa = ifa->ifa_next) { 2285d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes int family = ifa->ifa_addr ? ifa->ifa_addr->sa_family : 2295d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes ifa->ifa_broadaddr ? ifa->ifa_broadaddr->sa_family : AF_UNSPEC; 2305d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 231ed57b98758176f0cccdec16cbed524e444039fe7Elliott Hughes printf("\t%s\n" 2322ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes "\t\t%s (%d) flags=%#x%s\n", 2332ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ifa->ifa_name, FamilyToName(family), family, 2342ef5f633e7998cf71029341e466d8e13bad7b05bElliott Hughes ifa->ifa_flags, FlagsToString(ifa->ifa_flags).c_str()); 2355d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 2365d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (family == AF_PACKET) { 2375d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (ifa->ifa_addr) print_sockaddr_ll("hwaddr", ifa->ifa_addr); 2385d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (ifa->ifa_broadaddr) print_sockaddr_ll("hwbroad", ifa->ifa_addr); 2395d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } else if (family == AF_INET || family == AF_INET6) { 2405d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (ifa->ifa_addr) print_sockaddr_inet("address", ifa->ifa_addr); 2415d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes if (ifa->ifa_broadaddr && (ifa->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT)) != 0) { 2425d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes print_sockaddr_inet((ifa->ifa_flags & IFF_BROADCAST) ? "broadcast" : "destination", 2435d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes ifa->ifa_broadaddr); 2445d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } 2455d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } 2465d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 2475d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes fflush(stdout); 2485d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes } 2495d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes 2505d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes freeifaddrs(addrs); 2515d84373c69d2c0dbb0234c47920b02443b37421cElliott Hughes} 25231e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes 25331e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott HughesTEST(ifaddrs, inet6_scope_ids) { 25431e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes ifaddrs* addrs; 25531e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes ASSERT_EQ(0, getifaddrs(&addrs)); 25631e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes 25731e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes for (ifaddrs* ifa = addrs; ifa != nullptr; ifa = ifa->ifa_next) { 25831e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes if (ifa->ifa_addr && ifa->ifa_addr->sa_family == AF_INET6) { 25931e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes sockaddr_in6* sa6 = reinterpret_cast<sockaddr_in6*>(ifa->ifa_addr); 26031e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes // Any link-local IPv6 address should have a scope id. (http://b/27219454.) 26131e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes // 0 isn't a valid interface index, so that would mean the scope id wasn't set. 26231e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&sa6->sin6_addr)) { 26331e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes ASSERT_NE(sa6->sin6_scope_id, 0U); 26431e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes } 26531e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes } 26631e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes } 26731e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes 26831e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes freeifaddrs(addrs); 26931e4472dc7779f4de13975090fc88b1e5dfb52b2Elliott Hughes} 270