xref: /aosp_15_r20/external/cronet/net/base/ip_address.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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