diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-24 01:56:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-24 01:56:35 +0000 |
commit | ea7b101b409c45955f5d5446bb3bfdf7758b9226 (patch) | |
tree | aca5d4fbf94bc524c392a5dd9cf4571f3a29ccb8 /src/defrag.c | |
parent | Adding upstream version 1:7.0.4. (diff) | |
download | suricata-ea7b101b409c45955f5d5446bb3bfdf7758b9226.tar.xz suricata-ea7b101b409c45955f5d5446bb3bfdf7758b9226.zip |
Adding upstream version 1:7.0.5.upstream/1%7.0.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/defrag.c')
-rw-r--r-- | src/defrag.c | 1620 |
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 */ } |