diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 1b12dd407..b2b08ad22 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -633,6 +633,24 @@ void otDatasetConvertToTlvs(const otOperationalDataset *aDataset, otOperationalD */ otError otDatasetUpdateTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs); +/** + * Indicates whether or not a given Operational Dataset (in TLVs format) affects connectivity. + * + * A Dataset affects connectivity if it contains a different Channel, PAN ID, Mesh Local Prefix, Network Key, or + * Security Policy than the current values in use. + * + * The following security policy changes are considered to affect connectivity: + * - Disabling routers (R bit: 1 to 0). + * - Enabling non-CCM routers (NCR bit: 0 to 1). + * - Increasing the version threshold for routing (VR field). + * + * @param[in] aInstance A pointer to an OpenThread instance. + * @param[in] aDatasetTlvs A pointer to Operational Dataset TLVs. + * + * @returns TRUE if @p aDatasetTlvs affects connectivity, FALSE otherwise. + */ +bool otDatasetAffectsConnectivity(otInstance *aInstance, const otOperationalDatasetTlvs *aDatasetTlvs); + /** * @} */ diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 863796c59..d3b0b1f51 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -52,7 +52,7 @@ extern "C" { * * @note This number versions both OpenThread platform and user APIs. */ -#define OPENTHREAD_API_VERSION (598) +#define OPENTHREAD_API_VERSION (599) /** * @addtogroup api-instance diff --git a/src/core/api/dataset_api.cpp b/src/core/api/dataset_api.cpp index 17d6f7e59..99be9580a 100644 --- a/src/core/api/dataset_api.cpp +++ b/src/core/api/dataset_api.cpp @@ -228,3 +228,17 @@ otError otDatasetUpdateTlvs(const otOperationalDataset *aDataset, otOperationalD exit: return error; } + +bool otDatasetAffectsConnectivity(otInstance *aInstance, const otOperationalDatasetTlvs *aDatasetTlvs) +{ + bool affects = false; + MeshCoP::Dataset dataset; + + AssertPointerIsNotNull(aDatasetTlvs); + + SuccessOrExit(dataset.SetFrom(*aDatasetTlvs)); + affects = dataset.AffectsConnectivity(AsCoreType(aInstance)); + +exit: + return affects; +} diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index 362e774f8..85c2f755d 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -611,6 +611,51 @@ exit: return isSubset; } +bool Dataset::AffectsConnectivity(Instance &aInstance) const +{ + bool affects = true; + ChannelTlvValue channelValue; + Mac::PanId panId; + Ip6::NetworkPrefix meshLocalPrefix; + + if (Read(channelValue) == kErrorNone) + { + VerifyOrExit(channelValue.GetChannel() == aInstance.Get().GetPanChannel()); + } + + if (Read(panId) == kErrorNone) + { + VerifyOrExit(panId == aInstance.Get().GetPanId()); + } + + if (Read(meshLocalPrefix) == kErrorNone) + { + VerifyOrExit(meshLocalPrefix == aInstance.Get().GetMeshLocalPrefix()); + } + + VerifyOrExit(!AffectsNetworkKey(aInstance)); + + affects = false; + +exit: + return affects; +} + +bool Dataset::AffectsNetworkKey(Instance &aInstance) const +{ + bool affects = false; + NetworkKey networkKey; + NetworkKey localNetworkKey; + + SuccessOrExit(Read(networkKey)); + + aInstance.Get().GetNetworkKey(localNetworkKey); + affects = (networkKey != localNetworkKey); + +exit: + return affects; +} + const char *Dataset::TypeToString(Type aType) { return (aType == kActive) ? "Active" : "Pending"; } } // namespace MeshCoP diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index 6358d18b9..3de8b09d0 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -655,6 +655,36 @@ public: */ bool IsSubsetOf(const Dataset &aOther) const; + /** + * Indicates whether or not the Dataset affects connectivity. + * + * A Dataset affects connectivity if it contains a different Channel, PAN ID, Mesh Local Prefix, Network Key, or + * Security Policy than the current values in use. + * + * The following security policy changes are considered to affect connectivity: + * - Disabling routers (R bit: 1 to 0). + * - Enabling non-CCM routers (NCR bit: 0 to 1). + * - Increasing the version threshold for routing (VR field). + * + * @param[in] aInstance The OpenThread instance. + * + * @retval TRUE The Dataset affects connectivity. + * @retval FALSE The Dataset does not affect connectivity. + */ + bool AffectsConnectivity(Instance &aInstance) const; + + /** + * Indicates whether or not the Dataset affects the Network Key. + * + * A Dataset affects the Network Key if it contains a different Network Key than the current value in use. + * + * @param[in] aInstance The OpenThread instance. + * + * @retval TRUE The Dataset affects the Network Key. + * @retval FALSE The Dataset does not affect the Network Key. + */ + bool AffectsNetworkKey(Instance &aInstance) const; + /** * Converts a Dataset Type to a string. * diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index 697963d6b..f7bfcefe3 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -49,16 +49,12 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand, const Coap::Message &aMessage, RequestInfo &aInfo) const { - Error error = kErrorParse; - Dataset dataset; - OffsetRange offsetRange; - Timestamp activeTimestamp; - ChannelTlvValue channelValue; - uint16_t sessionId; - Ip6::NetworkPrefix meshLocalPrefix; - NetworkKey networkKey; - uint16_t panId; - uint32_t delayTimer; + Error error = kErrorParse; + Dataset dataset; + OffsetRange offsetRange; + Timestamp activeTimestamp; + uint16_t sessionId; + uint32_t delayTimer; aInfo.Clear(); @@ -86,35 +82,8 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand, // Determine whether the new Dataset affects connectivity // or network key. - if ((dataset.Read(channelValue) == kErrorNone) && - (channelValue.GetChannel() != Get().GetPanChannel())) - { - aInfo.mAffectsConnectivity = true; - } - - if ((dataset.Read(panId) == kErrorNone) && (panId != Get().GetPanId())) - { - aInfo.mAffectsConnectivity = true; - } - - if ((dataset.Read(meshLocalPrefix) == kErrorNone) && - (meshLocalPrefix != Get().GetMeshLocalPrefix())) - { - aInfo.mAffectsConnectivity = true; - } - - if (dataset.Read(networkKey) == kErrorNone) - { - NetworkKey localNetworkKey; - - Get().GetNetworkKey(localNetworkKey); - - if (networkKey != localNetworkKey) - { - aInfo.mAffectsConnectivity = true; - aInfo.mAffectsNetworkKey = true; - } - } + aInfo.mAffectsConnectivity = dataset.AffectsConnectivity(GetInstance()); + aInfo.mAffectsNetworkKey = dataset.AffectsNetworkKey(GetInstance()); // Check active timestamp rollback. If there is no change to // network key, active timestamp must be ahead of local value.