defrag: stop reassembly at the first packet with more flags not set

pull/1675/head
Jason Ish 10 years ago committed by Victor Julien
parent 3aa7e38c14
commit 6f223c6dba

@ -337,6 +337,10 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
}
if (!frag->more_frags) {
break;
}
}
SCLogDebug("ip_hdr_offset %u, hlen %u, fragmentable_len %u",
@ -460,6 +464,10 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
if (frag->offset + frag->data_len > fragmentable_len)
fragmentable_len = frag->offset + frag->data_len;
}
if (!frag->more_frags) {
break;
}
}
rp->ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + ip_hdr_offset);
@ -747,6 +755,7 @@ insert:
new->data_len = data_len - ltrim;
new->ip_hdr_offset = ip_hdr_offset;
new->frag_hdr_offset = frag_hdr_offset;
new->more_frags = more_frags;
#ifdef DEBUG
new->pcap_cnt = pcap_cnt;
#endif
@ -2392,6 +2401,132 @@ end:
return ret;
}
/**
* IPV4: Test the case where you have a packet fragmented in 3 parts
* and send like:
* - Offset: 2; MF: 1
* - Offset: 0; MF: 1
* - Offset: 1; MF: 0
*
* Only the fragments with offset 0 and 1 should be reassembled.
*/
static int DefragMfIpv4Test(void)
{
int retval = 0;
int ip_id = 9;
DefragInit();
Packet *p1 = BuildTestPacket(ip_id, 2, 1, 'C', 8);
Packet *p2 = BuildTestPacket(ip_id, 0, 1, 'A', 8);
Packet *p3 = BuildTestPacket(ip_id, 1, 0, 'B', 8);
if (p1 == NULL || p2 == NULL || p3 == NULL) {
goto end;
}
Packet *p = Defrag(NULL, NULL, p1, NULL);
if (p != NULL) {
goto end;
}
p = Defrag(NULL, NULL, p2, NULL);
if (p != NULL) {
goto end;
}
/* This should return a packet as MF=0. */
p = Defrag(NULL, NULL, p3, NULL);
if (p == NULL) {
goto end;
}
/* Expected IP length is 20 + 8 + 8 = 36 as only 2 of the
* fragments should be in the re-assembled packet. */
if (IPV4_GET_IPLEN(p) != 36) {
goto end;
}
retval = 1;
end:
if (p1 != NULL) {
SCFree(p1);
}
if (p2 != NULL) {
SCFree(p2);
}
if (p3 != NULL) {
SCFree(p3);
}
if (p != NULL) {
SCFree(p);
}
DefragDestroy();
return retval;
}
/**
* IPV6: Test the case where you have a packet fragmented in 3 parts
* and send like:
* - Offset: 2; MF: 1
* - Offset: 0; MF: 1
* - Offset: 1; MF: 0
*
* Only the fragments with offset 0 and 1 should be reassembled.
*/
static int DefragMfIpv6Test(void)
{
int retval = 0;
int ip_id = 9;
DefragInit();
Packet *p1 = IPV6BuildTestPacket(ip_id, 2, 1, 'C', 8);
Packet *p2 = IPV6BuildTestPacket(ip_id, 0, 1, 'A', 8);
Packet *p3 = IPV6BuildTestPacket(ip_id, 1, 0, 'B', 8);
if (p1 == NULL || p2 == NULL || p3 == NULL) {
goto end;
}
Packet *p = Defrag(NULL, NULL, p1, NULL);
if (p != NULL) {
goto end;
}
p = Defrag(NULL, NULL, p2, NULL);
if (p != NULL) {
goto end;
}
/* This should return a packet as MF=0. */
p = Defrag(NULL, NULL, p3, NULL);
if (p == NULL) {
goto end;
}
/* For IPv6 the expected length is just the length of the payload
* of 2 fragments, so 16. */
if (IPV6_GET_PLEN(p) != 16) {
goto end;
}
retval = 1;
end:
if (p1 != NULL) {
SCFree(p1);
}
if (p2 != NULL) {
SCFree(p2);
}
if (p3 != NULL) {
SCFree(p3);
}
if (p != NULL) {
SCFree(p);
}
DefragDestroy();
return retval;
}
#endif /* UNITTESTS */
void
@ -2437,11 +2572,11 @@ DefragRegisterTests(void)
UtRegisterTest("DefragVlanTest", DefragVlanTest, 1);
UtRegisterTest("DefragVlanQinQTest", DefragVlanQinQTest, 1);
UtRegisterTest("DefragTrackerReuseTest", DefragTrackerReuseTest, 1);
UtRegisterTest("DefragTimeoutTest",
DefragTimeoutTest, 1);
UtRegisterTest("DefragMfIpv4Test", DefragMfIpv4Test, 1);
UtRegisterTest("DefragMfIpv6Test", DefragMfIpv6Test, 1);
#endif /* UNITTESTS */
}

Loading…
Cancel
Save