From a3b464044eaecd911148b24eba9d09e532e79e1e Mon Sep 17 00:00:00 2001 From: Jonathan Hui Date: Fri, 9 Dec 2016 09:56:34 -0800 Subject: [PATCH] Cleanup DatasetManager::Set(). (#1058) --- src/core/meshcop/dataset_manager.cpp | 199 +++++++++++------------ src/core/meshcop/dataset_manager_ftd.cpp | 17 +- 2 files changed, 97 insertions(+), 119 deletions(-) diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index 8e606cc82..bb9dc6805 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -325,135 +325,128 @@ void DatasetManager::Get(Coap::Header &aHeader, Message &aMessage, const Ip6::Me ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const Ip6::MessageInfo &aMessageInfo) { Tlv tlv; - Timestamp timestamp; + Timestamp *timestamp; uint16_t offset = aMessage.GetOffset(); Tlv::Type type; bool isUpdateFromCommissioner = false; - bool isUpdateAffectConnectivity = false; - bool isUpdateIdenticalValue = true; + bool doesAffectConnectivity = false; StateTlv::State state = StateTlv::kAccept; ActiveTimestampTlv activeTimestamp; - NetworkMasterKeyTlv masterKey; + PendingTimestampTlv pendingTimestamp; ChannelTlv channel; + CommissionerSessionIdTlv sessionId; MeshLocalPrefixTlv meshLocalPrefix; + NetworkMasterKeyTlv masterKey; PanIdTlv panId; activeTimestamp.SetLength(0); - masterKey.SetLength(0); + pendingTimestamp.SetLength(0); channel.SetLength(0); + masterKey.SetLength(0); meshLocalPrefix.SetLength(0); panId.SetLength(0); + pendingTimestamp.SetLength(0); + sessionId.SetLength(0); VerifyOrExit(mMle.GetDeviceState() == Mle::kDeviceStateLeader, state = StateTlv::kReject); - type = (strcmp(mUriSet, OPENTHREAD_URI_ACTIVE_SET) == 0 ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp); - + // verify that TLV data size is less than maximum TLV value size while (offset < aMessage.GetLength()) { - Tlv::Type tlvType; - aMessage.Read(offset, sizeof(tlv), &tlv); - tlvType = tlv.GetType(); - - if (tlvType == type) - { - aMessage.Read(offset + sizeof(tlv), sizeof(timestamp), ×tamp); - } - - switch (tlvType) - { - case Tlv::kActiveTimestamp: - aMessage.Read(offset, sizeof(activeTimestamp), &activeTimestamp); - break; - - case Tlv::kNetworkMasterKey: - aMessage.Read(offset, sizeof(masterKey), &masterKey); - break; - - case Tlv::kChannel: - aMessage.Read(offset, sizeof(channel), &channel); - VerifyOrExit(channel.GetChannel() >= kPhyMinChannel && channel.GetChannel() <= kPhyMaxChannel, - state = StateTlv::kReject); - break; - - case Tlv::kMeshLocalPrefix: - aMessage.Read(offset, sizeof(meshLocalPrefix), &meshLocalPrefix); - break; - - case Tlv::kPanId: - aMessage.Read(offset, sizeof(panId), &panId); - break; - - default: - break; - } - - // verify the request does not include fields that affect connectivity - if ((type == Tlv::kActiveTimestamp) && - (tlvType == Tlv::kChannel || tlvType == Tlv::kMeshLocalPrefix || - tlvType == Tlv::kPanId || tlvType == Tlv::kNetworkMasterKey)) - { - isUpdateAffectConnectivity = true; - } - - // verify session id is the same - if (tlvType == Tlv::kCommissionerSessionId) - { - CommissionerSessionIdTlv *sessionId; - uint16_t rxSessionId; - - isUpdateFromCommissioner = true; - - sessionId = static_cast(mNetworkDataLeader.GetCommissioningDataSubTlv( - Tlv::kCommissionerSessionId)); - aMessage.Read(offset + sizeof(tlv), sizeof(rxSessionId), &rxSessionId); - - VerifyOrExit(sessionId != NULL && sessionId->GetCommissionerSessionId() == rxSessionId, - state = StateTlv::kReject); - } - - // verify that TLV data size is less than maximum TLV value size VerifyOrExit(tlv.GetLength() <= Dataset::kMaxValueSize, state = StateTlv::kReject); - offset += sizeof(tlv) + tlv.GetLength(); } - // verify whether or not tlv value is identical with current one - if (isUpdateAffectConnectivity && - (channel.GetChannel() != mNetif.GetMac().GetChannel() || - panId.GetPanId() != mNetif.GetMac().GetPanId() || - memcmp(meshLocalPrefix.GetMeshLocalPrefix(), mNetif.GetMle().GetMeshLocalPrefix(), - meshLocalPrefix.GetLength()) != 0 || - memcmp(masterKey.GetNetworkMasterKey(), mNetif.GetKeyManager().GetMasterKey(NULL), - masterKey.GetLength()) != 0)) - { - isUpdateIdenticalValue = false; - otLogInfoMeshCoP("Request includes tlv that affects connectivity."); - } - - // verify the update from commissioner should not contain tlv would affect connectivity - VerifyOrExit(!isUpdateFromCommissioner || !(isUpdateAffectConnectivity && !isUpdateIdenticalValue), - state = StateTlv::kReject); - - // verify the request includes a timestamp that is ahead of the locally stored value - VerifyOrExit(offset == aMessage.GetLength() && (mLocal.GetTimestamp() == NULL || - mLocal.GetTimestamp()->Compare(timestamp) > 0), state = StateTlv::kReject); - - // verify network master key if active timestamp is behind - if (type == Tlv::kPendingTimestamp) - { - const Timestamp *localActiveTimestamp = mNetif.GetActiveDataset().GetNetwork().GetTimestamp(); - - if (localActiveTimestamp != NULL && localActiveTimestamp->Compare(activeTimestamp) <= 0) - { - VerifyOrExit(masterKey.GetLength() != 0, state = StateTlv::kReject); - } - } - // verify that does not overflow dataset buffer VerifyOrExit((offset - aMessage.GetOffset()) <= Dataset::kMaxSize, state = StateTlv::kReject); + type = (strcmp(mUriSet, OPENTHREAD_URI_ACTIVE_SET) == 0 ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp); + + if (Tlv::GetTlv(aMessage, Tlv::kActiveTimestamp, sizeof(activeTimestamp), activeTimestamp) != kThreadError_None) + { + ExitNow(state = StateTlv::kReject); + } + + Tlv::GetTlv(aMessage, Tlv::kPendingTimestamp, sizeof(pendingTimestamp), pendingTimestamp); + + // verify the request includes a timestamp that is ahead of the locally stored value + timestamp = (type == Tlv::kActiveTimestamp) ? + static_cast(&activeTimestamp) : + static_cast(&pendingTimestamp); + + VerifyOrExit(mLocal.GetTimestamp() == NULL || mLocal.GetTimestamp()->Compare(*timestamp) > 0, + state = StateTlv::kReject); + + // check channel + if (Tlv::GetTlv(aMessage, Tlv::kChannel, sizeof(channel), channel) == kThreadError_None) + { + VerifyOrExit(channel.GetChannel() >= kPhyMinChannel && channel.GetChannel() <= kPhyMaxChannel, + state = StateTlv::kReject); + + if (type == Tlv::kActiveTimestamp && channel.GetChannel() != mNetif.GetMac().GetChannel()) + { + doesAffectConnectivity = true; + } + } + + // check PAN ID + if (Tlv::GetTlv(aMessage, Tlv::kPanId, sizeof(panId), panId) == kThreadError_None && + type == Tlv::kActiveTimestamp && + panId.GetPanId() != mNetif.GetMac().GetPanId()) + { + doesAffectConnectivity = true; + } + + // check mesh local prefix + if (Tlv::GetTlv(aMessage, Tlv::kMeshLocalPrefix, sizeof(meshLocalPrefix), meshLocalPrefix) == kThreadError_None && + type == Tlv::kActiveTimestamp && + memcmp(meshLocalPrefix.GetMeshLocalPrefix(), mNetif.GetMle().GetMeshLocalPrefix(), + meshLocalPrefix.GetLength())) + { + doesAffectConnectivity = true; + } + + // check network master key + if (Tlv::GetTlv(aMessage, Tlv::kNetworkMasterKey, sizeof(masterKey), masterKey) == kThreadError_None && + type == Tlv::kActiveTimestamp && + memcmp(masterKey.GetNetworkMasterKey(), mNetif.GetKeyManager().GetMasterKey(NULL), + masterKey.GetLength())) + { + doesAffectConnectivity = true; + } + + // check active timestamp rollback + if (type == Tlv::kPendingTimestamp && + (masterKey.GetLength() == 0 || + memcmp(masterKey.GetNetworkMasterKey(), mNetif.GetKeyManager().GetMasterKey(NULL), + masterKey.GetLength()) == 0)) + { + // no change to master key, active timestamp must be ahead + const Timestamp *localActiveTimestamp = mNetif.GetActiveDataset().GetNetwork().GetTimestamp(); + + VerifyOrExit(localActiveTimestamp == NULL || localActiveTimestamp->Compare(activeTimestamp) > 0, + state = StateTlv::kReject); + } + + // check commissioner session id + if (Tlv::GetTlv(aMessage, Tlv::kCommissionerSessionId, sizeof(sessionId), sessionId) == kThreadError_None) + { + CommissionerSessionIdTlv *localId; + + isUpdateFromCommissioner = true; + + localId = static_cast(mNetworkDataLeader.GetCommissioningDataSubTlv( + Tlv::kCommissionerSessionId)); + + VerifyOrExit(localId != NULL && localId->GetCommissionerSessionId() == sessionId.GetCommissionerSessionId(), + state = StateTlv::kReject); + } + + // verify the update from commissioner should not contain tlv would affect connectivity + VerifyOrExit(!isUpdateFromCommissioner || !doesAffectConnectivity, state = StateTlv::kReject); + // update dataset if (type == Tlv::kPendingTimestamp && isUpdateFromCommissioner) { @@ -461,7 +454,7 @@ ThreadError DatasetManager::Set(Coap::Header &aHeader, Message &aMessage, const mLocal.Set(mNetif.GetActiveDataset().GetNetwork()); } - if (!isUpdateAffectConnectivity || isUpdateIdenticalValue) + if (!doesAffectConnectivity) { offset = aMessage.GetOffset(); diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 1435f685b..e03c5ba16 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -67,22 +67,7 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif): bool ActiveDataset::IsTlvInitialized(Tlv::Type aType) { - bool rval = false; - const Tlv *cur = reinterpret_cast(mLocal.GetBytes()); - const Tlv *end = reinterpret_cast(mLocal.GetBytes() + mLocal.GetSize()); - - while (cur < end) - { - if (aType == cur->GetType()) - { - ExitNow(rval = true); - } - - cur = cur->GetNext(); - } - -exit: - return rval; + return mLocal.Get(aType) != NULL; } ThreadError ActiveDataset::GenerateLocal(void)