diff --git a/src/core/thread/lowpan.cpp b/src/core/thread/lowpan.cpp index f3bc718b6..f14ae9fca 100644 --- a/src/core/thread/lowpan.cpp +++ b/src/core/thread/lowpan.cpp @@ -1175,5 +1175,26 @@ exit: return error; } +otError FragmentHeader::Init(const uint8_t *aFrame, uint8_t aFrameLength) +{ + otError error = OT_ERROR_PARSE; + + VerifyOrExit(aFrameLength >= sizeof(mDispatchSize) + sizeof(mTag)); + memcpy(&mDispatchSize, aFrame, sizeof(mDispatchSize) + sizeof(mTag)); + aFrame += sizeof(mDispatchSize) + sizeof(mTag); + aFrameLength -= sizeof(mDispatchSize) + sizeof(mTag); + + if (IsOffsetPresent()) + { + VerifyOrExit(aFrameLength >= sizeof(mOffset)); + mOffset = *aFrame++; + } + + error = OT_ERROR_NONE; + +exit: + return error; +} + } // namespace Lowpan } // namespace ot diff --git a/src/core/thread/lowpan.hpp b/src/core/thread/lowpan.hpp index 197dc2f40..9f359587a 100644 --- a/src/core/thread/lowpan.hpp +++ b/src/core/thread/lowpan.hpp @@ -397,6 +397,18 @@ public: */ void Init(void) { mDispatchSize = HostSwap16(kDispatch); } + /** + * This method initializes the fragment header from a frame @p aFrame. + * + * @param[in] aFrame The pointer to the frame. + * @param[in] aFrameLength The length of the frame. + * + * @retval OT_ERROR_NONE Fragment Header initialized successfully. + * @retval OT_ERROR_PARSE Fragment header could not be initialized from @p aFrame (e.g., frame not long enough). + * + */ + otError Init(const uint8_t *aFrame, uint8_t aFrameLength); + /** * This method indicates whether or not the header is a Fragment Header. * @@ -412,9 +424,15 @@ public: * @returns The Fragment Header length in bytes. * */ - uint8_t GetHeaderLength(void) { - return (HostSwap16(mDispatchSize) & kOffset) ? sizeof(*this) : sizeof(*this) - sizeof(mOffset); - } + uint8_t GetHeaderLength(void) const { return IsOffsetPresent() ? sizeof(*this) : sizeof(*this) - sizeof(mOffset); } + + /** + * This method indicates whether or not the Offset field is present. + * + * @returns TRUE if the Offset field is present, FALSE otherwise. + * + */ + bool IsOffsetPresent(void) const { return (HostSwap16(mDispatchSize) & kOffset) != 0; } /** * This method returns the Datagram Size value. @@ -422,7 +440,7 @@ public: * @returns The Datagram Size value. * */ - uint16_t GetDatagramSize(void) { return HostSwap16(mDispatchSize) & kSizeMask; } + uint16_t GetDatagramSize(void) const { return HostSwap16(mDispatchSize) & kSizeMask; } /** * This method sets the Datagram Size value. @@ -440,7 +458,7 @@ public: * @returns The Datagram Tag value. * */ - uint16_t GetDatagramTag(void) { return HostSwap16(mTag); } + uint16_t GetDatagramTag(void) const { return HostSwap16(mTag); } /** * This method sets the Datagram Tag value. @@ -456,7 +474,7 @@ public: * @returns The Datagram Offset value. * */ - uint16_t GetDatagramOffset(void) { return (HostSwap16(mDispatchSize) & kOffset) ? static_cast(mOffset) * 8 : 0; } + uint16_t GetDatagramOffset(void) const { return IsOffsetPresent() ? static_cast(mOffset) * 8 : 0; } /** * This method sets the Datagram Offset value. diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index cc777015c..ff22e3cd0 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -1998,34 +1998,34 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength, { ThreadNetif &netif = GetNetif(); otError error = OT_ERROR_NONE; - Lowpan::FragmentHeader *fragmentHeader = reinterpret_cast(aFrame); - uint16_t datagramLength = fragmentHeader->GetDatagramSize(); - uint16_t datagramTag = fragmentHeader->GetDatagramTag(); + Lowpan::FragmentHeader fragmentHeader; Message *message = NULL; int headerLength; - if (fragmentHeader->GetDatagramOffset() == 0) - { - aFrame += fragmentHeader->GetHeaderLength(); - aFrameLength -= fragmentHeader->GetHeaderLength(); + // Check the fragment header + VerifyOrExit(fragmentHeader.Init(aFrame, aFrameLength) == OT_ERROR_NONE, error = OT_ERROR_DROP); + aFrame += fragmentHeader.GetHeaderLength(); + aFrameLength -= fragmentHeader.GetHeaderLength(); + if (fragmentHeader.GetDatagramOffset() == 0) + { VerifyOrExit((message = GetInstance().mMessagePool.New(Message::kTypeIp6, 0)) != NULL, error = OT_ERROR_NO_BUFS); message->SetLinkSecurityEnabled(aMessageInfo.mLinkSecurity); message->SetPanId(aMessageInfo.mPanId); message->AddRss(aMessageInfo.mRss); headerLength = netif.GetLowpan().Decompress(*message, aMacSource, aMacDest, aFrame, aFrameLength, - datagramLength); + fragmentHeader.GetDatagramSize()); VerifyOrExit(headerLength > 0, error = OT_ERROR_PARSE); aFrame += headerLength; aFrameLength -= static_cast(headerLength); - VerifyOrExit(datagramLength >= message->GetOffset() + aFrameLength, error = OT_ERROR_PARSE); + VerifyOrExit(fragmentHeader.GetDatagramSize() >= message->GetOffset() + aFrameLength, error = OT_ERROR_PARSE); - SuccessOrExit(error = message->SetLength(datagramLength)); + SuccessOrExit(error = message->SetLength(fragmentHeader.GetDatagramSize())); - message->SetDatagramTag(datagramTag); + message->SetDatagramTag(fragmentHeader.GetDatagramTag()); message->SetTimeout(kReassemblyTimeout); // copy Fragment @@ -2053,16 +2053,13 @@ void MeshForwarder::HandleFragment(uint8_t *aFrame, uint8_t aFrameLength, } else { - aFrame += fragmentHeader->GetHeaderLength(); - aFrameLength -= fragmentHeader->GetHeaderLength(); - for (message = mReassemblyList.GetHead(); message; message = message->GetNext()) { // Security Check: only consider reassembly buffers that had the same Security Enabled setting. - if (message->GetLength() == datagramLength && - message->GetDatagramTag() == datagramTag && - message->GetOffset() == fragmentHeader->GetDatagramOffset() && - message->GetOffset() + aFrameLength <= datagramLength && + if (message->GetLength() == fragmentHeader.GetDatagramSize() && + message->GetDatagramTag() == fragmentHeader.GetDatagramTag() && + message->GetOffset() == fragmentHeader.GetDatagramOffset() && + message->GetOffset() + aFrameLength <= fragmentHeader.GetDatagramSize() && message->IsLinkSecurityEnabled() == aMessageInfo.mLinkSecurity) { break; @@ -2116,9 +2113,9 @@ exit: aFrameLength, aMacSource.ToString(srcStringBuffer, sizeof(srcStringBuffer)), aMacDest.ToString(dstStringBuffer, sizeof(dstStringBuffer)), - datagramTag, - fragmentHeader->GetDatagramOffset(), - datagramLength, + fragmentHeader.GetDatagramTag(), + fragmentHeader.GetDatagramOffset(), + fragmentHeader.GetDatagramSize(), aMessageInfo.mLinkSecurity ? "yes" : "no" );