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..36c7c1e1cd8b68eb3e77143b17e8cd07211d6657 100644 |
--- a/net/base/net_util_posix.cc |
+++ b/net/base/net_util_posix.cc |
@@ -23,12 +23,73 @@ |
#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 NET_EXPORT 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 set to false. |
agl
2014/03/27 14:52:53
remove "set to"
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ NetworkInterface interface; |
+}; |
+ |
+// This method will remove permanent IPv6 address, if a temporary address |
agl
2014/03/27 14:52:53
remove comma
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+// is available for same network interface. |
+void PruneIPv6Addresses(std::vector<NetworkInterfaceInfo>* infos) { |
agl
2014/03/27 14:52:53
I would go nuts with the name in order to make thi
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
I Agree.
On 2014/03/27 14:52:53, agl wrote:
|
+ // First find a temporary address. If available find permanent address |
+ // belonging to same interface. If available remove it. |
+ |
+ // Pushing all IPv6 temp addresses to a different list. |
+ std::vector<NetworkInterfaceInfo> temp_ipv6_list; |
+ std::vector<NetworkInterfaceInfo>::iterator iter = infos->begin(); |
agl
2014/03/27 14:52:53
If you just just |i| for iter then you can use |j|
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ for (; iter != infos->end(); ++iter) { |
agl
2014/03/27 14:52:53
do the assignment of iter in the first for clause.
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ if (iter->permanent && iter->interface.address.size() == kIPv6AddressSize) { |
agl
2014/03/27 14:52:53
This is pushing permanent addresses into a list ca
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Yea, I discovered that later.
On 2014/03/27 14:52:
|
+ temp_ipv6_list.push_back(*iter); |
+ iter = infos->erase(iter); |
+ } |
+ } |
+ |
+ // Search for permenent address belonging to same network interface. |
+ iter = temp_ipv6_list.begin(); |
agl
2014/03/27 14:52:53
move into the for loop.
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ for (; iter != temp_ipv6_list.end(); ++iter) { |
+ std::string name = iter->interface.name; |
agl
2014/03/27 14:52:53
const &?
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
not needed.
On 2014/03/27 14:52:53, agl wrote:
|
+ std::vector<NetworkInterfaceInfo>::iterator piter = infos->begin(); |
+ for (; piter != infos->end(); ++piter) { |
+ if (piter->interface.address.size() == kIPv4AddressSize) |
+ continue; |
+ if (piter->interface.name != iter->interface.name) |
agl
2014/03/27 14:52:53
RHS should be |name|?
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
removed now.
On 2014/03/27 14:52:53, agl wrote:
|
+ continue; |
+ DCHECK_EQ(piter->interface.address.size(), kIPv6AddressSize); |
+ piter = infos->erase(piter); |
+ } |
+ } |
agl
2014/03/27 14:52:53
Isn't it easier to do one pass building a set?:
s
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Cool, that makes life bit easy.
On 2014/03/27 14:5
|
+ |
+ // Push temp addresses back to original list. |
+ iter = temp_ipv6_list.begin(); |
+ for (; iter != temp_ipv6_list.end(); ++iter) { |
+ infos->push_back(*iter); |
+ } |
+ |
+ // TODO(mallinath) Above logic seems to be it "quirky", find better solution. |
+} |
+ |
+#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 +124,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 +154,21 @@ bool GetNetworkList(NetworkInterfaceList* networks, |
// getifaddrs() may require IO operations. |
base::ThreadRestrictions::AssertIOAllowed(); |
+ int ioctl_socket = -1; |
+ if (policy & INCLUDE_IPV6_TEMP_ADDRESS_IF_AVAILABLE) { |
+ // 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 +210,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 && |
((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_IPV6_TEMP_ADDRESS_IF_AVAILABLE && |
+ ioctl_socket > 0 && addr->sa_family == AF_INET6) { |
agl
2014/03/27 14:52:53
ioctl_socket >= 0
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ 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 +246,23 @@ 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(network_info); |
} |
} |
- |
freeifaddrs(interfaces); |
+ close(ioctl_socket); |
agl
2014/03/27 14:52:53
guard this by an if - we shouldn't call close(-1)
Mallinath (Gone from Chromium)
2014/03/27 19:04:18
Done.
|
+ |
+ if (policy & INCLUDE_IPV6_TEMP_ADDRESS_IF_AVAILABLE) { |
+ PruneIPv6Addresses(&network_infos); |
+ } |
+ for (size_t i = 0; i < network_infos.size(); ++i) { |
+ networks->push_back(network_infos[i].interface); |
+ } |
return true; |
#endif |
} |