Skip to content

Commit

Permalink
defrag: stop reassembly at the first packet with more flags not set
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonish authored and victorjulien committed Oct 8, 2015
1 parent 3aa7e38 commit 6f223c6
Showing 1 changed file with 137 additions and 2 deletions.
139 changes: 137 additions & 2 deletions src/defrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -747,6 +755,7 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
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
Expand Down Expand Up @@ -2392,6 +2401,132 @@ static int DefragTrackerReuseTest(void)
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
Expand Down Expand Up @@ -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 */
}

0 comments on commit 6f223c6

Please sign in to comment.