1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/base/ip_address.h"
11
12 #include <stddef.h>
13
14 #include <algorithm>
15 #include <array>
16 #include <climits>
17 #include <optional>
18 #include <string_view>
19
20 #include "base/check_op.h"
21 #include "base/debug/alias.h"
22 #include "base/debug/crash_logging.h"
23 #include "base/logging.h"
24 #include "base/notreached.h"
25 #include "base/ranges/algorithm.h"
26 #include "base/strings/strcat.h"
27 #include "base/strings/string_split.h"
28 #include "base/strings/stringprintf.h"
29 #include "base/trace_event/memory_usage_estimator.h"
30 #include "base/values.h"
31 #include "net/base/parse_number.h"
32 #include "url/gurl.h"
33 #include "url/url_canon_ip.h"
34
35 namespace net {
36 namespace {
37
38 // The prefix for IPv6 mapped IPv4 addresses.
39 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2
40 constexpr uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0,
41 0, 0, 0, 0, 0xFF, 0xFF};
42
43 // Note that this function assumes:
44 // * |ip_address| is at least |prefix_length_in_bits| (bits) long;
45 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long.
IPAddressPrefixCheck(const IPAddressBytes & ip_address,const uint8_t * ip_prefix,size_t prefix_length_in_bits)46 bool IPAddressPrefixCheck(const IPAddressBytes& ip_address,
47 const uint8_t* ip_prefix,
48 size_t prefix_length_in_bits) {
49 // Compare all the bytes that fall entirely within the prefix.
50 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
51 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
52 if (ip_address[i] != ip_prefix[i])
53 return false;
54 }
55
56 // In case the prefix was not a multiple of 8, there will be 1 byte
57 // which is only partially masked.
58 size_t remaining_bits = prefix_length_in_bits % 8;
59 if (remaining_bits != 0) {
60 uint8_t mask = 0xFF << (8 - remaining_bits);
61 size_t i = num_entire_bytes_in_prefix;
62 if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
63 return false;
64 }
65 return true;
66 }
67
CreateIPMask(IPAddressBytes * ip_address,size_t prefix_length_in_bits,size_t ip_address_length)68 bool CreateIPMask(IPAddressBytes* ip_address,
69 size_t prefix_length_in_bits,
70 size_t ip_address_length) {
71 if (ip_address_length != IPAddress::kIPv4AddressSize &&
72 ip_address_length != IPAddress::kIPv6AddressSize) {
73 return false;
74 }
75 if (prefix_length_in_bits > ip_address_length * 8) {
76 return false;
77 }
78
79 ip_address->Resize(ip_address_length);
80 size_t idx = 0;
81 // Set all fully masked bytes
82 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
83 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
84 (*ip_address)[idx++] = 0xff;
85 }
86
87 // In case the prefix was not a multiple of 8, there will be 1 byte
88 // which is only partially masked.
89 size_t remaining_bits = prefix_length_in_bits % 8;
90 if (remaining_bits != 0) {
91 uint8_t remaining_bits_mask = 0xFF << (8 - remaining_bits);
92 (*ip_address)[idx++] = remaining_bits_mask;
93 }
94
95 // Zero out any other bytes.
96 size_t bytes_remaining = ip_address_length - num_entire_bytes_in_prefix -
97 (remaining_bits != 0 ? 1 : 0);
98 for (size_t i = 0; i < bytes_remaining; ++i) {
99 (*ip_address)[idx++] = 0;
100 }
101
102 return true;
103 }
104
105 // Returns false if |ip_address| matches any of the reserved IPv4 ranges. This
106 // method operates on a list of reserved IPv4 ranges. Some ranges are
107 // consolidated.
108 // Sources for info:
109 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
110 // www.iana.org/assignments/iana-ipv4-special-registry/
111 // iana-ipv4-special-registry.xhtml
IsPubliclyRoutableIPv4(const IPAddressBytes & ip_address)112 bool IsPubliclyRoutableIPv4(const IPAddressBytes& ip_address) {
113 // Different IP versions have different range reservations.
114 DCHECK_EQ(IPAddress::kIPv4AddressSize, ip_address.size());
115 struct {
116 const uint8_t address[4];
117 size_t prefix_length_in_bits;
118 } static const kReservedIPv4Ranges[] = {
119 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10},
120 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12},
121 {{192, 0, 0, 0}, 24}, {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24},
122 {{192, 168, 0, 0}, 16}, {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24},
123 {{203, 0, 113, 0}, 24}, {{224, 0, 0, 0}, 3}};
124
125 for (const auto& range : kReservedIPv4Ranges) {
126 if (IPAddressPrefixCheck(ip_address, range.address,
127 range.prefix_length_in_bits)) {
128 return false;
129 }
130 }
131
132 return true;
133 }
134
135 // Returns false if |ip_address| matches any of the IPv6 ranges IANA reserved
136 // for local networks. This method operates on an allowlist of non-reserved
137 // IPv6 ranges, plus the list of reserved IPv4 ranges mapped to IPv6.
138 // Sources for info:
139 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
IsPubliclyRoutableIPv6(const IPAddressBytes & ip_address)140 bool IsPubliclyRoutableIPv6(const IPAddressBytes& ip_address) {
141 DCHECK_EQ(IPAddress::kIPv6AddressSize, ip_address.size());
142 struct {
143 const uint8_t address_prefix[2];
144 size_t prefix_length_in_bits;
145 } static const kPublicIPv6Ranges[] = {// 2000::/3 -- Global Unicast
146 {{0x20, 0}, 3},
147 // ff00::/8 -- Multicast
148 {{0xff, 0}, 8}};
149
150 for (const auto& range : kPublicIPv6Ranges) {
151 if (IPAddressPrefixCheck(ip_address, range.address_prefix,
152 range.prefix_length_in_bits)) {
153 return true;
154 }
155 }
156
157 IPAddress addr(ip_address);
158 if (addr.IsIPv4MappedIPv6()) {
159 IPAddress ipv4 = ConvertIPv4MappedIPv6ToIPv4(addr);
160 return IsPubliclyRoutableIPv4(ipv4.bytes());
161 }
162
163 return false;
164 }
165
ParseIPLiteralToBytes(std::string_view ip_literal,IPAddressBytes * bytes)166 bool ParseIPLiteralToBytes(std::string_view ip_literal, IPAddressBytes* bytes) {
167 // |ip_literal| could be either an IPv4 or an IPv6 literal. If it contains
168 // a colon however, it must be an IPv6 address.
169 if (ip_literal.find(':') != std::string_view::npos) {
170 // GURL expects IPv6 hostnames to be surrounded with brackets.
171 std::string host_brackets = base::StrCat({"[", ip_literal, "]"});
172 url::Component host_comp(0, host_brackets.size());
173
174 // Try parsing the hostname as an IPv6 literal.
175 bytes->Resize(16); // 128 bits.
176 return url::IPv6AddressToNumber(host_brackets.data(), host_comp,
177 bytes->data());
178 }
179
180 // Otherwise the string is an IPv4 address.
181 bytes->Resize(4); // 32 bits.
182 url::Component host_comp(0, ip_literal.size());
183 int num_components;
184 url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
185 ip_literal.data(), host_comp, bytes->data(), &num_components);
186 return family == url::CanonHostInfo::IPV4;
187 }
188
189 } // namespace
190
IPAddressBytes()191 IPAddressBytes::IPAddressBytes() : size_(0) {}
192
IPAddressBytes(base::span<const uint8_t> data)193 IPAddressBytes::IPAddressBytes(base::span<const uint8_t> data) {
194 Assign(data);
195 }
196
197 IPAddressBytes::~IPAddressBytes() = default;
198 IPAddressBytes::IPAddressBytes(IPAddressBytes const& other) = default;
199
Assign(base::span<const uint8_t> data)200 void IPAddressBytes::Assign(base::span<const uint8_t> data) {
201 CHECK_GE(16u, data.size());
202 size_ = data.size();
203 base::span(*this).copy_from(data);
204 }
205
operator <(const IPAddressBytes & other) const206 bool IPAddressBytes::operator<(const IPAddressBytes& other) const {
207 if (size_ == other.size_)
208 return std::lexicographical_compare(begin(), end(), other.begin(),
209 other.end());
210 return size_ < other.size_;
211 }
212
operator ==(const IPAddressBytes & other) const213 bool IPAddressBytes::operator==(const IPAddressBytes& other) const {
214 return base::ranges::equal(*this, other);
215 }
216
operator !=(const IPAddressBytes & other) const217 bool IPAddressBytes::operator!=(const IPAddressBytes& other) const {
218 return !(*this == other);
219 }
220
Append(base::span<const uint8_t> data)221 void IPAddressBytes::Append(base::span<const uint8_t> data) {
222 CHECK_LE(data.size(), static_cast<size_t>(16 - size_));
223 size_ += data.size();
224 base::span(*this).last(data.size()).copy_from(data);
225 }
226
EstimateMemoryUsage() const227 size_t IPAddressBytes::EstimateMemoryUsage() const {
228 return base::trace_event::EstimateMemoryUsage(bytes_);
229 }
230
231 // static
FromValue(const base::Value & value)232 std::optional<IPAddress> IPAddress::FromValue(const base::Value& value) {
233 if (!value.is_string()) {
234 return std::nullopt;
235 }
236
237 return IPAddress::FromIPLiteral(value.GetString());
238 }
239
240 // static
FromIPLiteral(std::string_view ip_literal)241 std::optional<IPAddress> IPAddress::FromIPLiteral(std::string_view ip_literal) {
242 IPAddress address;
243 if (!address.AssignFromIPLiteral(ip_literal)) {
244 return std::nullopt;
245 }
246 DCHECK(address.IsValid());
247 return address;
248 }
249
250 IPAddress::IPAddress() = default;
251
252 IPAddress::IPAddress(const IPAddress& other) = default;
253
IPAddress(const IPAddressBytes & address)254 IPAddress::IPAddress(const IPAddressBytes& address) : ip_address_(address) {}
255
IPAddress(base::span<const uint8_t> address)256 IPAddress::IPAddress(base::span<const uint8_t> address)
257 : ip_address_(address) {}
258
IPAddress(uint8_t b0,uint8_t b1,uint8_t b2,uint8_t b3)259 IPAddress::IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) {
260 const uint8_t bytes[] = {b0, b1, b2, b3};
261 ip_address_.Assign(bytes);
262 }
263
IPAddress(uint8_t b0,uint8_t b1,uint8_t b2,uint8_t b3,uint8_t b4,uint8_t b5,uint8_t b6,uint8_t b7,uint8_t b8,uint8_t b9,uint8_t b10,uint8_t b11,uint8_t b12,uint8_t b13,uint8_t b14,uint8_t b15)264 IPAddress::IPAddress(uint8_t b0,
265 uint8_t b1,
266 uint8_t b2,
267 uint8_t b3,
268 uint8_t b4,
269 uint8_t b5,
270 uint8_t b6,
271 uint8_t b7,
272 uint8_t b8,
273 uint8_t b9,
274 uint8_t b10,
275 uint8_t b11,
276 uint8_t b12,
277 uint8_t b13,
278 uint8_t b14,
279 uint8_t b15) {
280 const uint8_t bytes[] = {b0, b1, b2, b3, b4, b5, b6, b7,
281 b8, b9, b10, b11, b12, b13, b14, b15};
282 ip_address_.Assign(bytes);
283 }
284
285 IPAddress::~IPAddress() = default;
286
IsIPv4() const287 bool IPAddress::IsIPv4() const {
288 return ip_address_.size() == kIPv4AddressSize;
289 }
290
IsIPv6() const291 bool IPAddress::IsIPv6() const {
292 return ip_address_.size() == kIPv6AddressSize;
293 }
294
IsValid() const295 bool IPAddress::IsValid() const {
296 return IsIPv4() || IsIPv6();
297 }
298
IsPubliclyRoutable() const299 bool IPAddress::IsPubliclyRoutable() const {
300 if (IsIPv4()) {
301 return IsPubliclyRoutableIPv4(ip_address_);
302 } else if (IsIPv6()) {
303 return IsPubliclyRoutableIPv6(ip_address_);
304 }
305 return true;
306 }
307
IsZero() const308 bool IPAddress::IsZero() const {
309 for (auto x : ip_address_) {
310 if (x != 0)
311 return false;
312 }
313
314 return !empty();
315 }
316
IsIPv4MappedIPv6() const317 bool IPAddress::IsIPv4MappedIPv6() const {
318 return IsIPv6() && IPAddressStartsWith(*this, kIPv4MappedPrefix);
319 }
320
IsLoopback() const321 bool IPAddress::IsLoopback() const {
322 // 127.0.0.1/8
323 if (IsIPv4())
324 return ip_address_[0] == 127;
325
326 // ::1
327 if (IsIPv6()) {
328 for (size_t i = 0; i + 1 < ip_address_.size(); ++i) {
329 if (ip_address_[i] != 0)
330 return false;
331 }
332 return ip_address_.back() == 1;
333 }
334
335 return false;
336 }
337
IsLinkLocal() const338 bool IPAddress::IsLinkLocal() const {
339 // 169.254.0.0/16
340 if (IsIPv4())
341 return (ip_address_[0] == 169) && (ip_address_[1] == 254);
342
343 // [::ffff:169.254.0.0]/112
344 if (IsIPv4MappedIPv6())
345 return (ip_address_[12] == 169) && (ip_address_[13] == 254);
346
347 // [fe80::]/10
348 if (IsIPv6())
349 return (ip_address_[0] == 0xFE) && ((ip_address_[1] & 0xC0) == 0x80);
350
351 return false;
352 }
353
IsUniqueLocalIPv6() const354 bool IPAddress::IsUniqueLocalIPv6() const {
355 // [fc00::]/7
356 return IsIPv6() && ((ip_address_[0] & 0xFE) == 0xFC);
357 }
358
AssignFromIPLiteral(std::string_view ip_literal)359 bool IPAddress::AssignFromIPLiteral(std::string_view ip_literal) {
360 bool success = ParseIPLiteralToBytes(ip_literal, &ip_address_);
361 if (!success)
362 ip_address_.Resize(0);
363 return success;
364 }
365
CopyBytesToVector() const366 std::vector<uint8_t> IPAddress::CopyBytesToVector() const {
367 return std::vector<uint8_t>(ip_address_.begin(), ip_address_.end());
368 }
369
370 // static
IPv4Localhost()371 IPAddress IPAddress::IPv4Localhost() {
372 static const uint8_t kLocalhostIPv4[] = {127, 0, 0, 1};
373 return IPAddress(kLocalhostIPv4);
374 }
375
376 // static
IPv6Localhost()377 IPAddress IPAddress::IPv6Localhost() {
378 static const uint8_t kLocalhostIPv6[] = {0, 0, 0, 0, 0, 0, 0, 0,
379 0, 0, 0, 0, 0, 0, 0, 1};
380 return IPAddress(kLocalhostIPv6);
381 }
382
383 // static
AllZeros(size_t num_zero_bytes)384 IPAddress IPAddress::AllZeros(size_t num_zero_bytes) {
385 CHECK_LE(num_zero_bytes, 16u);
386 IPAddress result;
387 for (size_t i = 0; i < num_zero_bytes; ++i)
388 result.ip_address_.push_back(0u);
389 return result;
390 }
391
392 // static
IPv4AllZeros()393 IPAddress IPAddress::IPv4AllZeros() {
394 return AllZeros(kIPv4AddressSize);
395 }
396
397 // static
IPv6AllZeros()398 IPAddress IPAddress::IPv6AllZeros() {
399 return AllZeros(kIPv6AddressSize);
400 }
401
402 // static
CreateIPv4Mask(IPAddress * ip_address,size_t mask_prefix_length)403 bool IPAddress::CreateIPv4Mask(IPAddress* ip_address,
404 size_t mask_prefix_length) {
405 return CreateIPMask(&(ip_address->ip_address_), mask_prefix_length,
406 kIPv4AddressSize);
407 }
408
409 // static
CreateIPv6Mask(IPAddress * ip_address,size_t mask_prefix_length)410 bool IPAddress::CreateIPv6Mask(IPAddress* ip_address,
411 size_t mask_prefix_length) {
412 return CreateIPMask(&(ip_address->ip_address_), mask_prefix_length,
413 kIPv6AddressSize);
414 }
415
operator ==(const IPAddress & that) const416 bool IPAddress::operator==(const IPAddress& that) const {
417 return ip_address_ == that.ip_address_;
418 }
419
operator !=(const IPAddress & that) const420 bool IPAddress::operator!=(const IPAddress& that) const {
421 return ip_address_ != that.ip_address_;
422 }
423
operator <(const IPAddress & that) const424 bool IPAddress::operator<(const IPAddress& that) const {
425 // Sort IPv4 before IPv6.
426 if (ip_address_.size() != that.ip_address_.size()) {
427 return ip_address_.size() < that.ip_address_.size();
428 }
429
430 return ip_address_ < that.ip_address_;
431 }
432
ToString() const433 std::string IPAddress::ToString() const {
434 std::string str;
435 url::StdStringCanonOutput output(&str);
436
437 if (IsIPv4()) {
438 url::AppendIPv4Address(ip_address_.data(), &output);
439 } else if (IsIPv6()) {
440 url::AppendIPv6Address(ip_address_.data(), &output);
441 }
442
443 output.Complete();
444 return str;
445 }
446
ToValue() const447 base::Value IPAddress::ToValue() const {
448 DCHECK(IsValid());
449 return base::Value(ToString());
450 }
451
EstimateMemoryUsage() const452 size_t IPAddress::EstimateMemoryUsage() const {
453 return base::trace_event::EstimateMemoryUsage(ip_address_);
454 }
455
IPAddressToStringWithPort(const IPAddress & address,uint16_t port)456 std::string IPAddressToStringWithPort(const IPAddress& address, uint16_t port) {
457 std::string address_str = address.ToString();
458 if (address_str.empty())
459 return address_str;
460
461 if (address.IsIPv6()) {
462 // Need to bracket IPv6 addresses since they contain colons.
463 return base::StringPrintf("[%s]:%d", address_str.c_str(), port);
464 }
465 return base::StringPrintf("%s:%d", address_str.c_str(), port);
466 }
467
IPAddressToPackedString(const IPAddress & address)468 std::string IPAddressToPackedString(const IPAddress& address) {
469 return std::string(reinterpret_cast<const char*>(address.bytes().data()),
470 address.size());
471 }
472
ConvertIPv4ToIPv4MappedIPv6(const IPAddress & address)473 IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address) {
474 CHECK(address.IsIPv4());
475 // IPv4-mapped addresses are formed by:
476 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>.
477 IPAddressBytes bytes;
478 bytes.Append(kIPv4MappedPrefix);
479 bytes.Append(address.bytes());
480 return IPAddress(bytes);
481 }
482
ConvertIPv4MappedIPv6ToIPv4(const IPAddress & address)483 IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address) {
484 DCHECK(address.IsIPv4MappedIPv6());
485
486 IPAddressBytes bytes;
487 bytes.Append(
488 base::span(address.bytes()).subspan(std::size(kIPv4MappedPrefix)));
489 return IPAddress(bytes);
490 }
491
IPAddressMatchesPrefix(const IPAddress & ip_address,const IPAddress & ip_prefix,size_t prefix_length_in_bits)492 bool IPAddressMatchesPrefix(const IPAddress& ip_address,
493 const IPAddress& ip_prefix,
494 size_t prefix_length_in_bits) {
495 // Both the input IP address and the prefix IP address should be either IPv4
496 // or IPv6.
497 CHECK(ip_address.IsValid());
498 CHECK(ip_prefix.IsValid());
499
500 CHECK_LE(prefix_length_in_bits, ip_prefix.size() * 8);
501
502 // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to
503 // IPv6 addresses in order to do the comparison.
504 if (ip_address.size() != ip_prefix.size()) {
505 if (ip_address.IsIPv4()) {
506 return IPAddressMatchesPrefix(ConvertIPv4ToIPv4MappedIPv6(ip_address),
507 ip_prefix, prefix_length_in_bits);
508 }
509 return IPAddressMatchesPrefix(ip_address,
510 ConvertIPv4ToIPv4MappedIPv6(ip_prefix),
511 96 + prefix_length_in_bits);
512 }
513
514 return IPAddressPrefixCheck(ip_address.bytes(), ip_prefix.bytes().data(),
515 prefix_length_in_bits);
516 }
517
ParseCIDRBlock(std::string_view cidr_literal,IPAddress * ip_address,size_t * prefix_length_in_bits)518 bool ParseCIDRBlock(std::string_view cidr_literal,
519 IPAddress* ip_address,
520 size_t* prefix_length_in_bits) {
521 // We expect CIDR notation to match one of these two templates:
522 // <IPv4-literal> "/" <number of bits>
523 // <IPv6-literal> "/" <number of bits>
524
525 std::vector<std::string_view> parts = base::SplitStringPiece(
526 cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
527 if (parts.size() != 2)
528 return false;
529
530 // Parse the IP address.
531 if (!ip_address->AssignFromIPLiteral(parts[0]))
532 return false;
533
534 // Parse the prefix length.
535 uint32_t number_of_bits;
536 if (!ParseUint32(parts[1], ParseIntFormat::NON_NEGATIVE, &number_of_bits)) {
537 return false;
538 }
539
540 // Make sure the prefix length is in a valid range.
541 if (number_of_bits > ip_address->size() * 8)
542 return false;
543
544 *prefix_length_in_bits = number_of_bits;
545 return true;
546 }
547
ParseURLHostnameToAddress(std::string_view hostname,IPAddress * ip_address)548 bool ParseURLHostnameToAddress(std::string_view hostname,
549 IPAddress* ip_address) {
550 if (hostname.size() >= 2 && hostname.front() == '[' &&
551 hostname.back() == ']') {
552 // Strip the square brackets that surround IPv6 literals.
553 auto ip_literal = std::string_view(hostname).substr(1, hostname.size() - 2);
554 return ip_address->AssignFromIPLiteral(ip_literal) && ip_address->IsIPv6();
555 }
556
557 return ip_address->AssignFromIPLiteral(hostname) && ip_address->IsIPv4();
558 }
559
CommonPrefixLength(const IPAddress & a1,const IPAddress & a2)560 size_t CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) {
561 DCHECK_EQ(a1.size(), a2.size());
562 for (size_t i = 0; i < a1.size(); ++i) {
563 unsigned diff = a1.bytes()[i] ^ a2.bytes()[i];
564 if (!diff)
565 continue;
566 for (unsigned j = 0; j < CHAR_BIT; ++j) {
567 if (diff & (1 << (CHAR_BIT - 1)))
568 return i * CHAR_BIT + j;
569 diff <<= 1;
570 }
571 NOTREACHED();
572 }
573 return a1.size() * CHAR_BIT;
574 }
575
MaskPrefixLength(const IPAddress & mask)576 size_t MaskPrefixLength(const IPAddress& mask) {
577 IPAddressBytes all_ones;
578 all_ones.Resize(mask.size());
579 std::fill(all_ones.begin(), all_ones.end(), 0xFF);
580 return CommonPrefixLength(mask, IPAddress(all_ones));
581 }
582
ExtractPref64FromIpv4onlyArpaAAAA(const IPAddress & address)583 Dns64PrefixLength ExtractPref64FromIpv4onlyArpaAAAA(const IPAddress& address) {
584 DCHECK(address.IsIPv6());
585 IPAddress ipv4onlyarpa0(192, 0, 0, 170);
586 IPAddress ipv4onlyarpa1(192, 0, 0, 171);
587 auto span = base::span(address.bytes());
588
589 if (base::ranges::equal(ipv4onlyarpa0.bytes(), span.subspan(12u)) ||
590 base::ranges::equal(ipv4onlyarpa1.bytes(), span.subspan(12u))) {
591 return Dns64PrefixLength::k96bit;
592 }
593 if (base::ranges::equal(ipv4onlyarpa0.bytes(), span.subspan(9u, 4u)) ||
594 base::ranges::equal(ipv4onlyarpa1.bytes(), span.subspan(9u, 4u))) {
595 return Dns64PrefixLength::k64bit;
596 }
597 IPAddressBytes ipv4;
598 ipv4.Append(span.subspan(7u, 1u));
599 ipv4.Append(span.subspan(9u, 3u));
600 if (base::ranges::equal(ipv4onlyarpa0.bytes(), ipv4) ||
601 base::ranges::equal(ipv4onlyarpa1.bytes(), ipv4)) {
602 return Dns64PrefixLength::k56bit;
603 }
604 ipv4 = IPAddressBytes();
605 ipv4.Append(span.subspan(6u, 2u));
606 ipv4.Append(span.subspan(9u, 2u));
607 if (base::ranges::equal(ipv4onlyarpa0.bytes(), ipv4) ||
608 base::ranges::equal(ipv4onlyarpa1.bytes(), ipv4)) {
609 return Dns64PrefixLength::k48bit;
610 }
611 ipv4 = IPAddressBytes();
612 ipv4.Append(span.subspan(5u, 3u));
613 ipv4.Append(span.subspan(9u, 1u));
614 if (base::ranges::equal(ipv4onlyarpa0.bytes(), ipv4) ||
615 base::ranges::equal(ipv4onlyarpa1.bytes(), ipv4)) {
616 return Dns64PrefixLength::k40bit;
617 }
618 if (base::ranges::equal(ipv4onlyarpa0.bytes(), span.subspan(4u, 4u)) ||
619 base::ranges::equal(ipv4onlyarpa1.bytes(), span.subspan(4u, 4u))) {
620 return Dns64PrefixLength::k32bit;
621 }
622 // if ipv4onlyarpa address is not found return 0
623 return Dns64PrefixLength::kInvalid;
624 }
625
ConvertIPv4ToIPv4EmbeddedIPv6(const IPAddress & ipv4_address,const IPAddress & ipv6_address,Dns64PrefixLength prefix_length)626 IPAddress ConvertIPv4ToIPv4EmbeddedIPv6(const IPAddress& ipv4_address,
627 const IPAddress& ipv6_address,
628 Dns64PrefixLength prefix_length) {
629 DCHECK(ipv4_address.IsIPv4());
630 DCHECK(ipv6_address.IsIPv6());
631
632 IPAddressBytes bytes;
633
634 constexpr uint8_t kZeroBits[8] = {0x00, 0x00, 0x00, 0x00,
635 0x00, 0x00, 0x00, 0x00};
636
637 switch (prefix_length) {
638 case Dns64PrefixLength::k96bit:
639 bytes.Append(base::span(ipv6_address.bytes()).first(12u));
640 bytes.Append(ipv4_address.bytes());
641 return IPAddress(bytes);
642 case Dns64PrefixLength::k64bit:
643 bytes.Append(base::span(ipv6_address.bytes()).first(8u));
644 bytes.Append(base::span(kZeroBits).first(1u));
645 bytes.Append(ipv4_address.bytes());
646 bytes.Append(base::span(kZeroBits).first(3u));
647 return IPAddress(bytes);
648 case Dns64PrefixLength::k56bit: {
649 bytes.Append(base::span(ipv6_address.bytes()).first(7u));
650 auto [first, second] = base::span(ipv4_address.bytes()).split_at(1u);
651 bytes.Append(first);
652 bytes.Append(base::span(kZeroBits).first(1u));
653 bytes.Append(second);
654 bytes.Append(base::span(kZeroBits).first(4u));
655 return IPAddress(bytes);
656 }
657 case Dns64PrefixLength::k48bit: {
658 bytes.Append(base::span(ipv6_address.bytes()).first(6u));
659 auto [first, second] = base::span(ipv4_address.bytes()).split_at(2u);
660 bytes.Append(first);
661 bytes.Append(base::span(kZeroBits).first(1u));
662 bytes.Append(second);
663 bytes.Append(base::span(kZeroBits).first(5u));
664 return IPAddress(bytes);
665 }
666 case Dns64PrefixLength::k40bit: {
667 bytes.Append(base::span(ipv6_address.bytes()).first(5u));
668 auto [first, second] = base::span(ipv4_address.bytes()).split_at(3u);
669 bytes.Append(first);
670 bytes.Append(base::span(kZeroBits).first(1u));
671 bytes.Append(second);
672 bytes.Append(base::span(kZeroBits).first(6u));
673 return IPAddress(bytes);
674 }
675 case Dns64PrefixLength::k32bit:
676 bytes.Append(base::span(ipv6_address.bytes()).first(4u));
677 bytes.Append(ipv4_address.bytes());
678 bytes.Append(base::span(kZeroBits).first(8u));
679 return IPAddress(bytes);
680 case Dns64PrefixLength::kInvalid:
681 return ipv4_address;
682 }
683 }
684
685 } // namespace net
686