[core] add OffsetRange class (#10436)

This commit introduces the `OffsetRange` class, which represents a
range of offsets within a `Message` or data buffer (i.e., a starting
offset and a length indicating the number of bytes in the range).

The class provides methods for common operations:

- Getting the start or end offset, or the remaining length.
- Checking if the range is empty or contains a certain number of
  bytes.
- Advancing the start offset by a given amount, ensuring it never goes
  beyond the end offset.
- Shrinking the range's length.

The new `OffsetRange` class simplifies methods that previously used
separate `aOffset` and `aLength` input parameters, improving code
readability and maintainability. It also facilitates reading and
processing content within a specified range.

For example, `Tlv::FindTlvValueOffsetRange()` now directly returns an
`OffsetRange` indicating the location of the TLV value. The `Message`
class is also updated with new `Read()` and `Append()` method variants
that accept `OffsetRange` arguments. These methods ensure that read
content is contained within the specified `OffsetRange`.
This commit is contained in:
Abtin Keshavarzian
2024-07-01 19:15:17 -07:00
committed by GitHub
parent 6aa6f45606
commit a448bce915
37 changed files with 855 additions and 382 deletions
+2
View File
@@ -432,6 +432,8 @@ openthread_core_files = [
"common/notifier.hpp",
"common/num_utils.hpp",
"common/numeric_limits.hpp",
"common/offset_range.cpp",
"common/offset_range.hpp",
"common/owned_ptr.hpp",
"common/owning_list.hpp",
"common/pool.hpp",
+1
View File
@@ -112,6 +112,7 @@ set(COMMON_SOURCES
common/log.cpp
common/message.cpp
common/notifier.cpp
common/offset_range.cpp
common/preference.cpp
common/random.cpp
common/settings.cpp
+9 -11
View File
@@ -149,7 +149,7 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
ThreadStatusTlv::MlrStatus status = ThreadStatusTlv::kMlrSuccess;
Config config;
uint16_t addressesOffset, addressesLength;
OffsetRange offsetRange;
Ip6::Address address;
Ip6::Address addresses[Ip6AddressesTlv::kMaxAddresses];
uint8_t failedAddressNum = 0;
@@ -188,11 +188,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
processTimeoutTlv = hasCommissionerSessionIdTlv && (Tlv::Find<ThreadTimeoutTlv>(aMessage, timeout) == kErrorNone);
VerifyOrExit(Tlv::FindTlvValueOffset(aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
kErrorNone,
VerifyOrExit(Tlv::FindTlvValueOffsetRange(aMessage, Ip6AddressesTlv::kIp6Addresses, offsetRange) == kErrorNone,
error = kErrorParse);
VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
VerifyOrExit(offsetRange.GetLength() % sizeof(Ip6::Address) == 0, status = ThreadStatusTlv::kMlrGeneralFailure);
VerifyOrExit(offsetRange.GetLength() / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
status = ThreadStatusTlv::kMlrGeneralFailure);
if (!processTimeoutTlv)
@@ -220,9 +219,10 @@ void Manager::HandleMulticastListenerRegistration(const Coap::Message &aMessage,
expireTime = TimerMilli::GetNow() + TimeMilli::SecToMsec(timeout);
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
while (!offsetRange.IsEmpty())
{
IgnoreError(aMessage.Read(addressesOffset + offset, address));
IgnoreError(aMessage.Read(offsetRange, address));
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
if (timeout == 0)
{
@@ -581,7 +581,7 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Message &aMessage,
bool proactive;
Ip6::Address dua;
Ip6::InterfaceIdentifier meshLocalIid;
uint16_t networkNameOffset, networkNameLength;
OffsetRange offsetRange;
uint32_t timeSinceLastTransaction;
uint16_t srcRloc16 = Mle::kInvalidRloc16;
@@ -595,9 +595,7 @@ template <> void Manager::HandleTmf<kUriBackboneAnswer>(Coap::Message &aMessage,
SuccessOrExit(error = Tlv::Find<ThreadTargetTlv>(aMessage, dua));
SuccessOrExit(error = Tlv::Find<ThreadMeshLocalEidTlv>(aMessage, meshLocalIid));
SuccessOrExit(error = Tlv::Find<ThreadLastTransactionTimeTlv>(aMessage, timeSinceLastTransaction));
SuccessOrExit(error =
Tlv::FindTlvValueOffset(aMessage, ThreadTlv::kNetworkName, networkNameOffset, networkNameLength));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, ThreadTlv::kNetworkName, offsetRange));
error = Tlv::Find<ThreadRloc16Tlv>(aMessage, srcRloc16);
VerifyOrExit(error == kErrorNone || error == kErrorNotFound);
+21
View File
@@ -412,6 +412,11 @@ exit:
return error;
}
Error Message::AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange)
{
return AppendBytesFromMessage(aMessage, aOffsetRange.GetOffset(), aOffsetRange.GetLength());
}
Error Message::AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
{
Error error = kErrorNone;
@@ -649,11 +654,27 @@ uint16_t Message::ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) cons
return static_cast<uint16_t>(bufPtr - reinterpret_cast<uint8_t *>(aBuf));
}
uint16_t Message::ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const
{
return ReadBytes(aOffsetRange.GetOffset(), aBuf, aOffsetRange.GetLength());
}
Error Message::Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const
{
return (ReadBytes(aOffset, aBuf, aLength) == aLength) ? kErrorNone : kErrorParse;
}
Error Message::Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const
{
Error error = kErrorNone;
VerifyOrExit(aOffsetRange.Contains(aLength), error = kErrorParse);
VerifyOrExit(ReadBytes(aOffsetRange.GetOffset(), aBuf, aLength) == aLength, error = kErrorParse);
exit:
return error;
}
bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher) const
{
uint16_t bytesToCompare = aLength;
+64
View File
@@ -52,6 +52,7 @@
#include "common/linked_list.hpp"
#include "common/locator.hpp"
#include "common/non_copyable.hpp"
#include "common/offset_range.hpp"
#include "common/pool.hpp"
#include "common/timer.hpp"
#include "common/type_traits.hpp"
@@ -707,6 +708,19 @@ public:
*/
Error AppendBytesFromMessage(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
/**
* Appends bytes read from another or potentially the same message to the end of the current message.
*
* @param[in] aMessage The message to read the bytes from (it can be the same as the current message).
* @param[in] aOffsetRange The offset range in @p aMessage to read bytes from.
*
* @retval kErrorNone Successfully appended the bytes.
* @retval kErrorNoBufs Insufficient available buffers to grow the message.
* @retval kErrorParse Not enough bytes in @p aMessage to read @p aOffsetRange.
*
*/
Error AppendBytesFromMessage(const Message &aMessage, const OffsetRange &aOffsetRange);
/**
* Appends an object to the end of the message.
*
@@ -757,6 +771,17 @@ public:
*/
uint16_t ReadBytes(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
/**
* Reads bytes from the message.
*
* @param[in] aOffsetRange The offset range in the message to read bytes from.
* @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
*
* @returns The number of bytes read.
*
*/
uint16_t ReadBytes(const OffsetRange &aOffsetRange, void *aBuf) const;
/**
* Reads a given number of bytes from the message.
*
@@ -773,6 +798,22 @@ public:
*/
Error Read(uint16_t aOffset, void *aBuf, uint16_t aLength) const;
/**
* Reads a given number of bytes from the message.
*
* If there are fewer bytes available in the message or @p aOffsetRange than the requested @p aLength, the
* available bytes are read and copied into @p aBuf. In this case `kErrorParse` will be returned.
*
* @param[in] aOffsetRange The offset range in the message to read from.
* @param[out] aBuf A pointer to a data buffer to copy the read bytes into.
* @param[in] aLength Number of bytes to read.
*
* @retval kErrorNone Requested bytes were successfully read from message.
* @retval kErrorParse Not enough bytes remaining to read the requested @p aLength.
*
*/
Error Read(const OffsetRange &aOffsetRange, void *aBuf, uint16_t aLength) const;
/**
* Reads an object from the message.
*
@@ -796,6 +837,29 @@ public:
return Read(aOffset, &aObject, sizeof(ObjectType));
}
/**
* Reads an object from the message.
*
* If there are fewer bytes available in the message or @p aOffsetRange than the requested object size, the
* available bytes will be read and copied into @p aObject (@p aObject will be read partially). In this case
* `kErrorParse` will be returned.
*
* @tparam ObjectType The object type to read from the message.
*
* @param[in] aOffsetRange The offset range in the message to read from.
* @param[out] aObject A reference to the object to read into.
*
* @retval kErrorNone Object @p aObject was successfully read from message.
* @retval kErrorParse Not enough bytes remaining in message to read the entire object.
*
*/
template <typename ObjectType> Error Read(const OffsetRange &aOffsetRange, ObjectType &aObject) const
{
static_assert(!TypeTraits::IsPointer<ObjectType>::kValue, "ObjectType must not be a pointer");
return Read(aOffsetRange, &aObject, sizeof(ObjectType));
}
/**
* Compares the bytes in the message at a given offset with a given byte array.
*
+73
View File
@@ -0,0 +1,73 @@
/*
* 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.
*/
/**
* @file
* This file implements helper method for an offset range.
*/
#include "offset_range.hpp"
#include "common/code_utils.hpp"
#include "common/message.hpp"
#include "common/num_utils.hpp"
#include "common/numeric_limits.hpp"
namespace ot {
void OffsetRange::Init(uint16_t aOffset, uint16_t aLength)
{
uint16_t maxLength = NumericLimits<uint16_t>::kMax - aOffset;
mOffset = aOffset;
mLength = Min(aLength, maxLength);
}
void OffsetRange::InitFromRange(uint16_t aStartOffset, uint16_t aEndOffset)
{
Init(aStartOffset, Max(aStartOffset, aEndOffset) - aStartOffset);
}
void OffsetRange::InitFromMessageOffsetToEnd(const Message &aMessage)
{
InitFromRange(aMessage.GetOffset(), aMessage.GetLength());
}
void OffsetRange::InitFromMessageFullLength(const Message &aMessage) { Init(0, aMessage.GetLength()); }
void OffsetRange::AdvanceOffset(uint32_t aLength)
{
uint16_t length = static_cast<uint16_t>(Min<uint32_t>(aLength, mLength));
mOffset += length;
mLength -= length;
}
void OffsetRange::ShrinkLength(uint16_t aLength) { mLength = Min(mLength, aLength); }
} // namespace ot
+172
View File
@@ -0,0 +1,172 @@
/*
* 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.
*/
/**
* @file
* This file includes definitions for an offset range.
*/
#ifndef OFFSET_RANGE_HPP_
#define OFFSET_RANGE_HPP_
#include "openthread-core-config.h"
#include <stdbool.h>
#include <stdint.h>
#include "common/clearable.hpp"
namespace ot {
class Message;
/**
* Represents an offset range.
*
*/
class OffsetRange : public Clearable<OffsetRange>
{
public:
/**
* Initializes the `OffsetRange`.
*
* @param[in] aOffset The start offset.
* @param[in] aLength The range length (number of bytes).
*
*/
void Init(uint16_t aOffset, uint16_t aLength);
/**
* Initializes the `OffsetRange` from given start and end offsets.
*
* The range is inclusive of the start offset (@p aStartOffset) but exclusive of the end offset (@p aEndOffset).
*
* @param[in] aStartOffset The start offset (inclusive).
* @param[in] aEndOffset The end offset (exclusive).
*
*/
void InitFromRange(uint16_t aStartOffset, uint16_t aEndOffset);
/**
* Initializes the `OffsetRange` from a given `Message` from its offset to the message end.
*
* The start offset of the range is set to `aMessage.GetOffset()`, and the end offset is set to include all bytes
* in the message up to its current length `aMessage.GetLength()`.
*
* @param[in] aMessage The `Message` to initialize the `OffsetRange` from.
*
*/
void InitFromMessageOffsetToEnd(const Message &aMessage);
/**
* Initializes the `OffsetRange` from a given `Message` from zero offset up to to its full length.
*
* The start offset of the range is set to zero, and the end offset is set to include full length of @p aMessage.
*
* @param[in] aMessage The `Message` to initialize the `OffsetRange` from.
*
*/
void InitFromMessageFullLength(const Message &aMessage);
/**
* Gets the start offset of the `OffsetRange`
*
* @returns The start offset.
*
*/
uint16_t GetOffset(void) const { return mOffset; }
/**
* Gets the end offset of the `OffsetRange`.
*
* This offset is exclusive, meaning it marks the position immediately after the last byte within the range.
*
* @returns The end offset.
*
*/
uint16_t GetEndOffset(void) const { return (mOffset + mLength); }
/**
* Gets the `OffsetRange` length.
*
* @returns The length of the `OffsetRange` in bytes.
*
*/
uint16_t GetLength(void) const { return mLength; }
/**
* Indicates whether or not the `OffsetRange` is empty.
*
* @retval TRUE The `OffsetRange` is empty.
* @retval FALSE The `OffsetRange` is not empty (contains at least one byte).
*
*/
bool IsEmpty(void) const { return (mLength == 0); }
/**
* Indicates whether or not the `OffsetRange` contains a given number of bytes.
*
* @param[in] aLength The length to check.
*
* @retval TRUE The `OffsetRange` contains @p aLength or more bytes.
* @retval FALSE The `OffsetRange` does not contain @p aLength bytes.
*
*/
bool Contains(uint32_t aLength) const { return aLength <= mLength; }
/**
* Advances the start offset forward by the given number of bytes.
*
* This method ensures the start offset does not go beyond the end offset of the `OffsetRange`. If @p aLength is
* greater than the available bytes in the `OffsetRange`, the start offset is adjusted to the end offset,
* effectively shrinking the range to zero length.
*
* @param[in] aLength The number of bytes to advance the start offset.
*
*/
void AdvanceOffset(uint32_t aLength);
/**
* Shrinks the `OffsetRange` length to a given length.
*
* If the current length of the `OffsetRange` is longer than @p aLength, the offset range is shortened to
* @p aLength. If the range is already shorter or the same, it remains unchanged.
*
* @param[in] aLength The new length to use.
*
*/
void ShrinkLength(uint16_t aLength);
private:
uint16_t mOffset;
uint16_t mLength;
};
} // namespace ot
#endif // OFFSET_RANGE_HPP_
+11 -34
View File
@@ -56,19 +56,15 @@ const uint8_t *Tlv::GetValue(void) const
Error Tlv::AppendTo(Message &aMessage) const { return aMessage.AppendBytes(this, static_cast<uint16_t>(GetSize())); }
Error Tlv::ParseAndSkipTlv(const Message &aMessage, uint16_t &aOffset)
Error Tlv::ParseAndSkipTlv(const Message &aMessage, OffsetRange &aOffsetRange)
{
Error error;
ParsedInfo info;
SuccessOrExit(error = info.ParseFrom(aMessage, aOffset));
SuccessOrExit(error = info.ParseFrom(aMessage, aOffsetRange.GetOffset()));
// `ParseFrom()` has already validated that the entire TLV is
// present within `aMessage`. This ensures that `aOffset + mSize`
// is less than `aMessage.GetLength()`, and therefore we cannot
// have an overflow here.
aOffset += info.mSize;
VerifyOrExit(aOffsetRange.Contains(info.mSize), error = kErrorParse);
aOffsetRange.AdvanceOffset(info.mSize);
exit:
return error;
@@ -99,32 +95,15 @@ Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, uint16_t aMaxSize, Tl
exit:
return error;
}
Error Tlv::FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength)
Error Tlv::FindTlvValueOffsetRange(const Message &aMessage, uint8_t aType, OffsetRange &aOffsetRange)
{
Error error;
ParsedInfo info;
SuccessOrExit(error = info.FindIn(aMessage, aType));
aValueOffset = info.mValueOffset;
aLength = info.mLength;
exit:
return error;
}
Error Tlv::FindTlvValueStartEndOffsets(const Message &aMessage,
uint8_t aType,
uint16_t &aValueStartOffset,
uint16_t &aValueEndOffset)
{
Error error;
ParsedInfo info;
SuccessOrExit(error = info.FindIn(aMessage, aType));
aValueStartOffset = info.mValueOffset;
aValueEndOffset = info.mValueOffset + info.mLength;
aOffsetRange.Init(info.mValueOffset, info.mLength);
exit:
return error;
@@ -291,13 +270,11 @@ template Error Tlv::FindUintTlv<uint32_t>(const Message &aMessage, uint8_t aType
Error Tlv::FindTlv(const Message &aMessage, uint8_t aType, void *aValue, uint16_t aLength)
{
Error error;
uint16_t offset;
uint16_t length;
Error error;
OffsetRange offsetRange;
SuccessOrExit(error = FindTlvValueOffset(aMessage, aType, offset, length));
VerifyOrExit(length >= aLength, error = kErrorParse);
aMessage.ReadBytes(offset, aValue, aLength);
SuccessOrExit(error = FindTlvValueOffsetRange(aMessage, aType, offsetRange));
error = aMessage.Read(offsetRange, aValue, aLength);
exit:
return error;
+10 -29
View File
@@ -42,6 +42,7 @@
#include "common/const_cast.hpp"
#include "common/encoding.hpp"
#include "common/error.hpp"
#include "common/offset_range.hpp"
#include "common/type_traits.hpp"
namespace ot {
@@ -245,19 +246,19 @@ public:
// Static methods for reading/finding/appending TLVs in a `Message`.
/**
* Parses a TLV in a message at a given offset, validating that it is fully contained within the message and then
* updating the offset to skip over the entire parsed TLV.
* Parses a TLV in a message from a given offset range, validating that it is fully contained within the offset
* range and the message, and then updating the offset range to skip over the entire parsed TLV.
*
* Can be used independent of whether the read TLV (from the message) is an Extended TLV or not.
*
* @param[in] aMessage The message to read from.
* @param[in,out] aOffset The offset to read from. On success, it is updated to point after the parsed TLV.
* @param[in] aMessage The message to read from.
* @param[in,out] aOffsetRange The offset range to read from. On success, it is updated to skip the TLV.
*
* @retval kErrorNone Successfully parsed a TLV from @p aMessage. @p aOffset is updated.
* @retval kErrorNone Successfully parsed a TLV from @p aMessage. @p aOffsetRange is updated.
* @retval kErrorParse The TLV was not well-formed or was not fully contained in @p aMessage.
*
*/
static Error ParseAndSkipTlv(const Message &aMessage, uint16_t &aOffset);
static Error ParseAndSkipTlv(const Message &aMessage, OffsetRange &aOffsetRange);
/**
* Reads a TLV's value in a message at a given offset expecting a minimum length for the value.
@@ -405,39 +406,19 @@ public:
}
/**
* Finds the offset and length of TLV value for a given TLV type within @p aMessage.
* Finds the offset range of the TLV value for a given TLV type within @p aMessage.
*
* Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
*
* @param[in] aMessage A reference to the message.
* @param[in] aType The Type value to search for.
* @param[out] aValueOffset The offset where the value starts.
* @param[out] aLength The length of the value.
* @param[out] aOffsetRange A reference to return the offset range of the TLV value when found.
*
* @retval kErrorNone Successfully found the TLV.
* @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
static Error FindTlvValueOffset(const Message &aMessage, uint8_t aType, uint16_t &aValueOffset, uint16_t &aLength);
/**
* Finds the start and end offset of TLV value for a given TLV type with @p aMessage.
*
* Can be used independent of whether the read TLV (from message) is an Extended TLV or not.
*
* @param[in] aMessage A reference to the message.
* @param[in] aType The Type value to search for.
* @param[out] aValueStartOffset The offset where the value starts.
* @param[out] aValueEndOffset The offset immediately after the last byte of value.
*
* @retval kErrorNone Successfully found the TLV.
* @retval kErrorNotFound Could not find the TLV with Type @p aType.
*
*/
static Error FindTlvValueStartEndOffsets(const Message &aMessage,
uint8_t aType,
uint16_t &aValueStartOffset,
uint16_t &aValueEndOffset);
static Error FindTlvValueOffsetRange(const Message &aMessage, uint8_t aType, OffsetRange &aOffsetRange);
/**
* Searches for a TLV with a given type in a message, ensures its length is same or larger than
+21 -17
View File
@@ -317,22 +317,20 @@ template <> void BorderAgent::HandleTmf<kUriProxyTx>(Coap::Message &aMessage, co
Error error = kErrorNone;
Message *message = nullptr;
Ip6::MessageInfo messageInfo;
uint16_t offset;
uint16_t length;
OffsetRange offsetRange;
UdpEncapsulationTlvHeader udpEncapHeader;
VerifyOrExit(mState != kStateStopped);
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kUdpEncapsulation, offset, length));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kUdpEncapsulation, offsetRange));
SuccessOrExit(error = aMessage.Read(offset, udpEncapHeader));
offset += sizeof(UdpEncapsulationTlvHeader);
length -= sizeof(UdpEncapsulationTlvHeader);
SuccessOrExit(error = aMessage.Read(offsetRange, udpEncapHeader));
offsetRange.AdvanceOffset(sizeof(UdpEncapsulationTlvHeader));
VerifyOrExit(udpEncapHeader.GetSourcePort() > 0 && udpEncapHeader.GetDestinationPort() > 0, error = kErrorDrop);
VerifyOrExit((message = Get<Ip6::Udp>().NewMessage()) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offset, length));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
messageInfo.SetSockPort(udpEncapHeader.GetSourcePort());
messageInfo.SetSockAddr(mCommissionerAloc.GetAddress());
@@ -376,16 +374,18 @@ bool BorderAgent::HandleUdpReceive(const Message &aMessage, const Ip6::MessageIn
{
ExtendedTlv extTlv;
UdpEncapsulationTlvHeader udpEncapHeader;
uint16_t udpLength = aMessage.GetLength() - aMessage.GetOffset();
OffsetRange offsetRange;
offsetRange.InitFromMessageOffsetToEnd(aMessage);
extTlv.SetType(Tlv::kUdpEncapsulation);
extTlv.SetLength(sizeof(UdpEncapsulationTlvHeader) + udpLength);
extTlv.SetLength(sizeof(UdpEncapsulationTlvHeader) + offsetRange.GetLength());
SuccessOrExit(error = message->Append(extTlv));
udpEncapHeader.SetSourcePort(aMessageInfo.GetPeerPort());
udpEncapHeader.SetDestinationPort(aMessageInfo.GetSockPort());
SuccessOrExit(error = message->Append(udpEncapHeader));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(), udpLength));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
}
SuccessOrExit(error = Tlv::Append<Ip6AddressTlv>(*message, aMessageInfo.GetPeerAddr()));
@@ -427,10 +427,12 @@ exit:
Error BorderAgent::ForwardToCommissioner(Coap::Message &aForwardMessage, const Message &aMessage)
{
Error error;
Error error;
OffsetRange offsetRange;
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, offsetRange));
SuccessOrExit(error = aForwardMessage.AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
aMessage.GetLength() - aMessage.GetOffset()));
SuccessOrExit(error = SendMessage(aForwardMessage));
LogInfo("Sent to commissioner");
@@ -498,6 +500,7 @@ template <> void BorderAgent::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, co
uint16_t joinerRouterRloc;
Coap::Message *message = nullptr;
Tmf::MessageInfo messageInfo(GetInstance());
OffsetRange offsetRange;
VerifyOrExit(mState != kStateStopped);
@@ -508,8 +511,8 @@ template <> void BorderAgent::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, co
message = Get<Tmf::Agent>().NewPriorityNonConfirmablePostMessage(kUriRelayTx);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
aMessage.GetLength() - aMessage.GetOffset()));
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
messageInfo.SetSockAddrToRlocPeerAddrTo(joinerRouterRloc);
messageInfo.SetSockPortToTmf();
@@ -531,6 +534,7 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes
Coap::Message *message = nullptr;
bool petition = false;
bool separate = false;
OffsetRange offsetRange;
VerifyOrExit(mState != kStateStopped);
@@ -558,8 +562,8 @@ Error BorderAgent::ForwardToLeader(const Coap::Message &aMessage, const Ip6::Mes
message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(aUri);
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(),
aMessage.GetLength() - aMessage.GetOffset()));
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
messageInfo.SetSockAddrToRlocPeerAddrToLeaderAloc();
messageInfo.SetSockPortToTmf();
+4 -6
View File
@@ -902,8 +902,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
Ip6::InterfaceIdentifier joinerIid;
uint16_t joinerRloc;
Ip6::MessageInfo joinerMessageInfo;
uint16_t startOffset;
uint16_t endOffset;
OffsetRange offsetRange;
VerifyOrExit(mState == kStateActive, error = kErrorInvalidState);
@@ -913,8 +912,7 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMessage, joinerIid));
SuccessOrExit(error = Tlv::Find<JoinerRouterLocatorTlv>(aMessage, joinerRloc));
SuccessOrExit(
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Tlv::kJoinerDtlsEncapsulation, startOffset, endOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kJoinerDtlsEncapsulation, offsetRange));
if (!Get<Tmf::SecureAgent>().IsConnectionActive())
{
@@ -951,8 +949,8 @@ template <> void Commissioner::HandleTmf<kUriRelayRx>(Coap::Message &aMessage, c
LogInfo("Received %s (%s, 0x%04x)", UriToString<kUriRelayRx>(), mJoinerIid.ToString().AsCString(), mJoinerRloc);
aMessage.SetOffset(startOffset);
SuccessOrExit(error = aMessage.SetLength(endOffset));
aMessage.SetOffset(offsetRange.GetOffset());
SuccessOrExit(error = aMessage.SetLength(offsetRange.GetEndOffset()));
joinerMessageInfo.SetPeerAddr(Get<Mle::MleRouter>().GetMeshLocalEid());
joinerMessageInfo.GetPeerAddr().SetIid(mJoinerIid);
+4 -4
View File
@@ -337,14 +337,14 @@ void Dataset::SetFrom(const Info &aDatasetInfo)
// `mUpdateTime` is already set by `WriteTlvsFrom()`.
}
Error Dataset::SetFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
Error Dataset::SetFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
{
Error error = kErrorNone;
VerifyOrExit(aLength <= kMaxLength, error = kErrorInvalidArgs);
VerifyOrExit(aOffsetRange.GetLength() <= kMaxLength, error = kErrorInvalidArgs);
SuccessOrExit(error = aMessage.Read(aOffset, mTlvs, aLength));
mLength = static_cast<uint8_t>(aLength);
SuccessOrExit(error = aMessage.Read(aOffsetRange, mTlvs, aOffsetRange.GetLength()));
mLength = static_cast<uint8_t>(aOffsetRange.GetLength());
mUpdateTime = TimerMilli::GetNow();
+4 -5
View File
@@ -633,16 +633,15 @@ public:
/**
* 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.
* @param[in] aMessage The message to read from.
* @param[in] aOffsetRange The offset range in @p aMessage to read the Dataset TLVs.
*
* @retval kErrorNone Successfully set the Dataset.
* @retval kInvalidArgs The @p aLength is longer than `kMaxLength`.
* @retval kInvalidArgs The given offset range length 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);
Error SetFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
/**
* Returns a pointer to the start of Dataset TLVs sequence.
+7 -7
View File
@@ -532,17 +532,17 @@ exit:
void DatasetManager::HandleGet(const Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo) const
{
TlvList tlvList;
uint8_t tlvType;
uint16_t offset;
uint16_t length;
TlvList tlvList;
uint8_t tlvType;
OffsetRange offsetRange;
SuccessOrExit(Tlv::FindTlvValueOffset(aMessage, Tlv::kGet, offset, length));
SuccessOrExit(Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kGet, offsetRange));
for (; length > 0; length--, offset++)
while (!offsetRange.IsEmpty())
{
IgnoreError(aMessage.Read(offset, tlvType));
IgnoreError(aMessage.Read(offsetRange, tlvType));
tlvList.Add(tlvType);
offsetRange.AdvanceOffset(sizeof(uint8_t));
}
// MGMT_PENDING_GET.rsp must include Delay Timer TLV (Thread 1.1.1
+3 -1
View File
@@ -71,6 +71,7 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand,
{
Error error = kErrorParse;
Dataset dataset;
OffsetRange offsetRange;
Timestamp activeTimestamp;
ChannelTlvValue channelValue;
uint16_t sessionId;
@@ -81,7 +82,8 @@ Error DatasetManager::ProcessSetOrReplaceRequest(MgmtCommand aCommand,
aInfo.Clear();
SuccessOrExit(dataset.SetFrom(aMessage, aMessage.GetOffset(), aMessage.GetLength() - aMessage.GetOffset()));
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(dataset.SetFrom(aMessage, offsetRange));
SuccessOrExit(dataset.ValidateTlvs());
// Verify that the request includes timestamps that are
+7 -5
View File
@@ -161,14 +161,16 @@ void DatasetUpdater::HandleNotifierEvents(Events aEvents)
void DatasetUpdater::HandleDatasetChanged(Dataset::Type aType)
{
Dataset requestedDataset;
Dataset newDataset;
Timestamp newTimestamp;
Timestamp requestedTimestamp;
Dataset requestedDataset;
Dataset newDataset;
Timestamp newTimestamp;
Timestamp requestedTimestamp;
OffsetRange offsetRange;
VerifyOrExit(IsUpdateOngoing());
SuccessOrExit(requestedDataset.SetFrom(*mDataset, /* aOffset */ 0, mDataset->GetLength()));
offsetRange.InitFromMessageFullLength(*mDataset);
SuccessOrExit(requestedDataset.SetFrom(*mDataset, offsetRange));
if (aType == Dataset::kActive)
{
+8 -6
View File
@@ -133,6 +133,7 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
Tmf::MessageInfo messageInfo(GetInstance());
ExtendedTlv tlv;
uint16_t borderAgentRloc;
OffsetRange offsetRange;
LogInfo("JoinerRouter::HandleUdpReceive");
@@ -145,10 +146,12 @@ void JoinerRouter::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &a
SuccessOrExit(error = Tlv::Append<JoinerIidTlv>(*message, aMessageInfo.GetPeerAddr().GetIid()));
SuccessOrExit(error = Tlv::Append<JoinerRouterLocatorTlv>(*message, Get<Mle::MleRouter>().GetRloc16()));
offsetRange.InitFromMessageOffsetToEnd(aMessage);
tlv.SetType(Tlv::kJoinerDtlsEncapsulation);
tlv.SetLength(aMessage.GetLength() - aMessage.GetOffset());
tlv.SetLength(offsetRange.GetLength());
SuccessOrExit(error = message->Append(tlv));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, aMessage.GetOffset(), tlv.GetLength()));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
messageInfo.SetSockAddrToRlocPeerAddrTo(borderAgentRloc);
@@ -168,8 +171,7 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, c
uint16_t joinerPort;
Ip6::InterfaceIdentifier joinerIid;
Kek kek;
uint16_t offset;
uint16_t length;
OffsetRange offsetRange;
Message *message = nullptr;
Message::Settings settings(Message::kNoLinkSecurity, Message::kPriorityNet);
Ip6::MessageInfo messageInfo;
@@ -181,11 +183,11 @@ template <> void JoinerRouter::HandleTmf<kUriRelayTx>(Coap::Message &aMessage, c
SuccessOrExit(error = Tlv::Find<JoinerUdpPortTlv>(aMessage, joinerPort));
SuccessOrExit(error = Tlv::Find<JoinerIidTlv>(aMessage, joinerIid));
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Tlv::kJoinerDtlsEncapsulation, offset, length));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Tlv::kJoinerDtlsEncapsulation, offsetRange));
VerifyOrExit((message = mSocket.NewMessage(0, settings)) != nullptr, error = kErrorNoBufs);
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offset, length));
SuccessOrExit(error = message->AppendBytesFromMessage(aMessage, offsetRange));
messageInfo.GetPeerAddr().SetToLinkLocalAddress(joinerIid);
messageInfo.SetPeerPort(joinerPort);
+5 -2
View File
@@ -146,12 +146,15 @@ Error ChannelMaskTlv::FindIn(const Message &aMessage, uint32_t &aChannelMask)
{
Error error;
EntriesData entriesData;
OffsetRange offsetRange;
entriesData.Clear();
entriesData.mMessage = &aMessage;
SuccessOrExit(error = FindTlvValueOffset(aMessage, Tlv::kChannelMask, entriesData.mOffset, entriesData.mLength));
error = entriesData.Parse(aChannelMask);
SuccessOrExit(error = FindTlvValueOffsetRange(aMessage, Tlv::kChannelMask, offsetRange));
entriesData.mOffset = offsetRange.GetOffset();
entriesData.mLength = offsetRange.GetLength();
error = entriesData.Parse(aChannelMask);
exit:
return error;
+5 -3
View File
@@ -462,10 +462,12 @@ exit:
Error TcatAgent::HandleSetActiveOperationalDataset(const Message &aIncommingMessage, uint16_t aOffset, uint16_t aLength)
{
Dataset dataset;
Error error;
Dataset dataset;
OffsetRange offsetRange;
Error error;
SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, aOffset, aLength));
offsetRange.Init(aOffset, aLength);
SuccessOrExit(error = dataset.SetFrom(aIncommingMessage, offsetRange));
SuccessOrExit(error = dataset.ValidateTlvs());
if (!CheckCommandClassAuthorizationFlags(mCommissionerAuthorizationField.mApplicationFlags,
+15 -15
View File
@@ -312,8 +312,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
MeshCoP::Tlv meshcopTlv;
MeshCoP::DiscoveryResponseTlv discoveryResponse;
ScanResult result;
uint16_t offset;
uint16_t end;
OffsetRange offsetRange;
bool didCheckSteeringData = false;
Mle::Log(Mle::kMessageReceive, Mle::kTypeDiscoveryResponse, aRxInfo.mMessageInfo.GetPeerAddr());
@@ -321,7 +320,7 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
VerifyOrExit(mState == kStateScanning, error = kErrorDrop);
// Find MLE Discovery TLV
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kDiscovery, offset, end));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kDiscovery, offsetRange));
ClearAllBytes(result);
result.mDiscover = true;
@@ -333,35 +332,35 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
aRxInfo.mMessageInfo.GetPeerAddr().GetIid().ConvertToExtAddress(AsCoreType(&result.mExtAddress));
// Process MeshCoP TLVs
while (offset < end)
while (!offsetRange.IsEmpty())
{
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, meshcopTlv));
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, meshcopTlv));
if (meshcopTlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offset));
VerifyOrExit(offset <= end, error = kErrorParse);
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offsetRange));
continue;
}
VerifyOrExit(meshcopTlv.GetSize() + offset <= aRxInfo.mMessage.GetLength(), error = kErrorParse);
VerifyOrExit(offsetRange.Contains(meshcopTlv.GetSize()), error = kErrorParse);
switch (meshcopTlv.GetType())
{
case MeshCoP::Tlv::kDiscoveryResponse:
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, discoveryResponse));
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, discoveryResponse));
VerifyOrExit(discoveryResponse.IsValid(), error = kErrorParse);
result.mVersion = discoveryResponse.GetVersion();
result.mIsNative = discoveryResponse.IsNativeCommissioner();
break;
case MeshCoP::Tlv::kExtendedPanId:
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset,
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
AsCoreType(&result.mExtendedPanId)));
break;
case MeshCoP::Tlv::kNetworkName:
SuccessOrExit(error = Tlv::Read<MeshCoP::NetworkNameTlv>(aRxInfo.mMessage, offset, result.mNetworkName.m8));
SuccessOrExit(error = Tlv::Read<MeshCoP::NetworkNameTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
result.mNetworkName.m8));
break;
case MeshCoP::Tlv::kSteeringData:
@@ -377,7 +376,8 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
steeringData.Init(dataLength);
SuccessOrExit(error = Tlv::ReadTlvValue(aRxInfo.mMessage, offset, steeringData.GetData(), dataLength));
SuccessOrExit(error = Tlv::ReadTlvValue(aRxInfo.mMessage, offsetRange.GetOffset(),
steeringData.GetData(), dataLength));
if (mEnableFiltering)
{
@@ -389,15 +389,15 @@ void DiscoverScanner::HandleDiscoveryResponse(Mle::RxInfo &aRxInfo) const
break;
case MeshCoP::Tlv::kJoinerUdpPort:
SuccessOrExit(error =
Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offset, result.mJoinerUdpPort));
SuccessOrExit(error = Tlv::Read<MeshCoP::JoinerUdpPortTlv>(aRxInfo.mMessage, offsetRange.GetOffset(),
result.mJoinerUdpPort));
break;
default:
break;
}
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
offsetRange.AdvanceOffset(meshcopTlv.GetSize());
}
VerifyOrExit(!mEnableFiltering || didCheckSteeringData);
+70 -66
View File
@@ -123,11 +123,9 @@ exit:
return error;
}
void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress)
void Initiator::HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress)
{
Error error = kErrorNone;
uint16_t offset = aOffset;
uint16_t endOffset = aOffset + aLength;
bool hasStatus = false;
bool hasReport = false;
Tlv tlv;
@@ -142,18 +140,17 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
values.Clear();
while (offset < endOffset)
while (!aOffsetRange.IsEmpty())
{
SuccessOrExit(error = aMessage.Read(offset, tlv));
SuccessOrExit(error = aMessage.Read(aOffsetRange, tlv));
if (tlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
VerifyOrExit(offset <= endOffset, error = kErrorParse);
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, aOffsetRange));
continue;
}
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
VerifyOrExit(aOffsetRange.Contains(tlv.GetSize()), error = kErrorParse);
// The report must contain either:
// - One or more Report Sub-TLVs (in case of success), or
@@ -163,7 +160,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
{
case StatusSubTlv::kType:
VerifyOrExit(!hasStatus && !hasReport, error = kErrorDrop);
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offset, status));
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, aOffsetRange.GetOffset(), status));
hasStatus = true;
break;
@@ -171,7 +168,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
VerifyOrExit(!hasStatus, error = kErrorDrop);
// Read the report sub-TLV assuming minimum length
SuccessOrExit(error = aMessage.Read(offset, &reportTlv, sizeof(Tlv) + ReportSubTlv::kMinLength));
SuccessOrExit(error = aMessage.Read(aOffsetRange, &reportTlv, sizeof(Tlv) + ReportSubTlv::kMinLength));
VerifyOrExit(reportTlv.IsValid(), error = kErrorParse);
hasReport = true;
@@ -187,7 +184,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
{
// If Type ID indicates metric value has 4 bytes length, we
// read the full `reportTlv`.
SuccessOrExit(error = aMessage.Read(offset, reportTlv));
SuccessOrExit(error = aMessage.Read(aOffsetRange.GetOffset(), reportTlv));
}
switch (typeId)
@@ -220,7 +217,7 @@ void Initiator::HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t
break;
}
offset += sizeof(Tlv) + tlv.GetLength();
aOffsetRange.AdvanceOffset(tlv.GetSize());
}
VerifyOrExit(hasStatus || hasReport);
@@ -310,37 +307,34 @@ exit:
Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Address &aAddress)
{
Error error = kErrorNone;
uint16_t offset;
uint16_t endOffset;
uint8_t status;
bool hasStatus = false;
Error error = kErrorNone;
OffsetRange offsetRange;
uint8_t status;
bool hasStatus = false;
VerifyOrExit(mMgmtResponseCallback.IsSet());
SuccessOrExit(
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, endOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offsetRange));
while (offset < endOffset)
while (!offsetRange.IsEmpty())
{
Tlv tlv;
SuccessOrExit(error = aMessage.Read(offset, tlv));
SuccessOrExit(error = aMessage.Read(offsetRange, tlv));
if (tlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
VerifyOrExit(offset <= endOffset, error = kErrorParse);
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
continue;
}
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
switch (tlv.GetType())
{
case StatusSubTlv::kType:
VerifyOrExit(!hasStatus, error = kErrorParse);
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offset, status));
SuccessOrExit(error = Tlv::Read<StatusSubTlv>(aMessage, offsetRange.GetOffset(), status));
hasStatus = true;
break;
@@ -348,7 +342,7 @@ Error Initiator::HandleManagementResponse(const Message &aMessage, const Ip6::Ad
break;
}
offset += sizeof(Tlv) + tlv.GetLength();
offsetRange.AdvanceOffset(tlv.GetSize());
}
VerifyOrExit(hasStatus, error = kErrorParse);
@@ -440,7 +434,7 @@ Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, N
bool hasQueryId = false;
uint16_t length;
uint16_t offset;
uint16_t endOffset;
OffsetRange offsetRange;
MetricsValues values;
values.Clear();
@@ -449,40 +443,43 @@ Error Subject::AppendReport(Message &aMessage, const Message &aRequestMessage, N
// Parse MLE Link Metrics Query TLV and its sub-TLVs from
// `aRequestMessage`.
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offset,
endOffset));
SuccessOrExit(error =
Tlv::FindTlvValueOffsetRange(aRequestMessage, Mle::Tlv::Type::kLinkMetricsQuery, offsetRange));
while (offset < endOffset)
while (!offsetRange.IsEmpty())
{
SuccessOrExit(error = aRequestMessage.Read(offset, tlv));
OffsetRange tlvOffsetRange;
SuccessOrExit(error = aRequestMessage.Read(offsetRange, tlv));
if (tlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offset));
VerifyOrExit(offset <= endOffset, error = kErrorParse);
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
continue;
}
VerifyOrExit(tlv.GetSize() + offset <= endOffset, error = kErrorParse);
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
tlvOffsetRange = offsetRange;
tlvOffsetRange.ShrinkLength(tlv.GetSize());
switch (tlv.GetType())
{
case SubTlv::kQueryId:
SuccessOrExit(error = Tlv::Read<QueryIdSubTlv>(aRequestMessage, offset, queryId));
SuccessOrExit(error = Tlv::Read<QueryIdSubTlv>(aRequestMessage, tlvOffsetRange.GetOffset(), queryId));
hasQueryId = true;
break;
case SubTlv::kQueryOptions:
SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, offset + sizeof(tlv),
static_cast<uint16_t>(offset + tlv.GetSize()),
values.GetMetrics()));
tlvOffsetRange.AdvanceOffset(sizeof(tlv));
SuccessOrExit(error = ReadTypeIdsFromMessage(aRequestMessage, tlvOffsetRange, values.GetMetrics()));
break;
default:
break;
}
offset += static_cast<uint16_t>(tlv.GetSize());
offsetRange.AdvanceOffset(tlv.GetSize());
}
VerifyOrExit(hasQueryId, error = kErrorParse);
@@ -539,31 +536,39 @@ exit:
Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeighbor, Status &aStatus)
{
Error error = kErrorNone;
uint16_t offset;
uint16_t endOffset;
uint16_t tlvEndOffset;
OffsetRange offsetRange;
FwdProbingRegSubTlv fwdProbingSubTlv;
EnhAckConfigSubTlv enhAckConfigSubTlv;
Metrics metrics;
SuccessOrExit(
error = Tlv::FindTlvValueStartEndOffsets(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offset, endOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkMetricsManagement, offsetRange));
// Set sub-TLV lengths to zero to indicate that we have
// not yet seen them in the message.
fwdProbingSubTlv.SetLength(0);
enhAckConfigSubTlv.SetLength(0);
for (; offset < endOffset; offset = tlvEndOffset)
while (!offsetRange.IsEmpty())
{
Tlv tlv;
uint16_t minTlvSize;
Tlv *subTlv;
Tlv tlv;
uint16_t minTlvSize;
Tlv *subTlv;
OffsetRange tlvOffsetRange;
SuccessOrExit(error = aMessage.Read(offset, tlv));
SuccessOrExit(error = aMessage.Read(offsetRange, tlv));
VerifyOrExit(offset + tlv.GetSize() <= endOffset, error = kErrorParse);
tlvEndOffset = static_cast<uint16_t>(offset + tlv.GetSize());
if (tlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aMessage, offsetRange));
continue;
}
VerifyOrExit(offsetRange.Contains(tlv.GetSize()), error = kErrorParse);
tlvOffsetRange = offsetRange;
tlvOffsetRange.ShrinkLength(tlv.GetSize());
offsetRange.AdvanceOffset(tlv.GetSize());
switch (tlv.GetType())
{
@@ -588,8 +593,10 @@ Error Subject::HandleManagementRequest(const Message &aMessage, Neighbor &aNeigh
VerifyOrExit(tlv.GetSize() >= minTlvSize, error = kErrorParse);
// Read `subTlv` with its `minTlvSize`, followed by the Type IDs.
SuccessOrExit(error = aMessage.Read(offset, subTlv, minTlvSize));
SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, offset + minTlvSize, tlvEndOffset, metrics));
SuccessOrExit(error = aMessage.Read(tlvOffsetRange.GetOffset(), subTlv, minTlvSize));
tlvOffsetRange.AdvanceOffset(minTlvSize);
SuccessOrExit(error = ReadTypeIdsFromMessage(aMessage, tlvOffsetRange, metrics));
}
if (fwdProbingSubTlv.GetLength() != 0)
@@ -609,13 +616,11 @@ exit:
Error Subject::HandleLinkProbe(const Message &aMessage, uint8_t &aSeriesId)
{
Error error = kErrorNone;
uint16_t offset;
uint16_t length;
Error error = kErrorNone;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueOffset(aMessage, Mle::Tlv::Type::kLinkProbe, offset, length));
VerifyOrExit(length >= sizeof(aSeriesId), error = kErrorParse);
error = aMessage.Read(offset, aSeriesId);
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Mle::Tlv::Type::kLinkProbe, offsetRange));
error = aMessage.Read(offsetRange, aSeriesId);
exit:
return error;
@@ -662,20 +667,17 @@ exit:
void Subject::Free(SeriesInfo &aSeriesInfo) { mSeriesInfoPool.Free(aSeriesInfo); }
Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
uint16_t aStartOffset,
uint16_t aEndOffset,
Metrics &aMetrics)
Error Subject::ReadTypeIdsFromMessage(const Message &aMessage, OffsetRange &aOffsetRange, Metrics &aMetrics)
{
Error error = kErrorNone;
aMetrics.Clear();
for (uint16_t offset = aStartOffset; offset < aEndOffset; offset++)
while (!aOffsetRange.IsEmpty())
{
uint8_t typeId;
SuccessOrExit(aMessage.Read(offset, typeId));
SuccessOrExit(aMessage.Read(aOffsetRange, typeId));
switch (typeId)
{
@@ -702,7 +704,7 @@ Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
default:
if (TypeId::IsExtended(typeId))
{
offset += sizeof(uint8_t); // Skip the additional second byte.
aOffsetRange.AdvanceOffset(sizeof(uint8_t)); // Skip the additional second byte.
}
else
{
@@ -710,6 +712,8 @@ Error Subject::ReadTypeIdsFromMessage(const Message &aMessage,
}
break;
}
aOffsetRange.AdvanceOffset(sizeof(uint8_t));
}
exit:
+3 -7
View File
@@ -148,12 +148,11 @@ public:
* Handles the received Link Metrics report contained in @p aMessage.
*
* @param[in] aMessage A reference to the message.
* @param[in] aOffset The offset in bytes where the metrics report sub-TLVs start.
* @param[in] aLength The length of the metrics report sub-TLVs in bytes.
* @param[in] aOffsetRange The offset range in @p aMessage where the metrics report sub-TLVs are present.
* @param[in] aAddress A reference to the source address of the message.
*
*/
void HandleReport(const Message &aMessage, uint16_t aOffset, uint16_t aLength, const Ip6::Address &aAddress);
void HandleReport(const Message &aMessage, OffsetRange &aOffsetRange, const Ip6::Address &aAddress);
/**
* Sends an MLE Link Metrics Management Request to configure/clear a Forward Tracking Series.
@@ -342,10 +341,7 @@ private:
static constexpr uint16_t kMaxSeriesSupported = OPENTHREAD_CONFIG_MLE_LINK_METRICS_SERIES_MTD;
#endif
static Error ReadTypeIdsFromMessage(const Message &aMessage,
uint16_t aStartOffset,
uint16_t aEndOffset,
Metrics &aMetrics);
static Error ReadTypeIdsFromMessage(const Message &aMessage, OffsetRange &aOffsetRange, Metrics &aMetrics);
static Error AppendReportSubTlvToMessage(Message &aMessage, const MetricsValues &aValues);
Status ConfigureForwardTrackingSeries(uint8_t aSeriesId,
+22 -31
View File
@@ -2842,12 +2842,11 @@ void Mle::HandleDataResponse(RxInfo &aRxInfo)
#if OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
{
uint16_t offset;
uint16_t length;
OffsetRange offsetRange;
if (Tlv::FindTlvValueOffset(aRxInfo.mMessage, Tlv::kLinkMetricsReport, offset, length) == kErrorNone)
if (Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kLinkMetricsReport, offsetRange) == kErrorNone)
{
Get<LinkMetrics::Initiator>().HandleReport(aRxInfo.mMessage, offset, length,
Get<LinkMetrics::Initiator>().HandleReport(aRxInfo.mMessage, offsetRange,
aRxInfo.mMessageInfo.GetPeerAddr());
}
}
@@ -4948,10 +4947,9 @@ exit:
bool Mle::RxMessage::ContainsTlv(Tlv::Type aTlvType) const
{
uint16_t offset;
uint16_t length;
OffsetRange offsetRange;
return Tlv::FindTlvValueOffset(*this, aTlvType, offset, length) == kErrorNone;
return Tlv::FindTlvValueOffsetRange(*this, aTlvType, offsetRange) == kErrorNone;
}
Error Mle::RxMessage::ReadModeTlv(DeviceMode &aMode) const
@@ -4979,12 +4977,11 @@ exit:
Error Mle::RxMessage::ReadChallengeOrResponse(uint8_t aTlvType, RxChallenge &aRxChallenge) const
{
Error error;
uint16_t offset;
uint16_t length;
Error error;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, aTlvType, offset, length));
error = aRxChallenge.ReadFrom(*this, offset, length);
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, aTlvType, offsetRange));
error = aRxChallenge.ReadFrom(*this, offsetRange);
exit:
return error;
@@ -5049,15 +5046,14 @@ exit:
Error Mle::RxMessage::ReadAndSetNetworkDataTlv(const LeaderData &aLeaderData) const
{
Error error;
uint16_t offset;
uint16_t length;
Error error;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kNetworkData, offset, length));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, Tlv::kNetworkData, offsetRange));
error = Get<NetworkData::Leader>().SetNetworkData(aLeaderData.GetDataVersion(NetworkData::kFullSet),
aLeaderData.GetDataVersion(NetworkData::kStableSubset),
Get<Mle>().GetNetworkDataType(), *this, offset, length);
Get<Mle>().GetNetworkDataType(), *this, offsetRange);
exit:
return error;
}
@@ -5078,12 +5074,11 @@ Error Mle::RxMessage::ReadAndSaveDataset(MeshCoP::Dataset::Type aDatasetType,
Error error = kErrorNone;
Tlv::Type tlvType = (aDatasetType == MeshCoP::Dataset::kActive) ? Tlv::kActiveDataset : Tlv::kPendingDataset;
MeshCoP::Dataset dataset;
uint16_t offset;
uint16_t length;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, tlvType, offset, length));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, tlvType, offsetRange));
SuccessOrExit(error = dataset.SetFrom(*this, offset, length));
SuccessOrExit(error = dataset.SetFrom(*this, offsetRange));
SuccessOrExit(error = dataset.ValidateTlvs());
SuccessOrExit(error = dataset.WriteTimestamp(aDatasetType, aTimestamp));
@@ -5103,19 +5098,15 @@ exit:
Error Mle::RxMessage::ReadTlvRequestTlv(TlvList &aTlvList) const
{
Error error;
uint16_t offset;
uint16_t length;
Error error;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueOffset(*this, Tlv::kTlvRequest, offset, length));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(*this, Tlv::kTlvRequest, offsetRange));
if (length > aTlvList.GetMaxSize())
{
length = aTlvList.GetMaxSize();
}
offsetRange.ShrinkLength(aTlvList.GetMaxSize());
ReadBytes(offset, aTlvList.GetArrayBuffer(), length);
aTlvList.SetLength(static_cast<uint8_t>(length));
ReadBytes(offsetRange, aTlvList.GetArrayBuffer());
aTlvList.SetLength(static_cast<uint8_t>(offsetRange.GetLength()));
exit:
return error;
+22 -27
View File
@@ -1761,11 +1761,10 @@ exit:
Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
{
Error error;
uint16_t offset;
uint16_t endOffset;
uint8_t count = 0;
uint8_t storedCount = 0;
Error error;
OffsetRange offsetRange;
uint8_t count = 0;
uint8_t storedCount = 0;
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
Ip6::Address oldDua;
#endif
@@ -1775,8 +1774,7 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
OT_UNUSED_VARIABLE(storedCount);
SuccessOrExit(error =
Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kAddressRegistration, offset, endOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kAddressRegistration, offsetRange));
#if OPENTHREAD_CONFIG_TMF_PROXY_DUA_ENABLE
if (aChild.GetDomainUnicastAddress(oldDua) != kErrorNone)
@@ -1807,14 +1805,14 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
aChild.ClearIp6Addresses();
while (offset < endOffset)
while (!offsetRange.IsEmpty())
{
uint8_t controlByte;
Ip6::Address address;
// Read out the control byte (first byte in entry)
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, controlByte));
offset++;
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, controlByte));
offsetRange.AdvanceOffset(sizeof(uint8_t));
count++;
address.Clear();
@@ -1828,9 +1826,8 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
uint8_t contextId = AddressRegistrationTlv::GetContextId(controlByte);
Lowpan::Context context;
VerifyOrExit(offset + sizeof(Ip6::InterfaceIdentifier) <= endOffset, error = kErrorParse);
IgnoreError(aRxInfo.mMessage.Read(offset, address.GetIid()));
offset += sizeof(Ip6::InterfaceIdentifier);
IgnoreError(aRxInfo.mMessage.Read(offsetRange, address.GetIid()));
offsetRange.AdvanceOffset(sizeof(Ip6::InterfaceIdentifier));
if (Get<NetworkData::Leader>().GetContext(contextId, context) != kErrorNone)
{
@@ -1845,9 +1842,8 @@ Error MleRouter::ProcessAddressRegistrationTlv(RxInfo &aRxInfo, Child &aChild)
{
// Uncompressed entry contains the full IPv6 address.
VerifyOrExit(offset + sizeof(Ip6::Address) <= endOffset, error = kErrorParse);
IgnoreError(aRxInfo.mMessage.Read(offset, address));
offset += sizeof(Ip6::Address);
IgnoreError(aRxInfo.mMessage.Read(offsetRange, address));
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
}
#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
@@ -2624,8 +2620,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
MeshCoP::Tlv meshcopTlv;
MeshCoP::DiscoveryRequestTlv discoveryRequestTlv;
MeshCoP::ExtendedPanId extPanId;
uint16_t offset;
uint16_t end;
OffsetRange offsetRange;
Log(kMessageReceive, kTypeDiscoveryRequest, aRxInfo.mMessageInfo.GetPeerAddr());
@@ -2633,31 +2628,31 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
VerifyOrExit(IsRouterEligible(), error = kErrorInvalidState);
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRxInfo.mMessage, Tlv::kDiscovery, offset, end));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRxInfo.mMessage, Tlv::kDiscovery, offsetRange));
while (offset < end)
while (!offsetRange.IsEmpty())
{
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, meshcopTlv));
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, meshcopTlv));
if (meshcopTlv.IsExtended())
{
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offset));
VerifyOrExit(offset <= end, error = kErrorParse);
SuccessOrExit(error = Tlv::ParseAndSkipTlv(aRxInfo.mMessage, offsetRange));
continue;
}
VerifyOrExit(meshcopTlv.GetSize() + offset <= aRxInfo.mMessage.GetLength(), error = kErrorParse);
VerifyOrExit(offsetRange.Contains(meshcopTlv.GetSize()));
switch (meshcopTlv.GetType())
{
case MeshCoP::Tlv::kDiscoveryRequest:
SuccessOrExit(error = aRxInfo.mMessage.Read(offset, discoveryRequestTlv));
SuccessOrExit(error = aRxInfo.mMessage.Read(offsetRange, discoveryRequestTlv));
VerifyOrExit(discoveryRequestTlv.IsValid(), error = kErrorParse);
break;
case MeshCoP::Tlv::kExtendedPanId:
SuccessOrExit(error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offset, extPanId));
SuccessOrExit(
error = Tlv::Read<MeshCoP::ExtendedPanIdTlv>(aRxInfo.mMessage, offsetRange.GetOffset(), extPanId));
VerifyOrExit(Get<MeshCoP::ExtendedPanIdManager>().GetExtPanId() != extPanId, error = kErrorDrop);
break;
@@ -2666,7 +2661,7 @@ void MleRouter::HandleDiscoveryRequest(RxInfo &aRxInfo)
break;
}
offset += sizeof(meshcopTlv) + meshcopTlv.GetLength();
offsetRange.AdvanceOffset(meshcopTlv.GetSize());
}
if (discoveryRequestTlv.IsValid())
+8 -6
View File
@@ -160,17 +160,19 @@ void TxChallenge::GenerateRandom(void) { IgnoreError(Random::Crypto::Fill(*this)
//---------------------------------------------------------------------------------------------------------------------
// RxChallenge
Error RxChallenge::ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength)
Error RxChallenge::ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange)
{
Error error = kErrorNone;
Error error = kErrorNone;
OffsetRange offsetRange = aOffsetRange;
Clear();
aLength = Min<uint16_t>(aLength, kMaxSize);
VerifyOrExit(kMinSize <= aLength, error = kErrorParse);
offsetRange.ShrinkLength(kMaxSize);
SuccessOrExit(error = aMessage.Read(aOffset, mArray.GetArrayBuffer(), aLength));
mArray.SetLength(static_cast<uint8_t>(aLength));
VerifyOrExit(offsetRange.Contains(kMinSize), error = kErrorParse);
SuccessOrExit(error = aMessage.Read(offsetRange, mArray.GetArrayBuffer(), offsetRange.GetLength()));
mArray.SetLength(static_cast<uint8_t>(offsetRange.GetLength()));
exit:
return error;
+5 -5
View File
@@ -51,6 +51,7 @@
#include "common/encoding.hpp"
#include "common/equatable.hpp"
#include "common/numeric_limits.hpp"
#include "common/offset_range.hpp"
#include "common/string.hpp"
#include "mac/mac_types.hpp"
#include "meshcop/extended_panid.hpp"
@@ -526,15 +527,14 @@ public:
*
* If the given @p aLength is longer than `kMaxSize`, only `kMaxSize` bytes will be read.
*
* @param[in] aMessage The message to read the challenge from.
* @param[in] aOffset The offset in @p aMessage to read from.
* @param[in] aLength Number of bytes to read.
* @param[in] aMessage The message to read the challenge from.
* @param[in] aOffsetRange The offset range in @p aMessage to read from.
*
* @retval kErrorNone Successfully read the challenge data from @p aMessage.
* @retval kErrorParse Not enough bytes to read, or invalid @p aLength (smaller than `kMinSize`).
* @retval kErrorParse Not enough bytes to read, or invalid length (smaller than `kMinSize`).
*
*/
Error ReadFrom(const Message &aMessage, uint16_t aOffset, uint16_t aLength);
Error ReadFrom(const Message &aMessage, const OffsetRange &aOffsetRange);
/**
* Compares the `RxChallenge` with a given `TxChallenge`.
+9 -8
View File
@@ -482,8 +482,8 @@ Error MlrManager::ParseMlrResponse(Error aResult,
uint8_t &aStatus,
AddressArray &aFailedAddresses)
{
Error error;
uint16_t addressesOffset, addressesLength;
Error error;
OffsetRange offsetRange;
aStatus = ThreadStatusTlv::kMlrGeneralFailure;
@@ -492,15 +492,16 @@ Error MlrManager::ParseMlrResponse(Error aResult,
SuccessOrExit(error = Tlv::Find<ThreadStatusTlv>(*aMessage, aStatus));
if (ThreadTlv::FindTlvValueOffset(*aMessage, Ip6AddressesTlv::kIp6Addresses, addressesOffset, addressesLength) ==
kErrorNone)
if (ThreadTlv::FindTlvValueOffsetRange(*aMessage, Ip6AddressesTlv::kIp6Addresses, offsetRange) == kErrorNone)
{
VerifyOrExit(addressesLength % sizeof(Ip6::Address) == 0, error = kErrorParse);
VerifyOrExit(addressesLength / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses, error = kErrorParse);
VerifyOrExit(offsetRange.GetLength() % sizeof(Ip6::Address) == 0, error = kErrorParse);
VerifyOrExit(offsetRange.GetLength() / sizeof(Ip6::Address) <= Ip6AddressesTlv::kMaxAddresses,
error = kErrorParse);
for (uint16_t offset = 0; offset < addressesLength; offset += sizeof(Ip6::Address))
while (!offsetRange.IsEmpty())
{
IgnoreError(aMessage->Read(addressesOffset + offset, *aFailedAddresses.PushBack()));
IgnoreError(aMessage->Read(offsetRange, *aFailedAddresses.PushBack()));
offsetRange.AdvanceOffset(sizeof(Ip6::Address));
}
}
+10 -10
View File
@@ -426,19 +426,19 @@ Error Leader::DefaultRouteLookup(const PrefixTlv &aPrefix, uint16_t &aRloc16) co
return error;
}
Error Leader::SetNetworkData(uint8_t aVersion,
uint8_t aStableVersion,
Type aType,
const Message &aMessage,
uint16_t aOffset,
uint16_t aLength)
Error Leader::SetNetworkData(uint8_t aVersion,
uint8_t aStableVersion,
Type aType,
const Message &aMessage,
const OffsetRange &aOffsetRange)
{
Error error = kErrorNone;
Error error = kErrorNone;
uint16_t length = aOffsetRange.GetLength();
VerifyOrExit(aLength <= kMaxSize, error = kErrorParse);
SuccessOrExit(error = aMessage.Read(aOffset, GetBytes(), aLength));
VerifyOrExit(length <= kMaxSize, error = kErrorParse);
SuccessOrExit(error = aMessage.Read(aOffsetRange.GetOffset(), GetBytes(), length));
SetLength(static_cast<uint8_t>(aLength));
SetLength(static_cast<uint8_t>(length));
mVersion = aVersion;
mStableVersion = aStableVersion;
+6 -8
View File
@@ -168,19 +168,17 @@ public:
* @param[in] aStableVersion The Stable Version value.
* @param[in] aType The Network Data type to set, the full set or stable subset.
* @param[in] aMessage A reference to the message.
* @param[in] aOffset The offset in @p aMessage pointing to start of Network Data.
* @param[in] aLength The length of Network Data.
* @param[in] aOffsetRange The offset range in @p aMessage to read from.
*
* @retval kErrorNone Successfully set the network data.
* @retval kErrorParse Network Data in @p aMessage is not valid.
*
*/
Error SetNetworkData(uint8_t aVersion,
uint8_t aStableVersion,
Type aType,
const Message &aMessage,
uint16_t aOffset,
uint16_t aLength);
Error SetNetworkData(uint8_t aVersion,
uint8_t aStableVersion,
Type aType,
const Message &aMessage,
const OffsetRange &aOffsetRange);
/**
* Gets the Commissioning Dataset from Network Data.
+11 -9
View File
@@ -206,25 +206,25 @@ exit:
template <> void Leader::HandleTmf<kUriCommissionerGet>(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
uint16_t length;
uint16_t offset;
Coap::Message *response = nullptr;
OffsetRange offsetRange;
VerifyOrExit(Get<Mle::Mle>().IsLeader() && !mWaitingForNetDataSync);
response = Get<Tmf::Agent>().NewPriorityResponseMessage(aMessage);
VerifyOrExit(response != nullptr);
if (Tlv::FindTlvValueOffset(aMessage, MeshCoP::Tlv::kGet, offset, length) == kErrorNone)
if (Tlv::FindTlvValueOffsetRange(aMessage, MeshCoP::Tlv::kGet, offsetRange) == kErrorNone)
{
// Append the requested sub-TLV types given in Get TLV.
for (; length > 0; offset++, length--)
while (!offsetRange.IsEmpty())
{
uint8_t type;
const MeshCoP::Tlv *subTlv;
IgnoreError(aMessage.Read(offset, type));
IgnoreError(aMessage.Read(offsetRange, type));
offsetRange.AdvanceOffset(sizeof(type));
subTlv = FindCommissioningDataSubTlv(type);
@@ -1334,12 +1334,14 @@ exit:
Error Leader::SetCommissioningData(const Message &aMessage)
{
Error error = kErrorNone;
uint16_t dataLength = aMessage.GetLength() - aMessage.GetOffset();
Error error = kErrorNone;
OffsetRange offsetRange;
CommissioningDataTlv *dataTlv;
SuccessOrExit(error = UpdateCommissioningData(dataLength, dataTlv));
aMessage.ReadBytes(aMessage.GetOffset(), dataTlv->GetValue(), dataLength);
offsetRange.InitFromMessageOffsetToEnd(aMessage);
SuccessOrExit(error = UpdateCommissioningData(offsetRange.GetLength(), dataTlv));
aMessage.ReadBytes(offsetRange, dataTlv->GetValue());
exit:
return error;
+11 -13
View File
@@ -239,17 +239,17 @@ Error Server::AppendMacCounters(Message &aMessage)
Error Server::AppendRequestedTlvs(const Message &aRequest, Message &aResponse)
{
Error error;
uint16_t offset;
uint16_t endOffset;
Error error;
OffsetRange offsetRange;
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aRequest, Tlv::kTypeList, offset, endOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
for (; offset < endOffset; offset++)
while (!offsetRange.IsEmpty())
{
uint8_t tlvType;
SuccessOrExit(error = aRequest.Read(offset, tlvType));
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
offsetRange.AdvanceOffset(sizeof(tlvType));
SuccessOrExit(error = AppendDiagTlv(tlvType, aResponse));
}
@@ -536,9 +536,7 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa
Coap::Message *answer;
Error error;
AnswerInfo info;
uint16_t offset;
uint16_t length;
uint16_t endOffset;
OffsetRange offsetRange;
AnswerTlv answerTlv;
if (Tlv::Find<QueryIdTlv>(aRequest, info.mQueryId) == kErrorNone)
@@ -550,14 +548,14 @@ void Server::PrepareAndSendAnswers(const Ip6::Address &aDestination, const Messa
SuccessOrExit(error = AllocateAnswer(answer, info));
SuccessOrExit(error = Tlv::FindTlvValueOffset(aRequest, Tlv::kTypeList, offset, length));
endOffset = offset + length;
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aRequest, Tlv::kTypeList, offsetRange));
for (; offset < endOffset; offset++)
while (!offsetRange.IsEmpty())
{
uint8_t tlvType;
SuccessOrExit(error = aRequest.Read(offset, tlvType));
SuccessOrExit(error = aRequest.Read(offsetRange, tlvType));
offsetRange.AdvanceOffset(sizeof(tlvType));
switch (tlvType)
{
+15 -19
View File
@@ -379,8 +379,7 @@ exit:
bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
{
bool didPorcess = false;
uint16_t offset;
uint16_t endOffset;
OffsetRange offsetRange;
ChildIp6AddressListTlvValue tlvValue;
Ip6AddrIterator ip6AddrIterator;
@@ -388,11 +387,11 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
while (true)
{
SuccessOrExit(Tlv::FindTlvValueStartEndOffsets(aMessage, ChildIp6AddressListTlv::kType, offset, endOffset));
SuccessOrExit(Tlv::FindTlvValueOffsetRange(aMessage, ChildIp6AddressListTlv::kType, offsetRange));
didPorcess = true;
if (offset == endOffset)
if (offsetRange.IsEmpty())
{
// We reached end of the list
mState = kStateIdle;
@@ -404,13 +403,11 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
// Read the `ChildIp6AddressListTlvValue` (which contains the
// child RLOC16) and then prepare the `Ip6AddrIterator`.
VerifyOrExit(offset + sizeof(tlvValue) <= endOffset);
IgnoreError(aMessage.Read(offset, tlvValue));
offset += sizeof(tlvValue);
SuccessOrExit(aMessage.Read(offsetRange, tlvValue));
offsetRange.AdvanceOffset(sizeof(tlvValue));
ip6AddrIterator.mMessage = &aMessage;
ip6AddrIterator.mCurOffset = offset;
ip6AddrIterator.mEndOffset = endOffset;
ip6AddrIterator.mMessage = &aMessage;
ip6AddrIterator.mOffsetRange = offsetRange;
mQueryChildrenIp6Addrs.mCallback.InvokeIfSet(kErrorPending, tlvValue.GetRloc16(), &ip6AddrIterator);
@@ -418,7 +415,7 @@ bool MeshDiag::ProcessChildrenIp6AddrsAnswer(Coap::Message &aMessage, const Ip6:
// callback.
VerifyOrExit(mState == kStateQueryChildrenIp6Addrs);
aMessage.SetOffset(endOffset);
aMessage.SetOffset(offsetRange.GetEndOffset());
}
exit:
@@ -531,7 +528,7 @@ Error MeshDiag::Ip6AddrIterator::InitFrom(const Message &aMessage)
{
Error error;
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aMessage, Ip6AddressListTlv::kType, mCurOffset, mEndOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, Ip6AddressListTlv::kType, mOffsetRange));
mMessage = &aMessage;
exit:
@@ -543,10 +540,9 @@ Error MeshDiag::Ip6AddrIterator::GetNextAddress(Ip6::Address &aAddress)
Error error = kErrorNone;
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
VerifyOrExit(mCurOffset + sizeof(Ip6::Address) <= mEndOffset, error = kErrorNotFound);
IgnoreError(mMessage->Read(mCurOffset, aAddress));
mCurOffset += sizeof(Ip6::Address);
VerifyOrExit(mMessage->Read(mOffsetRange, aAddress) == kErrorNone, error = kErrorNotFound);
mOffsetRange.AdvanceOffset(sizeof(Ip6::Address));
exit:
return error;
@@ -559,7 +555,8 @@ Error MeshDiag::ChildIterator::InitFrom(const Message &aMessage, uint16_t aParen
{
Error error;
SuccessOrExit(error = Tlv::FindTlvValueStartEndOffsets(aMessage, ChildTableTlv::kType, mCurOffset, mEndOffset));
SuccessOrExit(error = Tlv::FindTlvValueOffsetRange(aMessage, ChildTableTlv::kType, mOffsetRange));
mMessage = &aMessage;
mParentRloc16 = aParentRloc16;
@@ -573,10 +570,9 @@ Error MeshDiag::ChildIterator::GetNextChildInfo(ChildInfo &aChildInfo)
ChildTableEntry entry;
VerifyOrExit(mMessage != nullptr, error = kErrorNotFound);
VerifyOrExit(mCurOffset + sizeof(ChildTableEntry) <= mEndOffset, error = kErrorNotFound);
IgnoreError(mMessage->Read(mCurOffset, entry));
mCurOffset += sizeof(ChildTableEntry);
VerifyOrExit(mMessage->Read(mOffsetRange, entry) == kErrorNone, error = kErrorNotFound);
mOffsetRange.AdvanceOffset(sizeof(ChildTableEntry));
aChildInfo.mRloc16 = mParentRloc16 + entry.GetChildId();
entry.GetMode().Get(aChildInfo.mMode);
+2 -4
View File
@@ -105,8 +105,7 @@ public:
Error InitFrom(const Message &aMessage);
const Message *mMessage;
uint16_t mCurOffset;
uint16_t mEndOffset;
OffsetRange mOffsetRange;
};
/**
@@ -153,8 +152,7 @@ public:
Error InitFrom(const Message &aMessage, uint16_t aParentRloc16);
const Message *mMessage;
uint16_t mCurOffset;
uint16_t mEndOffset;
OffsetRange mOffsetRange;
uint16_t mParentRloc16;
};
+1
View File
@@ -207,6 +207,7 @@ ot_unit_test(ndproxy_table)
ot_unit_test(netif)
ot_unit_test(network_data)
ot_unit_test(network_name)
ot_unit_test(offset_range)
ot_unit_test(pool)
ot_unit_test(power_calibration)
ot_unit_test(priority_queue)
+4 -1
View File
@@ -103,6 +103,7 @@ void TestIphcVector::GetUncompressedStream(Message &aMessage)
static void Init(void)
{
otMeshLocalPrefix meshLocalPrefix = {{0xfd, 0x00, 0xca, 0xfe, 0xfa, 0xce, 0x12, 0x34}};
OffsetRange offsetRange;
sInstance->Get<Mle::MleRouter>().SetMeshLocalPrefix(static_cast<Ip6::NetworkPrefix &>(meshLocalPrefix));
@@ -127,8 +128,10 @@ static void Init(void)
SuccessOrQuit(message->AppendBytes(mockNetworkData, sizeof(mockNetworkData)));
offsetRange.Init(2, 0x20);
IgnoreError(
sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, NetworkData::kStableSubset, *message, 2, 0x20));
sInstance->Get<NetworkData::Leader>().SetNetworkData(0, 0, NetworkData::kStableSubset, *message, offsetRange));
}
/**
+187
View File
@@ -0,0 +1,187 @@
/*
* 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 "common/message.hpp"
#include "common/offset_range.hpp"
#include "instance/instance.hpp"
#include "test_platform.h"
#include "test_util.hpp"
namespace ot {
void TestOffsetRange(void)
{
Instance *instance;
Message *message;
OffsetRange offsetRange;
instance = testInitInstance();
VerifyOrQuit(instance != nullptr);
// Empty `OffsetRange`
offsetRange.Clear();
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
VerifyOrQuit(offsetRange.IsEmpty());
offsetRange.ShrinkLength(10);
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
VerifyOrQuit(offsetRange.IsEmpty());
offsetRange.AdvanceOffset(20);
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 0);
VerifyOrQuit(offsetRange.IsEmpty());
// Empty `OffsetRange` with non-zero starting offset
offsetRange.Init(100, 0);
VerifyOrQuit(offsetRange.GetOffset() == 100);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
VerifyOrQuit(offsetRange.IsEmpty());
offsetRange.ShrinkLength(10);
VerifyOrQuit(offsetRange.GetOffset() == 100);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
VerifyOrQuit(offsetRange.IsEmpty());
offsetRange.AdvanceOffset(20);
VerifyOrQuit(offsetRange.GetOffset() == 100);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 100);
VerifyOrQuit(offsetRange.IsEmpty());
// Non-empty `OffsetRange`
offsetRange.Init(200, 10);
VerifyOrQuit(offsetRange.GetOffset() == 200);
VerifyOrQuit(offsetRange.GetLength() == 10);
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
VerifyOrQuit(!offsetRange.IsEmpty());
VerifyOrQuit(offsetRange.Contains(10));
VerifyOrQuit(!offsetRange.Contains(11));
offsetRange.ShrinkLength(10);
VerifyOrQuit(offsetRange.GetOffset() == 200);
VerifyOrQuit(offsetRange.GetLength() == 10);
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
offsetRange.ShrinkLength(20);
VerifyOrQuit(offsetRange.GetOffset() == 200);
VerifyOrQuit(offsetRange.GetLength() == 10);
VerifyOrQuit(offsetRange.GetEndOffset() == 210);
offsetRange.ShrinkLength(5);
VerifyOrQuit(offsetRange.GetOffset() == 200);
VerifyOrQuit(offsetRange.GetLength() == 5);
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
VerifyOrQuit(!offsetRange.Contains(10));
VerifyOrQuit(!offsetRange.Contains(6));
VerifyOrQuit(offsetRange.Contains(5));
offsetRange.AdvanceOffset(4);
VerifyOrQuit(offsetRange.GetOffset() == 204);
VerifyOrQuit(offsetRange.GetLength() == 1);
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
VerifyOrQuit(!offsetRange.IsEmpty());
VerifyOrQuit(offsetRange.Contains(1));
VerifyOrQuit(!offsetRange.Contains(2));
offsetRange.AdvanceOffset(1);
VerifyOrQuit(offsetRange.GetOffset() == 205);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 205);
VerifyOrQuit(offsetRange.IsEmpty());
// `InitFromRange()`
offsetRange.InitFromRange(300, 400);
VerifyOrQuit(offsetRange.GetOffset() == 300);
VerifyOrQuit(offsetRange.GetLength() == 100);
VerifyOrQuit(offsetRange.GetEndOffset() == 400);
VerifyOrQuit(!offsetRange.IsEmpty());
VerifyOrQuit(offsetRange.Contains(100));
VerifyOrQuit(!offsetRange.Contains(101));
offsetRange.AdvanceOffset(101);
VerifyOrQuit(offsetRange.GetOffset() == 400);
VerifyOrQuit(offsetRange.GetLength() == 0);
VerifyOrQuit(offsetRange.GetEndOffset() == 400);
VerifyOrQuit(offsetRange.IsEmpty());
// Init from a `Message` from offset or full length
message = instance->Get<MessagePool>().Allocate(Message::kTypeOther);
VerifyOrQuit(message != nullptr);
SuccessOrQuit(message->SetLength(120));
VerifyOrQuit(message->GetOffset() == 0);
offsetRange.InitFromMessageOffsetToEnd(*message);
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 120);
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
offsetRange.InitFromMessageFullLength(*message);
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 120);
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
message->SetOffset(40);
VerifyOrQuit(message->GetOffset() == 40);
offsetRange.InitFromMessageOffsetToEnd(*message);
VerifyOrQuit(offsetRange.GetOffset() == 40);
VerifyOrQuit(offsetRange.GetLength() == 80);
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
offsetRange.InitFromMessageFullLength(*message);
VerifyOrQuit(offsetRange.GetOffset() == 0);
VerifyOrQuit(offsetRange.GetLength() == 120);
VerifyOrQuit(offsetRange.GetEndOffset() == 120);
message->Free();
testFreeInstance(instance);
}
} // namespace ot
int main(void)
{
ot::TestOffsetRange();
printf("All tests passed\n");
return 0;
}
+23 -23
View File
@@ -45,7 +45,7 @@ void TestTlv(void)
Tlv tlv;
ExtendedTlv extTlv;
uint16_t offset;
uint16_t valueOffset;
OffsetRange offsetRange;
uint16_t length;
uint8_t buffer[4];
@@ -57,7 +57,7 @@ void TestTlv(void)
VerifyOrQuit(message->GetOffset() == 0);
VerifyOrQuit(message->GetLength() == 0);
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length) == kErrorNotFound);
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 1, offsetRange) == kErrorNotFound);
VerifyOrQuit(Tlv::ReadTlvValue(*message, 0, buffer, 1) == kErrorParse);
// Add an empty TLV with type 1 and check that we can find it
@@ -68,9 +68,9 @@ void TestTlv(void)
tlv.SetLength(0);
SuccessOrQuit(message->Append(tlv));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 1, valueOffset, length));
VerifyOrQuit(valueOffset == sizeof(Tlv));
VerifyOrQuit(length == 0);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 1, offsetRange));
VerifyOrQuit(offsetRange.GetOffset() == sizeof(Tlv));
VerifyOrQuit(offsetRange.GetLength() == 0);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
@@ -82,9 +82,9 @@ void TestTlv(void)
extTlv.SetLength(0);
SuccessOrQuit(message->Append(extTlv));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 2, valueOffset, length));
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
VerifyOrQuit(length == 0);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 2, offsetRange));
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
VerifyOrQuit(offsetRange.GetLength() == 0);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0));
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
@@ -97,9 +97,9 @@ void TestTlv(void)
SuccessOrQuit(message->Append(tlv));
SuccessOrQuit(message->Append<uint8_t>(0xff));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 3, valueOffset, length));
VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
VerifyOrQuit(length == 1);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 3, offsetRange));
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(Tlv));
VerifyOrQuit(offsetRange.GetLength() == 1);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
VerifyOrQuit(buffer[0] == 0x0ff);
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
@@ -114,9 +114,9 @@ void TestTlv(void)
SuccessOrQuit(message->Append<uint8_t>(0x12));
SuccessOrQuit(message->Append<uint8_t>(0x34));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 4, valueOffset, length));
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
VerifyOrQuit(length == 2);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 4, offsetRange));
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
VerifyOrQuit(offsetRange.GetLength() == 2);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
VerifyOrQuit(buffer[0] == 0x12);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
@@ -132,15 +132,15 @@ void TestTlv(void)
tlv.SetLength(1);
SuccessOrQuit(message->Append(tlv));
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length) != kErrorNone);
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 5, offsetRange) != kErrorNone);
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 0) == kErrorParse);
// Add the missing value.
SuccessOrQuit(message->Append<uint8_t>(0xaa));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 5, valueOffset, length));
VerifyOrQuit(valueOffset == offset + sizeof(Tlv));
VerifyOrQuit(length == 1);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 5, offsetRange));
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(Tlv));
VerifyOrQuit(offsetRange.GetLength() == 1);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1));
VerifyOrQuit(buffer[0] == 0xaa);
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2) == kErrorParse);
@@ -154,14 +154,14 @@ void TestTlv(void)
SuccessOrQuit(message->Append(extTlv));
SuccessOrQuit(message->Append<uint8_t>(0xbb));
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 6, offsetRange) != kErrorNone);
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
SuccessOrQuit(message->Append<uint8_t>(0xcc));
SuccessOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 6, valueOffset, length) != kErrorNone);
VerifyOrQuit(valueOffset == offset + sizeof(ExtendedTlv));
VerifyOrQuit(length == 2);
SuccessOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 6, offsetRange) != kErrorNone);
VerifyOrQuit(offsetRange.GetOffset() == offset + sizeof(ExtendedTlv));
VerifyOrQuit(offsetRange.GetLength() == 2);
SuccessOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 2));
VerifyOrQuit(buffer[0] == 0xbb);
VerifyOrQuit(buffer[1] == 0xcc);
@@ -176,7 +176,7 @@ void TestTlv(void)
SuccessOrQuit(message->Append(extTlv));
SuccessOrQuit(message->Append<uint8_t>(0x11));
VerifyOrQuit(Tlv::FindTlvValueOffset(*message, /* aType */ 7, valueOffset, length) != kErrorNone);
VerifyOrQuit(Tlv::FindTlvValueOffsetRange(*message, /* aType */ 7, offsetRange) != kErrorNone);
VerifyOrQuit(Tlv::ReadTlvValue(*message, offset, buffer, 1) == kErrorParse);
message->Free();