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