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 #ifndef NET_BASE_IP_ADDRESS_H_
6 #define NET_BASE_IP_ADDRESS_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <algorithm>
12 #include <array>
13 #include <optional>
14 #include <string>
15 #include <string_view>
16 #include <vector>
17
18 #include "base/check_op.h"
19 #include "base/containers/span.h"
20 #include "base/values.h"
21 #include "net/base/net_export.h"
22
23 namespace net {
24
25 // Helper class to represent the sequence of bytes in an IP address.
26 // A vector<uint8_t> would be simpler but incurs heap allocation, so
27 // IPAddressBytes uses a fixed size array.
28 class NET_EXPORT IPAddressBytes {
29 public:
30 IPAddressBytes();
31 explicit IPAddressBytes(base::span<const uint8_t> data);
32 IPAddressBytes(const IPAddressBytes& other);
33 ~IPAddressBytes();
34
35 // Copies elements from |data| into this object.
36 void Assign(base::span<const uint8_t> data);
37
38 // Returns the number of elements in the underlying array.
size()39 size_t size() const { return size_; }
40
41 // Sets the size to be |size|. Does not actually change the size
42 // of the underlying array or zero-initialize the bytes.
Resize(size_t size)43 void Resize(size_t size) {
44 DCHECK_LE(size, 16u);
45 size_ = static_cast<uint8_t>(size);
46 }
47
48 // Returns true if the underlying array is empty.
empty()49 bool empty() const { return size_ == 0; }
50
51 // Returns a pointer to the underlying array of bytes.
data()52 const uint8_t* data() const { return bytes_.data(); }
data()53 uint8_t* data() { return bytes_.data(); }
54
55 // Returns a pointer to the first element.
begin()56 const uint8_t* begin() const { return data(); }
begin()57 uint8_t* begin() { return data(); }
58
59 // Returns a pointer past the last element.
end()60 const uint8_t* end() const { return data() + size_; }
end()61 uint8_t* end() { return data() + size_; }
62
63 // Returns a reference to the last element.
back()64 uint8_t& back() {
65 DCHECK(!empty());
66 return bytes_[size_ - 1];
67 }
back()68 const uint8_t& back() const {
69 DCHECK(!empty());
70 return bytes_[size_ - 1];
71 }
72
73 // Appends |val| to the end and increments the size.
push_back(uint8_t val)74 void push_back(uint8_t val) {
75 DCHECK_GT(16, size_);
76 bytes_[size_++] = val;
77 }
78
79 // Appends `data` to the end and increments the size.
80 void Append(base::span<const uint8_t> data);
81
82 // Returns a reference to the byte at index |pos|.
83 uint8_t& operator[](size_t pos) {
84 DCHECK_LT(pos, size_);
85 return bytes_[pos];
86 }
87 const uint8_t& operator[](size_t pos) const {
88 DCHECK_LT(pos, size_);
89 return bytes_[pos];
90 }
91
92 bool operator<(const IPAddressBytes& other) const;
93 bool operator!=(const IPAddressBytes& other) const;
94 bool operator==(const IPAddressBytes& other) const;
95
96 size_t EstimateMemoryUsage() const;
97
98 private:
99 // Underlying sequence of bytes
100 std::array<uint8_t, 16> bytes_;
101
102 // Number of elements in |bytes_|. Should be either kIPv4AddressSize
103 // or kIPv6AddressSize or 0.
104 uint8_t size_;
105 };
106
107 class NET_EXPORT IPAddress {
108 public:
109 enum : size_t { kIPv4AddressSize = 4, kIPv6AddressSize = 16 };
110
111 // Nullopt if `value` is malformed to be deserialized to IPAddress.
112 static std::optional<IPAddress> FromValue(const base::Value& value);
113
114 // Parses an IP address literal (either IPv4 or IPv6). Returns the resulting
115 // IPAddress on success, or nullopt on error.
116 static std::optional<IPAddress> FromIPLiteral(std::string_view ip_literal);
117
118 // Creates a zero-sized, invalid address.
119 IPAddress();
120
121 IPAddress(const IPAddress& other);
122
123 // Copies the input address to |ip_address_|.
124 explicit IPAddress(const IPAddressBytes& address);
125
126 // Copies the input address to |ip_address_|. The input is expected to be in
127 // network byte order.
128 explicit IPAddress(base::span<const uint8_t> address);
129
130 // Initializes |ip_address_| from the 4 bX bytes to form an IPv4 address.
131 // The bytes are expected to be in network byte order.
132 IPAddress(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3);
133
134 // Initializes |ip_address_| from the 16 bX bytes to form an IPv6 address.
135 // The bytes are expected to be in network byte order.
136 IPAddress(uint8_t b0,
137 uint8_t b1,
138 uint8_t b2,
139 uint8_t b3,
140 uint8_t b4,
141 uint8_t b5,
142 uint8_t b6,
143 uint8_t b7,
144 uint8_t b8,
145 uint8_t b9,
146 uint8_t b10,
147 uint8_t b11,
148 uint8_t b12,
149 uint8_t b13,
150 uint8_t b14,
151 uint8_t b15);
152
153 ~IPAddress();
154
155 // Returns true if the IP has |kIPv4AddressSize| elements.
156 bool IsIPv4() const;
157
158 // Returns true if the IP has |kIPv6AddressSize| elements.
159 bool IsIPv6() const;
160
161 // Returns true if the IP is either an IPv4 or IPv6 address. This function
162 // only checks the address length.
163 bool IsValid() const;
164
165 // Returns true if the IP is not in a range reserved by the IANA for
166 // local networks. Works with both IPv4 and IPv6 addresses.
167 // IPv4-mapped-to-IPv6 addresses are considered publicly routable.
168 bool IsPubliclyRoutable() const;
169
170 // Returns true if the IP is "zero" (e.g. the 0.0.0.0 IPv4 address).
171 bool IsZero() const;
172
173 // Returns true if |ip_address_| is an IPv4-mapped IPv6 address.
174 bool IsIPv4MappedIPv6() const;
175
176 // Returns true if |ip_address_| is 127.0.0.1/8 or ::1/128
177 bool IsLoopback() const;
178
179 // Returns true if |ip_address_| is 169.254.0.0/16 or fe80::/10, or
180 // ::ffff:169.254.0.0/112 (IPv4 mapped IPv6 link-local).
181 bool IsLinkLocal() const;
182
183 // Returns true if `ip_address_` is a unique local IPv6 address (fc00::/7).
184 bool IsUniqueLocalIPv6() const;
185
186 // The size in bytes of |ip_address_|.
size()187 size_t size() const { return ip_address_.size(); }
188
189 // Returns true if the IP is an empty, zero-sized (invalid) address.
empty()190 bool empty() const { return ip_address_.empty(); }
191
192 // Returns the canonical string representation of an IP address.
193 // For example: "192.168.0.1" or "::1". Returns the empty string when
194 // |ip_address_| is invalid.
195 std::string ToString() const;
196
197 // Parses an IP address literal (either IPv4 or IPv6) to its numeric value.
198 // Returns true on success and fills |ip_address_| with the numeric value.
199 //
200 // When parsing fails, the original value of |this| will be overwritten such
201 // that |this->empty()| and |!this->IsValid()|.
202 [[nodiscard]] bool AssignFromIPLiteral(std::string_view ip_literal);
203
204 // Returns the underlying bytes.
bytes()205 const IPAddressBytes& bytes() const { return ip_address_; }
206
207 // Copies the bytes to a new vector. Generally callers should be using
208 // |bytes()| and the IPAddressBytes abstraction. This method is provided as a
209 // convenience for call sites that existed prior to the introduction of
210 // IPAddressBytes.
211 std::vector<uint8_t> CopyBytesToVector() const;
212
213 // Returns an IPAddress instance representing the 127.0.0.1 address.
214 static IPAddress IPv4Localhost();
215
216 // Returns an IPAddress instance representing the ::1 address.
217 static IPAddress IPv6Localhost();
218
219 // Returns an IPAddress made up of |num_zero_bytes| zeros.
220 static IPAddress AllZeros(size_t num_zero_bytes);
221
222 // Returns an IPAddress instance representing the 0.0.0.0 address.
223 static IPAddress IPv4AllZeros();
224
225 // Returns an IPAddress instance representing the :: address.
226 static IPAddress IPv6AllZeros();
227
228 // Create an IPv4 mask with prefix |mask_prefix_length|
229 // Returns false if |max_prefix_length| is greater than the maximum length of
230 // an IPv4 address.
231 static bool CreateIPv4Mask(IPAddress* ip_address, size_t mask_prefix_length);
232
233 // Create an IPv6 mask with prefix |mask_prefix_length|
234 // Returns false if |max_prefix_length| is greater than the maximum length of
235 // an IPv6 address.
236 static bool CreateIPv6Mask(IPAddress* ip_address, size_t mask_prefix_length);
237
238 bool operator==(const IPAddress& that) const;
239 bool operator!=(const IPAddress& that) const;
240 bool operator<(const IPAddress& that) const;
241
242 // Must be a valid address (per IsValid()).
243 base::Value ToValue() const;
244
245 size_t EstimateMemoryUsage() const;
246
247 private:
248 IPAddressBytes ip_address_;
249
250 // This class is copyable and assignable.
251 };
252
253 using IPAddressList = std::vector<IPAddress>;
254
255 // Returns the canonical string representation of an IP address along with its
256 // port. For example: "192.168.0.1:99" or "[::1]:80".
257 NET_EXPORT std::string IPAddressToStringWithPort(const IPAddress& address,
258 uint16_t port);
259
260 // Returns the address as a sequence of bytes in network-byte-order.
261 NET_EXPORT std::string IPAddressToPackedString(const IPAddress& address);
262
263 // Converts an IPv4 address to an IPv4-mapped IPv6 address.
264 // For example 192.168.0.1 would be converted to ::ffff:192.168.0.1.
265 NET_EXPORT IPAddress ConvertIPv4ToIPv4MappedIPv6(const IPAddress& address);
266
267 // Converts an IPv4-mapped IPv6 address to IPv4 address. Should only be called
268 // on IPv4-mapped IPv6 addresses.
269 NET_EXPORT IPAddress ConvertIPv4MappedIPv6ToIPv4(const IPAddress& address);
270
271 // Compares an IP address to see if it falls within the specified IP block.
272 // Returns true if it does, false otherwise.
273 //
274 // The IP block is given by (|ip_prefix|, |prefix_length_in_bits|) -- any
275 // IP address whose |prefix_length_in_bits| most significant bits match
276 // |ip_prefix| will be matched.
277 //
278 // In cases when an IPv4 address is being compared to an IPv6 address prefix
279 // and vice versa, the IPv4 addresses will be converted to IPv4-mapped
280 // (IPv6) addresses.
281 NET_EXPORT bool IPAddressMatchesPrefix(const IPAddress& ip_address,
282 const IPAddress& ip_prefix,
283 size_t prefix_length_in_bits);
284
285 // Parses an IP block specifier from CIDR notation to an
286 // (IP address, prefix length) pair. Returns true on success and fills
287 // |*ip_address| with the numeric value of the IP address and sets
288 // |*prefix_length_in_bits| with the length of the prefix. On failure,
289 // |ip_address| will be cleared to an empty value.
290 //
291 // CIDR notation literals can use either IPv4 or IPv6 literals. Some examples:
292 //
293 // 10.10.3.1/20
294 // a:b:c::/46
295 // ::1/128
296 NET_EXPORT bool ParseCIDRBlock(std::string_view cidr_literal,
297 IPAddress* ip_address,
298 size_t* prefix_length_in_bits);
299
300 // Parses a URL-safe IP literal (see RFC 3986, Sec 3.2.2) to its numeric value.
301 // Returns true on success, and fills |ip_address| with the numeric value.
302 // In other words, |hostname| must be an IPv4 literal, or an IPv6 literal
303 // surrounded by brackets as in [::1]. On failure |ip_address| may have been
304 // overwritten and could contain an invalid IPAddress.
305 [[nodiscard]] NET_EXPORT bool ParseURLHostnameToAddress(
306 std::string_view hostname,
307 IPAddress* ip_address);
308
309 // Returns number of matching initial bits between the addresses |a1| and |a2|.
310 NET_EXPORT size_t CommonPrefixLength(const IPAddress& a1, const IPAddress& a2);
311
312 // Computes the number of leading 1-bits in |mask|.
313 NET_EXPORT size_t MaskPrefixLength(const IPAddress& mask);
314
315 // Checks whether |address| starts with |prefix|. This provides similar
316 // functionality as IPAddressMatchesPrefix() but doesn't perform automatic IPv4
317 // to IPv4MappedIPv6 conversions and only checks against full bytes.
318 template <size_t N>
IPAddressStartsWith(const IPAddress & address,const uint8_t (& prefix)[N])319 bool IPAddressStartsWith(const IPAddress& address, const uint8_t (&prefix)[N]) {
320 if (address.size() < N)
321 return false;
322 return std::equal(prefix, prefix + N, address.bytes().begin());
323 }
324
325 // According to RFC6052 Section 2.2 IPv4-Embedded IPv6 Address Format.
326 // https://www.rfc-editor.org/rfc/rfc6052#section-2.2
327 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
328 // |PL| 0-------------32--40--48--56--64--72--80--88--96--104---------|
329 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
330 // |32| prefix |v4(32) | u | suffix |
331 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
332 // |40| prefix |v4(24) | u |(8)| suffix |
333 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
334 // |48| prefix |v4(16) | u | (16) | suffix |
335 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
336 // |56| prefix |(8)| u | v4(24) | suffix |
337 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
338 // |64| prefix | u | v4(32) | suffix |
339 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
340 // |96| prefix | v4(32) |
341 // +--+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
342 //
343 // The NAT64/DNS64 translation prefixes has one of the following lengths.
344 enum class Dns64PrefixLength {
345 k32bit,
346 k40bit,
347 k48bit,
348 k56bit,
349 k64bit,
350 k96bit,
351 kInvalid
352 };
353
354 // Extracts the NAT64 translation prefix from the IPv6 address using the well
355 // known address ipv4only.arpa 192.0.0.170 and 192.0.0.171.
356 // Returns prefix length on success, or Dns64PrefixLength::kInvalid on failure
357 // (when the ipv4only.arpa IPv4 address is not found)
358 NET_EXPORT Dns64PrefixLength
359 ExtractPref64FromIpv4onlyArpaAAAA(const IPAddress& address);
360
361 // Converts an IPv4 address to an IPv4-embedded IPv6 address using the given
362 // prefix. For example 192.168.0.1 and 64:ff9b::/96 would be converted to
363 // 64:ff9b::192.168.0.1
364 // Returns converted IPv6 address when prefix_length is not
365 // Dns64PrefixLength::kInvalid, and returns the original IPv4 address when
366 // prefix_length is Dns64PrefixLength::kInvalid.
367 NET_EXPORT IPAddress
368 ConvertIPv4ToIPv4EmbeddedIPv6(const IPAddress& ipv4_address,
369 const IPAddress& ipv6_address,
370 Dns64PrefixLength prefix_length);
371
372 } // namespace net
373
374 #endif // NET_BASE_IP_ADDRESS_H_
375