diff --git a/src/core/meshcop/border_agent.cpp b/src/core/meshcop/border_agent.cpp index 96255231a..07ca33d76 100644 --- a/src/core/meshcop/border_agent.cpp +++ b/src/core/meshcop/border_agent.cpp @@ -535,10 +535,10 @@ Error Manager::EvictActiveCommissioner(void) { Error error = kErrorNone; uint16_t sessionId; - uint16_t baRloc16; OwnedPtr message; - SuccessOrExit(error = Get().FindBorderAgentRloc(baRloc16)); + VerifyOrExit(Get().HasBorderAgentRloc(), error = kErrorNotFound); + SuccessOrExit(error = Get().FindCommissioningSessionId(sessionId)); message.Reset(Get().AllocateAndInitPriorityConfirmablePostMessage(kUriLeaderKeepAlive)); diff --git a/src/core/meshcop/border_agent_admitter.cpp b/src/core/meshcop/border_agent_admitter.cpp index 3428dc59c..3e4d3c02a 100644 --- a/src/core/meshcop/border_agent_admitter.cpp +++ b/src/core/meshcop/border_agent_admitter.cpp @@ -571,7 +571,7 @@ void Admitter::CommissionerPetitioner::SendPetitionIfNoOtherCommissioner(void) OT_ASSERT(mState == kToPetition || mState == kRejected); - if (Get().FindInCommissioningData() != nullptr) + if (Get().HasBorderAgentRloc()) { SetState(kRejected); ExitNow(); diff --git a/src/core/meshcop/meshcop_leader.cpp b/src/core/meshcop/meshcop_leader.cpp index fec1506af..52897c9e6 100644 --- a/src/core/meshcop/meshcop_leader.cpp +++ b/src/core/meshcop/meshcop_leader.cpp @@ -112,10 +112,9 @@ exit: template <> void Leader::HandleTmf(Coap::Msg &aMsg) { - uint8_t state; - uint16_t sessionId; - BorderAgentLocatorTlv *borderAgentLocator; - StateTlv::State responseState; + uint8_t state; + uint16_t sessionId; + StateTlv::State responseState; LogInfo("Received %s", UriToString()); @@ -125,9 +124,7 @@ template <> void Leader::HandleTmf(Coap::Msg &aMsg) SuccessOrExit(Tlv::Find(aMsg.mMessage, sessionId)); - borderAgentLocator = Get().FindInCommissioningData(); - - if ((borderAgentLocator == nullptr) || (sessionId != mSessionId)) + if (!Get().HasBorderAgentRloc() || (sessionId != mSessionId)) { responseState = StateTlv::kReject; } @@ -138,13 +135,7 @@ template <> void Leader::HandleTmf(Coap::Msg &aMsg) } else { - uint16_t rloc = aMsg.mMessageInfo.GetPeerAddr().GetIid().GetLocator(); - - if (borderAgentLocator->GetBorderAgentLocator() != rloc) - { - borderAgentLocator->SetBorderAgentLocator(rloc); - Get().IncrementVersion(); - } + Get().UpdateBorderAgentRloc(aMsg.mMessageInfo.GetPeerAddr().GetIid().GetLocator()); responseState = StateTlv::kAccept; mTimer.Start(kLeaderPetitionTimeout); diff --git a/src/core/thread/energy_scan_server.cpp b/src/core/thread/energy_scan_server.cpp index 4e79f51a6..ca8c9fce7 100644 --- a/src/core/thread/energy_scan_server.cpp +++ b/src/core/thread/energy_scan_server.cpp @@ -174,10 +174,8 @@ exit: void EnergyScanServer::HandleNotifierEvents(Events aEvents) { - uint16_t borderAgentRloc; - if (aEvents.Contains(kEventThreadNetdataChanged) && (mReportMessage != nullptr) && - Get().FindBorderAgentRloc(borderAgentRloc) != kErrorNone) + !Get().HasBorderAgentRloc()) { Stop(); } diff --git a/src/core/thread/network_data_leader.cpp b/src/core/thread/network_data_leader.cpp index 3c9fa4791..1846e69e5 100644 --- a/src/core/thread/network_data_leader.cpp +++ b/src/core/thread/network_data_leader.cpp @@ -505,26 +505,36 @@ const CommissioningDataTlv *Leader::FindCommissioningData(void) const return NetworkDataTlv::Find(GetTlvsStart(), GetTlvsEnd()); } -const MeshCoP::Tlv *Leader::FindCommissioningDataSubTlv(uint8_t aType) const +Error Leader::FindCommissioningDataSubTlv(uint8_t aType, CommissioningDataSubTlvInfo &aSubTlvInfo) const { - const MeshCoP::Tlv *subTlv = nullptr; + Error error = kErrorNotFound; const NetworkDataTlv *dataTlv = FindCommissioningData(); + const MeshCoP::Tlv *subTlv; VerifyOrExit(dataTlv != nullptr); + subTlv = As(Tlv::FindTlv(dataTlv->GetValue(), dataTlv->GetLength(), aType)); + VerifyOrExit(subTlv != nullptr); + + aSubTlvInfo.mTlv = subTlv; + aSubTlvInfo.mValue = subTlv->GetValue(); + aSubTlvInfo.mLength = subTlv->IsExtended() ? As(subTlv)->GetLength() : subTlv->GetLength(); + + error = kErrorNone; exit: - return subTlv; + return error; } Error Leader::ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::Type aType, uint16_t &aValue) const { - Error error = kErrorNone; - const MeshCoP::Tlv *subTlv = FindCommissioningDataSubTlv(aType); + Error error; + CommissioningDataSubTlvInfo subTlvInfo; - VerifyOrExit(subTlv != nullptr, error = kErrorNotFound); - VerifyOrExit(subTlv->GetLength() >= sizeof(uint16_t), error = kErrorParse); - aValue = BigEndian::ReadUint16(subTlv->GetValue()); + SuccessOrExit(error = FindCommissioningDataSubTlv(aType, subTlvInfo)); + + VerifyOrExit(subTlvInfo.mLength >= sizeof(uint16_t), error = kErrorParse); + aValue = BigEndian::ReadUint16(subTlvInfo.mValue); exit: return error; @@ -583,16 +593,14 @@ Coap::Message *Leader::ProcessCommissionerGetRequest(const Coap::Message &aMessa while (!offsetRange.IsEmpty()) { - uint8_t type; - const MeshCoP::Tlv *subTlv; + uint8_t type; + CommissioningDataSubTlvInfo subTlvInfo; IgnoreError(aMessage.ReadAndAdvance(offsetRange, type)); - subTlv = FindCommissioningDataSubTlv(type); - - if (subTlv != nullptr) + if (FindCommissioningDataSubTlv(type, subTlvInfo) == kErrorNone) { - SuccessOrExit(error = subTlv->AppendTo(*response)); + SuccessOrExit(error = subTlvInfo.mTlv->AppendTo(*response)); } } } @@ -618,6 +626,13 @@ Error Leader::FindBorderAgentRloc(uint16_t &aRloc16) const return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16); } +bool Leader::HasBorderAgentRloc(void) const +{ + uint16_t rloc16; + + return (FindBorderAgentRloc(rloc16) == kErrorNone); +} + Error Leader::FindCommissioningSessionId(uint16_t &aSessionId) const { return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kCommissionerSessionId, aSessionId); @@ -630,11 +645,14 @@ Error Leader::FindJoinerUdpPort(uint16_t &aPort) const Error Leader::FindSteeringData(MeshCoP::SteeringData &aSteeringData) const { - Error error = kErrorNone; - const MeshCoP::SteeringDataTlv *steeringDataTlv = FindInCommissioningData(); + Error error = kErrorNotFound; + CommissioningDataSubTlvInfo subTlvInfo; + uint16_t steeringDataLength; - VerifyOrExit(steeringDataTlv != nullptr, error = kErrorNotFound); - error = steeringDataTlv->CopyTo(aSteeringData); + SuccessOrExit(FindCommissioningDataSubTlv(MeshCoP::Tlv::kSteeringData, subTlvInfo)); + + steeringDataLength = Min(subTlvInfo.mLength, MeshCoP::SteeringData::kMaxLength); + error = aSteeringData.Init(static_cast(steeringDataLength), subTlvInfo.mValue); exit: return error; diff --git a/src/core/thread/network_data_leader.hpp b/src/core/thread/network_data_leader.hpp index 1195da4b1..1b64a1c90 100644 --- a/src/core/thread/network_data_leader.hpp +++ b/src/core/thread/network_data_leader.hpp @@ -186,30 +186,6 @@ public: */ Coap::Message *ProcessCommissionerGetRequest(const Coap::Message &aMessage) const; - /** - * Searches for given sub-TLV in Commissioning Data TLV. - * - * @tparam SubTlvType The sub-TLV type to search for. - * - * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists. - */ - template const SubTlvType *FindInCommissioningData(void) const - { - return As(FindCommissioningDataSubTlv(SubTlvType::kType)); - } - - /** - * Searches for given sub-TLV in Commissioning Data TLV. - * - * @tparam SubTlvType The sub-TLV type to search for. - * - * @returns A pointer to the Commissioning Data Sub-TLV or `nullptr` if no such sub-TLV exists. - */ - template SubTlvType *FindInCommissioningData(void) - { - return As(FindCommissioningDataSubTlv(SubTlvType::kType)); - } - /** * Finds and reads the Commissioning Session ID in Commissioning Data TLV. * @@ -232,6 +208,14 @@ public: */ Error FindBorderAgentRloc(uint16_t &aRloc16) const; + /** + * Indicates whether the Commissioning Data contains a valid Border Agent Locator sub-TLV. + * + * @retval TRUE The Commissioning Data contains a valid Border Agent Locator sub-TLV. + * @retval FALSE The Commissioning Data does not contain a valid Border Agent Locator sub-TLV. + */ + bool HasBorderAgentRloc(void) const; + /** * Finds and reads the Joiner UDP Port in Commissioning Data TLV. * @@ -356,6 +340,18 @@ public: */ void IncrementVersionAndStableVersion(void); + /** + * Updates the Border Agent Locator sub-TLV in the Commissioning Data. + * + * If the Border Agent Locator sub-TLV is present in the Commissioning Data and its value differs from @p aRloc16, + * this method updates its value in-place and increments the Thread Network Data version. If the sub-TLV is not + * present, or if its value already matches @p aRloc16, no changes are made and the Network Data version is not + * incremented. + * + * @param[in] aRloc16 The new Border Agent RLOC16 value. + */ + void UpdateBorderAgentRloc(uint16_t aRloc16); + /** * Performs anycast ALOC route lookup using the Network Data. * @@ -432,6 +428,13 @@ private: typedef bool (&EntryChecker)(const BorderRouterEntry &aEntry); + struct CommissioningDataSubTlvInfo + { + const Tlv *mTlv; + const uint8_t *mValue; + uint16_t mLength; + }; + const PrefixTlv *FindNextMatchingPrefixTlv(const Ip6::Address &aAddress, const PrefixTlv *aPrevTlv) const; const PrefixTlv *FindPrefixTlvForContextId(uint8_t aContextId, const ContextTlv *&aContextTlv) const; @@ -453,11 +456,7 @@ private: void SignalNetDataChanged(void); const CommissioningDataTlv *FindCommissioningData(void) const; CommissioningDataTlv *FindCommissioningData(void) { return AsNonConst(AsConst(this)->FindCommissioningData()); } - const MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) const; - MeshCoP::Tlv *FindCommissioningDataSubTlv(uint8_t aType) - { - return AsNonConst(AsConst(this)->FindCommissioningDataSubTlv(aType)); - } + Error FindCommissioningDataSubTlv(uint8_t aType, CommissioningDataSubTlvInfo &aSubTlvInfo) const; #if OPENTHREAD_FTD static constexpr uint32_t kMaxNetDataSyncWait = 60 * 1000; // Maximum time to wait for netdata sync in msec. diff --git a/src/core/thread/network_data_leader_ftd.cpp b/src/core/thread/network_data_leader_ftd.cpp index e4c37c9d1..16e8a4f25 100644 --- a/src/core/thread/network_data_leader_ftd.cpp +++ b/src/core/thread/network_data_leader_ftd.cpp @@ -99,6 +99,22 @@ exit: return; } +void Leader::UpdateBorderAgentRloc(uint16_t aRloc16) +{ + CommissioningDataSubTlvInfo subTlvInfo; + + SuccessOrExit(FindCommissioningDataSubTlv(MeshCoP::Tlv::kBorderAgentLocator, subTlvInfo)); + + VerifyOrExit(subTlvInfo.mLength >= sizeof(uint16_t)); + VerifyOrExit(BigEndian::ReadUint16(subTlvInfo.mValue) != aRloc16); + BigEndian::WriteUint16(aRloc16, AsNonConst(subTlvInfo.mValue)); + + IncrementVersion(); + +exit: + return; +} + Error Leader::AnycastLookup(uint16_t aAloc16, uint16_t &aRloc16) const { Error error = kErrorNone; @@ -1285,7 +1301,6 @@ void Leader::HandleNetworkDataRestoredAfterReset(void) const PrefixTlv *prefix; TlvIterator tlvIterator(GetTlvsStart(), GetTlvsEnd()); ChangedFlags flags; - uint16_t rloc16; uint16_t sessionId; Rlocs rlocs; @@ -1339,7 +1354,7 @@ void Leader::HandleNetworkDataRestoredAfterReset(void) Get().SetSessionId(sessionId); } - if (FindBorderAgentRloc(rloc16) == kErrorNone) + if (HasBorderAgentRloc()) { Get().SetEmptyCommissionerData(); } diff --git a/tests/nexus/test_border_admitter.cpp b/tests/nexus/test_border_admitter.cpp index 213fd15c0..61a03c41b 100644 --- a/tests/nexus/test_border_admitter.cpp +++ b/tests/nexus/test_border_admitter.cpp @@ -721,7 +721,7 @@ void TestBorderAdmitterEnrollerInteraction(void) VerifyOrQuit(admitter.Get().IsPrimeAdmitter()); VerifyOrQuit(!admitter.Get().IsActiveCommissioner()); - VerifyOrQuit(admitter.Get().FindBorderAgentRloc(rloc16) == kErrorNotFound); + VerifyOrQuit(!admitter.Get().HasBorderAgentRloc()); nexus.AdvanceTime(10 * Time::kOneSecondInMsec); @@ -933,7 +933,7 @@ void TestBorderAdmitterEnrollerInteraction(void) VerifyOrQuit(admitter.Get().IsPrimeAdmitter()); VerifyOrQuit(!admitter.Get().IsActiveCommissioner()); - VerifyOrQuit(admitter.Get().FindBorderAgentRloc(rloc16) == kErrorNotFound); + VerifyOrQuit(!admitter.Get().HasBorderAgentRloc()); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Log("Re-establish DTLS session");