3 * Copyright (c) 2020-2021 Project CHIP Authors
4 * Copyright (c) 2019 Google LLC.
5 * Copyright (c) 2013-2018 Nest Labs, Inc.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
22 * This file defines the class <tt>Inet::IPAddress</tt> and
23 * related enumerated constants. The CHIP Inet Layer uses objects
24 * of this class to represent Internet protocol addresses of both
25 * IPv4 and IPv6 address families. (IPv4 addresses are stored
26 * internally in the V4COMPAT format, reserved for that purpose.)
34 #include <support/DLLUtil.h>
36 #include <inet/InetConfig.h>
38 #include "inet/IANAConstants.h"
40 #if CHIP_SYSTEM_CONFIG_USE_LWIP
41 #include <lwip/init.h>
42 #include <lwip/ip_addr.h>
43 #if INET_CONFIG_ENABLE_IPV4
44 #include <lwip/ip4_addr.h>
45 #endif // INET_CONFIG_ENABLE_IPV4
46 #include <lwip/inet.h>
47 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
49 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
51 #include <netinet/in.h>
52 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
54 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS
55 #include <sys/socket.h>
56 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS
58 #define NL_INET_IPV6_ADDR_LEN_IN_BYTES (16)
59 #define NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES (14)
62 * @brief Adaptation for LwIP ip4_addr_t type.
65 * Before LwIP 2.0.0, the \c ip_addr_t type alias referred to a structure comprising
66 * an IPv4 address. At LwIP 2.0.0 and thereafter, this type alias is renamed \c ip4_addr_t
67 * and \c ip_addr_t is replaced with an alias to a union of both. Here, the \c ip4_addr_t
68 * type alias is provided even when the LwIP version is earlier than 2.0.0 so as to prepare
69 * for the import of the new logic.
71 #if CHIP_SYSTEM_CONFIG_USE_LWIP && INET_CONFIG_ENABLE_IPV4 && LWIP_VERSION_MAJOR < 2 && LWIP_VERSION_MINOR < 5
72 typedef ip_addr_t ip4_addr_t;
73 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && INET_CONFIG_ENABLE_IPV4 && LWIP_VERSION_MAJOR < 2 && LWIP_VERSION_MINOR < 5
75 #if CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR >= 5
76 typedef u8_t lwip_ip_addr_type;
77 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP && LWIP_VERSION_MAJOR == 1 && LWIP_VERSION_MINOR >= 5
83 * @brief Internet protocol address family
86 * Values of the \c IPAddressType type are returned by the
87 * <tt>IPAddress::Type()</tt> method. They indicate the address family
88 * entailed by the use of the address.
93 kIPAddressType_Unknown = 0,
95 #if INET_CONFIG_ENABLE_IPV4
96 /** Internet protocol version 4. */
97 kIPAddressType_IPv4 = 1,
98 #endif // INET_CONFIG_ENABLE_IPV4
100 /** Internet protocol version 6. */
101 kIPAddressType_IPv6 = 2,
103 /** The unspecified internet address (independent of protocol version) */
104 kIPAddressType_Any = 3
108 * @brief Internet protocol v6 multicast flags
111 * Values of the \c IPv6MulticastFlag type are used to call the
112 * <tt>IPAddress::MakeIPv6Multicast()</tt> methods. They indicate the
113 * type of IPv6 multicast address to create. These numbers are
114 * registered by IETF with IANA.
118 /** The multicast address is (1) transient (i.e., dynamically-assigned) rather than (0) well-known (i.e, IANA-assigned). */
119 kIPv6MulticastFlag_Transient = 0x01,
121 /** The multicast address is (1) based on a network prefix. */
122 kIPv6MulticastFlag_Prefix = 0x02
126 * @brief Maximum length of the string representation of an IP address.
128 #if CHIP_SYSTEM_CONFIG_USE_LWIP
129 constexpr uint16_t kMaxIPAddressStringLength = IP6ADDR_STRLEN_MAX;
131 constexpr uint16_t kMaxIPAddressStringLength = INET6_ADDRSTRLEN;
135 * @brief Internet protocol address
138 * The CHIP Inet Layer uses objects of this class to represent Internet
139 * protocol addresses (independent of protocol version).
141 class DLL_EXPORT IPAddress
144 IPAddress() = default;
147 * Copy constructor for the IPAddress class.
150 IPAddress(const IPAddress & other) = default;
153 * @brief Opaque word array to contain IP addresses (independent of protocol version)
156 * IPv6 address use all 128-bits split into four 32-bit network byte
157 * ordered unsigned integers. IPv4 addresses are V4COMPAT, i.e. the
158 * first three words are zero, and the fourth word contains the IPv4
159 * address in network byte order.
164 * @brief Test whether address is IPv6 compatible.
167 * Use this method to check if the address belongs to the IPv6 address
168 * family. Note well: the unspecified address is not an IPv6 address.
170 * @retval true The address is IPv6 and not the unspecified address.
171 * @retval false The address is IPv4 or the unspecified address.
176 * @brief Test whether address is IPv6 global unicast address.
179 * Use this method to check if the address belongs to the IPv6 address
180 * family and has the global unicast address prefix.
182 * @retval true Address is IPv6 global unicast
183 * @retval false Otherwise
185 bool IsIPv6GlobalUnicast() const;
188 * @brief Test whether address is IPv6 unique-local address (ULA).
191 * Use this method to check if the address belongs to the IPv6 address
192 * family and has the reserved IPv6 unique-local address prefix.
194 * @retval true Address is IPv6 unique-local
195 * @retval false Otherwise
197 bool IsIPv6ULA() const;
200 * @brief Test whether address is IPv6 link-local address (LL).
203 * Use this method to check if the address belongs to the IPv6 address
204 * family and has the reserved IPv6 link-local address prefix.
206 * @retval true Address is IPv6 link-local
207 * @retval false Otherwise
209 bool IsIPv6LinkLocal() const;
212 * @brief Test whether address is IPv6 multicast.
215 * Use this method to check if the address belongs to the IPv6 address
216 * family and has the reserved IPv6 multicast address prefix.
218 * @retval true Address is IPv6 multicast
219 * @retval false Otherwise
221 bool IsIPv6Multicast() const;
224 * @brief Test whether address is IPv4 or IPv6 multicast.
227 * Use this method to check if the address belongs to the IPv4 or IPv6 address
228 * family and has the reserved IPv4 or IPv6 multicast address prefix.
230 * @retval true Address is IPv4 or IPv6 multicast
231 * @retval false Otherwise
233 bool IsMulticast() const;
236 * @brief Extract the IID of an IPv6 ULA address.
239 * Use this method with an IPv6 unique-local address (ULA) to extract the
240 * identifier identifier (IID), which is the least significant 64 bits of
243 * @return 64-bit interface identifier, or zero if the IP address is not
244 * an IPv6 unique-local address.
246 uint64_t InterfaceId() const;
249 * @brief Extract the 16-bit subnet identifier of an IPv6 ULA address.
252 * Use this method with an IPv6 unique-local address (ULA) to extract the
253 * subnet identifier, which is the least significant 16 bits of the
254 * network prefix. The network prefix is the most significant 64 bits of
255 * of the address. In other words, the subnet identifier is located in
256 * the 7th and 8th bytes of a 16-byte address.
258 * @return 16-bit subnet identifier, or zero if the IP address is not
259 * an IPv6 unique-local address.
261 uint16_t Subnet() const;
264 * @brief Extract the 16-bit global network identifier of an IPv6 ULA
268 * Use this method with an IPv6 unique-local address (ULA) to extract the
269 * global network identifier, which is the 40 bits immediately following
270 * the distinguished ULA network prefix, i.e. fd00::/8. In other words,
271 * the global network identifier is located in the five bytes from the 2nd
272 * 2nd through the 6th bytes in the address.
274 * @return 40-bit global network identifier, or zero if the IP address
275 * is not an IPv6 unique-local address.
277 uint64_t GlobalId() const;
280 * @brief Extract the type of the IP address.
283 * Use this method to return an value of the enumerated type \c
284 * IPAddressType to indicate the type of the IP address.
286 * @retval kIPAddressType_IPv4 The address is IPv4.
287 * @retval kIPAddressType_IPv6 The address is IPv6.
288 * @retval kIPAddressType_Any The address is the unspecified address.
290 IPAddressType Type() const;
293 * @brief Compare this IP address with another for equivalence.
295 * @param[in] other The address to compare.
297 * @retval true If equivalent to \c other
298 * @retval false Otherwise
300 bool operator==(const IPAddress & other) const;
303 * @brief Compare this IP address with another for inequivalence.
305 * @param[in] other The address to compare.
307 * @retval true If equivalent to \c other
308 * @retval false Otherwise
310 bool operator!=(const IPAddress & other) const;
313 * @brief Conventional assignment operator.
315 * @param[in] other The address to copy.
317 * @return A reference to this object.
319 IPAddress & operator=(const IPAddress & other);
322 * @brief Emit the IP address in conventional text presentation format.
324 * @param[out] buf The address of the emitted text.
325 * @param[in] bufSize The size of the buffer for the emitted text.
328 * Use <tt>ToString(char *buf, uint32_t bufSize) const</tt> to write the
329 * conventional text presentation form of the IP address to the memory
330 * located at \c buf and extending as much as \c bufSize bytes, including
331 * its NUL termination character.
333 * Note Well: not compliant with RFC 5952 on some platforms. Specifically,
334 * zero compression may not be applied according to section 4.2.
336 * @return The argument \c buf if no formatting error, or zero otherwise.
338 char * ToString(char * buf, uint32_t bufSize) const;
341 * A version of ToString that writes to a literal and deduces how much space
342 * it as to work with.
344 template <uint32_t N>
345 inline char * ToString(char (&buf)[N]) const
347 return ToString(buf, N);
351 * @brief Scan the IP address from its conventional presentation text.
353 * @param[in] str The address of the emitted text.
354 * @param[out] output The object to set to the scanned address.
357 * Use <tt>FromString(const char *str, IPAddress& output)</tt> to
358 * overwrite an IP address by scanning the conventional text presentation
361 * @retval true The presentation format is valid
362 * @retval false Otherwise
364 static bool FromString(const char * str, IPAddress & output);
367 * @brief Scan the IP address from its conventional presentation text.
369 * @param[in] str A pointer to the text to be scanned.
370 * @param[in] strLen The length of the text to be scanned.
371 * @param[out] output The object to set to the scanned address.
374 * Use <tt>FromString(const char *str, size_t strLen, IPAddress& output)</tt> to
375 * overwrite an IP address by scanning the conventional text presentation
378 * @retval true The presentation format is valid
379 * @retval false Otherwise
381 static bool FromString(const char * str, size_t strLen, IPAddress & output);
384 * @brief Emit the IP address in standard network representation.
386 * @param[in,out] p Reference to the cursor to use for writing.
389 * Use <tt>WriteAddress(uint8_t *&p)</tt> to encode the IP address in
390 * the binary format defined by RFC 4291 for IPv6 addresses. IPv4
391 * addresses are encoded according to section 2.5.5.1 "IPv4-Compatible
392 * IPv6 Address" (V4COMPAT).
394 void WriteAddress(uint8_t *& p) const;
397 * @brief Emit the IP address in standard network representation.
399 * @param[in,out] p Reference to the cursor to use for reading.
400 * @param[out] output Object to receive decoded IP address.
403 * Use <tt>ReadAddress(uint8_t *&p, IPAddress &output)</tt> to decode
404 * the IP address at \c p to the object \c output.
406 static void ReadAddress(const uint8_t *& p, IPAddress & output);
409 * @brief Test whether address is IPv4 compatible.
412 * Use this method to check if the address belongs to the IPv4 address
413 * family. Note well: the unspecified address is not an IPv4 address.
415 * @retval true The address is IPv4 and not the unspecified address.
416 * @retval false The address is IPv6 or the unspecified address.
421 * @brief Test whether address is IPv4 multicast.
424 * Use this method to check if the address is an IPv4 multicast
427 * @retval true Address is the IPv4 multicast
428 * @retval false Otherwise
430 bool IsIPv4Multicast() const;
433 * @brief Test whether address is IPv4 broadcast.
436 * Use this method to check if the address is the special purpose IPv4
439 * @retval true Address is the IPv4 broadcast
440 * @retval false Otherwise
442 bool IsIPv4Broadcast() const;
447 * @brief Extract the IPv4 address as a platform data structure.
450 * Use <tt>ToIPv4() const</tt> to extract the content as an IPv4 address,
451 * if possible. IPv6 addresses and the unspecified address are
452 * extracted as <tt>0.0.0.0</tt>.
454 * The result is either of type <tt>struct in_addr</tt> (on POSIX) or
455 * <tt>ip4_addr_t</tt> (on LwIP).
457 * @return The encapsulated IPv4 address, or \c 0.0.0.0 if the address is
458 * either unspecified or not an IPv4 address.
464 * @brief Extract the IPv6 address as a platform data structure.
467 * Use <tt>ToIPv6() const</tt> to extract the content as an IPv6 address,
468 * if possible. IPv4 addresses and the unspecified address are extracted
471 * The result is either of type <tt>struct in6_addr</tt> (on POSIX) or
472 * <tt>ip6_addr_t</tt> (on LwIP).
474 * @return The encapsulated IPv4 address, or \c [::] if the address is
475 * either unspecified or not an IPv4 address.
479 * @fn static IPAddress FromIPv4(const struct in_addr & addr)
481 * @brief Inject the IPv4 address from a platform data structure.
484 * Use <tt>FromIPv4(const ip4_addr_t &addr)</tt> to inject \c addr as an
487 * The argument \c addr is either of type <tt>const struct in_addr&</tt>
488 * (on POSIX) or <tt>const ip4_addr_t&</tt> (on LwIP).
490 * @return The constructed IP address.
493 * @overload static IPAddress FromIPv4(const ip4_addr_t &addr)
497 * @fn static IPAddress FromIPv6(const struct in6_addr& addr)
499 * @brief Inject the IPv6 address from a platform data structure.
502 * Use <tt>FromIPv6(const ip6_addr_t &addr)</tt> to inject \c addr as an
505 * The argument \c addr is either of type <tt>const struct in6_addr&</tt>
506 * (on POSIX) or <tt>const ip6_addr_t&</tt> (on LwIP).
508 * @return The constructed IP address.
511 * @overload static IPAddress FromIPv6(const ip6_addr_t &addr)
514 #if CHIP_SYSTEM_CONFIG_USE_LWIP
516 #if LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
518 * @fn ToLwIPAddr() const
520 * @brief Extract the IP address as a LwIP ip_addr_t structure.
523 * Use <tt>ToLwIPAddr() const</tt> to extract the content as an IP address,
526 * @return An LwIP ip_addr_t structure corresponding to the IP address.
528 ip_addr_t ToLwIPAddr(void) const;
531 * @fn static IPAddress FromLwIPAddr(const ip_addr_t& addr)
533 * @brief Inject the IP address from an LwIP ip_addr_t structure.
536 * Use <tt>FromLwIPAddr(const ip_addr_t &addr)</tt> to inject \c addr as an
537 * Inet layer IP address.
539 * The argument \c addr is of type <tt>const ip_addr_t&</tt> (on LwIP).
541 * @return The constructed IP address.
543 static IPAddress FromLwIPAddr(const ip_addr_t & addr);
546 * @brief Convert the INET layer address type to its underlying LwIP type.
549 * Use <tt>ToLwIPAddrType(IPAddressType)</tt> to convert the IP address type
550 * to its underlying LwIP address type code. (LWIP_VERSION_MAJOR > 1 only).
552 static lwip_ip_addr_type ToLwIPAddrType(IPAddressType);
553 #endif // LWIP_VERSION_MAJOR > 1 || LWIP_VERSION_MINOR >= 5
555 ip6_addr_t ToIPv6(void) const;
556 static IPAddress FromIPv6(const ip6_addr_t & addr);
558 #if INET_CONFIG_ENABLE_IPV4
559 ip4_addr_t ToIPv4(void) const;
560 static IPAddress FromIPv4(const ip4_addr_t & addr);
561 #endif // INET_CONFIG_ENABLE_IPV4
563 #endif // CHIP_SYSTEM_CONFIG_USE_LWIP
565 #if CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_CONFIG_USE_NETWORK_FRAMEWORK
567 struct in6_addr ToIPv6() const;
568 static IPAddress FromIPv6(const struct in6_addr & addr);
570 #if INET_CONFIG_ENABLE_IPV4
571 struct in_addr ToIPv4() const;
572 static IPAddress FromIPv4(const struct in_addr & addr);
573 #endif // INET_CONFIG_ENABLE_IPV4
576 * @brief Inject the IPv6 address from a POSIX <tt>struct sockaddr&</tt>
579 * Use <tt>FromSockAddr(const struct sockaddr& sockaddr)</tt> to inject
580 * <tt>sockaddr.sa_addr</tt> as an IPv6 address.
582 * @return The constructed IP address.
584 static IPAddress FromSockAddr(const struct sockaddr & sockaddr);
586 #endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS || CHIP_SYSTEM_USE_NETWORK_FRAMEWORK
589 * @brief Construct an IPv6 unique-local address (ULA) from its parts.
592 * Use <tt>MakeULA(uint64_t globalId, uint16_t subnet, uint64_t
593 * interfaceId)</tt> to construct a unique-local address (ULA) with global
594 * network identifier \c globalId, subnet identifier \c subnet and
595 * interface identifier (IID) \c interfaceId.
597 * @return The constructed IP address.
599 static IPAddress MakeULA(uint64_t globalId, uint16_t subnet, uint64_t interfaceId);
602 * @brief Construct an IPv6 link-local address (LL) from its IID.
605 * Use <tt>MakeLLA(uint64_t interfaceId)</tt> to construct an IPv6
606 * link-local address (LL) with interface identifier \c interfaceId.
608 * @return The constructed IP address.
610 static IPAddress MakeLLA(uint64_t interfaceId);
613 * @brief Construct an IPv6 multicast address from its parts.
616 * Use <tt>MakeIPv6Multicast(uint8_t flags, uint8_t scope,
617 * uint8_t groupId[14])</tt> to construct an IPv6 multicast
618 * address with \c flags for routing scope \c scope and group
619 * identifier octets \c groupId.
621 * @return The constructed IP address.
623 static IPAddress MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope,
624 const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]);
627 * @brief Construct an IPv6 multicast address from its parts.
630 * Use <tt>MakeIPv6Multicast(uint8_t flags, uint8_t scope,
631 * uint32_t groupId)</tt> to construct an IPv6 multicast
632 * address with \c flags for routing scope \c scope and group
633 * identifier \c groupId.
635 * @return The constructed IP address.
637 static IPAddress MakeIPv6Multicast(uint8_t aFlags, uint8_t aScope, uint32_t aGroupId);
640 * @brief Construct a well-known IPv6 multicast address from its parts.
643 * Use <tt>MakeIPv6WellKnownMulticast(uint8_t scope, uint32_t
644 * groupId)</tt> to construct an IPv6 multicast address for
645 * routing scope \c scope and group identifier \c groupId.
647 * @return The constructed IP address.
649 static IPAddress MakeIPv6WellKnownMulticast(uint8_t aScope, uint32_t aGroupId);
652 * @brief Construct a transient IPv6 multicast address from its parts.
655 * Use <tt>MakeIPv6TransientMulticast(uint8_t flags, uint8_t scope,
656 * uint8_t groupId[14])</tt> to construct a transient IPv6
657 * multicast address with \c flags for routing scope \c scope and
658 * group identifier octets \c groupId.
660 * @return The constructed IP address.
662 static IPAddress MakeIPv6TransientMulticast(uint8_t aFlags, uint8_t aScope,
663 const uint8_t aGroupId[NL_INET_IPV6_MCAST_GROUP_LEN_IN_BYTES]);
666 * @brief Construct a transient, prefix IPv6 multicast address from its parts.
669 * Use <tt>MakeIPv6PrefixMulticast(uint8_t scope, uint8_t
670 * prefixlen, const uint64_t prefix, uint32_t groupId)</tt> to
671 * construct a transient, prefix IPv6 multicast address with for
672 * routing scope \c scope and group identifier octets \c groupId,
673 * qualified by the prefix \c prefix of length \c prefixlen bits.
675 * @return The constructed IP address.
677 static IPAddress MakeIPv6PrefixMulticast(uint8_t aScope, uint8_t aPrefixLength, const uint64_t & aPrefix, uint32_t aGroupId);
680 * @brief Construct an IPv4 broadcast address.
682 * @return The constructed IP address.
684 static IPAddress MakeIPv4Broadcast();
687 * @brief The distinguished unspecified IP address object.
690 * This object is used as a constant for equivalence comparisons. It must
691 * not be modified by users of the CHIP Inet Layer.
693 static IPAddress Any;