| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "net/base/ip_address.h" |
| |
| #include <vector> |
| |
| #include "base/format_macros.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/stringprintf.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace net { |
| |
| namespace { |
| |
| // Helper to stringize an IP address (used to define expectations). |
| std::string DumpIPAddress(const IPAddress& v) { |
| std::string out; |
| for (size_t i = 0; i < v.bytes().size(); ++i) { |
| if (i != 0) |
| out.append(","); |
| out.append(base::UintToString(v.bytes()[i])); |
| } |
| return out; |
| } |
| |
| TEST(IPAddressBytesTest, ConstructEmpty) { |
| IPAddressBytes bytes; |
| ASSERT_EQ(0u, bytes.size()); |
| } |
| |
| TEST(IPAddressBytesTest, ConstructIPv4) { |
| uint8_t data[] = {192, 168, 1, 1}; |
| IPAddressBytes bytes(data, base::size(data)); |
| ASSERT_EQ(base::size(data), bytes.size()); |
| size_t i = 0; |
| for (uint8_t byte : bytes) |
| EXPECT_EQ(data[i++], byte); |
| ASSERT_EQ(base::size(data), i); |
| } |
| |
| TEST(IPAddressBytesTest, ConstructIPv6) { |
| uint8_t data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; |
| IPAddressBytes bytes(data, base::size(data)); |
| ASSERT_EQ(base::size(data), bytes.size()); |
| size_t i = 0; |
| for (uint8_t byte : bytes) |
| EXPECT_EQ(data[i++], byte); |
| ASSERT_EQ(base::size(data), i); |
| } |
| |
| TEST(IPAddressBytesTest, Assign) { |
| uint8_t data[] = {192, 168, 1, 1}; |
| IPAddressBytes copy; |
| copy.Assign(data, base::size(data)); |
| EXPECT_EQ(IPAddressBytes(data, base::size(data)), copy); |
| } |
| |
| TEST(IPAddressTest, ConstructIPv4) { |
| EXPECT_EQ("127.0.0.1", IPAddress::IPv4Localhost().ToString()); |
| |
| IPAddress ipv4_ctor(192, 168, 1, 1); |
| EXPECT_EQ("192.168.1.1", ipv4_ctor.ToString()); |
| } |
| |
| TEST(IPAddressTest, IsIPVersion) { |
| uint8_t addr1[4] = {192, 168, 0, 1}; |
| IPAddress ip_address1(addr1); |
| EXPECT_TRUE(ip_address1.IsIPv4()); |
| EXPECT_FALSE(ip_address1.IsIPv6()); |
| |
| uint8_t addr2[16] = {0xFE, 0xDC, 0xBA, 0x98}; |
| IPAddress ip_address2(addr2); |
| EXPECT_TRUE(ip_address2.IsIPv6()); |
| EXPECT_FALSE(ip_address2.IsIPv4()); |
| |
| IPAddress ip_address3; |
| EXPECT_FALSE(ip_address3.IsIPv6()); |
| EXPECT_FALSE(ip_address3.IsIPv4()); |
| } |
| |
| TEST(IPAddressTest, IsValid) { |
| uint8_t addr1[4] = {192, 168, 0, 1}; |
| IPAddress ip_address1(addr1); |
| EXPECT_TRUE(ip_address1.IsValid()); |
| EXPECT_FALSE(ip_address1.empty()); |
| |
| uint8_t addr2[16] = {0xFE, 0xDC, 0xBA, 0x98}; |
| IPAddress ip_address2(addr2); |
| EXPECT_TRUE(ip_address2.IsValid()); |
| EXPECT_FALSE(ip_address2.empty()); |
| |
| uint8_t addr3[5] = {0xFE, 0xDC, 0xBA, 0x98}; |
| IPAddress ip_address3(addr3); |
| EXPECT_FALSE(ip_address3.IsValid()); |
| EXPECT_FALSE(ip_address3.empty()); |
| |
| IPAddress ip_address4; |
| EXPECT_FALSE(ip_address4.IsValid()); |
| EXPECT_TRUE(ip_address4.empty()); |
| } |
| |
| enum IPAddressReservedResult : bool { NOT_RESERVED = false, RESERVED = true }; |
| |
| // Tests for the reserved IPv4 ranges and the (unreserved) blocks in between. |
| // The reserved ranges are tested by checking the first and last address of each |
| // range. The unreserved blocks are tested similarly. These tests cover the |
| // entire IPv4 address range, as well as this range mapped to IPv6. |
| TEST(IPAddressTest, IsPubliclyRoutableIPv4) { |
| struct { |
| const char* const address; |
| IPAddressReservedResult is_reserved; |
| } tests[] = {// 0.0.0.0/8 |
| {"0.0.0.0", RESERVED}, |
| {"0.255.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"1.0.0.0", NOT_RESERVED}, |
| {"9.255.255.255", NOT_RESERVED}, |
| // 10.0.0.0/8 |
| {"10.0.0.0", RESERVED}, |
| {"10.255.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"11.0.0.0", NOT_RESERVED}, |
| {"100.63.255.255", NOT_RESERVED}, |
| // 100.64.0.0/10 |
| {"100.64.0.0", RESERVED}, |
| {"100.127.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"100.128.0.0", NOT_RESERVED}, |
| {"126.255.255.255", NOT_RESERVED}, |
| // 127.0.0.0/8 |
| {"127.0.0.0", RESERVED}, |
| {"127.255.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"128.0.0.0", NOT_RESERVED}, |
| {"169.253.255.255", NOT_RESERVED}, |
| // 169.254.0.0/16 |
| {"169.254.0.0", RESERVED}, |
| {"169.254.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"169.255.0.0", NOT_RESERVED}, |
| {"172.15.255.255", NOT_RESERVED}, |
| // 172.16.0.0/12 |
| {"172.16.0.0", RESERVED}, |
| {"172.31.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"172.32.0.0", NOT_RESERVED}, |
| {"191.255.255.255", NOT_RESERVED}, |
| // 192.0.0.0/24 (including sub ranges) |
| {"192.0.0.0", NOT_RESERVED}, |
| {"192.0.0.255", NOT_RESERVED}, |
| // Unreserved block(s) |
| {"192.0.1.0", NOT_RESERVED}, |
| {"192.0.1.255", NOT_RESERVED}, |
| // 192.0.2.0/24 |
| {"192.0.2.0", RESERVED}, |
| {"192.0.2.255", RESERVED}, |
| // Unreserved block(s) |
| {"192.0.3.0", NOT_RESERVED}, |
| {"192.31.195.255", NOT_RESERVED}, |
| // 192.31.196.0/24 |
| {"192.31.196.0", NOT_RESERVED}, |
| {"192.31.196.255", NOT_RESERVED}, |
| // Unreserved block(s) |
| {"192.32.197.0", NOT_RESERVED}, |
| {"192.52.192.255", NOT_RESERVED}, |
| // 192.52.193.0/24 |
| {"192.52.193.0", NOT_RESERVED}, |
| {"192.52.193.255", NOT_RESERVED}, |
| // Unreserved block(s) |
| {"192.52.194.0", NOT_RESERVED}, |
| {"192.88.98.255", NOT_RESERVED}, |
| // 192.88.99.0/24 |
| {"192.88.99.0", RESERVED}, |
| {"192.88.99.255", RESERVED}, |
| // Unreserved block(s) |
| {"192.88.100.0", NOT_RESERVED}, |
| {"192.167.255.255", NOT_RESERVED}, |
| // 192.168.0.0/16 |
| {"192.168.0.0", RESERVED}, |
| {"192.168.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"192.169.0.0", NOT_RESERVED}, |
| {"192.175.47.255", NOT_RESERVED}, |
| // 192.175.48.0/24 |
| {"192.175.48.0", NOT_RESERVED}, |
| {"192.175.48.255", NOT_RESERVED}, |
| // Unreserved block(s) |
| {"192.175.49.0", NOT_RESERVED}, |
| {"198.17.255.255", NOT_RESERVED}, |
| // 198.18.0.0/15 |
| {"198.18.0.0", RESERVED}, |
| {"198.19.255.255", RESERVED}, |
| // Unreserved block(s) |
| {"198.20.0.0", NOT_RESERVED}, |
| {"198.51.99.255", NOT_RESERVED}, |
| // 198.51.100.0/24 |
| {"198.51.100.0", RESERVED}, |
| {"198.51.100.255", RESERVED}, |
| // Unreserved block(s) |
| {"198.51.101.0", NOT_RESERVED}, |
| {"203.0.112.255", NOT_RESERVED}, |
| // 203.0.113.0/24 |
| {"203.0.113.0", RESERVED}, |
| {"203.0.113.255", RESERVED}, |
| // Unreserved block(s) |
| {"203.0.114.0", NOT_RESERVED}, |
| {"223.255.255.255", NOT_RESERVED}, |
| // 224.0.0.0/8 - 255.0.0.0/8 |
| {"224.0.0.0", RESERVED}, |
| {"255.255.255.255", RESERVED}}; |
| |
| IPAddress address; |
| IPAddress mapped_address; |
| for (const auto& test : tests) { |
| EXPECT_TRUE(address.AssignFromIPLiteral(test.address)); |
| ASSERT_TRUE(address.IsValid()); |
| EXPECT_EQ(!test.is_reserved, address.IsPubliclyRoutable()); |
| |
| // Check these IPv4 addresses when mapped to IPv6. This verifies we're |
| // properly unpacking mapped addresses. |
| IPAddress mapped_address = ConvertIPv4ToIPv4MappedIPv6(address); |
| EXPECT_EQ(!test.is_reserved, mapped_address.IsPubliclyRoutable()); |
| } |
| } |
| |
| // Tests for the reserved IPv6 ranges and the (unreserved) blocks in between. |
| // The reserved ranges are tested by checking the first and last address of each |
| // range. The unreserved blocks are tested similarly. These tests cover the |
| // entire IPv6 address range. |
| TEST(IPAddressTest, IsPubliclyRoutableIPv6) { |
| struct { |
| const char* const address; |
| IPAddressReservedResult is_reserved; |
| } tests[] = {// 0000::/8. |
| // Skip testing ::ffff:/96 explicitly since it was tested |
| // in IsPubliclyRoutableIPv4 |
| {"0:0:0:0:0:0:0:0", RESERVED}, |
| {"ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 0100::/8 |
| {"100:0:0:0:0:0:0:0", RESERVED}, |
| {"1ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 0200::/7 |
| {"200:0:0:0:0:0:0:0", RESERVED}, |
| {"3ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 0400::/6 |
| {"400:0:0:0:0:0:0:0", RESERVED}, |
| {"7ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 0800::/5 |
| {"800:0:0:0:0:0:0:0", RESERVED}, |
| {"fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 1000::/4 |
| {"1000:0:0:0:0:0:0:0", RESERVED}, |
| {"1fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 2000::/3 (Global Unicast) |
| {"2000:0:0:0:0:0:0:0", NOT_RESERVED}, |
| {"3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", NOT_RESERVED}, |
| // 4000::/3 |
| {"4000:0:0:0:0:0:0:0", RESERVED}, |
| {"5fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 6000::/3 |
| {"6000:0:0:0:0:0:0:0", RESERVED}, |
| {"7fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // 8000::/3 |
| {"8000:0:0:0:0:0:0:0", RESERVED}, |
| {"9fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // c000::/3 |
| {"c000:0:0:0:0:0:0:0", RESERVED}, |
| {"dfff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // e000::/4 |
| {"e000:0:0:0:0:0:0:0", RESERVED}, |
| {"efff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // f000::/5 |
| {"f000:0:0:0:0:0:0:0", RESERVED}, |
| {"f7ff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // f800::/6 |
| {"f800:0:0:0:0:0:0:0", RESERVED}, |
| {"fbff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // fc00::/7 |
| {"fc00:0:0:0:0:0:0:0", RESERVED}, |
| {"fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // fe00::/9 |
| {"fe00:0:0:0:0:0:0:0", RESERVED}, |
| {"fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // fe80::/10 |
| {"fe80:0:0:0:0:0:0:0", RESERVED}, |
| {"febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // fec0::/10 |
| {"fec0:0:0:0:0:0:0:0", RESERVED}, |
| {"feff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", RESERVED}, |
| // ff00::/8 (Multicast) |
| {"ff00:0:0:0:0:0:0:0", NOT_RESERVED}, |
| {"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", NOT_RESERVED}}; |
| |
| IPAddress address; |
| for (const auto& test : tests) { |
| EXPECT_TRUE(address.AssignFromIPLiteral(test.address)); |
| EXPECT_EQ(!test.is_reserved, address.IsPubliclyRoutable()); |
| } |
| } |
| |
| TEST(IPAddressTest, IsZero) { |
| uint8_t address1[4] = {}; |
| IPAddress zero_ipv4_address(address1); |
| EXPECT_TRUE(zero_ipv4_address.IsZero()); |
| |
| uint8_t address2[4] = {10}; |
| IPAddress non_zero_ipv4_address(address2); |
| EXPECT_FALSE(non_zero_ipv4_address.IsZero()); |
| |
| uint8_t address3[16] = {}; |
| IPAddress zero_ipv6_address(address3); |
| EXPECT_TRUE(zero_ipv6_address.IsZero()); |
| |
| uint8_t address4[16] = {10}; |
| IPAddress non_zero_ipv6_address(address4); |
| EXPECT_FALSE(non_zero_ipv6_address.IsZero()); |
| |
| IPAddress empty_address; |
| EXPECT_FALSE(empty_address.IsZero()); |
| } |
| |
| TEST(IPAddressTest, IsIPv4Mapped) { |
| IPAddress ipv4_address(192, 168, 0, 1); |
| EXPECT_FALSE(ipv4_address.IsIPv4MappedIPv6()); |
| IPAddress ipv6_address(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); |
| EXPECT_FALSE(ipv6_address.IsIPv4MappedIPv6()); |
| IPAddress mapped_address(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 1, 1, 0, 1); |
| EXPECT_TRUE(mapped_address.IsIPv4MappedIPv6()); |
| } |
| |
| TEST(IPAddressTest, AllZeros) { |
| EXPECT_TRUE(IPAddress::AllZeros(0).empty()); |
| |
| EXPECT_EQ(3u, IPAddress::AllZeros(3).size()); |
| EXPECT_TRUE(IPAddress::AllZeros(3).IsZero()); |
| |
| EXPECT_EQ("0.0.0.0", IPAddress::IPv4AllZeros().ToString()); |
| EXPECT_EQ("::", IPAddress::IPv6AllZeros().ToString()); |
| } |
| |
| TEST(IPAddressTest, ToString) { |
| EXPECT_EQ("0.0.0.0", IPAddress::IPv4AllZeros().ToString()); |
| |
| IPAddress address(192, 168, 0, 1); |
| EXPECT_EQ("192.168.0.1", address.ToString()); |
| |
| IPAddress address2(0xFE, 0xDC, 0xBA, 0x98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0); |
| EXPECT_EQ("fedc:ba98::", address2.ToString()); |
| |
| // ToString() shouldn't crash on invalid addresses. |
| uint8_t addr4[2]; |
| IPAddress address4(addr4); |
| EXPECT_EQ("", address4.ToString()); |
| |
| IPAddress address5; |
| EXPECT_EQ("", address5.ToString()); |
| } |
| |
| TEST(IPAddressTest, IPAddressToStringWithPort) { |
| EXPECT_EQ("0.0.0.0:3", |
| IPAddressToStringWithPort(IPAddress::IPv4AllZeros(), 3)); |
| |
| IPAddress address1(192, 168, 0, 1); |
| EXPECT_EQ("192.168.0.1:99", IPAddressToStringWithPort(address1, 99)); |
| |
| IPAddress address2(0xFE, 0xDC, 0xBA, 0x98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 0); |
| EXPECT_EQ("[fedc:ba98::]:8080", IPAddressToStringWithPort(address2, 8080)); |
| |
| // IPAddressToStringWithPort() shouldn't crash on invalid addresses. |
| uint8_t addr3[2]; |
| EXPECT_EQ("", IPAddressToStringWithPort(IPAddress(addr3), 8080)); |
| } |
| |
| TEST(IPAddressTest, IPAddressToPackedString) { |
| IPAddress ipv4_address; |
| EXPECT_TRUE(ipv4_address.AssignFromIPLiteral("4.31.198.44")); |
| std::string expected_ipv4_address("\x04\x1f\xc6\x2c", 4); |
| EXPECT_EQ(expected_ipv4_address, IPAddressToPackedString(ipv4_address)); |
| |
| IPAddress ipv6_address; |
| EXPECT_TRUE(ipv6_address.AssignFromIPLiteral("2001:0700:0300:1800::000f")); |
| std::string expected_ipv6_address( |
| "\x20\x01\x07\x00\x03\x00\x18\x00" |
| "\x00\x00\x00\x00\x00\x00\x00\x0f", |
| 16); |
| EXPECT_EQ(expected_ipv6_address, IPAddressToPackedString(ipv6_address)); |
| } |
| |
| // Test that invalid IP literals fail to parse. |
| TEST(IPAddressTest, AssignFromIPLiteral_FailParse) { |
| IPAddress address; |
| |
| EXPECT_FALSE(address.AssignFromIPLiteral("bad value")); |
| EXPECT_FALSE(address.AssignFromIPLiteral("bad:value")); |
| EXPECT_FALSE(address.AssignFromIPLiteral(std::string())); |
| EXPECT_FALSE(address.AssignFromIPLiteral("192.168.0.1:30")); |
| EXPECT_FALSE(address.AssignFromIPLiteral(" 192.168.0.1 ")); |
| EXPECT_FALSE(address.AssignFromIPLiteral("[::1]")); |
| } |
| |
| // Test that a failure calling AssignFromIPLiteral() has the sideffect of |
| // clearing the current value. |
| TEST(IPAddressTest, AssignFromIPLiteral_ResetOnFailure) { |
| IPAddress address = IPAddress::IPv6Localhost(); |
| |
| EXPECT_TRUE(address.IsValid()); |
| EXPECT_FALSE(address.empty()); |
| |
| EXPECT_FALSE(address.AssignFromIPLiteral("bad value")); |
| |
| EXPECT_FALSE(address.IsValid()); |
| EXPECT_TRUE(address.empty()); |
| } |
| |
| // Test parsing an IPv4 literal. |
| TEST(IPAddressTest, AssignFromIPLiteral_IPv4) { |
| IPAddress address; |
| EXPECT_TRUE(address.AssignFromIPLiteral("192.168.0.1")); |
| EXPECT_EQ("192,168,0,1", DumpIPAddress(address)); |
| EXPECT_EQ("192.168.0.1", address.ToString()); |
| } |
| |
| // Test parsing an IPv6 literal. |
| TEST(IPAddressTest, AssignFromIPLiteral_IPv6) { |
| IPAddress address; |
| EXPECT_TRUE(address.AssignFromIPLiteral("1:abcd::3:4:ff")); |
| EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPAddress(address)); |
| EXPECT_EQ("1:abcd::3:4:ff", address.ToString()); |
| } |
| |
| TEST(IPAddressTest, IsIPv4MappedIPv6) { |
| IPAddress ipv4_address(192, 168, 0, 1); |
| EXPECT_FALSE(ipv4_address.IsIPv4MappedIPv6()); |
| IPAddress ipv6_address = IPAddress::IPv6Localhost(); |
| EXPECT_FALSE(ipv6_address.IsIPv4MappedIPv6()); |
| IPAddress mapped_address(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 1, 1, 0, 1); |
| EXPECT_TRUE(mapped_address.IsIPv4MappedIPv6()); |
| } |
| |
| TEST(IPAddressTest, IsEqual) { |
| IPAddress ip_address1; |
| EXPECT_TRUE(ip_address1.AssignFromIPLiteral("127.0.0.1")); |
| IPAddress ip_address2; |
| EXPECT_TRUE(ip_address2.AssignFromIPLiteral("2001:db8:0::42")); |
| IPAddress ip_address3; |
| EXPECT_TRUE(ip_address3.AssignFromIPLiteral("127.0.0.1")); |
| |
| EXPECT_FALSE(ip_address1 == ip_address2); |
| EXPECT_TRUE(ip_address1 == ip_address3); |
| } |
| |
| TEST(IPAddressTest, LessThan) { |
| // IPv4 vs IPv6 |
| IPAddress ip_address1; |
| EXPECT_TRUE(ip_address1.AssignFromIPLiteral("127.0.0.1")); |
| IPAddress ip_address2; |
| EXPECT_TRUE(ip_address2.AssignFromIPLiteral("2001:db8:0::42")); |
| EXPECT_TRUE(ip_address1 < ip_address2); |
| EXPECT_FALSE(ip_address2 < ip_address1); |
| |
| // Compare equivalent addresses. |
| IPAddress ip_address3; |
| EXPECT_TRUE(ip_address3.AssignFromIPLiteral("127.0.0.1")); |
| EXPECT_FALSE(ip_address1 < ip_address3); |
| EXPECT_FALSE(ip_address3 < ip_address1); |
| |
| IPAddress ip_address4; |
| EXPECT_TRUE(ip_address4.AssignFromIPLiteral("128.0.0.0")); |
| EXPECT_TRUE(ip_address1 < ip_address4); |
| EXPECT_FALSE(ip_address4 < ip_address1); |
| } |
| |
| // Test mapping an IPv4 address to an IPv6 address. |
| TEST(IPAddressTest, ConvertIPv4ToIPv4MappedIPv6) { |
| IPAddress ipv4_address(192, 168, 0, 1); |
| IPAddress ipv6_address = ConvertIPv4ToIPv4MappedIPv6(ipv4_address); |
| |
| // ::ffff:192.168.0.1 |
| EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1", |
| DumpIPAddress(ipv6_address)); |
| EXPECT_EQ("::ffff:c0a8:1", ipv6_address.ToString()); |
| } |
| |
| // Test reversal of a IPv6 address mapping. |
| TEST(IPAddressTest, ConvertIPv4MappedIPv6ToIPv4) { |
| IPAddress ipv4mapped_address; |
| EXPECT_TRUE(ipv4mapped_address.AssignFromIPLiteral("::ffff:c0a8:1")); |
| |
| IPAddress expected(192, 168, 0, 1); |
| |
| IPAddress result = ConvertIPv4MappedIPv6ToIPv4(ipv4mapped_address); |
| EXPECT_EQ(expected, result); |
| } |
| |
| TEST(IPAddressTest, IPAddressMatchesPrefix) { |
| struct { |
| const char* const cidr_literal; |
| size_t prefix_length_in_bits; |
| const char* const ip_literal; |
| bool expected_to_match; |
| } tests[] = { |
| // IPv4 prefix with IPv4 inputs. |
| {"10.10.1.32", 27, "10.10.1.44", true}, |
| {"10.10.1.32", 27, "10.10.1.90", false}, |
| {"10.10.1.32", 27, "10.10.1.90", false}, |
| |
| // IPv6 prefix with IPv6 inputs. |
| {"2001:db8::", 32, "2001:DB8:3:4::5", true}, |
| {"2001:db8::", 32, "2001:c8::", false}, |
| |
| // IPv6 prefix with IPv4 inputs. |
| {"2001:db8::", 33, "192.168.0.1", false}, |
| {"::ffff:192.168.0.1", 112, "192.168.33.77", true}, |
| |
| // IPv4 prefix with IPv6 inputs. |
| {"10.11.33.44", 16, "::ffff:0a0b:89", true}, |
| {"10.11.33.44", 16, "::ffff:10.12.33.44", false}, |
| }; |
| for (const auto& test : tests) { |
| SCOPED_TRACE( |
| base::StringPrintf("%s, %s", test.cidr_literal, test.ip_literal)); |
| |
| IPAddress ip_address; |
| EXPECT_TRUE(ip_address.AssignFromIPLiteral(test.ip_literal)); |
| |
| IPAddress ip_prefix; |
| EXPECT_TRUE(ip_prefix.AssignFromIPLiteral(test.cidr_literal)); |
| |
| EXPECT_EQ(test.expected_to_match, |
| IPAddressMatchesPrefix(ip_address, ip_prefix, |
| test.prefix_length_in_bits)); |
| } |
| } |
| |
| // Test parsing invalid CIDR notation literals. |
| TEST(IPAddressTest, ParseCIDRBlock_Invalid) { |
| const char* const bad_literals[] = {"foobar", |
| "", |
| "192.168.0.1", |
| "::1", |
| "/", |
| "/1", |
| "1", |
| "192.168.1.1/-1", |
| "192.168.1.1/33", |
| "::1/-3", |
| "a::3/129", |
| "::1/x", |
| "192.168.0.1//11", |
| "192.168.1.1/+1", |
| "192.168.1.1/ +1", |
| "192.168.1.1/"}; |
| |
| for (auto* bad_literal : bad_literals) { |
| IPAddress ip_address; |
| size_t prefix_length_in_bits; |
| |
| EXPECT_FALSE( |
| ParseCIDRBlock(bad_literal, &ip_address, &prefix_length_in_bits)); |
| } |
| } |
| |
| // Test parsing a valid CIDR notation literal. |
| TEST(IPAddressTest, ParseCIDRBlock_Valid) { |
| IPAddress ip_address; |
| size_t prefix_length_in_bits; |
| |
| EXPECT_TRUE( |
| ParseCIDRBlock("192.168.0.1/11", &ip_address, &prefix_length_in_bits)); |
| |
| EXPECT_EQ("192,168,0,1", DumpIPAddress(ip_address)); |
| EXPECT_EQ(11u, prefix_length_in_bits); |
| |
| EXPECT_TRUE(ParseCIDRBlock("::ffff:192.168.0.1/112", &ip_address, |
| &prefix_length_in_bits)); |
| |
| EXPECT_EQ("0,0,0,0,0,0,0,0,0,0,255,255,192,168,0,1", |
| DumpIPAddress(ip_address)); |
| EXPECT_EQ(112u, prefix_length_in_bits); |
| } |
| |
| TEST(IPAddressTest, ParseURLHostnameToAddress_FailParse) { |
| IPAddress address; |
| EXPECT_FALSE(ParseURLHostnameToAddress("bad value", &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress("bad:value", &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress(std::string(), &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress("192.168.0.1:30", &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress(" 192.168.0.1 ", &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress("::1", &address)); |
| EXPECT_FALSE(ParseURLHostnameToAddress("[192.169.0.1]", &address)); |
| } |
| |
| TEST(IPAddressTest, ParseURLHostnameToAddress_IPv4) { |
| IPAddress address; |
| EXPECT_TRUE(ParseURLHostnameToAddress("192.168.0.1", &address)); |
| EXPECT_EQ("192,168,0,1", DumpIPAddress(address)); |
| EXPECT_EQ("192.168.0.1", address.ToString()); |
| } |
| |
| TEST(IPAddressTest, ParseURLHostnameToAddress_IPv6) { |
| IPAddress address; |
| EXPECT_TRUE(ParseURLHostnameToAddress("[1:abcd::3:4:ff]", &address)); |
| EXPECT_EQ("0,1,171,205,0,0,0,0,0,0,0,3,0,4,0,255", DumpIPAddress(address)); |
| EXPECT_EQ("1:abcd::3:4:ff", address.ToString()); |
| } |
| |
| TEST(IPAddressTest, IPAddressStartsWith) { |
| IPAddress ipv4_address(192, 168, 10, 5); |
| |
| uint8_t ipv4_prefix1[] = {192, 168, 10}; |
| EXPECT_TRUE(IPAddressStartsWith(ipv4_address, ipv4_prefix1)); |
| |
| uint8_t ipv4_prefix3[] = {192, 168, 10, 5}; |
| EXPECT_TRUE(IPAddressStartsWith(ipv4_address, ipv4_prefix3)); |
| |
| uint8_t ipv4_prefix2[] = {192, 168, 10, 10}; |
| EXPECT_FALSE(IPAddressStartsWith(ipv4_address, ipv4_prefix2)); |
| |
| // Prefix is longer than the address. |
| uint8_t ipv4_prefix4[] = {192, 168, 10, 10, 0}; |
| EXPECT_FALSE(IPAddressStartsWith(ipv4_address, ipv4_prefix4)); |
| |
| IPAddress ipv6_address; |
| EXPECT_TRUE(ipv6_address.AssignFromIPLiteral("2a00:1450:400c:c09::64")); |
| |
| uint8_t ipv6_prefix1[] = {42, 0, 20, 80, 64, 12, 12, 9}; |
| EXPECT_TRUE(IPAddressStartsWith(ipv6_address, ipv6_prefix1)); |
| |
| uint8_t ipv6_prefix2[] = {41, 0, 20, 80, 64, 12, 12, 9, |
| 0, 0, 0, 0, 0, 0, 100}; |
| EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix2)); |
| |
| uint8_t ipv6_prefix3[] = {42, 0, 20, 80, 64, 12, 12, 9, |
| 0, 0, 0, 0, 0, 0, 0, 100}; |
| EXPECT_TRUE(IPAddressStartsWith(ipv6_address, ipv6_prefix3)); |
| |
| uint8_t ipv6_prefix4[] = {42, 0, 20, 80, 64, 12, 12, 9, |
| 0, 0, 0, 0, 0, 0, 0, 0}; |
| EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix4)); |
| |
| // Prefix is longer than the address. |
| uint8_t ipv6_prefix5[] = {42, 0, 20, 80, 64, 12, 12, 9, 0, |
| 0, 0, 0, 0, 0, 0, 0, 10}; |
| EXPECT_FALSE(IPAddressStartsWith(ipv6_address, ipv6_prefix5)); |
| } |
| |
| } // anonymous namespace |
| |
| } // namespace net |