Chromium Code Reviews| Index: net/base/net_util_posix.cc |
| diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc |
| index 8b9e067f4faad7972a84f222795607086f43f99a..350422e564a56ca45a1b65694f48547cdc3aec86 100644 |
| --- a/net/base/net_util_posix.cc |
| +++ b/net/base/net_util_posix.cc |
| @@ -4,6 +4,7 @@ |
| #include "net/base/net_util.h" |
| +#include <set> |
| #include <sys/types.h> |
| #include "base/files/file_path.h" |
| @@ -23,12 +24,66 @@ |
| #include <net/if.h> |
| #include <netinet/in.h> |
| +#if defined(OS_MACOSX) || defined(OS_BSD) |
| +#include <netinet/in_var.h> |
| +#include <sys/ioctl.h> |
| +#endif |
| + |
| #if defined(OS_ANDROID) |
| #include "net/android/network_library.h" |
| #endif |
| namespace net { |
| +namespace { |
| + |
| +#if !defined(OS_ANDROID) |
| + |
| +struct NetworkInterfaceInfo { |
| + NetworkInterfaceInfo() : permanent(true) { } |
| + |
| + bool permanent; // IPv6 has notion of temporary address. If the address is |
| + // IPv6 and it's temporary this field will be false. |
| + NetworkInterface interface; |
| +}; |
| + |
| +// This method will remove permanent IPv6 address if a temporary address |
|
agl
2014/03/27 19:11:40
s/address/addresses/ (just the first instance)
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
|
| +// is available for same network interface. |
| +void RemovePermanentIPv6AddressesWhereTemporaryExists( |
| + std::vector<NetworkInterfaceInfo>* infos) { |
| + if (!infos || infos->empty()) |
| + return; |
| + |
| + // Pushing all IPv6 temp addresses interface name to a different list. |
|
agl
2014/03/27 19:11:40
// Build a set containing the names of interfaces
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
|
| + std::set<std::string> ifaces_with_temp_addrs; |
| + std::vector<NetworkInterfaceInfo>::iterator i; |
| + for (i = infos->begin(); i != infos->end(); ++i) { |
| + if (!i->permanent && i->interface.address.size() == kIPv6AddressSize) { |
| + ifaces_with_temp_addrs.insert(i->interface.name); |
| + } |
| + } |
| + |
| + // If the temp ipv6 list is empty, no work to be done further. |
|
agl
2014/03/27 19:11:40
// The there are no such interfaces then there's n
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
|
| + if (ifaces_with_temp_addrs.empty()) |
| + return; |
| + |
| + // Search for permenent address belonging to same network interface. |
|
agl
2014/03/27 19:11:40
s/address/addresses.
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
|
| + for (i = infos->begin(); i != infos->end(); ++i) { |
| + // IPv4 can have same name and it will be permanent. |
| + if (i->interface.address.size() == kIPv4AddressSize) |
| + continue; |
| + DCHECK_EQ(i->interface.address.size(), kIPv6AddressSize); |
| + if (i->permanent && ifaces_with_temp_addrs.find(i->interface.name) != |
| + ifaces_with_temp_addrs.end()) { |
| + i = infos->erase(i); |
| + } |
| + } |
| +} |
| + |
| +#endif |
| + |
| +} // namespace |
| + |
| bool FileURLToFilePath(const GURL& url, base::FilePath* path) { |
| *path = base::FilePath(); |
| std::string& file_path_str = const_cast<std::string&>(path->value()); |
| @@ -63,8 +118,7 @@ bool FileURLToFilePath(const GURL& url, base::FilePath* path) { |
| return !file_path_str.empty(); |
| } |
| -bool GetNetworkList(NetworkInterfaceList* networks, |
| - HostScopeVirtualInterfacePolicy policy) { |
| +bool GetNetworkList(NetworkInterfaceList* networks, int policy) { |
| #if defined(OS_ANDROID) |
| std::string network_list = android::GetNetworkList(); |
| base::StringTokenizer network_interfaces(network_list, "\n"); |
| @@ -94,12 +148,21 @@ bool GetNetworkList(NetworkInterfaceList* networks, |
| // getifaddrs() may require IO operations. |
| base::ThreadRestrictions::AssertIOAllowed(); |
| + int ioctl_socket = -1; |
| + if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { |
| + // we need a socket to query information about temporary address. |
| + ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0); |
| + DCHECK_GT(ioctl_socket, 0); |
| + } |
| + |
| ifaddrs *interfaces; |
| if (getifaddrs(&interfaces) < 0) { |
| PLOG(ERROR) << "getifaddrs"; |
| return false; |
| } |
| + std::vector<NetworkInterfaceInfo> network_infos; |
| + |
| // Enumerate the addresses assigned to network interfaces which are up. |
| for (ifaddrs *interface = interfaces; |
| interface != NULL; |
| @@ -141,11 +204,29 @@ bool GetNetworkList(NetworkInterfaceList* networks, |
| const std::string& name = interface->ifa_name; |
| // Filter out VMware interfaces, typically named vmnet1 and vmnet8. |
| - if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES && |
| + if (policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES && |
|
agl
2014/03/27 19:11:40
( ) around "policy & EXCLUDE_HOST_SCOPE_VIRTUAL_IN
agl
2014/03/27 19:11:40
This will never run because EXCLUDE_HOST_SCOPE_VIR
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
oops. Yea. Changed the value in .h to non-zero.
On
|
| ((name.find("vmnet") != std::string::npos) || |
| (name.find("vnic") != std::string::npos))) { |
| continue; |
| } |
| + |
| + NetworkInterfaceInfo network_info; |
| +#if defined(OS_MACOSX) || defined(OS_BSD) |
| + // Check if this is a temporary address. Currently this is only supported |
| + // on Mac. |
| + if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE && |
|
agl
2014/03/27 19:11:40
( ) around "policy & INCLUDE_ONLY_TEMP_IPV6_ADDRES
Mallinath (Gone from Chromium)
2014/03/27 19:54:18
Done.
|
| + ioctl_socket >= 0 && addr->sa_family == AF_INET6) { |
| + struct in6_ifreq ifr = {}; |
| + strncpy(ifr.ifr_name, interface->ifa_name, sizeof(ifr.ifr_name) - 1); |
| + memcpy(&ifr.ifr_ifru.ifru_addr, interface->ifa_addr, |
| + interface->ifa_addr->sa_len); |
| + int rv = ioctl(ioctl_socket, SIOCGIFAFLAG_IN6, &ifr); |
| + if (rv >= 0) { |
| + network_info.permanent = !(ifr.ifr_ifru.ifru_flags & IN6_IFF_TEMPORARY); |
| + } |
| + } |
| +#endif |
| + |
| IPEndPoint address; |
| if (address.FromSockAddr(addr, addr_size)) { |
| uint8 net_mask = 0; |
| @@ -159,15 +240,25 @@ bool GetNetworkList(NetworkInterfaceList* networks, |
| net_mask = MaskPrefixLength(netmask.address()); |
| } |
| } |
| + network_info.interface = NetworkInterface( |
| + name, name, if_nametoindex(name.c_str()), |
| + address.address(), net_mask); |
| - networks->push_back( |
| - NetworkInterface(name, name, if_nametoindex(name.c_str()), |
| - address.address(), net_mask)); |
| + network_infos.push_back(NetworkInterfaceInfo(network_info)); |
| } |
| } |
| - |
| freeifaddrs(interfaces); |
| + if (ioctl_socket >= 0) { |
| + close(ioctl_socket); |
| + } |
| + |
| + if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) { |
| + RemovePermanentIPv6AddressesWhereTemporaryExists(&network_infos); |
| + } |
| + for (size_t i = 0; i < network_infos.size(); ++i) { |
| + networks->push_back(network_infos[i].interface); |
| + } |
| return true; |
| #endif |
| } |