ThreadOperationalDataset: various bug fixes (#34331)
* ThreadOperationalDataset: various bug fixes
- Ensure TLVs read have the correct length
- Default construct as empty (mLength == 0)
- Change MakeRoom() size argument to size_t to avoid chance of truncation
- Check for null in SetNetworkName
- Use Encoding::BigEndian instead of hand-rolled math
- Use ReturnErrorOnFailure / VerifyOrReturnError consistently
- Make tests independent from each other (non-static dataset member)
- Add more tests
* Fix includes
diff --git a/src/lib/support/ThreadOperationalDataset.cpp b/src/lib/support/ThreadOperationalDataset.cpp
index 70db620..9f2ae6a 100644
--- a/src/lib/support/ThreadOperationalDataset.cpp
+++ b/src/lib/support/ThreadOperationalDataset.cpp
@@ -15,11 +15,13 @@
* limitations under the License.
*/
-#include <assert.h>
-#include <string.h>
-
#include <lib/support/ThreadOperationalDataset.h>
+#include <lib/core/CHIPEncoding.h>
+
+#include <cassert>
+#include <cstring>
+
namespace chip {
namespace Thread {
@@ -70,7 +72,7 @@
mLength = aLength;
}
- const void * GetValue() const
+ const uint8_t * GetValue() const
{
assert(mLength != kLengthEscape);
@@ -79,75 +81,44 @@
return reinterpret_cast<const uint8_t *>(this) + sizeof(*this);
}
- void * GetValue() { return const_cast<void *>(const_cast<const ThreadTLV *>(this)->GetValue()); }
+ uint8_t * GetValue() { return const_cast<uint8_t *>(const_cast<const ThreadTLV *>(this)->GetValue()); }
+
+ ByteSpan GetValueAsSpan() const { return ByteSpan(static_cast<const uint8_t *>(GetValue()), GetLength()); }
void Get64(uint64_t & aValue) const
{
assert(GetLength() >= sizeof(aValue));
+ aValue = Encoding::BigEndian::Get64(GetValue());
+ }
- const uint8_t * p = reinterpret_cast<const uint8_t *>(GetValue());
- aValue = //
- (static_cast<uint64_t>(p[0]) << 56) | //
- (static_cast<uint64_t>(p[1]) << 48) | //
- (static_cast<uint64_t>(p[2]) << 40) | //
- (static_cast<uint64_t>(p[3]) << 32) | //
- (static_cast<uint64_t>(p[4]) << 24) | //
- (static_cast<uint64_t>(p[5]) << 16) | //
- (static_cast<uint64_t>(p[6]) << 8) | //
- (static_cast<uint64_t>(p[7]));
+ void Get32(uint32_t & aValue) const
+ {
+ assert(GetLength() >= sizeof(aValue));
+ aValue = Encoding::BigEndian::Get32(GetValue());
}
void Get16(uint16_t & aValue) const
{
assert(GetLength() >= sizeof(aValue));
-
- const uint8_t * p = static_cast<const uint8_t *>(GetValue());
-
- aValue = static_cast<uint16_t>(p[0] << 8 | p[1]);
- }
-
- void Get8(uint8_t & aValue) const
- {
- assert(GetLength() >= sizeof(aValue));
- aValue = *static_cast<const uint8_t *>(GetValue());
+ aValue = Encoding::BigEndian::Get16(GetValue());
}
void Set64(uint64_t aValue)
{
- uint8_t * value = static_cast<uint8_t *>(GetValue());
-
SetLength(sizeof(aValue));
+ Encoding::BigEndian::Put64(GetValue(), aValue);
+ }
- value[0] = static_cast<uint8_t>((aValue >> 56) & 0xff);
- value[1] = static_cast<uint8_t>((aValue >> 48) & 0xff);
- value[2] = static_cast<uint8_t>((aValue >> 40) & 0xff);
- value[3] = static_cast<uint8_t>((aValue >> 32) & 0xff);
- value[4] = static_cast<uint8_t>((aValue >> 24) & 0xff);
- value[5] = static_cast<uint8_t>((aValue >> 16) & 0xff);
- value[6] = static_cast<uint8_t>((aValue >> 8) & 0xff);
- value[7] = static_cast<uint8_t>(aValue & 0xff);
+ void Set32(uint32_t aValue)
+ {
+ SetLength(sizeof(aValue));
+ Encoding::BigEndian::Put32(GetValue(), aValue);
}
void Set16(uint16_t aValue)
{
- uint8_t * value = static_cast<uint8_t *>(GetValue());
-
SetLength(sizeof(aValue));
-
- value[0] = static_cast<uint8_t>(aValue >> 8);
- value[1] = static_cast<uint8_t>(aValue & 0xff);
- }
-
- void Set8(uint8_t aValue)
- {
- SetLength(sizeof(aValue));
- *static_cast<uint8_t *>(GetValue()) = aValue;
- }
-
- void Set8(int8_t aValue)
- {
- SetLength(sizeof(aValue));
- *static_cast<int8_t *>(GetValue()) = aValue;
+ Encoding::BigEndian::Put16(GetValue(), aValue);
}
void SetValue(const void * aValue, uint8_t aLength)
@@ -218,24 +189,16 @@
CHIP_ERROR OperationalDataset::GetActiveTimestamp(uint64_t & aActiveTimestamp) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kActiveTimestamp);
-
- if (tlv != nullptr)
- {
- tlv->Get64(aActiveTimestamp);
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == sizeof(aActiveTimestamp), CHIP_ERROR_INVALID_TLV_ELEMENT);
+ tlv->Get64(aActiveTimestamp);
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetActiveTimestamp(uint64_t aActiveTimestamp)
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kActiveTimestamp, sizeof(*tlv) + sizeof(aActiveTimestamp));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->Set64(aActiveTimestamp);
@@ -247,26 +210,19 @@
CHIP_ERROR OperationalDataset::GetChannel(uint16_t & aChannel) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kChannel);
-
- if (tlv != nullptr)
- {
- const uint8_t * value = reinterpret_cast<const uint8_t *>(tlv->GetValue());
- aChannel = static_cast<uint16_t>((value[1] << 8) | value[2]);
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == 3, CHIP_ERROR_INVALID_TLV_ELEMENT);
+ // Note: The channel page (byte 0) is not returned
+ const uint8_t * value = tlv->GetValue();
+ aChannel = static_cast<uint16_t>((value[1] << 8) | value[2]);
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetChannel(uint16_t aChannel)
{
uint8_t value[] = { 0, static_cast<uint8_t>(aChannel >> 8), static_cast<uint8_t>(aChannel & 0xff) };
ThreadTLV * tlv = MakeRoom(ThreadTLV::kChannel, sizeof(*tlv) + sizeof(value));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(value, sizeof(value));
@@ -278,13 +234,7 @@
CHIP_ERROR OperationalDataset::GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const
{
ByteSpan extPanIdSpan;
- CHIP_ERROR error = GetExtendedPanIdAsByteSpan(extPanIdSpan);
-
- if (error != CHIP_NO_ERROR)
- {
- return error;
- }
-
+ ReturnErrorOnFailure(GetExtendedPanIdAsByteSpan(extPanIdSpan));
memcpy(aExtendedPanId, extPanIdSpan.data(), extPanIdSpan.size());
return CHIP_NO_ERROR;
}
@@ -292,17 +242,8 @@
CHIP_ERROR OperationalDataset::GetExtendedPanIdAsByteSpan(ByteSpan & span) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kExtendedPanId);
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
- }
-
- if (tlv->GetLength() != kSizeExtendedPanId)
- {
- return CHIP_ERROR_INVALID_TLV_ELEMENT;
- }
-
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == kSizeExtendedPanId, CHIP_ERROR_INVALID_TLV_ELEMENT);
span = ByteSpan(static_cast<const uint8_t *>(tlv->GetValue()), tlv->GetLength());
return CHIP_NO_ERROR;
}
@@ -310,11 +251,7 @@
CHIP_ERROR OperationalDataset::SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId])
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kExtendedPanId, sizeof(*tlv) + sizeof(aExtendedPanId));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(aExtendedPanId, sizeof(aExtendedPanId));
@@ -328,24 +265,16 @@
CHIP_ERROR OperationalDataset::GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kMasterKey);
-
- if (tlv != nullptr)
- {
- memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey));
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == sizeof(aMasterKey), CHIP_ERROR_INVALID_TLV_ELEMENT);
+ memcpy(aMasterKey, tlv->GetValue(), sizeof(aMasterKey));
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey])
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kMasterKey, sizeof(*tlv) + sizeof(aMasterKey));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(aMasterKey, sizeof(aMasterKey));
@@ -359,24 +288,16 @@
CHIP_ERROR OperationalDataset::GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kMeshLocalPrefix);
-
- if (tlv != nullptr)
- {
- memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix));
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == sizeof(aMeshLocalPrefix), CHIP_ERROR_INVALID_TLV_ELEMENT);
+ memcpy(aMeshLocalPrefix, tlv->GetValue(), sizeof(aMeshLocalPrefix));
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix])
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kMeshLocalPrefix, sizeof(*tlv) + sizeof(aMeshLocalPrefix));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(aMeshLocalPrefix, sizeof(aMeshLocalPrefix));
@@ -388,32 +309,21 @@
CHIP_ERROR OperationalDataset::GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kNetworkName);
-
- if (tlv != nullptr)
- {
- memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength());
- aNetworkName[tlv->GetLength()] = '\0';
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() <= kSizeNetworkName, CHIP_ERROR_INVALID_TLV_ELEMENT);
+ memcpy(aNetworkName, tlv->GetValue(), tlv->GetLength());
+ aNetworkName[tlv->GetLength()] = '\0';
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetNetworkName(const char * aNetworkName)
{
+ VerifyOrReturnError(aNetworkName != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
size_t len = strlen(aNetworkName);
+ VerifyOrReturnError(0 < len && len <= kSizeNetworkName, CHIP_ERROR_INVALID_STRING_LENGTH);
- if (len > kSizeNetworkName || len == 0)
- {
- return CHIP_ERROR_INVALID_STRING_LENGTH;
- }
-
- ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, static_cast<uint8_t>(sizeof(*tlv) + static_cast<uint8_t>(len)));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ ThreadTLV * tlv = MakeRoom(ThreadTLV::kNetworkName, sizeof(*tlv) + len);
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(aNetworkName, static_cast<uint8_t>(len));
@@ -425,24 +335,16 @@
CHIP_ERROR OperationalDataset::GetPanId(uint16_t & aPanId) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kPanId);
-
- if (tlv != nullptr)
- {
- tlv->Get16(aPanId);
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == sizeof(aPanId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+ tlv->Get16(aPanId);
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetPanId(uint16_t aPanId)
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kPanId, sizeof(*tlv) + sizeof(aPanId));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->Set16(aPanId);
@@ -454,24 +356,16 @@
CHIP_ERROR OperationalDataset::GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const
{
const ThreadTLV * tlv = Locate(ThreadTLV::kPSKc);
-
- if (tlv != nullptr)
- {
- memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc));
- return CHIP_NO_ERROR;
- }
-
- return CHIP_ERROR_TLV_TAG_NOT_FOUND;
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ VerifyOrReturnError(tlv->GetLength() == sizeof(aPSKc), CHIP_ERROR_INVALID_TLV_ELEMENT);
+ memcpy(aPSKc, tlv->GetValue(), sizeof(aPSKc));
+ return CHIP_NO_ERROR;
}
CHIP_ERROR OperationalDataset::SetPSKc(const uint8_t (&aPSKc)[kSizePSKc])
{
ThreadTLV * tlv = MakeRoom(ThreadTLV::kPSKc, sizeof(*tlv) + sizeof(aPSKc));
-
- if (tlv == nullptr)
- {
- return CHIP_ERROR_NO_MEMORY;
- }
+ VerifyOrReturnError(tlv != nullptr, CHIP_ERROR_NO_MEMORY);
tlv->SetValue(aPSKc, sizeof(aPSKc));
@@ -533,7 +427,7 @@
}
}
-ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, uint8_t aSize)
+ThreadTLV * OperationalDataset::MakeRoom(uint8_t aType, size_t aSize)
{
ThreadTLV * tlv = Locate(aType);
diff --git a/src/lib/support/ThreadOperationalDataset.h b/src/lib/support/ThreadOperationalDataset.h
index e4de3dd..7bb528d 100644
--- a/src/lib/support/ThreadOperationalDataset.h
+++ b/src/lib/support/ThreadOperationalDataset.h
@@ -54,7 +54,6 @@
*
* @retval CHIP_NO_ERROR Successfully initialized the dataset.
* @retval CHIP_ERROR_INVALID_ARGUMENT The dataset length @p aLength is too long or @p data is corrupted.
- *
*/
CHIP_ERROR Init(ByteSpan aData);
@@ -65,7 +64,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the active timestamp.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread active timestamp is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetActiveTimestamp(uint64_t & aActiveTimestamp) const;
@@ -76,7 +75,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the active timestamp.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread active timestamp.
- *
*/
CHIP_ERROR SetActiveTimestamp(uint64_t aActiveTimestamp);
@@ -87,7 +85,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the channel.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread channel is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetChannel(uint16_t & aChannel) const;
@@ -98,7 +96,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the channel.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread channel.
- *
*/
CHIP_ERROR SetChannel(uint16_t aChannel);
@@ -109,7 +106,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetExtendedPanId(uint8_t (&aExtendedPanId)[kSizeExtendedPanId]) const;
@@ -121,7 +118,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the extended PAN ID.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread extended PAN ID is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetExtendedPanIdAsByteSpan(ByteSpan & span) const;
@@ -132,7 +129,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the extended PAN ID.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread extended PAN ID.
- *
*/
CHIP_ERROR SetExtendedPanId(const uint8_t (&aExtendedPanId)[kSizeExtendedPanId]);
@@ -143,7 +139,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the master key.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread master key is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetMasterKey(uint8_t (&aMasterKey)[kSizeMasterKey]) const;
@@ -154,13 +150,11 @@
*
* @retval CHIP_NO_ERROR Successfully set the master key.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread master key.
- *
*/
CHIP_ERROR SetMasterKey(const uint8_t (&aMasterKey)[kSizeMasterKey]);
/**
* This method unsets Thread master key to the dataset.
- *
*/
void UnsetMasterKey(void);
@@ -171,7 +165,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the mesh local prefix.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread mesh local prefix is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetMeshLocalPrefix(uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]) const;
@@ -182,7 +176,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the Thread mesh local prefix.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread mesh local prefix.
- *
*/
CHIP_ERROR SetMeshLocalPrefix(const uint8_t (&aMeshLocalPrefix)[kSizeMeshLocalPrefix]);
@@ -193,7 +186,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the network name.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread network name is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetNetworkName(char (&aNetworkName)[kSizeNetworkName + 1]) const;
@@ -204,7 +197,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the network name.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread network name.
- *
*/
CHIP_ERROR SetNetworkName(const char * aNetworkName);
@@ -215,7 +207,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the PAN ID.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PAN ID is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetPanId(uint16_t & aPanId) const;
@@ -226,7 +218,6 @@
*
* @retval CHIP_NO_ERROR Successfully set the PAN ID.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PAN ID.
- *
*/
CHIP_ERROR SetPanId(uint16_t aPanId);
@@ -237,7 +228,7 @@
*
* @retval CHIP_NO_ERROR Successfully retrieved the PSKc.
* @retval CHIP_ERROR_TLV_TAG_NOT_FOUND Thread PSKc is not present in the dataset.
- *
+ * @retval CHIP_ERROR_INVALID_TLV_ELEMENT If the TLV element is invalid.
*/
CHIP_ERROR GetPSKc(uint8_t (&aPSKc)[kSizePSKc]) const;
@@ -248,13 +239,11 @@
*
* @retval CHIP_NO_ERROR Successfully set the PSKc.
* @retval CHIP_ERROR_NO_MEMORY Insufficient memory in the dataset for setting Thread PSKc.
- *
*/
CHIP_ERROR SetPSKc(const uint8_t (&aPSKc)[kSizePSKc]);
/**
* This method unsets Thread PSKc to the dataset.
- *
*/
void UnsetPSKc(void);
@@ -296,12 +285,12 @@
ThreadTLV & End(void) { return const_cast<ThreadTLV &>(const_cast<const OperationalDataset *>(this)->End()); }
void Remove(uint8_t aType);
void Remove(ThreadTLV & aTlv);
- ThreadTLV * MakeRoom(uint8_t aType, uint8_t aSize);
+ ThreadTLV * MakeRoom(uint8_t aType, size_t aSize);
bool Has(uint8_t aType) const { return Locate(aType) != nullptr; }
uint8_t mData[kSizeOperationalDataset];
- uint8_t mLength;
+ uint8_t mLength = 0;
};
} // namespace Thread
-}; // namespace chip
+} // namespace chip
diff --git a/src/lib/support/tests/TestThreadOperationalDataset.cpp b/src/lib/support/tests/TestThreadOperationalDataset.cpp
index d9e13c8..b37cde4 100644
--- a/src/lib/support/tests/TestThreadOperationalDataset.cpp
+++ b/src/lib/support/tests/TestThreadOperationalDataset.cpp
@@ -30,11 +30,9 @@
static void SetUpTestSuite() { ASSERT_EQ(chip::Platform::MemoryInit(), CHIP_NO_ERROR); }
static void TearDownTestSuite() { chip::Platform::MemoryShutdown(); }
- static Thread::OperationalDataset dataset;
+ Thread::OperationalDataset dataset;
};
-Thread::OperationalDataset TestThreadOperationalDataset::dataset;
-
TEST_F(TestThreadOperationalDataset, TestInit)
{
@@ -103,6 +101,10 @@
EXPECT_EQ(dataset.SetMasterKey(kMasterKey), CHIP_NO_ERROR);
EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
EXPECT_EQ(memcmp(masterKey, kMasterKey, sizeof(kMasterKey)), 0);
+
+ dataset.UnsetMasterKey();
+ EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_TLV_TAG_NOT_FOUND);
+ EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
}
TEST_F(TestThreadOperationalDataset, TestMeshLocalPrefix)
@@ -129,6 +131,7 @@
EXPECT_EQ(dataset.SetNetworkName("0123456789abcdef"), CHIP_NO_ERROR);
EXPECT_EQ(dataset.SetNetworkName("0123456789abcdefg"), CHIP_ERROR_INVALID_STRING_LENGTH);
EXPECT_EQ(dataset.SetNetworkName(""), CHIP_ERROR_INVALID_STRING_LENGTH);
+ EXPECT_EQ(dataset.SetNetworkName(nullptr), CHIP_ERROR_INVALID_ARGUMENT);
}
TEST_F(TestThreadOperationalDataset, TestPanId)
@@ -152,25 +155,7 @@
EXPECT_EQ(dataset.SetPSKc(kPSKc), CHIP_NO_ERROR);
EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
EXPECT_FALSE(memcmp(pskc, kPSKc, sizeof(kPSKc)));
-}
-TEST_F(TestThreadOperationalDataset, TestUnsetMasterKey)
-{
-
- uint8_t masterKey[Thread::kSizeMasterKey] = { 0 };
-
- EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
- dataset.UnsetMasterKey();
- EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_TLV_TAG_NOT_FOUND);
- EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
-}
-
-TEST_F(TestThreadOperationalDataset, TestUnsetPSKc)
-{
-
- uint8_t pskc[Thread::kSizePSKc] = { 0 };
-
- EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
dataset.UnsetPSKc();
EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_ERROR_TLV_TAG_NOT_FOUND);
EXPECT_EQ(dataset.SetPSKc(pskc), CHIP_NO_ERROR);
@@ -178,45 +163,19 @@
TEST_F(TestThreadOperationalDataset, TestClear)
{
-
{
- uint64_t activeTimestamp;
- EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_NO_ERROR);
- }
-
- {
- uint16_t channel;
- EXPECT_EQ(dataset.GetChannel(channel), CHIP_NO_ERROR);
- }
-
- {
- uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 0 };
- EXPECT_EQ(dataset.GetExtendedPanId(extendedPanId), CHIP_NO_ERROR);
- }
-
- {
+ EXPECT_EQ(dataset.SetActiveTimestamp(123), CHIP_NO_ERROR);
+ EXPECT_EQ(dataset.SetChannel(5), CHIP_NO_ERROR);
+ uint8_t extendedPanId[Thread::kSizeExtendedPanId] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+ EXPECT_EQ(dataset.SetExtendedPanId(extendedPanId), CHIP_NO_ERROR);
uint8_t masterKey[Thread::kSizeMasterKey] = { 0 };
- EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
- }
-
- {
+ EXPECT_EQ(dataset.SetMasterKey(masterKey), CHIP_NO_ERROR);
uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix] = { 0 };
- EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
- }
-
- {
- char networkName[Thread::kSizeNetworkName + 1] = { 0 };
- EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_NO_ERROR);
- }
-
- {
- uint16_t panid;
- EXPECT_EQ(dataset.GetPanId(panid), CHIP_NO_ERROR);
- }
-
- {
+ EXPECT_EQ(dataset.SetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
+ EXPECT_EQ(dataset.SetNetworkName("w00tw00t"), CHIP_NO_ERROR);
+ EXPECT_EQ(dataset.SetPanId(0x4242), CHIP_NO_ERROR);
uint8_t pskc[Thread::kSizePSKc] = { 0 };
- EXPECT_EQ(dataset.GetPSKc(pskc), CHIP_NO_ERROR);
+ EXPECT_EQ(dataset.SetPSKc(pskc), CHIP_NO_ERROR);
}
dataset.Clear();
@@ -262,4 +221,103 @@
}
}
+TEST_F(TestThreadOperationalDataset, TestExampleDataset)
+{
+ const uint8_t example[] = {
+ 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // Active Timestamp 1
+ 0x00, 0x03, 0x00, 0x00, 0x0f, // Channel 15
+ 0x35, 0x04, 0x07, 0xff, 0xf8, 0x00, // Channel Mask 0x07fff800
+ 0x02, 0x08, 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb, // Ext PAN ID 39758ec8144b07fb
+ 0x07, 0x08, 0xfd, 0xf1, 0xf1, 0xad, 0xd0, 0x79, 0x7d, 0xc0, // Mesh Local Prefix fdf1:f1ad:d079:7dc0::/64
+ 0x05, 0x10, 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9, 0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, 0x23, // Network Key
+ 0x03, 0x0f, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x35, 0x39, 0x33, 0x38, // "OpenThread-5938"
+ 0x01, 0x02, 0x59, 0x38, // PAN ID : 0x5938
+ 0x04, 0x10, 0x3c, 0xa6, 0x7c, 0x96, 0x9e, 0xfb, 0x0d, 0x0c, 0x74, 0xa4, 0xd8, 0xee, 0x92, 0x3b, 0x57, 0x6c, // PKSc
+ 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8, // Security Policy
+ };
+ EXPECT_EQ(dataset.Init(ByteSpan(example)), CHIP_NO_ERROR);
+
+ uint64_t activeTimestamp;
+ EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_NO_ERROR);
+ EXPECT_EQ(activeTimestamp, 1u);
+
+ uint16_t channel;
+ EXPECT_EQ(dataset.GetChannel(channel), CHIP_NO_ERROR);
+ EXPECT_EQ(channel, 15u);
+
+ uint8_t extPanId[Thread::kSizeExtendedPanId];
+ EXPECT_EQ(dataset.GetExtendedPanId(extPanId), CHIP_NO_ERROR);
+ const uint8_t expectedExtPanId[] = { 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb };
+ EXPECT_TRUE(ByteSpan(extPanId).data_equal(ByteSpan(expectedExtPanId)));
+
+ uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix];
+ EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_NO_ERROR);
+ const uint8_t expectedMeshLocalPrefix[] = { 0xfd, 0xf1, 0xf1, 0xad, 0xd0, 0x79, 0x7d, 0xc0 };
+ EXPECT_TRUE(ByteSpan(meshLocalPrefix).data_equal(ByteSpan(expectedMeshLocalPrefix)));
+
+ uint8_t masterKey[Thread::kSizeMasterKey];
+ EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_NO_ERROR);
+ const uint8_t expectedMasterKey[] = { 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9,
+ 0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, 0x23 };
+ EXPECT_TRUE(ByteSpan(masterKey).data_equal(ByteSpan(expectedMasterKey)));
+
+ char networkName[Thread::kSizeNetworkName + 1];
+ EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_NO_ERROR);
+ EXPECT_EQ(strncmp(networkName, "OpenThread-5938", sizeof(networkName)), 0);
+
+ uint16_t panId;
+ EXPECT_EQ(dataset.GetPanId(panId), CHIP_NO_ERROR);
+ EXPECT_EQ(panId, 0x5938u);
+
+ uint8_t pksc[Thread::kSizePSKc];
+ EXPECT_EQ(dataset.GetPSKc(pksc), CHIP_NO_ERROR);
+ const uint8_t expectedPksc[] = {
+ 0x3c, 0xa6, 0x7c, 0x96, 0x9e, 0xfb, 0x0d, 0x0c, 0x74, 0xa4, 0xd8, 0xee, 0x92, 0x3b, 0x57, 0x6c
+ };
+ EXPECT_TRUE(ByteSpan(pksc).data_equal(ByteSpan(expectedPksc)));
+}
+
+TEST_F(TestThreadOperationalDataset, TestInvalidExampleDataset)
+{
+ const uint8_t invalid[] = {
+ 0x0e, 0x01, 0x01, // Active Timestamp
+ 0x00, 0x01, 0x0f, // Channel
+ 0x35, 0x00, // Channel Mask
+ 0x02, 0x09, 0x39, 0x75, 0x8e, 0xc8, 0x14, 0x4b, 0x07, 0xfb, 0xff, // Ext PAN ID
+ 0x07, 0x01, 0x01, // Mesh Local Prefix
+ 0x05, 0x0f, 0xf3, 0x66, 0xce, 0xc7, 0xa4, 0x46, 0xba, 0xb9, 0x78, 0xd9, 0x0d, 0x27, 0xab, 0xe3, 0x8f, // Network Key
+ 0x03, 0x11, 0x4f, 0x70, 0x65, 0x6e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x35, 0x39, 0x33, 0x38, 0xff, 0xff, // Name
+ 0x01, 0x01, 0xff, // PAN ID
+ 0x04, 0x01, 0x3c, // PKSc
+ 0x0c, 0x01, 0x01, // Security Policy
+ };
+
+ // The overall TLV structure is valid, but all TLVs have invalid sizes
+ EXPECT_EQ(dataset.Init(ByteSpan(invalid)), CHIP_NO_ERROR);
+
+ uint64_t activeTimestamp;
+ EXPECT_EQ(dataset.GetActiveTimestamp(activeTimestamp), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ uint16_t channel;
+ EXPECT_EQ(dataset.GetChannel(channel), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ ByteSpan extPanId;
+ EXPECT_EQ(dataset.GetExtendedPanIdAsByteSpan(extPanId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ uint8_t meshLocalPrefix[Thread::kSizeMeshLocalPrefix];
+ EXPECT_EQ(dataset.GetMeshLocalPrefix(meshLocalPrefix), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ uint8_t masterKey[Thread::kSizeMasterKey];
+ EXPECT_EQ(dataset.GetMasterKey(masterKey), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ char networkName[Thread::kSizeNetworkName + 1];
+ EXPECT_EQ(dataset.GetNetworkName(networkName), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ uint16_t panId;
+ EXPECT_EQ(dataset.GetPanId(panId), CHIP_ERROR_INVALID_TLV_ELEMENT);
+
+ uint8_t pksc[Thread::kSizePSKc];
+ EXPECT_EQ(dataset.GetPSKc(pksc), CHIP_ERROR_INVALID_TLV_ELEMENT);
+}
+
} // namespace