diff options
author | martijn <martijn@martijnc.be> | 2016-03-20 13:22:09 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-20 20:24:35 +0000 |
commit | 579658b7b5e5ef315ad4513574c669fc5363ea9d (patch) | |
tree | 74d50e5030d928328b1c3e90dec66a9147181ec8 | |
parent | 43f18e9e7c90f40d6306f720791f60c1a09165dc (diff) | |
download | chromium_src-579658b7b5e5ef315ad4513574c669fc5363ea9d.zip chromium_src-579658b7b5e5ef315ad4513574c669fc5363ea9d.tar.gz chromium_src-579658b7b5e5ef315ad4513574c669fc5363ea9d.tar.bz2 |
Migrate net/proxy/* to net::IPAddress.
This CL also moves the ParseCIDRBlock() implementation to ip_address.h.
BUG=496258
Review URL: https://codereview.chromium.org/1810183002
Cr-Commit-Position: refs/heads/master@{#382225}
-rw-r--r-- | net/base/ip_address.cc | 33 | ||||
-rw-r--r-- | net/base/ip_address.h | 14 | ||||
-rw-r--r-- | net/base/ip_address_number.cc | 30 | ||||
-rw-r--r-- | net/base/ip_address_number.h | 14 | ||||
-rw-r--r-- | net/base/ip_address_number_unittest.cc | 120 | ||||
-rw-r--r-- | net/base/ip_address_unittest.cc | 44 | ||||
-rw-r--r-- | net/proxy/proxy_bypass_rules.cc | 19 | ||||
-rw-r--r-- | net/proxy/proxy_resolver_v8.cc | 55 |
8 files changed, 149 insertions, 180 deletions
diff --git a/net/base/ip_address.cc b/net/base/ip_address.cc index 606483b..42071e0 100644 --- a/net/base/ip_address.cc +++ b/net/base/ip_address.cc @@ -4,6 +4,9 @@ #include "net/base/ip_address.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_split.h" #include "net/base/ip_address_number.h" #include "url/gurl.h" #include "url/url_canon_ip.h" @@ -139,6 +142,36 @@ bool IPAddressMatchesPrefix(const IPAddress& ip_address, prefix_length_in_bits); } +bool ParseCIDRBlock(const std::string& cidr_literal, + IPAddress* ip_address, + size_t* prefix_length_in_bits) { + // We expect CIDR notation to match one of these two templates: + // <IPv4-literal> "/" <number of bits> + // <IPv6-literal> "/" <number of bits> + + std::vector<base::StringPiece> parts = base::SplitStringPiece( + cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + if (parts.size() != 2) + return false; + + // Parse the IP address. + if (!ip_address->AssignFromIPLiteral(parts[0])) + return false; + + // Parse the prefix length. + int number_of_bits = -1; + if (!base::StringToInt(parts[1], &number_of_bits)) + return false; + + // Make sure the prefix length is in a valid range. + if (number_of_bits < 0 || + number_of_bits > static_cast<int>(ip_address->size() * 8)) + return false; + + *prefix_length_in_bits = static_cast<size_t>(number_of_bits); + return true; +} + unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) { return CommonPrefixLength(a1.bytes(), a2.bytes()); } diff --git a/net/base/ip_address.h b/net/base/ip_address.h index f1f244e..91ce071 100644 --- a/net/base/ip_address.h +++ b/net/base/ip_address.h @@ -149,6 +149,20 @@ NET_EXPORT bool IPAddressMatchesPrefix(const IPAddress& ip_address, const IPAddress& ip_prefix, size_t prefix_length_in_bits); +// Parses an IP block specifier from CIDR notation to an +// (IP address, prefix length) pair. Returns true on success and fills +// |*ip_address| with the numeric value of the IP address and sets +// |*prefix_length_in_bits| with the length of the prefix. +// +// CIDR notation literals can use either IPv4 or IPv6 literals. Some examples: +// +// 10.10.3.1/20 +// a:b:c::/46 +// ::1/128 +NET_EXPORT bool ParseCIDRBlock(const std::string& cidr_literal, + IPAddress* ip_address, + size_t* prefix_length_in_bits); + // Returns number of matching initial bits between the addresses |a1| and |a2|. unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2); diff --git a/net/base/ip_address_number.cc b/net/base/ip_address_number.cc index 80cd7e9..1c3090d 100644 --- a/net/base/ip_address_number.cc +++ b/net/base/ip_address_number.cc @@ -218,36 +218,6 @@ IPAddressNumber ConvertIPv4MappedToIPv4(const IPAddressNumber& address) { address.end()); } -bool ParseCIDRBlock(const std::string& cidr_literal, - IPAddressNumber* ip_number, - size_t* prefix_length_in_bits) { - // We expect CIDR notation to match one of these two templates: - // <IPv4-literal> "/" <number of bits> - // <IPv6-literal> "/" <number of bits> - - std::vector<base::StringPiece> parts = base::SplitStringPiece( - cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - if (parts.size() != 2) - return false; - - // Parse the IP address. - if (!ParseIPLiteralToNumber(parts[0], ip_number)) - return false; - - // Parse the prefix length. - int number_of_bits = -1; - if (!base::StringToInt(parts[1], &number_of_bits)) - return false; - - // Make sure the prefix length is in a valid range. - if (number_of_bits < 0 || - number_of_bits > static_cast<int>(ip_number->size() * 8)) - return false; - - *prefix_length_in_bits = static_cast<size_t>(number_of_bits); - return true; -} - bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number, const IPAddressNumber& ip_prefix, size_t prefix_length_in_bits) { diff --git a/net/base/ip_address_number.h b/net/base/ip_address_number.h index 80c524c..1f7a1e7 100644 --- a/net/base/ip_address_number.h +++ b/net/base/ip_address_number.h @@ -81,20 +81,6 @@ NET_EXPORT_PRIVATE bool IsIPv4Mapped(const IPAddressNumber& address); NET_EXPORT_PRIVATE IPAddressNumber ConvertIPv4MappedToIPv4( const IPAddressNumber& address); -// Parses an IP block specifier from CIDR notation to an -// (IP address, prefix length) pair. Returns true on success and fills -// |*ip_number| with the numeric value of the IP address and sets -// |*prefix_length_in_bits| with the length of the prefix. -// -// CIDR notation literals can use either IPv4 or IPv6 literals. Some examples: -// -// 10.10.3.1/20 -// a:b:c::/46 -// ::1/128 -NET_EXPORT bool ParseCIDRBlock(const std::string& cidr_literal, - IPAddressNumber* ip_number, - size_t* prefix_length_in_bits); - // Compares an IP address to see if it falls within the specified IP block. // Returns true if it does, false otherwise. // diff --git a/net/base/ip_address_number_unittest.cc b/net/base/ip_address_number_unittest.cc index 67d9f31..a0365f4 100644 --- a/net/base/ip_address_number_unittest.cc +++ b/net/base/ip_address_number_unittest.cc @@ -146,105 +146,29 @@ TEST(IpAddressNumberTest, ConvertIPv4MappedToIPv4) { EXPECT_EQ(expected, result); } -// Test parsing invalid CIDR notation literals. -TEST(IpAddressNumberTest, 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" - }; - - for (size_t i = 0; i < arraysize(bad_literals); ++i) { - IPAddressNumber ip_number; - size_t prefix_length_in_bits; - - EXPECT_FALSE(ParseCIDRBlock(bad_literals[i], - &ip_number, - &prefix_length_in_bits)); - } -} - -// Test parsing a valid CIDR notation literal. -TEST(IpAddressNumberTest, ParseCIDRBlock_Valid) { - IPAddressNumber ip_number; - size_t prefix_length_in_bits; - - EXPECT_TRUE(ParseCIDRBlock("192.168.0.1/11", - &ip_number, - &prefix_length_in_bits)); - - EXPECT_EQ("192,168,0,1", DumpIPNumber(ip_number)); - EXPECT_EQ(11u, prefix_length_in_bits); -} - TEST(IpAddressNumberTest, IPNumberMatchesPrefix) { 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 - }, + // 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 (size_t i = 0; i < arraysize(tests); ++i) { SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: %s, %s", i, @@ -255,16 +179,12 @@ TEST(IpAddressNumberTest, IPNumberMatchesPrefix) { EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].ip_literal, &ip_number)); IPAddressNumber ip_prefix; - size_t prefix_length_in_bits; - EXPECT_TRUE(ParseCIDRBlock(tests[i].cidr_literal, - &ip_prefix, - &prefix_length_in_bits)); + EXPECT_TRUE(ParseIPLiteralToNumber(tests[i].cidr_literal, &ip_prefix)); EXPECT_EQ(tests[i].expected_to_match, - IPNumberMatchesPrefix(ip_number, - ip_prefix, - prefix_length_in_bits)); + IPNumberMatchesPrefix(ip_number, ip_prefix, + tests[i].prefix_length_in_bits)); } } diff --git a/net/base/ip_address_unittest.cc b/net/base/ip_address_unittest.cc index 2863c6b..d78f6c3 100644 --- a/net/base/ip_address_unittest.cc +++ b/net/base/ip_address_unittest.cc @@ -238,6 +238,50 @@ TEST(IPAddressTest, ConvertIPv4MappedIPv6ToIPv4) { EXPECT_EQ(expected, result); } +// 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"}; + + for (const 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, IPAddressStartsWith) { IPAddress ipv4_address(192, 168, 10, 5); diff --git a/net/proxy/proxy_bypass_rules.cc b/net/proxy/proxy_bypass_rules.cc index e74d9e6..64a23c9 100644 --- a/net/proxy/proxy_bypass_rules.cc +++ b/net/proxy/proxy_bypass_rules.cc @@ -12,7 +12,7 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "net/base/host_port_pair.h" -#include "net/base/ip_address_number.h" +#include "net/base/ip_address.h" #include "net/base/url_util.h" namespace net { @@ -84,13 +84,12 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule { // |ip_prefix| + |prefix_length| define the IP block to match. BypassIPBlockRule(const std::string& description, const std::string& optional_scheme, - const IPAddressNumber& ip_prefix, + const IPAddress& ip_prefix, size_t prefix_length_in_bits) : description_(description), optional_scheme_(optional_scheme), ip_prefix_(ip_prefix), - prefix_length_in_bits_(prefix_length_in_bits) { - } + prefix_length_in_bits_(prefix_length_in_bits) {} bool Matches(const GURL& url) const override { if (!url.HostIsIPAddress()) @@ -100,13 +99,13 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule { return false; // Didn't match scheme expectation. // Parse the input IP literal to a number. - IPAddressNumber ip_number; - if (!ParseIPLiteralToNumber(url.HostNoBrackets(), &ip_number)) + IPAddress ip_address; + if (!ip_address.AssignFromIPLiteral(url.HostNoBrackets())) return false; // Test if it has the expected prefix. - return IPNumberMatchesPrefix(ip_number, ip_prefix_, - prefix_length_in_bits_); + return IPAddressMatchesPrefix(ip_address, ip_prefix_, + prefix_length_in_bits_); } std::string ToString() const override { return description_; } @@ -121,7 +120,7 @@ class BypassIPBlockRule : public ProxyBypassRules::Rule { private: const std::string description_; const std::string optional_scheme_; - const IPAddressNumber ip_prefix_; + const IPAddress ip_prefix_; const size_t prefix_length_in_bits_; }; @@ -284,7 +283,7 @@ bool ProxyBypassRules::AddRuleFromStringInternal( // If there is a forward slash in the input, it is probably a CIDR style // mask. if (raw.find('/') != std::string::npos) { - IPAddressNumber ip_prefix; + IPAddress ip_prefix; size_t prefix_length_in_bits; if (!ParseCIDRBlock(raw, &ip_prefix, &prefix_length_in_bits)) diff --git a/net/proxy/proxy_resolver_v8.cc b/net/proxy/proxy_resolver_v8.cc index 80ae06b..a0c9717 100644 --- a/net/proxy/proxy_resolver_v8.cc +++ b/net/proxy/proxy_resolver_v8.cc @@ -21,7 +21,7 @@ #include "gin/array_buffer.h" #include "gin/public/isolate_holder.h" #include "gin/v8_initializer.h" -#include "net/base/ip_address_number.h" +#include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_resolver_script.h" @@ -244,26 +244,29 @@ bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args, return success; } -// Wrapper for passing around IP address strings and IPAddressNumber objects. -struct IPAddress { - IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) - : string_value(ip_string), - ip_address_number(ip_number) { - } +// Wrapper around an IP address that stores the original string as well as a +// corresponding parsed IPAddress. + +// This struct is used as a helper for sorting IP address strings - the IP +// literal is parsed just once and used as the sorting key, while also +// preserving the original IP literal string. +struct IPAddressSortingEntry { + IPAddressSortingEntry(const std::string& ip_string, + const IPAddress& ip_address) + : string_value(ip_string), ip_address(ip_address) {} // Used for sorting IP addresses in ascending order in SortIpAddressList(). - // IP6 addresses are placed ahead of IPv4 addresses. - bool operator<(const IPAddress& rhs) const { - const IPAddressNumber& ip1 = this->ip_address_number; - const IPAddressNumber& ip2 = rhs.ip_address_number; + // IPv6 addresses are placed ahead of IPv4 addresses. + bool operator<(const IPAddressSortingEntry& rhs) const { + const IPAddress& ip1 = this->ip_address; + const IPAddress& ip2 = rhs.ip_address; if (ip1.size() != ip2.size()) return ip1.size() > ip2.size(); // IPv6 before IPv4. - DCHECK(ip1.size() == ip2.size()); - return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0; // Ascending order. + return ip1 < ip2; // Ascending order. } std::string string_value; - IPAddressNumber ip_address_number; + IPAddress ip_address; }; // Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a @@ -284,13 +287,13 @@ bool SortIpAddressList(const std::string& ip_address_list, return false; // Split-up IP addresses and store them in a vector. - std::vector<IPAddress> ip_vector; - IPAddressNumber ip_num; + std::vector<IPAddressSortingEntry> ip_vector; + IPAddress ip_address; base::StringTokenizer str_tok(cleaned_ip_address_list, ";"); while (str_tok.GetNext()) { - if (!ParseIPLiteralToNumber(str_tok.token(), &ip_num)) + if (!ip_address.AssignFromIPLiteral(str_tok.token())) return false; - ip_vector.push_back(IPAddress(str_tok.token(), ip_num)); + ip_vector.push_back(IPAddressSortingEntry(str_tok.token(), ip_address)); } if (ip_vector.empty()) // Can happen if we have something like @@ -320,11 +323,11 @@ bool SortIpAddressList(const std::string& ip_address_list, // format, or if an address and prefix of different types are used (e.g. IPv6 // address and IPv4 prefix). bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { - IPAddressNumber address; - if (!ParseIPLiteralToNumber(ip_address, &address)) + IPAddress address; + if (!address.AssignFromIPLiteral(ip_address)) return false; - IPAddressNumber prefix; + IPAddress prefix; size_t prefix_length_in_bits; if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits)) return false; @@ -333,10 +336,10 @@ bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { if (address.size() != prefix.size()) return false; - DCHECK((address.size() == 4 && prefix.size() == 4) || - (address.size() == 16 && prefix.size() == 16)); + DCHECK((address.IsIPv4() && prefix.IsIPv4()) || + (address.IsIPv6() && prefix.IsIPv6())); - return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); + return IPAddressMatchesPrefix(address, prefix, prefix_length_in_bits); } // Consider only single component domains like 'foo' as plain host names. @@ -346,8 +349,8 @@ bool IsPlainHostName(const std::string& hostname_utf8) { // IPv6 literals might not contain any periods, however are not considered // plain host names. - IPAddressNumber unused; - return !ParseIPLiteralToNumber(hostname_utf8, &unused); + IPAddress unused; + return !unused.AssignFromIPLiteral(hostname_utf8); } // All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is |