diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp index 75485a505..d2db236b0 100644 --- a/src/core/net/ip6.cpp +++ b/src/core/net/ip6.cpp @@ -646,8 +646,6 @@ otError Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto) FragmentHeader::MakeDivisibleByEight(kMinimalMtu - aMessage.GetOffset() - sizeof(fragmentHeader)); uint16_t payloadLeft = aMessage.GetLength() - aMessage.GetOffset(); - VerifyOrExit(aMessage.GetLength() <= kMaxAssembledDatagramLength, error = OT_ERROR_NO_BUFS); - VerifyOrExit(aMessage.Read(0, sizeof(header), &header) == sizeof(header), error = OT_ERROR_PARSE); header.SetNextHeader(kProtoFragment); @@ -699,6 +697,7 @@ otError Ip6::FragmentDatagram(Message &aMessage, uint8_t aIpProto) otLogInfoIp6("Fragment %d with %d bytes sent", fragmentCnt, payloadFragment); } + aMessage.Free(); exit: @@ -757,6 +756,15 @@ otError Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMess offset = FragmentHeader::FragmentOffsetToBytes(fragmentHeader.GetOffset()); payloadFragment = aMessage.GetLength() - aMessage.GetOffset() - sizeof(fragmentHeader); + otLogInfoIp6("Fragment with id %d received > %d bytes, offset %d", fragmentHeader.GetIdentification(), + payloadFragment, offset); + + if (offset + payloadFragment + aMessage.GetOffset() > kMaxAssembledDatagramLength) + { + otLogWarnIp6("Packet too large for fragment buffer"); + ExitNow(error = OT_ERROR_NO_BUFS); + } + if (message == NULL) { VerifyOrExit((message = NewMessage(0)) != NULL, error = OT_ERROR_NO_BUFS); @@ -780,15 +788,6 @@ otError Ip6::HandleFragment(Message &aMessage, Netif *aNetif, MessageInfo &aMess otLogDebgIp6("start reassembly."); } - otLogInfoIp6("Fragment with id %d received > %d bytes, offset %d", message->GetDatagramTag(), payloadFragment, - offset); - - if (offset + payloadFragment + aMessage.GetOffset() > kMaxAssembledDatagramLength) - { - otLogWarnIp6("Package too large for fragment buffer"); - ExitNow(error = OT_ERROR_NO_BUFS); - } - // increase message buffer if necessary if (message->GetLength() < offset + payloadFragment + aMessage.GetOffset()) { @@ -833,6 +832,7 @@ exit: } otLogWarnIp6("Reassembly failed: %s", otThreadErrorToString(error)); } + if (isFragmented) { // drop all fragments, the payload is stored in the fragment buffer @@ -970,6 +970,9 @@ otError Ip6::HandleExtensionHeaders(Message & aMessage, break; case kProtoFragment: + // Always forward IPv6 fragments to the Host. + IgnoreError(ProcessReceiveCallback(aMessage, aMessageInfo, aNextHeader, aFromNcpHost)); + SuccessOrExit(error = HandleFragment(aMessage, aNetif, aMessageInfo, aFromNcpHost)); break; diff --git a/tests/scripts/thread-cert/test_ipv6_fragmentation.py b/tests/scripts/thread-cert/test_ipv6_fragmentation.py index f669e528d..00506d205 100755 --- a/tests/scripts/thread-cert/test_ipv6_fragmentation.py +++ b/tests/scripts/thread-cert/test_ipv6_fragmentation.py @@ -77,9 +77,6 @@ class TestIPv6Fragmentation(thread_cert.TestCase): self.simulator.go(5) self.nodes[LEADER].udp_check_rx(1831) - self.nodes[ROUTER].udp_send(1953, mleid_leader, common.UDP_TEST_PORT, - False) - self.nodes[ROUTER].udp_stop() self.nodes[LEADER].udp_stop()