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