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 |
} |