| /* |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * Copyright (c) 2019 Google LLC. |
| * Copyright (c) 2013-2017 Nest Labs, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * This file defines the <tt>Inet::InterfaceId</tt> type alias and related |
| * classes for iterating on the list of system network interfaces and the list |
| * of system interface addresses. |
| */ |
| |
| #pragma once |
| |
| #include <inet/InetConfig.h> |
| |
| #include <inet/IPAddress.h> |
| #include <inet/InetError.h> |
| #include <lib/support/DLLUtil.h> |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| #include <lwip/netif.h> |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| struct if_nameindex; |
| struct ifaddrs; |
| #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| |
| #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| #include <device.h> |
| |
| struct net_if; |
| struct net_if_ipv4; |
| struct net_if_ipv6; |
| #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| namespace chip { |
| namespace Inet { |
| |
| class IPAddress; |
| class IPPrefix; |
| |
| /** |
| * @typedef InterfaceId |
| * |
| * @brief Indicator for system network interfaces. |
| * |
| * @details |
| * Portability depends on never witnessing this alias. It may be replaced by a |
| * concrete opaque class in the future. |
| * |
| * Note Well: The term "interface identifier" also conventionally refers to |
| * the lower 64 bits of an IPv6 address in all the relevant IETF standards |
| * documents, where the abbreviation "IID" is often used. In this text, the |
| * term "interface indicator" refers to values of this type alias. |
| */ |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| typedef struct netif * InterfaceId; |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| typedef unsigned InterfaceId; |
| #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| |
| #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| typedef int InterfaceId; |
| #endif |
| |
| /** |
| * @def INET_NULL_INTERFACEID |
| * |
| * @brief The distinguished value indicating no network interface. |
| * |
| * @details |
| * Note Well: This is not the indicator of a "null" network interface. This |
| * value can be used to indicate the absence of a specific network interface, |
| * or to specify that any applicable network interface is acceptable. Usage |
| * varies depending on context. |
| */ |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| #define INET_NULL_INTERFACEID NULL |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS || CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| #define INET_NULL_INTERFACEID 0 |
| #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS || CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| |
| /** |
| * @brief Test \c ID for inequivalence with \c INET_NULL_INTERFACEID |
| * |
| * @details |
| * This macro resolves to an expression that evaluates \c false if the |
| * argument is equivalent to \c INET_NULL_INTERFACEID and \c true otherwise. |
| */ |
| #define IsInterfaceIdPresent(intfId) ((intfId) != INET_NULL_INTERFACEID) |
| |
| /** |
| * Get the name of the network interface |
| * |
| * @param[in] intfId A network interface. |
| * @param[in] nameBuf Region of memory to write the interface name. |
| * @param[in] nameBufSize Size of the region denoted by \c nameBuf. |
| * |
| * @retval CHIP_NO_ERROR Successful result, interface name written. |
| * @retval CHIP_ERROR_BUFFER_TOO_SMALL Buffer is too small for the interface name. |
| * @retval other Another system or platform error. |
| * |
| * Writes the name of the network interface as a \c NUL terminated text string at \c nameBuf. |
| * The name of the unspecified network interface is the empty string. |
| */ |
| extern CHIP_ERROR GetInterfaceName(InterfaceId intfId, char * nameBuf, size_t nameBufSize); |
| |
| /** |
| * Search the list of network interfaces for the indicated name. |
| * |
| * @param[in] intfName Name of the network interface to find. |
| * @param[out] intfId Indicator of the network interface to assign. |
| * |
| * @retval CHIP_NO_ERROR Success, network interface indicated. |
| * @retval INET_ERROR_UNKNOWN_INTERFACE No network interface found. |
| * @retval other Another system or platform error. |
| * |
| * @note |
| * On LwIP, this function must be called with the LwIP stack lock acquired. |
| */ |
| extern CHIP_ERROR InterfaceNameToId(const char * intfName, InterfaceId & intfId); |
| |
| /** |
| * Compute a prefix length from a variable-length netmask. |
| */ |
| extern uint8_t NetmaskToPrefixLength(const uint8_t * netmask, uint16_t netmaskLen); |
| |
| /** |
| * @brief Iterator for the list of system network interfaces. |
| * |
| * @details |
| * Use objects of this class to iterate the list of system network interfaces. |
| * |
| * Methods on an individual instance of this class are *not* thread-safe; |
| * however separate instances may be used simultaneously by multiple threads. |
| * |
| * On multi-threaded LwIP systems, instances are thread-safe relative to other |
| * threads accessing the global LwIP state provided that the other threads hold |
| * the LwIP core lock while mutating the list of netifs, and that netif object |
| * themselves are never destroyed. |
| * |
| * On sockets-based systems, iteration is always stable in the face of changes |
| * to the underlying system's interfaces. |
| * |
| * On LwIP systems, iteration is stable except in the case where the currently |
| * selected interface is removed from the list, in which case iteration ends |
| * immediately. |
| */ |
| class InterfaceIterator |
| { |
| public: |
| /** |
| * Constructs an InterfaceIterator object. |
| * |
| * Starts the iterator at the first network interface. On some platforms, |
| * this constructor may allocate resources recycled by the destructor. |
| */ |
| InterfaceIterator(); |
| ~InterfaceIterator(); |
| |
| /** |
| * Test whether the iterator is positioned on an interface |
| * |
| * @return \c true if the iterator is positioned on an interface; |
| * \c false if positioned beyond the end of the interface list. |
| */ |
| bool HasCurrent(); |
| |
| /** |
| * Advance the iterator to the next network interface. |
| * |
| * @return \c false if advanced beyond the end, else \c true. |
| * |
| * Advances the internal iterator to the next network interface or to a position |
| * beyond the end of the interface list. |
| * |
| * On multi-threaded LwIP systems, this method is thread-safe relative to other |
| * threads accessing the global LwIP state provided that: 1) the other threads |
| * hold the LwIP core lock while mutating the list of netifs; and 2) netif objects |
| * themselves are never destroyed. |
| * |
| * Iteration is stable in the face of changes to the underlying system's |
| * interfaces, *except* in the case of LwIP systems when the currently selected |
| * interface is removed from the list, which causes iteration to end immediately. |
| */ |
| bool Next(); |
| |
| /** |
| * NetworkInterface InterfaceIterator::GetInterfaceId(void) |
| * |
| * Returns the network interface id at the current iterator position. |
| * |
| * @retval id The current network interface id. |
| * @retval NetworkInterface() If advanced beyond the end of the list. |
| */ |
| InterfaceId GetInterfaceId(); |
| |
| /** |
| * @brief Deprecated alias for \c GetInterfaceId(void) |
| */ |
| InterfaceId GetInterface() { return GetInterfaceId(); } |
| |
| /** |
| * Get the name of the current network interface |
| * |
| * @param[in] nameBuf Region of memory to write the interface name. |
| * @param[in] nameBufSize Size of the region denoted by \c nameBuf. |
| * |
| * @retval CHIP_NO_ERROR Successful result, interface name written. |
| * @retval CHIP_ERROR_INCORRECT_STATE Iterator is positioned beyond the end of the list. |
| * @retval CHIP_ERROR_BUFFER_TOO_SMALL Name is too large to be written in buffer. |
| * @retval other Another system or platform error. |
| * |
| * Writes the name of the network interface as \c NUL terminated text string at \c nameBuf. |
| */ |
| CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); |
| |
| /** |
| * Returns whether the current network interface is up. |
| * |
| * @return \c true if current network interface is up, \c false if not |
| * or if the iterator is positioned beyond the end of the list. |
| */ |
| bool IsUp(); |
| |
| /** |
| * Returns whether the current network interface supports multicast. |
| * |
| * @return \c true if current network interface supports multicast, \c false |
| * if not, or if the iterator is positioned beyond the end of the list. |
| */ |
| bool SupportsMulticast(); |
| |
| /** |
| * Returns whether the current network interface has a broadcast address. |
| * |
| * @return \c true if current network interface has a broadcast address, \c false |
| * if not, or if the iterator is positioned beyond the end of the list. |
| */ |
| bool HasBroadcastAddress(); |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| static constexpr size_t kMaxIfNameLength = 13; // Names are formatted as %c%c%d |
| #elif CHIP_SYSTEM_CONFIG_USE_SOCKETS && CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| static constexpr size_t kMaxIfNameLength = IF_NAMESIZE; |
| #elif CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| static constexpr size_t kMaxIfNameLength = Z_DEVICE_MAX_NAME_LEN; |
| #elif defined(IFNAMSIZ) |
| static constexpr size_t kMaxIfNameLength = IFNAMSIZ; |
| #else |
| // No constant available here - set some reasonable size |
| static constexpr size_t kMaxIfNameLength = 33; |
| #endif |
| |
| protected: |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| struct netif * mCurNetif; |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| struct if_nameindex * mIntfArray; |
| size_t mCurIntf; |
| short mIntfFlags; |
| bool mIntfFlagsCached; |
| |
| short GetFlags(); |
| #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| |
| #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| InterfaceId mCurrentId = 1; |
| net_if * mCurrentInterface = nullptr; |
| #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| }; |
| |
| /** |
| * @brief Iterator for the list of system network interface IP addresses. |
| * |
| * @details |
| * Use objects of this class to iterate the list of system network interface |
| * interface IP addresses. |
| * |
| * Methods on an individual instance of this class are *not* thread-safe; |
| * however separate instances may be used simultaneously by multiple threads. |
| * |
| * On multi-threaded LwIP systems, instances are thread-safe relative to other |
| * threads accessing the global LwIP state provided that: 1) other threads hold |
| * the LwIP core lock while mutating the list of netifs; and 2) netif object |
| * themselves are never destroyed. |
| * |
| * On sockets-based systems, iteration is always stable in the face of changes |
| * to the underlying system's interfaces and/or addresses. |
| * |
| * On LwIP systems, iteration is stable except in the case where the interface |
| * associated with the current address is removed, in which case iteration may |
| * end prematurely. |
| */ |
| class DLL_EXPORT InterfaceAddressIterator |
| { |
| public: |
| /** |
| * Constructs an InterfaceAddressIterator object. |
| * |
| * Starts the iterator at the first network address. On some platforms, |
| * this constructor may allocate resources recycled by the destructor. |
| */ |
| InterfaceAddressIterator(); |
| |
| /** |
| * Destroys an InterfaceAddressIterator object. |
| * |
| * Recycles any resources allocated by the constructor. |
| */ |
| ~InterfaceAddressIterator(); |
| |
| /** |
| * Test whether the iterator is positioned on an interface address |
| * |
| * @return \c true if the iterator is positioned on an interface address; |
| * \c false if positioned beyond the end of the address list. |
| */ |
| bool HasCurrent(); |
| |
| /** |
| * @fn bool InterfaceAddressIterator::Next(void) |
| * |
| * @brief Advance the iterator to the next interface address. |
| * |
| * @return \c false if advanced beyond the end, else \c true. |
| * |
| * @details |
| * Advances the iterator to the next interface address or to a position |
| * beyond the end of the address list. |
| * |
| * On LwIP, this method is thread-safe provided that: 1) other threads hold |
| * the LwIP core lock while mutating the netif list; and 2) netif objects |
| * themselves are never destroyed. Additionally, iteration on LwIP systems |
| * will terminate early if the current interface is removed from the list. |
| */ |
| bool Next(); |
| |
| /** |
| * @fn IPAddress InterfaceAddressIterator::GetAddress(void) |
| * |
| * @brief Get the current interface address. |
| * |
| * @return the current interface address or \c IPAddress::Any if the iterator |
| * is positioned beyond the end of the address list. |
| */ |
| IPAddress GetAddress(); |
| |
| /** |
| * @fn uint8_t InterfaceAddressIterator::GetPrefixLength(void) |
| * |
| * @brief Gets the network prefix associated with the current interface address. |
| * |
| * @return the network prefix (in bits) or 0 if the iterator is positioned beyond |
| * the end of the address list. |
| * |
| * @details |
| * On LwIP, this method simply returns the hard-coded constant 64. |
| * |
| * Note Well: the standard subnet prefix on all links other than PPP |
| * links is 64 bits. On PPP links and some non-broadcast multipoint access |
| * links, the convention is either 127 bits or 128 bits, but it might be |
| * something else. On most platforms, the system's interface address |
| * structure can represent arbitrary prefix lengths between 0 and 128. |
| */ |
| uint8_t GetPrefixLength(); |
| |
| /** |
| * @brief Deprecated alias for \c GetPrefixLength(void) |
| */ |
| uint8_t GetIPv6PrefixLength() { return GetPrefixLength(); } |
| |
| /** |
| * @fn void InterfaceAddressIterator::GetAddressWithPrefix(IPPrefix & addrWithPrefix) |
| * |
| * @brief Returns an IPPrefix containing the address and prefix length |
| * for the current address. |
| */ |
| void GetAddressWithPrefix(IPPrefix & addrWithPrefix); |
| |
| /** |
| * @fn NetworkInterface InterfaceAddressIterator::GetInterfaceId(void) |
| * |
| * @brief Returns the network interface id associated with the current |
| * interface address. |
| * |
| * @return the interface id or \c NetworkInterface() if the iterator |
| * is positioned beyond the end of the address list. |
| */ |
| InterfaceId GetInterfaceId(); |
| |
| /** |
| * @brief Deprecated alias for \c GetInterfaceId(void) |
| */ |
| InterfaceId GetInterface() { return GetInterfaceId(); } |
| |
| /** |
| * @fn CHIP_ERROR InterfaceAddressIterator::GetInterfaceName(char * nameBuf, size_t nameBufSize) |
| * |
| * @brief Get the name of the network interface associated with the |
| * current interface address. |
| * |
| * @param[in] nameBuf region of memory to write the interface name |
| * @param[in] nameBufSize size of the region denoted by \c nameBuf |
| * |
| * @retval CHIP_NO_ERROR successful result, interface name written |
| * @retval CHIP_ERROR_BUFFER_TOO_SMALL name is too large to be written in buffer |
| * @retval CHIP_ERROR_INCORRECT_STATE |
| * the iterator is not currently positioned on an |
| * interface address |
| * @retval other another system or platform error |
| * |
| * @details |
| * Writes the name of the network interface as \c NUL terminated text string |
| * at \c nameBuf. |
| */ |
| CHIP_ERROR GetInterfaceName(char * nameBuf, size_t nameBufSize); |
| |
| /** |
| * Returns whether the network interface associated with the current interface address is up. |
| * |
| * @return \c true if current network interface is up, \c false if not, or |
| * if the iterator is not positioned on an interface address. |
| */ |
| bool IsUp(); |
| |
| /** |
| * Returns whether the network interface associated with the current interface address supports multicast. |
| * |
| * @return \c true if multicast is supported, \c false if not, or |
| * if the iterator is not positioned on an interface address. |
| */ |
| bool SupportsMulticast(); |
| |
| /** |
| * Returns whether the network interface associated with the current interface address has an IPv4 broadcast address. |
| * |
| * @return \c true if the interface has a broadcast address, \c false if not, or |
| * if the iterator is not positioned on an interface address. |
| */ |
| bool HasBroadcastAddress(); |
| |
| private: |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| enum |
| { |
| kBeforeStartIndex = -1 |
| }; |
| |
| InterfaceIterator mIntfIter; |
| int mCurAddrIndex; |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| struct ifaddrs * mAddrsList; |
| struct ifaddrs * mCurAddr; |
| #endif // CHIP_SYSTEM_CONFIG_USE_BSD_IFADDRS |
| |
| #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| InterfaceIterator mIntfIter; |
| net_if_ipv6 * mIpv6 = nullptr; |
| int mCurAddrIndex = -1; |
| #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| }; |
| |
| #if CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| inline InterfaceIterator::InterfaceIterator(void) |
| { |
| mCurNetif = netif_list; |
| } |
| |
| inline InterfaceIterator::~InterfaceIterator(void) {} |
| |
| inline bool InterfaceIterator::HasCurrent(void) |
| { |
| return mCurNetif != NULL; |
| } |
| |
| inline InterfaceId InterfaceIterator::GetInterfaceId(void) |
| { |
| return mCurNetif; |
| } |
| |
| inline InterfaceAddressIterator::InterfaceAddressIterator(void) |
| { |
| mCurAddrIndex = kBeforeStartIndex; |
| } |
| |
| inline InterfaceAddressIterator::~InterfaceAddressIterator(void) {} |
| |
| #endif // CHIP_SYSTEM_CONFIG_USE_LWIP |
| |
| #if CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| inline InterfaceIterator::~InterfaceIterator() = default; |
| inline InterfaceAddressIterator::~InterfaceAddressIterator() = default; |
| #endif // CHIP_SYSTEM_CONFIG_USE_ZEPHYR_NET_IF |
| |
| } // namespace Inet |
| } // namespace chip |