diff --git a/src/core/common/message.cpp b/src/core/common/message.cpp index 2c18c4f7a..ffa595b31 100644 --- a/src/core/common/message.cpp +++ b/src/core/common/message.cpp @@ -663,6 +663,17 @@ exit: return error; } +Error Message::ReadAtAndAdvanceOffset(void *aBuf, uint16_t aLength) +{ + Error error; + + SuccessOrExit(error = Read(GetOffset(), aBuf, aLength)); + MoveOffset(aLength); + +exit: + return error; +} + bool Message::CompareBytes(uint16_t aOffset, const void *aBuf, uint16_t aLength, ByteMatcher aMatcher) const { uint16_t bytesToCompare = aLength; diff --git a/src/core/common/message.hpp b/src/core/common/message.hpp index e01ddfefd..289a60359 100644 --- a/src/core/common/message.hpp +++ b/src/core/common/message.hpp @@ -925,6 +925,34 @@ public: return Read(aOffsetRange, &aObject, sizeof(ObjectType)); } + /** + * Reads a given number of bytes from the message at the current message offset and advances the message offset. + * + * @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. Message offset is advanced. + * @retval kErrorParse Not enough bytes remaining to read the requested @p aLength. Message offset is unchanged. + */ + Error ReadAtAndAdvanceOffset(void *aBuf, uint16_t aLength); + + /** + * Reads an object from the message at the current message offset and advances the message offset. + * + * @tparam ObjectType The object type to read from the message. + * + * @param[out] aObject A reference to the object to read into. + * + * @retval kErrorNone Object @p aObject was successfully read from message. Message offset is advanced. + * @retval kErrorParse Not enough bytes remaining in message to read the entire object. Offset is unchanged. + */ + template Error ReadAtAndAdvanceOffset(ObjectType &aObject) + { + static_assert(!TypeTraits::IsPointer::kValue, "ObjectType must not be a pointer"); + + return ReadAtAndAdvanceOffset(&aObject, sizeof(ObjectType)); + } + /** * Compares the bytes in the message at a given offset with a given byte array. * diff --git a/src/core/net/dhcp6_client.cpp b/src/core/net/dhcp6_client.cpp index 46177b9bb..294e860a4 100644 --- a/src/core/net/dhcp6_client.cpp +++ b/src/core/net/dhcp6_client.cpp @@ -358,8 +358,7 @@ void Client::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag Header header; - SuccessOrExit(aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(aMessage.ReadAtAndAdvanceOffset(header)); if ((header.GetMsgType() == kMsgTypeReply) && (header.GetTransactionId() == mTransactionId)) { diff --git a/src/core/net/dhcp6_server.cpp b/src/core/net/dhcp6_server.cpp index 17211ad0e..2d449c940 100644 --- a/src/core/net/dhcp6_server.cpp +++ b/src/core/net/dhcp6_server.cpp @@ -177,8 +177,7 @@ void Server::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessag { Header header; - SuccessOrExit(aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(aMessage.ReadAtAndAdvanceOffset(header)); VerifyOrExit((header.GetMsgType() == kMsgTypeSolicit)); diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 4f42a1cda..e9d0f8b19 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -800,15 +800,13 @@ Error Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto) Error Ip6::HandleFragment(Message &aMessage) { - Error error = kErrorNone; + Error error; FragmentHeader fragmentHeader; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), fragmentHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(fragmentHeader)); VerifyOrExit(fragmentHeader.GetOffset() == 0 && !fragmentHeader.IsMoreFlagSet(), error = kErrorDrop); - aMessage.MoveOffset(sizeof(fragmentHeader)); - exit: return error; } diff --git a/src/core/net/udp6.cpp b/src/core/net/udp6.cpp index 83c5d5fca..cfa3e4f09 100644 --- a/src/core/net/udp6.cpp +++ b/src/core/net/udp6.cpp @@ -450,13 +450,12 @@ Error Udp::HandleMessage(Message &aMessage, MessageInfo &aMessageInfo) Error error = kErrorNone; Header udpHeader; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader)); - #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION SuccessOrExit(error = Checksum::VerifyMessageChecksum(aMessage, aMessageInfo, kProtoUdp)); #endif - aMessage.MoveOffset(sizeof(udpHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(udpHeader)); + aMessageInfo.mPeerPort = udpHeader.GetSourcePort(); aMessageInfo.mSockPort = udpHeader.GetDestinationPort(); diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index e289ee8b5..284b2c31c 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -261,7 +261,7 @@ Error Lowpan::Compress(Message &aMessage, uint8_t headerDepth = 0; uint8_t headerMaxDepth = aHeaderDepth; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), ip6Header)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(ip6Header)); FindContextToCompressAddress(ip6Header.GetSource(), srcContext); FindContextToCompressAddress(ip6Header.GetDestination(), dstContext); @@ -395,8 +395,6 @@ Error Lowpan::Compress(Message &aMessage, headerDepth++; - aMessage.MoveOffset(sizeof(ip6Header)); - nextHeader = static_cast(ip6Header.GetNextHeader()); while (headerDepth < headerMaxDepth) @@ -450,8 +448,7 @@ Error Lowpan::CompressExtensionHeader(Message &aMessage, FrameBuilder &aFrameBui uint16_t padLength = 0; uint8_t tmpByte; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), extHeader)); - aMessage.MoveOffset(sizeof(extHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(extHeader)); tmpByte = kExtHdrDispatch | kExtHdrEidHbh; @@ -526,7 +523,7 @@ Error Lowpan::CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder) uint16_t source; uint16_t destination; - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), udpHeader)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(udpHeader)); source = udpHeader.GetSourcePort(); destination = udpHeader.GetDestinationPort(); @@ -556,8 +553,6 @@ Error Lowpan::CompressUdp(Message &aMessage, FrameBuilder &aFrameBuilder) SuccessOrExit(error = aFrameBuilder.AppendBigEndianUint16(udpHeader.GetChecksum())); - aMessage.MoveOffset(sizeof(udpHeader)); - exit: if (error != kErrorNone) { diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp index ac6c6071d..4175d9411 100644 --- a/src/core/thread/mle.cpp +++ b/src/core/thread/mle.cpp @@ -1564,13 +1564,11 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn VerifyOrExit(aMessageInfo.GetHopLimit() == kMleHopLimit, error = kErrorParse); - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), securitySuite)); - aMessage.MoveOffset(sizeof(securitySuite)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(securitySuite)); if (securitySuite == kNoSecurity) { - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), command)); - aMessage.MoveOffset(sizeof(command)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(command)); switch (command) { @@ -1593,8 +1591,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn VerifyOrExit(!IsDisabled(), error = kErrorInvalidState); VerifyOrExit(securitySuite == k154Security, error = kErrorParse); - SuccessOrExit(error = aMessage.Read(aMessage.GetOffset(), header)); - aMessage.MoveOffset(sizeof(header)); + SuccessOrExit(error = aMessage.ReadAtAndAdvanceOffset(header)); VerifyOrExit(header.IsSecurityControlValid(), error = kErrorParse); @@ -1604,8 +1601,7 @@ void Mle::HandleUdpReceive(Message &aMessage, const Ip6::MessageInfo &aMessageIn SuccessOrExit( error = ProcessMessageSecurity(Crypto::AesCcm::kDecrypt, aMessage, aMessageInfo, aMessage.GetOffset(), header)); - IgnoreError(aMessage.Read(aMessage.GetOffset(), command)); - aMessage.MoveOffset(sizeof(command)); + IgnoreError(aMessage.ReadAtAndAdvanceOffset(command)); extAddr.SetFromIid(aMessageInfo.GetPeerAddr().GetIid()); neighbor = (command == kCommandChildIdResponse) ? mNeighborTable.FindParent(extAddr)