Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(769)

Unified Diff: net/base/net_util.cc

Issue 22538003: Add IP address handling to net::IsHostnameNonUnique (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Take 3 Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/net_util.cc
diff --git a/net/base/net_util.cc b/net/base/net_util.cc
index 958e3c3bca82049671f39fda3574b7eca3871664..e390ed5a52d2f9ece4db07f92f53286ff5a6db9a 100644
--- a/net/base/net_util.cc
+++ b/net/base/net_util.cc
@@ -1391,7 +1391,6 @@ std::string GetHostAndOptionalPort(const GURL& url) {
return url.host();
}
-// static
bool IsHostnameNonUnique(const std::string& hostname) {
// CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
const std::string host_or_ip = hostname.find(':') != std::string::npos ?
@@ -1404,11 +1403,24 @@ bool IsHostnameNonUnique(const std::string& hostname) {
if (canonical_name.empty())
return false;
- // If |hostname| is an IP address, presume it's unique.
- // TODO(rsleevi): In the future, this should also reject IP addresses in
- // IANA-reserved ranges.
- if (host_info.IsIPAddress())
- return false;
+ // If |hostname| is an IP address, check to see if it's in an IANA-reserved
+ // range.
+ if (host_info.IsIPAddress()) {
+ IPAddressNumber host_addr;
+ if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
+ host_info.out_host.len),
+ &host_addr)) {
+ return false;
+ }
+ switch (host_info.family) {
+ case url_canon::CanonHostInfo::IPV4:
+ case url_canon::CanonHostInfo::IPV6:
+ return IsIPAddressReserved(host_addr);
+ case url_canon::CanonHostInfo::NEUTRAL:
+ case url_canon::CanonHostInfo::BROKEN:
+ return false;
+ }
+ }
// Check for a registry controlled portion of |hostname|, ignoring private
// registries, as they already chain to ICANN-administered registries,
@@ -1425,6 +1437,80 @@ bool IsHostnameNonUnique(const std::string& hostname) {
registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
}
+bool IPNumberPrefixCheck(const IPAddressNumber& ip_number,
+ const unsigned char* ip_prefix,
+ size_t prefix_length_in_bits) {
+ // Compare all the bytes that fall entirely within the prefix.
+ int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
+ for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
+ if (ip_number[i] != ip_prefix[i])
+ return false;
+ }
+
+ // In case the prefix was not a multiple of 8, there will be 1 byte
+ // which is only partially masked.
+ int remaining_bits = prefix_length_in_bits % 8;
+ if (remaining_bits != 0) {
+ unsigned char mask = 0xFF << (8 - remaining_bits);
+ int i = num_entire_bytes_in_prefix;
+ if ((ip_number[i] & mask) != (ip_prefix[i] & mask))
Ryan Sleevi 2013/08/12 21:11:51 style nit: indentation is off by one here
felt 2013/08/13 04:17:06 Done.
+ return false;
+ }
+ return true;
+}
+
+// We shouldn't compare IPv4 to IPv6 (they have different range reservations),
+// so we keep separate arrays. Within each array, adjacent reserved ranges are
+// consolidated when possible.
Ryan Sleevi 2013/08/12 21:11:51 Can you rewrite this comment without the "We". Enj
felt 2013/08/13 04:17:06 Oh, huh, I hadn't heard that before. Done.
+// Sources for info:
+// www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
+// www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+// They're formatted here with the prefix as the last element. For example:
+// 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
+bool IsIPAddressReserved(const IPAddressNumber& host_addr) {
+ static const unsigned char kReservedIPv4[][5] = {
+ { 0,0,0,0,8 }, { 10,0,0,0,8 }, { 100,64,0,0,10 }, { 127,0,0,0,8 },
+ { 169,254,0,0,16 }, { 172,16,0,0,12 }, { 192,0,2,0,24 }, { 192,88,99,0,24 },
+ { 192,168,0,0,16 }, { 198,18,0,0,15 }, { 198,51,100,0,24 },
+ { 203,0,113,0,24 }, { 224,0,0,0,3 }
Ryan Sleevi 2013/08/12 21:11:51 style nit: four spaces
felt 2013/08/13 04:17:06 Done.
+ };
+ static const unsigned char kReservedIPv6[][17] = {
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8 },
+ { 0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
+ { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
+ { 0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 },
+ { 0xe0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 },
+ { 0xf0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 },
+ { 0xf8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 },
+ { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7 },
+ { 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 },
+ { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
+ { 0xfe,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
Ryan Sleevi 2013/08/12 21:11:51 style nit: four spaces
felt 2013/08/13 04:17:06 Done.
+ };
+ size_t array_size = 0;
+ const unsigned char* array = NULL;
+ switch (host_addr.size()) {
+ case kIPv4AddressSize:
+ array_size = arraysize(kReservedIPv4);
+ array = kReservedIPv4[0];
+ break;
+ case kIPv6AddressSize:
+ array_size = arraysize(kReservedIPv6);
+ array = kReservedIPv6[0];
+ break;
+ }
+ if (!array)
+ return false;
+ int width = host_addr.size()+1;
Ryan Sleevi 2013/08/12 21:11:51 style nit: "host_addr.size()+1" -> "host_addr.size
felt 2013/08/13 04:17:06 Done.
+ for (size_t i = 0; i < array_size*width; i = i + width) {
Ryan Sleevi 2013/08/12 21:11:51 style nit: "array_size*width" -> "array_size * wid
felt 2013/08/13 04:17:06 is it generally preferred to avoid indexing, or is
Ryan Sleevi 2013/08/13 20:45:39 Shorter and more readable. Forms like (&foo[bar])[
+ if (IPNumberPrefixCheck(
+ host_addr, &array[i], (&array[i])[width-1])) {
+ return true;
+ }
+ }
+ return false;
+}
+
// Extracts the address and port portions of a sockaddr.
bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
socklen_t sock_addr_len,
@@ -1996,25 +2082,7 @@ bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number,
96 + prefix_length_in_bits);
}
- // Otherwise we are comparing two IPv4 addresses, or two IPv6 addresses.
- // Compare all the bytes that fall entirely within the prefix.
- int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
- for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
- if (ip_number[i] != ip_prefix[i])
- return false;
- }
-
- // In case the prefix was not a multiple of 8, there will be 1 byte
- // which is only partially masked.
- int remaining_bits = prefix_length_in_bits % 8;
- if (remaining_bits != 0) {
- unsigned char mask = 0xFF << (8 - remaining_bits);
- int i = num_entire_bytes_in_prefix;
- if ((ip_number[i] & mask) != (ip_prefix[i] & mask))
- return false;
- }
-
- return true;
+ return IPNumberPrefixCheck(ip_number, &ip_prefix[0], prefix_length_in_bits);
}
const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address,
« net/base/net_util.h ('K') | « net/base/net_util.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698