diff --git a/include/openthread/ip6.h b/include/openthread/ip6.h index bc025c63b..323a6ce10 100644 --- a/include/openthread/ip6.h +++ b/include/openthread/ip6.h @@ -408,6 +408,31 @@ typedef void (*otIp6ReceiveCallback)(otMessage *aMessage, void *aContext); */ void otIp6SetReceiveCallback(otInstance *aInstance, otIp6ReceiveCallback aCallback, void *aCallbackContext); +/** + * This function pointer is called when an internal IPv6 address is added or removed. + * + * @param[in] aAddress A pointer to the IPv6 address. + * @param[in] aPrefixLength The prefix length if @p aAddress is unicast address, and 128 for multicast address. + * @param[in] aIsAdded TRUE if the @p aAddress was added, FALSE if @p aAddress was removed. + * @param[in] aContext A pointer to application-specific context. + * + */ +typedef void (*otIp6AddressCallback)(const otIp6Address *aAddress, + uint8_t aPrefixLength, + bool aIsAdded, + void * aContext); + +/** + * This function registers a callback to notify internal IPv6 address changes. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aCallback A pointer to a function that is called when an internal IPv6 address is added or + * removed. NULL to disable the callback. + * @param[in] aCallbackContext A pointer to application-specific context. + * + */ +void otIp6SetAddressCallback(otInstance *aInstance, otIp6AddressCallback aCallback, void *aCallbackContext); + /** * This function indicates whether or not Thread control traffic is filtered out when delivering IPv6 datagrams * via the callback specified in otIp6SetReceiveCallback(). diff --git a/src/core/api/ip6_api.cpp b/src/core/api/ip6_api.cpp index c13b7ad5f..3d6cee3fe 100644 --- a/src/core/api/ip6_api.cpp +++ b/src/core/api/ip6_api.cpp @@ -170,6 +170,13 @@ void otIp6SetReceiveCallback(otInstance *aInstance, otIp6ReceiveCallback aCallba instance.GetIp6().SetReceiveDatagramCallback(aCallback, aCallbackContext); } +void otIp6SetAddressCallback(otInstance *aInstance, otIp6AddressCallback aCallback, void *aCallbackContext) +{ + Instance &instance = *static_cast(aInstance); + + instance.GetThreadNetif().SetAddressCallback(aCallback, aCallbackContext); +} + bool otIp6IsReceiveFilterEnabled(otInstance *aInstance) { Instance &instance = *static_cast(aInstance); diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index 8b7fcf95c..cbfe8e30c 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -119,7 +119,7 @@ void Dhcp6Client::UpdateAddresses(otInstance * aInstance, if (!found) { - otIp6RemoveUnicastAddress(aInstance, &(address->mAddress.mAddress)); + GetNetif().RemoveUnicastAddress(*static_cast(&address->mAddress)); RemoveIdentityAssociation(config.mRloc16, config.mPrefix); memset(address, 0, sizeof(*address)); } @@ -689,7 +689,7 @@ otError Dhcp6Client::ProcessIaAddress(Message &aMessage, uint16_t aOffset) address->mValidLifetime = option.GetValidLifetime(); address->mAddress.mPreferred = address->mPreferredLifetime != 0; address->mAddress.mValid = address->mValidLifetime != 0; - otIp6AddUnicastAddress(&GetNetif().GetInstance(), &address->mAddress); + GetNetif().AddUnicastAddress(*static_cast(&address->mAddress)); break; } } diff --git a/src/core/net/netif.cpp b/src/core/net/netif.cpp index 7805ba373..17da7915e 100644 --- a/src/core/net/netif.cpp +++ b/src/core/net/netif.cpp @@ -87,6 +87,8 @@ Netif::Netif(Instance &aInstance, int8_t aInterfaceId) , mInterfaceId(aInterfaceId) , mMulticastPromiscuous(false) , mNext(NULL) + , mAddressCallback(NULL) + , mAddressCallbackContext(NULL) { for (size_t i = 0; i < OT_ARRAY_LENGTH(mExtUnicastAddresses); i++) { @@ -124,6 +126,15 @@ void Netif::SubscribeAllNodesMulticast(void) mMulticastAddresses = static_cast( const_cast(&kLinkLocalAllNodesMulticastAddress)); + if (mAddressCallback != NULL) + { + for (const otNetifMulticastAddress *entry = &kLinkLocalAllNodesMulticastAddress; entry != NULL; + entry = entry->mNext) + { + mAddressCallback(&entry->mAddress, kMulticastPrefixLength, true, mAddressCallbackContext); + } + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); } @@ -133,6 +144,15 @@ void Netif::UnsubscribeAllNodesMulticast(void) mMulticastAddresses = NULL; + if (mAddressCallback != NULL) + { + for (const otNetifMulticastAddress *entry = &kLinkLocalAllNodesMulticastAddress; entry != NULL; + entry = entry->mNext) + { + mAddressCallback(&entry->mAddress, kMulticastPrefixLength, false, mAddressCallbackContext); + } + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } @@ -162,6 +182,15 @@ otError Netif::SubscribeAllRoutersMulticast(void) } } + if (mAddressCallback != NULL) + { + for (const otNetifMulticastAddress *entry = &kLinkLocalAllRoutersMulticastAddress; + entry != &kLinkLocalAllNodesMulticastAddress; entry = entry->mNext) + { + mAddressCallback(&entry->mAddress, kMulticastPrefixLength, true, mAddressCallbackContext); + } + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: @@ -194,6 +223,15 @@ exit: if (error != OT_ERROR_NOT_FOUND) { + if (mAddressCallback != NULL) + { + for (const otNetifMulticastAddress *entry = &kLinkLocalAllRoutersMulticastAddress; + entry != &kLinkLocalAllNodesMulticastAddress; entry = entry->mNext) + { + mAddressCallback(&entry->mAddress, kMulticastPrefixLength, false, mAddressCallbackContext); + } + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } @@ -214,6 +252,12 @@ otError Netif::SubscribeMulticast(NetifMulticastAddress &aAddress) aAddress.mNext = mMulticastAddresses; mMulticastAddresses = &aAddress; + + if (mAddressCallback != NULL) + { + mAddressCallback(&aAddress.mAddress, kMulticastPrefixLength, true, mAddressCallbackContext); + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_SUBSRCRIBED); exit: @@ -247,6 +291,11 @@ exit: if (error != OT_ERROR_NOT_FOUND) { + if (mAddressCallback != NULL) + { + mAddressCallback(&aAddress.mAddress, kMulticastPrefixLength, false, mAddressCallbackContext); + } + GetNotifier().Signal(OT_CHANGED_IP6_MULTICAST_UNSUBSRCRIBED); } @@ -366,6 +415,12 @@ void Netif::UnsubscribeAllExternalMulticastAddresses(void) } } +void Netif::SetAddressCallback(otIp6AddressCallback aCallback, void *aCallbackContext) +{ + mAddressCallback = aCallback; + mAddressCallbackContext = aCallbackContext; +} + otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress) { otError error = OT_ERROR_NONE; @@ -381,6 +436,11 @@ otError Netif::AddUnicastAddress(NetifUnicastAddress &aAddress) aAddress.mNext = mUnicastAddresses; mUnicastAddresses = &aAddress; + if (mAddressCallback != NULL) + { + mAddressCallback(&aAddress.mAddress, aAddress.mPrefixLength, true, mAddressCallbackContext); + } + GetNotifier().Signal(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_ADDED : OT_CHANGED_IP6_ADDRESS_ADDED); exit: @@ -414,6 +474,11 @@ exit: if (error != OT_ERROR_NOT_FOUND) { + if (mAddressCallback != NULL) + { + mAddressCallback(&aAddress.mAddress, aAddress.mPrefixLength, false, mAddressCallbackContext); + } + GetNotifier().Signal(aAddress.mRloc ? OT_CHANGED_THREAD_RLOC_REMOVED : OT_CHANGED_IP6_ADDRESS_REMOVED); } diff --git a/src/core/net/netif.hpp b/src/core/net/netif.hpp index 6f3222986..ffb23c614 100644 --- a/src/core/net/netif.hpp +++ b/src/core/net/netif.hpp @@ -209,6 +209,15 @@ public: */ int8_t GetInterfaceId(void) const { return mInterfaceId; } + /** + * 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 a pointer to the list of unicast addresses. * @@ -463,12 +472,20 @@ protected: void UnsubscribeAllNodesMulticast(void); private: + enum + { + kMulticastPrefixLength = 128, ///< Multicast prefix length used to notify internal address changes. + }; + NetifUnicastAddress * mUnicastAddresses; NetifMulticastAddress *mMulticastAddresses; int8_t mInterfaceId; bool mMulticastPromiscuous; Netif * mNext; + otIp6AddressCallback mAddressCallback; + void * mAddressCallbackContext; + NetifUnicastAddress mExtUnicastAddresses[OPENTHREAD_CONFIG_MAX_EXT_IP_ADDRS]; NetifMulticastAddress mExtMulticastAddresses[OPENTHREAD_CONFIG_MAX_EXT_MULTICAST_IP_ADDRS]; diff --git a/src/core/utils/slaac_address.cpp b/src/core/utils/slaac_address.cpp index ccd3d81c4..96f13cc3e 100644 --- a/src/core/utils/slaac_address.cpp +++ b/src/core/utils/slaac_address.cpp @@ -40,6 +40,7 @@ #include "common/code_utils.hpp" #include "common/debug.hpp" +#include "common/instance.hpp" #include "common/random.hpp" #include "crypto/sha256.hpp" #include "mac/mac.hpp" @@ -87,7 +88,8 @@ void Slaac::UpdateAddresses(otInstance * aInstance, if (!found) { - otIp6RemoveUnicastAddress(aInstance, &address->mAddress); + static_cast(aInstance)->GetThreadNetif().RemoveUnicastAddress( + *static_cast(address)); address->mValid = false; } } @@ -116,7 +118,8 @@ void Slaac::UpdateAddresses(otInstance * aInstance, if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength && config.mPrefix.mLength == address->mPrefixLength) { - otIp6AddUnicastAddress(aInstance, address); + static_cast(aInstance)->GetThreadNetif().AddUnicastAddress( + *static_cast(address)); found = true; break; } @@ -145,7 +148,8 @@ void Slaac::UpdateAddresses(otInstance * aInstance, CreateRandomIid(aInstance, address, aContext); } - otIp6AddUnicastAddress(aInstance, address); + static_cast(aInstance)->GetThreadNetif().AddUnicastAddress( + *static_cast(address)); break; } }