[mle] respond to Child Update Request from non-parent (#4297)

This allows an end device to indicate that it is not a child of	the
Child Update Request transmitter.
This commit is contained in:
Jonathan Hui
2019-11-06 07:02:19 -08:00
parent 7703bad23f
commit 779b7851bf
2 changed files with 53 additions and 29 deletions
+50 -28
View File
@@ -2362,6 +2362,10 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con
SuccessOrExit(error = AppendTimeout(*message, mTimeout)); SuccessOrExit(error = AppendTimeout(*message, mTimeout));
break; break;
case Tlv::kStatus:
SuccessOrExit(error = AppendStatus(*message, StatusTlv::kError));
break;
case Tlv::kAddressRegistration: case Tlv::kAddressRegistration:
if (!IsFullThreadDevice()) if (!IsFullThreadDevice())
{ {
@@ -2808,7 +2812,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn
} }
else else
{ {
HandleChildUpdateRequest(aMessage, aMessageInfo); HandleChildUpdateRequest(aMessage, aMessageInfo, neighbor);
} }
break; break;
@@ -3500,15 +3504,15 @@ exit:
return error; return error;
} }
otError Mle::HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo) otError Mle::HandleChildUpdateRequest(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor)
{ {
static const uint8_t kMaxResponseTlvs = 5; static const uint8_t kMaxResponseTlvs = 6;
otError error = OT_ERROR_NONE; otError error = OT_ERROR_NONE;
Mac::ExtAddress srcAddr;
SourceAddressTlv sourceAddress; SourceAddressTlv sourceAddress;
ChallengeTlv challenge; ChallengeTlv challenge;
StatusTlv status;
TlvRequestTlv tlvRequest; TlvRequestTlv tlvRequest;
uint8_t tlvs[kMaxResponseTlvs] = {}; uint8_t tlvs[kMaxResponseTlvs] = {};
uint8_t numTlvs = 0; uint8_t numTlvs = 0;
@@ -3519,42 +3523,60 @@ otError Mle::HandleChildUpdateRequest(const Message &aMessage, const Ip6::Messag
LogMleMessage("Receive Child Update Request from parent", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16()); LogMleMessage("Receive Child Update Request from parent", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
VerifyOrExit(mParent.GetRloc16() == sourceAddress.GetRloc16(), error = OT_ERROR_DROP); // Challenge
if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == OT_ERROR_NONE)
// Leader Data, Network Data, Active Timestamp, Pending Timestamp
SuccessOrExit(error = HandleLeaderData(aMessage, aMessageInfo));
// Status
if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == OT_ERROR_NONE)
{ {
VerifyOrExit(status.IsValid(), error = OT_ERROR_PARSE); VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
tlvs[numTlvs++] = Tlv::kResponse;
tlvs[numTlvs++] = Tlv::kMleFrameCounter;
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
}
aMessageInfo.GetPeerAddr().ToExtAddress(srcAddr); if (aNeighbor == &mParent)
VerifyOrExit(mParent.GetExtAddress() == srcAddr, error = OT_ERROR_DROP); {
StatusTlv status;
if (status.GetStatus() == StatusTlv::kError) if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == OT_ERROR_NONE)
{
VerifyOrExit(status.IsValid(), error = OT_ERROR_PARSE);
if (status.GetStatus() == StatusTlv::kError)
{
BecomeDetached();
ExitNow();
}
}
if (mParent.GetRloc16() != sourceAddress.GetRloc16())
{ {
BecomeDetached(); BecomeDetached();
ExitNow(); ExitNow();
} }
// Leader Data, Network Data, Active Timestamp, Pending Timestamp
SuccessOrExit(error = HandleLeaderData(aMessage, aMessageInfo));
}
else
{
// this device is not a child of the Child Update Request source
tlvs[numTlvs++] = Tlv::kStatus;
} }
// TLV Request // TLV Request
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE) if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE)
{ {
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= sizeof(tlvs), error = OT_ERROR_PARSE); VerifyOrExit(tlvRequest.IsValid(), error = OT_ERROR_PARSE);
memcpy(tlvs, tlvRequest.GetTlvs(), tlvRequest.GetLength());
numTlvs += tlvRequest.GetLength();
}
// Challenge for (uint8_t i = 0; i < tlvRequest.GetLength(); i++)
if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == OT_ERROR_NONE) {
{ if (numTlvs >= sizeof(tlvs))
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE); {
VerifyOrExit(static_cast<size_t>(numTlvs + 3) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS); otLogNoteMle("Failed to respond with TLVs: %d of %d", i, tlvRequest.GetLength());
tlvs[numTlvs++] = Tlv::kResponse; break;
tlvs[numTlvs++] = Tlv::kMleFrameCounter; }
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
tlvs[numTlvs++] = tlvRequest.GetTlvs()[i];
}
} }
SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge)); SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge));
+3 -1
View File
@@ -1708,7 +1708,9 @@ private:
otError HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); otError HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError HandleChildIdResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); otError HandleChildIdResponse(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
otError HandleChildUpdateRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo); otError HandleChildUpdateRequest(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor);
otError HandleChildUpdateResponse(const Message & aMessage, otError HandleChildUpdateResponse(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo, const Ip6::MessageInfo &aMessageInfo,
const Neighbor * aNeighbor); const Neighbor * aNeighbor);