summaryrefslogtreecommitdiffstats
path: root/src/defrag.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/defrag.c')
-rw-r--r--src/defrag.c1620
1 files changed, 1118 insertions, 502 deletions
diff --git a/src/defrag.c b/src/defrag.c
index 71cf420..4596d72 100644
--- a/src/defrag.c
+++ b/src/defrag.c
@@ -104,26 +104,6 @@ static DefragContext *defrag_context;
RB_GENERATE(IP_FRAGMENTS, Frag_, rb, DefragRbFragCompare);
/**
- * Utility/debugging function to dump the frags associated with a
- * tracker. Only enable when unit tests are enabled.
- */
-#if 0
-#ifdef UNITTESTS
-static void
-DumpFrags(DefragTracker *tracker)
-{
- Frag *frag;
-
- printf("Dumping frags for packet: ID=%d\n", tracker->id);
- TAILQ_FOREACH(frag, &tracker->frags, next) {
- printf("-> Frag: frag_offset=%d, frag_len=%d, data_len=%d, ltrim=%d, skip=%d\n", frag->offset, frag->len, frag->data_len, frag->ltrim, frag->skip);
- PrintRawDataFp(stdout, frag->pkt, frag->len);
- }
-}
-#endif /* UNITTESTS */
-#endif
-
-/**
* \brief Reset a frag for reuse in a pool.
*/
static void
@@ -266,7 +246,7 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
}
/* Check that we have all the data. Relies on the fact that
- * fragments are inserted if frag_offset order. */
+ * fragments are inserted in frag_offset order. */
Frag *frag = NULL;
size_t len = 0;
RB_FOREACH_FROM(frag, IP_FRAGMENTS, first) {
@@ -276,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);
}
}
@@ -288,17 +269,27 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
}
PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
rp->flags |= PKT_REBUILT_FRAGMENT;
- rp->recursion_level = p->recursion_level;
+ rp->datalink = tracker->datalink;
int fragmentable_offset = 0;
uint16_t fragmentable_len = 0;
uint16_t hlen = 0;
int ip_hdr_offset = 0;
+ /* Assume more frags. */
+ uint16_t prev_offset = 0;
+ bool more_frags = 1;
+
RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
SCLogDebug("frag %p, data_len %u, offset %u, pcap_cnt %"PRIu64,
frag, frag->data_len, frag->offset, frag->pcap_cnt);
+ /* Previous fragment has no more fragments, and this packet
+ * doesn't overlap. We're done. */
+ if (!more_frags && frag->offset > prev_offset) {
+ break;
+ }
+
if (frag->skip)
continue;
if (frag->ltrim >= frag->data_len)
@@ -339,9 +330,16 @@ Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
fragmentable_len = frag->offset + frag->data_len;
}
- if (!frag->more_frags) {
- break;
- }
+ /* Even if this fragment is flagged as having no more
+ * fragments, still continue. The next fragment may have the
+ * same offset with data that is preferred.
+ *
+ * For example, DefragBsdFragmentAfterNoMfIpv{4,6}Test
+ *
+ * This is due to not all fragments being completely trimmed,
+ * but relying on the copy ordering. */
+ more_frags = frag->more_frags;
+ prev_offset = frag->offset;
}
SCLogDebug("ip_hdr_offset %u, hlen %" PRIu16 ", fragmentable_len %" PRIu16, ip_hdr_offset, hlen,
@@ -417,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);
}
}
}
@@ -430,13 +428,23 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
goto error_remove_tracker;
}
PKT_SET_SRC(rp, PKT_SRC_DEFRAG);
+ rp->flags |= PKT_REBUILT_FRAGMENT;
+ rp->datalink = tracker->datalink;
uint16_t unfragmentable_len = 0;
int fragmentable_offset = 0;
uint16_t fragmentable_len = 0;
int ip_hdr_offset = 0;
uint8_t next_hdr = 0;
+
+ /* Assume more frags. */
+ uint16_t prev_offset = 0;
+ bool more_frags = 1;
+
RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
+ if (!more_frags && frag->offset > prev_offset) {
+ break;
+ }
if (frag->skip)
continue;
if (frag->data_len - frag->ltrim <= 0)
@@ -481,9 +489,16 @@ Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
fragmentable_len = frag->offset + frag->data_len;
}
- if (!frag->more_frags) {
- break;
- }
+ /* Even if this fragment is flagged as having no more
+ * fragments, still continue. The next fragment may have the
+ * same offset with data that is preferred.
+ *
+ * For example, DefragBsdFragmentAfterNoMfIpv{4,6}Test
+ *
+ * This is due to not all fragments being completely trimmed,
+ * but relying on the copy ordering. */
+ more_frags = frag->more_frags;
+ prev_offset = frag->offset;
}
rp->ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + ip_hdr_offset);
@@ -660,16 +675,45 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
switch (tracker->policy) {
case DEFRAG_POLICY_BSD:
if (frag_offset < prev->offset + prev->data_len) {
- if (frag_offset >= prev->offset) {
- ltrim = prev->offset + prev->data_len - frag_offset;
+ if (prev->offset <= frag_offset) {
+ /* We prefer the data from the previous
+ * fragment, so trim off the data in the new
+ * fragment that exists in the previous
+ * fragment. */
+ uint16_t prev_end = prev->offset + prev->data_len;
+ if (prev_end > frag_end) {
+ /* Just skip. */
+ /* TODO: Set overlap flag. */
+ goto done;
+ }
+ ltrim = prev_end - frag_offset;
+
+ if ((next != NULL) && (frag_end > next->offset)) {
+ next->ltrim = frag_end - next->offset;
+ }
+
+ goto insert;
}
+
+ /* If the end of this fragment overlaps the start
+ * of the previous fragment, then trim up the
+ * start of previous fragment so this fragment is
+ * used.
+ *
+ * See:
+ * DefragBsdSubsequentOverlapsStartOfOriginal.
+ */
+ if (frag_offset <= prev->offset && frag_end > prev->offset + prev->ltrim) {
+ uint16_t prev_ltrim = frag_end - prev->offset;
+ if (prev_ltrim > prev->ltrim) {
+ prev->ltrim = prev_ltrim;
+ }
+ }
+
if ((next != NULL) && (frag_end > next->offset)) {
next->ltrim = frag_end - next->offset;
}
- if ((frag_offset < prev->offset) &&
- (frag_end >= prev->offset + prev->data_len)) {
- prev->skip = 1;
- }
+
goto insert;
}
break;
@@ -861,6 +905,9 @@ DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker,
#ifdef DEBUG
new->pcap_cnt = pcap_cnt;
#endif
+ if (frag_offset == 0) {
+ tracker->datalink = p->datalink;
+ }
IP_FRAGMENTS_RB_INSERT(&tracker->fragment_tree, new);
@@ -1093,8 +1140,8 @@ void DefragDestroy(void)
* Allocate a test packet. Nothing to fancy, just a simple IP packet
* with some payload of no particular protocol.
*/
-static Packet *BuildTestPacket(uint8_t proto, uint16_t id, uint16_t off, int mf,
- const char content, int content_len)
+static Packet *BuildIpv4TestPacket(
+ uint8_t proto, uint16_t id, uint16_t off, int mf, const char content, int content_len)
{
Packet *p = NULL;
int hlen = 20;
@@ -1167,8 +1214,79 @@ error:
return NULL;
}
-static Packet *IPV6BuildTestPacket(uint8_t proto, uint32_t id, uint16_t off,
- int mf, const char content, int content_len)
+/**
+ * Allocate a test packet, much like BuildIpv4TestPacket, but with
+ * the full content provided by the caller.
+ */
+static Packet *BuildIpv4TestPacketWithContent(
+ uint8_t proto, uint16_t id, uint16_t off, int mf, const uint8_t *content, int content_len)
+{
+ Packet *p = NULL;
+ int hlen = 20;
+ int ttl = 64;
+ IPV4Hdr ip4h;
+
+ p = SCCalloc(1, sizeof(*p) + default_packet_size);
+ if (unlikely(p == NULL))
+ return NULL;
+
+ PacketInit(p);
+
+ struct timeval tval;
+ gettimeofday(&tval, NULL);
+ p->ts = SCTIME_FROM_TIMEVAL(&tval);
+ ip4h.ip_verhl = 4 << 4;
+ ip4h.ip_verhl |= hlen >> 2;
+ ip4h.ip_len = htons(hlen + content_len);
+ ip4h.ip_id = htons(id);
+ if (mf)
+ ip4h.ip_off = htons(IP_MF | off);
+ else
+ ip4h.ip_off = htons(off);
+ ip4h.ip_ttl = ttl;
+ ip4h.ip_proto = proto;
+
+ ip4h.s_ip_src.s_addr = 0x01010101; /* 1.1.1.1 */
+ ip4h.s_ip_dst.s_addr = 0x02020202; /* 2.2.2.2 */
+
+ /* copy content_len crap, we need full length */
+ PacketCopyData(p, (uint8_t *)&ip4h, sizeof(ip4h));
+ p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
+ SET_IPV4_SRC_ADDR(p, &p->src);
+ SET_IPV4_DST_ADDR(p, &p->dst);
+
+ PacketCopyDataOffset(p, hlen, content, content_len);
+ SET_PKT_LEN(p, hlen + content_len);
+
+ p->ip4h->ip_csum = IPV4Checksum((uint16_t *)GET_PKT_DATA(p), hlen, 0);
+
+ /* Self test. */
+ if (IPV4_GET_VER(p) != 4)
+ goto error;
+ if (IPV4_GET_HLEN(p) != hlen)
+ goto error;
+ if (IPV4_GET_IPLEN(p) != hlen + content_len)
+ goto error;
+ if (IPV4_GET_IPID(p) != id)
+ goto error;
+ if (IPV4_GET_IPOFFSET(p) != off)
+ goto error;
+ if (IPV4_GET_MF(p) != mf)
+ goto error;
+ if (IPV4_GET_IPTTL(p) != ttl)
+ goto error;
+ if (IPV4_GET_IPPROTO(p) != proto)
+ goto error;
+
+ return p;
+error:
+ if (p != NULL)
+ SCFree(p);
+ return NULL;
+}
+
+static Packet *BuildIpv6TestPacket(
+ uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t content, int content_len)
{
Packet *p = NULL;
uint8_t *pcontent;
@@ -1238,6 +1356,71 @@ error:
return NULL;
}
+static Packet *BuildIpv6TestPacketWithContent(
+ uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t *content, int content_len)
+{
+ Packet *p = NULL;
+ IPV6Hdr ip6h;
+
+ p = SCCalloc(1, sizeof(*p) + default_packet_size);
+ if (unlikely(p == NULL))
+ return NULL;
+
+ PacketInit(p);
+
+ struct timeval tval;
+ gettimeofday(&tval, NULL);
+ p->ts = SCTIME_FROM_TIMEVAL(&tval);
+
+ ip6h.s_ip6_nxt = 44;
+ ip6h.s_ip6_hlim = 2;
+
+ /* Source and dest address - very bogus addresses. */
+ ip6h.s_ip6_src[0] = 0x01010101;
+ ip6h.s_ip6_src[1] = 0x01010101;
+ ip6h.s_ip6_src[2] = 0x01010101;
+ ip6h.s_ip6_src[3] = 0x01010101;
+ ip6h.s_ip6_dst[0] = 0x02020202;
+ ip6h.s_ip6_dst[1] = 0x02020202;
+ ip6h.s_ip6_dst[2] = 0x02020202;
+ ip6h.s_ip6_dst[3] = 0x02020202;
+
+ /* copy content_len crap, we need full length */
+ PacketCopyData(p, (uint8_t *)&ip6h, sizeof(IPV6Hdr));
+
+ p->ip6h = (IPV6Hdr *)GET_PKT_DATA(p);
+ IPV6_SET_RAW_VER(p->ip6h, 6);
+ /* Fragmentation header. */
+ IPV6FragHdr *fh = (IPV6FragHdr *)(GET_PKT_DATA(p) + sizeof(IPV6Hdr));
+ fh->ip6fh_nxt = proto;
+ fh->ip6fh_ident = htonl(id);
+ fh->ip6fh_offlg = htons((off << 3) | mf);
+
+ DecodeIPV6FragHeader(p, (uint8_t *)fh, 8, 8 + content_len, 0);
+
+ PacketCopyDataOffset(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr), content, content_len);
+ SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr) + content_len);
+
+ p->ip6h->s_ip6_plen = htons(sizeof(IPV6FragHdr) + content_len);
+
+ SET_IPV6_SRC_ADDR(p, &p->src);
+ SET_IPV6_DST_ADDR(p, &p->dst);
+
+ /* Self test. */
+ if (IPV6_GET_VER(p) != 6)
+ goto error;
+ if (IPV6_GET_NH(p) != 44)
+ goto error;
+ if (IPV6_GET_PLEN(p) != sizeof(IPV6FragHdr) + content_len)
+ goto error;
+
+ return p;
+error:
+ if (p != NULL)
+ SCFree(p);
+ return NULL;
+}
+
/**
* Test the simplest possible re-assembly scenario. All packet in
* order and no overlaps.
@@ -1251,11 +1434,11 @@ static int DefragInOrderSimpleTest(void)
DefragInit();
- p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = BuildTestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
+ p2 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
FAIL_IF_NULL(p2);
- p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
+ p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
FAIL_IF_NULL(p3);
FAIL_IF(Defrag(NULL, NULL, p1) != NULL);
@@ -1303,11 +1486,11 @@ static int DefragReverseSimpleTest(void)
DefragInit();
- p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = BuildTestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
+ p2 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
FAIL_IF_NULL(p2);
- p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
+ p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
FAIL_IF_NULL(p3);
FAIL_IF(Defrag(NULL, NULL, p3) != NULL);
@@ -1347,7 +1530,7 @@ static int DefragReverseSimpleTest(void)
* Test the simplest possible re-assembly scenario. All packet in
* order and no overlaps.
*/
-static int IPV6DefragInOrderSimpleTest(void)
+static int DefragInOrderSimpleIpv6Test(void)
{
Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
Packet *reassembled = NULL;
@@ -1356,11 +1539,11 @@ static int IPV6DefragInOrderSimpleTest(void)
DefragInit();
- p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
+ p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
+ p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
FAIL_IF_NULL(p2);
- p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
+ p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
FAIL_IF_NULL(p3);
FAIL_IF(Defrag(NULL, NULL, p1) != NULL);
@@ -1394,7 +1577,7 @@ static int IPV6DefragInOrderSimpleTest(void)
PASS;
}
-static int IPV6DefragReverseSimpleTest(void)
+static int DefragReverseSimpleIpv6Test(void)
{
DefragContext *dc = NULL;
Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
@@ -1407,11 +1590,11 @@ static int IPV6DefragReverseSimpleTest(void)
dc = DefragContextNew();
FAIL_IF_NULL(dc);
- p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
+ p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
+ p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
FAIL_IF_NULL(p2);
- p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
+ p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
FAIL_IF_NULL(p3);
FAIL_IF(Defrag(NULL, NULL, p3) != NULL);
@@ -1444,8 +1627,7 @@ static int IPV6DefragReverseSimpleTest(void)
PASS;
}
-static int DefragDoSturgesNovakTest(int policy, u_char *expected,
- size_t expected_len)
+static int DefragDoSturgesNovakTest(int policy, uint8_t *expected, size_t expected_len)
{
int i;
@@ -1463,60 +1645,60 @@ static int DefragDoSturgesNovakTest(int policy, u_char *expected,
* Original fragments.
*/
- /* A*24 at 0. */
- packets[0] = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
+ /* <1> A*24 at 0. */
+ packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
- /* B*15 at 32. */
- packets[1] = BuildTestPacket(IPPROTO_ICMP, id, 32 >> 3, 1, 'B', 16);
+ /* <2> B*16 at 32. */
+ packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 32 >> 3, 1, 'B', 16);
- /* C*24 at 48. */
- packets[2] = BuildTestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'C', 24);
+ /* <3> C*24 at 48. */
+ packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'C', 24);
- /* D*8 at 80. */
- packets[3] = BuildTestPacket(IPPROTO_ICMP, id, 80 >> 3, 1, 'D', 8);
+ /* <3_1> D*8 at 80. */
+ packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 80 >> 3, 1, 'D', 8);
- /* E*16 at 104. */
- packets[4] = BuildTestPacket(IPPROTO_ICMP, id, 104 >> 3, 1, 'E', 16);
+ /* <3_2> E*16 at 104. */
+ packets[4] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 104 >> 3, 1, 'E', 16);
- /* F*24 at 120. */
- packets[5] = BuildTestPacket(IPPROTO_ICMP, id, 120 >> 3, 1, 'F', 24);
+ /* <3_3> F*24 at 120. */
+ packets[5] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 120 >> 3, 1, 'F', 24);
- /* G*16 at 144. */
- packets[6] = BuildTestPacket(IPPROTO_ICMP, id, 144 >> 3, 1, 'G', 16);
+ /* <3_4> G*16 at 144. */
+ packets[6] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 144 >> 3, 1, 'G', 16);
- /* H*16 at 160. */
- packets[7] = BuildTestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'H', 16);
+ /* <3_5> H*16 at 160. */
+ packets[7] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'H', 16);
- /* I*8 at 176. */
- packets[8] = BuildTestPacket(IPPROTO_ICMP, id, 176 >> 3, 1, 'I', 8);
+ /* <3_6> I*8 at 176. */
+ packets[8] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 176 >> 3, 1, 'I', 8);
/*
* Overlapping subsequent fragments.
*/
- /* J*32 at 8. */
- packets[9] = BuildTestPacket(IPPROTO_ICMP, id, 8 >> 3, 1, 'J', 32);
+ /* <4> J*32 at 8. */
+ packets[9] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 8 >> 3, 1, 'J', 32);
- /* K*24 at 48. */
- packets[10] = BuildTestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'K', 24);
+ /* <5> K*24 at 48. */
+ packets[10] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'K', 24);
- /* L*24 at 72. */
- packets[11] = BuildTestPacket(IPPROTO_ICMP, id, 72 >> 3, 1, 'L', 24);
+ /* <6> L*24 at 72. */
+ packets[11] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 72 >> 3, 1, 'L', 24);
- /* M*24 at 96. */
- packets[12] = BuildTestPacket(IPPROTO_ICMP, id, 96 >> 3, 1, 'M', 24);
+ /* <7> M*24 at 96. */
+ packets[12] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 96 >> 3, 1, 'M', 24);
- /* N*8 at 128. */
- packets[13] = BuildTestPacket(IPPROTO_ICMP, id, 128 >> 3, 1, 'N', 8);
+ /* <8> N*8 at 128. */
+ packets[13] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 128 >> 3, 1, 'N', 8);
- /* O*8 at 152. */
- packets[14] = BuildTestPacket(IPPROTO_ICMP, id, 152 >> 3, 1, 'O', 8);
+ /* <9> O*8 at 152. */
+ packets[14] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 152 >> 3, 1, 'O', 8);
- /* P*8 at 160. */
- packets[15] = BuildTestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'P', 8);
+ /* <10> P*8 at 160. */
+ packets[15] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'P', 8);
- /* Q*16 at 176. */
- packets[16] = BuildTestPacket(IPPROTO_ICMP, id, 176 >> 3, 0, 'Q', 16);
+ /* <11> Q*16 at 176. */
+ packets[16] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 176 >> 3, 0, 'Q', 16);
default_policy = policy;
@@ -1542,8 +1724,15 @@ static int DefragDoSturgesNovakTest(int policy, u_char *expected,
FAIL_IF(IPV4_GET_HLEN(reassembled) != 20);
FAIL_IF(IPV4_GET_IPLEN(reassembled) != 20 + 192);
-
- FAIL_IF(memcmp(GET_PKT_DATA(reassembled) + 20, expected, expected_len) != 0);
+ FAIL_IF(expected_len != 192);
+
+ if (memcmp(expected, GET_PKT_DATA(reassembled) + 20, expected_len) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, expected_len);
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(reassembled) + 20, GET_PKT_LEN(reassembled) - 20);
+ FAIL;
+ }
SCFree(reassembled);
/* Make sure all frags were returned back to the pool. */
@@ -1556,8 +1745,7 @@ static int DefragDoSturgesNovakTest(int policy, u_char *expected,
PASS;
}
-static int IPV6DefragDoSturgesNovakTest(int policy, u_char *expected,
- size_t expected_len)
+static int DefragDoSturgesNovakIpv6Test(int policy, uint8_t *expected, size_t expected_len)
{
int i;
@@ -1575,60 +1763,60 @@ static int IPV6DefragDoSturgesNovakTest(int policy, u_char *expected,
* Original fragments.
*/
- /* A*24 at 0. */
- packets[0] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 24);
+ /* <1> A*24 at 0. */
+ packets[0] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 24);
- /* B*15 at 32. */
- packets[1] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 32 >> 3, 1, 'B', 16);
+ /* <2> B*16 at 32. */
+ packets[1] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 32 >> 3, 1, 'B', 16);
- /* C*24 at 48. */
- packets[2] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'C', 24);
+ /* <3> C*24 at 48. */
+ packets[2] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'C', 24);
- /* D*8 at 80. */
- packets[3] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 80 >> 3, 1, 'D', 8);
+ /* <3_1> D*8 at 80. */
+ packets[3] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 80 >> 3, 1, 'D', 8);
- /* E*16 at 104. */
- packets[4] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 104 >> 3, 1, 'E', 16);
+ /* <3_2> E*16 at 104. */
+ packets[4] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 104 >> 3, 1, 'E', 16);
- /* F*24 at 120. */
- packets[5] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 120 >> 3, 1, 'F', 24);
+ /* <3_3> F*24 at 120. */
+ packets[5] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 120 >> 3, 1, 'F', 24);
- /* G*16 at 144. */
- packets[6] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 144 >> 3, 1, 'G', 16);
+ /* <3_4> G*16 at 144. */
+ packets[6] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 144 >> 3, 1, 'G', 16);
- /* H*16 at 160. */
- packets[7] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'H', 16);
+ /* <3_5> H*16 at 160. */
+ packets[7] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'H', 16);
- /* I*8 at 176. */
- packets[8] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 1, 'I', 8);
+ /* <3_6> I*8 at 176. */
+ packets[8] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 1, 'I', 8);
/*
* Overlapping subsequent fragments.
*/
- /* J*32 at 8. */
- packets[9] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 8 >> 3, 1, 'J', 32);
+ /* <4> J*32 at 8. */
+ packets[9] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 8 >> 3, 1, 'J', 32);
- /* K*24 at 48. */
- packets[10] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'K', 24);
+ /* <5> K*24 at 48. */
+ packets[10] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'K', 24);
- /* L*24 at 72. */
- packets[11] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 72 >> 3, 1, 'L', 24);
+ /* <6> L*24 at 72. */
+ packets[11] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 72 >> 3, 1, 'L', 24);
- /* M*24 at 96. */
- packets[12] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 96 >> 3, 1, 'M', 24);
+ /* <7> M*24 at 96. */
+ packets[12] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 96 >> 3, 1, 'M', 24);
- /* N*8 at 128. */
- packets[13] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 128 >> 3, 1, 'N', 8);
+ /* <8> N*8 at 128. */
+ packets[13] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 128 >> 3, 1, 'N', 8);
- /* O*8 at 152. */
- packets[14] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 152 >> 3, 1, 'O', 8);
+ /* <9> O*8 at 152. */
+ packets[14] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 152 >> 3, 1, 'O', 8);
- /* P*8 at 160. */
- packets[15] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'P', 8);
+ /* <10> P*8 at 160. */
+ packets[15] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'P', 8);
- /* Q*16 at 176. */
- packets[16] = IPV6BuildTestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 0, 'Q', 16);
+ /* <11> Q*16 at 176. */
+ packets[16] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 0, 'Q', 16);
default_policy = policy;
@@ -1667,35 +1855,61 @@ static int IPV6DefragDoSturgesNovakTest(int policy, u_char *expected,
PASS;
}
+/* Define data that matches the naming "Target-Based Fragmentation
+ * Reassembly".
+ *
+ * For example, the data refers to a fragment of data as <1>, or <3_6>
+ * and uses these to diagram the input fragments and the resulting
+ * policies. We build test cases for the papers scenario but assign
+ * specific values to each segment.
+ */
+#define D_1 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'
+#define D_2 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'
+#define D_3 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'
+#define D_3_1 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
+#define D_3_2 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'
+#define D_3_3 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'
+#define D_3_4 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'
+#define D_3_5 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H'
+#define D_3_6 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I'
+#define D_4 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J'
+#define D_5 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K'
+#define D_6 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
+#define D_7 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M'
+#define D_8 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'
+#define D_9 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'
+#define D_10 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'
+#define D_11 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q'
+
static int
DefragSturgesNovakBsdTest(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_4,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected,
@@ -1703,69 +1917,68 @@ DefragSturgesNovakBsdTest(void)
PASS;
}
-static int IPV6DefragSturgesNovakBsdTest(void)
+static int DefragSturgesNovakBsdIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_4,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
- FAIL_IF_NOT(IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_BSD, expected, sizeof(expected)));
PASS;
}
static int DefragSturgesNovakLinuxIpv4Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "KKKKKKKK"
- "KKKKKKKK"
- "KKKKKKKK"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "PPPPPPPP"
- "HHHHHHHH"
- "QQQQQQQQ"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_4,
+ D_2,
+ D_5,
+ D_5,
+ D_5,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_10,
+ D_3_5,
+ D_11,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected,
@@ -1773,69 +1986,68 @@ static int DefragSturgesNovakLinuxIpv4Test(void)
PASS;
}
-static int IPV6DefragSturgesNovakLinuxTest(void)
+static int DefragSturgesNovakLinuxIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "KKKKKKKK"
- "KKKKKKKK"
- "KKKKKKKK"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "PPPPPPPP"
- "HHHHHHHH"
- "QQQQQQQQ"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_4,
+ D_2,
+ D_5,
+ D_5,
+ D_5,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_10,
+ D_3_5,
+ D_11,
+ D_11,
};
- FAIL_IF_NOT(IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_LINUX, expected, sizeof(expected)));
PASS;
}
static int DefragSturgesNovakWindowsIpv4Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "EEEEEEEE"
- "EEEEEEEE"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_3_2,
+ D_3_2,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected,
@@ -1843,69 +2055,68 @@ static int DefragSturgesNovakWindowsIpv4Test(void)
PASS;
}
-static int IPV6DefragSturgesNovakWindowsTest(void)
+static int DefragSturgesNovakWindowsIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "EEEEEEEE"
- "EEEEEEEE"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_3_2,
+ D_3_2,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
- FAIL_IF_NOT(IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_WINDOWS, expected, sizeof(expected)));
PASS;
}
static int DefragSturgesNovakSolarisTest(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected,
@@ -1913,69 +2124,68 @@ static int DefragSturgesNovakSolarisTest(void)
PASS;
}
-static int IPV6DefragSturgesNovakSolarisTest(void)
+static int DefragSturgesNovakSolarisIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
- FAIL_IF_NOT(IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_SOLARIS, expected, sizeof(expected)));
PASS;
}
static int DefragSturgesNovakFirstTest(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "DDDDDDDD"
- "LLLLLLLL"
- "MMMMMMMM"
- "EEEEEEEE"
- "EEEEEEEE"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_3_1,
+ D_6,
+ D_7,
+ D_3_2,
+ D_3_2,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected,
@@ -1983,69 +2193,68 @@ static int DefragSturgesNovakFirstTest(void)
PASS;
}
-static int IPV6DefragSturgesNovakFirstTest(void)
+static int DefragSturgesNovakFirstIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "JJJJJJJJ"
- "BBBBBBBB"
- "BBBBBBBB"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "LLLLLLLL"
- "DDDDDDDD"
- "LLLLLLLL"
- "MMMMMMMM"
- "EEEEEEEE"
- "EEEEEEEE"
- "FFFFFFFF"
- "FFFFFFFF"
- "FFFFFFFF"
- "GGGGGGGG"
- "GGGGGGGG"
- "HHHHHHHH"
- "HHHHHHHH"
- "IIIIIIII"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_1,
+ D_1,
+ D_4,
+ D_2,
+ D_2,
+ D_3,
+ D_3,
+ D_3,
+ D_6,
+ D_3_1,
+ D_6,
+ D_7,
+ D_3_2,
+ D_3_2,
+ D_3_3,
+ D_3_3,
+ D_3_3,
+ D_3_4,
+ D_3_4,
+ D_3_5,
+ D_3_5,
+ D_3_6,
+ D_11,
};
- return IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected,
- sizeof(expected));
+ return DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_FIRST, expected, sizeof(expected));
}
static int
DefragSturgesNovakLastTest(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "KKKKKKKK"
- "KKKKKKKK"
- "KKKKKKKK"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "NNNNNNNN"
- "FFFFFFFF"
- "GGGGGGGG"
- "OOOOOOOO"
- "PPPPPPPP"
- "HHHHHHHH"
- "QQQQQQQQ"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_4,
+ D_4,
+ D_4,
+ D_4,
+ D_2,
+ D_5,
+ D_5,
+ D_5,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_8,
+ D_3_3,
+ D_3_4,
+ D_9,
+ D_10,
+ D_3_5,
+ D_11,
+ D_11,
};
FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected,
@@ -2053,38 +2262,37 @@ DefragSturgesNovakLastTest(void)
PASS;
}
-static int IPV6DefragSturgesNovakLastTest(void)
+static int DefragSturgesNovakLastIpv6Test(void)
{
/* Expected data. */
- u_char expected[] = {
- "AAAAAAAA"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "JJJJJJJJ"
- "BBBBBBBB"
- "KKKKKKKK"
- "KKKKKKKK"
- "KKKKKKKK"
- "LLLLLLLL"
- "LLLLLLLL"
- "LLLLLLLL"
- "MMMMMMMM"
- "MMMMMMMM"
- "MMMMMMMM"
- "FFFFFFFF"
- "NNNNNNNN"
- "FFFFFFFF"
- "GGGGGGGG"
- "OOOOOOOO"
- "PPPPPPPP"
- "HHHHHHHH"
- "QQQQQQQQ"
- "QQQQQQQQ"
+ uint8_t expected[] = {
+ D_1,
+ D_4,
+ D_4,
+ D_4,
+ D_4,
+ D_2,
+ D_5,
+ D_5,
+ D_5,
+ D_6,
+ D_6,
+ D_6,
+ D_7,
+ D_7,
+ D_7,
+ D_3_3,
+ D_8,
+ D_3_3,
+ D_3_4,
+ D_9,
+ D_10,
+ D_3_5,
+ D_11,
+ D_11,
};
- FAIL_IF_NOT(IPV6DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected,
- sizeof(expected)));
+ FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_LAST, expected, sizeof(expected)));
PASS;
}
@@ -2099,7 +2307,7 @@ static int DefragTimeoutTest(void)
/* Load in 16 packets. */
for (i = 0; i < 16; i++) {
- Packet *p = BuildTestPacket(IPPROTO_ICMP,i, 0, 1, 'A' + i, 16);
+ Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, i, 0, 1, 'A' + i, 16);
FAIL_IF_NULL(p);
Packet *tp = Defrag(NULL, NULL, p);
@@ -2109,7 +2317,7 @@ static int DefragTimeoutTest(void)
/* Build a new packet but push the timestamp out by our timeout.
* This should force our previous fragments to be timed out. */
- Packet *p = BuildTestPacket(IPPROTO_ICMP, 99, 0, 1, 'A' + i, 16);
+ Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, 99, 0, 1, 'A' + i, 16);
FAIL_IF_NULL(p);
p->ts = SCTIME_ADD_SECS(p->ts, defrag_context->timeout + 1);
@@ -2134,7 +2342,7 @@ static int DefragTimeoutTest(void)
* fail. The fix was simple, but this unit test is just to make sure
* its not introduced.
*/
-static int DefragIPv4NoDataTest(void)
+static int DefragNoDataIpv4Test(void)
{
DefragContext *dc = NULL;
Packet *p = NULL;
@@ -2146,7 +2354,7 @@ static int DefragIPv4NoDataTest(void)
FAIL_IF_NULL(dc);
/* This packet has an offset > 0, more frags set to 0 and no data. */
- p = BuildTestPacket(IPPROTO_ICMP, id, 1, 0, 'A', 0);
+ p = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 0, 'A', 0);
FAIL_IF_NULL(p);
/* We do not expect a packet returned. */
@@ -2163,7 +2371,7 @@ static int DefragIPv4NoDataTest(void)
PASS;
}
-static int DefragIPv4TooLargeTest(void)
+static int DefragTooLargeIpv4Test(void)
{
DefragContext *dc = NULL;
Packet *p = NULL;
@@ -2175,7 +2383,7 @@ static int DefragIPv4TooLargeTest(void)
/* Create a fragment that would extend past the max allowable size
* for an IPv4 packet. */
- p = BuildTestPacket(IPPROTO_ICMP, 1, 8183, 0, 'A', 71);
+ p = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8183, 0, 'A', 71);
FAIL_IF_NULL(p);
/* We do not expect a packet returned. */
@@ -2206,9 +2414,9 @@ static int DefragVlanTest(void)
DefragInit();
- p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
+ p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
FAIL_IF_NULL(p2);
/* With no VLAN IDs set, packets should re-assemble. */
@@ -2238,9 +2446,9 @@ static int DefragVlanQinQTest(void)
DefragInit();
- p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
+ p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
FAIL_IF_NULL(p2);
/* With no VLAN IDs set, packets should re-assemble. */
@@ -2272,9 +2480,9 @@ static int DefragVlanQinQinQTest(void)
DefragInit();
- Packet *p1 = BuildTestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
+ Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- Packet *p2 = BuildTestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
+ Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
FAIL_IF_NULL(p2);
/* With no VLAN IDs set, packets should re-assemble. */
@@ -2308,7 +2516,7 @@ static int DefragTrackerReuseTest(void)
/* Build a packet, its not a fragment but shouldn't matter for
* this test. */
- p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 0, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 0, 'A', 8);
FAIL_IF_NULL(p1);
/* Get a tracker. It shouldn't look like its already in use. */
@@ -2355,9 +2563,9 @@ static int DefragMfIpv4Test(void)
DefragInit();
- Packet *p1 = BuildTestPacket(IPPROTO_ICMP, ip_id, 2, 1, 'C', 8);
- Packet *p2 = BuildTestPacket(IPPROTO_ICMP, ip_id, 0, 1, 'A', 8);
- Packet *p3 = BuildTestPacket(IPPROTO_ICMP, ip_id, 1, 0, 'B', 8);
+ Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 2, 1, 'C', 8);
+ Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 0, 1, 'A', 8);
+ Packet *p3 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 1, 0, 'B', 8);
FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
p = Defrag(NULL, NULL, p1);
@@ -2374,6 +2582,10 @@ static int DefragMfIpv4Test(void)
* fragments should be in the re-assembled packet. */
FAIL_IF(IPV4_GET_IPLEN(p) != 36);
+ /* Verify the payload of the IPv4 packet. */
+ uint8_t expected_payload[] = "AAAAAAAABBBBBBBB";
+ FAIL_IF(memcmp(GET_PKT_DATA(p) + sizeof(IPV4Hdr), expected_payload, sizeof(expected_payload)));
+
SCFree(p1);
SCFree(p2);
SCFree(p3);
@@ -2398,9 +2610,9 @@ static int DefragMfIpv6Test(void)
DefragInit();
- Packet *p1 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 2, 1, 'C', 8);
- Packet *p2 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 0, 1, 'A', 8);
- Packet *p3 = IPV6BuildTestPacket(IPPROTO_ICMPV6, ip_id, 1, 0, 'B', 8);
+ Packet *p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 2, 1, 'C', 8);
+ Packet *p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 0, 1, 'A', 8);
+ Packet *p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 1, 0, 'B', 8);
FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
p = Defrag(NULL, NULL, p1);
@@ -2417,6 +2629,10 @@ static int DefragMfIpv6Test(void)
* of 2 fragments, so 16. */
FAIL_IF(IPV6_GET_PLEN(p) != 16);
+ /* Verify the payload of the IPv4 packet. */
+ uint8_t expected_payload[] = "AAAAAAAABBBBBBBB";
+ FAIL_IF(memcmp(GET_PKT_DATA(p) + sizeof(IPV6Hdr), expected_payload, sizeof(expected_payload)));
+
SCFree(p1);
SCFree(p2);
SCFree(p3);
@@ -2436,11 +2652,11 @@ static int DefragTestBadProto(void)
DefragInit();
- p1 = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
+ p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
FAIL_IF_NULL(p1);
- p2 = BuildTestPacket(IPPROTO_UDP, id, 1, 1, 'B', 8);
+ p2 = BuildIpv4TestPacket(IPPROTO_UDP, id, 1, 1, 'B', 8);
FAIL_IF_NULL(p2);
- p3 = BuildTestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
+ p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
FAIL_IF_NULL(p3);
FAIL_IF_NOT_NULL(Defrag(NULL, NULL, p1));
@@ -2461,19 +2677,19 @@ static int DefragTestBadProto(void)
*/
static int DefragTestJeremyLinux(void)
{
- char expected[] = "AAAAAAAA"
- "AAAAAAAA"
- "AAAAAAAA"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "CCCCCCCC"
- "BBBBBBBB"
- "BBBBBBBB"
- "DDDDDDDD"
- "DDDDDD";
+ uint8_t expected[] = "AAAAAAAA"
+ "AAAAAAAA"
+ "AAAAAAAA"
+ "CCCCCCCC"
+ "CCCCCCCC"
+ "CCCCCCCC"
+ "CCCCCCCC"
+ "CCCCCCCC"
+ "CCCCCCCC"
+ "BBBBBBBB"
+ "BBBBBBBB"
+ "DDDDDDDD"
+ "DDDDDD";
DefragInit();
default_policy = DEFRAG_POLICY_LINUX;
@@ -2482,10 +2698,10 @@ static int DefragTestJeremyLinux(void)
Packet *packets[4];
int i = 0;
- packets[0] = BuildTestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
- packets[1] = BuildTestPacket(IPPROTO_ICMP, id, 40 >> 3, 1, 'B', 48);
- packets[2] = BuildTestPacket(IPPROTO_ICMP, id, 24 >> 3, 1, 'C', 48);
- packets[3] = BuildTestPacket(IPPROTO_ICMP, id, 88 >> 3, 0, 'D', 14);
+ packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
+ packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 40 >> 3, 1, 'B', 48);
+ packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 24 >> 3, 1, 'C', 48);
+ packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 88 >> 3, 0, 'D', 14);
Packet *r = Defrag(NULL, NULL, packets[0]);
FAIL_IF_NOT_NULL(r);
@@ -2510,6 +2726,401 @@ static int DefragTestJeremyLinux(void)
PASS;
}
+/**
+ * | 0 | 8 | 16 | 24 | 32 |
+ * |----------|----------|----------|----------|----------|
+ * | AAAAAAAA | AAAAAAAA |
+ * | | BBBBBBBB | BBBBBBBB | | |
+ * | | | CCCCCCCC | CCCCCCCC | |
+ * | DDDDDDDD | | | | |
+ *
+ * | DDDDDDDD | BBBBBBBB | BBBBBBBB | CCCCCCCC | AAAAAAAA |
+ */
+static int DefragBsdFragmentAfterNoMfIpv4Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0, 'A', 16);
+ packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1, 'B', 16);
+ packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1, 'C', 16);
+ packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 0, 1, 'D', 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_NULL(r);
+
+ // clang-format off
+ uint8_t expected[] = {
+ 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
+ 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
+ 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
+ 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
+ FAIL;
+ }
+
+ DefragDestroy();
+ PASS;
+}
+
+static int DefragBsdFragmentAfterNoMfIpv6Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0, 'A', 16);
+ packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1, 'B', 16);
+ packets[2] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1, 'C', 16);
+ packets[3] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 0, 1, 'D', 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_NULL(r);
+
+ // clang-format off
+ uint8_t expected[] = {
+ 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
+ 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
+ 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
+ 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
+ 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 40, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
+ FAIL;
+ }
+
+ DefragDestroy();
+ PASS;
+}
+
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ /* Packet 1: off=16, mf=1 */
+ packets[0] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
+
+ /* Packet 2: off=8, mf=1 */
+ packets[1] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16);
+
+ /* Packet 3: off=0, mf=1: IP and ICMP header. */
+ packets[2] = BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
+
+ /* Packet 4: off=8, mf=1 */
+ packets[3] =
+ BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 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_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ // AACCBBDD
+ // AACCDDBB
+ // AABBDDCC
+ // DDCCBBAA
+ 'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
+ 'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
+ 'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
+ 'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
+ };
+ // clang-format on
+
+ FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 20 + 8, sizeof(expected)) != 0);
+
+ DefragDestroy();
+ PASS;
+}
+
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[4];
+
+ /* Packet 1: off=16, mf=1 */
+ packets[0] = BuildIpv6TestPacketWithContent(
+ IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
+
+ /* Packet 2: off=8, mf=1 */
+ packets[1] = BuildIpv6TestPacketWithContent(
+ IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16);
+
+ /* Packet 3: off=0, mf=1: IP and ICMP header. */
+ packets[2] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
+
+ /* Packet 4: off=8, mf=1 */
+ packets[3] =
+ BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 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_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ // AACCBBDD
+ // AACCDDBB
+ // AABBDDCC
+ // DDCCBBAA
+ 'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
+ 'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
+ 'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
+ 'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
+ };
+ // clang-format on
+
+ FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 40 + 8, sizeof(expected)) != 0);
+
+ DefragDestroy();
+ PASS;
+}
+
+/**
+ * #### Input
+ *
+ * | 96 (0) | 104 (8) | 112 (16) | 120 (24) |
+ * |----------|----------|----------|----------|
+ * | | EEEEEEEE | EEEEEEEE | EEEEEEEE |
+ * | MMMMMMMM | MMMMMMMM | MMMMMMMM | |
+ *
+ * #### Expected Output
+ *
+ * | MMMMMMMM | MMMMMMMM | MMMMMMMM | EEEEEEEE |
+ */
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[2];
+
+ packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
+ packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
+ FAIL;
+ }
+
+ PASS;
+}
+
+static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(void)
+{
+ DefragInit();
+ default_policy = DEFRAG_POLICY_BSD;
+ Packet *packets[2];
+
+ packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
+ packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
+
+ Packet *r = Defrag(NULL, NULL, packets[0]);
+ FAIL_IF_NOT_NULL(r);
+
+ r = Defrag(NULL, NULL, packets[1]);
+ FAIL_IF_NULL(r);
+
+ // clang-format off
+ const uint8_t expected[] = {
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
+ 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
+ };
+ // clang-format on
+
+ if (memcmp(expected, GET_PKT_DATA(r) + 40, sizeof(expected)) != 0) {
+ printf("Expected:\n");
+ PrintRawDataFp(stdout, expected, sizeof(expected));
+ printf("Got:\n");
+ PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
+ FAIL;
+ }
+
+ 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];
+
+ packets[0] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
+
+ packets[1] =
+ BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8);
+
+ packets[2] = BuildIpv4TestPacketWithContent(
+ IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16);
+
+ /* ICMP header. */
+ packets[3] = BuildIpv4TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
+
+ packets[4] =
+ BuildIpv4TestPacketWithContent(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)
@@ -2527,23 +3138,17 @@ void DefragRegisterTests(void)
UtRegisterTest("DefragSturgesNovakFirstTest", DefragSturgesNovakFirstTest);
UtRegisterTest("DefragSturgesNovakLastTest", DefragSturgesNovakLastTest);
- UtRegisterTest("DefragIPv4NoDataTest", DefragIPv4NoDataTest);
- UtRegisterTest("DefragIPv4TooLargeTest", DefragIPv4TooLargeTest);
-
- UtRegisterTest("IPV6DefragInOrderSimpleTest", IPV6DefragInOrderSimpleTest);
- UtRegisterTest("IPV6DefragReverseSimpleTest", IPV6DefragReverseSimpleTest);
- UtRegisterTest("IPV6DefragSturgesNovakBsdTest",
- IPV6DefragSturgesNovakBsdTest);
- UtRegisterTest("IPV6DefragSturgesNovakLinuxTest",
- IPV6DefragSturgesNovakLinuxTest);
- UtRegisterTest("IPV6DefragSturgesNovakWindowsTest",
- IPV6DefragSturgesNovakWindowsTest);
- UtRegisterTest("IPV6DefragSturgesNovakSolarisTest",
- IPV6DefragSturgesNovakSolarisTest);
- UtRegisterTest("IPV6DefragSturgesNovakFirstTest",
- IPV6DefragSturgesNovakFirstTest);
- UtRegisterTest("IPV6DefragSturgesNovakLastTest",
- IPV6DefragSturgesNovakLastTest);
+ UtRegisterTest("DefragNoDataIpv4Test", DefragNoDataIpv4Test);
+ UtRegisterTest("DefragTooLargeIpv4Test", DefragTooLargeIpv4Test);
+
+ UtRegisterTest("DefragInOrderSimpleIpv6Test", DefragInOrderSimpleIpv6Test);
+ UtRegisterTest("DefragReverseSimpleIpv6Test", DefragReverseSimpleIpv6Test);
+ UtRegisterTest("DefragSturgesNovakBsdIpv6Test", DefragSturgesNovakBsdIpv6Test);
+ UtRegisterTest("DefragSturgesNovakLinuxIpv6Test", DefragSturgesNovakLinuxIpv6Test);
+ UtRegisterTest("DefragSturgesNovakWindowsIpv6Test", DefragSturgesNovakWindowsIpv6Test);
+ UtRegisterTest("DefragSturgesNovakSolarisIpv6Test", DefragSturgesNovakSolarisIpv6Test);
+ UtRegisterTest("DefragSturgesNovakFirstIpv6Test", DefragSturgesNovakFirstIpv6Test);
+ UtRegisterTest("DefragSturgesNovakLastIpv6Test", DefragSturgesNovakLastIpv6Test);
UtRegisterTest("DefragVlanTest", DefragVlanTest);
UtRegisterTest("DefragVlanQinQTest", DefragVlanQinQTest);
@@ -2555,5 +3160,16 @@ void DefragRegisterTests(void)
UtRegisterTest("DefragTestBadProto", DefragTestBadProto);
UtRegisterTest("DefragTestJeremyLinux", DefragTestJeremyLinux);
+
+ UtRegisterTest("DefragBsdFragmentAfterNoMfIpv4Test", DefragBsdFragmentAfterNoMfIpv4Test);
+ UtRegisterTest("DefragBsdFragmentAfterNoMfIpv6Test", DefragBsdFragmentAfterNoMfIpv6Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test",
+ DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2", DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
+ UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2", DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
+ UtRegisterTest("DefragBsdMissingFragmentIpv4Test", DefragBsdMissingFragmentIpv4Test);
+ UtRegisterTest("DefragBsdMissingFragmentIpv6Test", DefragBsdMissingFragmentIpv6Test);
#endif /* UNITTESTS */
}