OSDN Git Service

Merge "Implement if_nameindex(3)/if_freenameindex(3)."
authorElliott Hughes <enh@google.com>
Tue, 19 Jan 2016 17:24:16 +0000 (17:24 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Tue, 19 Jan 2016 17:24:16 +0000 (17:24 +0000)
1  2 
tests/ifaddrs_test.cpp

@@@ -71,98 -65,9 +71,98 @@@ TEST(ifaddrs, getifaddrs_lo) 
    freeifaddrs(addrs);
  }
  
 +// Check that getifaddrs sees the same list of interfaces as /sys/class/net.
 +TEST(ifaddrs, getifaddrs_interfaces) {
 +  std::vector<std::string> ifaddrs_socks;
 +  {
 +    ifaddrs* addrs;
 +    ASSERT_EQ(0, getifaddrs(&addrs));
 +
 +    for (ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next) {
 +      int family = addr->ifa_addr ? addr->ifa_addr->sa_family :
 +          addr->ifa_broadaddr ? addr->ifa_broadaddr->sa_family :
 +          AF_UNSPEC;
 +
 +      if (family == AF_PACKET || family == AF_UNSPEC) {
 +        ifaddrs_socks.push_back(std::string(addr->ifa_name));
 +      }
 +    }
 +
 +    freeifaddrs(addrs);
 +  }
 +
 +  std::vector<std::string> sys_class_net;
 +  {
 +    auto dir_deleter = [](DIR* handle) { if (handle) closedir(handle); };
 +    std::unique_ptr<DIR, decltype(dir_deleter)> d(opendir("/sys/class/net"), dir_deleter);
 +    ASSERT_TRUE(d != nullptr);
 +    dirent* dir;
 +    while ((dir = readdir(d.get())) != nullptr) {
 +      if (dir->d_type == DT_LNK) {
 +        sys_class_net.push_back(std::string(dir->d_name));
 +      }
 +    }
 +  }
 +
 +  ASSERT_TRUE(std::is_permutation(ifaddrs_socks.begin(), ifaddrs_socks.end(),
 +                                  sys_class_net.begin()));
 +}
 +
 +TEST(ifaddrs, getifaddrs_INET) {
 +  std::multimap<std::string,in_addr_t> inetaddrs;
 +  std::multimap<std::string,in_addr_t> broadinetaddrs;
 +
 +  {
 +    ifaddrs* addrs;
 +    ASSERT_EQ(0, getifaddrs(&addrs));
 +    for (ifaddrs* addr = addrs; addr != nullptr; addr = addr->ifa_next) {
 +      if (addr->ifa_name && addr->ifa_addr && addr->ifa_addr->sa_family == AF_INET) {
 +        auto sock = reinterpret_cast<sockaddr_in*>(addr->ifa_addr);
 +        inetaddrs.emplace(std::string(addr->ifa_name), sock->sin_addr.s_addr);
 +      }
 +      if (addr->ifa_name && addr->ifa_broadaddr && addr->ifa_broadaddr->sa_family == AF_INET) {
 +        auto sock = reinterpret_cast<sockaddr_in*>(addr->ifa_broadaddr);
 +        broadinetaddrs.emplace(std::string(addr->ifa_name), sock->sin_addr.s_addr);
 +      }
 +    }
 +    freeifaddrs(addrs);
 +  }
 +
 +  {
 +    int fd = socket(AF_INET, SOCK_DGRAM, 0);
 +    ASSERT_TRUE(fd != -1);
 +
 +    auto check_inet_agrees = [&](std::multimap<std::string, in_addr_t> addrs, int request)->bool {
 +      for (auto it = addrs.begin(); it != addrs.end(); ) {
 +        ifreq ifr;
 +        ifr.ifr_addr.sa_family = AF_INET;
 +        it->first.copy(ifr.ifr_name, IFNAMSIZ - 1);
 +        ioctl(fd, request, &ifr);
 +
 +        sockaddr_in* sock = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr);
 +        in_addr_t addr = sock->sin_addr.s_addr;
 +
 +        bool found = false;
 +        for (auto ub = addrs.upper_bound(it->first); it != ub; ++it) {
 +          if (it->second == addr) {
 +            found = true;
 +          }
 +        }
 +        if (!found) return false;
 +      }
 +      return true;
 +    };
 +
 +    ASSERT_TRUE(check_inet_agrees(inetaddrs, SIOCGIFADDR));
 +    ASSERT_TRUE(check_inet_agrees(broadinetaddrs, SIOCGIFBRDADDR));
 +
 +    close(fd);
 +  }
 +}
 +
  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]);