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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/base/ip_address.h" 5 #include "net/base/ip_address.h"
6 6
7 #include "base/strings/string_piece.h" 7 #include "base/strings/string_piece.h"
8 #include "base/strings/string_split.h" 8 #include "base/strings/string_split.h"
9 #include "net/base/ip_address_number.h" 9 #include "net/base/ip_address_number.h"
10 #include "net/base/parse_number.h" 10 #include "net/base/parse_number.h"
11 #include "url/gurl.h" 11 #include "url/gurl.h"
12 #include "url/url_canon_ip.h" 12 #include "url/url_canon_ip.h"
13 13
14 namespace {
15
16 bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address,
17 const unsigned char* ip_prefix,
18 size_t prefix_length_in_bits) {
19 // Compare all the bytes that fall entirely within the prefix.
20 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
21 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
22 if (ip_address[i] != ip_prefix[i])
23 return false;
24 }
25
26 // In case the prefix was not a multiple of 8, there will be 1 byte
27 // which is only partially masked.
28 int remaining_bits = prefix_length_in_bits % 8;
29 if (remaining_bits != 0) {
30 unsigned char mask = 0xFF << (8 - remaining_bits);
31 int i = num_entire_bytes_in_prefix;
32 if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
33 return false;
34 }
35 return true;
36 }
37
38 } // namespace
39
14 namespace net { 40 namespace net {
15 41
16 IPAddress::IPAddress() {} 42 IPAddress::IPAddress() {}
17 43
18 IPAddress::IPAddress(const IPAddressNumber& address) : ip_address_(address) {} 44 IPAddress::IPAddress(const IPAddressNumber& address) : ip_address_(address) {}
19 45
20 IPAddress::IPAddress(const IPAddress& other) = default; 46 IPAddress::IPAddress(const IPAddress& other) = default;
21 47
22 IPAddress::IPAddress(const uint8_t* address, size_t address_len) 48 IPAddress::IPAddress(const uint8_t* address, size_t address_len)
23 : ip_address_(address, address + address_len) {} 49 : ip_address_(address, address + address_len) {}
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 } 84 }
59 85
60 bool IPAddress::IsIPv6() const { 86 bool IPAddress::IsIPv6() const {
61 return ip_address_.size() == kIPv6AddressSize; 87 return ip_address_.size() == kIPv6AddressSize;
62 } 88 }
63 89
64 bool IPAddress::IsValid() const { 90 bool IPAddress::IsValid() const {
65 return IsIPv4() || IsIPv6(); 91 return IsIPv4() || IsIPv6();
66 } 92 }
67 93
94 // Don't compare IPv4 and IPv6 addresses (they have different range
95 // reservations). Keep separate reservation arrays for each IP type, and
96 // consolidate adjacent reserved ranges within a reservation array when
97 // possible.
98 // Sources for info:
99 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
100 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
101 // They're formatted here with the prefix as the last element. For example:
102 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
68 bool IPAddress::IsReserved() const { 103 bool IPAddress::IsReserved() const {
69 return IsIPAddressReserved(ip_address_); 104 static const unsigned char kReservedIPv4[][5] = {
105 {0, 0, 0, 0, 8}, {10, 0, 0, 0, 8}, {100, 64, 0, 0, 10},
106 {127, 0, 0, 0, 8}, {169, 254, 0, 0, 16}, {172, 16, 0, 0, 12},
107 {192, 0, 2, 0, 24}, {192, 88, 99, 0, 24}, {192, 168, 0, 0, 16},
108 {198, 18, 0, 0, 15}, {198, 51, 100, 0, 24}, {203, 0, 113, 0, 24},
109 {224, 0, 0, 0, 3}};
110 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
111 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
112 {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
113 {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
114 {0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3},
115 {0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4},
116 {0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5},
117 {0xf8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6},
118 {0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7},
119 {0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9},
120 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10},
121 {0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10},
122 };
123 size_t array_size = 0;
124 const unsigned char* array = nullptr;
125 switch (ip_address_.size()) {
126 case kIPv4AddressSize:
127 array_size = arraysize(kReservedIPv4);
128 array = kReservedIPv4[0];
129 break;
130 case kIPv6AddressSize:
131 array_size = arraysize(kReservedIPv6);
132 array = kReservedIPv6[0];
133 break;
134 }
135 if (!array)
136 return false;
137 size_t width = ip_address_.size() + 1;
138 for (size_t i = 0; i < array_size; ++i, array += width) {
139 if (IPAddressPrefixCheck(ip_address_, array, array[width - 1]))
140 return true;
141 }
142 return false;
70 } 143 }
71 144
72 bool IPAddress::IsZero() const { 145 bool IPAddress::IsZero() const {
73 for (auto x : ip_address_) { 146 for (auto x : ip_address_) {
74 if (x != 0) 147 if (x != 0)
75 return false; 148 return false;
76 } 149 }
77 150
78 return !empty(); 151 return !empty();
79 } 152 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 return IPAddress(ConvertIPv4NumberToIPv6Number(address.bytes())); 225 return IPAddress(ConvertIPv4NumberToIPv6Number(address.bytes()));
153 } 226 }
154 227
155 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) { 228 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
156 return IPAddress(ConvertIPv4MappedToIPv4(address.bytes())); 229 return IPAddress(ConvertIPv4MappedToIPv4(address.bytes()));
157 } 230 }
158 231
159 bool IPAddressMatchesPrefix(const IPAddress& ip_address, 232 bool IPAddressMatchesPrefix(const IPAddress& ip_address,
160 const IPAddress& ip_prefix, 233 const IPAddress& ip_prefix,
161 size_t prefix_length_in_bits) { 234 size_t prefix_length_in_bits) {
162 return IPNumberMatchesPrefix(ip_address.bytes(), ip_prefix.bytes(), 235 // Both the input IP address and the prefix IP address should be either IPv4
163 prefix_length_in_bits); 236 // or IPv6.
237 DCHECK(ip_address.IsValid());
238 DCHECK(ip_prefix.IsValid());
239
240 DCHECK_LE(prefix_length_in_bits, ip_prefix.size() * 8);
241
242 // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to
243 // IPv6 addresses in order to do the comparison.
244 if (ip_address.size() != ip_prefix.size()) {
245 if (ip_address.IsIPv4()) {
246 return IPAddressMatchesPrefix(ConvertIPv4ToIPv4MappedIPv6(ip_address),
247 ip_prefix, prefix_length_in_bits);
248 }
249 return IPAddressMatchesPrefix(ip_address,
250 ConvertIPv4ToIPv4MappedIPv6(ip_prefix),
251 96 + prefix_length_in_bits);
252 }
253
254 return IPAddressPrefixCheck(ip_address.bytes(), ip_prefix.bytes().data(),
255 prefix_length_in_bits);
164 } 256 }
165 257
166 bool ParseCIDRBlock(const std::string& cidr_literal, 258 bool ParseCIDRBlock(const std::string& cidr_literal,
167 IPAddress* ip_address, 259 IPAddress* ip_address,
168 size_t* prefix_length_in_bits) { 260 size_t* prefix_length_in_bits) {
169 // We expect CIDR notation to match one of these two templates: 261 // We expect CIDR notation to match one of these two templates:
170 // <IPv4-literal> "/" <number of bits> 262 // <IPv4-literal> "/" <number of bits>
171 // <IPv6-literal> "/" <number of bits> 263 // <IPv6-literal> "/" <number of bits>
172 264
173 std::vector<base::StringPiece> parts = base::SplitStringPiece( 265 std::vector<base::StringPiece> parts = base::SplitStringPiece(
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 300
209 unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) { 301 unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) {
210 return CommonPrefixLength(a1.bytes(), a2.bytes()); 302 return CommonPrefixLength(a1.bytes(), a2.bytes());
211 } 303 }
212 304
213 unsigned MaskPrefixLength(const IPAddress& mask) { 305 unsigned MaskPrefixLength(const IPAddress& mask) {
214 return MaskPrefixLength(mask.bytes()); 306 return MaskPrefixLength(mask.bytes());
215 } 307 }
216 308
217 } // namespace net 309 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698