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