| 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..95b963e7a60d385452c1940dd11b269a005ec562 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,67 @@
|
| #include <net/if.h>
|
| #include <netinet/in.h>
|
|
|
| +#if defined(OS_MACOSX) && !defined(OS_IOS)
|
| +#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 addresses if a temporary address
|
| +// is available for same network interface.
|
| +void RemovePermanentIPv6AddressesWhereTemporaryExists(
|
| + std::vector<NetworkInterfaceInfo>* infos) {
|
| + if (!infos || infos->empty())
|
| + return;
|
| +
|
| + // Build a set containing the names of interfaces with a temp IPv6 address
|
| + 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 there are no such interfaces then there's no further work.
|
| + if (ifaces_with_temp_addrs.empty())
|
| + return;
|
| +
|
| + // Search for permenent addresses belonging to same network interface.
|
| + for (i = infos->begin(); i != infos->end(); ) {
|
| + // If the address is IPv6 and it's permanent and there is temporary
|
| + // address for it, then we can remove this address.
|
| + if ((i->interface.address.size() == kIPv6AddressSize) && i->permanent &&
|
| + (ifaces_with_temp_addrs.find(i->interface.name) !=
|
| + ifaces_with_temp_addrs.end())) {
|
| + i = infos->erase(i);
|
| + } else {
|
| + ++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 +119,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 +149,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 +205,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_IOS)
|
| + // Check if this is a temporary address. Currently this is only supported
|
| + // on Mac.
|
| + if ((policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) &&
|
| + 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 +241,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
|
| }
|
|
|