From 0d92f0018bd510e2120eef0550b1601462d98453 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Tue, 15 Dec 2009 23:45:15 -0800 Subject: [PATCH] First cut at IPv6 re-assembly. Only BSD policy for now, packets don't actually get passed to it yet though. --- src/decode-ipv6.c | 11 + src/defrag.c | 623 +++++++++++++++++++++++++++++++++++++++++++--- src/defrag.h | 2 +- 3 files changed, 598 insertions(+), 38 deletions(-) diff --git a/src/decode-ipv6.c b/src/decode-ipv6.c index 9e57dab909..082258dae1 100644 --- a/src/decode-ipv6.c +++ b/src/decode-ipv6.c @@ -5,6 +5,7 @@ #include "decode-ipv6.h" #include "decode-icmpv6.h" #include "decode-events.h" +#include "defrag.h" #include "util-debug.h" #define IPV6_EXTHDRS ip6eh.ip6_exthdrs @@ -406,6 +407,16 @@ void DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, uint8_t *pkt, break; } +#if 0 + /* Pass to defragger if a fragment. */ + if (IPV6_EXTHDR_ISSET_FH(p)) { + Packet *rp = Defrag6(tv, NULL, p); + if (rp != NULL) { + /* Reinject. */ + } + } +#endif + #ifdef DEBUG if (IPV6_EXTHDR_ISSET_FH(p)) { printf("IPV6 FRAG - HDRLEN: %" PRIuMAX " NH: %" PRIu32 " OFFSET: %" PRIu32 " ID: %" PRIu32 "\n", diff --git a/src/defrag.c b/src/defrag.c index 325b37fc5a..7224a46453 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -23,6 +23,7 @@ #include "eidps.h" #include "threads.h" #include "conf.h" +#include "decode-ipv6.h" #include "util-hashlist.h" #include "util-pool.h" #include "util-print.h" @@ -105,8 +106,21 @@ typedef struct _frag { uint8_t more_frags; /**< More frags? */ + uint16_t ipv6_hdr_offset; /**< Offset in the packet where the IPv6 + * header starts. */ + uint16_t frag_hdr_offset; /**< Offset in the packet where the frag + * header starts. */ + + uint16_t data_offset; /**< Offset to the packet data. */ + uint16_t data_len; /**< Length of data. */ + uint8_t *pkt; /**< The actual packet. */ + uint16_t ltrim; /**< Number of leading bytes to trim when + * re-assembling the packet. */ + + int8_t skip; /**< Skip this fragment during re-assembly. */ + TAILQ_ENTRY(_frag) next; /**< Pointer to next fragment for tailq. */ } Frag; @@ -163,7 +177,8 @@ DumpFrags(DefragTracker *tracker) printf("Dumping frags for packet: ID=%d\n", tracker->id); TAILQ_FOREACH(frag, &tracker->frags, next) { - printf("-> Frag: Offset=%d, Len=%d\n", frag->offset, frag->len); + printf("-> Frag: frag_offset=%d, frag_len=%d, data_len=%d\n", + frag->offset, frag->len, frag->data_len); PrintRawDataFp(stdout, frag->pkt, frag->len); } } @@ -660,6 +675,112 @@ done: SCMutexUnlock(&tracker->lock); } +static void +Defrag6InsertFrag(DefragContext *dc, DefragTracker *tracker, Packet *p) +{ + int ltrim = 0; + + /* We don't multiple by 8 here as this macro returns the value + * unshifted, which means its already the real offset. */ + uint16_t frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p); + + /* This is the offset of the start of the data in the packet that + * falls after the fragmentation header. */ + uint16_t data_offset = (uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr) - + p->pkt; + + /* The length of the (fragmented) data. This is the length of the + * data that falls after the fragmentation header. */ + uint16_t data_len = IPV6_GET_PLEN(p) - ( + ((uint8_t *)p->ip6eh.ip6fh + sizeof(IPV6FragHdr)) - + ((uint8_t *)p->ip6h + sizeof(IPV6Hdr))); + + /* Where the fragment ends. */ + uint16_t frag_end = frag_offset + data_len; + + /* Offset in the packet to the IPv6 header. */ + uint16_t ipv6_hdr_offset = (uint8_t *)p->ip6h - p->pkt; + + /* Offset in the packet to the IPv6 frag header. */ + uint16_t frag_hdr_offset = (uint8_t *)p->ip6eh.ip6fh - p->pkt; + + /* Lock this tracker as we'll be doing list operations on it. */ + SCMutexLock(&tracker->lock); + + /* Update timeout. */ + tracker->timeout = p->ts; + tracker->timeout.tv_sec += dc->timeout; + + Frag *prev, *next;; + if (!TAILQ_EMPTY(&tracker->frags)) { + TAILQ_FOREACH(prev, &tracker->frags, next) { + ltrim = 0; + next = TAILQ_NEXT(prev, next); + + switch (tracker->policy) { + case POLICY_BSD: + if (frag_offset < prev->offset + prev->data_len) { + if (frag_offset >= prev->offset) { + ltrim = prev->offset + prev->data_len - frag_offset; + } + if ((next != NULL) && (frag_end > next->offset)) { + next->ltrim = frag_end - next->offset; + } + else if ((frag_offset < prev->offset) && + (frag_end >= prev->offset + prev->data_len)) { + prev->skip = 1; + } + goto insert; + } + break; + default: + break; + } + } + } +insert: + + if (data_len - ltrim <= 0) { + goto done; + } + + /* Allocate fragment and insert. */ + SCMutexLock(&dc->frag_pool_lock); + Frag *new = PoolGet(dc->frag_pool); + SCMutexUnlock(&dc->frag_pool_lock); + if (new == NULL) + goto done; + new->pkt = malloc(p->pktlen); + if (new->pkt == NULL) { + SCMutexLock(&dc->frag_pool_lock); + PoolReturn(dc->frag_pool, new); + SCMutexUnlock(&dc->frag_pool_lock); + goto done; + } + memcpy(new->pkt, p->pkt + ltrim, p->pktlen - ltrim); + new->len = p->pktlen - ltrim; + new->offset = frag_offset + ltrim; + new->data_offset = data_offset; + new->data_len = data_len - ltrim; + new->ipv6_hdr_offset = ipv6_hdr_offset; + new->frag_hdr_offset = frag_hdr_offset; + + Frag *frag; + TAILQ_FOREACH(frag, &tracker->frags, next) { + if (frag_offset < frag->offset) + break; + } + if (frag == NULL) { + TAILQ_INSERT_TAIL(&tracker->frags, new, next); + } + else { + TAILQ_INSERT_BEFORE(frag, new, next); + } + +done: + SCMutexUnlock(&tracker->lock); +} + /** * Attempt to re-assemble a packet. * @@ -795,6 +916,112 @@ done: return rp; } +static Packet * +Defrag6Reassemble(ThreadVars *tv, DefragContext *dc, DefragTracker *tracker, + Packet *p) +{ + Packet *rp = NULL; + + /* Should not be here unless we have seen the last fragment. */ + if (!tracker->seen_last) + return NULL; + + /* Lock the tracker. */ + SCMutexLock(&tracker->lock); + + /* Check that we have all the data. Relies on the fact that + * fragments are inserted if frag_offset order. */ + Frag *frag; + int len = 0; + TAILQ_FOREACH(frag, &tracker->frags, next) { + if (frag->skip) + continue; + + if (frag == TAILQ_FIRST(&tracker->frags)) { + if (frag->offset != 0) { + printf("Defrag6Reassemble: no offset 0\n"); + goto done; + } + len = frag->data_len; + } + else { + if (frag->offset > len) { + /* This fragment starts after the end of the previous + * fragment. We have a hole. */ + printf("Defrag6Reassemble: hole: offset=%d, len=%d\n", + frag->offset, len); + goto done; + } + else { + len += frag->data_len; + } + } + } + + /* Allocate a Packet for the reassembled packet. On failure we + * free all the resources held by this tracker. */ + if (tv == NULL) { + /* Unit test. */ + rp = SetupPkt(); + } + else { + /* Not really a tunnel packet, but more of a pseudo packet. + * But for the most part we should get the same result. */ + rp = TunnelPktSetup(tv, NULL, p, (uint8_t *)p->ip6h, + IPV6_GET_PLEN(p) + sizeof(IPV6Hdr), 0); + } + if (rp == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Failed to allocate packet for fragmentation re-assembly, dumping fragments."); + SCMutexLock(&dc->frag_table_lock); + HashListTableRemove(dc->frag_table, tracker, sizeof(tracker)); + SCMutexUnlock(&dc->frag_table_lock); + DefragTrackerReset(tracker); + SCMutexLock(&dc->tracker_pool_lock); + PoolReturn(dc->tracker_pool, tracker); + SCMutexUnlock(&dc->tracker_pool_lock); + goto done; + } + + int payload_len = 0; + int fragmentable_offset = 0; + int pktlen = 0; + TAILQ_FOREACH(frag, &tracker->frags, next) { + if (frag->skip) + continue; + if (frag->offset == 0) { + /* This is the first packet, we use this packets link and + * IPv6 headers. We also copy in its data, but remove the + * fragmentation header. */ + memcpy(rp->pkt, frag->pkt, frag->frag_hdr_offset); + memcpy(rp->pkt + frag->frag_hdr_offset, + frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr), + frag->data_len); + rp->ip6h = (IPV6Hdr *)(rp->pkt + frag->ipv6_hdr_offset); + payload_len = ntohs(rp->ip6h->s_ip6_plen) - sizeof(IPV6FragHdr); + + /* This is the start of the fragmentable portion of the + * first packet. All fragment offsets are relative to + * this. */ + fragmentable_offset = frag->frag_hdr_offset; + + pktlen = frag->ipv6_hdr_offset + sizeof(IPV6Hdr); + } + else { + memcpy(rp->pkt + fragmentable_offset + frag->offset + frag->ltrim, + frag->pkt + frag->data_offset, frag->data_len - frag->ltrim); + payload_len += frag->data_len - frag->ltrim; + } + } + BUG_ON(rp->ip6h == NULL); + rp->ip6h->s_ip6_plen = htons(payload_len); + rp->pktlen = pktlen + payload_len; + +done: + SCMutexUnlock(&tracker->lock); + return rp; +} + + /** * \brief Timeout a tracker. * @@ -829,6 +1056,52 @@ DefragTimeoutTracker(DefragContext *dc, Packet *p) } } +DefragTracker * +DefragGetTracker(DefragContext *dc, DefragTracker *lookup_key, Packet *p) +{ + DefragTracker *tracker; + + SCMutexLock(&dc->frag_table_lock); + tracker = HashListTableLookup(dc->frag_table, lookup_key, + sizeof(*lookup_key)); + SCMutexUnlock(&dc->frag_table_lock); + if (tracker == NULL) { + SCMutexLock(&dc->tracker_pool_lock); + tracker = PoolGet(dc->tracker_pool); + if (tracker == NULL) { + /* Timeout trackers and try again. */ + DefragTimeoutTracker(dc, p); + tracker = PoolGet(dc->tracker_pool); + } + SCMutexUnlock(&dc->tracker_pool_lock); + if (tracker == NULL) { + /* Report memory error - actually a pool allocation error. */ + SCLogError(SC_ERR_MEM_ALLOC, "Defrag: Failed to allocate tracker."); + return NULL; + } + DefragTrackerReset(tracker); + tracker->family = lookup_key->family; + tracker->id = lookup_key->id; + tracker->src_addr = lookup_key->src_addr; + tracker->dst_addr = lookup_key->dst_addr; + + /* XXX Do policy lookup. */ + tracker->policy = dc->default_policy; + + SCMutexLock(&dc->frag_table_lock); + if (HashListTableAdd(dc->frag_table, tracker, sizeof(*tracker)) != 0) { + /* Failed to add new tracker. */ + SCMutexUnlock(&dc->frag_table_lock); + SCLogError(SC_ERR_MEM_ALLOC, + "Defrag: Failed to add new tracker to hash table."); + return NULL; + } + SCMutexUnlock(&dc->frag_table_lock); + } + + return tracker; +} + /** * \brief Entry point for IPv4 fragments. * @@ -864,42 +1137,10 @@ Defrag4(ThreadVars *tv, DefragContext *dc, Packet *p) lookup.id = IPV4_GET_IPID(p); lookup.src_addr = p->src; lookup.dst_addr = p->dst; - SCMutexLock(&dc->frag_table_lock); - tracker = HashListTableLookup(dc->frag_table, &lookup, sizeof(lookup)); - SCMutexUnlock(&dc->frag_table_lock); - if (tracker == NULL) { - SCMutexLock(&dc->tracker_pool_lock); - tracker = PoolGet(dc->tracker_pool); - if (tracker == NULL) { - /* Timeout trackers and try again. */ - DefragTimeoutTracker(dc, p); - tracker = PoolGet(dc->tracker_pool); - } - SCMutexUnlock(&dc->tracker_pool_lock); - if (tracker == NULL) { - /* Report memory error - actually a pool allocation error. */ - SCLogError(SC_ERR_MEM_ALLOC, "Defrag: Failed to allocate tracker."); - return NULL; - } - DefragTrackerReset(tracker); - tracker->family = lookup.family; - tracker->id = lookup.id; - tracker->src_addr = lookup.src_addr; - tracker->dst_addr = lookup.dst_addr; - /* XXX Do policy lookup. */ - tracker->policy = dc->default_policy; - - SCMutexLock(&dc->frag_table_lock); - if (HashListTableAdd(dc->frag_table, tracker, sizeof(*tracker)) != 0) { - /* Failed to add new tracker. */ - SCMutexUnlock(&dc->frag_table_lock); - SCLogError(SC_ERR_MEM_ALLOC, - "Defrag: Failed to add new tracker to hash table."); - return NULL; - } - SCMutexUnlock(&dc->frag_table_lock); - } + tracker = DefragGetTracker(dc, &lookup, p); + if (tracker == NULL) + return NULL; if (!more_frags) { tracker->seen_last = 1; @@ -925,13 +1166,42 @@ Defrag4(ThreadVars *tv, DefragContext *dc, Packet *p) * NULL is returned. */ Packet * -Defrag6(DefragContext *dc, Packet *p) +Defrag6(ThreadVars *tv, DefragContext *dc, Packet *p) { + uint16_t frag_offset; + uint8_t more_frags; + uint32_t id; + DefragTracker *tracker, lookup; + /* If no DefragContext was passed in, use the global one. Passing * one in is primarily useful for unit tests. */ if (dc == NULL) dc = defrag_context; + frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p); + more_frags = IPV6_EXTHDR_GET_FH_FLAG(p); + id = IPV6_EXTHDR_GET_FH_ID(p); + + /* Create a lookup key. */ + lookup.family = AF_INET6; + lookup.id = id; + lookup.src_addr = p->src; + lookup.dst_addr = p->dst; + + tracker = DefragGetTracker(dc, &lookup, p); + if (tracker == NULL) + return NULL; + + if (!more_frags) { + tracker->seen_last = 1; + } + Defrag6InsertFrag(dc, tracker, p); + if (tracker->seen_last) { + Packet *rp = Defrag6Reassemble(tv, dc, tracker, p); + return rp; + } + + return NULL; } @@ -1023,6 +1293,64 @@ error: return NULL; } +static Packet * +IPV6BuildTestPacket(uint32_t id, uint16_t off, int mf, const char content, + int content_len) +{ + Packet *p = NULL; + + p = calloc(1, sizeof(*p)); + if (p == NULL) + return NULL; + gettimeofday(&p->ts, NULL); + + p->ip6h = (IPV6Hdr *)p->pkt; + IPV6_SET_RAW_VER(p->ip6h, 6); + p->ip6h->s_ip6_nxt = 44; + p->ip6h->s_ip6_hlim = 2; + + /* Source and dest address - very bogus addresses. */ + p->ip6h->ip6_src[0] = 0x01010101; + p->ip6h->ip6_src[1] = 0x01010101; + p->ip6h->ip6_src[2] = 0x01010101; + p->ip6h->ip6_src[3] = 0x01010101; + p->ip6h->ip6_dst[0] = 0x02020202; + p->ip6h->ip6_dst[1] = 0x02020202; + p->ip6h->ip6_dst[2] = 0x02020202; + p->ip6h->ip6_dst[3] = 0x02020202; + + /* Fragmentation header. */ + p->ip6eh.ip6fh = (IPV6FragHdr *)(p->pkt + sizeof(IPV6Hdr)); + p->ip6eh.ip6fh->ip6fh_nxt = IPPROTO_ICMP; + p->ip6eh.ip6fh->ip6fh_ident = htonl(id); + p->ip6eh.ip6fh->ip6fh_offlg = htons((off << 3) | mf); + + memset(p->pkt + sizeof(IPV6Hdr) + sizeof(IPV6FragHdr), content, + content_len); + p->pktlen = 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. */ + IPV6_CACHE_INIT(p); + 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: + fprintf(stderr, "Error building test packet.\n"); + if (p != NULL) + free(p); + return NULL; +} + /** * Test the simplest possible re-assembly scenario. All packet in * order and no overlaps. @@ -1096,6 +1424,79 @@ end: return ret; } +/** + * Test the simplest possible re-assembly scenario. All packet in + * order and no overlaps. + */ +static int +IPV6DefragInOrderSimpleTest(void) +{ + DefragContext *dc = NULL; + Packet *p1 = NULL, *p2 = NULL, *p3 = NULL; + Packet *reassembled = NULL; + int id = 12; + int i; + int ret = 0; + + DefragInit(); + + dc = DefragContextNew(); + if (dc == NULL) + goto end; + + p1 = IPV6BuildTestPacket(id, 0, 1, 'A', 8); + if (p1 == NULL) + goto end; + p2 = IPV6BuildTestPacket(id, 1, 1, 'B', 8); + if (p2 == NULL) + goto end; + p3 = IPV6BuildTestPacket(id, 2, 0, 'C', 3); + if (p3 == NULL) + goto end; + + if (Defrag6(NULL, dc, p1) != NULL) + goto end; + if (Defrag6(NULL, dc, p2) != NULL) + goto end; + reassembled = Defrag6(NULL, dc, p3); + if (reassembled == NULL) + goto end; + + /* 40 bytes in we should find 8 bytes of A. */ + for (i = 40; i < 40 + 8; i++) { + if (reassembled->pkt[i] != 'A') + goto end; + } + + /* 28 bytes in we should find 8 bytes of B. */ + for (i = 48; i < 48 + 8; i++) { + if (reassembled->pkt[i] != 'B') + goto end; + } + + /* And 36 bytes in we should find 3 bytes of C. */ + for (i = 56; i < 56 + 3; i++) { + if (reassembled->pkt[i] != 'C') + goto end; + } + + ret = 1; +end: + if (dc != NULL) + DefragContextDestroy(dc); + if (p1 != NULL) + free(p1); + if (p2 != NULL) + free(p2); + if (p3 != NULL) + free(p3); + if (reassembled != NULL) + free(reassembled); + + DefragDestroy(); + return ret; +} + static int DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len) { @@ -1205,6 +1606,115 @@ end: return ret; } +static int +IPV6DefragDoSturgesNovakTest(int policy, u_char *expected, size_t expected_len) +{ + int i; + int ret = 0; + DefragContext *dc = NULL; + + DefragInit(); + + /* + * Build the packets. + */ + + int id = 1; + Packet *packets[17]; + memset(packets, 0x00, sizeof(packets)); + + /* + * Original fragments. + */ + + /* A*24 at 0. */ + packets[0] = IPV6BuildTestPacket(id, 0, 1, 'A', 24); + + /* B*15 at 32. */ + packets[1] = IPV6BuildTestPacket(id, 32 >> 3, 1, 'B', 16); + + /* C*24 at 48. */ + packets[2] = IPV6BuildTestPacket(id, 48 >> 3, 1, 'C', 24); + + /* D*8 at 80. */ + packets[3] = IPV6BuildTestPacket(id, 80 >> 3, 1, 'D', 8); + + /* E*16 at 104. */ + packets[4] = IPV6BuildTestPacket(id, 104 >> 3, 1, 'E', 16); + + /* F*24 at 120. */ + packets[5] = IPV6BuildTestPacket(id, 120 >> 3, 1, 'F', 24); + + /* G*16 at 144. */ + packets[6] = IPV6BuildTestPacket(id, 144 >> 3, 1, 'G', 16); + + /* H*16 at 160. */ + packets[7] = IPV6BuildTestPacket(id, 160 >> 3, 1, 'H', 16); + + /* I*8 at 176. */ + packets[8] = IPV6BuildTestPacket(id, 176 >> 3, 1, 'I', 8); + + /* + * Overlapping subsequent fragments. + */ + + /* J*32 at 8. */ + packets[9] = IPV6BuildTestPacket(id, 8 >> 3, 1, 'J', 32); + + /* K*24 at 48. */ + packets[10] = IPV6BuildTestPacket(id, 48 >> 3, 1, 'K', 24); + + /* L*24 at 72. */ + packets[11] = IPV6BuildTestPacket(id, 72 >> 3, 1, 'L', 24); + + /* M*24 at 96. */ + packets[12] = IPV6BuildTestPacket(id, 96 >> 3, 1, 'M', 24); + + /* N*8 at 128. */ + packets[13] = IPV6BuildTestPacket(id, 128 >> 3, 1, 'N', 8); + + /* O*8 at 152. */ + packets[14] = IPV6BuildTestPacket(id, 152 >> 3, 1, 'O', 8); + + /* P*8 at 160. */ + packets[15] = IPV6BuildTestPacket(id, 160 >> 3, 1, 'P', 8); + + /* Q*16 at 176. */ + packets[16] = IPV6BuildTestPacket(id, 176 >> 3, 0, 'Q', 16); + + dc = DefragContextNew(); + if (dc == NULL) + goto end; + dc->default_policy = policy; + + /* Send all but the last. */ + for (i = 0; i < 16; i++) { + Packet *tp = Defrag6(NULL, dc, packets[i]); + if (tp != NULL) { + free(tp); + goto end; + } + } + + /* And now the last one. */ + Packet *reassembled = Defrag6(NULL, dc, packets[16]); + if (reassembled == NULL) + goto end; + if (memcmp(reassembled->pkt + 40, expected, expected_len) != 0) + goto end; + free(reassembled); + + ret = 1; +end: + if (dc != NULL) + DefragContextDestroy(dc); + for (i = 0; i < 17; i++) { + free(packets[i]); + } + DefragDestroy(); + return ret; +} + static int DefragSturgesNovakBsdTest(void) { @@ -1239,6 +1749,40 @@ DefragSturgesNovakBsdTest(void) return DefragDoSturgesNovakTest(POLICY_BSD, expected, sizeof(expected)); } +static int +IPV6DefragSturgesNovakBsdTest(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" + }; + + return IPV6DefragDoSturgesNovakTest(POLICY_BSD, expected, sizeof(expected)); +} + static int DefragSturgesNovakLinuxTest(void) { @@ -1506,6 +2050,11 @@ DefragRegisterTests(void) DefragSturgesNovakLastTest, 1); UtRegisterTest("DefragTimeoutTest", DefragTimeoutTest, 1); + + UtRegisterTest("IPV6DefragInOrderSimpleTest", + IPV6DefragInOrderSimpleTest, 1); + UtRegisterTest("IPV6DefragSturgesNovakBsdTest", + IPV6DefragSturgesNovakBsdTest, 1); #endif /* UNITTESTS */ } diff --git a/src/defrag.h b/src/defrag.h index d732751a7b..d65f86d655 100644 --- a/src/defrag.h +++ b/src/defrag.h @@ -15,7 +15,7 @@ typedef struct _DefragContext DefragContext; void DefragInit(void); Packet *Defrag4(ThreadVars *, DefragContext *, Packet *); -Packet *Defrag6(DefragContext *, Packet *); +Packet *Defrag6(ThreadVars *, DefragContext *, Packet *); void DefragRegisterTests(void); #endif /* __DEFRAG_H__ */