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

Unified Diff: net/base/ip_address.cc

Issue 1886043002: Update IPAddress::IsReserved() ranges. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments eroman Created 4 years, 8 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
« no previous file with comments | « no previous file | net/base/ip_address_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/ip_address.cc
diff --git a/net/base/ip_address.cc b/net/base/ip_address.cc
index a0cf6735db0797c9c2a7da9ff421f99975772d47..7652b3c646a2c6a514ccab9e10e77899beb5a7ec 100644
--- a/net/base/ip_address.cc
+++ b/net/base/ip_address.cc
@@ -17,28 +17,89 @@ namespace {
// https://tools.ietf.org/html/rfc4291#section-2.5.5.2
const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
+// Note that this function assumes:
+// * |ip_address| is at least |prefix_length_in_bits| (bits) long;
+// * |ip_prefix| is at least |prefix_length_in_bits| (bits) long.
bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address,
- const unsigned char* ip_prefix,
+ const uint8_t* 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) {
+ size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
+ for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
if (ip_address[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;
+ size_t 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;
+ uint8_t mask = 0xFF << (8 - remaining_bits);
+ size_t i = num_entire_bytes_in_prefix;
if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
return false;
}
return true;
}
+// Returns true if |ip_address| matches any of the reserved IPv4 ranges. This
+// method operates on a blacklist of reserved IPv4 ranges. Some ranges are
+// consolidated.
+// Sources for info:
+// www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
+// www.iana.org/assignments/iana-ipv4-special-registry/
+// iana-ipv4-special-registry.xhtml
+bool IsReservedIPv4(const std::vector<uint8_t>& ip_address) {
+ // Different IP versions have different range reservations.
+ DCHECK_EQ(net::IPAddress::kIPv4AddressSize, ip_address.size());
+ struct {
+ const uint8_t address[4];
+ size_t prefix_length_in_bits;
+ } static const kReservedIPv4Ranges[] = {
+ {{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}};
+
+ for (const auto& range : kReservedIPv4Ranges) {
+ if (IPAddressPrefixCheck(ip_address, range.address,
+ range.prefix_length_in_bits)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Returns true if |ip_address| matches any of the reserved IPv6 ranges. This
+// method operates on a whitelist of non-reserved IPv6 ranges. All IPv6
+// addresses outside these ranges are reserved.
+// Sources for info:
+// www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+bool IsReservedIPv6(const std::vector<uint8_t>& ip_address) {
+ // Different IP versions have different range reservations.
+ DCHECK_EQ(net::IPAddress::kIPv6AddressSize, ip_address.size());
+ struct {
+ const uint8_t address_prefix[2];
+ size_t prefix_length_in_bits;
+ } static const kPublicIPv6Ranges[] = {
+ // 2000::/3 -- Global Unicast
+ {{0x20, 0}, 3},
+ // ff00::/8 -- Multicast
+ {{0xff, 0}, 8},
+ };
+
+ for (const auto& range : kPublicIPv6Ranges) {
+ if (IPAddressPrefixCheck(ip_address, range.address_prefix,
+ range.prefix_length_in_bits)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
} // namespace
namespace net {
@@ -95,53 +156,11 @@ bool IPAddress::IsValid() const {
return IsIPv4() || IsIPv6();
}
-// Don't compare IPv4 and IPv6 addresses (they have different range
-// reservations). Keep separate reservation arrays for each IP type, and
-// consolidate adjacent reserved ranges within a reservation array when
-// possible.
-// 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 IPAddress::IsReserved() const {
- 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}};
- 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},
- };
- size_t array_size = 0;
- const unsigned char* array = nullptr;
- switch (ip_address_.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;
- size_t width = ip_address_.size() + 1;
- for (size_t i = 0; i < array_size; ++i, array += width) {
- if (IPAddressPrefixCheck(ip_address_, array, array[width - 1]))
- return true;
+ if (IsIPv4()) {
+ return IsReservedIPv4(ip_address_);
+ } else if (IsIPv6()) {
+ return IsReservedIPv6(ip_address_);
}
return false;
}
« no previous file with comments | « no previous file | net/base/ip_address_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698