diff options
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/host_resolver.h | 2 | ||||
-rw-r--r-- | net/base/host_resolver_impl.cc | 23 | ||||
-rw-r--r-- | net/base/host_resolver_impl.h | 14 | ||||
-rw-r--r-- | net/base/net_util.cc | 70 |
4 files changed, 88 insertions, 21 deletions
diff --git a/net/base/host_resolver.h b/net/base/host_resolver.h index c4cdef6..3dfe3e0 100644 --- a/net/base/host_resolver.h +++ b/net/base/host_resolver.h @@ -170,7 +170,7 @@ class HostResolver : public base::RefCountedThreadSafe<HostResolver> { protected: friend class base::RefCountedThreadSafe<HostResolver>; - HostResolver() { } + HostResolver() {} // If any completion callbacks are pending when the resolver is destroyed, // the host resolutions are cancelled, and the completion callbacks will not diff --git a/net/base/host_resolver_impl.cc b/net/base/host_resolver_impl.cc index 184324b..2f50b10 100644 --- a/net/base/host_resolver_impl.cc +++ b/net/base/host_resolver_impl.cc @@ -20,6 +20,7 @@ #include "net/base/host_resolver_proc.h" #include "net/base/load_log.h" #include "net/base/net_errors.h" +#include "net/base/net_util.h" #include "net/base/network_change_notifier.h" #if defined(OS_WIN) @@ -575,7 +576,8 @@ HostResolverImpl::HostResolverImpl( resolver_proc_(resolver_proc), default_address_family_(ADDRESS_FAMILY_UNSPECIFIED), shutdown_(false), - network_change_notifier_(network_change_notifier) { + network_change_notifier_(network_change_notifier), + ipv6_probe_monitoring_(false) { DCHECK_GT(max_jobs, 0u); // It is cumbersome to expose all of the constraints in the constructor, @@ -736,6 +738,17 @@ void HostResolverImpl::RemoveObserver(HostResolver::Observer* observer) { observers_.erase(it); } +void HostResolverImpl::SetDefaultAddressFamily(AddressFamily address_family) { + ipv6_probe_monitoring_ = false; + default_address_family_ = address_family; +} + +void HostResolverImpl::ProbeIPv6Support() { + DCHECK(!ipv6_probe_monitoring_); + ipv6_probe_monitoring_ = true; + OnIPAddressChanged(); // Give initial setup call. +} + void HostResolverImpl::Shutdown() { shutdown_ = true; @@ -977,6 +990,14 @@ void HostResolverImpl::OnCancelRequest(LoadLog* load_log, void HostResolverImpl::OnIPAddressChanged() { if (cache_.get()) cache_->clear(); + if (ipv6_probe_monitoring_) { + bool support = IPv6Supported(); + default_address_family_ = support ? ADDRESS_FAMILY_UNSPECIFIED + : ADDRESS_FAMILY_IPV4; + LOG(INFO) << "IPv6Probe forced AddressFamily setting to " + << (support ? "ADDRESS_FAMILY_UNSPECIFIED" + : "ADDRESS_FAMILY_IPV4"); + } } // static diff --git a/net/base/host_resolver_impl.h b/net/base/host_resolver_impl.h index 3e273cd..b92b78b 100644 --- a/net/base/host_resolver_impl.h +++ b/net/base/host_resolver_impl.h @@ -88,9 +88,12 @@ class HostResolverImpl : public HostResolver, virtual void AddObserver(HostResolver::Observer* observer); virtual void RemoveObserver(HostResolver::Observer* observer); - virtual void SetDefaultAddressFamily(AddressFamily address_family) { - default_address_family_ = address_family; - } + // Set address family, and disable IPv6 probe support. + virtual void SetDefaultAddressFamily(AddressFamily address_family); + + // Continuously observe whether IPv6 is supported, and set the allowable + // address family to IPv4 iff IPv6 is not supported. + void ProbeIPv6Support(); virtual HostResolverImpl* GetAsHostResolverImpl() { return this; } @@ -244,6 +247,11 @@ class HostResolverImpl : public HostResolver, NetworkChangeNotifier* const network_change_notifier_; + // Indicate if probing is done after each network change event to set address + // family. + // When false, explicit setting of address family is used. + bool ipv6_probe_monitoring_; + scoped_refptr<RequestsTrace> requests_trace_; DISALLOW_COPY_AND_ASSIGN(HostResolverImpl); diff --git a/net/base/net_util.cc b/net/base/net_util.cc index a2eb04d..dea8c40 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -21,9 +21,11 @@ #include <ws2tcpip.h> #include <wspiapi.h> // Needed for Win2k compat. #elif defined(OS_POSIX) +#include <fcntl.h> +#include <ifaddrs.h> #include <netdb.h> +#include <net/if.h> #include <sys/socket.h> -#include <fcntl.h> #endif #include "base/base64.h" @@ -257,7 +259,7 @@ bool DecodeBQEncoding(const std::string& part, RFC2047EncodingType enc_type, bool DecodeWord(const std::string& encoded_word, const std::string& referrer_charset, - bool *is_rfc2047, + bool* is_rfc2047, std::string* output) { if (!IsStringASCII(encoded_word)) { // Try UTF-8, referrer_charset and the native OS default charset in turn. @@ -1541,15 +1543,21 @@ void SetExplicitlyAllowedPorts(const std::wstring& allowed_ports) { enum IPv6SupportStatus { IPV6_CANNOT_CREATE_SOCKETS, IPV6_CAN_CREATE_SOCKETS, + IPV6_GETIFADDRS_FAILED, + IPV6_GLOBAL_ADDRESS_MISSING, + IPV6_GLOBAL_ADDRESS_PRESENT, IPV6_SUPPORT_MAX // Bounding values for enumeration. }; static void IPv6SupportResults(IPv6SupportStatus result) { static bool run_once = false; - if (run_once) - return; - run_once = true; - UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status", result, IPV6_SUPPORT_MAX); + if (run_once) { + run_once = true; + UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status", result, IPV6_SUPPORT_MAX); + } else { + UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status_retest", result, + IPV6_SUPPORT_MAX); + } } // TODO(jar): The following is a simple estimate of IPv6 support. We may need @@ -1557,27 +1565,58 @@ static void IPv6SupportResults(IPv6SupportStatus result) { // static bool IPv6Supported() { #if defined(OS_POSIX) - int test_socket; - - test_socket = socket(AF_INET6, SOCK_STREAM, 0); + int test_socket = socket(AF_INET6, SOCK_STREAM, 0); if (test_socket == -1) { IPv6SupportResults(IPV6_CANNOT_CREATE_SOCKETS); return false; } - close(test_socket); - IPv6SupportResults(IPV6_CAN_CREATE_SOCKETS); + + // Check to see if any interface has a IPv6 address. + struct ifaddrs* interface_addr = NULL; + int rv = getifaddrs(&interface_addr); + if (rv != 0) { + IPv6SupportResults(IPV6_GETIFADDRS_FAILED); + return true; // Don't yet block IPv6. + } + + bool found_ipv6 = false; + for (struct ifaddrs* interface = interface_addr; + interface != NULL; + interface = interface->ifa_next) { + if (!(IFF_UP & interface->ifa_flags)) + continue; + if (IFF_LOOPBACK & interface->ifa_flags) + continue; + struct sockaddr* addr = interface->ifa_addr; + if (!addr) + continue; + if (addr->sa_family != AF_INET6) + continue; + // Safe cast since this is AF_INET6. + struct sockaddr_in6* addr_in6 = + reinterpret_cast<struct sockaddr_in6*>(addr); + struct in6_addr* sin6_addr = &addr_in6->sin6_addr; + if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) + continue; + found_ipv6 = true; + break; + } + freeifaddrs(interface_addr); + if (!found_ipv6) { + IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); + return false; + } + + IPv6SupportResults(IPV6_GLOBAL_ADDRESS_PRESENT); return true; #elif defined(OS_WIN) EnsureWinsockInit(); - SOCKET test_socket; - - test_socket = socket(AF_INET6, SOCK_STREAM, 0); + SOCKET test_socket = socket(AF_INET6, SOCK_STREAM, 0); if (test_socket == INVALID_SOCKET) { IPv6SupportResults(IPV6_CANNOT_CREATE_SOCKETS); return false; } - closesocket(test_socket); IPv6SupportResults(IPV6_CAN_CREATE_SOCKETS); return true; @@ -1587,5 +1626,4 @@ bool IPv6Supported() { #endif // defined(various platforms) } - } // namespace net |