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

Unified Diff: net/base/ip_address.cc

Issue 1860823005: Move some net::IPAddressNumber implementations to net::IPAddress. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
Index: net/base/ip_address.cc
diff --git a/net/base/ip_address.cc b/net/base/ip_address.cc
index 722e3703f35b0b6ae58c6e0db3e46e088017ec6f..9377c8a01aa83da643fb0e9dd89790d74b4a09d3 100644
--- a/net/base/ip_address.cc
+++ b/net/base/ip_address.cc
@@ -11,6 +11,32 @@
#include "url/gurl.h"
#include "url/url_canon_ip.h"
+namespace {
+
+bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address,
+ 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_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;
+ if (remaining_bits != 0) {
+ unsigned char mask = 0xFF << (8 - remaining_bits);
+ int i = num_entire_bytes_in_prefix;
+ if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
namespace net {
IPAddress::IPAddress() {}
@@ -65,8 +91,55 @@ 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 {
- return IsIPAddressReserved(ip_address_);
+ 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] = {
martijnc 2016/04/11 22:02:08 I copied this list but while trying to write tests
eroman 2016/04/12 05:30:56 Thanks for raising this issue Martin! Yeah, those
Ryan Sleevi 2016/04/12 21:15:59 When the review introducing this started, that's w
+ {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;
+ }
+ return false;
}
bool IPAddress::IsZero() const {
@@ -159,8 +232,27 @@ IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
bool IPAddressMatchesPrefix(const IPAddress& ip_address,
const IPAddress& ip_prefix,
size_t prefix_length_in_bits) {
- return IPNumberMatchesPrefix(ip_address.bytes(), ip_prefix.bytes(),
- prefix_length_in_bits);
+ // Both the input IP address and the prefix IP address should be either IPv4
+ // or IPv6.
+ DCHECK(ip_address.IsValid());
+ DCHECK(ip_prefix.IsValid());
+
+ DCHECK_LE(prefix_length_in_bits, ip_prefix.size() * 8);
+
+ // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to
+ // IPv6 addresses in order to do the comparison.
+ if (ip_address.size() != ip_prefix.size()) {
+ if (ip_address.IsIPv4()) {
+ return IPAddressMatchesPrefix(ConvertIPv4ToIPv4MappedIPv6(ip_address),
+ ip_prefix, prefix_length_in_bits);
+ }
+ return IPAddressMatchesPrefix(ip_address,
+ ConvertIPv4ToIPv4MappedIPv6(ip_prefix),
+ 96 + prefix_length_in_bits);
+ }
+
+ return IPAddressPrefixCheck(ip_address.bytes(), ip_prefix.bytes().data(),
+ prefix_length_in_bits);
}
bool ParseCIDRBlock(const std::string& cidr_literal,

Powered by Google App Engine
This is Rietveld 408576698