blob: 598fccd1e5290c204731c5b6358ec84bfd71b783 [file] [log] [blame]
/*
*
* Copyright (c) 2013-2017 Nest Labs, Inc.
* All rights reserved.
*
* 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>nl::Inet::InterfaceId</tt> type alias and related
* classes for iterating on the list of system network interfaces and the list
* of system interface addresses.
*/
#ifndef INETINTERFACE_H
#define INETINTERFACE_H
#include <Weave/Support/NLDLLUtil.h>
#include <InetLayer/IPAddress.h>
#include <stddef.h>
#include <stdint.h>
struct ifaddrs;
namespace nl {
namespace Inet {
/**
* @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.
*/
/**
* @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 WEAVE_SYSTEM_CONFIG_USE_LWIP
typedef struct netif *InterfaceId;
#define INET_NULL_INTERFACEID NULL
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
typedef unsigned InterfaceId;
#define INET_NULL_INTERFACEID 0
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
/**
* @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)
/**
* @brief Write the name of the network interface to a memory buffer
*
* @param[in] intfId a network interface
* @param[out] nameBuf region of memory to write the interface name
* @param[in] nameBufSize size of the region denoted by \c nameBuf
*
* @retval INET_NO_ERROR successful result, interface name written
* @retval INET_ERROR_NO_MEMORY name is too large to be written in buffer
* @retval other another system or platform error
*
* @details
* Writes the name of the network interface as \c NUL terminated text string
* at \c nameBuf. The name of the unspecified network interface is the empty
* string.
*
* The memory at \c nameBuf may be overwritten with nonsense even when the
* returned value is not \c INET_NO_ERROR.
*/
extern INET_ERROR GetInterfaceName(InterfaceId intfId, char *nameBuf, size_t nameBufSize);
/**
* @brief 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 INET_NO_ERROR success, network interface indicated
* @retval INET_ERROR_UNKNOWN_INTERFACE no network interface found
* @retval other another system or platform error
*
* @details
* On LwIP, this function must be called with the LwIP stack lock acquired.
*
* The \c intfId parameter is not updated unless the value returned is
* \c INET_NO_ERROR. It should be initialized with \c INET_NULL_INTERFACEID
* before calling this function.
*/
extern INET_ERROR InterfaceNameToId(const char *intfName, InterfaceId& intfId);
/**
* @brief Iterator for the list of system network interfaces.
*
* @details
* Use objects of this class to iterate the list of system network interfaces.
*
* On LwIP systems, it is recommended that the LwIP stack lock be acquired and
* not released over the entire lifetime of an object of this class.
*
* On some platforms, network interfaces without any IP addresses attached are
* not iterated.
*/
class InterfaceIterator
{
public:
/**
* @brief Conventional default constructor.
*
* @details
* Starts the cursor at the first network interface. On some platforms,
* this constructor may allocate resources recycled by the destructor.
*
* On LwIP, this constructor must be called with the LwIP stack lock
* acquired.
*/
InterfaceIterator(void);
/**
* @brief Non-virtual destructor.
*
* @details
* Recycles any resources allocated by the constructor.
*
* On LwIP, this destructor must be called with the LwIP stack lock
* acquired.
*/
~InterfaceIterator(void);
/**
* @brief Advance the cursor to the next network interface.
*
* @return \c false if advanced beyond the end, else \c true.
*
* @details
* Advances the internal cursor either to the next network interface or
* to the distinguished position corresponding to no further interfaces.
*
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool Next(void);
/**
* @brief Test whether the cursor is not yet positioned beyond the end.
*
* @return \c false if positioned beyond the end, else \c true.
*
* @details
* Advances the internal cursor either to the next network interface or to
* the distinguished position corresponding to no further interfaces.
*
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool HasCurrent(void) const
{
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
return (curIntf != NULL);
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
return (curAddr != NULL);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
}
/**
* @brief Extract the indicator of the network interface at the cursor.
*
* @retval INET_NULL_INTERFACEID if advanced beyond the end of the list.
* @retval id the indicator of the current interface.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
InterfaceId GetInterface(void);
/**
* @brief Inspect whether the current interface supports multicast.
*
* @return \c false if the current interface does not support multicast or
* the cursor has advanced beyond the end of the list, else \c true.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool SupportsMulticast(void);
private:
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
struct netif *curIntf;
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
struct ifaddrs *addrsList;
struct ifaddrs *curAddr;
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
};
/**
* @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.
*
* On LwIP systems, it is recommended that the LwIP stack lock be acquired and
* not released over the entire lifetime of an object of this class.
*/
class NL_DLL_EXPORT InterfaceAddressIterator
{
public:
/**
* @brief Conventional default constructor.
*
* @details
* Starts the cursor at the first network interface. On some platforms,
* this constructor may allocate resources recycled by the destructor.
*
* On LwIP, this constructor must be called with the LwIP stack lock
* acquired.
*/
InterfaceAddressIterator(void);
/**
* @brief Non-virtual destructor.
*
* @details
* Recycles any resources allocated by the constructor.
*
* On LwIP, this destructor must be called with the LwIP stack lock
* acquired.
*/
~InterfaceAddressIterator(void);
/**
* @brief Advance the cursor to the next network interface IP address.
*
* @return \c false if advanced beyond the end, else \c true.
*
* @details
* Advances the internal cursor either to the next network interface
* address or to the distinguished position corresponding to no further
* interface addresses.
*
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool Next(void);
/**
* @brief Test whether the cursor has not yet advanced beyond the end.
*
* @return \c false if advanced beyond the end, else \c true.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool HasCurrent(void) const
{
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
return (curIntf != NULL);
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
return (curAddr != NULL);
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
}
/**
* @brief Extract the current interface IP address.
*
* @return
* The current interface IP address, or \c IPAddress::Any if advanced
* beyond the end of the list.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
IPAddress GetAddress(void);
/**
* @brief Extract the length of the subnet prefix for the current
* network interface IPv6 address.
*
* @return length of the subnet prefix for the current IPv6 address, or
* zero if the current address is IPv4 or the iterator has
* advanced beyond the end of the 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 GetIPv6PrefixLength(void);
/**
* @brief Extract the indicator of the network interface for the current
* IP address.
*
* @retval INET_NULL_INTERFACEID if advanced beyond the end of the list.
* @retval id the indicator of the current interface.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
InterfaceId GetInterface(void);
/**
* @brief Inspect whether the interface for the current IP address
* supports multicast.
*
* @return \c false if the current interface does not support multicast or
* the iterator has advanced beyond the end of the list, else \c true.
*
* @details
* On LwIP, this method must be called with the LwIP stack lock
* acquired.
*/
bool SupportsMulticast(void);
private:
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
struct netif *curIntf;
int curAddrIndex;
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
#if WEAVE_SYSTEM_CONFIG_USE_SOCKETS
struct ifaddrs *addrsList;
struct ifaddrs *curAddr;
#endif // WEAVE_SYSTEM_CONFIG_USE_SOCKETS
};
#if WEAVE_SYSTEM_CONFIG_USE_LWIP
inline uint8_t InterfaceAddressIterator::GetIPv6PrefixLength(void)
{
return 64;
}
#endif // WEAVE_SYSTEM_CONFIG_USE_LWIP
} // namespace Inet
} // namespace nl
#endif /* INETINTERFACE_H */