Skip to content

Commit

Permalink
[border-agent] directly respond to MGMT_COMMISSIONER_GET from non-act…
Browse files Browse the repository at this point in the history
…ive commissioner (openthread#10632)
  • Loading branch information
librasungirl authored Aug 27, 2024
1 parent 3c6b8a3 commit abb6934
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 57 deletions.
35 changes: 20 additions & 15 deletions src/core/meshcop/border_agent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ void BorderAgent::HandleTmf<kUriCommissionerPetition>(Coap::Message &aMessage, c
template <>
void BorderAgent::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
IgnoreError(ForwardToLeader(aMessage, aMessageInfo, kUriCommissionerGet));
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriCommissionerGet);
}

template <>
Expand All @@ -479,7 +479,7 @@ void BorderAgent::HandleTmf<kUriCommissionerSet>(Coap::Message &aMessage, const

template <> void BorderAgent::HandleTmf<kUriActiveGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
HandleTmfDatasetGet(aMessage, aMessageInfo, Dataset::kActive);
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriActiveGet);
mCounters.mMgmtActiveGets++;
}

Expand All @@ -490,7 +490,7 @@ template <> void BorderAgent::HandleTmf<kUriActiveSet>(Coap::Message &aMessage,

template <> void BorderAgent::HandleTmf<kUriPendingGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
HandleTmfDatasetGet(aMessage, aMessageInfo, Dataset::kPending);
HandleTmfDatasetGet(aMessage, aMessageInfo, kUriPendingGet);
mCounters.mMgmtPendingGets++;
}

Expand Down Expand Up @@ -610,42 +610,47 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes
return error;
}

void BorderAgent::HandleTmfDatasetGet(Coap::Message &aMessage,
const Ip6::MessageInfo &aMessageInfo,
Dataset::Type aType)
void BorderAgent::HandleTmfDatasetGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Uri aUri)
{
Error error = kErrorNone;
Coap::Message *response = nullptr;

if (mState == kStateAccepted)
{
Uri uri = (aType == Dataset::kActive) ? kUriActiveGet : kUriPendingGet;

IgnoreError(ForwardToLeader(aMessage, aMessageInfo, uri));
IgnoreError(ForwardToLeader(aMessage, aMessageInfo, aUri));
ExitNow();
}

// When processing `MGMT_GET` request directly on Border Agent,
// the Security Policy flags (O-bit) should be ignore to allow
// the commissioner candidate to get the full Operational Dataset.

if (aType == Dataset::kActive)
switch (aUri)
{
case kUriActiveGet:
response = Get<ActiveDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
}
else
{
break;

case kUriPendingGet:
response = Get<PendingDatasetManager>().ProcessGetRequest(aMessage, DatasetManager::kIgnoreSecurityPolicyFlags);
break;

case kUriCommissionerGet:
response = Get<NetworkData::Leader>().ProcessCommissionerGetRequest(aMessage);
break;

default:
break;
}

VerifyOrExit(response != nullptr, error = kErrorParse);

SuccessOrExit(error = Get<Tmf::SecureAgent>().SendMessage(*response, aMessageInfo));

LogInfo("Sent %sGet response to non-active commissioner", Dataset::TypeToString(aType));
LogInfo("Sent %s response to non-active commissioner", PathForUri(aUri));

exit:
LogWarnOnError(error, "send Active/PendingGet response");
LogWarnOnError(error, "send Active/Pending/CommissionerGet response");
FreeMessageOnError(response, error);
}

Expand Down
2 changes: 1 addition & 1 deletion src/core/meshcop/border_agent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ class BorderAgent : public InstanceLocator, private NonCopyable

template <Uri kUri> void HandleTmf(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);

void HandleTmfDatasetGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Dataset::Type aType);
void HandleTmfDatasetGet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Uri aUri);
void HandleTimeout(void);

#if OPENTHREAD_CONFIG_BORDER_AGENT_EPHEMERAL_KEY_ENABLE
Expand Down
46 changes: 46 additions & 0 deletions src/core/thread/network_data_leader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,52 @@ void Leader::GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) co
return;
}

