diff --git a/include/openthread/instance.h b/include/openthread/instance.h index f47b5c27e..06676156c 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 (22) +#define OPENTHREAD_API_VERSION (23) /** * @addtogroup api-instance diff --git a/include/openthread/thread.h b/include/openthread/thread.h index 73012f472..35431f125 100644 --- a/include/openthread/thread.h +++ b/include/openthread/thread.h @@ -805,6 +805,37 @@ void otThreadRegisterParentResponseCallback(otInstance * aInst otThreadParentResponseCallback aCallback, void * aContext); +/** + * This structure represents the Thread Discovery Request data. + * + */ +typedef struct otThreadDiscoveryRequestInfo +{ + otExtAddress mExtAddress; ///< IEEE 802.15.4 Extended Address of the requester + uint8_t mVersion : 4; ///< Thread version. + bool mIsJoiner : 1; ///< Whether is from joiner. +} otThreadDiscoveryRequestInfo; + +/** + * This function pointer is called every time an MLE Discovery Request message is received. + * + * @param[in] aInfo A pointer to the Discovery Request info data. + * @param[in] aContext A pointer to callback application-specific context. + * + */ +typedef void (*otThreadDiscoveryRequestCallback)(const otThreadDiscoveryRequestInfo *aInfo, void *aContext); + +/** + * This function sets a callback to receive MLE Discovery Request data. + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aCallback A pointer to a function that is called upon receiving an MLE Discovery Request message. + * @param[in] aContext A pointer to callback application-specific context. + * + */ +void otThreadSetDiscoveryRequestCallback(otInstance * aInstnace, + otThreadDiscoveryRequestCallback aCallback, + void * aContext); /** * @} * diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp index 7b865cdba..470554c8e 100644 --- a/src/cli/cli.cpp +++ b/src/cli/cli.cpp @@ -287,6 +287,9 @@ Interpreter::Interpreter(Instance *aInstance) #if OPENTHREAD_FTD || OPENTHREAD_CONFIG_TMF_NETWORK_DIAG_MTD_ENABLE otThreadSetReceiveDiagnosticGetCallback(mInstance, &Interpreter::HandleDiagnosticGetResponse, this); #endif +#if OPENTHREAD_FTD + otThreadSetDiscoveryRequestCallback(mInstance, &Interpreter::HandleDiscoveryRequest, this); +#endif mIcmpHandler.mReceiveCallback = Interpreter::HandleIcmpReceive; mIcmpHandler.mContext = this; @@ -4590,6 +4593,13 @@ void Interpreter::SignalPingReply(const Ip6::Address &aPeerAddress, #endif } +void Interpreter::HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo) +{ + mServer->OutputFormat("~ Discovery Request from "); + OutputBytes(aInfo.mExtAddress.m8, sizeof(aInfo.mExtAddress.m8)); + mServer->OutputFormat(": version=%u,joiner=%d\r\n", aInfo.mVersion, aInfo.mIsJoiner); +} + extern "C" void otCliSetUserCommands(const otCliCommand *aUserCommands, uint8_t aLength) { Server::sServer->GetInterpreter().SetUserCommands(aUserCommands, aLength); diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp index 236e21a8f..d57c31c1f 100644 --- a/src/cli/cli.hpp +++ b/src/cli/cli.hpp @@ -429,6 +429,12 @@ private: #endif static Interpreter &GetOwner(OwnerLocator &aOwnerLocator); + static void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo *aInfo, void *aContext) + { + static_cast(aContext)->HandleDiscoveryRequest(*aInfo); + } + void HandleDiscoveryRequest(const otThreadDiscoveryRequestInfo &aInfo); + static const struct Command sCommands[]; const otCliCommand * mUserCommands; uint8_t mUserCommandsLength; diff --git a/src/core/api/thread_ftd_api.cpp b/src/core/api/thread_ftd_api.cpp index 518d2eabd..e478092b0 100644 --- a/src/core/api/thread_ftd_api.cpp +++ b/src/core/api/thread_ftd_api.cpp @@ -383,4 +383,12 @@ void otThreadRegisterNeighborTableCallback(otInstance *aInstance, otNeighborTabl instance.Get().RegisterNeighborTableChangedCallback(aCallback); } +void otThreadSetDiscoveryRequestCallback(otInstance * aInstance, + otThreadDiscoveryRequestCallback aCallback, + void * aContext) +{ + Instance &instance = *static_cast(aInstance); + + instance.Get().SetDiscoveryRequestCallback(aCallback, aContext); +} #endif // OPENTHREAD_FTD diff --git a/src/core/meshcop/meshcop_tlvs.hpp b/src/core/meshcop/meshcop_tlvs.hpp index 7f3e4d528..1c6f5fe36 100644 --- a/src/core/meshcop/meshcop_tlvs.hpp +++ b/src/core/meshcop/meshcop_tlvs.hpp @@ -1616,6 +1616,18 @@ public: return GetLength() <= sizeof(mProvisioningUrl) ? GetLength() : sizeof(mProvisioningUrl); } + /** + * This method indicates whether or not the TLV appears to be well-formed. + * + * @retval TRUE If the TLV appears to be well-formed. + * @retval FALSE If the TLV does not appear to be well-formed. + * + */ + bool IsValid(void) const + { + return GetType() == kProvisioningUrl && mProvisioningUrl[GetProvisioningUrlLength()] == '\0'; + } + /** * This method returns the Provisioning URL value. * diff --git a/src/core/thread/mle_router.cpp b/src/core/thread/mle_router.cpp index 81d726d78..bf351a7da 100644 --- a/src/core/thread/mle_router.cpp +++ b/src/core/thread/mle_router.cpp @@ -88,6 +88,8 @@ MleRouter::MleRouter(Instance &aInstance) #if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE , mMaxChildIpAddresses(0) #endif + , mDiscoveryRequestCallback(nullptr) + , mDiscoveryRequestCallbackContext(nullptr) { mDeviceMode.Set(mDeviceMode.Get() | DeviceMode::kModeFullThreadDevice | DeviceMode::kModeFullNetworkData); @@ -2860,6 +2862,8 @@ void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::Messa LogMleMessage("Receive Discovery Request", aMessageInfo.GetPeerAddr()); + discoveryRequest.SetLength(0); + // only Routers and REEDs respond VerifyOrExit(IsRouterEligible(), error = OT_ERROR_INVALID_STATE); @@ -2880,20 +2884,6 @@ void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::Messa aMessage.Read(offset, sizeof(discoveryRequest), &discoveryRequest); VerifyOrExit(discoveryRequest.IsValid(), error = OT_ERROR_PARSE); - if (discoveryRequest.IsJoiner()) - { -#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE - if (!mSteeringData.IsEmpty()) - { - break; - } - else // if steering data is not set out of band, fall back to network data -#endif - { - VerifyOrExit(Get().IsJoiningEnabled(), error = OT_ERROR_SECURITY); - } - } - break; case MeshCoP::Tlv::kExtendedPanId: @@ -2909,6 +2899,33 @@ void MleRouter::HandleDiscoveryRequest(const Message &aMessage, const Ip6::Messa offset += sizeof(meshcopTlv) + meshcopTlv.GetLength(); } + if (discoveryRequest.IsValid()) + { + if (mDiscoveryRequestCallback != nullptr) + { + otThreadDiscoveryRequestInfo info; + + aMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(*static_cast(&info.mExtAddress)); + info.mVersion = discoveryRequest.GetVersion(); + info.mIsJoiner = discoveryRequest.IsJoiner(); + + mDiscoveryRequestCallback(&info, mDiscoveryRequestCallbackContext); + } + + if (discoveryRequest.IsJoiner()) + { +#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE + if (!mSteeringData.IsEmpty()) + { + } + else // if steering data is not set out of band, fall back to network data +#endif + { + VerifyOrExit(Get().IsJoiningEnabled(), error = OT_ERROR_SECURITY); + } + } + } + error = SendDiscoveryResponse(aMessageInfo.GetPeerAddr(), aMessage.GetPanId()); exit: diff --git a/src/core/thread/mle_router.hpp b/src/core/thread/mle_router.hpp index ec75f1bee..ec1632477 100644 --- a/src/core/thread/mle_router.hpp +++ b/src/core/thread/mle_router.hpp @@ -490,6 +490,19 @@ public: mNeighborTableChangedCallback = aCallback; } + /** + * This function sets the callback that is called when processing an MLE Discovery Request message. + * + * @param[in] aCallback A pointer to a function that is called to deliver MLE Discovery Request data. + * @param[in] aContext A pointer to application-specific context. + * + */ + void SetDiscoveryRequestCallback(otThreadDiscoveryRequestCallback aCallback, void *aContext) + { + mDiscoveryRequestCallback = aCallback; + mDiscoveryRequestCallbackContext = aContext; + } + /** * This method signals a "neighbor table changed" events (invoking the registered callback function). * @@ -706,6 +719,9 @@ private: #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE MeshCoP::SteeringData mSteeringData; #endif + + otThreadDiscoveryRequestCallback mDiscoveryRequestCallback; + void * mDiscoveryRequestCallbackContext; }; #endif // OPENTHREAD_FTD diff --git a/tests/scripts/expect/cli-scan-discover.exp b/tests/scripts/expect/cli-scan-discover.exp index 5d0b7c9ff..04fe2b451 100755 --- a/tests/scripts/expect/cli-scan-discover.exp +++ b/tests/scripts/expect/cli-scan-discover.exp @@ -88,7 +88,16 @@ wait_for "" "Done" send "discover something_invalid\n" expect "Error 7: InvalidArgs" +set spawn_id $spawn_1 +expect "version=2,joiner=0" + set spawn_id $spawn_3 +send "joiner start 123456\n" +set timeout 10 +expect "NotFound" dispose +set spawn_id $spawn_1 +expect "version=2,joiner=1" + dispose_nodes