Handle IPv4-mapped addresses in IP classification functions. This change ensures that functions like IPIsLoopback, IPIsLinkLocal, IPIsPrivateNetwork, and IPIsSharedNetwork correctly handle IPv4-mapped IPv6 addresses by normalizing them before classification. Bug: webrtc:479635018 Change-Id: I3a99f44e090d0cc0d2e1e7b55b0bfb75be78315f Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/462842 Reviewed-by: Danil Chapovalov <danilchap@webrtc.org> Commit-Queue: Harald Alvestrand <hta@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47406}
diff --git a/rtc_base/ip_address.cc b/rtc_base/ip_address.cc index 179bc37..007f13e 100644 --- a/rtc_base/ip_address.cc +++ b/rtc_base/ip_address.cc
@@ -229,12 +229,13 @@ } bool IPIsPrivateNetwork(const IPAddress& ip) { - switch (ip.family()) { + IPAddress normalized = ip.Normalized(); + switch (normalized.family()) { case AF_INET: { - return IPIsPrivateNetworkV4(ip); + return IPIsPrivateNetworkV4(normalized); } case AF_INET6: { - return IPIsPrivateNetworkV6(ip); + return IPIsPrivateNetworkV6(normalized); } } return false; @@ -246,8 +247,9 @@ } bool IPIsSharedNetwork(const IPAddress& ip) { - if (ip.family() == AF_INET) { - return IPIsSharedNetworkV4(ip); + IPAddress normalized = ip.Normalized(); + if (normalized.family() == AF_INET) { + return IPIsSharedNetworkV4(normalized); } return false; } @@ -324,12 +326,13 @@ } bool IPIsLoopback(const IPAddress& ip) { - switch (ip.family()) { + IPAddress normalized = ip.Normalized(); + switch (normalized.family()) { case AF_INET: { - return IPIsLoopbackV4(ip); + return IPIsLoopbackV4(normalized); } case AF_INET6: { - return IPIsLoopbackV6(ip); + return IPIsLoopbackV6(normalized); } } return false; @@ -345,12 +348,13 @@ } size_t HashIP(const IPAddress& ip) { - switch (ip.family()) { + IPAddress normalized = ip.Normalized(); + switch (normalized.family()) { case AF_INET: { - return ip.ipv4_address().s_addr; + return normalized.ipv4_address().s_addr; } case AF_INET6: { - in6_addr v6addr = ip.ipv6_address(); + in6_addr v6addr = normalized.ipv6_address(); const uint32_t* v6_as_ints = reinterpret_cast<const uint32_t*>(&v6addr.s6_addr); return v6_as_ints[0] ^ v6_as_ints[1] ^ v6_as_ints[2] ^ v6_as_ints[3]; @@ -483,12 +487,13 @@ } bool IPIsLinkLocal(const IPAddress& ip) { - switch (ip.family()) { + IPAddress normalized = ip.Normalized(); + switch (normalized.family()) { case AF_INET: { - return IPIsLinkLocalV4(ip); + return IPIsLinkLocalV4(normalized); } case AF_INET6: { - return IPIsLinkLocalV6(ip); + return IPIsLinkLocalV6(normalized); } } return false;
diff --git a/rtc_base/ip_address_unittest.cc b/rtc_base/ip_address_unittest.cc index 1e91727..38b625b 100644 --- a/rtc_base/ip_address_unittest.cc +++ b/rtc_base/ip_address_unittest.cc
@@ -634,6 +634,28 @@ EXPECT_TRUE(IPIsAny(IPAddress(kIPv4MappedAnyAddr))); } +TEST(IPAddressTest, TestMappedLocalAddresses) { + // IPv4 loopback: 127.0.0.1 + IPAddress v4_loopback(0x7f000001); + // IPv4-mapped IPv6 loopback: ::ffff:127.0.0.1 + IPAddress mapped_loopback = v4_loopback.AsIPv6Address(); + EXPECT_TRUE(IPIsLoopback(mapped_loopback)); + + // IPv4 private: 192.168.1.1 + IPAddress v4_private; + EXPECT_TRUE(IPFromString("192.168.1.1", &v4_private)); + // IPv4-mapped IPv6 private: ::ffff:192.168.1.1 + IPAddress mapped_private = v4_private.AsIPv6Address(); + EXPECT_TRUE(IPIsPrivate(mapped_private)); + + // IPv4 link-local: 169.254.1.1 + IPAddress v4_linklocal; + EXPECT_TRUE(IPFromString("169.254.1.1", &v4_linklocal)); + // IPv4-mapped IPv6 link-local: ::ffff:169.254.1.1 + IPAddress mapped_linklocal = v4_linklocal.AsIPv6Address(); + EXPECT_TRUE(IPIsLinkLocal(mapped_linklocal)); +} + TEST(IPAddressTest, TestIsEui64) { IPAddress addr; EXPECT_TRUE(IPFromString(kIPv6EuiAddrString, &addr));