| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/net_util.h" | 5 #include "net/base/net_util.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <map> | 9 #include <map> |
| 10 | 10 |
| (...skipping 1777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1788 | 1788 |
| 1789 ScopedPortException::~ScopedPortException() { | 1789 ScopedPortException::~ScopedPortException() { |
| 1790 std::multiset<int>::iterator it = | 1790 std::multiset<int>::iterator it = |
| 1791 g_explicitly_allowed_ports.Get().find(port_); | 1791 g_explicitly_allowed_ports.Get().find(port_); |
| 1792 if (it != g_explicitly_allowed_ports.Get().end()) | 1792 if (it != g_explicitly_allowed_ports.Get().end()) |
| 1793 g_explicitly_allowed_ports.Get().erase(it); | 1793 g_explicitly_allowed_ports.Get().erase(it); |
| 1794 else | 1794 else |
| 1795 NOTREACHED(); | 1795 NOTREACHED(); |
| 1796 } | 1796 } |
| 1797 | 1797 |
| 1798 namespace { | |
| 1799 | |
| 1800 const char* kFinalStatusNames[] = { | |
| 1801 "Cannot create sockets", | |
| 1802 "Can create sockets", | |
| 1803 "Can't get addresses", | |
| 1804 "Global ipv6 address missing", | |
| 1805 "Global ipv6 address present", | |
| 1806 "Interface array too short", | |
| 1807 "Probing not supported", // IPV6_SUPPORT_MAX | |
| 1808 }; | |
| 1809 COMPILE_ASSERT(arraysize(kFinalStatusNames) == IPV6_SUPPORT_MAX + 1, | |
| 1810 IPv6SupportStatus_name_count_mismatch); | |
| 1811 | |
| 1812 // TODO(jar): The following is a simple estimate of IPv6 support. We may need | |
| 1813 // to do a test resolution, and a test connection, to REALLY verify support. | |
| 1814 IPv6SupportResult TestIPv6SupportInternal() { | |
| 1815 #if defined(OS_ANDROID) | |
| 1816 // TODO: We should fully implement IPv6 probe once 'getifaddrs' API available; | |
| 1817 // Another approach is implementing the similar feature by | |
| 1818 // java.net.NetworkInterface through JNI. | |
| 1819 NOTIMPLEMENTED(); | |
| 1820 return IPv6SupportResult(true, IPV6_SUPPORT_MAX, 0); | |
| 1821 #elif defined(OS_POSIX) | |
| 1822 int test_socket = socket(AF_INET6, SOCK_STREAM, 0); | |
| 1823 if (test_socket == -1) | |
| 1824 return IPv6SupportResult(false, IPV6_CANNOT_CREATE_SOCKETS, errno); | |
| 1825 close(test_socket); | |
| 1826 | |
| 1827 // Check to see if any interface has a IPv6 address. | |
| 1828 struct ifaddrs* interface_addr = NULL; | |
| 1829 int rv = getifaddrs(&interface_addr); | |
| 1830 if (rv != 0) { | |
| 1831 // Don't yet block IPv6. | |
| 1832 return IPv6SupportResult(true, IPV6_GETIFADDRS_FAILED, errno); | |
| 1833 } | |
| 1834 | |
| 1835 bool found_ipv6 = false; | |
| 1836 for (struct ifaddrs* interface = interface_addr; | |
| 1837 interface != NULL; | |
| 1838 interface = interface->ifa_next) { | |
| 1839 if (!(IFF_UP & interface->ifa_flags)) | |
| 1840 continue; | |
| 1841 if (IFF_LOOPBACK & interface->ifa_flags) | |
| 1842 continue; | |
| 1843 struct sockaddr* addr = interface->ifa_addr; | |
| 1844 if (!addr) | |
| 1845 continue; | |
| 1846 if (addr->sa_family != AF_INET6) | |
| 1847 continue; | |
| 1848 // Safe cast since this is AF_INET6. | |
| 1849 struct sockaddr_in6* addr_in6 = | |
| 1850 reinterpret_cast<struct sockaddr_in6*>(addr); | |
| 1851 struct in6_addr* sin6_addr = &addr_in6->sin6_addr; | |
| 1852 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) | |
| 1853 continue; | |
| 1854 found_ipv6 = true; | |
| 1855 break; | |
| 1856 } | |
| 1857 freeifaddrs(interface_addr); | |
| 1858 if (!found_ipv6) | |
| 1859 return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, 0); | |
| 1860 | |
| 1861 return IPv6SupportResult(true, IPV6_GLOBAL_ADDRESS_PRESENT, 0); | |
| 1862 #elif defined(OS_WIN) | |
| 1863 EnsureWinsockInit(); | |
| 1864 SOCKET test_socket = socket(AF_INET6, SOCK_STREAM, 0); | |
| 1865 if (test_socket == INVALID_SOCKET) { | |
| 1866 return IPv6SupportResult(false, | |
| 1867 IPV6_CANNOT_CREATE_SOCKETS, | |
| 1868 WSAGetLastError()); | |
| 1869 } | |
| 1870 closesocket(test_socket); | |
| 1871 | |
| 1872 // Check to see if any interface has a IPv6 address. | |
| 1873 // The GetAdaptersAddresses MSDN page recommends using a size of 15000 to | |
| 1874 // avoid reallocation. | |
| 1875 ULONG adapters_size = 15000; | |
| 1876 scoped_ptr_malloc<IP_ADAPTER_ADDRESSES> adapters; | |
| 1877 ULONG error; | |
| 1878 int num_tries = 0; | |
| 1879 do { | |
| 1880 adapters.reset( | |
| 1881 reinterpret_cast<PIP_ADAPTER_ADDRESSES>(malloc(adapters_size))); | |
| 1882 // Return only unicast addresses. | |
| 1883 error = GetAdaptersAddresses(AF_UNSPEC, | |
| 1884 GAA_FLAG_SKIP_ANYCAST | | |
| 1885 GAA_FLAG_SKIP_MULTICAST | | |
| 1886 GAA_FLAG_SKIP_DNS_SERVER | | |
| 1887 GAA_FLAG_SKIP_FRIENDLY_NAME, | |
| 1888 NULL, adapters.get(), &adapters_size); | |
| 1889 num_tries++; | |
| 1890 } while (error == ERROR_BUFFER_OVERFLOW && num_tries <= 3); | |
| 1891 if (error == ERROR_NO_DATA) | |
| 1892 return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, error); | |
| 1893 if (error != ERROR_SUCCESS) { | |
| 1894 // Don't yet block IPv6. | |
| 1895 return IPv6SupportResult(true, IPV6_GETIFADDRS_FAILED, error); | |
| 1896 } | |
| 1897 | |
| 1898 PIP_ADAPTER_ADDRESSES adapter; | |
| 1899 for (adapter = adapters.get(); adapter; adapter = adapter->Next) { | |
| 1900 if (adapter->OperStatus != IfOperStatusUp) | |
| 1901 continue; | |
| 1902 if (adapter->IfType == IF_TYPE_SOFTWARE_LOOPBACK) | |
| 1903 continue; | |
| 1904 PIP_ADAPTER_UNICAST_ADDRESS unicast_address; | |
| 1905 for (unicast_address = adapter->FirstUnicastAddress; | |
| 1906 unicast_address; | |
| 1907 unicast_address = unicast_address->Next) { | |
| 1908 if (unicast_address->Address.lpSockaddr->sa_family != AF_INET6) | |
| 1909 continue; | |
| 1910 // Safe cast since this is AF_INET6. | |
| 1911 struct sockaddr_in6* addr_in6 = reinterpret_cast<struct sockaddr_in6*>( | |
| 1912 unicast_address->Address.lpSockaddr); | |
| 1913 struct in6_addr* sin6_addr = &addr_in6->sin6_addr; | |
| 1914 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) | |
| 1915 continue; | |
| 1916 const uint8 kTeredoPrefix[] = { 0x20, 0x01, 0, 0 }; | |
| 1917 if (!memcmp(sin6_addr->s6_addr, kTeredoPrefix, arraysize(kTeredoPrefix))) | |
| 1918 continue; | |
| 1919 return IPv6SupportResult(true, IPV6_GLOBAL_ADDRESS_PRESENT, 0); | |
| 1920 } | |
| 1921 } | |
| 1922 | |
| 1923 return IPv6SupportResult(false, IPV6_GLOBAL_ADDRESS_MISSING, 0); | |
| 1924 #else | |
| 1925 NOTIMPLEMENTED(); | |
| 1926 return IPv6SupportResult(true, IPV6_SUPPORT_MAX, 0); | |
| 1927 #endif // defined(various platforms) | |
| 1928 } | |
| 1929 | |
| 1930 } // namespace | |
| 1931 | |
| 1932 IPv6SupportResult::IPv6SupportResult(bool ipv6_supported, | |
| 1933 IPv6SupportStatus ipv6_support_status, | |
| 1934 int os_error) | |
| 1935 : ipv6_supported(ipv6_supported), | |
| 1936 ipv6_support_status(ipv6_support_status), | |
| 1937 os_error(os_error) { | |
| 1938 } | |
| 1939 | |
| 1940 base::Value* IPv6SupportResult::ToNetLogValue( | |
| 1941 NetLog::LogLevel /* log_level */) const { | |
| 1942 base::DictionaryValue* dict = new base::DictionaryValue(); | |
| 1943 dict->SetBoolean("ipv6_supported", ipv6_supported); | |
| 1944 dict->SetString("ipv6_support_status", | |
| 1945 kFinalStatusNames[ipv6_support_status]); | |
| 1946 if (os_error) | |
| 1947 dict->SetInteger("os_error", os_error); | |
| 1948 return dict; | |
| 1949 } | |
| 1950 | |
| 1951 IPv6SupportResult TestIPv6Support() { | |
| 1952 IPv6SupportResult result = TestIPv6SupportInternal(); | |
| 1953 | |
| 1954 // Record UMA. | |
| 1955 if (result.ipv6_support_status != IPV6_SUPPORT_MAX) { | |
| 1956 static bool run_once = false; | |
| 1957 if (!run_once) { | |
| 1958 run_once = true; | |
| 1959 UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status", | |
| 1960 result.ipv6_support_status, | |
| 1961 IPV6_SUPPORT_MAX); | |
| 1962 } else { | |
| 1963 UMA_HISTOGRAM_ENUMERATION("Net.IPv6Status_retest", | |
| 1964 result.ipv6_support_status, | |
| 1965 IPV6_SUPPORT_MAX); | |
| 1966 } | |
| 1967 } | |
| 1968 return result; | |
| 1969 } | |
| 1970 | |
| 1971 bool HaveOnlyLoopbackAddresses() { | 1798 bool HaveOnlyLoopbackAddresses() { |
| 1972 #if defined(OS_ANDROID) | 1799 #if defined(OS_ANDROID) |
| 1973 return android::HaveOnlyLoopbackAddresses(); | 1800 return android::HaveOnlyLoopbackAddresses(); |
| 1974 #elif defined(OS_POSIX) | 1801 #elif defined(OS_POSIX) |
| 1975 struct ifaddrs* interface_addr = NULL; | 1802 struct ifaddrs* interface_addr = NULL; |
| 1976 int rv = getifaddrs(&interface_addr); | 1803 int rv = getifaddrs(&interface_addr); |
| 1977 if (rv != 0) { | 1804 if (rv != 0) { |
| 1978 DVLOG(1) << "getifaddrs() failed with errno = " << errno; | 1805 DVLOG(1) << "getifaddrs() failed with errno = " << errno; |
| 1979 return false; | 1806 return false; |
| 1980 } | 1807 } |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2224 | 2051 |
| 2225 NetworkInterface::NetworkInterface(const std::string& name, | 2052 NetworkInterface::NetworkInterface(const std::string& name, |
| 2226 const IPAddressNumber& address) | 2053 const IPAddressNumber& address) |
| 2227 : name(name), address(address) { | 2054 : name(name), address(address) { |
| 2228 } | 2055 } |
| 2229 | 2056 |
| 2230 NetworkInterface::~NetworkInterface() { | 2057 NetworkInterface::~NetworkInterface() { |
| 2231 } | 2058 } |
| 2232 | 2059 |
| 2233 } // namespace net | 2060 } // namespace net |
| OLD | NEW |