Index: net/base/net_util.cc |
=================================================================== |
--- net/base/net_util.cc (revision 42509) |
+++ net/base/net_util.cc (working copy) |
@@ -1555,10 +1555,11 @@ |
enum IPv6SupportStatus { |
IPV6_CANNOT_CREATE_SOCKETS, |
- IPV6_CAN_CREATE_SOCKETS, |
+ IPV6_CAN_CREATE_SOCKETS, // Deprecated: No longer used. |
IPV6_GETIFADDRS_FAILED, |
IPV6_GLOBAL_ADDRESS_MISSING, |
IPV6_GLOBAL_ADDRESS_PRESENT, |
+ IPV6_INTERFACE_ARRAY_TOO_SHORT, |
IPV6_SUPPORT_MAX // Bounding values for enumeration. |
}; |
@@ -1631,8 +1632,43 @@ |
return false; |
} |
closesocket(test_socket); |
- IPv6SupportResults(IPV6_CAN_CREATE_SOCKETS); |
- return true; |
+ |
+ // Check to see if any interface has a IPv6 address. |
+ // Note: The original IPv6 socket can't be used here, as WSAIoctl() will fail. |
+ test_socket = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0, 0); |
+ DCHECK(test_socket != INVALID_SOCKET); |
+ INTERFACE_INFO interfaces[128]; |
+ DWORD bytes_written = 0; |
+ int rv = WSAIoctl(test_socket, SIO_GET_INTERFACE_LIST, NULL, 0, interfaces, |
+ sizeof(interfaces), &bytes_written, NULL, NULL); |
+ closesocket(test_socket); |
+ |
+ if (0 != rv) { |
+ if (WSAGetLastError() == WSAEFAULT) |
+ IPv6SupportResults(IPV6_INTERFACE_ARRAY_TOO_SHORT); |
+ else |
+ IPv6SupportResults(IPV6_GETIFADDRS_FAILED); |
+ return true; // Don't yet block IPv6. |
+ } |
+ size_t interface_count = bytes_written / sizeof(interfaces[0]); |
+ for (size_t i = 0; i < interface_count; ++i) { |
+ INTERFACE_INFO* interface = &interfaces[i]; |
+ if (!(IFF_UP & interface->iiFlags)) |
+ continue; |
+ if (IFF_LOOPBACK & interface->iiFlags) |
+ continue; |
+ sockaddr* addr = &interface->iiAddress.Address; |
+ if (addr->sa_family != AF_INET6) |
+ continue; |
+ struct in6_addr* sin6_addr = &interface->iiAddress.AddressIn6.sin6_addr; |
+ if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) |
+ continue; |
+ IPv6SupportResults(IPV6_GLOBAL_ADDRESS_PRESENT); |
+ return true; |
+ } |
+ |
+ IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); |
+ return false; |
#else |
NOTIMPLEMENTED(); |
return true; |