diff --git a/webrtc/base/ipaddress.cc b/webrtc/base/ipaddress.cc index be709c834..ae3b38da8 100644 --- a/webrtc/base/ipaddress.cc +++ b/webrtc/base/ipaddress.cc @@ -300,9 +300,7 @@ bool IPIsPrivate(const IPAddress& ip) { return IsPrivateV4(ip.v4AddressAsHostOrderInteger()); } case AF_INET6: { - in6_addr v6 = ip.ipv6_address(); - return (v6.s6_addr[0] == 0xFE && v6.s6_addr[1] == 0x80) || - IPIsLoopback(ip); + return IPIsLinkLocal(ip) || IPIsLoopback(ip); } } return false; @@ -435,7 +433,16 @@ bool IPIs6To4(const IPAddress& ip) { bool IPIsLinkLocal(const IPAddress& ip) { // Can't use the helper because the prefix is 10 bits. in6_addr addr = ip.ipv6_address(); - return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0x80) == 0x80; + return addr.s6_addr[0] == 0xFE && addr.s6_addr[1] == 0x80; +} + +// According to http://www.ietf.org/rfc/rfc2373.txt, Appendix A, page 19. An +// address which contains MAC will have its 11th and 12th bytes as FF:FE as well +// as the U/L bit as 1. +bool IPIsMacBased(const IPAddress& ip) { + in6_addr addr = ip.ipv6_address(); + return ((addr.s6_addr[8] & 0x02) && addr.s6_addr[11] == 0xFF && + addr.s6_addr[12] == 0xFE); } bool IPIsSiteLocal(const IPAddress& ip) { diff --git a/webrtc/base/ipaddress.h b/webrtc/base/ipaddress.h index 3d77c28b2..fb222eeba 100644 --- a/webrtc/base/ipaddress.h +++ b/webrtc/base/ipaddress.h @@ -163,6 +163,7 @@ size_t HashIP(const IPAddress& ip); bool IPIs6Bone(const IPAddress& ip); bool IPIs6To4(const IPAddress& ip); bool IPIsLinkLocal(const IPAddress& ip); +bool IPIsMacBased(const IPAddress& ip); bool IPIsSiteLocal(const IPAddress& ip); bool IPIsTeredo(const IPAddress& ip); bool IPIsULA(const IPAddress& ip); diff --git a/webrtc/base/ipaddress_unittest.cc b/webrtc/base/ipaddress_unittest.cc index 7ff6c095f..3a8087a5d 100644 --- a/webrtc/base/ipaddress_unittest.cc +++ b/webrtc/base/ipaddress_unittest.cc @@ -46,6 +46,10 @@ static const std::string kIPv4PublicAddrAnonymizedString = "1.2.3.x"; static const std::string kIPv6AnyAddrString = "::"; static const std::string kIPv6LoopbackAddrString = "::1"; static const std::string kIPv6LinkLocalAddrString = "fe80::be30:5bff:fee5:c3"; +static const std::string kIPv6EuiAddrString = + "2620:0:1008:1201:a248:1cff:fe98:360"; +static const std::string kIPv6TemporaryAddrString = + "2620:0:1008:1201:2089:6dda:385e:80c0"; static const std::string kIPv6PublicAddrString = "2401:fa00:4:1000:be30:5bff:fee5:c3"; static const std::string kIPv6PublicAddrAnonymizedString = "2401:fa00:4::"; @@ -565,6 +569,24 @@ TEST(IPAddressTest, TestIsAny) { EXPECT_TRUE(IPIsAny(IPAddress(kIPv4MappedAnyAddr))); } +TEST(IPAddressTest, TestIsEui64) { + IPAddress addr; + EXPECT_TRUE(IPFromString(kIPv6EuiAddrString, &addr)); + EXPECT_TRUE(IPIsMacBased(addr)); + + EXPECT_TRUE(IPFromString(kIPv6TemporaryAddrString, &addr)); + EXPECT_FALSE(IPIsMacBased(addr)); + + EXPECT_TRUE(IPFromString(kIPv6LinkLocalAddrString, &addr)); + EXPECT_TRUE(IPIsMacBased(addr)); + + EXPECT_TRUE(IPFromString(kIPv6AnyAddrString, &addr)); + EXPECT_FALSE(IPIsMacBased(addr)); + + EXPECT_TRUE(IPFromString(kIPv6LoopbackAddrString, &addr)); + EXPECT_FALSE(IPIsMacBased(addr)); +} + TEST(IPAddressTest, TestNormalized) { // Check normalizing a ::ffff:a.b.c.d address. IPAddress addr; diff --git a/webrtc/base/network.cc b/webrtc/base/network.cc index 9ed1c87e3..ff092366f 100644 --- a/webrtc/base/network.cc +++ b/webrtc/base/network.cc @@ -128,6 +128,26 @@ std::string AdapterTypeToString(AdapterType type) { } } +bool IsIgnoredIPv6(const IPAddress& ip) { + if (ip.family() != AF_INET6) { + return false; + } + + // Link-local addresses require scope id to be bound successfully. + // However, our IPAddress structure doesn't carry that so the + // information is lost and causes binding failure. + if (IPIsLinkLocal(ip)) { + return true; + } + + // Any MAC based IPv6 should be avoided to prevent the MAC tracking. + if (IPIsMacBased(ip)) { + return true; + } + + return false; +} + } // namespace std::string MakeNetworkKey(const std::string& name, const IPAddress& prefix, @@ -334,6 +354,11 @@ void BasicNetworkManager::ConvertIfAddrs(struct ifaddrs* interfaces, if (ipv6_enabled()) { ip = IPAddress( reinterpret_cast(cursor->ifa_addr)->sin6_addr); + + if (IsIgnoredIPv6(ip)) { + continue; + } + mask = IPAddress( reinterpret_cast(cursor->ifa_netmask)->sin6_addr); scope_id = @@ -489,6 +514,11 @@ bool BasicNetworkManager::CreateNetworks(bool include_ignored, reinterpret_cast(address->Address.lpSockaddr); scope_id = v6_addr->sin6_scope_id; ip = IPAddress(v6_addr->sin6_addr); + + if (IsIgnoredIPv6(ip)) { + continue; + } + break; } else { continue; @@ -602,13 +632,6 @@ bool BasicNetworkManager::IsIgnoredNetwork(const Network& network) const { return (network.prefix().v4AddressAsHostOrderInteger() < 0x01000000); } - // Linklocal addresses require scope id to be bound successfully. However, our - // IPAddress structure doesn't carry that so the information is lost and - // causes binding failure. - if (network.prefix().family() == AF_INET6 && - IPIsLinkLocal(network.GetBestIP())) { - return true; - } return false; } diff --git a/webrtc/base/network.h b/webrtc/base/network.h index 69108fe01..8e5c8f0fb 100644 --- a/webrtc/base/network.h +++ b/webrtc/base/network.h @@ -195,7 +195,8 @@ class BasicNetworkManager : public NetworkManagerBase, // Creates a network object for each network available on the machine. bool CreateNetworks(bool include_ignored, NetworkList* networks) const; - // Determines if a network should be ignored. + // Determines if a network should be ignored. This should only be determined + // based on the network's property instead of any individual IP. bool IsIgnoredNetwork(const Network& network) const; private: