• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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