From 779b7851bf1bdeb0ca268d7433a1fd7f43820d6a Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Thu, 24 Oct 2019 22:13:08 -0700 Subject: [PATCH] [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. --- src/core/thread/mle.cpp | 78 ++++++++++++++++++++++++++--------------- src/core/thread/mle.hpp | 4 ++- 2 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index 7af3630b3..d88434015 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -2362,6 +2362,10 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con SuccessOrExit(error = AppendTimeout(*message, mTimeout)); break; + case Tlv::kStatus: + SuccessOrExit(error = AppendStatus(*message, StatusTlv::kError)); + break; + case Tlv::kAddressRegistration: if (!IsFullThreadDevice()) { @@ -2808,7 +2812,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn } else { - HandleChildUpdateRequest(aMessage, aMessageInfo); + HandleChildUpdateRequest(aMessage, aMessageInfo, neighbor); } break; @@ -3500,15 +3504,15 @@ exit: 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; - Mac::ExtAddress srcAddr; SourceAddressTlv sourceAddress; ChallengeTlv challenge; - StatusTlv status; TlvRequestTlv tlvRequest; uint8_t tlvs[kMaxResponseTlvs] = {}; 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()); - VerifyOrExit(mParent.GetRloc16() == sourceAddress.GetRloc16(), error = OT_ERROR_DROP); - - // 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) + // Challenge + if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == 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); - VerifyOrExit(mParent.GetExtAddress() == srcAddr, error = OT_ERROR_DROP); + if (aNeighbor == &mParent) + { + 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(); 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 if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE) { - VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= sizeof(tlvs), error = OT_ERROR_PARSE); - memcpy(tlvs, tlvRequest.GetTlvs(), tlvRequest.GetLength()); - numTlvs += tlvRequest.GetLength(); - } + VerifyOrExit(tlvRequest.IsValid(), error = OT_ERROR_PARSE); - // Challenge - if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == OT_ERROR_NONE) - { - VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE); - VerifyOrExit(static_cast(numTlvs + 3) <= sizeof(tlvs), error = OT_ERROR_NO_BUFS); - tlvs[numTlvs++] = Tlv::kResponse; - tlvs[numTlvs++] = Tlv::kMleFrameCounter; - tlvs[numTlvs++] = Tlv::kLinkFrameCounter; + for (uint8_t i = 0; i < tlvRequest.GetLength(); i++) + { + if (numTlvs >= sizeof(tlvs)) + { + otLogNoteMle("Failed to respond with TLVs: %d of %d", i, tlvRequest.GetLength()); + break; + } + + tlvs[numTlvs++] = tlvRequest.GetTlvs()[i]; + } } SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge)); diff --git a/src/core/thread/mle.hpp b/src/core/thread/mle.hpp index 977b73e4c..b20e0a7d6 100644 --- a/src/core/thread/mle.hpp +++ b/src/core/thread/mle.hpp @@ -1708,7 +1708,9 @@ private: otError HandleAdvertisement(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, const Ip6::MessageInfo &aMessageInfo, const Neighbor * aNeighbor);