| Index: net/base/net_util_posix.cc
|
| diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc
|
| index 9257989b9f6d76e7c2797be8f9598a6e887350c3..8ff720f3e43d0e47e4707eecde5a5a36a25892ea 100644
|
| --- a/net/base/net_util_posix.cc
|
| +++ b/net/base/net_util_posix.cc
|
| @@ -19,6 +19,8 @@
|
| #if !defined(OS_ANDROID)
|
| #include <ifaddrs.h>
|
| #endif
|
| +#include <net/if.h>
|
| +#include <netinet/in.h>
|
|
|
| namespace net {
|
|
|
| @@ -68,28 +70,52 @@ bool GetNetworkList(NetworkInterfaceList* networks) {
|
| // getifaddrs() may require IO operations.
|
| base::ThreadRestrictions::AssertIOAllowed();
|
|
|
| - ifaddrs *ifaddr;
|
| - if (getifaddrs(&ifaddr) < 0) {
|
| + ifaddrs *interfaces;
|
| + if (getifaddrs(&interfaces) < 0) {
|
| PLOG(ERROR) << "getifaddrs";
|
| return false;
|
| }
|
|
|
| - for (ifaddrs *ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
|
| - if (!ifa->ifa_addr)
|
| - continue; // Interface has no IP addresses, so skip it.
|
| - int family = ifa->ifa_addr->sa_family;
|
| - if (family == AF_INET || family == AF_INET6) {
|
| - IPEndPoint address;
|
| - std::string name = ifa->ifa_name;
|
| - if (address.FromSockAddr(ifa->ifa_addr,
|
| - sizeof(ifa->ifa_addr)) &&
|
| - name.substr(0, 2) != "lo") {
|
| - networks->push_back(NetworkInterface(name, address.address()));
|
| - }
|
| + // Enumerate the addresses assigned to network interfaces which are up.
|
| + for (ifaddrs *interface = interfaces;
|
| + interface != NULL;
|
| + interface = interface->ifa_next) {
|
| + // Skip loopback interfaces, and ones which are down.
|
| + if (!(IFF_UP & interface->ifa_flags))
|
| + continue;
|
| + if (IFF_LOOPBACK & interface->ifa_flags)
|
| + continue;
|
| + // Skip interfaces with no address configured.
|
| + struct sockaddr* addr = interface->ifa_addr;
|
| + if (!addr)
|
| + continue;
|
| + // Skip loopback addresses configured on non-loopback interfaces.
|
| + int addr_size = 0;
|
| + if (addr->sa_family == AF_INET6) {
|
| + struct sockaddr_in6* addr_in6 =
|
| + reinterpret_cast<struct sockaddr_in6*>(addr);
|
| + struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
|
| + addr_size = sizeof(*addr_in6);
|
| + if (IN6_IS_ADDR_LOOPBACK(sin6_addr))
|
| + continue;
|
| + } else if (addr->sa_family == AF_INET) {
|
| + struct sockaddr_in* addr_in =
|
| + reinterpret_cast<struct sockaddr_in*>(addr);
|
| + addr_size = sizeof(*addr_in);
|
| + if (addr_in->sin_addr.s_addr == INADDR_LOOPBACK)
|
| + continue;
|
| + } else {
|
| + // Skip non-IP addresses.
|
| + continue;
|
| + }
|
| + IPEndPoint address;
|
| + std::string name = interface->ifa_name;
|
| + if (address.FromSockAddr(addr, addr_size)) {
|
| + networks->push_back(NetworkInterface(name, address.address()));
|
| }
|
| }
|
|
|
| - freeifaddrs(ifaddr);
|
| + freeifaddrs(interfaces);
|
|
|
| return true;
|
| #endif
|
|
|