// 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 #include "base/format_macros.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::NumberToString(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, std::size(data)); ASSERT_EQ(std::size(data), bytes.size()); size_t i = 0; for (uint8_t byte : bytes) EXPECT_EQ(data[i++], byte); ASSERT_EQ(std::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, std::size(data)); ASSERT_EQ(std::size(data), bytes.size()); size_t i = 0; for (uint8_t byte : bytes) EXPECT_EQ(data[i++], byte); ASSERT_EQ(std::size(data), i); } TEST(IPAddressBytesTest, Assign) { uint8_t data[] = {192, 168, 1, 1}; IPAddressBytes copy; copy.Assign(data, std::size(data)); EXPECT_EQ(IPAddressBytes(data, std::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", RESERVED}, {"192.0.0.255", 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}}; for (const auto& test : tests) { IPAddress address; 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)); } TEST(IPAddressTest, IsLinkLocal) { const char* kPositive[] = { "169.254.0.0", "169.254.100.1", "169.254.100.1", "::ffff:169.254.0.0", "::ffff:169.254.100.1", "fe80::1", "fe81::1", }; for (const char* literal : kPositive) { IPAddress ip_address; ASSERT_TRUE(ip_address.AssignFromIPLiteral(literal)); EXPECT_TRUE(ip_address.IsLinkLocal()) << literal; } const char* kNegative[] = { "170.254.0.0", "169.255.0.0", "::169.254.0.0", "::fffe:169.254.0.0", "::ffff:169.255.0.0", "fec0::1", }; for (const char* literal : kNegative) { IPAddress ip_address; ASSERT_TRUE(ip_address.AssignFromIPLiteral(literal)); EXPECT_FALSE(ip_address.IsLinkLocal()) << literal; } } } // anonymous namespace } // namespace net