diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 782a0b353b6..15c0a64f796 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (364) +#define OPENTHREAD_API_VERSION (365) /** * @addtogroup api-instance diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index 35c11057e2e..057373310bc 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -144,6 +144,8 @@ struct otIp6Address typedef struct otIp6Address otIp6Address; /** + * @struct otIp6Prefix + * * Represents an IPv6 prefix. * */ @@ -178,15 +180,15 @@ enum */ typedef struct otNetifAddress { - otIp6Address mAddress; ///< The IPv6 unicast address. - uint8_t mPrefixLength; ///< The Prefix length (in bits). - uint8_t mAddressOrigin; ///< The IPv6 address origin. - bool mPreferred : 1; ///< TRUE if the address is preferred, FALSE otherwise. - bool mValid : 1; ///< TRUE if the address is valid, FALSE otherwise. - bool mScopeOverrideValid : 1; ///< TRUE if the mScopeOverride value is valid, FALSE otherwise. - unsigned int mScopeOverride : 4; ///< The IPv6 scope of this address. - bool mRloc : 1; ///< TRUE if the address is an RLOC, FALSE otherwise. - struct otNetifAddress *mNext; ///< A pointer to the next network interface address. + otIp6Address mAddress; ///< The IPv6 unicast address. + uint8_t mPrefixLength; ///< The Prefix length (in bits). + uint8_t mAddressOrigin; ///< The IPv6 address origin. + bool mPreferred : 1; ///< TRUE if the address is preferred, FALSE otherwise. + bool mValid : 1; ///< TRUE if the address is valid, FALSE otherwise. + bool mScopeOverrideValid : 1; ///< TRUE if the mScopeOverride value is valid, FALSE otherwise. + unsigned int mScopeOverride : 4; ///< The IPv6 scope of this address. + bool mRloc : 1; ///< TRUE if the address is an RLOC, FALSE otherwise. + const struct otNetifAddress *mNext; ///< A pointer to the next network interface address. } otNetifAddress; /** @@ -296,6 +298,7 @@ bool otIp6IsEnabled(otInstance *aInstance); * @retval OT_ERROR_NONE Successfully added (or updated) the Network Interface Address. * @retval OT_ERROR_INVALID_ARGS The IP Address indicated by @p aAddress is an internal address. * @retval OT_ERROR_NO_BUFS The Network Interface is already storing the maximum allowed external addresses. + * */ otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress); @@ -308,6 +311,7 @@ otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAdd * @retval OT_ERROR_NONE Successfully removed the Network Interface Address. * @retval OT_ERROR_INVALID_ARGS The IP Address indicated by @p aAddress is an internal address. * @retval OT_ERROR_NOT_FOUND The IP Address indicated by @p aAddress was not found. + * */ otError otIp6RemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress); @@ -317,9 +321,22 @@ otError otIp6RemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAd * @param[in] aInstance A pointer to an OpenThread instance. * * @returns A pointer to the first Network Interface Address. + * */ const otNetifAddress *otIp6GetUnicastAddresses(otInstance *aInstance); +/** + * Indicates whether or not a unicast IPv6 address is assigned to the Thread interface. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aAddress A pointer to the unicast address. + * + * @retval TRUE If @p aAddress is assigned to the Thread interface. + * @retval FALSE If @p aAddress is not assigned to the Thread interface. + * + */ +bool otIp6HasUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress); + /** * Subscribes the Thread interface to a Network Interface Multicast Address. * @@ -450,8 +467,6 @@ typedef void (*otIp6ReceiveCallback)(otMessage *aMessage, void *aContext); void otIp6SetReceiveCallback(otInstance *aInstance, otIp6ReceiveCallback aCallback, void *aCallbackContext); /** - * @struct otIp6AddressInfo - * * Represents IPv6 address information. * */ @@ -528,7 +543,7 @@ void otIp6SetReceiveFilterEnabled(otInstance *aInstance, bool aEnabled); * @retval OT_ERROR_INVALID_SOURCE_ADDRESS Source address is invalid, e.g. an anycast address or a multicast address. * @retval OT_ERROR_PARSE Encountered a malformed header when processing the message. * @retval OT_ERROR_INVALID_ARGS The message's metadata is invalid, e.g. the message uses - * `OT_MESSAGE_ORIGIN_THREAD_NETIF` as the origin. + * `OT_MESSAGE_ORIGIN_THREAD_NETIF` as the origin. * */ otError otIp6Send(otInstance *aInstance, otMessage *aMessage); @@ -849,7 +864,7 @@ otError otIp6RegisterMulticastListeners(otInstance * /** * Sets the Mesh Local IID (for test purpose). * - * `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE` must be enabled. + * Requires `OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE`. * * @param[in] aInstance A pointer to an OpenThread instance. * @param[in] aIid A pointer to the Mesh Local IID to set. diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 381d92bf247..b4cad097af8 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -6068,23 +6068,8 @@ template <> otError Interpreter::Process(Arg aArgs[]) SuccessOrExit(error = aArgs[1].ParseAsIp6Address(config.mSource)); #if !OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE - { - bool valid = false; - const otNetifAddress *unicastAddrs = otIp6GetUnicastAddresses(GetInstancePtr()); - - for (const otNetifAddress *addr = unicastAddrs; addr; addr = addr->mNext) - { - if (otIp6IsAddressEqual(&addr->mAddress, &config.mSource)) - { - valid = true; - break; - } - } - - VerifyOrExit(valid, error = OT_ERROR_INVALID_ARGS); - } + VerifyOrExit(otIp6HasUnicastAddress(GetInstancePtr(), &config.mSource), error = OT_ERROR_INVALID_ARGS); #endif - aArgs += 2; } diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp index 58f5524144a..d545fd38fee 100644 --- a/src/core/api/ip6_api.cpp +++ b/src/core/api/ip6_api.cpp @@ -75,6 +75,11 @@ const otNetifAddress *otIp6GetUnicastAddresses(otInstance *aInstance) return AsCoreType(aInstance).Get().GetUnicastAddresses().GetHead(); } +bool otIp6HasUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress) +{ + return AsCoreType(aInstance).Get().HasUnicastAddress(AsCoreType(aAddress)); +} + otError otIp6AddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAddress) { return AsCoreType(aInstance).Get().AddExternalUnicastAddress(AsCoreType(aAddress)); diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index b8a99a15309..effc36ed5bb 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -424,7 +424,7 @@ Error Netif::AddExternalUnicastAddress(const UnicastAddress &aAddress) if (entry != nullptr) { - VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorAlready); + VerifyOrExit(IsUnicastAddressExternal(*entry), error = kErrorInvalidArgs); entry->mPrefixLength = aAddress.mPrefixLength; entry->mAddressOrigin = aAddress.mAddressOrigin; diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index be186b54351..e2b777c09dd 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -215,6 +215,22 @@ class Netif : public InstanceLocator, private NonCopyable */ AddressOrigin GetOrigin(void) const { return static_cast(mAddressOrigin); } + /** + * Returns the next unicast address. + * + * @returns A pointer to the next unicast address. + * + */ + const UnicastAddress *GetNext(void) const { return static_cast(mNext); } + + /** + * Returns the next unicast address. + * + * @returns A pointer to the next unicast address. + * + */ + UnicastAddress *GetNext(void) { return static_cast(AsNonConst(mNext)); } + private: bool Matches(const Address &aAddress) const { return GetAddress() == aAddress; } }; @@ -412,7 +428,7 @@ class Netif : public InstanceLocator, private NonCopyable * * @param[in] aAddress A reference to the unicast address. * - * @retval TRUE If @p aAddress is assigned to the network interface, + * @retval TRUE If @p aAddress is assigned to the network interface. * @retval FALSE If @p aAddress is not assigned to the network interface. * */ @@ -423,7 +439,7 @@ class Netif : public InstanceLocator, private NonCopyable * * @param[in] aAddress A reference to the unicast address. * - * @retval TRUE If @p aAddress is assigned to the network interface, + * @retval TRUE If @p aAddress is assigned to the network interface. * @retval FALSE If @p aAddress is not assigned to the network interface. * */ diff --git a/src/posix/platform/netif.cpp b/src/posix/platform/netif.cpp index 331c0d747e7..0c42acf1b36 100644 --- a/src/posix/platform/netif.cpp +++ b/src/posix/platform/netif.cpp @@ -291,26 +291,6 @@ static bool sIsSyncingState = false; #define OPENTHREAD_POSIX_LOG_TUN_PACKETS 0 -#if !defined(__linux__) -static bool UnicastAddressIsSubscribed(otInstance *aInstance, const otNetifAddress *netAddr) -{ - const otNetifAddress *address = otIp6GetUnicastAddresses(aInstance); - - while (address != nullptr) - { - if (memcmp(address->mAddress.mFields.m8, netAddr->mAddress.mFields.m8, sizeof(address->mAddress.mFields.m8)) == - 0) - { - return true; - } - - address = address->mNext; - } - - return false; -} -#endif - #if defined(__APPLE__) || defined(__NetBSD__) || defined(__FreeBSD__) static const uint8_t allOnes[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; @@ -1435,14 +1415,11 @@ static void processNetifAddrEvent(otInstance *aInstance, struct rt_msghdr *rtm) if (!addr.IsMulticast()) { otNetifAddress netAddr; - bool subscribed; netAddr.mAddress = addr; netAddr.mPrefixLength = NetmaskToPrefixLength(&netmask); - subscribed = UnicastAddressIsSubscribed(aInstance, &netAddr); - - if (subscribed) + if (otIp6HasUnicastAddress(aInstance, &addr)) { logAddrEvent(/* isAdd */ true, addr, OT_ERROR_ALREADY); error = OT_ERROR_NONE;