blob: 65013559363215997021c7af5691282b9de07fa0 [file] [log] [blame]
/*
* Copyright (c) 2016, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definitions for IPv6 network interfaces.
*/
#ifndef NET_NETIF_HPP_
#define NET_NETIF_HPP_
#include "openthread-core-config.h"
#include "common/as_core_type.hpp"
#include "common/clearable.hpp"
#include "common/code_utils.hpp"
#include "common/const_cast.hpp"
#include "common/iterator_utils.hpp"
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/message.hpp"
#include "common/non_copyable.hpp"
#include "common/tasklet.hpp"
#include "mac/mac_types.hpp"
#include "net/ip6_address.hpp"
#include "net/socket.hpp"
#include "thread/mlr_types.hpp"
namespace ot {
namespace Ip6 {
class Ip6;
/**
* @addtogroup core-ip6-netif
*
* @brief
* This module includes definitions for IPv6 network interfaces.
*
* @{
*
*/
/**
* This class implements an IPv6 network interface.
*
*/
class Netif : public InstanceLocator, private NonCopyable
{
friend class Ip6;
friend class Address;
public:
/**
* This enumeration represent an address event (added or removed)
*
* The boolean values are used for `aIsAdded` parameter in the call of `otIp6AddressCallback`.
*
*/
enum AddressEvent : bool
{
kAddressRemoved = false, ///< Indicates that address was added.
kAddressAdded = true, ///< Indicates that address was removed.
};
/**
* This enumeration represents the address origin.
*
*/
enum AddressOrigin : uint8_t
{
kOriginThread = OT_ADDRESS_ORIGIN_THREAD, ///< Thread assigned address (ALOC, RLOC, MLEID, etc)
kOriginSlaac = OT_ADDRESS_ORIGIN_SLAAC, ///< SLAAC assigned address
kOriginDhcp6 = OT_ADDRESS_ORIGIN_DHCPV6, ///< DHCPv6 assigned address
kOriginManual = OT_ADDRESS_ORIGIN_MANUAL, ///< Manually assigned address
};
/**
* This class implements an IPv6 network interface unicast address.
*
*/
class UnicastAddress : public otNetifAddress,
public LinkedListEntry<UnicastAddress>,
public Clearable<UnicastAddress>
{
friend class LinkedList<UnicastAddress>;
public:
/**
* This method clears and initializes the unicast address as a preferred, valid, thread-origin address with
* 64-bit prefix length.
*
* @param[in] aPreferred Whether to initialize as a preferred address.
*
*/
void InitAsThreadOrigin(bool aPreferred = false);
/**
* This method clears and initializes the unicast address as a valid (but not preferred), thread-origin,
* realm-local scope (overridden) address with 64-bit prefix length.
*
*/
void InitAsThreadOriginRealmLocalScope(void);
/**
* This method clears and initializes the unicast address as a valid (but not preferred), thread-origin, global
* scope address.
*
*/
void InitAsThreadOriginGlobalScope(void);
/**
* This method clears and initializes the unicast address as a valid, SLAAC-origin address with a given
* preferred flag and a given prefix length.
*
* @param[in] aPrefixLength The prefix length (in bits).
* @param[in] aPreferred The preferred flag.
*
*/
void InitAsSlaacOrigin(uint8_t aPrefixLength, bool aPreferred);
/**
* This method returns the unicast address.
*
* @returns The unicast address.
*
*/
const Address &GetAddress(void) const { return AsCoreType(&mAddress); }
/**
* This method returns the unicast address.
*
* @returns The unicast address.
*
*/
Address &GetAddress(void) { return AsCoreType(&mAddress); }
/**
* This method returns the address's prefix length (in bits).
*
* @returns The prefix length (in bits).
*
*/
uint8_t GetPrefixLength(void) const { return mPrefixLength; }
/**
* This method indicates whether the address has a given prefix (i.e. same prefix length and matches the
* prefix).
*
* @param[in] aPrefix A prefix to check against.
*
* @retval TRUE The address has and fully matches the @p aPrefix.
* @retval FALSE The address does not contain or match the @p aPrefix.
*
*/
bool HasPrefix(const Prefix &aPrefix) const
{
return (mPrefixLength == aPrefix.GetLength()) && GetAddress().MatchesPrefix(aPrefix);
}
/**
* This method returns the IPv6 scope value.
*
* @returns The IPv6 scope value.
*
*/
uint8_t GetScope(void) const
{
return mScopeOverrideValid ? static_cast<uint8_t>(mScopeOverride) : GetAddress().GetScope();
}
/**
* This method sets the IPv6 scope override value.
*
* @param[in] aScope The IPv6 scope value.
*
*/
void SetScopeOverride(uint8_t aScope)
{
mScopeOverride = aScope;
mScopeOverrideValid = true;
}
/**
* This method gets the IPv6 address origin.
*
* @returns The address origin.
*
*/
AddressOrigin GetOrigin(void) const { return static_cast<AddressOrigin>(mAddressOrigin); }
private:
bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; }
};
/**
* This class implements an IPv6 network interface multicast address.
*
*/
class MulticastAddress : public otNetifMulticastAddress,
public LinkedListEntry<MulticastAddress>,
public Clearable<MulticastAddress>
{
friend class LinkedList<MulticastAddress>;
public:
/**
* This method returns the multicast address.
*
* @returns The multicast address.
*
*/
const Address &GetAddress(void) const { return AsCoreType(&mAddress); }
/**
* This method returns the multicast address.
*
* @returns The multicast address.
*
*/
Address &GetAddress(void) { return AsCoreType(&mAddress); }
/**
* This method returns the next multicast address subscribed to the interface.
*
* @returns A pointer to the next multicast address.
*
*/
const MulticastAddress *GetNext(void) const { return static_cast<const MulticastAddress *>(mNext); }
/**
* This method returns the next multicast address subscribed to the interface.
*
* @returns A pointer to the next multicast address.
*
*/
MulticastAddress *GetNext(void) { return static_cast<MulticastAddress *>(AsNonConst(mNext)); }
private:
bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; }
};
class ExternalMulticastAddress : public MulticastAddress
{
friend class Netif;
friend class LinkedList<ExternalMulticastAddress>;
public:
/**
* This class represents an iterator for iterating external multicast addresses in a `Netif` instance.
*
*/
class Iterator : public ItemPtrIterator<ExternalMulticastAddress, Iterator>
{
friend class ItemPtrIterator<ExternalMulticastAddress, Iterator>;
friend class Netif;
public:
/**
* This constructor initializes an `Iterator` instance to start from the first external multicast address
* that matches a given IPv6 address type filter.
*
* @param[in] aNetif A reference to the `Netif` instance.
* @param[in] aFilter The IPv6 address type filter.
*
*/
explicit Iterator(const Netif &aNetif, Address::TypeFilter aFilter = Address::kTypeAny);
private:
class Builder
{
public:
Builder(const Netif &aNetif, Address::TypeFilter aFilter)
: mNetif(aNetif)
, mFilter(aFilter)
{
}
Iterator begin(void) { return Iterator(mNetif, mFilter); }
Iterator end(void) { return Iterator(mNetif, Iterator::kEndIterator); }
private:
const Netif & mNetif;
Address::TypeFilter mFilter;
};
enum IteratorType : uint8_t
{
kEndIterator,
};
Iterator(const Netif &aNetif, IteratorType)
: mNetif(aNetif)
{
}
void AdvanceFrom(const MulticastAddress *aAddr);
void Advance(void) { AdvanceFrom(mItem->GetNext()); }
const Netif & mNetif;
Address::TypeFilter mFilter;
};
#if OPENTHREAD_CONFIG_MLR_ENABLE
/**
* This method returns the current Multicast Listener Registration (MLR) state.
*
* @returns The current Multicast Listener Registration state.
*
*/
MlrState GetMlrState(void) const { return mMlrState; }
/**
* This method sets the Multicast Listener Registration (MLR) state.
*
* @param[in] aState The new Multicast Listener Registration state.
*
*/
void SetMlrState(MlrState aState) { mMlrState = aState; }
#endif
private:
ExternalMulticastAddress *GetNext(void) { return static_cast<ExternalMulticastAddress *>(AsNonConst(mNext)); }
#if OPENTHREAD_CONFIG_MLR_ENABLE
MlrState mMlrState;
#endif
};
/**
* This constructor initializes the network interface.
*
* @param[in] aInstance A reference to the OpenThread instance.
*
*/
explicit Netif(Instance &aInstance);
/**
* This method registers a callback to notify internal IPv6 address changes.
*
* @param[in] aCallback A pointer to a function that is called when an IPv6 address is added or removed.
* @param[in] aCallbackContext A pointer to application-specific context.
*
*/
void SetAddressCallback(otIp6AddressCallback aCallback, void *aCallbackContext);
/**
* This method returns the linked list of unicast addresses.
*
* @returns The linked list of unicast addresses.
*
*/
const LinkedList<UnicastAddress> &GetUnicastAddresses(void) const { return mUnicastAddresses; }
/**
* This method adds a unicast address to the network interface.
*
* This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the
* unicast address linked list.
*
* If @p aAddress is already added, the call to `AddUnicastAddress()` with the same address will perform no action.
*
* @param[in] aAddress A reference to the unicast address.
*
*/
void AddUnicastAddress(UnicastAddress &aAddress);
/**
* This method removes a unicast address from the network interface.
*
* This method is intended for addresses internal to OpenThread. The @p aAddress instance is removed from the
* unicast address linked list.
*
* If @p aAddress is not in the list, the call to `RemoveUnicastAddress()` will perform no action.
*
* @param[in] aAddress A reference to the unicast address.
*
*/
void RemoveUnicastAddress(const UnicastAddress &aAddress);
/**
* This method indicates whether or not an address is assigned to the interface.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval TRUE If @p aAddress is assigned to the network interface,
* @retval FALSE If @p aAddress is not assigned to the network interface.
*
*/
bool HasUnicastAddress(const Address &aAddress) const;
/**
* This method indicates whether or not a unicast address is assigned to the network interface.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval TRUE If @p aAddress is assigned to the network interface,
* @retval FALSE If @p aAddress is not assigned to the network interface.
*
*/
bool HasUnicastAddress(const UnicastAddress &aAddress) const { return mUnicastAddresses.Contains(aAddress); }
/**
* This method indicates whether a unicast address is an external or internal address.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval TRUE The address is an external address.
* @retval FALSE The address is not an external address (it is an OpenThread internal address).
*
*/
bool IsUnicastAddressExternal(const UnicastAddress &aAddress) const;
/**
* This method adds an external (to OpenThread) unicast address to the network interface.
*
* For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied
* into a local entry (allocated from an internal pool) before being added in the unicast address linked list.
* The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS`.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval kErrorNone Successfully added (or updated) the unicast address.
* @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address.
* @retval kErrorNoBufs The maximum number of allowed external addresses are already added.
*
*/
Error AddExternalUnicastAddress(const UnicastAddress &aAddress);
/**
* This method removes a external (to OpenThread) unicast address from the network interface.
*
* @param[in] aAddress A reference to the unicast address.
*
* @retval kErrorNone Successfully removed the unicast address.
* @retval kErrorInvalidArgs The address indicated by @p aAddress is an internal address.
* @retval kErrorNotFound The unicast address was not found.
*
*/
Error RemoveExternalUnicastAddress(const Address &aAddress);
/**
* This method removes all the previously added external (to OpenThread) unicast addresses from the
* network interface.
*
*/
void RemoveAllExternalUnicastAddresses(void);
/**
* This method indicates whether or not the network interface is subscribed to a multicast address.
*
* @param[in] aAddress The multicast address to check.
*
* @retval TRUE If the network interface is subscribed to @p aAddress.
* @retval FALSE If the network interface is not subscribed to @p aAddress.
*
*/
bool IsMulticastSubscribed(const Address &aAddress) const;
/**
* This method subscribes the network interface to the link-local and realm-local all routers addresses.
*
* @note This method MUST be called after `SubscribeAllNodesMulticast()` or its behavior is undefined.
*
*/
void SubscribeAllRoutersMulticast(void);
/**
* This method unsubscribes the network interface to the link-local and realm-local all routers address.
*
*/
void UnsubscribeAllRoutersMulticast(void);
/**
* This method returns the linked list of multicast addresses.
*
* @returns The linked list of multicast addresses.
*
*/
const LinkedList<MulticastAddress> &GetMulticastAddresses(void) const { return mMulticastAddresses; }
/**
* This method indicates whether a multicast address is an external or internal address.
*
* @param[in] aAddress A reference to the multicast address.
*
* @retval TRUE The address is an external address.
* @retval FALSE The address is not an external address (it is an OpenThread internal address).
*
*/
bool IsMulticastAddressExternal(const MulticastAddress &aAddress) const;
/**
* This method subscribes the network interface to a multicast address.
*
* This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly added in the
* multicast address linked list.
*
* @param[in] aAddress A reference to the multicast address.
*
*/
void SubscribeMulticast(MulticastAddress &aAddress);
/**
* This method unsubscribes the network interface to a multicast address.
*
* This method is intended for addresses internal to OpenThread. The @p aAddress instance is directly removed from
* the multicast address linked list.
*
* @param[in] aAddress A reference to the multicast address.
*
*/
void UnsubscribeMulticast(const MulticastAddress &aAddress);
/**
* This method subscribes the network interface to the external (to OpenThread) multicast address.
*
* For external address, the @p aAddress instance is not directly used (i.e., it can be temporary). It is copied
* into a local entry (allocated from an internal pool) before being added in the multicast address linked list.
* The maximum number of external addresses is specified by `OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS`.
*
* @param[in] aAddress A reference to the multicast address.
*
* @retval kErrorNone Successfully subscribed to @p aAddress.
* @retval kErrorAlready The multicast address is already subscribed.
* @retval kErrorInvalidArgs The IP Address indicated by @p aAddress is an invalid multicast address.
* @retval kErrorRejected The IP Address indicated by @p aAddress is an internal multicast address.
* @retval kErrorNoBufs The maximum number of allowed external multicast addresses are already added.
*
*/
Error SubscribeExternalMulticast(const Address &aAddress);
/**
* This method unsubscribes the network interface to the external (to OpenThread) multicast address.
*
* @param[in] aAddress A reference to the multicast address.
*
* @retval kErrorNone Successfully unsubscribed to the unicast address.
* @retval kErrorRejected The address indicated by @p aAddress is an internal address.
* @retval kErrorNotFound The multicast address was not found.
*
*/
Error UnsubscribeExternalMulticast(const Address &aAddress);
/**
* This method unsubscribes the network interface from all previously added external (to OpenThread) multicast
* addresses.
*
*/
void UnsubscribeAllExternalMulticastAddresses(void);
/**
* This method checks if multicast promiscuous mode is enabled on the network interface.
*
* @retval TRUE If the multicast promiscuous mode is enabled.
* @retval FALSE If the multicast promiscuous mode is disabled.
*
*/
bool IsMulticastPromiscuousEnabled(void) const { return mMulticastPromiscuous; }
/**
* This method enables multicast promiscuous mode on the network interface.
*
* @param[in] aEnabled TRUE if Multicast Promiscuous mode is enabled, FALSE otherwise.
*
*/
void SetMulticastPromiscuous(bool aEnabled) { mMulticastPromiscuous = aEnabled; }
/**
* This method enables range-based `for` loop iteration over external multicast addresses on the Netif that matches
* a given IPv6 address type filter.
*
* This method should be used like follows: to iterate over all external multicast addresses
*
* for (Ip6::Netif::ExternalMulticastAddress &addr : Get<ThreadNetif>().IterateExternalMulticastAddresses())
* { ... }
*
* or to iterate over a subset of external multicast addresses determined by a given address type filter
*
* for (Ip6::Netif::ExternalMulticastAddress &addr :
* Get<ThreadNetif>().IterateExternalMulticastAddresses(Ip6::Address::kTypeMulticastLargerThanRealmLocal))
* { ... }
*
* @param[in] aFilter The IPv6 address type filter.
*
* @returns An `ExternalMulticastAddress::Iterator::Builder` instance.
*
*/
ExternalMulticastAddress::Iterator::Builder IterateExternalMulticastAddresses(
Address::TypeFilter aFilter = Address::kTypeAny)
{
return ExternalMulticastAddress::Iterator::Builder(*this, aFilter);
}
/**
* This method indicates whether or not the network interfaces is subscribed to any external multicast address.
*
* @retval TRUE The network interface is subscribed to at least one external multicast address.
* @retval FALSE The network interface is not subscribed to any external multicast address.
*
*/
bool HasAnyExternalMulticastAddress(void) const { return !ExternalMulticastAddress::Iterator(*this).IsDone(); }
protected:
/**
* This method subscribes the network interface to the realm-local all MPL forwarders, link-local, and realm-local
* all nodes address.
*
*/
void SubscribeAllNodesMulticast(void);
/**
* This method unsubscribes the network interface from the realm-local all MPL forwarders, link-local and
* realm-local all nodes address.
*
* @note This method MUST be called after `UnsubscribeAllRoutersMulticast()` or its behavior is undefined
*
*/
void UnsubscribeAllNodesMulticast(void);
private:
LinkedList<UnicastAddress> mUnicastAddresses;
LinkedList<MulticastAddress> mMulticastAddresses;
bool mMulticastPromiscuous;
otIp6AddressCallback mAddressCallback;
void * mAddressCallbackContext;
Pool<UnicastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_UCAST_ADDRS> mExtUnicastAddressPool;
Pool<ExternalMulticastAddress, OPENTHREAD_CONFIG_IP6_MAX_EXT_MCAST_ADDRS> mExtMulticastAddressPool;
static const otNetifMulticastAddress kRealmLocalAllMplForwardersMulticastAddress;
static const otNetifMulticastAddress kLinkLocalAllNodesMulticastAddress;
static const otNetifMulticastAddress kRealmLocalAllNodesMulticastAddress;
static const otNetifMulticastAddress kLinkLocalAllRoutersMulticastAddress;
static const otNetifMulticastAddress kRealmLocalAllRoutersMulticastAddress;
};
/**
* @}
*
*/
} // namespace Ip6
DefineCoreType(otNetifAddress, Ip6::Netif::UnicastAddress);
DefineCoreType(otNetifMulticastAddress, Ip6::Netif::MulticastAddress);
} // namespace ot
#endif // NET_NETIF_HPP_