diff options
author | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-10 22:36:49 +0000 |
---|---|---|
committer | wtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-10 22:36:49 +0000 |
commit | 8c51eebccd3f172634c29f392c00f6fada17d164 (patch) | |
tree | c511a61f0154c388c428fab0dff7e31a506f7bc8 /net/base/net_util.cc | |
parent | 350fc5264699040e1fb43d532a99e41b6b231a76 (diff) | |
download | chromium_src-8c51eebccd3f172634c29f392c00f6fada17d164.zip chromium_src-8c51eebccd3f172634c29f392c00f6fada17d164.tar.gz chromium_src-8c51eebccd3f172634c29f392c00f6fada17d164.tar.bz2 |
Implement IPv6Supported() for Windows using the
GetAdaptersAddresses function.
R=eroman
BUG=40851
TEST=none
Review URL: http://codereview.chromium.org/6621016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77718 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/base/net_util.cc')
-rw-r--r-- | net/base/net_util.cc | 82 |
1 files changed, 50 insertions, 32 deletions
diff --git a/net/base/net_util.cc b/net/base/net_util.cc index 0528d50..f3b0127 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -19,7 +19,8 @@ #if defined(OS_WIN) #include <windows.h> #include <winsock2.h> -#include <wspiapi.h> // Needed for Win2k compat. +#include <iphlpapi.h> +#pragma comment(lib, "iphlpapi.lib") #elif defined(OS_POSIX) #include <fcntl.h> #include <ifaddrs.h> @@ -1845,42 +1846,55 @@ bool IPv6Supported() { } closesocket(test_socket); - // TODO(jar): Bug 40851: The remainder of probe is not working. - IPv6SupportResults(IPV6_CAN_CREATE_SOCKETS); // Record status. - return true; // Don't disable IPv6 yet. - // 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 = socket(AF_INET, SOCK_STREAM, 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); + // The GetAdaptersAddresses MSDN page recommends using a size of 15000 to + // avoid reallocation. + ULONG adapters_size = 15000; + scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> adapters; + ULONG error; + int num_tries = 0; + do { + adapters.reset( + reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(adapters_size))); + // Return only unicast addresses. + error = GetAdaptersAddresses(AF_UNSPEC, + GAA_FLAG_SKIP_ANYCAST | + GAA_FLAG_SKIP_MULTICAST | + GAA_FLAG_SKIP_DNS_SERVER | + GAA_FLAG_SKIP_FRIENDLY_NAME, + NULL, adapters.get(), &adapters_size); + num_tries++; + } while (error == ERROR_BUFFER_OVERFLOW && num_tries <= 3); + if (error == ERROR_NO_DATA) { + IPv6SupportResults(IPV6_GLOBAL_ADDRESS_MISSING); + return false; + } + if (error != ERROR_SUCCESS) { + 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) + + PIP_ADAPTER_ADDRESSES adapter; + for (adapter = adapters.get(); adapter; adapter = adapter->Next) { + if (adapter->OperStatus != IfOperStatusUp) continue; - struct in6_addr* sin6_addr = &interface->iiAddress.AddressIn6.sin6_addr; - if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) + if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) continue; - IPv6SupportResults(IPV6_GLOBAL_ADDRESS_PRESENT); - return true; + PIP_ADAPTER_UNICAST_ADDRESS unicast_address; + for (unicast_address = adapter->FirstUnicastAddress; + unicast_address; + unicast_address = unicast_address->Next) { + if (unicast_address->Address.lpSockaddr->sa_family != AF_INET6) + continue; + // Safe cast since this is AF_INET6. + struct sockaddr_in6* addr_in6 = reinterpret_cast<struct sockaddr_in6*>( + unicast_address->Address.lpSockaddr); + struct in6_addr* sin6_addr = &addr_in6->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); @@ -1927,6 +1941,10 @@ bool HaveOnlyLoopbackAddresses() { } freeifaddrs(interface_addr); return result; +#elif defined(OS_WIN) + // TODO(wtc): implement with the GetAdaptersAddresses function. + NOTIMPLEMENTED(); + return false; #else NOTIMPLEMENTED(); return false; |