mirror of
https://github.com/espressif/openthread.git
synced 2026-11-01 20:16:39 +00:00
[mesh-forwarder] reject oversized mesh frames (#13758)
This commit updates MessageFramer::PrepareMeshFrame() to return an Error and propagate the result of PayloadBuilder::AppendBytesFromMessage() instead of asserting with SuccessOrAssert(). When MeshForwarder::PrepareFrame() receives an error from PrepareMeshFrame(), it advances mMessageNextOffset to the end of the message and aborts frame preparation so the oversized mesh message is dropped cleanly without retrying.
This commit is contained in:
@@ -929,7 +929,9 @@ Mac::TxFrame *MeshForwarder::PrepareFrame(Mac::TxFrames &aTxFrames)
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
case Message::kType6lowpan:
|
||||
mMessageNextOffset = Get<MessageFramer>().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs);
|
||||
mMessageNextOffset = mSendMessage->GetLength();
|
||||
VerifyOrExit(Get<MessageFramer>().PrepareMeshFrame(*frame, *mSendMessage, mMacAddrs) == kErrorNone,
|
||||
frame = nullptr);
|
||||
break;
|
||||
|
||||
case Message::kTypeSupervision:
|
||||
|
||||
@@ -356,8 +356,9 @@ start:
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
|
||||
uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
|
||||
Error MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs)
|
||||
{
|
||||
Error error;
|
||||
Mac::TxFrame::BuildInfo buildInfo;
|
||||
Mac::TxFrame::PayloadBuilder frameBuilder;
|
||||
|
||||
@@ -369,10 +370,11 @@ uint16_t MessageFramer::PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage
|
||||
|
||||
PrepareMacHeaders(aFrame, buildInfo, frameBuilder, &aMessage);
|
||||
|
||||
SuccessOrAssert(frameBuilder.AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
|
||||
SuccessOrExit(error = frameBuilder.AppendBytesFromMessage(aMessage, 0, aMessage.GetLength()));
|
||||
aFrame.FinishPayload(frameBuilder);
|
||||
|
||||
return aMessage.GetLength();
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
@@ -115,9 +115,11 @@ public:
|
||||
* @param[in] aMessage The 6LoWPAN Mesh message.
|
||||
* @param[in] aMacAddrs The MAC source and destination addresses.
|
||||
*
|
||||
* @returns The next offset into @p aMessage after the prepared frame.
|
||||
* @retval kErrorNone Successfully prepared the frame.
|
||||
* @retval kErrorNoBufs The message does not fit in the frame.
|
||||
* @retval kErrorParse Failed to read payload from @p aMessage.
|
||||
*/
|
||||
uint16_t PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs);
|
||||
Error PrepareMeshFrame(Mac::TxFrame &aFrame, Message &aMessage, const Mac::Addresses &aMacAddrs);
|
||||
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
|
||||
@@ -2161,6 +2161,51 @@ void TestLowpanDecompressRecursion(void)
|
||||
printf("PASS\n\n");
|
||||
}
|
||||
|
||||
#if OPENTHREAD_FTD
|
||||
void TestPrepareMeshFrame(void)
|
||||
{
|
||||
Instance *instance = testInitInstance();
|
||||
Message *message;
|
||||
Mac::Addresses macAddrs;
|
||||
Mac::TxFrame txFrame{};
|
||||
uint8_t psdu[OT_RADIO_FRAME_MAX_SIZE];
|
||||
uint16_t maxPayload;
|
||||
|
||||
printf("\n=== Test name: Prepare Mesh Frame ===\n\n");
|
||||
|
||||
VerifyOrQuit(instance != nullptr);
|
||||
|
||||
txFrame.mPsdu = psdu;
|
||||
#if OPENTHREAD_CONFIG_MULTI_RADIO
|
||||
txFrame.SetRadioType(Radio::kTypeIeee802154);
|
||||
#endif
|
||||
|
||||
macAddrs.mSource.SetShort(0x1000);
|
||||
macAddrs.mDestination.SetShort(0x2000);
|
||||
|
||||
message = instance->Get<MessagePool>().Allocate(Message::kType6lowpan);
|
||||
VerifyOrQuit(message != nullptr);
|
||||
|
||||
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
|
||||
maxPayload = txFrame.GetMtu() - txFrame.GetLength();
|
||||
|
||||
SuccessOrQuit(message->SetLength(maxPayload));
|
||||
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
|
||||
VerifyOrQuit(txFrame.GetLength() == txFrame.GetMtu());
|
||||
|
||||
SuccessOrQuit(message->SetLength(maxPayload + 1));
|
||||
VerifyOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs) == kErrorNoBufs);
|
||||
|
||||
SuccessOrQuit(message->SetLength(maxPayload - 1));
|
||||
SuccessOrQuit(instance->Get<MessageFramer>().PrepareMeshFrame(txFrame, *message, macAddrs));
|
||||
VerifyOrQuit(txFrame.GetLength() == txFrame.GetMtu() - 1);
|
||||
|
||||
message->Free();
|
||||
testFreeInstance(instance);
|
||||
printf("PASS\n\n");
|
||||
}
|
||||
#endif // OPENTHREAD_FTD
|
||||
|
||||
} // namespace ot
|
||||
|
||||
int main(void)
|
||||
@@ -2169,6 +2214,9 @@ int main(void)
|
||||
ot::TestLowpanMeshHeader();
|
||||
ot::TestLowpanFragmentHeader();
|
||||
ot::TestLowpanDecompressRecursion();
|
||||
#if OPENTHREAD_FTD
|
||||
ot::TestPrepareMeshFrame();
|
||||
#endif
|
||||
|
||||
printf("All tests passed\n");
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user