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