Coap::Message *Leader::ProcessCommissionerGetRequest(const Coap::Message &aMessage) const
{
Error error = kErrorNone;
Coap::Message *response = nullptr;
OffsetRange offsetRange;

response = Get<Tmf::Agent>().NewPriorityResponseMessage(aMessage);
VerifyOrExit(response != nullptr, error = kErrorNoBufs);

if (Tlv::FindTlvValueOffsetRange(aMessage, MeshCoP::Tlv::kGet, offsetRange) == kErrorNone)
{
// Append the requested sub-TLV types given in Get TLV.

while (!offsetRange.IsEmpty())
{
uint8_t type;
const MeshCoP::Tlv *subTlv;

IgnoreError(aMessage.Read(offsetRange, type));
offsetRange.AdvanceOffset(sizeof(type));

subTlv = FindCommissioningDataSubTlv(type);

if (subTlv != nullptr)
{
SuccessOrExit(error = subTlv->AppendTo(*response));
}
}
}
else
{
// Append all sub-TLVs in the Commissioning Data.

const CommissioningDataTlv *dataTlv = FindCommissioningData();

if (dataTlv != nullptr)
{
SuccessOrExit(error = response->AppendBytes(dataTlv->GetValue(), dataTlv->GetLength()));
}
}

exit:
FreeAndNullMessageOnError(response, error);
return response;
}

Error Leader::FindBorderAgentRloc(uint16_t &aRloc16) const
{
return ReadCommissioningDataUint16SubTlv(MeshCoP::Tlv::kBorderAgentLocator, aRloc16);
Expand Down
10 changes: 10 additions & 0 deletions src/core/thread/network_data_leader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,16 @@ class Leader : public MutableNetworkData, private NonCopyable
*/
void GetCommissioningDataset(MeshCoP::CommissioningDataset &aDataset) const;

/**
* Processes a MGMT_COMMISSIONER_GET request message and prepares the response.
*
* @param[in] aRequest The MGMT_COMMISSIONER_GET request message.
*
* @returns The prepared response, or `nullptr` if fails to parse the request or cannot allocate message.
*
*/
Coap::Message *ProcessCommissionerGetRequest(const Coap::Message &aMessage) const;

/**
* Searches for given sub-TLV in Commissioning Data TLV.
*
Expand Down
50 changes: 9 additions & 41 deletions src/core/thread/network_data_leader_ftd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,53 +317,21 @@ template <> void Leader::HandleTmf<kUriCommissionerSet>(Coap::Message &aMessage,

template <> void Leader::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
Error error = kErrorNone;
Coap::Message *response = nullptr;
OffsetRange offsetRange;

VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync);

response = Get<Tmf::Agent>().NewPriorityResponseMessage(aMessage);
VerifyOrExit(response != nullptr);

if (Tlv::FindTlvValueOffsetRange(aMessage, MeshCoP::Tlv::kGet, offsetRange) == kErrorNone)
{
// Append the requested sub-TLV types given in Get TLV.

while (!offsetRange.IsEmpty())
{
uint8_t type;
const MeshCoP::Tlv *subTlv;

IgnoreError(aMessage.Read(offsetRange, type));
offsetRange.AdvanceOffset(sizeof(type));

subTlv = FindCommissioningDataSubTlv(type);

if (subTlv != nullptr)
{
SuccessOrExit(subTlv->AppendTo(*response));
}
}
}
else
{
// Append all sub-TLVs in the Commissioning Data.

CommissioningDataTlv *dataTlv = FindCommissioningData();

if (dataTlv != nullptr)
{
SuccessOrExit(response->AppendBytes(dataTlv->GetValue(), dataTlv->GetLength()));
}
}
VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync, error = kErrorInvalidState);

SuccessOrExit(Get<Tmf::Agent>().SendMessage(*response, aMessageInfo));
response = nullptr; // `SendMessage` takes ownership on success
response = ProcessCommissionerGetRequest(aMessage);
VerifyOrExit(response != nullptr, error = kErrorParse);
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*response, aMessageInfo));

LogInfo("Sent %s response", UriToString<kUriCommissionerGet>());
LogInfo("Sent %s response to %s", UriToString<kUriCommissionerGet>(),
aMessageInfo.GetPeerAddr().ToString().AsCString());

exit:
FreeMessage(response);
LogWarnOnError(error, "send CommissionerGet response");
FreeMessageOnError(response, error);
}

void Leader::SendCommissioningSetResponse(const Coap::Message &aRequest,
Expand Down

0 comments on commit abb6934

Please sign in to comment.