mirror of
https://github.com/espressif/openthread.git
synced 2026-07-27 14:27:47 +00:00
Cleanup DatasetManager::Set(). (#1058)
This commit is contained in:
@@ -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<CommissionerSessionIdTlv *>(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<Timestamp *>(&activeTimestamp) :
|
||||
static_cast<Timestamp *>(&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<CommissionerSessionIdTlv *>(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();
|
||||
|
||||
|
||||
@@ -67,22 +67,7 @@ ActiveDataset::ActiveDataset(ThreadNetif &aThreadNetif):
|
||||
|
||||
bool ActiveDataset::IsTlvInitialized(Tlv::Type aType)
|
||||
{
|
||||
bool rval = false;
|
||||
const Tlv *cur = reinterpret_cast<const Tlv *>(mLocal.GetBytes());
|
||||
const Tlv *end = reinterpret_cast<const Tlv *>(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)
|
||||
|
||||
Reference in New Issue
Block a user