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