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