summaryrefslogtreecommitdiffstats
path: root/net/base/net_util.cc
diff options
context:
space:
mode:
authorjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 05:33:45 +0000
committerjar@chromium.org <jar@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-26 05:33:45 +0000
commit7be4c7eef651408e7e0cd30edf5b48e2ee93f226 (patch)
treeb3d6849e0df9a999c5a9d6425dd4004bd474d508 /net/base/net_util.cc
parent196e32aed9931577e45f76d482f5db8372a51a31 (diff)
downloadchromium_src-7be4c7eef651408e7e0cd30edf5b48e2ee93f226.zip
chromium_src-7be4c7eef651408e7e0cd30edf5b48e2ee93f226.tar.gz
chromium_src-7be4c7eef651408e7e0cd30edf5b48e2ee93f226.tar.bz2
Revert 39998 - Revert 39996 Refine IPv6 probe to require that the client has an IPv6 address on an interface
This is a second attempt to land a reviewed change. It was reverted because the tree got very red (for other reasons), and it was plausible that this change was causing startup latency in Mac and Linux (causing both perf bots to go red). If this landing turns those perf-bots red (tonight) I'll need to revert. (... and I'll need to rearchitect to do the probes asynchronously, and get off the startup-critical-path. This currently only works on Posix, not windows. Network changes are monitored, and the test is repeated each time interfaces change (which is a subset of any IP addresses changing). The test performed is still relatively low latency, and we *may* need to eventually move to an high latency test, such as a DNS resolution, or an actual test connection. If we move in that direction, then we'll need to post a task to perform the work, rather than immediately returning. BUG=25680 BUG=12754 r=wtc,eroman Review URL: http://codereview.chromium.org/652072 TBR=jar@chromium.org Review URL: http://codereview.chromium.org/660073 TBR=jar@chromium.org Review URL: http://codereview.chromium.org/661164 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@40099 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/net_util.cc')
-rw-r--r--net/base/net_util.cc70
1 files changed, 54 insertions, 16 deletions
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