From 485cb18ea40b47fe95aded2f71b1394b85b6c859 Mon Sep 17 00:00:00 2001 From: Abtin Keshavarzian Date: Thu, 2 May 2024 14:40:11 -0700 Subject: [PATCH] [dataset] add `ValidateTlvs()`, helper methods, and unit test (#10111) This commit enhances dataset handling: - Adds `ValidateTlvs()` which parses and validates all known TLVs within the `Dataset` and checks for any duplicates. - Introduces a set of `SetFrom()` methods for constructing a `Dataset` from various types of inputs, e.g., other `Dataset`, TLV sequences, `DatasetInfo` structures, bytes read from `Message`. Now they consistently clear the `Dataset` before setting it. - Adds `WriteTlvsFrom()` to update a `Dataset` replacing/appending a set of TLVs. - Adds `AppendTlvsFrom()` to append an already encoded sequence of TLVs without validating/checking the format. - Renames `Get/SetSize()` to `Get/SetLength()` for consistency. - Adds `test_dataset.cpp` unit test for basic `Dataset` validation. --- include/openthread/dataset.h | 7 +- include/openthread/instance.h | 2 +- src/cli/cli_dataset.cpp | 4 +- src/core/api/dataset_api.cpp | 16 +- src/core/common/settings.cpp | 8 +- src/core/meshcop/dataset.cpp | 278 ++++++++++++++--------- src/core/meshcop/dataset.hpp | 153 +++++++++---- src/core/meshcop/dataset_local.cpp | 15 +- src/core/meshcop/dataset_local.hpp | 1 + src/core/meshcop/dataset_manager.cpp | 16 +- src/core/meshcop/dataset_manager_ftd.cpp | 4 +- src/core/meshcop/dataset_updater.cpp | 2 +- src/core/meshcop/tcat_agent.cpp | 3 +- tests/unit/CMakeLists.txt | 1 + tests/unit/test_dataset.cpp | 238 +++++++++++++++++++ tests/unit/test_dns_client.cpp | 2 +- tests/unit/test_routing_manager.cpp | 2 +- tests/unit/test_srp_adv_proxy.cpp | 2 +- tests/unit/test_srp_server.cpp | 2 +- 19 files changed, 562 insertions(+), 194 deletions(-) create mode 100644 tests/unit/test_dataset.cpp diff --git a/include/openthread/dataset.h b/include/openthread/dataset.h index 1cfc4cf7f..077cbf33d 100644 --- a/include/openthread/dataset.h +++ b/include/openthread/dataset.h @@ -589,7 +589,7 @@ otError otNetworkNameFromString(otNetworkName *aNetworkName, const char *aNameSt * @param[out] aDataset A pointer to where the dataset will be placed. * * @retval OT_ERROR_NONE Successfully set @p aDataset from @p aDatasetTlvs. - * @retval OT_ERROR_INVALID_ARGS @p aDatasetTlvs is invalid. + * @retval OT_ERROR_INVALID_ARGS @p aDatasetTlvs's length is longer than `OT_OPERATIONAL_DATASET_MAX_LENGTH`. * */ otError otDatasetParseTlvs(const otOperationalDatasetTlvs *aDatasetTlvs, otOperationalDataset *aDataset); @@ -600,11 +600,8 @@ otError otDatasetParseTlvs(const otOperationalDatasetTlvs *aDatasetTlvs, otOpera * @param[in] aDataset An Operational dataset to convert to TLVs. * @param[out] aDatasetTlvs A pointer to dataset TLVs to return the result. * - * @retval OT_ERROR_NONE Successfully converted @p aDataset and updated @p aDatasetTlvs. - * @retval OT_ERROR_INVALID_ARGS @p aDataset is invalid, does not contain active or pending timestamps. - * */ -otError otDatasetConvertToTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs); +void otDatasetConvertToTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs); /** * Updates a given Operational Dataset. diff --git a/include/openthread/instance.h b/include/openthread/instance.h index ab0d5f63b..a117b7a8e 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (410) +#define OPENTHREAD_API_VERSION (411) /** * @addtogroup api-instance diff --git a/src/cli/cli_dataset.cpp b/src/cli/cli_dataset.cpp index 63e320381..86399c3fa 100644 --- a/src/cli/cli_dataset.cpp +++ b/src/cli/cli_dataset.cpp @@ -612,7 +612,7 @@ template <> otError Dataset::Process(Arg aArgs[]) otOperationalDataset dataset; SuccessOrExit(error = otDatasetCreateNewNetwork(GetInstancePtr(), &dataset)); - SuccessOrExit(error = otDatasetConvertToTlvs(&dataset, &sDatasetTlvs)); + otDatasetConvertToTlvs(&dataset, &sDatasetTlvs); } #endif else if (aArgs[0] == "tlvs") @@ -1105,7 +1105,7 @@ template <> otError Dataset::Process(Arg aArgs[]) { otOperationalDataset dataset; otOperationalDatasetTlvs datasetTlvs; - uint16_t tlvsLength = MeshCoP::Dataset::kMaxSize; + uint16_t tlvsLength = OT_OPERATIONAL_DATASET_MAX_LENGTH; SuccessOrExit(error = aArgs[1].ParseAsHexString(tlvsLength, datasetTlvs.mTlvs)); datasetTlvs.mLength = static_cast(tlvsLength); diff --git a/src/core/api/dataset_api.cpp b/src/core/api/dataset_api.cpp index 7e4c0d42d..33b5f3d68 100644 --- a/src/core/api/dataset_api.cpp +++ b/src/core/api/dataset_api.cpp @@ -161,26 +161,22 @@ otError otDatasetParseTlvs(const otOperationalDatasetTlvs *aDatasetTlvs, otOpera AssertPointerIsNotNull(aDatasetTlvs); - dataset.SetFrom(*aDatasetTlvs); - VerifyOrExit(dataset.IsValid(), error = kErrorInvalidArgs); + SuccessOrExit(error = dataset.SetFrom(*aDatasetTlvs)); + VerifyOrExit(dataset.ValidateTlvs() == kErrorNone, error = kErrorInvalidArgs); dataset.ConvertTo(AsCoreType(aDataset)); exit: return error; } -otError otDatasetConvertToTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs) +void otDatasetConvertToTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs) { - Error error = kErrorNone; MeshCoP::Dataset dataset; AssertPointerIsNotNull(aDatasetTlvs); - SuccessOrExit(error = dataset.SetFrom(AsCoreType(aDataset))); + dataset.SetFrom(AsCoreType(aDataset)); dataset.ConvertTo(*aDatasetTlvs); - -exit: - return error; } otError otDatasetUpdateTlvs(const otOperationalDataset *aDataset, otOperationalDatasetTlvs *aDatasetTlvs) @@ -190,8 +186,8 @@ otError otDatasetUpdateTlvs(const otOperationalDataset *aDataset, otOperationalD AssertPointerIsNotNull(aDatasetTlvs); - dataset.SetFrom(*aDatasetTlvs); - SuccessOrExit(error = dataset.SetFrom(AsCoreType(aDataset))); + SuccessOrExit(error = dataset.SetFrom(*aDatasetTlvs)); + SuccessOrExit(error = dataset.WriteTlvsFrom(AsCoreType(aDataset))); dataset.ConvertTo(*aDatasetTlvs); exit: diff --git a/src/core/common/settings.cpp b/src/core/common/settings.cpp index 3e1f860ee..df8226b93 100644 --- a/src/core/common/settings.cpp +++ b/src/core/common/settings.cpp @@ -224,7 +224,7 @@ Settings::Key Settings::KeyForDatasetType(MeshCoP::Dataset::Type aType) Error Settings::SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshCoP::Dataset &aDataset) { Key key = KeyForDatasetType(aType); - Error error = Get().Set(key, aDataset.GetBytes(), aDataset.GetSize()); + Error error = Get().Set(key, aDataset.GetBytes(), aDataset.GetLength()); Log(kActionSave, error, key); @@ -234,12 +234,12 @@ Error Settings::SaveOperationalDataset(MeshCoP::Dataset::Type aType, const MeshC Error Settings::ReadOperationalDataset(MeshCoP::Dataset::Type aType, MeshCoP::Dataset &aDataset) const { Error error = kErrorNone; - uint16_t length = MeshCoP::Dataset::kMaxSize; + uint16_t length = MeshCoP::Dataset::kMaxLength; SuccessOrExit(error = Get().Get(KeyForDatasetType(aType), aDataset.GetBytes(), &length)); - VerifyOrExit(length <= MeshCoP::Dataset::kMaxSize, error = kErrorNotFound); + VerifyOrExit(length <= MeshCoP::Dataset::kMaxLength, error = kErrorNotFound); - aDataset.SetSize(length); + aDataset.SetLength(static_cast(length)); exit: return error; diff --git a/src/core/meshcop/dataset.cpp b/src/core/meshcop/dataset.cpp index f757392b3..5849781fe 100644 --- a/src/core/meshcop/dataset.cpp +++ b/src/core/meshcop/dataset.cpp @@ -157,26 +157,34 @@ exit: } Dataset::Dataset(void) - : mUpdateTime(0) - , mLength(0) + : mLength(0) + , mUpdateTime(0) { ClearAllBytes(mTlvs); } -void Dataset::Clear(void) { mLength = 0; } - -bool Dataset::IsValid(void) const +Error Dataset::ValidateTlvs(void) const { - bool rval = true; - const Tlv *end = GetTlvsEnd(); + Error error = kErrorParse; + const Tlv *end = GetTlvsEnd(); + uint16_t validatedLength; - for (const Tlv *cur = GetTlvsStart(); cur < end; cur = cur->GetNext()) + VerifyOrExit(mLength <= kMaxLength); + + for (const Tlv *tlv = GetTlvsStart(); tlv < end; tlv = tlv->GetNext()) { - VerifyOrExit(!cur->IsExtended() && (cur + 1) <= end && cur->GetNext() <= end && IsTlvValid(*cur), rval = false); + VerifyOrExit(!tlv->IsExtended() && ((tlv + 1) <= end) && (tlv->GetNext() <= end)); + VerifyOrExit(IsTlvValid(*tlv)); + + // Ensure there are no duplicate TLVs. + validatedLength = static_cast(reinterpret_cast(tlv) - mTlvs); + VerifyOrExit(Tlv::FindTlv(mTlvs, validatedLength, tlv->GetType()) == nullptr); } + error = kErrorNone; + exit: - return rval; + return error; } bool Dataset::IsTlvValid(const Tlv &aTlv) @@ -308,110 +316,50 @@ void Dataset::ConvertTo(Tlvs &aTlvs) const aTlvs.mLength = static_cast(mLength); } -void Dataset::Set(Type aType, const Dataset &aDataset) +void Dataset::SetFrom(const Dataset &aDataset) { memcpy(mTlvs, aDataset.mTlvs, aDataset.mLength); - mLength = aDataset.mLength; - - if (aType == kActive) - { - RemoveTlv(Tlv::kPendingTimestamp); - RemoveTlv(Tlv::kDelayTimer); - } - + mLength = aDataset.mLength; mUpdateTime = aDataset.GetUpdateTime(); } -void Dataset::SetFrom(const Tlvs &aTlvs) -{ - mLength = aTlvs.mLength; - memcpy(mTlvs, aTlvs.mTlvs, mLength); -} +Error Dataset::SetFrom(const Tlvs &aTlvs) { return SetFrom(aTlvs.mTlvs, aTlvs.mLength); } -Error Dataset::SetFrom(const Info &aDatasetInfo) +Error Dataset::SetFrom(const uint8_t *aTlvs, uint8_t aLength) { Error error = kErrorNone; - if (aDatasetInfo.IsPresent()) - { - Timestamp activeTimestamp; + VerifyOrExit(aLength <= kMaxLength, error = kErrorInvalidArgs); - aDatasetInfo.Get(activeTimestamp); - IgnoreError(Write(activeTimestamp)); - } - - if (aDatasetInfo.IsPresent()) - { - Timestamp pendingTimestamp; - - aDatasetInfo.Get(pendingTimestamp); - IgnoreError(Write(pendingTimestamp)); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - ChannelTlvValue channelValue; - - channelValue.SetChannelAndPage(aDatasetInfo.Get()); - IgnoreError(Write(channelValue)); - } - - if (aDatasetInfo.IsPresent()) - { - ChannelMaskTlv::Value value; - - ChannelMaskTlv::PrepareValue(value, aDatasetInfo.Get()); - IgnoreError(WriteTlv(Tlv::kChannelMask, value.mData, value.mLength)); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - NameData nameData = aDatasetInfo.Get().GetAsData(); - - IgnoreError(WriteTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength())); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - IgnoreError(Write(aDatasetInfo.Get())); - } - - if (aDatasetInfo.IsPresent()) - { - SecurityPolicyTlv tlv; - - tlv.Init(); - tlv.SetSecurityPolicy(aDatasetInfo.Get()); - IgnoreError(WriteTlv(tlv)); - } + mLength = aLength; + memcpy(mTlvs, aTlvs, mLength); mUpdateTime = TimerMilli::GetNow(); +exit: + return error; +} + +void Dataset::SetFrom(const Info &aDatasetInfo) +{ + Clear(); + IgnoreError(WriteTlvsFrom(aDatasetInfo)); + + // `mUpdateTime` is already set by `WriteTlvsFrom()`. +} + +Error Dataset::SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength) +{ + Error error = kErrorNone; + + VerifyOrExit(aLength <= kMaxLength, error = kErrorInvalidArgs); + + SuccessOrExit(error = aMessage.Read(aOffset, mTlvs, aLength)); + mLength = static_cast(aLength); + + mUpdateTime = TimerMilli::GetNow(); + +exit: return error; } @@ -451,19 +399,129 @@ exit: Error Dataset::WriteTlv(const Tlv &aTlv) { return WriteTlv(aTlv.GetType(), aTlv.GetValue(), aTlv.GetLength()); } -Error Dataset::ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength) +Error Dataset::WriteTlvsFrom(const Dataset &aDataset) { - Error error = kErrorParse; + Error error; - VerifyOrExit(aLength <= kMaxSize); + SuccessOrExit(error = aDataset.ValidateTlvs()); - SuccessOrExit(aMessage.Read(aOffset, mTlvs, aLength)); - mLength = aLength; + for (const Tlv *tlv = aDataset.GetTlvsStart(); tlv < aDataset.GetTlvsEnd(); tlv = tlv->GetNext()) + { + SuccessOrExit(error = WriteTlv(*tlv)); + } - VerifyOrExit(IsValid(), error = kErrorParse); +exit: + return error; +} - mUpdateTime = TimerMilli::GetNow(); - error = kErrorNone; +Error Dataset::WriteTlvsFrom(const uint8_t *aTlvs, uint8_t aLength) +{ + Error error; + Dataset dataset; + + SuccessOrExit(error = dataset.SetFrom(aTlvs, aLength)); + error = WriteTlvsFrom(dataset); + +exit: + return error; +} + +Error Dataset::WriteTlvsFrom(const Dataset::Info &aDatasetInfo) +{ + Error error = kErrorNone; + + if (aDatasetInfo.IsPresent()) + { + Timestamp activeTimestamp; + + aDatasetInfo.Get(activeTimestamp); + SuccessOrExit(error = Write(activeTimestamp)); + } + + if (aDatasetInfo.IsPresent()) + { + Timestamp pendingTimestamp; + + aDatasetInfo.Get(pendingTimestamp); + SuccessOrExit(error = Write(pendingTimestamp)); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + ChannelTlvValue channelValue; + + channelValue.SetChannelAndPage(aDatasetInfo.Get()); + SuccessOrExit(error = Write(channelValue)); + } + + if (aDatasetInfo.IsPresent()) + { + ChannelMaskTlv::Value value; + + ChannelMaskTlv::PrepareValue(value, aDatasetInfo.Get()); + SuccessOrExit(error = WriteTlv(Tlv::kChannelMask, value.mData, value.mLength)); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + NameData nameData = aDatasetInfo.Get().GetAsData(); + + SuccessOrExit(error = WriteTlv(Tlv::kNetworkName, nameData.GetBuffer(), nameData.GetLength())); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + SuccessOrExit(error = Write(aDatasetInfo.Get())); + } + + if (aDatasetInfo.IsPresent()) + { + SecurityPolicyTlv tlv; + + tlv.Init(); + tlv.SetSecurityPolicy(aDatasetInfo.Get()); + SuccessOrExit(error = WriteTlv(tlv)); + } + +exit: + return error; +} + +Error Dataset::AppendTlvsFrom(const uint8_t *aTlvs, uint8_t aLength) +{ + Error error = kErrorNone; + uint16_t newLength = mLength; + + newLength += aLength; + VerifyOrExit(newLength <= kMaxLength, error = kErrorNoBufs); + + memcpy(mTlvs + mLength, aTlvs, aLength); + mLength += aLength; exit: return error; @@ -496,7 +554,7 @@ Error Dataset::ApplyConfiguration(Instance &aInstance, bool &aIsNetworkKeyUpdate KeyManager &keyManager = aInstance.Get(); Error error = kErrorNone; - VerifyOrExit(IsValid(), error = kErrorParse); + SuccessOrExit(error = ValidateTlvs()); aIsNetworkKeyUpdated = false; diff --git a/src/core/meshcop/dataset.hpp b/src/core/meshcop/dataset.hpp index af03896db..897cc04cc 100644 --- a/src/core/meshcop/dataset.hpp +++ b/src/core/meshcop/dataset.hpp @@ -61,7 +61,7 @@ class Dataset friend class DatasetLocal; public: - static constexpr uint8_t kMaxSize = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max size of MeshCoP Dataset (bytes) + static constexpr uint8_t kMaxLength = OT_OPERATIONAL_DATASET_MAX_LENGTH; ///< Max length of Dataset (bytes) static constexpr uint8_t kMaxValueSize = 16; ///< Max size of a TLV value (bytes) /** @@ -242,15 +242,21 @@ public: * Clears the Dataset. * */ - void Clear(void); + void Clear(void) { mLength = 0; } /** - * Indicates whether or not the dataset appears to be well-formed. + * Parses and validates all TLVs contained within the Dataset. * - * @returns TRUE if the dataset appears to be well-formed, FALSE otherwise. + * Performs the following checks all TLVs in the Dataset: + * - Ensures correct TLV format and expected minimum length for known TLV types that may appear in a Dataset. + * - Validates TLV value when applicable (e.g., Channel TLV using a supported channel). + * - Ensures no duplicate occurrence of same TLV type. + * + * @retval kErrorNone Successfully validated all the TLVs in the Dataset. + * @retval kErrorParse Dataset TLVs is not well-formed. * */ - bool IsValid(void) const; + Error ValidateTlvs(void) const; /** * Validates the format and value of a given MeshCoP TLV used in Dataset. @@ -429,6 +435,66 @@ public: return WriteTlv(static_cast(UintTlvType::kType), &value, sizeof(value)); } + /** + * Writes TLVs parsed from a given Dataset into this Dataset. + * + * TLVs from @p aDataset are parsed and written in the current Dataset. If the same TLV already exists, it will be + * replaced. Otherwise, the TLV will be appended. + * + * @param[in] aDataset A Dataset. + * + * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset. + * @retval kErrorParse The @p aDataset is not valid. + * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space. + * + */ + Error WriteTlvsFrom(const Dataset &aDataset); + + /** + * Writes TLVs parsed from a given buffer containing a sequence of TLVs into this Dataset. + * + * TLVs from @p aTlvs buffer are parsed and written in the current Dataset. If the same TLV already exists, it will + * be replaced. Otherwise, the TLV will be appended. + * + * @param[in] aTlvs A pointer to a buffer containing TLVs. + * @param[in] aLength Number of bytes in @p aTlvs buffer. + * + * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset. + * @retval kErrorParse The @p aTlvs is not valid. + * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space. + * + */ + Error WriteTlvsFrom(const uint8_t *aTlvs, uint8_t aLength); + + /** + * Writes TLVs corresponding to the components in a given `Dataset::Info` into this Dataset. + * + * If the same TLV already exists, it will be replaced. Otherwise the TLV will be appended. + * + * @param[in] aDataseInfo A `Dataset::Info`. + * + * @retval kErrorNone Successfully merged TLVs from @p aDataseInfo into this Dataset. + * @retval kErrorNoBufs Could not add the TLVs due to insufficient buffer space. + * + */ + Error WriteTlvsFrom(const Dataset::Info &aDatasetInfo); + + /** + * Appends a given sequence of TLVs to the Dataset. + * + * @note Unlike `WriteTlvsFrom()`, this method does not validate the @p aTlvs to be well-formed or check that there + * are no duplicates. It is up to caller to validate the resulting `Dataset` (e.g., using `ValidateTlvs()`) if + * desired. + * + * @param[in] aTlvs A pointer to a buffer containing TLVs. + * @param[in] aLength Number of bytes in @p aTlvs buffer. + * + * @retval kErrorNone Successfully merged TLVs from @p Dataset into this Dataset. + * @retval kErrorNoBufs Could not append the TLVs due to insufficient buffer space. + * + */ + Error AppendTlvsFrom(const uint8_t *aTlvs, uint8_t aLength); + /** * Removes a TLV from the Dataset. * @@ -472,12 +538,12 @@ public: void ConvertTo(Tlvs &aTlvs) const; /** - * Returns the Dataset size in bytes. + * Returns the Dataset length in bytes. * - * @returns The Dataset size in bytes. + * @returns The Dataset length in bytes. * */ - uint16_t GetSize(void) const { return mLength; } + uint8_t GetLength(void) const { return mLength; } /** * Sets the Dataset size in bytes. @@ -485,7 +551,7 @@ public: * @param[in] aSize The Dataset size in bytes. * */ - void SetSize(uint16_t aSize) { mLength = aSize; } + void SetLength(uint8_t aLength) { mLength = aLength; } /** * Returns the local time the dataset was last updated. @@ -496,48 +562,57 @@ public: TimeMilli GetUpdateTime(void) const { return mUpdateTime; } /** - * Reads the Dataset from a given message and checks that it is well-formed and valid. + * Sets this Dataset using an existing Dataset. * - * @param[in] aMessage The message to read from. - * @param[in] aOffset The offset in @p aMessage to start reading the Dataset TLVs. - * @param[in] aLength The dataset length in bytes. - * - * @retval kErrorNone Successfully read and validated the Dataset. - * @retval kErrorParse Could not read or parse the dataset from @p aMessage. - * - */ - Error ReadFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength); - - /** - * Sets the Dataset using an existing Dataset. - * - * If this Dataset is an Active Dataset, any Pending Timestamp and Delay Timer TLVs will be omitted in the copy - * from @p aDataset. - * - * @param[in] aType The type of the dataset, active or pending. * @param[in] aDataset The input Dataset. * */ - void Set(Type aType, const Dataset &aDataset); + void SetFrom(const Dataset &aDataset); /** * Sets the Dataset from a given structure representation. * * @param[in] aDatasetInfo The input Dataset as `Dataset::Info`. * - * @retval kErrorNone Successfully set the Dataset. - * @retval kErrorInvalidArgs Dataset is missing Active and/or Pending Timestamp. - * */ - Error SetFrom(const Info &aDatasetInfo); + void SetFrom(const Info &aDatasetInfo); /** - * Sets the Dataset using @p aDataset. + * Sets the Dataset from a given sequence of TLVs. * - * @param[in] aDataset The input Dataset as `Tlvs`. + * @param[in] aTlvs The input Dataset as `Tlvs`. + * + * @retval kErrorNone Successfully set the Dataset. + * @retval kErrorInvalidArgs The @p aTlvs is invalid and its length is longer than `kMaxLength`. * */ - void SetFrom(const Tlvs &aTlvs); + Error SetFrom(const Tlvs &aTlvs); + + /** + * Sets the Dataset from a buffer containing a sequence of TLVs. + * + * @param[in] aTlvs A pointer to a buffer containing TLVs. + * @param[in] aLength Number of bytes in @p aTlvs buffer. + * + * @retval kErrorNone Successfully set the Dataset. + * @retval kErrorInvalidArgs @p aLength is longer than `kMaxLength`. + * + */ + Error SetFrom(const uint8_t *aTlvs, uint8_t aLength); + + /** + * Sets the Dataset by reading the TLVs bytes from given message. + * + * @param[in] aMessage The message to read from. + * @param[in] aOffset The offset in @p aMessage to start reading the Dataset TLVs. + * @param[in] aLength The dataset length in bytes. + * + * @retval kErrorNone Successfully set the Dataset. + * @retval kInvalidArgs The @p aLength is longer than `kMaxLength`. + * @retval kErrorParse Could not read or parse the dataset from @p aMessage. + * + */ + Error SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength); /** * Applies the Active or Pending Dataset to the Thread interface. @@ -565,7 +640,7 @@ public: /** * Converts a Pending Dataset to an Active Dataset. * - * Removes the Delay Timer and Pending Timestamp TLVs + * Removes the Delay Timer and Pending Timestamp TLVs. * */ void ConvertToActive(void); @@ -646,9 +721,9 @@ public: private: void RemoveTlv(Tlv *aTlv); - uint8_t mTlvs[kMaxSize]; ///< The Dataset buffer - TimeMilli mUpdateTime; ///< Local time last updated - uint16_t mLength; ///< The number of valid bytes in @var mTlvs + uint8_t mTlvs[kMaxLength]; + uint8_t mLength; + TimeMilli mUpdateTime; // Local time last updated }; //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/core/meshcop/dataset_local.cpp b/src/core/meshcop/dataset_local.cpp index 6fec08461..848f6188a 100644 --- a/src/core/meshcop/dataset_local.cpp +++ b/src/core/meshcop/dataset_local.cpp @@ -151,7 +151,7 @@ Error DatasetLocal::Save(const Dataset::Info &aDatasetInfo) Error error; Dataset dataset; - SuccessOrExit(error = dataset.SetFrom(aDatasetInfo)); + dataset.SetFrom(aDatasetInfo); SuccessOrExit(error = Save(dataset)); exit: @@ -160,11 +160,14 @@ exit: Error DatasetLocal::Save(const Dataset::Tlvs &aDatasetTlvs) { + Error error = kErrorNone; Dataset dataset; - dataset.SetFrom(aDatasetTlvs); + SuccessOrExit(error = dataset.SetFrom(aDatasetTlvs)); + error = Save(dataset); - return Save(dataset); +exit: + return error; } Error DatasetLocal::Save(const Dataset &aDataset) @@ -175,7 +178,7 @@ Error DatasetLocal::Save(const Dataset &aDataset) DestroySecurelyStoredKeys(); #endif - if (aDataset.GetSize() == 0) + if (aDataset.GetLength() == 0) { // do not propagate error back IgnoreError(Get().DeleteOperationalDataset(mType)); @@ -188,7 +191,7 @@ Error DatasetLocal::Save(const Dataset &aDataset) // Store the network key and PSKC in the secure storage instead of settings. Dataset dataset; - dataset.Set(GetType(), aDataset); + dataset.SetFrom(aDataset); MoveKeysToSecureStorage(dataset); SuccessOrExit(error = Get().SaveOperationalDataset(mType, dataset)); #else @@ -258,7 +261,7 @@ void DatasetLocal::EmplaceSecurelyStoredKeys(Dataset &aDataset) const { Dataset dataset; - dataset.Set(GetType(), aDataset); + dataset.SetFrom(aDataset); MoveKeysToSecureStorage(dataset); SuccessOrAssert(Get().SaveOperationalDataset(mType, dataset)); } diff --git a/src/core/meshcop/dataset_local.hpp b/src/core/meshcop/dataset_local.hpp index 40e52bd61..85ceb3d16 100644 --- a/src/core/meshcop/dataset_local.hpp +++ b/src/core/meshcop/dataset_local.hpp @@ -167,6 +167,7 @@ public: * @param[in] aDatasetTlvs The Dataset to save as `Dataset::Tlvs`. * * @retval kErrorNone Successfully saved the dataset. + * @retval kErrorInvalidArgs The dataset TLVs is invalid, its length is longer than `Dataset::kMaxLength`. * @retval kErrorNotImplemented The platform does not implement settings functionality. * */ diff --git a/src/core/meshcop/dataset_manager.cpp b/src/core/meshcop/dataset_manager.cpp index b45bf8fc1..b80bce475 100644 --- a/src/core/meshcop/dataset_manager.cpp +++ b/src/core/meshcop/dataset_manager.cpp @@ -273,7 +273,7 @@ void DatasetManager::SendSet(void) VerifyOrExit(message != nullptr, error = kErrorNoBufs); IgnoreError(Read(dataset)); - SuccessOrExit(error = message->AppendBytes(dataset.GetBytes(), dataset.GetSize())); + SuccessOrExit(error = message->AppendBytes(dataset.GetBytes(), dataset.GetLength())); IgnoreError(messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc()); SuccessOrExit( @@ -410,14 +410,10 @@ exit: Error DatasetManager::AppendDatasetToMessage(const Dataset::Info &aDatasetInfo, Message &aMessage) const { - Error error; Dataset dataset; - SuccessOrExit(error = dataset.SetFrom(aDatasetInfo)); - error = aMessage.AppendBytes(dataset.GetBytes(), dataset.GetSize()); - -exit: - return error; + dataset.SetFrom(aDatasetInfo); + return aMessage.AppendBytes(dataset.GetBytes(), dataset.GetLength()); } Error DatasetManager::SendSetRequest(const Dataset::Info &aDatasetInfo, @@ -605,7 +601,8 @@ Error ActiveDatasetManager::Save(const Timestamp &aTimestamp, Error error = kErrorNone; Dataset dataset; - SuccessOrExit(error = dataset.ReadFromMessage(aMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.SetFrom(aMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.ValidateTlvs()); SuccessOrExit(error = dataset.Write(aTimestamp)); error = DatasetManager::Save(dataset); @@ -686,7 +683,8 @@ Error PendingDatasetManager::Save(const Timestamp &aTimestamp, Error error = kErrorNone; Dataset dataset; - SuccessOrExit(error = dataset.ReadFromMessage(aMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.SetFrom(aMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.ValidateTlvs()); SuccessOrExit(dataset.Write(aTimestamp)); SuccessOrExit(error = DatasetManager::Save(dataset)); StartDelayTimer(); diff --git a/src/core/meshcop/dataset_manager_ftd.cpp b/src/core/meshcop/dataset_manager_ftd.cpp index c6ac0e55d..606839be2 100644 --- a/src/core/meshcop/dataset_manager_ftd.cpp +++ b/src/core/meshcop/dataset_manager_ftd.cpp @@ -75,7 +75,7 @@ Error DatasetManager::AppendMleDatasetTlv(Message &aMessage) const dataset.RemoveTlv(IsActiveDataset() ? Tlv::kActiveTimestamp : Tlv::kPendingTimestamp); - return Tlv::AppendTlv(aMessage, mleTlvType, dataset.GetBytes(), static_cast(dataset.GetSize())); + return Tlv::AppendTlv(aMessage, mleTlvType, dataset.GetBytes(), dataset.GetLength()); } Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) @@ -104,7 +104,7 @@ Error DatasetManager::HandleSet(Coap::Message &aMessage, const Ip6::MessageInfo } // verify that does not overflow dataset buffer - VerifyOrExit((offset - aMessage.GetOffset()) <= Dataset::kMaxSize); + VerifyOrExit((offset - aMessage.GetOffset()) <= Dataset::kMaxLength); // verify the request includes a timestamp that is ahead of the locally stored value SuccessOrExit(Tlv::Find(aMessage, activeTimestamp)); diff --git a/src/core/meshcop/dataset_updater.cpp b/src/core/meshcop/dataset_updater.cpp index a6a3dce32..4aadbaff4 100644 --- a/src/core/meshcop/dataset_updater.cpp +++ b/src/core/meshcop/dataset_updater.cpp @@ -117,7 +117,7 @@ void DatasetUpdater::PreparePendingDataset(void) ExitNow(error = kErrorNone); } - IgnoreError(dataset.SetFrom(requestedDataset)); + SuccessOrExit(dataset.WriteTlvsFrom(requestedDataset)); if (!requestedDataset.IsPresent()) { diff --git a/src/core/meshcop/tcat_agent.cpp b/src/core/meshcop/tcat_agent.cpp index 325aa9a2c..b90163210 100644 --- a/src/core/meshcop/tcat_agent.cpp +++ b/src/core/meshcop/tcat_agent.cpp @@ -465,7 +465,8 @@ Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncommingMess Dataset::Tlvs datasetTlvs; Error error; - SuccessOrExit(error = dataset.ReadFromMessage(aIncommingMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, aOffset, aLength)); + SuccessOrExit(error = dataset.ValidateTlvs()); if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags, mDeviceAuthorizationField.mApplicationFlags, &dataset)) diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index a2995d491..a8364f7a7 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -173,6 +173,7 @@ ot_unit_test(child) ot_unit_test(child_table) ot_unit_test(cmd_line_parser) ot_unit_test(data) +ot_unit_test(dataset) ot_unit_test(dns) ot_unit_test(dns_client) ot_unit_test(dso) diff --git a/tests/unit/test_dataset.cpp b/tests/unit/test_dataset.cpp new file mode 100644 index 000000000..88fe2e5d0 --- /dev/null +++ b/tests/unit/test_dataset.cpp @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2024, The OpenThread Authors. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "test_platform.h" +#include "test_util.hpp" + +#include "meshcop/dataset.hpp" + +namespace ot { +namespace MeshCoP { + +void TestDataset(void) +{ + static const uint8_t kTlvBytes[] = { + 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0f, 0x35, 0x06, 0x00, + 0x04, 0x00, 0x1f, 0xff, 0xe0, 0x02, 0x08, 0x1d, 0xe5, 0xbf, 0xec, 0xd5, 0x16, 0x5b, 0x8f, 0x07, 0x08, 0xfd, + 0xe2, 0x1f, 0x0c, 0x8a, 0x13, 0xe8, 0xe7, 0x05, 0x10, 0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06, + 0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58, 0x03, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x64, 0x2d, 0x61, 0x61, 0x63, 0x33, 0x01, 0x02, 0xfa, 0xce, 0x04, 0x10, 0x2e, 0xaa, 0xe2, 0x94, 0x84, 0x38, + 0x8e, 0x31, 0x19, 0x58, 0x1a, 0x7b, 0x5a, 0x94, 0x8c, 0x07, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8, + }; + + static const otNetworkKey kNetworkKey = { + {0xea, 0xf9, 0x14, 0x9f, 0xdc, 0x73, 0x78, 0x77, 0x06, 0x98, 0xd5, 0x91, 0x80, 0x22, 0x19, 0x58}}; + + static const otNetworkKey kNewNetworkKey = { + {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}}; + + static const uint8_t kDuplicateChannels[] = { + 0x00, 0x03, 0x00, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x00, 0x1a, + }; + + static const Tlv::Type kDatasetTlvTypes[] = { + Tlv::kChannel, Tlv::kPanId, Tlv::kExtendedPanId, Tlv::kNetworkName, Tlv::kPskc, + Tlv::kNetworkKey, Tlv::kMeshLocalPrefix, Tlv::kSecurityPolicy, Tlv::kActiveTimestamp, + }; + + Dataset dataset; + Dataset dataset2; + Dataset::Tlvs datasetTlvs; + Dataset::Info datasetInfo; + uint16_t panId; + NetworkKey networkKey; + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes))); + + VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes)); + + SuccessOrQuit(dataset.ValidateTlvs()); + + for (Tlv::Type tlvType : kDatasetTlvTypes) + { + VerifyOrQuit(dataset.ContainsTlv(tlvType)); + } + + // Converting to `Dataset::Tlvs` + + dataset.ConvertTo(datasetTlvs); + VerifyOrQuit(datasetTlvs.mLength == sizeof(kTlvBytes)); + VerifyOrQuit(memcmp(datasetTlvs.mTlvs, kTlvBytes, sizeof(kTlvBytes)) == 0); + + // Converting to `Dataset::Info` + + dataset.ConvertTo(datasetInfo); + + VerifyOrQuit(datasetInfo.mComponents.mIsActiveTimestampPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsNetworkKeyPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsNetworkNamePresent); + VerifyOrQuit(datasetInfo.mComponents.mIsExtendedPanIdPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsMeshLocalPrefixPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsPanIdPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsChannelPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsPskcPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsSecurityPolicyPresent); + VerifyOrQuit(datasetInfo.mComponents.mIsChannelMaskPresent); + VerifyOrQuit(!datasetInfo.mComponents.mIsPendingTimestampPresent); + VerifyOrQuit(!datasetInfo.mComponents.mIsDelayPresent); + + VerifyOrQuit(datasetInfo.mPanId == 0xface); + VerifyOrQuit(AsCoreType(&datasetInfo.mNetworkKey) == AsCoreType(&kNetworkKey)); + + // Finding, reading TLVs + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr); + SuccessOrQuit(dataset.Read(panId)); + VerifyOrQuit(panId == 0xface); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr); + SuccessOrQuit(dataset.Read(networkKey)); + VerifyOrQuit(networkKey == AsCoreType(&kNetworkKey)); + + // Change PAN ID TLV + + SuccessOrQuit(dataset.Write(0xcafe)); + + SuccessOrQuit(dataset.ValidateTlvs()); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr); + SuccessOrQuit(dataset.Read(panId)); + VerifyOrQuit(panId == 0xcafe); + + for (Tlv::Type tlvType : kDatasetTlvTypes) + { + VerifyOrQuit(dataset.ContainsTlv(tlvType)); + } + + // Change Network Key TLV + + SuccessOrQuit(dataset.Write(AsCoreType(&kNewNetworkKey))); + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr); + SuccessOrQuit(dataset.Read(networkKey)); + VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey)); + + for (Tlv::Type tlvType : kDatasetTlvTypes) + { + VerifyOrQuit(dataset.ContainsTlv(tlvType)); + } + + // Remove PAN ID TLV + + dataset.RemoveTlv(Tlv::kPanId); + VerifyOrQuit(!dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) == nullptr); + VerifyOrQuit(dataset.Read(panId) == kErrorNotFound); + + SuccessOrQuit(dataset.ValidateTlvs()); + + // Invalid datasets + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes) - 1)); + VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse); + + SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels))); + VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse); + + SuccessOrQuit(dataset.SetFrom(kDuplicateChannels, sizeof(kDuplicateChannels) / 2)); + SuccessOrQuit(dataset.ValidateTlvs()); + + // Combining/Merging TLVs from two Datasets. + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes))); + + datasetInfo.Clear(); + datasetInfo.mComponents.mIsPanIdPresent = true; + datasetInfo.mComponents.mIsNetworkKeyPresent = true; + datasetInfo.mPanId = 0xcafe; + datasetInfo.mNetworkKey = kNewNetworkKey; + + dataset2.SetFrom(datasetInfo); + SuccessOrQuit(dataset2.ValidateTlvs()); + + SuccessOrQuit(dataset.WriteTlvsFrom(dataset2)); + + SuccessOrQuit(dataset.ValidateTlvs()); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr); + SuccessOrQuit(dataset.Read(panId)); + VerifyOrQuit(panId == 0xcafe); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr); + SuccessOrQuit(dataset.Read(networkKey)); + VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey)); + + // Combining/Merging TLVs from two Datasets (using `Dataset::Info`). + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes))); + + SuccessOrQuit(dataset.WriteTlvsFrom(datasetInfo)); + + SuccessOrQuit(dataset.ValidateTlvs()); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kPanId) != nullptr); + SuccessOrQuit(dataset.Read(panId)); + VerifyOrQuit(panId == 0xcafe); + + VerifyOrQuit(dataset.Contains()); + VerifyOrQuit(dataset.FindTlv(Tlv::kNetworkKey) != nullptr); + SuccessOrQuit(dataset.Read(networkKey)); + VerifyOrQuit(networkKey == AsCoreType(&kNewNetworkKey)); + + // Append TLVs + + SuccessOrQuit(dataset.SetFrom(kTlvBytes, sizeof(kTlvBytes))); + VerifyOrQuit(dataset.GetLength() == sizeof(kTlvBytes)); + VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0); + + SuccessOrQuit(dataset.AppendTlvsFrom(kTlvBytes, sizeof(kTlvBytes))); + VerifyOrQuit(dataset.GetLength() == 2 * sizeof(kTlvBytes)); + VerifyOrQuit(memcmp(dataset.GetBytes(), kTlvBytes, sizeof(kTlvBytes)) == 0); + VerifyOrQuit(memcmp(dataset.GetBytes() + sizeof(kTlvBytes), kTlvBytes, sizeof(kTlvBytes)) == 0); + + VerifyOrQuit(dataset.ValidateTlvs() == kErrorParse); +} + +} // namespace MeshCoP +} // namespace ot + +int main(void) +{ + ot::MeshCoP::TestDataset(); + + printf("All tests passed\n"); + return 0; +} diff --git a/tests/unit/test_dns_client.cpp b/tests/unit/test_dns_client.cpp index 74c5598c0..176654c0f 100644 --- a/tests/unit/test_dns_client.cpp +++ b/tests/unit/test_dns_client.cpp @@ -208,7 +208,7 @@ void InitTest(void) otOperationalDatasetTlvs datasetTlvs; SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset)); - SuccessOrQuit(otDatasetConvertToTlvs(&dataset, &datasetTlvs)); + otDatasetConvertToTlvs(&dataset, &datasetTlvs); SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs)); SuccessOrQuit(otIp6SetEnabled(sInstance, true)); diff --git a/tests/unit/test_routing_manager.cpp b/tests/unit/test_routing_manager.cpp index a474de4b1..c2d6fe84f 100644 --- a/tests/unit/test_routing_manager.cpp +++ b/tests/unit/test_routing_manager.cpp @@ -1185,7 +1185,7 @@ void InitTest(bool aEnablBorderRouting = false, bool aAfterReset = false) otOperationalDatasetTlvs datasetTlvs; - SuccessOrQuit(otDatasetConvertToTlvs(&kDataset, &datasetTlvs)); + otDatasetConvertToTlvs(&kDataset, &datasetTlvs); SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs)); SuccessOrQuit(otIp6SetEnabled(sInstance, true)); diff --git a/tests/unit/test_srp_adv_proxy.cpp b/tests/unit/test_srp_adv_proxy.cpp index ffd954a84..08b4a9470 100644 --- a/tests/unit/test_srp_adv_proxy.cpp +++ b/tests/unit/test_srp_adv_proxy.cpp @@ -537,7 +537,7 @@ void InitTest(void) otOperationalDatasetTlvs datasetTlvs; SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset)); - SuccessOrQuit(otDatasetConvertToTlvs(&dataset, &datasetTlvs)); + otDatasetConvertToTlvs(&dataset, &datasetTlvs); SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs)); SuccessOrQuit(otIp6SetEnabled(sInstance, true)); diff --git a/tests/unit/test_srp_server.cpp b/tests/unit/test_srp_server.cpp index ddf1e6e75..2104ae827 100644 --- a/tests/unit/test_srp_server.cpp +++ b/tests/unit/test_srp_server.cpp @@ -205,7 +205,7 @@ void InitTest(void) otOperationalDatasetTlvs datasetTlvs; SuccessOrQuit(otDatasetCreateNewNetwork(sInstance, &dataset)); - SuccessOrQuit(otDatasetConvertToTlvs(&dataset, &datasetTlvs)); + otDatasetConvertToTlvs(&dataset, &datasetTlvs); SuccessOrQuit(otDatasetSetActiveTlvs(sInstance, &datasetTlvs)); SuccessOrQuit(otIp6SetEnabled(sInstance, true));