[mle-tlvs] simplify processing of simple MLE Tlvs (#4635)

This commit changes the processing of the following MLE TLVs:
SourceAddess, Mode, Timeout, LinkFrameCounter, MleFrameCounter,
Address16, LinkMargin, Status, Version, PanId, XtalAccuracy, ScanMask,
NetworkData, Challenge, Response, and TlvRequest.
This commit is contained in:
Abtin Keshavarzian
2020-03-09 11:39:09 -07:00
committed by Jonathan Hui
parent 19ed02842c
commit 15d5644b7d
8 changed files with 629 additions and 1333 deletions
+211 -245
View File
@@ -122,7 +122,6 @@ Mle::Mle(Instance &aInstance)
mLeaderData.Clear();
mParentLeaderData.Clear();
mParent.Clear();
memset(&mChildIdRequest, 0, sizeof(mChildIdRequest));
mParentCandidate.Clear();
ResetCounters();
@@ -1152,101 +1151,83 @@ exit:
otError Mle::AppendSourceAddress(Message &aMessage)
{
SourceAddressTlv tlv;
tlv.Init();
tlv.SetRloc16(GetRloc16());
return tlv.AppendTo(aMessage);
return Tlv::AppendUint16Tlv(aMessage, Tlv::kSourceAddress, GetRloc16());
}
otError Mle::AppendStatus(Message &aMessage, StatusTlv::Status aStatus)
{
StatusTlv tlv;
tlv.Init();
tlv.SetStatus(aStatus);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint8Tlv(aMessage, Tlv::kStatus, static_cast<uint8_t>(aStatus));
}
otError Mle::AppendMode(Message &aMessage, DeviceMode aMode)
{
ModeTlv tlv;
tlv.Init();
tlv.SetMode(aMode);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint8Tlv(aMessage, Tlv::kMode, aMode.Get());
}
otError Mle::AppendTimeout(Message &aMessage, uint32_t aTimeout)
{
TimeoutTlv tlv;
return Tlv::AppendUint32Tlv(aMessage, Tlv::kTimeout, aTimeout);
}
tlv.Init();
tlv.SetTimeout(aTimeout);
return tlv.AppendTo(aMessage);
otError Mle::AppendChallenge(Message &aMessage, const Challenge &aChallenge)
{
return Tlv::AppendTlv(aMessage, Tlv::kChallenge, aChallenge.mBuffer, aChallenge.mLength);
}
otError Mle::AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength)
{
otError error;
Tlv tlv;
return Tlv::AppendTlv(aMessage, Tlv::kChallenge, aChallenge, aChallengeLength);
}
tlv.SetType(Tlv::kChallenge);
tlv.SetLength(aChallengeLength);
otError Mle::AppendResponse(Message &aMessage, const Challenge &aResponse)
{
return Tlv::AppendTlv(aMessage, Tlv::kResponse, aResponse.mBuffer, aResponse.mLength);
}
otError Mle::ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer)
{
otError error;
uint16_t offset;
uint16_t length;
SuccessOrExit(error = Tlv::GetValueOffset(aMessage, aTlvType, offset, length));
VerifyOrExit(length >= kMinChallengeSize, error = OT_ERROR_PARSE);
if (length > kMaxChallengeSize)
{
length = kMaxChallengeSize;
}
aMessage.Read(offset, length, aBuffer.mBuffer);
aBuffer.mLength = static_cast<uint8_t>(length);
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
SuccessOrExit(error = aMessage.Append(aChallenge, aChallengeLength));
exit:
return error;
}
otError Mle::AppendResponse(Message &aMessage, const uint8_t *aResponse, uint8_t aResponseLength)
otError Mle::ReadChallenge(const Message &aMessage, Challenge &aChallenge)
{
otError error;
Tlv tlv;
return ReadChallengeOrResponse(aMessage, Tlv::kChallenge, aChallenge);
}
tlv.SetType(Tlv::kResponse);
tlv.SetLength(aResponseLength);
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
SuccessOrExit(error = aMessage.Append(aResponse, aResponseLength));
exit:
return error;
otError Mle::ReadResponse(const Message &aMessage, Challenge &aResponse)
{
return ReadChallengeOrResponse(aMessage, Tlv::kResponse, aResponse);
}
otError Mle::AppendLinkFrameCounter(Message &aMessage)
{
LinkFrameCounterTlv tlv;
tlv.Init();
tlv.SetFrameCounter(Get<KeyManager>().GetMacFrameCounter());
return tlv.AppendTo(aMessage);
return Tlv::AppendUint32Tlv(aMessage, Tlv::kLinkFrameCounter, Get<KeyManager>().GetMacFrameCounter());
}
otError Mle::AppendMleFrameCounter(Message &aMessage)
{
MleFrameCounterTlv tlv;
tlv.Init();
tlv.SetFrameCounter(Get<KeyManager>().GetMleFrameCounter());
return tlv.AppendTo(aMessage);
return Tlv::AppendUint32Tlv(aMessage, Tlv::kMleFrameCounter, Get<KeyManager>().GetMleFrameCounter());
}
otError Mle::AppendAddress16(Message &aMessage, uint16_t aRloc16)
{
Address16Tlv tlv;
tlv.Init();
tlv.SetRloc16(aRloc16);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint16Tlv(aMessage, Tlv::kAddress16, aRloc16);
}
otError Mle::AppendLeaderData(Message &aMessage)
@@ -1258,26 +1239,18 @@ otError Mle::AppendLeaderData(Message &aMessage)
return mLeaderData.AppendTo(aMessage);
}
void Mle::FillNetworkDataTlv(NetworkDataTlv &aTlv, bool aStableOnly)
{
uint8_t length = sizeof(NetworkDataTlv) - sizeof(Tlv); // sizeof( NetworkDataTlv::mNetworkData )
// Ignore result code, provided buffer must be enough
Get<NetworkData::Leader>().GetNetworkData(aStableOnly, aTlv.GetNetworkData(), length);
aTlv.SetLength(length);
}
otError Mle::AppendNetworkData(Message &aMessage, bool aStableOnly)
{
otError error = OT_ERROR_NONE;
NetworkDataTlv tlv;
otError error = OT_ERROR_NONE;
uint8_t networkData[NetworkData::NetworkData::kMaxSize];
uint8_t length;
VerifyOrExit(!mRetrieveNewNetworkData, error = OT_ERROR_INVALID_STATE);
tlv.Init();
FillNetworkDataTlv(tlv, aStableOnly);
length = sizeof(networkData);
Get<NetworkData::Leader>().GetNetworkData(aStableOnly, networkData, length);
error = tlv.AppendTo(aMessage);
error = Tlv::AppendTlv(aMessage, Tlv::kNetworkData, networkData, length);
exit:
return error;
@@ -1285,14 +1258,24 @@ exit:
otError Mle::AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength)
{
otError error;
Tlv tlv;
return Tlv::AppendTlv(aMessage, Tlv::kTlvRequest, aTlvs, aTlvsLength);
}
tlv.SetType(Tlv::kTlvRequest);
tlv.SetLength(aTlvsLength);
otError Mle::ReadTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs)
{
otError error;
uint16_t offset;
uint16_t length;
SuccessOrExit(error = aMessage.Append(&tlv, sizeof(tlv)));
SuccessOrExit(error = aMessage.Append(aTlvs, aTlvsLength));
SuccessOrExit(error = Tlv::GetValueOffset(aMessage, Tlv::kTlvRequest, offset, length));
if (length > sizeof(aRequestedTlvs.mTlvs))
{
length = sizeof(aRequestedTlvs.mTlvs);
}
aMessage.Read(offset, length, aRequestedTlvs.mTlvs);
aRequestedTlvs.mNumTlvs = static_cast<uint8_t>(length);
exit:
return error;
@@ -1300,32 +1283,17 @@ exit:
otError Mle::AppendScanMask(Message &aMessage, uint8_t aScanMask)
{
ScanMaskTlv tlv;
tlv.Init();
tlv.SetMask(aScanMask);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint8Tlv(aMessage, Tlv::kScanMask, aScanMask);
}
otError Mle::AppendLinkMargin(Message &aMessage, uint8_t aLinkMargin)
{
LinkMarginTlv tlv;
tlv.Init();
tlv.SetLinkMargin(aLinkMargin);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint8Tlv(aMessage, Tlv::kLinkMargin, aLinkMargin);
}
otError Mle::AppendVersion(Message &aMessage)
{
VersionTlv tlv;
tlv.Init();
tlv.SetVersion(kThreadVersion);
return tlv.AppendTo(aMessage);
return Tlv::AppendUint16Tlv(aMessage, Tlv::kVersion, kThreadVersion);
}
bool Mle::HasUnregisteredAddress(void)
@@ -1464,12 +1432,7 @@ otError Mle::AppendTimeParameter(Message &aMessage)
otError Mle::AppendXtalAccuracy(Message &aMessage)
{
XtalAccuracyTlv tlv;
tlv.Init();
tlv.SetXtalAccuracy(otPlatTimeGetXtalAccuracy());
return tlv.AppendTo(aMessage);
return Tlv::AppendUint16Tlv(aMessage, Tlv::kXtalAccuracy, otPlatTimeGetXtalAccuracy());
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -1993,7 +1956,7 @@ otError Mle::SendParentRequest(ParentRequestType aType)
uint8_t scanMask = 0;
Ip6::Address destination;
Random::Crypto::FillBuffer(mParentRequest.mChallenge, sizeof(mParentRequest.mChallenge));
mParentRequestChallenge.GenerateRandom();
switch (aType)
{
@@ -2009,7 +1972,7 @@ otError Mle::SendParentRequest(ParentRequestType aType)
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
SuccessOrExit(error = AppendHeader(*message, Header::kCommandParentRequest));
SuccessOrExit(error = AppendMode(*message, mDeviceMode));
SuccessOrExit(error = AppendChallenge(*message, mParentRequest.mChallenge, sizeof(mParentRequest.mChallenge)));
SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
SuccessOrExit(error = AppendScanMask(*message, scanMask));
SuccessOrExit(error = AppendVersion(*message));
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -2080,7 +2043,7 @@ otError Mle::SendChildIdRequest(void)
VerifyOrExit((message = NewMleMessage()) != NULL, error = OT_ERROR_NO_BUFS);
message->SetSubType(Message::kSubTypeMleChildIdRequest);
SuccessOrExit(error = AppendHeader(*message, Header::kCommandChildIdRequest));
SuccessOrExit(error = AppendResponse(*message, mChildIdRequest.mChallenge, mChildIdRequest.mChallengeLength));
SuccessOrExit(error = AppendResponse(*message, mParentCandidateChallenge));
SuccessOrExit(error = AppendLinkFrameCounter(*message));
SuccessOrExit(error = AppendMleFrameCounter(*message));
SuccessOrExit(error = AppendMode(*message, mDeviceMode));
@@ -2320,8 +2283,8 @@ otError Mle::SendChildUpdateRequest(void)
switch (mRole)
{
case OT_DEVICE_ROLE_DETACHED:
Random::Crypto::FillBuffer(mParentRequest.mChallenge, sizeof(mParentRequest.mChallenge));
SuccessOrExit(error = AppendChallenge(*message, mParentRequest.mChallenge, sizeof(mParentRequest.mChallenge)));
mParentRequestChallenge.GenerateRandom();
SuccessOrExit(error = AppendChallenge(*message, mParentRequestChallenge));
break;
case OT_DEVICE_ROLE_CHILD:
@@ -2364,7 +2327,7 @@ exit:
return error;
}
otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const ChallengeTlv &aChallenge)
otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge)
{
otError error = OT_ERROR_NONE;
Ip6::Address destination;
@@ -2403,7 +2366,7 @@ otError Mle::SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, con
break;
case Tlv::kResponse:
SuccessOrExit(error = AppendResponse(*message, aChallenge.GetChallenge(), aChallenge.GetChallengeLength()));
SuccessOrExit(error = AppendResponse(*message, aChallenge));
break;
case Tlv::kLinkFrameCounter:
@@ -2453,7 +2416,6 @@ otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Add
{
otError error = OT_ERROR_NONE;
ChannelTlv channel;
PanIdTlv panid;
ActiveTimestampTlv activeTimestamp;
Message * message = NULL;
@@ -2482,9 +2444,8 @@ otError Mle::SendAnnounce(uint8_t aChannel, bool aOrphanAnnounce, const Ip6::Add
SuccessOrExit(error = AppendActiveTimestamp(*message));
}
panid.Init();
panid.SetPanId(Get<Mac::Mac>().GetPanId());
SuccessOrExit(error = panid.AppendTo(*message));
SuccessOrExit(error = Tlv::AppendUint16Tlv(*message, Tlv::kPanId, Get<Mac::Mac>().GetPanId()));
SuccessOrExit(error = SendMessage(*message, aDestination));
otLogInfoMle("Send Announce on channel %d", aChannel);
@@ -2842,18 +2803,17 @@ exit:
otError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
otError error = OT_ERROR_NONE;
SourceAddressTlv sourceAddress;
LeaderDataTlv leaderData;
RouteTlv route;
uint8_t tlvs[] = {Tlv::kNetworkData};
uint16_t delay;
otError error = OT_ERROR_NONE;
uint16_t sourceAddress;
LeaderDataTlv leaderData;
RouteTlv route;
uint8_t tlvs[] = {Tlv::kNetworkData};
uint16_t delay;
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
LogMleMessage("Receive Advertisement", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Advertisement", aMessageInfo.GetPeerAddr(), sourceAddress);
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
@@ -2865,7 +2825,7 @@ otError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo
{
SuccessOrExit(error = Get<MleRouter>().HandleAdvertisement(aMessage, aMessageInfo, aNeighbor));
}
else if ((aNeighbor == &mParent) && (mParent.GetRloc16() != sourceAddress.GetRloc16()))
else if ((aNeighbor == &mParent) && (mParent.GetRloc16() != sourceAddress))
{
// Remove stale parent.
BecomeDetached();
@@ -2881,9 +2841,8 @@ otError Mle::HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo
case OT_DEVICE_ROLE_CHILD:
VerifyOrExit(aNeighbor == &mParent);
if ((mParent.GetRloc16() == sourceAddress.GetRloc16()) &&
(leaderData.GetPartitionId() != mLeaderData.GetPartitionId() ||
leaderData.GetLeaderRouterId() != GetLeaderId()))
if ((mParent.GetRloc16() == sourceAddress) && (leaderData.GetPartitionId() != mLeaderData.GetPartitionId() ||
leaderData.GetLeaderRouterId() != GetLeaderId()))
{
SetLeaderData(leaderData.GetPartitionId(), leaderData.GetWeighting(), leaderData.GetLeaderRouterId());
@@ -3129,7 +3088,7 @@ bool Mle::IsBetterParent(uint16_t aRloc16,
uint8_t aLinkQuality,
uint8_t aLinkMargin,
const ConnectivityTlv &aConnectivityTlv,
VersionTlv & aVersionTlv)
uint8_t aVersion)
{
bool rval = false;
@@ -3161,9 +3120,9 @@ bool Mle::IsBetterParent(uint16_t aRloc16,
}
// Thread 1.2 Specification 4.5.2.1.2 Child Impacting Criteria
if (aVersionTlv.GetVersion() != mParentCandidate.GetVersion())
if (aVersion != mParentCandidate.GetVersion())
{
ExitNow(rval = (aVersionTlv.GetVersion() > mParentCandidate.GetVersion()));
ExitNow(rval = (aVersion > mParentCandidate.GetVersion()));
}
if (aConnectivityTlv.GetSedBufferSize() != mParentSedBufferSize)
@@ -3197,37 +3156,33 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
{
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
ResponseTlv response;
VersionTlv version;
SourceAddressTlv sourceAddress;
Challenge response;
uint16_t version;
uint16_t sourceAddress;
LeaderDataTlv leaderData;
LinkMarginTlv linkMarginTlv;
uint8_t linkMarginFromTlv;
uint8_t linkMargin;
uint8_t linkQuality;
ConnectivityTlv connectivity;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
ChallengeTlv challenge;
uint32_t linkFrameCounter;
uint32_t mleFrameCounter;
Mac::ExtAddress extAddress;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
TimeParameterTlv timeParameter;
#endif
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
LogMleMessage("Receive Parent Response", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Parent Response", aMessageInfo.GetPeerAddr(), sourceAddress);
// Version
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kVersion, sizeof(version), version));
VerifyOrExit(version.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kVersion, version));
VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
// Response
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response));
VerifyOrExit(response.IsValid() &&
memcmp(response.GetResponse(), mParentRequest.mChallenge, response.GetResponseLength()) == 0,
error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadResponse(aMessage, response));
VerifyOrExit(response == mParentRequestChallenge, error = OT_ERROR_PARSE);
aMessageInfo.GetPeerAddr().ToExtAddress(extAddress);
@@ -3240,15 +3195,14 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
VerifyOrExit(leaderData.IsValid(), error = OT_ERROR_PARSE);
// Link Quality
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLinkMargin, sizeof(linkMarginTlv), linkMarginTlv));
VerifyOrExit(linkMarginTlv.IsValid(), error = OT_ERROR_PARSE);
// Link Margin
SuccessOrExit(error = Tlv::ReadUint8Tlv(aMessage, Tlv::kLinkMargin, linkMarginFromTlv));
linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->mRss);
if (linkMargin > linkMarginTlv.GetLinkMargin())
if (linkMargin > linkMarginFromTlv)
{
linkMargin = linkMarginTlv.GetLinkMargin();
linkMargin = linkMarginFromTlv;
}
linkQuality = LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin);
@@ -3263,7 +3217,7 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
otThreadParentResponseInfo parentinfo;
parentinfo.mExtAddr = extAddress;
parentinfo.mRloc16 = sourceAddress.GetRloc16();
parentinfo.mRloc16 = sourceAddress;
parentinfo.mRssi = linkInfo->mRss;
parentinfo.mPriority = connectivity.GetParentPriority();
parentinfo.mLinkQuality3 = connectivity.GetLinkQuality3();
@@ -3325,22 +3279,23 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
VerifyOrExit(compare >= 0);
// only consider better parents if the partitions are the same
VerifyOrExit(compare != 0 ||
IsBetterParent(sourceAddress.GetRloc16(), linkQuality, linkMargin, connectivity, version));
VerifyOrExit(compare != 0 || IsBetterParent(sourceAddress, linkQuality, linkMargin, connectivity,
static_cast<uint8_t>(version)));
}
// Link Frame Counter
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter));
VerifyOrExit(linkFrameCounter.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint32Tlv(aMessage, Tlv::kLinkFrameCounter, linkFrameCounter));
// Mle Frame Counter
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kMleFrameCounter, mleFrameCounter))
{
VerifyOrExit(mleFrameCounter.IsValid());
}
else
{
mleFrameCounter.SetFrameCounter(linkFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
mleFrameCounter = linkFrameCounter;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -3365,22 +3320,19 @@ otError Mle::HandleParentResponse(const Message &aMessage, const Ip6::MessageInf
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
// Challenge
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge));
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
mChildIdRequest.mChallengeLength = challenge.GetChallengeLength();
memcpy(mChildIdRequest.mChallenge, challenge.GetChallenge(), mChildIdRequest.mChallengeLength);
SuccessOrExit(error = ReadChallenge(aMessage, mParentCandidateChallenge));
mParentCandidate.SetExtAddress(extAddress);
mParentCandidate.SetRloc16(sourceAddress.GetRloc16());
mParentCandidate.SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
mParentCandidate.SetMleFrameCounter(mleFrameCounter.GetFrameCounter());
mParentCandidate.SetVersion(static_cast<uint8_t>(version.GetVersion()));
mParentCandidate.SetRloc16(sourceAddress);
mParentCandidate.SetLinkFrameCounter(linkFrameCounter);
mParentCandidate.SetMleFrameCounter(mleFrameCounter);
mParentCandidate.SetVersion(static_cast<uint8_t>(version));
mParentCandidate.SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
DeviceMode::kModeFullNetworkData | DeviceMode::kModeSecureDataRequest));
mParentCandidate.GetLinkInfo().Clear();
mParentCandidate.GetLinkInfo().AddRss(linkInfo->mRss);
mParentCandidate.ResetLinkFailures();
mParentCandidate.SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMarginTlv.GetLinkMargin()));
mParentCandidate.SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMarginFromTlv));
mParentCandidate.SetState(Neighbor::kStateParentResponse);
mParentCandidate.SetKeySequence(aKeySequence);
@@ -3413,8 +3365,8 @@ otError Mle::HandleChildIdResponse(const Message & aMessage,
otError error = OT_ERROR_NONE;
LeaderDataTlv leaderData;
SourceAddressTlv sourceAddress;
Address16Tlv shortAddress;
uint16_t sourceAddress;
uint16_t shortAddress;
RouteTlv route;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
@@ -3423,10 +3375,9 @@ otError Mle::HandleChildIdResponse(const Message & aMessage,
uint16_t offset;
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
LogMleMessage("Receive Child ID Response", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Child ID Response", aMessageInfo.GetPeerAddr(), sourceAddress);
VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = OT_ERROR_SECURITY);
@@ -3437,8 +3388,7 @@ otError Mle::HandleChildIdResponse(const Message & aMessage,
VerifyOrExit(leaderData.IsValid(), error = OT_ERROR_PARSE);
// ShortAddress
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kAddress16, sizeof(shortAddress), shortAddress));
VerifyOrExit(shortAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kAddress16, shortAddress));
// Network Data
error = Tlv::GetOffset(aMessage, Tlv::kNetworkData, networkDataOffset);
@@ -3513,12 +3463,12 @@ otError Mle::HandleChildIdResponse(const Message & aMessage,
mParent = mParentCandidate;
mParentCandidate.Clear();
mParent.SetRloc16(sourceAddress.GetRloc16());
mParent.SetRloc16(sourceAddress);
Get<NetworkData::Leader>().SetNetworkData(leaderData.GetDataVersion(), leaderData.GetStableDataVersion(),
!IsFullNetworkData(), aMessage, networkDataOffset);
SetStateChild(shortAddress.GetRloc16());
SetStateChild(shortAddress);
exit:
@@ -3536,44 +3486,48 @@ otError Mle::HandleChildUpdateRequest(const Message & aMessage,
{
static const uint8_t kMaxResponseTlvs = 6;
otError error = OT_ERROR_NONE;
SourceAddressTlv sourceAddress;
ChallengeTlv challenge;
TlvRequestTlv tlvRequest;
uint8_t tlvs[kMaxResponseTlvs] = {};
uint8_t numTlvs = 0;
otError error = OT_ERROR_NONE;
uint16_t sourceAddress;
Challenge challenge;
RequestedTlvs requestedTlvs;
uint8_t tlvs[kMaxResponseTlvs] = {};
uint8_t numTlvs = 0;
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
LogMleMessage("Receive Child Update Request from parent", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Child Update Request from parent", aMessageInfo.GetPeerAddr(), sourceAddress);
// Challenge
if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == OT_ERROR_NONE)
switch (ReadChallenge(aMessage, challenge))
{
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
case OT_ERROR_NONE:
tlvs[numTlvs++] = Tlv::kResponse;
tlvs[numTlvs++] = Tlv::kMleFrameCounter;
tlvs[numTlvs++] = Tlv::kLinkFrameCounter;
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
if (aNeighbor == &mParent)
{
StatusTlv status;
uint8_t status;
if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == OT_ERROR_NONE)
switch (Tlv::ReadUint8Tlv(aMessage, Tlv::kStatus, status))
{
VerifyOrExit(status.IsValid(), error = OT_ERROR_PARSE);
if (status.GetStatus() == StatusTlv::kError)
{
BecomeDetached();
ExitNow();
}
case OT_ERROR_NONE:
VerifyOrExit(status != StatusTlv::kError, BecomeDetached());
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
if (mParent.GetRloc16() != sourceAddress.GetRloc16())
if (mParent.GetRloc16() != sourceAddress)
{
BecomeDetached();
ExitNow();
@@ -3589,20 +3543,24 @@ otError Mle::HandleChildUpdateRequest(const Message & aMessage,
}
// TLV Request
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE)
switch (ReadTlvRequest(aMessage, requestedTlvs))
{
VerifyOrExit(tlvRequest.IsValid(), error = OT_ERROR_PARSE);
for (uint8_t i = 0; i < tlvRequest.GetLength(); i++)
case OT_ERROR_NONE:
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
{
if (numTlvs >= sizeof(tlvs))
{
otLogWarnMle("Failed to respond with TLVs: %d of %d", i, tlvRequest.GetLength());
otLogWarnMle("Failed to respond with TLVs: %d of %d", i, requestedTlvs.mNumTlvs);
break;
}
tlvs[numTlvs++] = tlvRequest.GetTlvs()[i];
tlvs[numTlvs++] = requestedTlvs.mTlvs[i];
}
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
SuccessOrExit(error = SendChildUpdateResponse(tlvs, numTlvs, challenge));
@@ -3621,25 +3579,22 @@ otError Mle::HandleChildUpdateResponse(const Message & aMessage,
const Ip6::MessageInfo &aMessageInfo,
const Neighbor * aNeighbor)
{
otError error = OT_ERROR_NONE;
StatusTlv status;
ModeTlv mode;
ResponseTlv response;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
SourceAddressTlv sourceAddress;
TimeoutTlv timeout;
otError error = OT_ERROR_NONE;
uint8_t status;
uint8_t mode;
Challenge response;
uint32_t linkFrameCounter;
uint32_t mleFrameCounter;
uint16_t sourceAddress;
uint32_t timeout;
LogMleMessage("Receive Child Update Response from parent", aMessageInfo.GetPeerAddr());
switch (mRole)
{
case OT_DEVICE_ROLE_DETACHED:
VerifyOrExit(
(Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response) == OT_ERROR_NONE) &&
(response.IsValid()) &&
(!memcmp(response.GetResponse(), mParentRequest.mChallenge, sizeof(mParentRequest.mChallenge))),
error = OT_ERROR_SECURITY);
SuccessOrExit(error = ReadResponse(aMessage, response));
VerifyOrExit(response == mParentRequestChallenge, error = OT_ERROR_SECURITY);
break;
case OT_DEVICE_ROLE_CHILD:
@@ -3652,35 +3607,34 @@ otError Mle::HandleChildUpdateResponse(const Message & aMessage,
}
// Status
if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == OT_ERROR_NONE)
if (Tlv::ReadUint8Tlv(aMessage, Tlv::kStatus, status) == OT_ERROR_NONE)
{
BecomeDetached();
ExitNow();
}
// Mode
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kMode, sizeof(mode), mode));
VerifyOrExit(mode.IsValid(), error = OT_ERROR_PARSE);
VerifyOrExit(mode.GetMode() == mDeviceMode, error = OT_ERROR_DROP);
SuccessOrExit(error = Tlv::ReadUint8Tlv(aMessage, Tlv::kMode, mode));
VerifyOrExit(DeviceMode(mode) == mDeviceMode, error = OT_ERROR_DROP);
switch (mRole)
{
case OT_DEVICE_ROLE_DETACHED:
SuccessOrExit(error =
Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter));
VerifyOrExit(linkFrameCounter.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint32Tlv(aMessage, Tlv::kLinkFrameCounter, linkFrameCounter));
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kMleFrameCounter, mleFrameCounter))
{
VerifyOrExit(mleFrameCounter.IsValid(), error = OT_ERROR_PARSE);
}
else
{
mleFrameCounter.SetFrameCounter(linkFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
mleFrameCounter = linkFrameCounter;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
mParent.SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
mParent.SetMleFrameCounter(mleFrameCounter.GetFrameCounter());
mParent.SetLinkFrameCounter(linkFrameCounter);
mParent.SetMleFrameCounter(mleFrameCounter);
mParent.SetState(Neighbor::kStateValid);
SetStateChild(GetRloc16());
@@ -3691,10 +3645,9 @@ otError Mle::HandleChildUpdateResponse(const Message & aMessage,
case OT_DEVICE_ROLE_CHILD:
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
if (RouterIdFromRloc16(sourceAddress.GetRloc16()) != RouterIdFromRloc16(GetRloc16()))
if (RouterIdFromRloc16(sourceAddress) != RouterIdFromRloc16(GetRloc16()))
{
BecomeDetached();
ExitNow();
@@ -3704,10 +3657,15 @@ otError Mle::HandleChildUpdateResponse(const Message & aMessage,
SuccessOrExit(error = HandleLeaderData(aMessage, aMessageInfo));
// Timeout optional
if (Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kTimeout, timeout))
{
VerifyOrExit(timeout.IsValid(), error = OT_ERROR_PARSE);
mTimeout = timeout.GetTimeout();
case OT_ERROR_NONE:
mTimeout = timeout;
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
if (!IsRxOnWhenIdle())
@@ -3754,7 +3712,6 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
ChannelTlv channelTlv;
ActiveTimestampTlv timestamp;
const MeshCoP::Timestamp *localTimestamp;
PanIdTlv panIdTlv;
uint8_t channel;
uint16_t panId;
@@ -3768,9 +3725,7 @@ otError Mle::HandleAnnounce(const Message &aMessage, const Ip6::MessageInfo &aMe
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kActiveTimestamp, sizeof(timestamp), timestamp));
VerifyOrExit(timestamp.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panIdTlv), panIdTlv));
VerifyOrExit(panIdTlv.IsValid(), error = OT_ERROR_PARSE);
panId = panIdTlv.GetPanId();
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kPanId, panId));
localTimestamp = Get<MeshCoP::ActiveDataset>().GetTimestamp();
@@ -4348,5 +4303,16 @@ void Mle::RegisterParentResponseStatsCallback(otThreadParentResponseCallback aCa
mParentResponseCbContext = aContext;
}
void Mle::Challenge::GenerateRandom(void)
{
mLength = kMaxChallengeSize;
Random::Crypto::FillBuffer(mBuffer, mLength);
}
bool Mle::Challenge::Matches(const uint8_t *aBuffer, uint8_t aLength) const
{
return (mLength == aLength) && (memcmp(mBuffer, aBuffer, aLength) == 0);
}
} // namespace Mle
} // namespace ot
+114 -26
View File
@@ -1009,15 +1009,6 @@ public:
*/
static bool IsActiveRouter(uint16_t aRloc16) { return ChildIdFromRloc16(aRloc16) == 0; }
/**
* This method fills the NetworkDataTlv.
*
* @param[out] aTlv The NetworkDataTlv.
* @param[in] aStableOnly TRUE to append stable data, FALSE otherwise.
*
*/
void FillNetworkDataTlv(NetworkDataTlv &aTlv, bool aStableOnly);
/**
* This method returns a reference to the send queue.
*
@@ -1115,6 +1106,60 @@ protected:
kAppendMeshLocalOnly, ///< Only append the Mesh Local (ML-EID) address in Address Registration TLV.
};
/**
* This type represents a Challenge (or Response) data.
*
*/
struct Challenge
{
uint8_t mBuffer[kMaxChallengeSize]; ///< Buffer containing the challenge/response byte sequence.
uint8_t mLength; ///< Challenge length (in bytes).
/**
* This method generates a cryptographically secure random sequence to populate the challenge data.
*
*/
void GenerateRandom(void);
/**
* This method indicates whether the Challenge matches a given buffer.
*
* @param[in] aBuffer A pointer to a buffer to compare with the Challenge.
* @param[in] aLength Length of @p aBuffer (in bytes).
*
* @retval TRUE If the Challenge matches the given buffer.
* @retval FALSE If the Challenge does not match the given buffer.
*
*/
bool Matches(const uint8_t *aBuffer, uint8_t aLength) const;
/**
* This method indicates whether two Challenge data byte sequences are equal or not.
*
* @param[in] aOther Another Challenge data to compare.
*
* @retval TRUE If the two Challenges match.
* @retval FALSE If the two Challenges do not match.
*
*/
bool operator==(const Challenge &aOther) const { return Matches(aOther.mBuffer, aOther.mLength); }
};
/**
* This type represents list of requested TLVs in a TLV Request TLV.
*
*/
struct RequestedTlvs
{
enum
{
kMaxNumTlvs = 16, ///< Maximum number of TLVs in request array.
};
uint8_t mTlvs[kMaxNumTlvs]; ///< Array of requested TLVs.
uint8_t mNumTlvs; ///< Number of TLVs in the array.
};
/**
* This method allocates a new message buffer for preparing an MLE message.
*
@@ -1199,18 +1244,55 @@ protected:
*/
otError AppendChallenge(Message &aMessage, const uint8_t *aChallenge, uint8_t aChallengeLength);
/**
* This method appends a Challenge TLV to a message.
*
* @param[in] aMessage A reference to the message.
* @param[in] aChallenge A reference to the Challenge data.
*
* @retval OT_ERROR_NONE Successfully appended the Challenge TLV.
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Challenge TLV.
*
*/
otError AppendChallenge(Message &aMessage, const Challenge &aChallenge);
/**
* This method reads Challenge TLV from a message.
*
* @param[in] aMessage A reference to the message.
* @param[out] aChallenge A reference to the Challenge data where to output the read value.
*
* @retval OT_ERROR_NONE Successfully read the Challenge TLV.
* @retval OT_ERROR_NOT_FOUND Challenge TLV was not found in the message.
* @retval OT_ERROR_PARSE Challenge TLV was found but could not be parsed.
*
*/
otError ReadChallenge(const Message &aMessage, Challenge &aChallenge);
/**
* This method appends a Response TLV to a message.
*
* @param[in] aMessage A reference to the message.
* @param[in] aResponse A pointer to the Response value.
* @param[in] aResponseLength The length of the Response value in bytes.
* @param[in] aResponse A reference to the Response data.
*
* @retval OT_ERROR_NONE Successfully appended the Response TLV.
* @retval OT_ERROR_NO_BUFS Insufficient buffers available to append the Response TLV.
*
*/
otError AppendResponse(Message &aMessage, const uint8_t *aResponse, uint8_t aResponseLength);
otError AppendResponse(Message &aMessage, const Challenge &aResponse);
/**
* This method reads Response TLV from a message.
*
* @param[in] aMessage A reference to the message.
* @param[out] aResponse A reference to the Response data where to output the read value.
*
* @retval OT_ERROR_NONE Successfully read the Response TLV.
* @retval OT_ERROR_NOT_FOUND Response TLV was not found in the message.
* @retval OT_ERROR_PARSE Response TLV was found but could not be parsed.
*
*/
otError ReadResponse(const Message &aMessage, Challenge &aResponse);
/**
* This method appends a Link Frame Counter TLV to a message.
@@ -1271,6 +1353,19 @@ protected:
*/
otError AppendTlvRequest(Message &aMessage, const uint8_t *aTlvs, uint8_t aTlvsLength);
/**
* This method reads TLV Request TLV from a message.
*
* @param[in] aMessage A reference to the message.
* @param[out] aRequestedTlvs A reference to output the read list of requested TLVs.
*
* @retval OT_ERROR_NONE Successfully read the TLV.
* @retval OT_ERROR_NOT_FOUND TLV was not found in the message.
* @retval OT_ERROR_PARSE TLV was found but could not be parsed.
*
*/
otError ReadTlvRequest(const Message &aMessage, RequestedTlvs &aRequestedTlvs);
/**
* This method appends a Leader Data TLV to a message.
*
@@ -1496,13 +1591,13 @@ protected:
*
* @param[in] aTlvs A pointer to requested TLV types.
* @param[in] aNumTlvs The number of TLV types in @p aTlvs.
* @param[in] aChallenge The Challenge TLV for the response.
* @param[in] aChallenge The Challenge for the response.
*
* @retval OT_ERROR_NONE Successfully generated an MLE Child Update Response message.
* @retval OT_ERROR_NO_BUFS Insufficient buffers to generate the MLE Child Update Response message.
*
*/
otError SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const ChallengeTlv &aChallenge);
otError SendChildUpdateResponse(const uint8_t *aTlvs, uint8_t aNumTlvs, const Challenge &aChallenge);
/**
* This method submits an MLE message to the UDP socket.
@@ -1691,6 +1786,7 @@ private:
static void HandleUdpReceive(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
void HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
void ScheduleMessageTransmissionTimer(void);
otError ReadChallengeOrResponse(const Message &aMessage, uint8_t aTlvType, Challenge &aBuffer);
otError HandleAdvertisement(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor);
otError HandleChildIdResponse(const Message & aMessage,
@@ -1724,7 +1820,7 @@ private:
uint8_t aLinkQuality,
uint8_t aLinkMargin,
const ConnectivityTlv &aConnectivityTlv,
VersionTlv & aVersionTlv);
uint8_t aVersion);
bool IsNetworkDataNewer(const LeaderDataTlv &aLeaderData);
otError GetAlocAddress(Ip6::Address &aAddress, uint16_t aAloc16) const;
@@ -1749,16 +1845,7 @@ private:
MessageQueue mDelayedResponses;
struct
{
uint8_t mChallenge[ChallengeTlv::kMaxSize];
uint8_t mChallengeLength;
} mChildIdRequest;
struct
{
uint8_t mChallenge[ChallengeTlv::kMaxSize];
} mParentRequest;
Challenge mParentRequestChallenge;
AttachMode mParentRequestMode;
int8_t mParentPriority;
@@ -1780,7 +1867,8 @@ private:
bool mReceivedResponseFromParent;
LeaderDataTlv mParentLeaderData;
Router mParentCandidate;
Router mParentCandidate;
Challenge mParentCandidateChallenge;
Ip6::UdpSocket mSocket;
uint32_t mTimeout;
+9
View File
@@ -92,6 +92,15 @@ enum
kRlocPrefixLength = 14, ///< Prefix length of RLOC in bytes
};
/**
* MLE TLV Constants
*/
enum
{
kMinChallengeSize = 4, ///< Minimum Challenge size in bytes.
kMaxChallengeSize = 8, ///< Maximum Challenge size in bytes.
};
/**
* Routing Protocol Constants
*
+264 -236
View File
@@ -514,11 +514,10 @@ otError MleRouter::SendLinkRequest(Neighbor *aNeighbor)
if (aNeighbor == NULL)
{
Random::Crypto::FillBuffer(mChallenge, sizeof(mChallenge));
mChallenge.GenerateRandom();
mChallengeTimeout = (((2 * kMaxResponseDelay) + kStateUpdatePeriod - 1) / kStateUpdatePeriod);
SuccessOrExit(error = AppendChallenge(*message, mChallenge, sizeof(mChallenge)));
SuccessOrExit(error = AppendChallenge(*message, mChallenge));
destination.mFields.m8[0] = 0xff;
destination.mFields.m8[1] = 0x02;
destination.mFields.m8[15] = 2;
@@ -532,10 +531,10 @@ otError MleRouter::SendLinkRequest(Neighbor *aNeighbor)
}
else
{
uint8_t challenge[ChallengeTlv::kMaxSize];
Challenge challenge;
Random::Crypto::FillBuffer(challenge, sizeof(challenge));
SuccessOrExit(error = AppendChallenge(*message, challenge, sizeof(challenge)));
challenge.GenerateRandom();
SuccessOrExit(error = AppendChallenge(*message, challenge));
}
destination.mFields.m16[0] = HostSwap16(0xfe80);
@@ -558,13 +557,13 @@ exit:
otError MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::MessageInfo &aMessageInfo, Neighbor *aNeighbor)
{
otError error = OT_ERROR_NONE;
Neighbor * neighbor = NULL;
ChallengeTlv challenge;
VersionTlv version;
LeaderDataTlv leaderData;
SourceAddressTlv sourceAddress;
TlvRequestTlv tlvRequest;
otError error = OT_ERROR_NONE;
Neighbor * neighbor = NULL;
Challenge challenge;
uint16_t version;
LeaderDataTlv leaderData;
uint16_t sourceAddress;
RequestedTlvs requestedTlvs;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
TimeRequestTlv timeRequest;
#endif
@@ -576,12 +575,11 @@ otError MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::Message
VerifyOrExit(!IsAttaching(), error = OT_ERROR_INVALID_STATE);
// Challenge
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge));
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadChallenge(aMessage, challenge));
// Version
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kVersion, sizeof(version), version));
VerifyOrExit(version.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kVersion, version));
VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
// Leader Data
if (Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData) == OT_ERROR_NONE)
@@ -591,21 +589,16 @@ otError MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::Message
}
// Source Address
if (Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress) == OT_ERROR_NONE)
switch (Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress))
{
uint16_t rloc16;
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
rloc16 = sourceAddress.GetRloc16();
if (IsActiveRouter(rloc16))
case OT_ERROR_NONE:
if (IsActiveRouter(sourceAddress))
{
Mac::ExtAddress macAddr;
aMessageInfo.GetPeerAddr().ToExtAddress(macAddr);
neighbor = mRouterTable.GetRouter(RouterIdFromRloc16(rloc16));
neighbor = mRouterTable.GetRouter(RouterIdFromRloc16(sourceAddress));
VerifyOrExit(neighbor != NULL, error = OT_ERROR_PARSE);
VerifyOrExit(!neighbor->IsStateLinkRequest(), error = OT_ERROR_ALREADY);
@@ -625,23 +618,30 @@ otError MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::Message
VerifyOrExit(neighbor->GetExtAddress() == macAddr);
}
}
}
else
{
break;
case OT_ERROR_NOT_FOUND:
// lack of source address indicates router coming out of reset
VerifyOrExit(aNeighbor && aNeighbor->IsStateValid() && IsActiveRouter(aNeighbor->GetRloc16()),
error = OT_ERROR_DROP);
neighbor = aNeighbor;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// TLV Request
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE)
switch (ReadTlvRequest(aMessage, requestedTlvs))
{
VerifyOrExit(tlvRequest.IsValid(), error = OT_ERROR_PARSE);
}
else
{
tlvRequest.SetLength(0);
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
requestedTlvs.mNumTlvs = 0;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -658,7 +658,7 @@ otError MleRouter::HandleLinkRequest(const Message &aMessage, const Ip6::Message
}
#endif
SuccessOrExit(error = SendLinkAccept(aMessageInfo, neighbor, tlvRequest, challenge));
SuccessOrExit(error = SendLinkAccept(aMessageInfo, neighbor, requestedTlvs, challenge));
exit:
return error;
@@ -666,8 +666,8 @@ exit:
otError MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor,
const TlvRequestTlv & aTlvRequest,
const ChallengeTlv & aChallenge)
const RequestedTlvs & aRequestedTlvs,
const Challenge & aChallenge)
{
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
@@ -683,7 +683,7 @@ otError MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
SuccessOrExit(error = AppendHeader(*message, command));
SuccessOrExit(error = AppendVersion(*message));
SuccessOrExit(error = AppendSourceAddress(*message));
SuccessOrExit(error = AppendResponse(*message, aChallenge.GetChallenge(), aChallenge.GetChallengeLength()));
SuccessOrExit(error = AppendResponse(*message, aChallenge));
SuccessOrExit(error = AppendLinkFrameCounter(*message));
SuccessOrExit(error = AppendMleFrameCounter(*message));
@@ -697,9 +697,9 @@ otError MleRouter::SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
SuccessOrExit(error = AppendLeaderData(*message));
}
for (uint8_t i = 0; i < aTlvRequest.GetLength(); i++)
for (uint8_t i = 0; i < aRequestedTlvs.mNumTlvs; i++)
{
switch (aTlvRequest.GetTlvs()[i])
switch (aRequestedTlvs.mTlvs[i])
{
case Tlv::kRoute:
SuccessOrExit(error = AppendRoute(*message));
@@ -802,51 +802,47 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
Router * router;
Neighbor::State neighborState;
Mac::ExtAddress macAddr;
VersionTlv version;
ResponseTlv response;
SourceAddressTlv sourceAddress;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
uint16_t version;
Challenge response;
uint16_t sourceAddress;
uint32_t linkFrameCounter;
uint32_t mleFrameCounter;
uint8_t routerId;
Address16Tlv address16;
uint16_t address16;
RouteTlv route;
LeaderDataTlv leaderData;
LinkMarginTlv linkMargin;
uint8_t linkMargin;
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
if (aRequest)
{
LogMleMessage("Receive Link Accept and Request", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Link Accept and Request", aMessageInfo.GetPeerAddr(), sourceAddress);
}
else
{
LogMleMessage("Receive Link Accept", aMessageInfo.GetPeerAddr(), sourceAddress.GetRloc16());
LogMleMessage("Receive Link Accept", aMessageInfo.GetPeerAddr(), sourceAddress);
}
VerifyOrExit(IsActiveRouter(sourceAddress.GetRloc16()), error = OT_ERROR_PARSE);
VerifyOrExit(IsActiveRouter(sourceAddress), error = OT_ERROR_PARSE);
routerId = RouterIdFromRloc16(sourceAddress.GetRloc16());
routerId = RouterIdFromRloc16(sourceAddress);
router = mRouterTable.GetRouter(routerId);
neighborState = (router != NULL) ? router->GetState() : Neighbor::kStateInvalid;
// Response
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response));
VerifyOrExit(response.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadResponse(aMessage, response));
// verify response
switch (neighborState)
{
case Neighbor::kStateLinkRequest:
VerifyOrExit(memcmp(router->GetChallenge(), response.GetResponse(), router->GetChallengeSize()) == 0,
error = OT_ERROR_SECURITY);
VerifyOrExit(response.Matches(router->GetChallenge(), router->GetChallengeSize()), error = OT_ERROR_SECURITY);
break;
case Neighbor::kStateInvalid:
VerifyOrExit((mChallengeTimeout > 0) && (memcmp(mChallenge, response.GetResponse(), sizeof(mChallenge)) == 0),
error = OT_ERROR_SECURITY);
VerifyOrExit((mChallengeTimeout > 0) && (response == mChallenge), error = OT_ERROR_SECURITY);
case Neighbor::kStateValid:
break;
@@ -856,41 +852,43 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
}
// Remove stale neighbors
if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress.GetRloc16())
if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress)
{
RemoveNeighbor(*aNeighbor);
}
// Version
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kVersion, sizeof(version), version));
VerifyOrExit(version.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kVersion, version));
VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
// Link-Layer Frame Counter
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter));
VerifyOrExit(linkFrameCounter.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint32Tlv(aMessage, Tlv::kLinkFrameCounter, linkFrameCounter));
// MLE Frame Counter
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kMleFrameCounter, mleFrameCounter))
{
VerifyOrExit(mleFrameCounter.IsValid(), error = OT_ERROR_PARSE);
}
else
{
mleFrameCounter.SetFrameCounter(linkFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
mleFrameCounter = linkFrameCounter;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Link Margin
if (Tlv::GetTlv(aMessage, Tlv::kLinkMargin, sizeof(linkMargin), linkMargin) == OT_ERROR_NONE)
{
VerifyOrExit(linkMargin.IsValid(), error = OT_ERROR_PARSE);
}
else
switch (Tlv::ReadUint8Tlv(aMessage, Tlv::kLinkMargin, linkMargin))
{
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
// Link Margin TLV may be skipped in Router Synchronization process after Reset
VerifyOrExit(mRole == OT_DEVICE_ROLE_DETACHED, error = OT_ERROR_NOT_FOUND);
// Wait for an MLE Advertisement to establish a routing cost to the neighbor
linkMargin.SetLinkMargin(0);
linkMargin = 0;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
switch (mRole)
@@ -901,9 +899,8 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
case OT_DEVICE_ROLE_DETACHED:
// Address16
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kAddress16, sizeof(address16), address16));
VerifyOrExit(address16.IsValid(), error = OT_ERROR_PARSE);
VerifyOrExit(GetRloc16() == address16.GetRloc16(), error = OT_ERROR_DROP);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kAddress16, address16));
VerifyOrExit(GetRloc16() == address16, error = OT_ERROR_DROP);
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
@@ -974,15 +971,15 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
// finish link synchronization
aMessageInfo.GetPeerAddr().ToExtAddress(macAddr);
router->SetExtAddress(macAddr);
router->SetRloc16(sourceAddress.GetRloc16());
router->SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
router->SetMleFrameCounter(mleFrameCounter.GetFrameCounter());
router->SetRloc16(sourceAddress);
router->SetLinkFrameCounter(linkFrameCounter);
router->SetMleFrameCounter(mleFrameCounter);
router->SetLastHeard(TimerMilli::GetNow());
router->SetDeviceMode(DeviceMode(DeviceMode::kModeFullThreadDevice | DeviceMode::kModeRxOnWhenIdle |
DeviceMode::kModeFullNetworkData));
router->GetLinkInfo().Clear();
router->GetLinkInfo().AddRss(linkInfo->mRss);
router->SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin.GetLinkMargin()));
router->SetLinkQualityOut(LinkQualityInfo::ConvertLinkMarginToLinkQuality(linkMargin));
router->ResetLinkFailures();
router->SetState(Neighbor::kStateValid);
router->SetKeySequence(aKeySequence);
@@ -991,24 +988,25 @@ otError MleRouter::HandleLinkAccept(const Message & aMessage,
if (aRequest)
{
ChallengeTlv challenge;
TlvRequestTlv tlvRequest;
Challenge challenge;
RequestedTlvs requestedTlvs;
// Challenge
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge));
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadChallenge(aMessage, challenge));
// TLV Request
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE)
switch (ReadTlvRequest(aMessage, requestedTlvs))
{
VerifyOrExit(tlvRequest.IsValid(), error = OT_ERROR_PARSE);
}
else
{
tlvRequest.SetLength(0);
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
requestedTlvs.mNumTlvs = 0;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
SuccessOrExit(error = SendLinkAccept(aMessageInfo, router, tlvRequest, challenge));
SuccessOrExit(error = SendLinkAccept(aMessageInfo, router, requestedTlvs, challenge));
}
exit:
@@ -1158,20 +1156,19 @@ otError MleRouter::HandleAdvertisement(const Message & aMessage,
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
uint8_t linkMargin = LinkQualityInfo::ConvertRssToLinkMargin(Get<Mac::Mac>().GetNoiseFloor(), linkInfo->mRss);
Mac::ExtAddress macAddr;
SourceAddressTlv sourceAddress;
LeaderDataTlv leaderData;
RouteTlv route;
uint32_t partitionId;
Router * router;
uint8_t routerId;
uint8_t routerCount;
Mac::ExtAddress macAddr;
uint16_t sourceAddress;
LeaderDataTlv leaderData;
RouteTlv route;
uint32_t partitionId;
Router * router;
uint8_t routerId;
uint8_t routerCount;
aMessageInfo.GetPeerAddr().ToExtAddress(macAddr);
// Source Address
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress));
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress));
// Leader Data
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLeaderData, sizeof(leaderData), leaderData));
@@ -1235,8 +1232,8 @@ otError MleRouter::HandleAdvertisement(const Message & aMessage,
ExitNow();
}
VerifyOrExit(IsActiveRouter(sourceAddress.GetRloc16()) && route.IsValid());
routerId = RouterIdFromRloc16(sourceAddress.GetRloc16());
VerifyOrExit(IsActiveRouter(sourceAddress) && route.IsValid());
routerId = RouterIdFromRloc16(sourceAddress);
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
Get<TimeSync>().HandleTimeSyncMessage(aMessage);
@@ -1255,7 +1252,7 @@ otError MleRouter::HandleAdvertisement(const Message & aMessage,
break;
case OT_DEVICE_ROLE_CHILD:
if (sourceAddress.GetRloc16() == mParent.GetRloc16())
if (sourceAddress == mParent.GetRloc16())
{
processRouteTlv = true;
}
@@ -1295,7 +1292,7 @@ otError MleRouter::HandleAdvertisement(const Message & aMessage,
// MLE Advertisement from parent
router = &mParent;
if (mParent.GetRloc16() != sourceAddress.GetRloc16())
if (mParent.GetRloc16() != sourceAddress)
{
BecomeDetached();
ExitNow(error = OT_ERROR_NO_ROUTE);
@@ -1418,7 +1415,7 @@ otError MleRouter::HandleAdvertisement(const Message & aMessage,
UpdateRoutes(route, routerId);
exit:
if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress.GetRloc16())
if (aNeighbor && aNeighbor->GetRloc16() != sourceAddress)
{
// Remove stale neighbors
RemoveNeighbor(*aNeighbor);
@@ -1585,9 +1582,9 @@ otError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::Messa
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
Mac::ExtAddress macAddr;
VersionTlv version;
ScanMaskTlv scanMask;
ChallengeTlv challenge;
uint16_t version;
uint8_t scanMask;
Challenge challenge;
Router * leader;
Child * child;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
@@ -1624,12 +1621,11 @@ otError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::Messa
aMessageInfo.GetPeerAddr().ToExtAddress(macAddr);
// Version
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kVersion, sizeof(version), version));
VerifyOrExit(version.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kVersion, version));
VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
// Scan Mask
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kScanMask, sizeof(scanMask), scanMask));
VerifyOrExit(scanMask.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint8Tlv(aMessage, Tlv::kScanMask, scanMask));
switch (mRole)
{
@@ -1638,18 +1634,17 @@ otError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::Messa
ExitNow();
case OT_DEVICE_ROLE_CHILD:
VerifyOrExit(scanMask.IsEndDeviceFlagSet());
VerifyOrExit(ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
break;
case OT_DEVICE_ROLE_ROUTER:
case OT_DEVICE_ROLE_LEADER:
VerifyOrExit(scanMask.IsRouterFlagSet());
VerifyOrExit(ScanMaskTlv::IsRouterFlagSet(scanMask));
break;
}
// Challenge
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge));
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadChallenge(aMessage, challenge));
child = mChildTable.FindChild(macAddr, Child::kInStateAnyExceptInvalid);
@@ -1685,7 +1680,7 @@ otError MleRouter::HandleParentRequest(const Message &aMessage, const Ip6::Messa
child->SetTimeout(Time::MsecToSec(kMaxChildIdRequestTimeout));
}
SendParentResponse(child, challenge, !scanMask.IsEndDeviceFlagSet());
SendParentResponse(child, challenge, !ScanMaskTlv::IsEndDeviceFlagSet(scanMask));
exit:
@@ -1911,7 +1906,7 @@ exit:
return;
}
void MleRouter::SendParentResponse(Child *aChild, const ChallengeTlv &aChallenge, bool aRoutersOnlyRequest)
void MleRouter::SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest)
{
otError error = OT_ERROR_NONE;
Ip6::Address destination;
@@ -1926,7 +1921,7 @@ void MleRouter::SendParentResponse(Child *aChild, const ChallengeTlv &aChallenge
SuccessOrExit(error = AppendLeaderData(*message));
SuccessOrExit(error = AppendLinkFrameCounter(*message));
SuccessOrExit(error = AppendMleFrameCounter(*message));
SuccessOrExit(error = AppendResponse(*message, aChallenge.GetChallenge(), aChallenge.GetChallengeLength()));
SuccessOrExit(error = AppendResponse(*message, aChallenge));
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
if (aChild->IsTimeSyncEnabled())
{
@@ -2087,13 +2082,14 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
Mac::ExtAddress macAddr;
VersionTlv version;
ResponseTlv response;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
ModeTlv mode;
TimeoutTlv timeout;
TlvRequestTlv tlvRequest;
uint16_t version;
Challenge response;
uint32_t linkFrameCounter;
uint32_t mleFrameCounter;
uint8_t modeBitmask;
DeviceMode mode;
uint32_t timeout;
RequestedTlvs requestedTlvs;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
Child * child;
@@ -2115,14 +2111,12 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
VerifyOrExit(child != NULL, error = OT_ERROR_ALREADY);
// Version
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kVersion, sizeof(version), version));
VerifyOrExit(version.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint16Tlv(aMessage, Tlv::kVersion, version));
VerifyOrExit(version >= OT_THREAD_VERSION_1_1, error = OT_ERROR_PARSE);
// Response
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response));
VerifyOrExit(response.IsValid() &&
memcmp(response.GetResponse(), child->GetChallenge(), child->GetChallengeSize()) == 0,
error = OT_ERROR_SECURITY);
SuccessOrExit(error = ReadResponse(aMessage, response));
VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = OT_ERROR_SECURITY);
// Remove existing MLE messages
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleGeneral);
@@ -2131,30 +2125,30 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
Get<MeshForwarder>().RemoveMessages(*child, Message::kSubTypeMleDataResponse);
// Link-Layer Frame Counter
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter));
VerifyOrExit(linkFrameCounter.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint32Tlv(aMessage, Tlv::kLinkFrameCounter, linkFrameCounter));
// MLE Frame Counter
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kMleFrameCounter, mleFrameCounter))
{
VerifyOrExit(mleFrameCounter.IsValid(), error = OT_ERROR_PARSE);
}
else
{
mleFrameCounter.SetFrameCounter(linkFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
break;
case OT_ERROR_NOT_FOUND:
mleFrameCounter = linkFrameCounter;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Mode
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kMode, sizeof(mode), mode));
VerifyOrExit(mode.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint8Tlv(aMessage, Tlv::kMode, modeBitmask));
mode.Set(modeBitmask);
// Timeout
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout));
VerifyOrExit(timeout.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint32Tlv(aMessage, Tlv::kTimeout, timeout));
// TLV Request
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest));
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= Child::kMaxRequestTlvs, error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadTlvRequest(aMessage, requestedTlvs));
VerifyOrExit(requestedTlvs.mNumTlvs <= Child::kMaxRequestTlvs, error = OT_ERROR_PARSE);
// Active Timestamp
activeTimestamp.SetLength(0);
@@ -2172,7 +2166,7 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
VerifyOrExit(pendingTimestamp.IsValid(), error = OT_ERROR_PARSE);
}
if (!mode.GetMode().IsFullThreadDevice())
if (!mode.IsFullThreadDevice())
{
SuccessOrExit(error = Tlv::GetOffset(aMessage, Tlv::kAddressRegistration, addressRegistrationOffset));
SuccessOrExit(error = UpdateChildAddresses(aMessage, addressRegistrationOffset, *child));
@@ -2195,15 +2189,15 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
}
child->SetLastHeard(TimerMilli::GetNow());
child->SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
child->SetMleFrameCounter(mleFrameCounter.GetFrameCounter());
child->SetLinkFrameCounter(linkFrameCounter);
child->SetMleFrameCounter(mleFrameCounter);
child->SetKeySequence(aKeySequence);
child->SetDeviceMode(mode.GetMode());
child->SetVersion(static_cast<uint8_t>(version.GetVersion()));
child->SetDeviceMode(mode);
child->SetVersion(static_cast<uint8_t>(version));
child->GetLinkInfo().AddRss(linkInfo->mRss);
child->SetTimeout(timeout.GetTimeout());
child->SetTimeout(timeout);
if (mode.GetMode().IsFullNetworkData())
if (mode.IsFullNetworkData())
{
child->SetNetworkDataVersion(mLeaderData.GetDataVersion());
}
@@ -2214,9 +2208,9 @@ otError MleRouter::HandleChildIdRequest(const Message & aMessage,
child->ClearRequestTlvs();
for (numTlvs = 0; numTlvs < tlvRequest.GetLength(); numTlvs++)
for (numTlvs = 0; numTlvs < requestedTlvs.mNumTlvs; numTlvs++)
{
child->SetRequestTlv(numTlvs, tlvRequest.GetTlvs()[numTlvs]);
child->SetRequestTlv(numTlvs, requestedTlvs.mTlvs[numTlvs]);
}
if (activeTimestamp.GetLength() == 0 || Get<MeshCoP::ActiveDataset>().Compare(activeTimestamp) != 0)
@@ -2265,13 +2259,14 @@ otError MleRouter::HandleChildUpdateRequest(const Message & aMessage,
otError error = OT_ERROR_NONE;
Mac::ExtAddress macAddr;
ModeTlv mode;
ChallengeTlv challenge;
uint8_t modeBitmask;
DeviceMode mode;
Challenge challenge;
LeaderDataTlv leaderData;
TimeoutTlv timeout;
uint32_t timeout;
Child * child;
DeviceMode oldMode;
TlvRequestTlv tlvRequest;
RequestedTlvs requestedTlvs;
uint8_t tlvs[kMaxResponseTlvs];
uint8_t tlvslength = 0;
uint16_t addressRegistrationOffset = 0;
@@ -2280,15 +2275,20 @@ otError MleRouter::HandleChildUpdateRequest(const Message & aMessage,
LogMleMessage("Receive Child Update Request from child", aMessageInfo.GetPeerAddr());
// Mode
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kMode, sizeof(mode), mode));
VerifyOrExit(mode.IsValid(), error = OT_ERROR_PARSE);
SuccessOrExit(error = Tlv::ReadUint8Tlv(aMessage, Tlv::kMode, modeBitmask));
mode.Set(modeBitmask);
// Challenge
challenge.SetLength(0);
if (Tlv::GetTlv(aMessage, Tlv::kChallenge, sizeof(challenge), challenge) == OT_ERROR_NONE)
switch (ReadChallenge(aMessage, challenge))
{
VerifyOrExit(challenge.IsValid(), error = OT_ERROR_PARSE);
case OT_ERROR_NONE:
tlvs[tlvslength++] = Tlv::kResponse;
break;
case OT_ERROR_NOT_FOUND:
challenge.mLength = 0;
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Find Child
@@ -2302,7 +2302,7 @@ otError MleRouter::HandleChildUpdateRequest(const Message & aMessage,
if (child == NULL || child->IsStateInvalid())
{
// For invalid non-sleepy child, Send Child Update Response with status TLV (error)
if (mode.GetMode().IsRxOnWhenIdle())
if (mode.IsRxOnWhenIdle())
{
tlvs[tlvslength++] = Tlv::kStatus;
SendChildUpdateResponse(NULL, aMessageInfo, tlvs, tlvslength, challenge);
@@ -2312,14 +2312,14 @@ otError MleRouter::HandleChildUpdateRequest(const Message & aMessage,
}
oldMode = child->GetDeviceMode();
child->SetDeviceMode(mode.GetMode());
child->SetDeviceMode(mode);
tlvs[tlvslength++] = Tlv::kMode;
// Parent MUST include Leader Data TLV in Child Update Response
tlvs[tlvslength++] = Tlv::kLeaderData;
if (challenge.IsValid())
if (challenge.mLength != 0)
{
tlvs[tlvslength++] = Tlv::kMleFrameCounter;
tlvs[tlvslength++] = Tlv::kLinkFrameCounter;
@@ -2339,36 +2339,43 @@ otError MleRouter::HandleChildUpdateRequest(const Message & aMessage,
}
// Timeout
if (Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kTimeout, timeout))
{
VerifyOrExit(timeout.IsValid(), error = OT_ERROR_PARSE);
if (child->GetTimeout() != timeout.GetTimeout())
case OT_ERROR_NONE:
if (child->GetTimeout() != timeout)
{
child->SetTimeout(timeout.GetTimeout());
child->SetTimeout(timeout);
childDidChange = true;
}
tlvs[tlvslength++] = Tlv::kTimeout;
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// TLV Request
if (Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest) == OT_ERROR_NONE)
switch (ReadTlvRequest(aMessage, requestedTlvs))
{
uint8_t tlv;
TlvRequestIterator iterator = TLVREQUESTTLV_ITERATOR_INIT;
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= (kMaxResponseTlvs - tlvslength),
error = OT_ERROR_PARSE);
while (tlvRequest.GetNextTlv(iterator, tlv) == OT_ERROR_NONE)
case OT_ERROR_NONE:
VerifyOrExit(requestedTlvs.mNumTlvs <= (kMaxResponseTlvs - tlvslength), error = OT_ERROR_PARSE);
for (uint8_t i = 0; i < requestedTlvs.mNumTlvs; i++)
{
// Here skips Tlv::kLeaderData because it has already been included by default
if (tlv != Tlv::kLeaderData)
// Skip LeaderDataTlv since it is already included by default.
if (requestedTlvs.mTlvs[i] != Tlv::kLeaderData)
{
tlvs[tlvslength++] = tlv;
tlvs[tlvslength++] = requestedTlvs.mTlvs[i];
}
}
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
child->SetLastHeard(TimerMilli::GetNow());
@@ -2420,12 +2427,12 @@ otError MleRouter::HandleChildUpdateResponse(const Message & aMessage,
{
otError error = OT_ERROR_NONE;
const otThreadLinkInfo *linkInfo = static_cast<const otThreadLinkInfo *>(aMessageInfo.GetLinkInfo());
SourceAddressTlv sourceAddress;
TimeoutTlv timeout;
ResponseTlv response;
StatusTlv status;
LinkFrameCounterTlv linkFrameCounter;
MleFrameCounterTlv mleFrameCounter;
uint16_t sourceAddress;
uint32_t timeout;
Challenge response;
uint8_t status;
uint32_t linkFrameCounter;
uint32_t mleFrameCounter;
LeaderDataTlv leaderData;
Child * child;
uint16_t addressRegistrationOffset = 0;
@@ -2439,62 +2446,86 @@ otError MleRouter::HandleChildUpdateResponse(const Message & aMessage,
child = static_cast<Child *>(aNeighbor);
// Response
if (Tlv::GetTlv(aMessage, Tlv::kResponse, sizeof(response), response) == OT_ERROR_NONE)
{
VerifyOrExit(response.IsValid() &&
memcmp(response.GetResponse(), child->GetChallenge(), child->GetChallengeSize()) == 0,
error = OT_ERROR_SECURITY);
}
else
switch (ReadResponse(aMessage, response))
{
case OT_ERROR_NONE:
VerifyOrExit(response.Matches(child->GetChallenge(), child->GetChallengeSize()), error = OT_ERROR_SECURITY);
break;
case OT_ERROR_NOT_FOUND:
VerifyOrExit(child->IsStateValid(), error = OT_ERROR_SECURITY);
break;
default:
ExitNow(error = OT_ERROR_NONE);
}
LogMleMessage("Receive Child Update Response from child", aMessageInfo.GetPeerAddr(), child->GetRloc16());
// Source Address
if (Tlv::GetTlv(aMessage, Tlv::kSourceAddress, sizeof(sourceAddress), sourceAddress) == OT_ERROR_NONE)
switch (Tlv::ReadUint16Tlv(aMessage, Tlv::kSourceAddress, sourceAddress))
{
VerifyOrExit(sourceAddress.IsValid(), error = OT_ERROR_PARSE);
if (child->GetRloc16() != sourceAddress.GetRloc16())
case OT_ERROR_NONE:
if (child->GetRloc16() != sourceAddress)
{
RemoveNeighbor(*child);
ExitNow();
}
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Status
if (Tlv::GetTlv(aMessage, Tlv::kStatus, sizeof(status), status) == OT_ERROR_NONE)
switch (Tlv::ReadUint8Tlv(aMessage, Tlv::kStatus, status))
{
VerifyOrExit(status.IsValid(), error = OT_ERROR_PARSE);
if (status.GetStatus() == StatusTlv::kError)
{
RemoveNeighbor(*child);
ExitNow();
}
case OT_ERROR_NONE:
VerifyOrExit(status != StatusTlv::kError, RemoveNeighbor(*child));
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Link-Layer Frame Counter
if (Tlv::GetTlv(aMessage, Tlv::kLinkFrameCounter, sizeof(linkFrameCounter), linkFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kLinkFrameCounter, linkFrameCounter))
{
VerifyOrExit(linkFrameCounter.IsValid(), error = OT_ERROR_PARSE);
child->SetLinkFrameCounter(linkFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
child->SetLinkFrameCounter(linkFrameCounter);
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// MLE Frame Counter
if (Tlv::GetTlv(aMessage, Tlv::kMleFrameCounter, sizeof(mleFrameCounter), mleFrameCounter) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kMleFrameCounter, mleFrameCounter))
{
VerifyOrExit(mleFrameCounter.IsValid(), error = OT_ERROR_PARSE);
child->SetMleFrameCounter(mleFrameCounter.GetFrameCounter());
case OT_ERROR_NONE:
child->SetMleFrameCounter(mleFrameCounter);
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_NONE);
}
// Timeout
if (Tlv::GetTlv(aMessage, Tlv::kTimeout, sizeof(timeout), timeout) == OT_ERROR_NONE)
switch (Tlv::ReadUint32Tlv(aMessage, Tlv::kTimeout, timeout))
{
VerifyOrExit(timeout.IsValid(), error = OT_ERROR_PARSE);
child->SetTimeout(timeout.GetTimeout());
case OT_ERROR_NONE:
child->SetTimeout(timeout);
break;
case OT_ERROR_NOT_FOUND:
break;
default:
ExitNow(error = OT_ERROR_PARSE);
}
// Ip6 Address
@@ -2538,7 +2569,7 @@ otError MleRouter::HandleDataRequest(const Message & aMessage,
const Neighbor * aNeighbor)
{
otError error = OT_ERROR_NONE;
TlvRequestTlv tlvRequest;
RequestedTlvs requestedTlvs;
ActiveTimestampTlv activeTimestamp;
PendingTimestampTlv pendingTimestamp;
uint8_t tlvs[4];
@@ -2549,8 +2580,8 @@ otError MleRouter::HandleDataRequest(const Message & aMessage,
VerifyOrExit(aNeighbor && aNeighbor->IsStateValid(), error = OT_ERROR_SECURITY);
// TLV Request
SuccessOrExit(error = Tlv::GetTlv(aMessage, Tlv::kTlvRequest, sizeof(tlvRequest), tlvRequest));
VerifyOrExit(tlvRequest.IsValid() && tlvRequest.GetLength() <= sizeof(tlvs), error = OT_ERROR_PARSE);
SuccessOrExit(error = ReadTlvRequest(aMessage, requestedTlvs));
VerifyOrExit(requestedTlvs.mNumTlvs <= sizeof(tlvs), error = OT_ERROR_PARSE);
// Active Timestamp
activeTimestamp.SetLength(0);
@@ -2569,8 +2600,8 @@ otError MleRouter::HandleDataRequest(const Message & aMessage,
}
memset(tlvs, Tlv::kInvalid, sizeof(tlvs));
memcpy(tlvs, tlvRequest.GetTlvs(), tlvRequest.GetLength());
numTlvs = tlvRequest.GetLength();
memcpy(tlvs, requestedTlvs.mTlvs, requestedTlvs.mNumTlvs);
numTlvs = requestedTlvs.mNumTlvs;
if (activeTimestamp.GetLength() == 0 || Get<MeshCoP::ActiveDataset>().Compare(activeTimestamp))
{
@@ -3052,7 +3083,7 @@ void MleRouter::SendChildUpdateResponse(Child * aChild,
const Ip6::MessageInfo &aMessageInfo,
const uint8_t * aTlvs,
uint8_t aTlvsLength,
const ChallengeTlv & aChallenge)
const Challenge & aChallenge)
{
otError error = OT_ERROR_NONE;
Message *message;
@@ -3087,7 +3118,7 @@ void MleRouter::SendChildUpdateResponse(Child * aChild,
break;
case Tlv::kResponse:
SuccessOrExit(error = AppendResponse(*message, aChallenge.GetChallenge(), aChallenge.GetChallengeLength()));
SuccessOrExit(error = AppendResponse(*message, aChallenge));
break;
case Tlv::kSourceAddress:
@@ -4062,7 +4093,7 @@ void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::Message
ThreadStatusTlv statusTlv;
Router * router = NULL;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
XtalAccuracyTlv xtalAccuracyTlv;
uint16_t xtalAccuracy;
#endif
VerifyOrExit(aMessage.GetType() == OT_COAP_TYPE_CONFIRMABLE && aMessage.GetCode() == OT_COAP_CODE_POST,
@@ -4078,11 +4109,8 @@ void MleRouter::HandleAddressSolicit(Coap::Message &aMessage, const Ip6::Message
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
// In a time sync enabled network, all routers' xtal accuracy must be less than the threshold.
if (Tlv::GetTlv(aMessage, Tlv::kXtalAccuracy, sizeof(xtalAccuracyTlv), xtalAccuracyTlv) != OT_ERROR_NONE ||
xtalAccuracyTlv.GetXtalAccuracy() > Get<TimeSync>().GetXtalThreshold())
{
ExitNow(router = NULL);
}
SuccessOrExit(Tlv::ReadUint16Tlv(aMessage, Tlv::kXtalAccuracy, xtalAccuracy));
VerifyOrExit(xtalAccuracy <= Get<TimeSync>().GetXtalThreshold());
#endif
// see if allocation already exists
+7 -6
View File
@@ -716,16 +716,16 @@ private:
otError SendAdvertisement(void);
otError SendLinkAccept(const Ip6::MessageInfo &aMessageInfo,
Neighbor * aNeighbor,
const TlvRequestTlv & aTlvRequest,
const ChallengeTlv & aChallenge);
void SendParentResponse(Child *aChild, const ChallengeTlv &aChallenge, bool aRoutersOnlyRequest);
const RequestedTlvs & aRequestedTlvs,
const Challenge & aChallenge);
void SendParentResponse(Child *aChild, const Challenge &aChallenge, bool aRoutersOnlyRequest);
otError SendChildIdResponse(Child &aChild);
otError SendChildUpdateRequest(Child &aChild);
void SendChildUpdateResponse(Child * aChild,
const Ip6::MessageInfo &aMessageInfo,
const uint8_t * aTlvs,
uint8_t aTlvsLength,
const ChallengeTlv & aChallenge);
const Challenge & aChallenge);
otError SendDataResponse(const Ip6::Address &aDestination,
const uint8_t * aTlvs,
uint8_t aTlvsLength,
@@ -777,8 +777,9 @@ private:
otNeighborTableCallback mNeighborTableChangedCallback;
uint8_t mChallengeTimeout;
uint8_t mChallenge[8];
uint8_t mChallengeTimeout;
Challenge mChallenge;
uint16_t mNextChildId;
uint8_t mNetworkIdTimeout;
uint8_t mRouterUpgradeThreshold;
+14 -816
View File
@@ -41,7 +41,6 @@
#include "common/tlvs.hpp"
#include "meshcop/timestamp.hpp"
#include "net/ip6_address.hpp"
#include "thread/device_mode.hpp"
#include "thread/mle_constants.hpp"
namespace ot {
@@ -170,322 +169,6 @@ public:
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class SourceAddressTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kSourceAddress);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the RLOC16 value.
*
* @returns The RLOC16 value.
*
*/
uint16_t GetRloc16(void) const { return HostSwap16(mRloc16); }
/**
* This method sets the RLOC16 value.
*
* @param[in] aRloc16 The RLOC16 value.
*
*/
void SetRloc16(uint16_t aRloc16) { mRloc16 = HostSwap16(aRloc16); }
private:
uint16_t mRloc16;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class ModeTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kMode);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Mode value.
*
* @returns The Mode value.
*
*/
DeviceMode GetMode(void) const { return DeviceMode(mMode); }
/**
* This method sets the Mode value.
*
* @param[in] aMode The Mode value.
*
*/
void SetMode(DeviceMode aMode) { mMode = aMode.Get(); }
private:
uint8_t mMode;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class TimeoutTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kTimeout);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Timeout value.
*
* @returns The Timeout value.
*
*/
uint32_t GetTimeout(void) const { return HostSwap32(mTimeout); }
/**
* This method sets the Timeout value.
*
* @param[in] aTimeout The Timeout value.
*
*/
void SetTimeout(uint32_t aTimeout) { mTimeout = HostSwap32(aTimeout); }
private:
uint32_t mTimeout;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class ChallengeTlv : public Tlv
{
public:
enum
{
kMinSize = 4, ///< Minimum size in bytes (Thread Specification).
kMaxSize = 8, ///< Maximum size in bytes (Thread Specification).
};
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kChallenge);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= kMinSize; }
/**
* This method returns the Challenge length.
*
* @returns The Challenge length.
*
*/
uint8_t GetChallengeLength(void) const
{
return GetLength() <= sizeof(mChallenge) ? GetLength() : sizeof(mChallenge);
}
/**
* This method returns a pointer to the Challenge value.
*
* @returns A pointer to the Challenge value.
*
*/
const uint8_t *GetChallenge(void) const { return mChallenge; }
/**
* This method sets the Challenge value.
*
* @param[in] aChallenge A pointer to the Challenge value.
*
*/
void SetChallenge(const uint8_t *aChallenge) { memcpy(mChallenge, aChallenge, GetChallengeLength()); }
private:
uint8_t mChallenge[kMaxSize];
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class ResponseTlv : public Tlv
{
public:
enum
{
kMinSize = 4, ///< Minimum size in bytes (Thread Specification).
kMaxSize = 8, ///< Maximum size in bytes (Thread Specification).
};
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kResponse);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* This method indicates whether or not the TLV appears to be well-formed.
*
* OpenThread only generates Challenge values with 8-byte length. As a result, Response value lengths must also
* have 8-byte length.
*
* @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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Response length.
*
* @returns The Response length.
*
*/
uint8_t GetResponseLength(void) const { return GetLength() <= sizeof(mResponse) ? GetLength() : sizeof(mResponse); }
/**
* This method returns a pointer to the Response value.
*
* @returns A pointer to the Response value.
*
*/
const uint8_t *GetResponse(void) const { return mResponse; }
/**
* This method sets the Response value.
*
* @param[in] aResponse A pointer to the Response value.
*
*/
void SetResponse(const uint8_t *aResponse) { memcpy(mResponse, aResponse, GetResponseLength()); }
private:
uint8_t mResponse[kMaxSize];
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class LinkFrameCounterTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kLinkFrameCounter);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Frame Counter value.
*
* @returns The Frame Counter value.
*
*/
uint32_t GetFrameCounter(void) const { return HostSwap32(mFrameCounter); }
/**
* This method sets the Frame Counter value.
*
* @param[in] aFrameCounter The Frame Counter value.
*
*/
void SetFrameCounter(uint32_t aFrameCounter) { mFrameCounter = HostSwap32(aFrameCounter); }
private:
uint32_t mFrameCounter;
} OT_TOOL_PACKED_END;
#if !OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
/**
@@ -886,100 +569,6 @@ private:
#endif // OPENTHREAD_CONFIG_MLE_LONG_ROUTES_ENABLE
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class MleFrameCounterTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kMleFrameCounter);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Frame Counter value.
*
* @returns The Frame Counter value.
*
*/
uint32_t GetFrameCounter(void) const { return HostSwap32(mFrameCounter); }
/**
* This method sets the Frame Counter value.
*
* @param[in] aFrameCounter The Frame Counter value.
*
*/
void SetFrameCounter(uint32_t aFrameCounter) { mFrameCounter = HostSwap32(aFrameCounter); }
private:
uint32_t mFrameCounter;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class Address16Tlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kAddress16);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the RLOC16 value.
*
* @returns The RLOC16 value.
*
*/
uint16_t GetRloc16(void) const { return HostSwap16(mRloc16); }
/**
* This method sets the RLOC16 value.
*
* @param[in] aRloc16 The RLOC16 value.
*
*/
void SetRloc16(uint16_t aRloc16) { mRloc16 = HostSwap16(aRloc16); }
private:
uint16_t mRloc16;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
@@ -1102,199 +691,38 @@ private:
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
* This class implements Scan Mask TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class NetworkDataTlv : public Tlv
class ScanMaskTlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kNetworkData);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* This method returns a pointer to the Network Data.
*
* @returns A pointer to the Network Data.
*
*/
uint8_t *GetNetworkData(void) { return mNetworkData; }
/**
* This method sets the Network Data.
*
* @param[in] aNetworkData A pointer to the Network Data.
*
*/
void SetNetworkData(const uint8_t *aNetworkData) { memcpy(mNetworkData, aNetworkData, GetLength()); }
private:
uint8_t mNetworkData[255];
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class TlvRequestTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kTlvRequest);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() <= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns a pointer to the TLV list.
*
* @returns A pointer to the TLV list.
*
*/
const uint8_t *GetTlvs(void) const { return mTlvs; }
/**
* This method provides the next Tlv in the TlvRequestTlv.
*
* @retval OT_ERROR_NONE Successfully found the next Tlv.
* @retval OT_ERROR_NOT_FOUND No subsequent Tlv exists in TlvRequestTlv.
*
*/
otError GetNextTlv(TlvRequestIterator &aIterator, uint8_t &aTlv) const
{
otError error = OT_ERROR_NOT_FOUND;
if (aIterator < GetLength())
{
aTlv = mTlvs[aIterator];
aIterator = static_cast<TlvRequestIterator>(aIterator + sizeof(uint8_t));
error = OT_ERROR_NONE;
}
return error;
}
/**
* This method sets the list of TLVs.
*
* @param[in] aTlvs A pointer to the TLV list.
*
*/
void SetTlvs(const uint8_t *aTlvs) { memcpy(mTlvs, aTlvs, GetLength()); }
private:
enum
{
kMaxTlvs = 8,
kRouterFlag = 1 << 7, ///< Scan Mask Router Flag.
kEndDeviceFlag = 1 << 6, ///< Scan Mask End Device Flag.
};
uint8_t mTlvs[kMaxTlvs];
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class ScanMaskTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kScanMask);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
enum
{
kRouterFlag = 1 << 7,
kEndDeviceFlag = 1 << 6,
};
/**
* This method clears Router flag.
*
*/
void ClearRouterFlag(void) { mMask &= ~kRouterFlag; }
/**
* This method sets the Router flag.
*
*/
void SetRouterFlag(void) { mMask |= kRouterFlag; }
/**
* This method indicates whether or not the Router flag is set.
*
* @param[in] aMask A scan mask value.
*
* @retval TRUE If the Router flag is set.
* @retval FALSE If the Router flag is not set.
*/
bool IsRouterFlagSet(void) const { return (mMask & kRouterFlag) != 0; }
/**
* This method clears the End Device flag.
*
*/
void ClearEndDeviceFlag(void) { mMask &= ~kEndDeviceFlag; }
/**
* This method sets the End Device flag.
*
*/
void SetEndDeviceFlag(void) { mMask |= kEndDeviceFlag; }
static bool IsRouterFlagSet(uint8_t aMask) { return (aMask & kRouterFlag) != 0; }
/**
* This method indicates whether or not the End Device flag is set.
*
* @param[in] aMask A scan mask value.
*
* @retval TRUE If the End Device flag is set.
* @retval FALSE If the End Device flag is not set.
*/
bool IsEndDeviceFlagSet(void) const { return (mMask & kEndDeviceFlag) != 0; }
/**
* This method sets the Mask byte value.
*
* @param[in] aMask The Mask byte value.
*
*/
void SetMask(uint8_t aMask) { mMask = aMask; }
private:
uint8_t mMask;
} OT_TOOL_PACKED_END;
static bool IsEndDeviceFlagSet(uint8_t aMask) { return (aMask & kEndDeviceFlag) != 0; }
};
/**
* This class implements Source Address TLV generation and parsing.
@@ -1523,79 +951,11 @@ private:
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
* This class specifies Status TLV status values.
*
*/
OT_TOOL_PACKED_BEGIN
class LinkMarginTlv : public Tlv
struct StatusTlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kLinkMargin);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the Link Margin value.
*
* @returns The Link Margin value.
*
*/
uint8_t GetLinkMargin(void) const { return mLinkMargin; }
/**
* This method sets the Link Margin value.
*
* @param[in] aLinkMargin The Link Margin value.
*
*/
void SetLinkMargin(uint8_t aLinkMargin) { mLinkMargin = aLinkMargin; }
private:
uint8_t mLinkMargin;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class StatusTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kStatus);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* Status values.
*/
@@ -1603,76 +963,7 @@ public:
{
kError = 1, ///< Error.
};
/**
* This method returns the Status value.
*
* @returns The Status value.
*
*/
Status GetStatus(void) const { return static_cast<Status>(mStatus); }
/**
* This method sets the Status value.
*
* @param[in] aStatus The Status value.
*
*/
void SetStatus(Status aStatus) { mStatus = static_cast<uint8_t>(aStatus); }
private:
uint8_t mStatus;
} OT_TOOL_PACKED_END;
/**
* This class implements Source Address TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class VersionTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kVersion);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* This method indicates whether or not the TLV appears to be well-formed and valid version.
*
* @retval TRUE If the TLV appears to be well-formed and with valid version.
* @retval FALSE If the TLV does not appear to be well-formed or with invalid version.
*
*/
bool IsValid(void) const
{
return (GetLength() >= sizeof(*this) - sizeof(Tlv)) && mVersion >= OT_THREAD_VERSION_1_1;
}
/**
* This method returns the Version value.
*
* @returns The Version value.
*
*/
uint16_t GetVersion(void) const { return HostSwap16(mVersion); }
/**
* This method sets the Version value.
*
* @param[in] aVersion The Version value.
*
*/
void SetVersion(uint16_t aVersion) { mVersion = HostSwap16(aVersion); }
private:
uint16_t mVersion;
} OT_TOOL_PACKED_END;
};
/**
* This class implements Source Address TLV generation and parsing.
@@ -1833,53 +1124,6 @@ private:
uint16_t mChannel;
} OT_TOOL_PACKED_END;
/**
* This class implements PAN ID TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class PanIdTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kPanId);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the PAN ID value.
*
* @returns The PAN ID value.
*
*/
uint16_t GetPanId(void) const { return HostSwap16(mPanId); }
/**
* This method sets the PAN ID value.
*
* @param[in] aPanId The PAN ID value.
*
*/
void SetPanId(uint16_t aPanId) { mPanId = HostSwap16(aPanId); }
private:
uint16_t mPanId;
} OT_TOOL_PACKED_END;
#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
* This class implements Time Request TLV generation and parsing.
@@ -1973,52 +1217,6 @@ private:
uint16_t mXtalThreshold;
} OT_TOOL_PACKED_END;
/**
* This class implements XTAL Accuracy TLV generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class XtalAccuracyTlv : public Tlv
{
public:
/**
* This method initializes the TLV.
*
*/
void Init(void)
{
SetType(kXtalAccuracy);
SetLength(sizeof(*this) - sizeof(Tlv));
}
/**
* 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 GetLength() >= sizeof(*this) - sizeof(Tlv); }
/**
* This method returns the XTAL accuracy.
*
* @returns The XTAL accuracy.
*
*/
uint16_t GetXtalAccuracy(void) const { return HostSwap16(mXtalAccuracy); }
/**
* This method sets the XTAL accuracy.
*
* @param[in] aXTALAccuracy The XTAL accuracy.
*
*/
void SetXtalAccuracy(uint16_t aXtalAccuracy) { mXtalAccuracy = HostSwap16(aXtalAccuracy); }
private:
uint16_t mXtalAccuracy;
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
/**
+6 -1
View File
@@ -379,9 +379,14 @@ otError NetworkDiagnostic::FillRequestedTlvs(Message & aRequest,
case NetworkDiagnosticTlv::kNetworkData:
{
NetworkDataTlv tlv;
uint8_t length;
tlv.Init();
Get<Mle::MleRouter>().FillNetworkDataTlv((reinterpret_cast<Mle::NetworkDataTlv &>(tlv)), false);
length = sizeof(NetworkDataTlv) - sizeof(Tlv); // sizeof( NetworkDataTlv::mNetworkData )
Get<NetworkData::Leader>().GetNetworkData(/* aStableOnly */ false, tlv.GetNetworkData(), length);
tlv.SetLength(length);
SuccessOrExit(error = tlv.AppendTo(aResponse));
break;
}
+4 -3
View File
@@ -47,6 +47,7 @@
#include "thread/device_mode.hpp"
#include "thread/indirect_sender.hpp"
#include "thread/link_quality.hpp"
#include "thread/mle_constants.hpp"
#include "thread/mle_tlvs.hpp"
namespace ot {
@@ -465,7 +466,7 @@ private:
} mValid;
struct
{
uint8_t mChallenge[Mle::ChallengeTlv::kMaxSize]; ///< The challenge value
uint8_t mChallenge[Mle::kMaxChallengeSize]; ///< The challenge value
} mPending;
} mValidPending;
@@ -745,8 +746,8 @@ private:
union
{
uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs
uint8_t mAttachChallenge[Mle::ChallengeTlv::kMaxSize]; ///< The challenge value
uint8_t mRequestTlvs[kMaxRequestTlvs]; ///< Requested MLE TLVs
uint8_t mAttachChallenge[Mle::kMaxChallengeSize]; ///< The challenge value
};
#if OPENTHREAD_CONFIG_CHILD_SUPERVISION_ENABLE