defrag: fix check for complete packet

The list of fragments may still contain overlaps, so adding up the
fragment lengths is flawed. Instead track the largest size of
contiguous data that can be re-assembled.

Bug: #6675
pull/10934/head
Jason Ish 2 years ago committed by Victor Julien
parent f1709ea551
commit d226d0a3fc

@ -256,7 +256,8 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
goto done;
}
else {
len += frag->data_len;
/* Update the packet length to the largest known data offset. */
len = MAX(len, frag->offset + frag->data_len);
}
}
@ -414,7 +415,7 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
goto done;
}
else {
len += frag->data_len;
len = MAX(len, frag->offset + frag->data_len);
}
}
}
@ -3057,6 +3058,116 @@ static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(void)
PASS;
}
/**
* Reassembly should fail.
*
* |0 |8 |16 |24 |32 |40 |48 |
* |========|========|========|========|========|========|========|
* | | |AABBCCDD|AABBDDCC| | | |
* | | | | | |AACCBBDD| |
* | |AACCDDBB|AADDBBCC| | | | |
* |ZZZZZZZZ| | | | | | |
* | | | | | | |DDCCBBAA|
*/
static int DefragBsdMissingFragmentIpv4Test(void)
{
DefragInit();
default_policy = DEFRAG_POLICY_BSD;
Packet *packets[5];
FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
&packets[0], IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16));
FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
&packets[1], IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8));
FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
&packets[2], IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16));
/* ICMP header. */
FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
&packets[3], IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8));
FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
&packets[4], IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8));
Packet *r = Defrag(NULL, NULL, packets[0]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[1]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[2]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[3]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[4]);
FAIL_IF_NOT_NULL(r);
#if 0
PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
#endif
for (int i = 0; i < 5; i++) {
SCFree(packets[i]);
}
DefragDestroy();
PASS;
}
static int DefragBsdMissingFragmentIpv6Test(void)
{
DefragInit();
default_policy = DEFRAG_POLICY_BSD;
Packet *packets[5];
packets[0] = BuildIpv6TestPacketWithContent(
IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
packets[1] =
BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8);
packets[2] = BuildIpv6TestPacketWithContent(
IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16);
/* ICMP header. */
packets[3] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
packets[4] =
BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);
Packet *r = Defrag(NULL, NULL, packets[0]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[1]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[2]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[3]);
FAIL_IF_NOT_NULL(r);
r = Defrag(NULL, NULL, packets[4]);
FAIL_IF_NOT_NULL(r);
#if 0
PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
#endif
for (int i = 0; i < 5; i++) {
SCFree(packets[i]);
}
DefragDestroy();
PASS;
}
#endif /* UNITTESTS */
void DefragRegisterTests(void)
@ -3107,5 +3218,7 @@ void DefragRegisterTests(void)
DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2",
DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
UtRegisterTest("DefragBsdMissingFragmentIpv4Test", DefragBsdMissingFragmentIpv4Test);
UtRegisterTest("DefragBsdMissingFragmentIpv6Test", DefragBsdMissingFragmentIpv6Test);
#endif /* UNITTESTS */
}

Loading…
Cancel
Save