suricata
defrag.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2024 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Endace Technology Limited, Jason Ish <jason.ish@endace.com>
22  *
23  * Defragmentation module.
24  * References:
25  * - RFC 815
26  * - OpenBSD PF's IP normalization (pf_norm.c)
27  *
28  * \todo pool for frag packet storage
29  * \todo policy bsd-right
30  * \todo profile hash function
31  * \todo log anomalies
32  */
33 
34 #include "suricata-common.h"
35 
36 #include "queue.h"
37 
38 #include "suricata.h"
39 #include "threads.h"
40 #include "conf.h"
41 #include "decode-ipv6.h"
42 #include "util-hashlist.h"
43 #include "util-pool.h"
44 #include "util-time.h"
45 #include "util-print.h"
46 #include "util-debug.h"
47 #include "util-fix_checksum.h"
48 #include "util-random.h"
49 #include "stream-tcp-private.h"
50 #include "stream-tcp-reassemble.h"
51 #include "util-host-os-info.h"
52 #include "util-validate.h"
53 
54 #include "defrag.h"
55 #include "defrag-hash.h"
56 #include "defrag-config.h"
57 
58 #include "tmqh-packetpool.h"
59 #include "decode.h"
60 
61 #ifdef UNITTESTS
62 #include "util-unittest.h"
63 #endif
64 
65 #define DEFAULT_DEFRAG_HASH_SIZE 0xffff
66 #define DEFAULT_DEFRAG_POOL_SIZE 0xffff
67 
68 /**
69  * Default timeout (in seconds) before a defragmentation tracker will
70  * be released.
71  */
72 #define TIMEOUT_DEFAULT 60
73 
74 /**
75  * Maximum allowed timeout, 24 hours.
76  */
77 #define TIMEOUT_MAX (60 * 60 * 24)
78 
79 /**
80  * Minimum allowed timeout, 1 second.
81  */
82 #define TIMEOUT_MIN 1
83 
84 /** Fragment reassembly policies. */
93 
95 };
96 
97 static uint8_t default_policy = DEFRAG_POLICY_BSD;
98 
99 /** The global DefragContext so all threads operate from the same
100  * context. */
101 static DefragContext *defrag_context;
102 
104 
105 /**
106  * \brief Reset a frag for reuse in a pool.
107  */
108 static void
109 DefragFragReset(Frag *frag)
110 {
111  if (frag->pkt != NULL)
112  SCFree(frag->pkt);
113  memset(frag, 0, sizeof(*frag));
114 }
115 
116 /**
117  * \brief Allocate a new frag for use in a pool.
118  */
119 static int
120 DefragFragInit(void *data, void *initdata)
121 {
122  Frag *frag = data;
123 
124  memset(frag, 0, sizeof(*frag));
125  return 1;
126 }
127 
128 /**
129  * \brief Free all frags associated with a tracker.
130  */
131 void
133 {
134  Frag *frag, *tmp;
135 
136  /* Lock the frag pool as we'll be return items to it. */
137  SCMutexLock(&defrag_context->frag_pool_lock);
138 
139  RB_FOREACH_SAFE(frag, IP_FRAGMENTS, &tracker->fragment_tree, tmp) {
140  RB_REMOVE(IP_FRAGMENTS, &tracker->fragment_tree, frag);
141  DefragFragReset(frag);
142  PoolReturn(defrag_context->frag_pool, frag);
143  }
144 
145  SCMutexUnlock(&defrag_context->frag_pool_lock);
146 }
147 
148 /**
149  * \brief Create a new DefragContext.
150  *
151  * \retval On success a return an initialized DefragContext, otherwise
152  * NULL will be returned.
153  */
154 static DefragContext *
155 DefragContextNew(void)
156 {
157  DefragContext *dc;
158 
159  dc = SCCalloc(1, sizeof(*dc));
160  if (unlikely(dc == NULL))
161  return NULL;
162 
163  /* Initialize the pool of trackers. */
164  intmax_t tracker_pool_size;
165  if (!SCConfGetInt("defrag.trackers", &tracker_pool_size) || tracker_pool_size == 0) {
166  tracker_pool_size = DEFAULT_DEFRAG_HASH_SIZE;
167  }
168 
169  /* Initialize the pool of frags. */
170  intmax_t frag_pool_size;
171  if (!SCConfGetInt("defrag.max-frags", &frag_pool_size) || frag_pool_size == 0 ||
172  frag_pool_size > UINT32_MAX) {
173  frag_pool_size = DEFAULT_DEFRAG_POOL_SIZE;
174  }
175  uint32_t frag_pool_prealloc = (uint32_t)frag_pool_size / 2;
176  dc->frag_pool = PoolInit((uint32_t)frag_pool_size, frag_pool_prealloc, sizeof(Frag), NULL,
177  DefragFragInit, dc, NULL, NULL);
178  if (dc->frag_pool == NULL) {
179  FatalError("Defrag: Failed to initialize fragment pool.");
180  }
181  if (SCMutexInit(&dc->frag_pool_lock, NULL) != 0) {
182  FatalError("Defrag: Failed to initialize frag pool mutex.");
183  }
184 
185  /* Set the default timeout. */
186  intmax_t timeout;
187  if (!SCConfGetInt("defrag.timeout", &timeout)) {
188  dc->timeout = TIMEOUT_DEFAULT;
189  } else {
190  if (timeout < TIMEOUT_MIN) {
191  FatalError("defrag: Timeout less than minimum allowed value.");
192  }
193  else if (timeout > TIMEOUT_MAX) {
194  FatalError("defrag: Timeout greater than maximum allowed value.");
195  }
196  dc->timeout = (uint32_t)timeout;
197  }
198 
199  SCLogDebug("Defrag Initialized:");
200  SCLogDebug("\tTimeout: %"PRIuMAX, (uintmax_t)dc->timeout);
201  SCLogDebug("\tMaximum defrag trackers: %"PRIuMAX, tracker_pool_size);
202  SCLogDebug("\tPreallocated defrag trackers: %"PRIuMAX, tracker_pool_size);
203  SCLogDebug("\tMaximum fragments: %"PRIuMAX, (uintmax_t)frag_pool_size);
204  SCLogDebug("\tPreallocated fragments: %"PRIuMAX, (uintmax_t)frag_pool_prealloc);
205 
206  return dc;
207 }
208 
209 static void
210 DefragContextDestroy(DefragContext *dc)
211 {
212  if (dc == NULL)
213  return;
214 
215  PoolFree(dc->frag_pool);
216  SCFree(dc);
217 }
218 
219 /**
220  * Attempt to re-assemble a packet.
221  *
222  * \param tracker The defragmentation tracker to reassemble from.
223  */
224 static Packet *
225 Defrag4Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
226 {
227  Packet *rp = NULL;
228 
229  /* Should not be here unless we have seen the last fragment. */
230  if (!tracker->seen_last) {
231  return NULL;
232  }
233 
234  /* Check that we have the first fragment and its of a valid size. */
235  Frag *first = RB_MIN(IP_FRAGMENTS, &tracker->fragment_tree);
236  if (first == NULL) {
237  goto done;
238  } else if (first->offset != 0) {
239  /* Still waiting for the first fragment. */
240  goto done;
241  } else if (first->len < sizeof(IPV4Hdr)) {
242  /* First fragment isn't enough for an IPv6 header. */
243  goto error_remove_tracker;
244  }
245 
246  /* Check that we have all the data. Relies on the fact that
247  * fragments are inserted in frag_offset order. */
248  Frag *frag = NULL;
249  size_t len = 0;
250  RB_FOREACH_FROM(frag, IP_FRAGMENTS, first) {
251  if (frag->offset > len) {
252  /* This fragment starts after the end of the previous
253  * fragment. We have a hole. */
254  goto done;
255  }
256  else {
257  /* Update the packet length to the largest known data offset. */
258  len = MAX(len, frag->offset + frag->data_len);
259  }
260  }
261 
262  const IPV4Hdr *oip4h = PacketGetIPv4(p);
263 
264  /* Allocate a Packet for the reassembled packet. On failure we
265  * SCFree all the resources held by this tracker. */
266  rp = PacketDefragPktSetup(p, NULL, 0, IPV4_GET_RAW_IPPROTO(oip4h));
267  if (rp == NULL) {
268  goto error_remove_tracker;
269  }
272  rp->datalink = tracker->datalink;
273 
274  int fragmentable_offset = 0;
275  uint16_t fragmentable_len = 0;
276  uint16_t hlen = 0;
277  int ip_hdr_offset = 0;
278 
279  /* Assume more frags. */
280  uint16_t prev_offset = 0;
281  bool more_frags = 1;
282 
283  RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
284  SCLogDebug("frag %p, data_len %u, offset %u, pcap_cnt %"PRIu64,
285  frag, frag->data_len, frag->offset, frag->pcap_cnt);
286 
287  /* Previous fragment has no more fragments, and this packet
288  * doesn't overlap. We're done. */
289  if (!more_frags && frag->offset > prev_offset) {
290  break;
291  }
292 
293  if (frag->skip)
294  continue;
295  if (frag->ltrim >= frag->data_len)
296  continue;
297  if (frag->offset == 0) {
298 
299  if (PacketCopyData(rp, frag->pkt, frag->len) == -1)
300  goto error_remove_tracker;
301 
302  hlen = frag->hlen;
303  ip_hdr_offset = tracker->ip_hdr_offset;
304 
305  /* This is the start of the fragmentable portion of the
306  * first packet. All fragment offsets are relative to
307  * this. */
308  fragmentable_offset = tracker->ip_hdr_offset + frag->hlen;
309  fragmentable_len = frag->data_len;
310  }
311  else {
312  int pkt_end = fragmentable_offset + frag->offset + frag->data_len;
313  if (pkt_end > (int)MAX_PAYLOAD_SIZE) {
314  SCLogDebug("Failed re-assemble "
315  "fragmented packet, exceeds size of packet buffer.");
316  goto error_remove_tracker;
317  }
318  if (PacketCopyDataOffset(rp,
319  fragmentable_offset + frag->offset + frag->ltrim,
320  frag->pkt + frag->data_offset + frag->ltrim,
321  frag->data_len - frag->ltrim) == -1) {
322  goto error_remove_tracker;
323  }
324  if (frag->offset > UINT16_MAX - frag->data_len) {
325  SCLogDebug("Failed re-assemble "
326  "fragmentable_len exceeds UINT16_MAX");
327  goto error_remove_tracker;
328  }
329  if (frag->offset + frag->data_len > fragmentable_len)
330  fragmentable_len = frag->offset + frag->data_len;
331  }
332 
333  /* Even if this fragment is flagged as having no more
334  * fragments, still continue. The next fragment may have the
335  * same offset with data that is preferred.
336  *
337  * For example, DefragBsdFragmentAfterNoMfIpv{4,6}Test
338  *
339  * This is due to not all fragments being completely trimmed,
340  * but relying on the copy ordering. */
341  more_frags = frag->more_frags;
342  prev_offset = frag->offset;
343  }
344 
345  SCLogDebug("ip_hdr_offset %u, hlen %" PRIu16 ", fragmentable_len %" PRIu16, ip_hdr_offset, hlen,
346  fragmentable_len);
347 
348  IPV4Hdr *ip4h = (IPV4Hdr *)(GET_PKT_DATA(rp) + ip_hdr_offset);
349  uint16_t old = ip4h->ip_len + ip4h->ip_off;
350  DEBUG_VALIDATE_BUG_ON(hlen > UINT16_MAX - fragmentable_len);
351  ip4h->ip_len = htons(fragmentable_len + hlen);
352  ip4h->ip_off = 0;
353  ip4h->ip_csum = FixChecksum(ip4h->ip_csum, old, ip4h->ip_len + ip4h->ip_off);
354  SET_PKT_LEN(rp, ip_hdr_offset + hlen + fragmentable_len);
355 
356  tracker->remove = 1;
357  DefragTrackerFreeFrags(tracker);
358 done:
359  return rp;
360 
361 error_remove_tracker:
362  tracker->remove = 1;
363  DefragTrackerFreeFrags(tracker);
364  if (rp != NULL)
366  return NULL;
367 }
368 
369 /**
370  * Attempt to re-assemble a packet.
371  *
372  * \param tracker The defragmentation tracker to reassemble from.
373  */
374 static Packet *
375 Defrag6Reassemble(ThreadVars *tv, DefragTracker *tracker, Packet *p)
376 {
377  Packet *rp = NULL;
378 
379  /* Should not be here unless we have seen the last fragment. */
380  if (!tracker->seen_last)
381  return NULL;
382 
383  /* Check that we have the first fragment and its of a valid size. */
384  Frag *first = RB_MIN(IP_FRAGMENTS, &tracker->fragment_tree);
385  if (first == NULL) {
386  goto done;
387  } else if (first->offset != 0) {
388  /* Still waiting for the first fragment. */
389  goto done;
390  } else if (first->len < sizeof(IPV6Hdr)) {
391  /* First fragment isn't enough for an IPv6 header. */
392  goto error_remove_tracker;
393  }
394 
395  /* Check that we have all the data. Relies on the fact that
396  * fragments are inserted if frag_offset order. */
397  size_t len = 0;
398  Frag *frag = NULL;
399  RB_FOREACH_FROM(frag, IP_FRAGMENTS, first) {
400  if (frag->skip) {
401  continue;
402  }
403 
404  if (frag == first) {
405  if (frag->offset != 0) {
406  goto done;
407  }
408  len = frag->data_len;
409  }
410  else {
411  if (frag->offset > len) {
412  /* This fragment starts after the end of the previous
413  * fragment. We have a hole. */
414  goto done;
415  }
416  else {
417  len = MAX(len, frag->offset + frag->data_len);
418  }
419  }
420  }
421 
422  const IPV6Hdr *oip6h = PacketGetIPv6(p);
423 
424  /* Allocate a Packet for the reassembled packet. On failure we
425  * SCFree all the resources held by this tracker. */
427  p, (const uint8_t *)oip6h, IPV6_GET_RAW_PLEN(oip6h) + sizeof(IPV6Hdr), 0);
428  if (rp == NULL) {
429  goto error_remove_tracker;
430  }
433  rp->datalink = tracker->datalink;
434 
435  uint16_t unfragmentable_len = 0;
436  int fragmentable_offset = 0;
437  uint16_t fragmentable_len = 0;
438  int ip_hdr_offset = 0;
439  uint8_t next_hdr = 0;
440 
441  /* Assume more frags. */
442  uint16_t prev_offset = 0;
443  bool more_frags = 1;
444 
445  RB_FOREACH(frag, IP_FRAGMENTS, &tracker->fragment_tree) {
446  if (!more_frags && frag->offset > prev_offset) {
447  break;
448  }
449  if (frag->skip)
450  continue;
451  if (frag->data_len - frag->ltrim <= 0)
452  continue;
453  if (frag->offset == 0) {
454  IPV6FragHdr *frag_hdr = (IPV6FragHdr *)(frag->pkt +
455  frag->frag_hdr_offset);
456  next_hdr = frag_hdr->ip6fh_nxt;
457 
458  /* This is the first packet, we use this packets link and
459  * IPv6 headers. We also copy in its data, but remove the
460  * fragmentation header. */
461  if (PacketCopyData(rp, frag->pkt, frag->frag_hdr_offset) == -1)
462  goto error_remove_tracker;
464  frag->pkt + frag->frag_hdr_offset + sizeof(IPV6FragHdr),
465  frag->data_len) == -1)
466  goto error_remove_tracker;
467  ip_hdr_offset = tracker->ip_hdr_offset;
468 
469  /* This is the start of the fragmentable portion of the
470  * first packet. All fragment offsets are relative to
471  * this. */
472  fragmentable_offset = frag->frag_hdr_offset;
473  fragmentable_len = frag->data_len;
474 
475  /* unfragmentable part is the part between the ipv6 header
476  * and the frag header. */
477  DEBUG_VALIDATE_BUG_ON(fragmentable_offset < ip_hdr_offset + IPV6_HEADER_LEN);
479  fragmentable_offset - ip_hdr_offset - IPV6_HEADER_LEN > UINT16_MAX);
480  unfragmentable_len = (uint16_t)(fragmentable_offset - ip_hdr_offset - IPV6_HEADER_LEN);
481  if (unfragmentable_len >= fragmentable_offset)
482  goto error_remove_tracker;
483  }
484  else {
485  if (PacketCopyDataOffset(rp, fragmentable_offset + frag->offset + frag->ltrim,
486  frag->pkt + frag->data_offset + frag->ltrim,
487  frag->data_len - frag->ltrim) == -1)
488  goto error_remove_tracker;
489  if (frag->offset + frag->data_len > fragmentable_len)
490  fragmentable_len = frag->offset + frag->data_len;
491  }
492 
493  /* Even if this fragment is flagged as having no more
494  * fragments, still continue. The next fragment may have the
495  * same offset with data that is preferred.
496  *
497  * For example, DefragBsdFragmentAfterNoMfIpv{4,6}Test
498  *
499  * This is due to not all fragments being completely trimmed,
500  * but relying on the copy ordering. */
501  more_frags = frag->more_frags;
502  prev_offset = frag->offset;
503  }
504 
505  IPV6Hdr *ip6h = (IPV6Hdr *)(GET_PKT_DATA(rp) + tracker->ip_hdr_offset);
506  DEBUG_VALIDATE_BUG_ON(unfragmentable_len > UINT16_MAX - fragmentable_len);
507  ip6h->s_ip6_plen = htons(fragmentable_len + unfragmentable_len);
508  /* if we have no unfragmentable part, so no ext hdrs before the frag
509  * header, we need to update the ipv6 headers next header field. This
510  * points to the frag header, and we will make it point to the layer
511  * directly after the frag header. */
512  if (unfragmentable_len == 0)
513  ip6h->s_ip6_nxt = next_hdr;
514  SET_PKT_LEN(rp, ip_hdr_offset + sizeof(IPV6Hdr) +
515  unfragmentable_len + fragmentable_len);
516 
517  tracker->remove = 1;
518  DefragTrackerFreeFrags(tracker);
519 done:
520  return rp;
521 
522 error_remove_tracker:
523  tracker->remove = 1;
524  DefragTrackerFreeFrags(tracker);
525  if (rp != NULL)
527  return NULL;
528 }
529 
530 /**
531  * The RB_TREE compare function for fragments.
532  *
533  * When it comes to adding fragments, we want subsequent ones with the
534  * same offset to be treated as greater than, so we don't have an
535  * equal return value here.
536  */
537 int DefragRbFragCompare(struct Frag_ *a, struct Frag_ *b) {
538  if (a->offset < b->offset) {
539  return -1;
540  }
541  return 1;
542 }
543 
544 /**
545  * Insert a new IPv4/IPv6 fragment into a tracker.
546  *
547  * \todo Allocate packet buffers from a pool.
548  */
549 static Packet *
550 DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
551 {
552  Packet *r = NULL;
553  uint16_t ltrim = 0;
554 
555  bool more_frags;
556  uint16_t frag_offset;
557 
558  /* IPv4 header length - IPv4 only. */
559  uint8_t hlen = 0;
560 
561  /* This is the offset of the start of the data in the packet that
562  * falls after the IP header. */
563  uint16_t data_offset;
564 
565  /* The length of the (fragmented) data. This is the length of the
566  * data that falls after the IP header. */
567  uint16_t data_len;
568 
569  /* Where the fragment ends. */
570  uint16_t frag_end;
571 
572  /* Offset in the packet to the IPv6 header. */
573  uint16_t ip_hdr_offset;
574 
575  /* Offset in the packet to the IPv6 frag header. IPv6 only. */
576  uint16_t frag_hdr_offset = 0;
577 
578  /* Address family */
579  int af = tracker->af;
580 
581  /* settings for updating a payload when an ip6 fragment with
582  * unfragmentable exthdrs are encountered. */
583  uint32_t ip6_nh_set_offset = 0;
584  uint8_t ip6_nh_set_value = 0;
585 
586 #ifdef DEBUG
587  uint64_t pcap_cnt = p->pcap_cnt;
588 #endif
589 
590  if (tracker->af == AF_INET) {
591  const IPV4Hdr *ip4h = PacketGetIPv4(p);
592  more_frags = IPV4_GET_RAW_FLAG_MF(ip4h);
593  frag_offset = (uint16_t)((uint16_t)IPV4_GET_RAW_FRAGOFFSET(ip4h) << (uint16_t)3);
594  hlen = IPV4_GET_RAW_HLEN(ip4h);
595  data_offset = (uint16_t)((uint8_t *)ip4h + hlen - GET_PKT_DATA(p));
596  data_len = IPV4_GET_RAW_IPLEN(ip4h) - hlen;
597  frag_end = frag_offset + data_len;
598  ip_hdr_offset = (uint16_t)((uint8_t *)ip4h - GET_PKT_DATA(p));
599 
600  /* Ignore fragment if the end of packet extends past the
601  * maximum size of a packet. */
602  if (IPV4_HEADER_LEN + frag_offset + data_len > IPV4_MAXPACKET_LEN) {
604  return NULL;
605  }
606  }
607  else if (tracker->af == AF_INET6) {
608  const IPV6Hdr *ip6h = PacketGetIPv6(p);
609  more_frags = IPV6_EXTHDR_GET_FH_FLAG(p);
610  frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p);
611  data_offset = p->l3.vars.ip6.eh.fh_data_offset;
612  data_len = p->l3.vars.ip6.eh.fh_data_len;
613  frag_end = frag_offset + data_len;
614  ip_hdr_offset = (uint16_t)((uint8_t *)ip6h - GET_PKT_DATA(p));
615  frag_hdr_offset = p->l3.vars.ip6.eh.fh_header_offset;
616 
617  SCLogDebug("mf %s frag_offset %u data_offset %u, data_len %u, "
618  "frag_end %u, ip_hdr_offset %u, frag_hdr_offset %u",
619  more_frags ? "true" : "false", frag_offset, data_offset,
620  data_len, frag_end, ip_hdr_offset, frag_hdr_offset);
621 
622  /* handle unfragmentable exthdrs */
623  if (ip_hdr_offset + IPV6_HEADER_LEN < frag_hdr_offset) {
624  SCLogDebug("we have exthdrs before fraghdr %u bytes",
625  (uint32_t)(frag_hdr_offset - (ip_hdr_offset + IPV6_HEADER_LEN)));
626 
627  /* get the offset of the 'next' field in exthdr before the FH,
628  * relative to the buffer start */
629 
630  /* store offset and FH 'next' value for updating frag buffer below */
631  ip6_nh_set_offset = p->l3.vars.ip6.eh.fh_prev_hdr_offset;
632  ip6_nh_set_value = IPV6_EXTHDR_GET_FH_NH(p);
633  SCLogDebug("offset %d, value %u", ip6_nh_set_offset, ip6_nh_set_value);
634  }
635 
636  /* Ignore fragment if the end of packet extends past the
637  * maximum size of a packet. */
638  if (frag_offset + data_len > IPV6_MAXPACKET) {
640  return NULL;
641  }
642  }
643  else {
645  return NULL;
646  }
647 
648  /* Update timeout. */
649  tracker->timeout = SCTIME_FROM_SECS(SCTIME_SECS(p->ts) + tracker->host_timeout);
650 
651  Frag *prev = NULL, *next = NULL;
652  bool overlap = false;
653  ltrim = 0;
654 
655  if (!RB_EMPTY(&tracker->fragment_tree)) {
656  Frag key = {
657  .offset = frag_offset - 1,
658  };
659  next = RB_NFIND(IP_FRAGMENTS, &tracker->fragment_tree, &key);
660  if (next == NULL) {
661  prev = RB_MIN(IP_FRAGMENTS, &tracker->fragment_tree);
662  next = IP_FRAGMENTS_RB_NEXT(prev);
663  } else {
664  prev = IP_FRAGMENTS_RB_PREV(next);
665  if (prev == NULL) {
666  prev = next;
667  next = IP_FRAGMENTS_RB_NEXT(prev);
668  }
669  }
670  while (prev != NULL) {
671  if (prev->skip) {
672  goto next;
673  }
674  if (frag_offset < prev->offset + prev->data_len && prev->offset < frag_end) {
675  overlap = true;
676  }
677 
678  switch (tracker->policy) {
679  case DEFRAG_POLICY_BSD:
680  if (frag_offset < prev->offset + prev->data_len) {
681  if (prev->offset <= frag_offset) {
682  /* We prefer the data from the previous
683  * fragment, so trim off the data in the new
684  * fragment that exists in the previous
685  * fragment. */
686  uint16_t prev_end = prev->offset + prev->data_len;
687  if (prev_end > frag_end) {
688  /* Just skip. */
689  /* TODO: Set overlap flag. */
690  goto done;
691  }
692  ltrim = prev_end - frag_offset;
693 
694  if ((next != NULL) && (frag_end > next->offset)) {
695  next->ltrim = frag_end - next->offset;
696  }
697 
698  goto insert;
699  }
700 
701  /* If the end of this fragment overlaps the start
702  * of the previous fragment, then trim up the
703  * start of previous fragment so this fragment is
704  * used.
705  *
706  * See:
707  * DefragBsdSubsequentOverlapsStartOfOriginal.
708  */
709  if (frag_offset <= prev->offset && frag_end > prev->offset + prev->ltrim) {
710  uint16_t prev_ltrim = frag_end - prev->offset;
711  if (prev_ltrim > prev->ltrim) {
712  prev->ltrim = prev_ltrim;
713  }
714  }
715 
716  if ((next != NULL) && (frag_end > next->offset)) {
717  next->ltrim = frag_end - next->offset;
718  }
719 
720  goto insert;
721  }
722  break;
723  case DEFRAG_POLICY_LINUX:
724  /* Check if new fragment overlaps the end of previous
725  * fragment, if it does, trim the new fragment.
726  *
727  * Old: AAAAAAAA AAAAAAAA AAAAAAAA
728  * New: BBBBBBBB BBBBBBBB BBBBBBBB
729  * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
730  */
731  if (prev->offset + prev->ltrim < frag_offset + ltrim &&
732  prev->offset + prev->data_len > frag_offset + ltrim) {
733  ltrim += prev->offset + prev->data_len - frag_offset;
734  }
735 
736  /* Check if new fragment overlaps the beginning of
737  * previous fragment, if it does, tim the previous
738  * fragment.
739  *
740  * Old: AAAAAAAA AAAAAAAA
741  * New: BBBBBBBB BBBBBBBB BBBBBBBB
742  * Res: BBBBBBBB BBBBBBBB BBBBBBBB
743  */
744  if (frag_offset + ltrim < prev->offset + prev->ltrim &&
745  frag_end > prev->offset + prev->ltrim) {
746  prev->ltrim += frag_end - (prev->offset + prev->ltrim);
747  goto insert;
748  }
749 
750  /* If the new fragment completely overlaps the
751  * previous fragment, mark the previous to be
752  * skipped. Re-assembly would succeed without doing
753  * this, but this will prevent the bytes from being
754  * copied just to be overwritten. */
755  if (frag_offset + ltrim <= prev->offset + prev->ltrim &&
756  frag_end >= prev->offset + prev->data_len) {
757  prev->skip = 1;
758  goto insert;
759  }
760 
761  break;
763  /* If new fragment fits inside a previous fragment, drop it. */
764  if (frag_offset + ltrim >= prev->offset + ltrim &&
765  frag_end <= prev->offset + prev->data_len) {
766  goto done;
767  }
768 
769  /* If new fragment starts before and ends after
770  * previous fragment, drop the previous fragment. */
771  if (frag_offset + ltrim < prev->offset + ltrim &&
772  frag_end > prev->offset + prev->data_len) {
773  prev->skip = 1;
774  goto insert;
775  }
776 
777  /* Check if new fragment overlaps the end of previous
778  * fragment, if it does, trim the new fragment.
779  *
780  * Old: AAAAAAAA AAAAAAAA AAAAAAAA
781  * New: BBBBBBBB BBBBBBBB BBBBBBBB
782  * Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB
783  */
784  if (frag_offset + ltrim > prev->offset + prev->ltrim &&
785  frag_offset + ltrim < prev->offset + prev->data_len) {
786  ltrim += prev->offset + prev->data_len - frag_offset;
787  goto insert;
788  }
789 
790  /* If new fragment starts at same offset as an
791  * existing fragment, but ends after it, trim the new
792  * fragment. */
793  if (frag_offset + ltrim == prev->offset + ltrim &&
794  frag_end > prev->offset + prev->data_len) {
795  ltrim += prev->offset + prev->data_len - frag_offset;
796  goto insert;
797  }
798  break;
800  if (frag_offset < prev->offset + prev->data_len) {
801  if (frag_offset >= prev->offset) {
802  ltrim = prev->offset + prev->data_len - frag_offset;
803  }
804  if ((frag_offset < prev->offset) &&
805  (frag_end >= prev->offset + prev->data_len)) {
806  prev->skip = 1;
807  }
808  goto insert;
809  }
810  break;
811  case DEFRAG_POLICY_FIRST:
812  if ((frag_offset >= prev->offset) &&
813  (frag_end <= prev->offset + prev->data_len)) {
814  goto done;
815  }
816  if (frag_offset < prev->offset) {
817  goto insert;
818  }
819  if (frag_offset < prev->offset + prev->data_len) {
820  ltrim = prev->offset + prev->data_len - frag_offset;
821  goto insert;
822  }
823  break;
824  case DEFRAG_POLICY_LAST:
825  if (frag_offset <= prev->offset) {
826  if (frag_end > prev->offset) {
827  prev->ltrim = frag_end - prev->offset;
828  }
829  goto insert;
830  }
831  break;
832  default:
833  break;
834  }
835 
836  next:
837  prev = next;
838  if (next != NULL) {
839  next = IP_FRAGMENTS_RB_NEXT(next);
840  }
841  continue;
842 
843  insert:
844  /* If existing fragment has been trimmed up completely
845  * (complete overlap), remove it now instead of holding
846  * onto it. */
847  if (prev->skip || prev->ltrim >= prev->data_len) {
848  RB_REMOVE(IP_FRAGMENTS, &tracker->fragment_tree, prev);
849  DefragFragReset(prev);
850  SCMutexLock(&defrag_context->frag_pool_lock);
851  PoolReturn(defrag_context->frag_pool, prev);
852  SCMutexUnlock(&defrag_context->frag_pool_lock);
853  }
854  break;
855  }
856  }
857 
858  if (ltrim >= data_len) {
859  /* Full packet has been trimmed due to the overlap policy. Overlap
860  * already set. */
861  goto done;
862  }
863 
864  /* Allocate fragment and insert. */
865  SCMutexLock(&defrag_context->frag_pool_lock);
866  Frag *new = PoolGet(defrag_context->frag_pool);
867  SCMutexUnlock(&defrag_context->frag_pool_lock);
868  if (new == NULL) {
869  if (af == AF_INET) {
871  } else {
873  }
874  if (tv != NULL && dtv != NULL) {
876  }
877  goto error_remove_tracker;
878  }
879  new->pkt = SCMalloc(GET_PKT_LEN(p));
880  if (new->pkt == NULL) {
881  SCMutexLock(&defrag_context->frag_pool_lock);
882  PoolReturn(defrag_context->frag_pool, new);
883  SCMutexUnlock(&defrag_context->frag_pool_lock);
884  if (af == AF_INET) {
886  } else {
888  }
889  goto error_remove_tracker;
890  }
891  memcpy(new->pkt, GET_PKT_DATA(p) + ltrim, GET_PKT_LEN(p) - ltrim);
892  new->len = (GET_PKT_LEN(p) - ltrim);
893  /* in case of unfragmentable exthdrs, update the 'next hdr' field
894  * in the raw buffer so the reassembled packet will point to the
895  * correct next header after stripping the frag header */
896  if (ip6_nh_set_offset > 0 && frag_offset == 0 && ltrim == 0) {
897  if (new->len > ip6_nh_set_offset) {
898  SCLogDebug("updating frag to have 'correct' nh value: %u -> %u",
899  new->pkt[ip6_nh_set_offset], ip6_nh_set_value);
900  new->pkt[ip6_nh_set_offset] = ip6_nh_set_value;
901  }
902  }
903 
904  new->hlen = hlen;
905  new->offset = frag_offset + ltrim;
906  new->data_offset = data_offset;
907  new->data_len = data_len - ltrim;
908  new->frag_hdr_offset = frag_hdr_offset;
909  new->more_frags = more_frags;
910 #ifdef DEBUG
911  new->pcap_cnt = pcap_cnt;
912 #endif
913  if (new->offset == 0) {
914  tracker->ip_hdr_offset = ip_hdr_offset;
915  tracker->datalink = p->datalink;
916  }
917 
918  IP_FRAGMENTS_RB_INSERT(&tracker->fragment_tree, new);
919 
920  if (!more_frags) {
921  tracker->seen_last = 1;
922  }
923 
924  if (tracker->seen_last) {
925  if (tracker->af == AF_INET) {
926  r = Defrag4Reassemble(tv, tracker, p);
927  if (r != NULL && tv != NULL && dtv != NULL) {
929  const uint32_t len = GET_PKT_LEN(r) - (uint32_t)tracker->ip_hdr_offset;
930  DEBUG_VALIDATE_BUG_ON(len > UINT16_MAX);
931  if (DecodeIPV4(tv, dtv, r, GET_PKT_DATA(r) + tracker->ip_hdr_offset,
932  (uint16_t)len) != TM_ECODE_OK) {
933  r->root = NULL;
935  r = NULL;
936  } else {
938  }
939  }
940  }
941  else if (tracker->af == AF_INET6) {
942  r = Defrag6Reassemble(tv, tracker, p);
943  if (r != NULL && tv != NULL && dtv != NULL) {
945  const uint32_t len = GET_PKT_LEN(r) - (uint32_t)tracker->ip_hdr_offset;
946  DEBUG_VALIDATE_BUG_ON(len > UINT16_MAX);
947  if (DecodeIPV6(tv, dtv, r, GET_PKT_DATA(r) + tracker->ip_hdr_offset,
948  (uint16_t)len) != TM_ECODE_OK) {
949  r->root = NULL;
951  r = NULL;
952  } else {
954  }
955  }
956  }
957  }
958 
959 
960 done:
961  if (overlap) {
962  if (af == AF_INET) {
964  }
965  else {
967  }
968  }
969  return r;
970 error_remove_tracker:
971  tracker->remove = 1;
972  DefragTrackerFreeFrags(tracker);
973  return NULL;
974 }
975 
976 /**
977  * \brief Get the defrag policy based on the destination address of
978  * the packet.
979  *
980  * \param p The packet used to get the destination address.
981  *
982  * \retval The defrag policy to use.
983  */
984 uint8_t
986 {
987  int policy = -1;
988 
989  if (PacketIsIPv4(p)) {
990  policy = SCHInfoGetIPv4HostOSFlavour((uint8_t *)GET_IPV4_DST_ADDR_PTR(p));
991  } else if (PacketIsIPv6(p)) {
992  policy = SCHInfoGetIPv6HostOSFlavour((uint8_t *)GET_IPV6_DST_ADDR(p));
993  }
994 
995  if (policy == -1) {
996  return default_policy;
997  }
998 
999  /* Map the OS policies returned from the configured host info to
1000  * defrag specific policies. */
1001  switch (policy) {
1002  /* BSD. */
1003  case OS_POLICY_BSD:
1004  case OS_POLICY_HPUX10:
1005  case OS_POLICY_IRIX:
1006  return DEFRAG_POLICY_BSD;
1007 
1008  /* BSD-Right. */
1009  case OS_POLICY_BSD_RIGHT:
1010  return DEFRAG_POLICY_BSD_RIGHT;
1011 
1012  /* Linux. */
1013  case OS_POLICY_OLD_LINUX:
1014  case OS_POLICY_LINUX:
1015  return DEFRAG_POLICY_LINUX;
1016 
1017  /* First. */
1018  case OS_POLICY_OLD_SOLARIS:
1019  case OS_POLICY_HPUX11:
1020  case OS_POLICY_MACOS:
1021  case OS_POLICY_FIRST:
1022  return DEFRAG_POLICY_FIRST;
1023 
1024  /* Solaris. */
1025  case OS_POLICY_SOLARIS:
1026  return DEFRAG_POLICY_SOLARIS;
1027 
1028  /* Windows. */
1029  case OS_POLICY_WINDOWS:
1030  case OS_POLICY_VISTA:
1031  case OS_POLICY_WINDOWS2K3:
1032  return DEFRAG_POLICY_WINDOWS;
1033 
1034  /* Last. */
1035  case OS_POLICY_LAST:
1036  return DEFRAG_POLICY_LAST;
1037 
1038  default:
1039  return default_policy;
1040  }
1041 }
1042 
1043 /** \internal
1044  *
1045  * \retval NULL or a *LOCKED* tracker */
1046 static DefragTracker *
1047 DefragGetTracker(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
1048 {
1049  return DefragGetTrackerFromHash(tv, dtv, p);
1050 }
1051 
1052 /**
1053  * \brief Entry point for IPv4 and IPv6 fragments.
1054  *
1055  * \param tv ThreadVars for the calling decoder.
1056  * \param p The packet fragment.
1057  *
1058  * \retval A new Packet resembling the re-assembled packet if the most
1059  * recent fragment allowed the packet to be re-assembled, otherwise
1060  * NULL is returned.
1061  */
1062 Packet *
1064 {
1065  uint16_t frag_offset;
1066  uint8_t more_frags;
1067  DefragTracker *tracker;
1068  int af;
1069 
1070  if (PacketIsIPv4(p)) {
1071  const IPV4Hdr *ip4h = PacketGetIPv4(p);
1072  af = AF_INET;
1073  more_frags = IPV4_GET_RAW_FLAG_MF(ip4h);
1074  frag_offset = IPV4_GET_RAW_FRAGOFFSET(ip4h);
1075  } else if (PacketIsIPv6(p)) {
1076  af = AF_INET6;
1077  frag_offset = IPV6_EXTHDR_GET_FH_OFFSET(p);
1078  more_frags = IPV6_EXTHDR_GET_FH_FLAG(p);
1079  } else {
1080  return NULL;
1081  }
1082 
1083  if (frag_offset == 0 && more_frags == 0) {
1084  return NULL;
1085  }
1086 
1087  if (tv != NULL && dtv != NULL) {
1088  if (af == AF_INET) {
1090  }
1091  else if (af == AF_INET6) {
1093  }
1094  }
1095 
1096  /* return a locked tracker or NULL */
1097  tracker = DefragGetTracker(tv, dtv, p);
1098  if (tracker == NULL) {
1099  if (tv != NULL && dtv != NULL) {
1101  }
1102  return NULL;
1103  }
1104 
1105  Packet *rp = DefragInsertFrag(tv, dtv, tracker, p);
1106  DefragTrackerRelease(tracker);
1107 
1108  return rp;
1109 }
1110 
1111 void
1113 {
1114  intmax_t tracker_pool_size;
1115  if (!SCConfGetInt("defrag.trackers", &tracker_pool_size)) {
1116  tracker_pool_size = DEFAULT_DEFRAG_HASH_SIZE;
1117  }
1118 
1119  /* Load the defrag-per-host lookup. */
1121 
1122  /* Allocate the DefragContext. */
1123  defrag_context = DefragContextNew();
1124  if (defrag_context == NULL) {
1125  FatalError("Failed to allocate memory for the Defrag module.");
1126  }
1127 
1128  DefragSetDefaultTimeout(defrag_context->timeout);
1129  DefragInitConfig(false);
1130 }
1131 
1132 void DefragDestroy(void)
1133 {
1135  DefragContextDestroy(defrag_context);
1136  defrag_context = NULL;
1138 }
1139 
1140 #ifdef UNITTESTS
1141 #include "util-unittest-helper.h"
1142 #include "packet.h"
1143 
1144 #define IP_MF 0x2000
1146 /**
1147  * Allocate a test packet. Nothing to fancy, just a simple IP packet
1148  * with some payload of no particular protocol.
1149  */
1150 static Packet *BuildIpv4TestPacket(
1151  uint8_t proto, uint16_t id, uint16_t off, int mf, const char content, int content_len)
1152 {
1153  Packet *p = NULL;
1154  int hlen = 20;
1155  int ttl = 64;
1156  uint8_t *pcontent;
1157  IPV4Hdr ip4h;
1158 
1159  p = SCCalloc(1, sizeof(*p) + default_packet_size);
1160  if (unlikely(p == NULL))
1161  return NULL;
1162 
1163  PacketInit(p);
1164 
1165  struct timeval tval;
1166  gettimeofday(&tval, NULL);
1167  p->ts = SCTIME_FROM_TIMEVAL(&tval);
1168  //p->ip4h = (IPV4Hdr *)GET_PKT_DATA(p);
1169  ip4h.ip_verhl = 4 << 4;
1170  ip4h.ip_verhl |= hlen >> 2;
1171  ip4h.ip_len = htons(hlen + content_len);
1172  ip4h.ip_id = htons(id);
1173  if (mf)
1174  ip4h.ip_off = htons(IP_MF | off);
1175  else
1176  ip4h.ip_off = htons(off);
1177  ip4h.ip_ttl = ttl;
1178  ip4h.ip_proto = proto;
1179 
1180  ip4h.s_ip_src.s_addr = 0x01010101; /* 1.1.1.1 */
1181  ip4h.s_ip_dst.s_addr = 0x02020202; /* 2.2.2.2 */
1182 
1183  /* copy content_len crap, we need full length */
1184  PacketCopyData(p, (uint8_t *)&ip4h, sizeof(ip4h));
1185  IPV4Hdr *ip4p = PacketSetIPV4(p, GET_PKT_DATA(p));
1186  SET_IPV4_SRC_ADDR(ip4p, &p->src);
1187  SET_IPV4_DST_ADDR(ip4p, &p->dst);
1188 
1189  pcontent = SCCalloc(1, content_len);
1190  if (unlikely(pcontent == NULL))
1191  return NULL;
1192  memset(pcontent, content, content_len);
1193  PacketCopyDataOffset(p, hlen, pcontent, content_len);
1194  SET_PKT_LEN(p, hlen + content_len);
1195  SCFree(pcontent);
1196 
1197  ip4p->ip_csum = IPV4Checksum((uint16_t *)GET_PKT_DATA(p), hlen, 0);
1198 
1199  /* Self test. */
1200  FAIL_IF(IPV4_GET_RAW_VER(ip4p) != 4);
1201  FAIL_IF(IPV4_GET_RAW_HLEN(ip4p) != hlen);
1202  FAIL_IF(IPV4_GET_RAW_IPLEN(ip4p) != hlen + content_len);
1203  FAIL_IF(IPV4_GET_RAW_IPID(ip4p) != id);
1204  FAIL_IF(IPV4_GET_RAW_FRAGOFFSET(ip4p) != off);
1205  FAIL_IF(IPV4_GET_RAW_FLAG_MF(ip4p) != mf);
1206  FAIL_IF(IPV4_GET_RAW_IPTTL(ip4p) != ttl);
1208 
1209  return p;
1210 }
1211 
1212 /**
1213  * Allocate a test packet, much like BuildIpv4TestPacket, but with
1214  * the full content provided by the caller.
1215  */
1216 static int BuildIpv4TestPacketWithContent(Packet **packet, uint8_t proto, uint16_t id, uint16_t off,
1217  int mf, const uint8_t *content, int content_len)
1218 {
1219  Packet *p = NULL;
1220  int hlen = 20;
1221  int ttl = 64;
1222  IPV4Hdr ip4h;
1223 
1224  p = SCCalloc(1, sizeof(*p) + default_packet_size);
1225  FAIL_IF_NULL(p);
1226 
1227  PacketInit(p);
1228 
1229  struct timeval tval;
1230  gettimeofday(&tval, NULL);
1231  p->ts = SCTIME_FROM_TIMEVAL(&tval);
1232  ip4h.ip_verhl = 4 << 4;
1233  ip4h.ip_verhl |= hlen >> 2;
1234  ip4h.ip_len = htons(hlen + content_len);
1235  ip4h.ip_id = htons(id);
1236  if (mf)
1237  ip4h.ip_off = htons(IP_MF | off);
1238  else
1239  ip4h.ip_off = htons(off);
1240  ip4h.ip_ttl = ttl;
1241  ip4h.ip_proto = proto;
1242 
1243  ip4h.s_ip_src.s_addr = 0x01010101; /* 1.1.1.1 */
1244  ip4h.s_ip_dst.s_addr = 0x02020202; /* 2.2.2.2 */
1245 
1246  /* copy content_len crap, we need full length */
1247  PacketCopyData(p, (uint8_t *)&ip4h, sizeof(ip4h));
1248  IPV4Hdr *ip4p = PacketSetIPV4(p, GET_PKT_DATA(p));
1249  SET_IPV4_SRC_ADDR(ip4p, &p->src);
1250  SET_IPV4_DST_ADDR(ip4p, &p->dst);
1251 
1252  PacketCopyDataOffset(p, hlen, content, content_len);
1253  SET_PKT_LEN(p, hlen + content_len);
1254 
1255  ip4p->ip_csum = IPV4Checksum((uint16_t *)GET_PKT_DATA(p), hlen, 0);
1256 
1257  /* Self test. */
1258  FAIL_IF(IPV4_GET_RAW_VER(ip4p) != 4);
1259  FAIL_IF(IPV4_GET_RAW_HLEN(ip4p) != hlen);
1260  FAIL_IF(IPV4_GET_RAW_IPLEN(ip4p) != hlen + content_len);
1261  FAIL_IF(IPV4_GET_RAW_IPID(ip4p) != id);
1262  FAIL_IF(IPV4_GET_RAW_FRAGOFFSET(ip4p) != off);
1263  FAIL_IF(IPV4_GET_RAW_FLAG_MF(ip4p) != mf);
1264  FAIL_IF(IPV4_GET_RAW_IPTTL(ip4p) != ttl);
1266 
1267  *packet = p;
1268  PASS;
1269 }
1270 
1271 static Packet *BuildIpv6TestPacket(
1272  uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t content, int content_len)
1273 {
1274  Packet *p = NULL;
1275  uint8_t *pcontent;
1276  IPV6Hdr ip6h;
1277 
1278  p = SCCalloc(1, sizeof(*p) + default_packet_size);
1279  if (unlikely(p == NULL))
1280  return NULL;
1281 
1282  PacketInit(p);
1283 
1284  struct timeval tval;
1285  gettimeofday(&tval, NULL);
1286  p->ts = SCTIME_FROM_TIMEVAL(&tval);
1287 
1288  ip6h.s_ip6_nxt = 44;
1289  ip6h.s_ip6_hlim = 2;
1290 
1291  /* Source and dest address - very bogus addresses. */
1292  ip6h.s_ip6_src[0] = 0x01010101;
1293  ip6h.s_ip6_src[1] = 0x01010101;
1294  ip6h.s_ip6_src[2] = 0x01010101;
1295  ip6h.s_ip6_src[3] = 0x01010101;
1296  ip6h.s_ip6_dst[0] = 0x02020202;
1297  ip6h.s_ip6_dst[1] = 0x02020202;
1298  ip6h.s_ip6_dst[2] = 0x02020202;
1299  ip6h.s_ip6_dst[3] = 0x02020202;
1300 
1301  /* copy content_len crap, we need full length */
1302  PacketCopyData(p, (uint8_t *)&ip6h, sizeof(IPV6Hdr));
1303 
1304  IPV6Hdr *ip6p = PacketSetIPV6(p, GET_PKT_DATA(p));
1305  IPV6_SET_RAW_VER(ip6p, 6);
1306  /* Fragmentation header. */
1307  IPV6FragHdr *fh = (IPV6FragHdr *)(GET_PKT_DATA(p) + sizeof(IPV6Hdr));
1308  fh->ip6fh_nxt = proto;
1309  fh->ip6fh_ident = htonl(id);
1310  fh->ip6fh_offlg = htons((off << 3) | mf);
1311 
1312  DecodeIPV6FragHeader(p, (uint8_t *)fh, 8, 8 + content_len, 0);
1313 
1314  pcontent = SCCalloc(1, content_len);
1315  if (unlikely(pcontent == NULL))
1316  return NULL;
1317  memset(pcontent, content, content_len);
1318  PacketCopyDataOffset(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr), pcontent, content_len);
1319  SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr) + content_len);
1320  SCFree(pcontent);
1321 
1322  ip6p->s_ip6_plen = htons(sizeof(IPV6FragHdr) + content_len);
1323 
1324  SET_IPV6_SRC_ADDR(ip6p, &p->src);
1325  SET_IPV6_DST_ADDR(ip6p, &p->dst);
1326 
1327  /* Self test. */
1328  if (IPV6_GET_RAW_VER(ip6p) != 6)
1329  goto error;
1330  if (IPV6_GET_RAW_NH(ip6p) != 44)
1331  goto error;
1332  if (IPV6_GET_RAW_PLEN(ip6p) != sizeof(IPV6FragHdr) + content_len)
1333  goto error;
1334 
1335  return p;
1336 error:
1337  if (p != NULL)
1338  SCFree(p);
1339  return NULL;
1340 }
1341 
1342 static Packet *BuildIpv6TestPacketWithContent(
1343  uint8_t proto, uint32_t id, uint16_t off, int mf, const uint8_t *content, int content_len)
1344 {
1345  Packet *p = NULL;
1346  IPV6Hdr ip6h;
1347 
1348  p = SCCalloc(1, sizeof(*p) + default_packet_size);
1349  if (unlikely(p == NULL))
1350  return NULL;
1351 
1352  PacketInit(p);
1353 
1354  struct timeval tval;
1355  gettimeofday(&tval, NULL);
1356  p->ts = SCTIME_FROM_TIMEVAL(&tval);
1357 
1358  ip6h.s_ip6_nxt = 44;
1359  ip6h.s_ip6_hlim = 2;
1360 
1361  /* Source and dest address - very bogus addresses. */
1362  ip6h.s_ip6_src[0] = 0x01010101;
1363  ip6h.s_ip6_src[1] = 0x01010101;
1364  ip6h.s_ip6_src[2] = 0x01010101;
1365  ip6h.s_ip6_src[3] = 0x01010101;
1366  ip6h.s_ip6_dst[0] = 0x02020202;
1367  ip6h.s_ip6_dst[1] = 0x02020202;
1368  ip6h.s_ip6_dst[2] = 0x02020202;
1369  ip6h.s_ip6_dst[3] = 0x02020202;
1370 
1371  /* copy content_len crap, we need full length */
1372  PacketCopyData(p, (uint8_t *)&ip6h, sizeof(IPV6Hdr));
1373 
1374  IPV6Hdr *ip6p = PacketSetIPV6(p, GET_PKT_DATA(p));
1375  IPV6_SET_RAW_VER(ip6p, 6);
1376  /* Fragmentation header. */
1377  IPV6FragHdr *fh = (IPV6FragHdr *)(GET_PKT_DATA(p) + sizeof(IPV6Hdr));
1378  fh->ip6fh_nxt = proto;
1379  fh->ip6fh_ident = htonl(id);
1380  fh->ip6fh_offlg = htons((off << 3) | mf);
1381 
1382  DecodeIPV6FragHeader(p, (uint8_t *)fh, 8, 8 + content_len, 0);
1383 
1384  PacketCopyDataOffset(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr), content, content_len);
1385  SET_PKT_LEN(p, sizeof(IPV6Hdr) + sizeof(IPV6FragHdr) + content_len);
1386 
1387  ip6p->s_ip6_plen = htons(sizeof(IPV6FragHdr) + content_len);
1388 
1389  SET_IPV6_SRC_ADDR(ip6p, &p->src);
1390  SET_IPV6_DST_ADDR(ip6p, &p->dst);
1391 
1392  /* Self test. */
1393  if (IPV6_GET_RAW_VER(ip6p) != 6)
1394  goto error;
1395  if (IPV6_GET_RAW_NH(ip6p) != 44)
1396  goto error;
1397  if (IPV6_GET_RAW_PLEN(ip6p) != sizeof(IPV6FragHdr) + content_len)
1398  goto error;
1399 
1400  return p;
1401 error:
1402  if (p != NULL)
1403  SCFree(p);
1404  return NULL;
1405 }
1406 
1407 /**
1408  * Test the simplest possible re-assembly scenario. All packet in
1409  * order and no overlaps.
1410  */
1411 static int DefragInOrderSimpleTest(void)
1412 {
1413  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1414  Packet *reassembled = NULL;
1415  int id = 12;
1416  ThreadVars tv;
1417  memset(&tv, 0, sizeof(tv));
1419  memset(&dtv, 0, sizeof(dtv));
1420 
1421  DefragInit();
1422 
1423  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
1424  FAIL_IF_NULL(p1);
1425  p2 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
1426  FAIL_IF_NULL(p2);
1427  p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
1428  FAIL_IF_NULL(p3);
1429 
1430  FAIL_IF(Defrag(&tv, &dtv, p1) != NULL);
1431  FAIL_IF(Defrag(&tv, &dtv, p2) != NULL);
1432 
1433  reassembled = Defrag(&tv, &dtv, p3);
1434  FAIL_IF_NULL(reassembled);
1435 
1436  FAIL_IF(IPV4_GET_RAW_HLEN(PacketGetIPv4(reassembled)) != 20);
1437  FAIL_IF(IPV4_GET_RAW_IPLEN(PacketGetIPv4(reassembled)) != 39);
1438 
1439  /* 20 bytes in we should find 8 bytes of A. */
1440  for (int i = 20; i < 20 + 8; i++) {
1441  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'A');
1442  }
1443 
1444  /* 28 bytes in we should find 8 bytes of B. */
1445  for (int i = 28; i < 28 + 8; i++) {
1446  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'B');
1447  }
1448 
1449  /* And 36 bytes in we should find 3 bytes of C. */
1450  for (int i = 36; i < 36 + 3; i++) {
1451  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'C');
1452  }
1453 
1454  SCFree(p1);
1455  SCFree(p2);
1456  SCFree(p3);
1457  SCFree(reassembled);
1458 
1459  DefragDestroy();
1460  PASS;
1461 }
1462 
1463 /**
1464  * Simple fragmented packet in reverse order.
1465  */
1466 static int DefragReverseSimpleTest(void)
1467 {
1468  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1469  Packet *reassembled = NULL;
1470  int id = 12;
1471  ThreadVars tv;
1472  memset(&tv, 0, sizeof(tv));
1474  memset(&dtv, 0, sizeof(dtv));
1475 
1476  DefragInit();
1477 
1478  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
1479  FAIL_IF_NULL(p1);
1480  p2 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 1, 'B', 8);
1481  FAIL_IF_NULL(p2);
1482  p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
1483  FAIL_IF_NULL(p3);
1484 
1485  FAIL_IF(Defrag(&tv, &dtv, p3) != NULL);
1486  FAIL_IF(Defrag(&tv, &dtv, p2) != NULL);
1487  reassembled = Defrag(&tv, &dtv, p1);
1488  FAIL_IF_NULL(reassembled);
1489 
1490  FAIL_IF(IPV4_GET_RAW_HLEN(PacketGetIPv4(reassembled)) != 20);
1491  FAIL_IF(IPV4_GET_RAW_IPLEN(PacketGetIPv4(reassembled)) != 39);
1492 
1493  /* 20 bytes in we should find 8 bytes of A. */
1494  for (int i = 20; i < 20 + 8; i++) {
1495  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'A');
1496  }
1497 
1498  /* 28 bytes in we should find 8 bytes of B. */
1499  for (int i = 28; i < 28 + 8; i++) {
1500  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'B');
1501  }
1502 
1503  /* And 36 bytes in we should find 3 bytes of C. */
1504  for (int i = 36; i < 36 + 3; i++) {
1505  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'C');
1506  }
1507 
1508  SCFree(p1);
1509  SCFree(p2);
1510  SCFree(p3);
1511  SCFree(reassembled);
1512 
1513  DefragDestroy();
1514  PASS;
1515 }
1516 
1517 /**
1518  * Test the simplest possible re-assembly scenario. All packet in
1519  * order and no overlaps.
1520  */
1521 static int DefragInOrderSimpleIpv6Test(void)
1522 {
1523  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1524  Packet *reassembled = NULL;
1525  int id = 12;
1526  ThreadVars tv;
1527  memset(&tv, 0, sizeof(tv));
1529  memset(&dtv, 0, sizeof(dtv));
1530 
1531  DefragInit();
1532 
1533  p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
1534  FAIL_IF_NULL(p1);
1535  p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
1536  FAIL_IF_NULL(p2);
1537  p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
1538  FAIL_IF_NULL(p3);
1539 
1540  FAIL_IF(Defrag(&tv, &dtv, p1) != NULL);
1541  FAIL_IF(Defrag(&tv, &dtv, p2) != NULL);
1542  reassembled = Defrag(&tv, &dtv, p3);
1543  FAIL_IF_NULL(reassembled);
1544 
1545  const IPV6Hdr *ip6h = PacketGetIPv6(reassembled);
1546  FAIL_IF(IPV6_GET_RAW_PLEN(ip6h) != 19);
1547 
1548  /* 40 bytes in we should find 8 bytes of A. */
1549  for (int i = 40; i < 40 + 8; i++) {
1550  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'A');
1551  }
1552 
1553  /* 28 bytes in we should find 8 bytes of B. */
1554  for (int i = 48; i < 48 + 8; i++) {
1555  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'B');
1556  }
1557 
1558  /* And 36 bytes in we should find 3 bytes of C. */
1559  for (int i = 56; i < 56 + 3; i++) {
1560  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'C');
1561  }
1562 
1563  SCFree(p1);
1564  SCFree(p2);
1565  SCFree(p3);
1566  SCFree(reassembled);
1567 
1568  DefragDestroy();
1569  PASS;
1570 }
1571 
1572 static int DefragReverseSimpleIpv6Test(void)
1573 {
1574  DefragContext *dc = NULL;
1575  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
1576  Packet *reassembled = NULL;
1577  int id = 12;
1578  ThreadVars tv;
1579  memset(&tv, 0, sizeof(tv));
1581  memset(&dtv, 0, sizeof(dtv));
1582 
1583  DefragInit();
1584 
1585  dc = DefragContextNew();
1586  FAIL_IF_NULL(dc);
1587 
1588  p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 8);
1589  FAIL_IF_NULL(p1);
1590  p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 1, 1, 'B', 8);
1591  FAIL_IF_NULL(p2);
1592  p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 2, 0, 'C', 3);
1593  FAIL_IF_NULL(p3);
1594 
1595  FAIL_IF(Defrag(&tv, &dtv, p3) != NULL);
1596  FAIL_IF(Defrag(&tv, &dtv, p2) != NULL);
1597  reassembled = Defrag(&tv, &dtv, p1);
1598  FAIL_IF_NULL(reassembled);
1599 
1600  /* 40 bytes in we should find 8 bytes of A. */
1601  for (int i = 40; i < 40 + 8; i++) {
1602  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'A');
1603  }
1604 
1605  /* 28 bytes in we should find 8 bytes of B. */
1606  for (int i = 48; i < 48 + 8; i++) {
1607  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'B');
1608  }
1609 
1610  /* And 36 bytes in we should find 3 bytes of C. */
1611  for (int i = 56; i < 56 + 3; i++) {
1612  FAIL_IF(GET_PKT_DATA(reassembled)[i] != 'C');
1613  }
1614 
1615  DefragContextDestroy(dc);
1616  SCFree(p1);
1617  SCFree(p2);
1618  SCFree(p3);
1619  SCFree(reassembled);
1620 
1621  DefragDestroy();
1622  PASS;
1623 }
1624 
1625 static int DefragDoSturgesNovakTest(int policy, uint8_t *expected, size_t expected_len)
1626 {
1627  int i;
1628  ThreadVars tv;
1629  memset(&tv, 0, sizeof(tv));
1631  memset(&dtv, 0, sizeof(dtv));
1632 
1633  DefragInit();
1634 
1635  /*
1636  * Build the packets.
1637  */
1638 
1639  int id = 1;
1640  Packet *packets[17];
1641  memset(packets, 0x00, sizeof(packets));
1642 
1643  /*
1644  * Original fragments.
1645  */
1646 
1647  /* <1> A*24 at 0. */
1648  packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
1649 
1650  /* <2> B*16 at 32. */
1651  packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 32 >> 3, 1, 'B', 16);
1652 
1653  /* <3> C*24 at 48. */
1654  packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'C', 24);
1655 
1656  /* <3_1> D*8 at 80. */
1657  packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 80 >> 3, 1, 'D', 8);
1658 
1659  /* <3_2> E*16 at 104. */
1660  packets[4] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 104 >> 3, 1, 'E', 16);
1661 
1662  /* <3_3> F*24 at 120. */
1663  packets[5] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 120 >> 3, 1, 'F', 24);
1664 
1665  /* <3_4> G*16 at 144. */
1666  packets[6] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 144 >> 3, 1, 'G', 16);
1667 
1668  /* <3_5> H*16 at 160. */
1669  packets[7] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'H', 16);
1670 
1671  /* <3_6> I*8 at 176. */
1672  packets[8] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 176 >> 3, 1, 'I', 8);
1673 
1674  /*
1675  * Overlapping subsequent fragments.
1676  */
1677 
1678  /* <4> J*32 at 8. */
1679  packets[9] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 8 >> 3, 1, 'J', 32);
1680 
1681  /* <5> K*24 at 48. */
1682  packets[10] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 48 >> 3, 1, 'K', 24);
1683 
1684  /* <6> L*24 at 72. */
1685  packets[11] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 72 >> 3, 1, 'L', 24);
1686 
1687  /* <7> M*24 at 96. */
1688  packets[12] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 96 >> 3, 1, 'M', 24);
1689 
1690  /* <8> N*8 at 128. */
1691  packets[13] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 128 >> 3, 1, 'N', 8);
1692 
1693  /* <9> O*8 at 152. */
1694  packets[14] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 152 >> 3, 1, 'O', 8);
1695 
1696  /* <10> P*8 at 160. */
1697  packets[15] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 160 >> 3, 1, 'P', 8);
1698 
1699  /* <11> Q*16 at 176. */
1700  packets[16] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 176 >> 3, 0, 'Q', 16);
1701 
1702  default_policy = policy;
1703 
1704  /* Send all but the last. */
1705  for (i = 0; i < 9; i++) {
1706  Packet *tp = Defrag(&tv, &dtv, packets[i]);
1707  FAIL_IF_NOT_NULL(tp);
1709  }
1710  int overlap = 0;
1711  for (; i < 16; i++) {
1712  Packet *tp = Defrag(&tv, &dtv, packets[i]);
1713  FAIL_IF_NOT_NULL(tp);
1714  if (ENGINE_ISSET_EVENT(packets[i], IPV4_FRAG_OVERLAP)) {
1715  overlap++;
1716  }
1717  }
1718  FAIL_IF_NOT(overlap);
1719 
1720  /* And now the last one. */
1721  Packet *reassembled = Defrag(&tv, &dtv, packets[16]);
1722  FAIL_IF_NULL(reassembled);
1723 
1724  FAIL_IF(IPV4_GET_RAW_HLEN(PacketGetIPv4(reassembled)) != 20);
1725  FAIL_IF(IPV4_GET_RAW_IPLEN(PacketGetIPv4(reassembled)) != 20 + 192);
1726  FAIL_IF(expected_len != 192);
1727 
1728  if (memcmp(expected, GET_PKT_DATA(reassembled) + 20, expected_len) != 0) {
1729  printf("Expected:\n");
1730  PrintRawDataFp(stdout, expected, expected_len);
1731  printf("Got:\n");
1732  PrintRawDataFp(stdout, GET_PKT_DATA(reassembled) + 20, GET_PKT_LEN(reassembled) - 20);
1733  FAIL;
1734  }
1735  SCFree(reassembled);
1736 
1737  /* Make sure all frags were returned back to the pool. */
1738  FAIL_IF(defrag_context->frag_pool->outstanding != 0);
1739 
1740  for (i = 0; i < 17; i++) {
1741  SCFree(packets[i]);
1742  }
1743  DefragDestroy();
1744  PASS;
1745 }
1746 
1747 static int DefragDoSturgesNovakIpv6Test(int policy, uint8_t *expected, size_t expected_len)
1748 {
1749  int i;
1750  ThreadVars tv;
1751  memset(&tv, 0, sizeof(tv));
1753  memset(&dtv, 0, sizeof(dtv));
1754 
1755  DefragInit();
1756 
1757  /*
1758  * Build the packets.
1759  */
1760 
1761  int id = 1;
1762  Packet *packets[17];
1763  memset(packets, 0x00, sizeof(packets));
1764 
1765  /*
1766  * Original fragments.
1767  */
1768 
1769  /* <1> A*24 at 0. */
1770  packets[0] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 0, 1, 'A', 24);
1771 
1772  /* <2> B*16 at 32. */
1773  packets[1] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 32 >> 3, 1, 'B', 16);
1774 
1775  /* <3> C*24 at 48. */
1776  packets[2] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'C', 24);
1777 
1778  /* <3_1> D*8 at 80. */
1779  packets[3] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 80 >> 3, 1, 'D', 8);
1780 
1781  /* <3_2> E*16 at 104. */
1782  packets[4] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 104 >> 3, 1, 'E', 16);
1783 
1784  /* <3_3> F*24 at 120. */
1785  packets[5] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 120 >> 3, 1, 'F', 24);
1786 
1787  /* <3_4> G*16 at 144. */
1788  packets[6] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 144 >> 3, 1, 'G', 16);
1789 
1790  /* <3_5> H*16 at 160. */
1791  packets[7] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'H', 16);
1792 
1793  /* <3_6> I*8 at 176. */
1794  packets[8] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 1, 'I', 8);
1795 
1796  /*
1797  * Overlapping subsequent fragments.
1798  */
1799 
1800  /* <4> J*32 at 8. */
1801  packets[9] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 8 >> 3, 1, 'J', 32);
1802 
1803  /* <5> K*24 at 48. */
1804  packets[10] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 48 >> 3, 1, 'K', 24);
1805 
1806  /* <6> L*24 at 72. */
1807  packets[11] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 72 >> 3, 1, 'L', 24);
1808 
1809  /* <7> M*24 at 96. */
1810  packets[12] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 96 >> 3, 1, 'M', 24);
1811 
1812  /* <8> N*8 at 128. */
1813  packets[13] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 128 >> 3, 1, 'N', 8);
1814 
1815  /* <9> O*8 at 152. */
1816  packets[14] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 152 >> 3, 1, 'O', 8);
1817 
1818  /* <10> P*8 at 160. */
1819  packets[15] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 160 >> 3, 1, 'P', 8);
1820 
1821  /* <11> Q*16 at 176. */
1822  packets[16] = BuildIpv6TestPacket(IPPROTO_ICMPV6, id, 176 >> 3, 0, 'Q', 16);
1823 
1824  default_policy = policy;
1825 
1826  /* Send all but the last. */
1827  for (i = 0; i < 9; i++) {
1828  Packet *tp = Defrag(&tv, &dtv, packets[i]);
1829  FAIL_IF_NOT_NULL(tp);
1831  }
1832  int overlap = 0;
1833  for (; i < 16; i++) {
1834  Packet *tp = Defrag(&tv, &dtv, packets[i]);
1835  FAIL_IF_NOT_NULL(tp);
1836  if (ENGINE_ISSET_EVENT(packets[i], IPV6_FRAG_OVERLAP)) {
1837  overlap++;
1838  }
1839  }
1840  FAIL_IF_NOT(overlap);
1841 
1842  /* And now the last one. */
1843  Packet *reassembled = Defrag(&tv, &dtv, packets[16]);
1844  FAIL_IF_NULL(reassembled);
1845  FAIL_IF(memcmp(GET_PKT_DATA(reassembled) + 40, expected, expected_len) != 0);
1846 
1847  FAIL_IF(IPV6_GET_RAW_PLEN(PacketGetIPv6(reassembled)) != 192);
1848 
1849  SCFree(reassembled);
1850 
1851  /* Make sure all frags were returned to the pool. */
1852  FAIL_IF(defrag_context->frag_pool->outstanding != 0);
1853 
1854  for (i = 0; i < 17; i++) {
1855  SCFree(packets[i]);
1856  }
1857  DefragDestroy();
1858  PASS;
1859 }
1860 
1861 /* Define data that matches the naming "Target-Based Fragmentation
1862  * Reassembly".
1863  *
1864  * For example, the data refers to a fragment of data as <1>, or <3_6>
1865  * and uses these to diagram the input fragments and the resulting
1866  * policies. We build test cases for the papers scenario but assign
1867  * specific values to each segment.
1868  */
1869 #define D_1 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'
1870 #define D_2 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B'
1871 #define D_3 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C'
1872 #define D_3_1 'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D'
1873 #define D_3_2 'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E'
1874 #define D_3_3 'F', 'F', 'F', 'F', 'F', 'F', 'F', 'F'
1875 #define D_3_4 'G', 'G', 'G', 'G', 'G', 'G', 'G', 'G'
1876 #define D_3_5 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H'
1877 #define D_3_6 'I', 'I', 'I', 'I', 'I', 'I', 'I', 'I'
1878 #define D_4 'J', 'J', 'J', 'J', 'J', 'J', 'J', 'J'
1879 #define D_5 'K', 'K', 'K', 'K', 'K', 'K', 'K', 'K'
1880 #define D_6 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'
1881 #define D_7 'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M'
1882 #define D_8 'N', 'N', 'N', 'N', 'N', 'N', 'N', 'N'
1883 #define D_9 'O', 'O', 'O', 'O', 'O', 'O', 'O', 'O'
1884 #define D_10 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P'
1885 #define D_11 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q', 'Q'
1887 static int
1888 DefragSturgesNovakBsdTest(void)
1889 {
1890  /* Expected data. */
1891  uint8_t expected[] = {
1892  D_1,
1893  D_1,
1894  D_1,
1895  D_4,
1896  D_4,
1897  D_2,
1898  D_3,
1899  D_3,
1900  D_3,
1901  D_6,
1902  D_6,
1903  D_6,
1904  D_7,
1905  D_7,
1906  D_7,
1907  D_3_3,
1908  D_3_3,
1909  D_3_3,
1910  D_3_4,
1911  D_3_4,
1912  D_3_5,
1913  D_3_5,
1914  D_3_6,
1915  D_11,
1916  };
1917 
1918  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_BSD, expected,
1919  sizeof(expected)));
1920  PASS;
1921 }
1922 
1923 static int DefragSturgesNovakBsdIpv6Test(void)
1924 {
1925  /* Expected data. */
1926  uint8_t expected[] = {
1927  D_1,
1928  D_1,
1929  D_1,
1930  D_4,
1931  D_4,
1932  D_2,
1933  D_3,
1934  D_3,
1935  D_3,
1936  D_6,
1937  D_6,
1938  D_6,
1939  D_7,
1940  D_7,
1941  D_7,
1942  D_3_3,
1943  D_3_3,
1944  D_3_3,
1945  D_3_4,
1946  D_3_4,
1947  D_3_5,
1948  D_3_5,
1949  D_3_6,
1950  D_11,
1951  };
1952 
1953  FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_BSD, expected, sizeof(expected)));
1954  PASS;
1955 }
1956 
1957 static int DefragSturgesNovakLinuxIpv4Test(void)
1958 {
1959  /* Expected data. */
1960  uint8_t expected[] = {
1961  D_1,
1962  D_1,
1963  D_1,
1964  D_4,
1965  D_4,
1966  D_2,
1967  D_5,
1968  D_5,
1969  D_5,
1970  D_6,
1971  D_6,
1972  D_6,
1973  D_7,
1974  D_7,
1975  D_7,
1976  D_3_3,
1977  D_3_3,
1978  D_3_3,
1979  D_3_4,
1980  D_3_4,
1981  D_10,
1982  D_3_5,
1983  D_11,
1984  D_11,
1985  };
1986 
1987  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LINUX, expected,
1988  sizeof(expected)));
1989  PASS;
1990 }
1991 
1992 static int DefragSturgesNovakLinuxIpv6Test(void)
1993 {
1994  /* Expected data. */
1995  uint8_t expected[] = {
1996  D_1,
1997  D_1,
1998  D_1,
1999  D_4,
2000  D_4,
2001  D_2,
2002  D_5,
2003  D_5,
2004  D_5,
2005  D_6,
2006  D_6,
2007  D_6,
2008  D_7,
2009  D_7,
2010  D_7,
2011  D_3_3,
2012  D_3_3,
2013  D_3_3,
2014  D_3_4,
2015  D_3_4,
2016  D_10,
2017  D_3_5,
2018  D_11,
2019  D_11,
2020  };
2021 
2022  FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_LINUX, expected, sizeof(expected)));
2023  PASS;
2024 }
2025 
2026 static int DefragSturgesNovakWindowsIpv4Test(void)
2027 {
2028  /* Expected data. */
2029  uint8_t expected[] = {
2030  D_1,
2031  D_1,
2032  D_1,
2033  D_4,
2034  D_2,
2035  D_2,
2036  D_3,
2037  D_3,
2038  D_3,
2039  D_6,
2040  D_6,
2041  D_6,
2042  D_7,
2043  D_3_2,
2044  D_3_2,
2045  D_3_3,
2046  D_3_3,
2047  D_3_3,
2048  D_3_4,
2049  D_3_4,
2050  D_3_5,
2051  D_3_5,
2052  D_3_6,
2053  D_11,
2054  };
2055 
2056  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_WINDOWS, expected,
2057  sizeof(expected)));
2058  PASS;
2059 }
2060 
2061 static int DefragSturgesNovakWindowsIpv6Test(void)
2062 {
2063  /* Expected data. */
2064  uint8_t expected[] = {
2065  D_1,
2066  D_1,
2067  D_1,
2068  D_4,
2069  D_2,
2070  D_2,
2071  D_3,
2072  D_3,
2073  D_3,
2074  D_6,
2075  D_6,
2076  D_6,
2077  D_7,
2078  D_3_2,
2079  D_3_2,
2080  D_3_3,
2081  D_3_3,
2082  D_3_3,
2083  D_3_4,
2084  D_3_4,
2085  D_3_5,
2086  D_3_5,
2087  D_3_6,
2088  D_11,
2089  };
2090 
2091  FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_WINDOWS, expected, sizeof(expected)));
2092  PASS;
2093 }
2094 
2095 static int DefragSturgesNovakSolarisTest(void)
2096 {
2097  /* Expected data. */
2098  uint8_t expected[] = {
2099  D_1,
2100  D_1,
2101  D_1,
2102  D_4,
2103  D_2,
2104  D_2,
2105  D_3,
2106  D_3,
2107  D_3,
2108  D_6,
2109  D_6,
2110  D_6,
2111  D_7,
2112  D_7,
2113  D_7,
2114  D_3_3,
2115  D_3_3,
2116  D_3_3,
2117  D_3_4,
2118  D_3_4,
2119  D_3_5,
2120  D_3_5,
2121  D_3_6,
2122  D_11,
2123  };
2124 
2125  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_SOLARIS, expected,
2126  sizeof(expected)));
2127  PASS;
2128 }
2129 
2130 static int DefragSturgesNovakSolarisIpv6Test(void)
2131 {
2132  /* Expected data. */
2133  uint8_t expected[] = {
2134  D_1,
2135  D_1,
2136  D_1,
2137  D_4,
2138  D_2,
2139  D_2,
2140  D_3,
2141  D_3,
2142  D_3,
2143  D_6,
2144  D_6,
2145  D_6,
2146  D_7,
2147  D_7,
2148  D_7,
2149  D_3_3,
2150  D_3_3,
2151  D_3_3,
2152  D_3_4,
2153  D_3_4,
2154  D_3_5,
2155  D_3_5,
2156  D_3_6,
2157  D_11,
2158  };
2159 
2160  FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_SOLARIS, expected, sizeof(expected)));
2161  PASS;
2162 }
2163 
2164 static int DefragSturgesNovakFirstTest(void)
2165 {
2166  /* Expected data. */
2167  uint8_t expected[] = {
2168  D_1,
2169  D_1,
2170  D_1,
2171  D_4,
2172  D_2,
2173  D_2,
2174  D_3,
2175  D_3,
2176  D_3,
2177  D_6,
2178  D_3_1,
2179  D_6,
2180  D_7,
2181  D_3_2,
2182  D_3_2,
2183  D_3_3,
2184  D_3_3,
2185  D_3_3,
2186  D_3_4,
2187  D_3_4,
2188  D_3_5,
2189  D_3_5,
2190  D_3_6,
2191  D_11,
2192  };
2193 
2194  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_FIRST, expected,
2195  sizeof(expected)));
2196  PASS;
2197 }
2198 
2199 static int DefragSturgesNovakFirstIpv6Test(void)
2200 {
2201  /* Expected data. */
2202  uint8_t expected[] = {
2203  D_1,
2204  D_1,
2205  D_1,
2206  D_4,
2207  D_2,
2208  D_2,
2209  D_3,
2210  D_3,
2211  D_3,
2212  D_6,
2213  D_3_1,
2214  D_6,
2215  D_7,
2216  D_3_2,
2217  D_3_2,
2218  D_3_3,
2219  D_3_3,
2220  D_3_3,
2221  D_3_4,
2222  D_3_4,
2223  D_3_5,
2224  D_3_5,
2225  D_3_6,
2226  D_11,
2227  };
2228 
2229  return DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_FIRST, expected, sizeof(expected));
2230 }
2231 
2232 static int
2233 DefragSturgesNovakLastTest(void)
2234 {
2235  /* Expected data. */
2236  uint8_t expected[] = {
2237  D_1,
2238  D_4,
2239  D_4,
2240  D_4,
2241  D_4,
2242  D_2,
2243  D_5,
2244  D_5,
2245  D_5,
2246  D_6,
2247  D_6,
2248  D_6,
2249  D_7,
2250  D_7,
2251  D_7,
2252  D_3_3,
2253  D_8,
2254  D_3_3,
2255  D_3_4,
2256  D_9,
2257  D_10,
2258  D_3_5,
2259  D_11,
2260  D_11,
2261  };
2262 
2263  FAIL_IF_NOT(DefragDoSturgesNovakTest(DEFRAG_POLICY_LAST, expected,
2264  sizeof(expected)));
2265  PASS;
2266 }
2267 
2268 static int DefragSturgesNovakLastIpv6Test(void)
2269 {
2270  /* Expected data. */
2271  uint8_t expected[] = {
2272  D_1,
2273  D_4,
2274  D_4,
2275  D_4,
2276  D_4,
2277  D_2,
2278  D_5,
2279  D_5,
2280  D_5,
2281  D_6,
2282  D_6,
2283  D_6,
2284  D_7,
2285  D_7,
2286  D_7,
2287  D_3_3,
2288  D_8,
2289  D_3_3,
2290  D_3_4,
2291  D_9,
2292  D_10,
2293  D_3_5,
2294  D_11,
2295  D_11,
2296  };
2297 
2298  FAIL_IF_NOT(DefragDoSturgesNovakIpv6Test(DEFRAG_POLICY_LAST, expected, sizeof(expected)));
2299  PASS;
2300 }
2301 
2302 static int DefragTimeoutTest(void)
2303 {
2304  int i;
2305  ThreadVars tv;
2306  memset(&tv, 0, sizeof(tv));
2308  memset(&dtv, 0, sizeof(dtv));
2309 
2310  /* Setup a small number of trackers. */
2311  FAIL_IF_NOT(SCConfSet("defrag.trackers", "16"));
2312 
2313  DefragInit();
2314 
2315  /* Load in 16 packets. */
2316  for (i = 0; i < 16; i++) {
2317  Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, i, 0, 1, 'A' + i, 16);
2318  FAIL_IF_NULL(p);
2319 
2320  Packet *tp = Defrag(&tv, &dtv, p);
2321  SCFree(p);
2322  FAIL_IF_NOT_NULL(tp);
2323  }
2324 
2325  /* Build a new packet but push the timestamp out by our timeout.
2326  * This should force our previous fragments to be timed out. */
2327  Packet *p = BuildIpv4TestPacket(IPPROTO_ICMP, 99, 0, 1, 'A' + i, 16);
2328  FAIL_IF_NULL(p);
2329 
2330  p->ts = SCTIME_ADD_SECS(p->ts, defrag_context->timeout + 1);
2331  Packet *tp = Defrag(&tv, &dtv, p);
2332  FAIL_IF_NOT_NULL(tp);
2333 
2335  FAIL_IF_NULL(tracker);
2336 
2337  FAIL_IF(tracker->id != 99);
2338 
2339  SCMutexUnlock(&tracker->lock);
2340  SCFree(p);
2341 
2342  DefragDestroy();
2343  PASS;
2344 }
2345 
2346 /**
2347  * QA found that if you send a packet where more frags is 0, offset is
2348  * > 0 and there is no data in the packet that the re-assembler will
2349  * fail. The fix was simple, but this unit test is just to make sure
2350  * its not introduced.
2351  */
2352 static int DefragNoDataIpv4Test(void)
2353 {
2354  DefragContext *dc = NULL;
2355  Packet *p = NULL;
2356  int id = 12;
2357  ThreadVars tv;
2358  memset(&tv, 0, sizeof(tv));
2360  memset(&dtv, 0, sizeof(dtv));
2361 
2362  DefragInit();
2363 
2364  dc = DefragContextNew();
2365  FAIL_IF_NULL(dc);
2366 
2367  /* This packet has an offset > 0, more frags set to 0 and no data. */
2368  p = BuildIpv4TestPacket(IPPROTO_ICMP, id, 1, 0, 'A', 0);
2369  FAIL_IF_NULL(p);
2370 
2371  /* We do not expect a packet returned. */
2372  FAIL_IF(Defrag(&tv, &dtv, p) != NULL);
2373 
2374  /* The fragment should have been ignored so no fragments should
2375  * have been allocated from the pool. */
2376  FAIL_IF(dc->frag_pool->outstanding != 0);
2377 
2378  DefragContextDestroy(dc);
2379  SCFree(p);
2380 
2381  DefragDestroy();
2382  PASS;
2383 }
2384 
2385 static int DefragTooLargeIpv4Test(void)
2386 {
2387  DefragContext *dc = NULL;
2388  Packet *p = NULL;
2389  ThreadVars tv;
2390  memset(&tv, 0, sizeof(tv));
2392  memset(&dtv, 0, sizeof(dtv));
2393 
2394  DefragInit();
2395 
2396  dc = DefragContextNew();
2397  FAIL_IF_NULL(dc);
2398 
2399  /* Create a fragment that would extend past the max allowable size
2400  * for an IPv4 packet. */
2401  p = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8183, 0, 'A', 71);
2402  FAIL_IF_NULL(p);
2403 
2404  /* We do not expect a packet returned. */
2405  FAIL_IF(Defrag(&tv, &dtv, p) != NULL);
2406 
2407  /* We do expect an event. */
2409 
2410  /* The fragment should have been ignored so no fragments should have
2411  * been allocated from the pool. */
2412  FAIL_IF(dc->frag_pool->outstanding != 0);
2413 
2414  DefragContextDestroy(dc);
2415  SCFree(p);
2416 
2417  DefragDestroy();
2418  PASS;
2419 }
2420 
2421 /**
2422  * Test that fragments in different VLANs that would otherwise be
2423  * re-assembled, are not re-assembled. Just use simple in-order
2424  * fragments.
2425  */
2426 static int DefragVlanTest(void)
2427 {
2428  Packet *p1 = NULL, *p2 = NULL, *r = NULL;
2429  ThreadVars tv;
2430  memset(&tv, 0, sizeof(tv));
2432  memset(&dtv, 0, sizeof(dtv));
2433 
2434  DefragInit();
2435 
2436  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
2437  FAIL_IF_NULL(p1);
2438  p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
2439  FAIL_IF_NULL(p2);
2440 
2441  /* With no VLAN IDs set, packets should re-assemble. */
2442  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2443  FAIL_IF((r = Defrag(&tv, &dtv, p2)) == NULL);
2444  SCFree(r);
2445 
2446  /* With mismatched VLANs, packets should not re-assemble. */
2447  p1->vlan_id[0] = 1;
2448  p2->vlan_id[0] = 2;
2449  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2450  FAIL_IF((r = Defrag(&tv, &dtv, p2)) != NULL);
2451 
2452  SCFree(p1);
2453  SCFree(p2);
2454  DefragDestroy();
2455 
2456  PASS;
2457 }
2458 
2459 /**
2460  * Like DefragVlanTest, but for QinQ, testing the second level VLAN ID.
2461  */
2462 static int DefragVlanQinQTest(void)
2463 {
2464  Packet *p1 = NULL, *p2 = NULL, *r = NULL;
2465  ThreadVars tv;
2466  memset(&tv, 0, sizeof(tv));
2468  memset(&dtv, 0, sizeof(dtv));
2469 
2470  DefragInit();
2471 
2472  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
2473  FAIL_IF_NULL(p1);
2474  p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
2475  FAIL_IF_NULL(p2);
2476 
2477  /* With no VLAN IDs set, packets should re-assemble. */
2478  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2479  FAIL_IF((r = Defrag(&tv, &dtv, p2)) == NULL);
2480  SCFree(r);
2481 
2482  /* With mismatched VLANs, packets should not re-assemble. */
2483  p1->vlan_id[0] = 1;
2484  p2->vlan_id[0] = 1;
2485  p1->vlan_id[1] = 1;
2486  p2->vlan_id[1] = 2;
2487  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2488  FAIL_IF((r = Defrag(&tv, &dtv, p2)) != NULL);
2489 
2490  SCFree(p1);
2491  SCFree(p2);
2492  DefragDestroy();
2493 
2494  PASS;
2495 }
2496 
2497 /**
2498  * Like DefragVlanTest, but for QinQinQ, testing the third level VLAN ID.
2499  */
2500 static int DefragVlanQinQinQTest(void)
2501 {
2502  Packet *r = NULL;
2503  ThreadVars tv;
2504  memset(&tv, 0, sizeof(tv));
2506  memset(&dtv, 0, sizeof(dtv));
2507 
2508  DefragInit();
2509 
2510  Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'A', 8);
2511  FAIL_IF_NULL(p1);
2512  Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 1, 0, 'B', 8);
2513  FAIL_IF_NULL(p2);
2514 
2515  /* With no VLAN IDs set, packets should re-assemble. */
2516  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2517  FAIL_IF((r = Defrag(&tv, &dtv, p2)) == NULL);
2518  SCFree(r);
2519 
2520  /* With mismatched VLANs, packets should not re-assemble. */
2521  p1->vlan_id[0] = 1;
2522  p2->vlan_id[0] = 1;
2523  p1->vlan_id[1] = 2;
2524  p2->vlan_id[1] = 2;
2525  p1->vlan_id[2] = 3;
2526  p2->vlan_id[2] = 4;
2527  FAIL_IF((r = Defrag(&tv, &dtv, p1)) != NULL);
2528  FAIL_IF((r = Defrag(&tv, &dtv, p2)) != NULL);
2529 
2530  PacketFree(p1);
2531  PacketFree(p2);
2532  DefragDestroy();
2533 
2534  PASS;
2535 }
2536 static int DefragTrackerReuseTest(void)
2537 {
2538  int id = 1;
2539  Packet *p1 = NULL;
2540  DefragTracker *tracker1 = NULL, *tracker2 = NULL;
2541  ThreadVars tv;
2542  memset(&tv, 0, sizeof(tv));
2544  memset(&dtv, 0, sizeof(dtv));
2545 
2546  DefragInit();
2547 
2548  /* Build a packet, its not a fragment but shouldn't matter for
2549  * this test. */
2550  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 0, 'A', 8);
2551  FAIL_IF_NULL(p1);
2552 
2553  /* Get a tracker. It shouldn't look like its already in use. */
2554  tracker1 = DefragGetTracker(&tv, &dtv, p1);
2555  FAIL_IF_NULL(tracker1);
2556  FAIL_IF(tracker1->seen_last);
2557  FAIL_IF(tracker1->remove);
2558  DefragTrackerRelease(tracker1);
2559 
2560  /* Get a tracker again, it should be the same one. */
2561  tracker2 = DefragGetTracker(&tv, &dtv, p1);
2562  FAIL_IF_NULL(tracker2);
2563  FAIL_IF(tracker2 != tracker1);
2564  DefragTrackerRelease(tracker1);
2565 
2566  /* Now mark the tracker for removal. It should not be returned
2567  * when we get a tracker for a packet that may have the same
2568  * attributes. */
2569  tracker1->remove = 1;
2570 
2571  tracker2 = DefragGetTracker(&tv, &dtv, p1);
2572  FAIL_IF_NULL(tracker2);
2573  /* DefragGetTracker will have returned tracker1 to the stack,
2574  * the set up a new tracker. Since it pops the stack, it got
2575  * tracker1. */
2576  FAIL_IF(tracker2 != tracker1);
2577  FAIL_IF(tracker2->remove);
2578 
2579  SCFree(p1);
2580  DefragDestroy();
2581  PASS;
2582 }
2583 
2584 /**
2585  * IPV4: Test the case where you have a packet fragmented in 3 parts
2586  * and send like:
2587  * - Offset: 2; MF: 1
2588  * - Offset: 0; MF: 1
2589  * - Offset: 1; MF: 0
2590  *
2591  * Only the fragments with offset 0 and 1 should be reassembled.
2592  */
2593 static int DefragMfIpv4Test(void)
2594 {
2595  int ip_id = 9;
2596  Packet *p = NULL;
2597  ThreadVars tv;
2598  memset(&tv, 0, sizeof(tv));
2600  memset(&dtv, 0, sizeof(dtv));
2601 
2602  DefragInit();
2603 
2604  Packet *p1 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 2, 1, 'C', 8);
2605  Packet *p2 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 0, 1, 'A', 8);
2606  Packet *p3 = BuildIpv4TestPacket(IPPROTO_ICMP, ip_id, 1, 0, 'B', 8);
2607  FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
2608 
2609  p = Defrag(&tv, &dtv, p1);
2610  FAIL_IF_NOT_NULL(p);
2611 
2612  p = Defrag(&tv, &dtv, p2);
2613  FAIL_IF_NOT_NULL(p);
2614 
2615  /* This should return a packet as MF=0. */
2616  p = Defrag(&tv, &dtv, p3);
2617  FAIL_IF_NULL(p);
2618 
2619  /* Expected IP length is 20 + 8 + 8 = 36 as only 2 of the
2620  * fragments should be in the re-assembled packet. */
2621  FAIL_IF(IPV4_GET_RAW_IPLEN(PacketGetIPv4(p)) != 36);
2622 
2623  /* Verify the payload of the IPv4 packet. */
2624  uint8_t expected_payload[] = "AAAAAAAABBBBBBBB";
2625  FAIL_IF(memcmp(GET_PKT_DATA(p) + sizeof(IPV4Hdr), expected_payload, sizeof(expected_payload)));
2626 
2627  SCFree(p1);
2628  SCFree(p2);
2629  SCFree(p3);
2630  SCFree(p);
2631  DefragDestroy();
2632  PASS;
2633 }
2634 
2635 /**
2636  * IPV6: Test the case where you have a packet fragmented in 3 parts
2637  * and send like:
2638  * - Offset: 2; MF: 1
2639  * - Offset: 0; MF: 1
2640  * - Offset: 1; MF: 0
2641  *
2642  * Only the fragments with offset 0 and 1 should be reassembled.
2643  */
2644 static int DefragMfIpv6Test(void)
2645 {
2646  int ip_id = 9;
2647  Packet *p = NULL;
2648  ThreadVars tv;
2649  memset(&tv, 0, sizeof(tv));
2651  memset(&dtv, 0, sizeof(dtv));
2652 
2653  DefragInit();
2654 
2655  Packet *p1 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 2, 1, 'C', 8);
2656  Packet *p2 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 0, 1, 'A', 8);
2657  Packet *p3 = BuildIpv6TestPacket(IPPROTO_ICMPV6, ip_id, 1, 0, 'B', 8);
2658  FAIL_IF(p1 == NULL || p2 == NULL || p3 == NULL);
2659 
2660  p = Defrag(&tv, &dtv, p1);
2661  FAIL_IF_NOT_NULL(p);
2662 
2663  p = Defrag(&tv, &dtv, p2);
2664  FAIL_IF_NOT_NULL(p);
2665 
2666  /* This should return a packet as MF=0. */
2667  p = Defrag(&tv, &dtv, p3);
2668  FAIL_IF_NULL(p);
2669 
2670  /* For IPv6 the expected length is just the length of the payload
2671  * of 2 fragments, so 16. */
2672  FAIL_IF(IPV6_GET_RAW_PLEN(PacketGetIPv6(p)) != 16);
2673 
2674  /* Verify the payload of the IPv4 packet. */
2675  uint8_t expected_payload[] = "AAAAAAAABBBBBBBB";
2676  FAIL_IF(memcmp(GET_PKT_DATA(p) + sizeof(IPV6Hdr), expected_payload, sizeof(expected_payload)));
2677 
2678  SCFree(p1);
2679  SCFree(p2);
2680  SCFree(p3);
2681  SCFree(p);
2682  DefragDestroy();
2683  PASS;
2684 }
2685 
2686 /**
2687  * \brief Test that fragments that match other than the proto don't
2688  * actually get matched.
2689  */
2690 static int DefragTestBadProto(void)
2691 {
2692  Packet *p1 = NULL, *p2 = NULL, *p3 = NULL;
2693  int id = 12;
2694  ThreadVars tv;
2695  memset(&tv, 0, sizeof(tv));
2697  memset(&dtv, 0, sizeof(dtv));
2698 
2699  DefragInit();
2700 
2701  p1 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 8);
2702  FAIL_IF_NULL(p1);
2703  p2 = BuildIpv4TestPacket(IPPROTO_UDP, id, 1, 1, 'B', 8);
2704  FAIL_IF_NULL(p2);
2705  p3 = BuildIpv4TestPacket(IPPROTO_ICMP, id, 2, 0, 'C', 3);
2706  FAIL_IF_NULL(p3);
2707 
2708  FAIL_IF_NOT_NULL(Defrag(&tv, &dtv, p1));
2709  FAIL_IF_NOT_NULL(Defrag(&tv, &dtv, p2));
2710  FAIL_IF_NOT_NULL(Defrag(&tv, &dtv, p3));
2711 
2712  SCFree(p1);
2713  SCFree(p2);
2714  SCFree(p3);
2715 
2716  DefragDestroy();
2717  PASS;
2718 }
2719 
2720 /**
2721  * \test Test a report Linux overlap issue that doesn't appear to be
2722  * covered by the Sturges/Novak tests above.
2723  */
2724 static int DefragTestJeremyLinux(void)
2725 {
2726  ThreadVars tv;
2727  memset(&tv, 0, sizeof(tv));
2729  memset(&dtv, 0, sizeof(dtv));
2730  uint8_t expected[] = "AAAAAAAA"
2731  "AAAAAAAA"
2732  "AAAAAAAA"
2733  "CCCCCCCC"
2734  "CCCCCCCC"
2735  "CCCCCCCC"
2736  "CCCCCCCC"
2737  "CCCCCCCC"
2738  "CCCCCCCC"
2739  "BBBBBBBB"
2740  "BBBBBBBB"
2741  "DDDDDDDD"
2742  "DDDDDD";
2743 
2744  DefragInit();
2745  default_policy = DEFRAG_POLICY_LINUX;
2746 
2747  int id = 1;
2748  Packet *packets[4];
2749  int i = 0;
2750 
2751  packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 0, 1, 'A', 24);
2752  packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 40 >> 3, 1, 'B', 48);
2753  packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 24 >> 3, 1, 'C', 48);
2754  packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, id, 88 >> 3, 0, 'D', 14);
2755 
2756  Packet *r = Defrag(&tv, &dtv, packets[0]);
2757  FAIL_IF_NOT_NULL(r);
2758 
2759  r = Defrag(&tv, &dtv, packets[1]);
2760  FAIL_IF_NOT_NULL(r);
2761 
2762  r = Defrag(&tv, &dtv, packets[2]);
2763  FAIL_IF_NOT_NULL(r);
2764 
2765  r = Defrag(&tv, &dtv, packets[3]);
2766  FAIL_IF_NULL(r);
2767 
2768  FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0);
2769 
2770  for (i = 0; i < 4; i++) {
2771  SCFree(packets[i]);
2772  }
2773  SCFree(r);
2774 
2775  DefragDestroy();
2776  PASS;
2777 }
2778 
2779 /**
2780  * | 0 | 8 | 16 | 24 | 32 |
2781  * |----------|----------|----------|----------|----------|
2782  * | AAAAAAAA | AAAAAAAA |
2783  * | | BBBBBBBB | BBBBBBBB | | |
2784  * | | | CCCCCCCC | CCCCCCCC | |
2785  * | DDDDDDDD | | | | |
2786  *
2787  * | DDDDDDDD | BBBBBBBB | BBBBBBBB | CCCCCCCC | AAAAAAAA |
2788  */
2789 static int DefragBsdFragmentAfterNoMfIpv4Test(void)
2790 {
2791  DefragInit();
2792  default_policy = DEFRAG_POLICY_BSD;
2793  Packet *packets[4];
2794 
2795  packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0, 'A', 16);
2796  packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1, 'B', 16);
2797  packets[2] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1, 'C', 16);
2798  packets[3] = BuildIpv4TestPacket(IPPROTO_ICMP, 0x96, 0, 1, 'D', 8);
2799 
2800  Packet *r = Defrag(NULL, NULL, packets[0]);
2801  FAIL_IF_NOT_NULL(r);
2802 
2803  r = Defrag(NULL, NULL, packets[1]);
2804  FAIL_IF_NOT_NULL(r);
2805 
2806  r = Defrag(NULL, NULL, packets[2]);
2807  FAIL_IF_NOT_NULL(r);
2808 
2809  r = Defrag(NULL, NULL, packets[3]);
2810  FAIL_IF_NULL(r);
2811 
2812  // clang-format off
2813  uint8_t expected[] = {
2814  'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
2815  'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
2816  'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
2817  'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
2818  'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
2819  };
2820  // clang-format on
2821 
2822  if (memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0) {
2823  printf("Expected:\n");
2824  PrintRawDataFp(stdout, expected, sizeof(expected));
2825  printf("Got:\n");
2826  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
2827  FAIL;
2828  }
2829 
2830  DefragDestroy();
2831  PASS;
2832 }
2833 
2834 static int DefragBsdFragmentAfterNoMfIpv6Test(void)
2835 {
2836  DefragInit();
2837  default_policy = DEFRAG_POLICY_BSD;
2838  Packet *packets[4];
2839 
2840  packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 24 >> 3, 0, 'A', 16);
2841  packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 8 >> 3, 1, 'B', 16);
2842  packets[2] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 16 >> 3, 1, 'C', 16);
2843  packets[3] = BuildIpv6TestPacket(IPPROTO_ICMP, 0x96, 0, 1, 'D', 8);
2844 
2845  Packet *r = Defrag(NULL, NULL, packets[0]);
2846  FAIL_IF_NOT_NULL(r);
2847 
2848  r = Defrag(NULL, NULL, packets[1]);
2849  FAIL_IF_NOT_NULL(r);
2850 
2851  r = Defrag(NULL, NULL, packets[2]);
2852  FAIL_IF_NOT_NULL(r);
2853 
2854  r = Defrag(NULL, NULL, packets[3]);
2855  FAIL_IF_NULL(r);
2856 
2857  // clang-format off
2858  uint8_t expected[] = {
2859  'D', 'D', 'D', 'D', 'D', 'D', 'D', 'D',
2860  'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
2861  'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B',
2862  'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C',
2863  'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
2864  };
2865  // clang-format on
2866 
2867  if (memcmp(expected, GET_PKT_DATA(r) + 40, sizeof(expected)) != 0) {
2868  printf("Expected:\n");
2869  PrintRawDataFp(stdout, expected, sizeof(expected));
2870  printf("Got:\n");
2871  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
2872  FAIL;
2873  }
2874 
2875  DefragDestroy();
2876  PASS;
2877 }
2878 
2879 static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2(void)
2880 {
2881  DefragInit();
2882  default_policy = DEFRAG_POLICY_BSD;
2883  Packet *packets[4];
2884 
2885  /* Packet 1: off=16, mf=1 */
2886  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
2887  &packets[0], IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16));
2888 
2889  /* Packet 2: off=8, mf=1 */
2890  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
2891  &packets[1], IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16));
2892 
2893  /* Packet 3: off=0, mf=1: IP and ICMP header. */
2894  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
2895  &packets[2], IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8));
2896 
2897  /* Packet 4: off=8, mf=1 */
2898  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
2899  &packets[3], IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)"DDCCBBAA", 8));
2900 
2901  Packet *r = Defrag(NULL, NULL, packets[0]);
2902  FAIL_IF_NOT_NULL(r);
2903 
2904  r = Defrag(NULL, NULL, packets[1]);
2905  FAIL_IF_NOT_NULL(r);
2906 
2907  r = Defrag(NULL, NULL, packets[2]);
2908  FAIL_IF_NOT_NULL(r);
2909 
2910  r = Defrag(NULL, NULL, packets[3]);
2911  FAIL_IF_NULL(r);
2912 
2913  // clang-format off
2914  const uint8_t expected[] = {
2915  // AACCBBDD
2916  // AACCDDBB
2917  // AABBDDCC
2918  // DDCCBBAA
2919  'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
2920  'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
2921  'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
2922  'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
2923  };
2924  // clang-format on
2925 
2926  FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 20 + 8, sizeof(expected)) != 0);
2927 
2928  DefragDestroy();
2929  PASS;
2930 }
2931 
2932 static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2(void)
2933 {
2934  DefragInit();
2935  default_policy = DEFRAG_POLICY_BSD;
2936  Packet *packets[4];
2937 
2938  /* Packet 1: off=16, mf=1 */
2939  packets[0] = BuildIpv6TestPacketWithContent(
2940  IPPROTO_ICMP, 6, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
2941 
2942  /* Packet 2: off=8, mf=1 */
2943  packets[1] = BuildIpv6TestPacketWithContent(
2944  IPPROTO_ICMP, 6, 8 >> 3, 1, (uint8_t *)"AACCBBDDAACCDDBB", 16);
2945 
2946  /* Packet 3: off=0, mf=1: IP and ICMP header. */
2947  packets[2] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
2948 
2949  /* Packet 4: off=8, mf=1 */
2950  packets[3] =
2951  BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 6, 32 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);
2952 
2953  Packet *r = Defrag(NULL, NULL, packets[0]);
2954  FAIL_IF_NOT_NULL(r);
2955 
2956  r = Defrag(NULL, NULL, packets[1]);
2957  FAIL_IF_NOT_NULL(r);
2958 
2959  r = Defrag(NULL, NULL, packets[2]);
2960  FAIL_IF_NOT_NULL(r);
2961 
2962  r = Defrag(NULL, NULL, packets[3]);
2963  FAIL_IF_NULL(r);
2964 
2965  // clang-format off
2966  const uint8_t expected[] = {
2967  // AACCBBDD
2968  // AACCDDBB
2969  // AABBDDCC
2970  // DDCCBBAA
2971  'A', 'A', 'C', 'C', 'B', 'B', 'D', 'D',
2972  'A', 'A', 'C', 'C', 'D', 'D', 'B', 'B',
2973  'A', 'A', 'B', 'B', 'D', 'D', 'C', 'C',
2974  'D', 'D', 'C', 'C', 'B', 'B', 'A', 'A',
2975  };
2976  // clang-format on
2977 
2978  FAIL_IF(memcmp(expected, GET_PKT_DATA(r) + 40 + 8, sizeof(expected)) != 0);
2979 
2980  DefragDestroy();
2981  PASS;
2982 }
2983 
2984 /**
2985  * #### Input
2986  *
2987  * | 96 (0) | 104 (8) | 112 (16) | 120 (24) |
2988  * |----------|----------|----------|----------|
2989  * | | EEEEEEEE | EEEEEEEE | EEEEEEEE |
2990  * | MMMMMMMM | MMMMMMMM | MMMMMMMM | |
2991  *
2992  * #### Expected Output
2993  *
2994  * | MMMMMMMM | MMMMMMMM | MMMMMMMM | EEEEEEEE |
2995  */
2996 static int DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test(void)
2997 {
2998  DefragInit();
2999  default_policy = DEFRAG_POLICY_BSD;
3000  Packet *packets[2];
3001 
3002  packets[0] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
3003  packets[1] = BuildIpv4TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
3004 
3005  Packet *r = Defrag(NULL, NULL, packets[0]);
3006  FAIL_IF_NOT_NULL(r);
3007 
3008  r = Defrag(NULL, NULL, packets[1]);
3009  FAIL_IF_NULL(r);
3010 
3011  // clang-format off
3012  const uint8_t expected[] = {
3013  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3014  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3015  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3016  'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
3017  };
3018  // clang-format on
3019 
3020  if (memcmp(expected, GET_PKT_DATA(r) + 20, sizeof(expected)) != 0) {
3021  printf("Expected:\n");
3022  PrintRawDataFp(stdout, expected, sizeof(expected));
3023  printf("Got:\n");
3024  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
3025  FAIL;
3026  }
3027 
3028  PASS;
3029 }
3030 
3031 static int DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test(void)
3032 {
3033  DefragInit();
3034  default_policy = DEFRAG_POLICY_BSD;
3035  Packet *packets[2];
3036 
3037  packets[0] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 8 >> 3, 0, 'E', 24);
3038  packets[1] = BuildIpv6TestPacket(IPPROTO_ICMP, 1, 0, 1, 'M', 24);
3039 
3040  Packet *r = Defrag(NULL, NULL, packets[0]);
3041  FAIL_IF_NOT_NULL(r);
3042 
3043  r = Defrag(NULL, NULL, packets[1]);
3044  FAIL_IF_NULL(r);
3045 
3046  // clang-format off
3047  const uint8_t expected[] = {
3048  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3049  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3050  'M', 'M', 'M', 'M', 'M', 'M', 'M', 'M',
3051  'E', 'E', 'E', 'E', 'E', 'E', 'E', 'E',
3052  };
3053  // clang-format on
3054 
3055  if (memcmp(expected, GET_PKT_DATA(r) + 40, sizeof(expected)) != 0) {
3056  printf("Expected:\n");
3057  PrintRawDataFp(stdout, expected, sizeof(expected));
3058  printf("Got:\n");
3059  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
3060  FAIL;
3061  }
3062 
3063  PASS;
3064 }
3065 
3066 /**
3067  * Reassembly should fail.
3068  *
3069  * |0 |8 |16 |24 |32 |40 |48 |
3070  * |========|========|========|========|========|========|========|
3071  * | | |AABBCCDD|AABBDDCC| | | |
3072  * | | | | | |AACCBBDD| |
3073  * | |AACCDDBB|AADDBBCC| | | | |
3074  * |ZZZZZZZZ| | | | | | |
3075  * | | | | | | |DDCCBBAA|
3076  */
3077 static int DefragBsdMissingFragmentIpv4Test(void)
3078 {
3079  DefragInit();
3080  default_policy = DEFRAG_POLICY_BSD;
3081  Packet *packets[5];
3082 
3083  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
3084  &packets[0], IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16));
3085 
3086  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
3087  &packets[1], IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8));
3088 
3089  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
3090  &packets[2], IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16));
3091 
3092  /* ICMP header. */
3093  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
3094  &packets[3], IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8));
3095 
3096  FAIL_IF_NOT(BuildIpv4TestPacketWithContent(
3097  &packets[4], IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8));
3098 
3099  Packet *r = Defrag(NULL, NULL, packets[0]);
3100  FAIL_IF_NOT_NULL(r);
3101 
3102  r = Defrag(NULL, NULL, packets[1]);
3103  FAIL_IF_NOT_NULL(r);
3104 
3105  r = Defrag(NULL, NULL, packets[2]);
3106  FAIL_IF_NOT_NULL(r);
3107 
3108  r = Defrag(NULL, NULL, packets[3]);
3109  FAIL_IF_NOT_NULL(r);
3110 
3111  r = Defrag(NULL, NULL, packets[4]);
3112  FAIL_IF_NOT_NULL(r);
3113 
3114 #if 0
3115  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 20, GET_PKT_LEN(r) - 20);
3116 #endif
3117 
3118  for (int i = 0; i < 5; i++) {
3119  SCFree(packets[i]);
3120  }
3121 
3122  DefragDestroy();
3123 
3124  PASS;
3125 }
3126 
3127 static int DefragBsdMissingFragmentIpv6Test(void)
3128 {
3129  DefragInit();
3130  default_policy = DEFRAG_POLICY_BSD;
3131  Packet *packets[5];
3132 
3133  packets[0] = BuildIpv6TestPacketWithContent(
3134  IPPROTO_ICMP, 189, 16 >> 3, 1, (uint8_t *)"AABBCCDDAABBDDCC", 16);
3135 
3136  packets[1] =
3137  BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 40 >> 3, 1, (uint8_t *)"AACCBBDD", 8);
3138 
3139  packets[2] = BuildIpv6TestPacketWithContent(
3140  IPPROTO_ICMP, 189, 8 >> 3, 1, (uint8_t *)"AACCDDBBAADDBBCC", 16);
3141 
3142  /* ICMP header. */
3143  packets[3] = BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 0, 1, (uint8_t *)"ZZZZZZZZ", 8);
3144 
3145  packets[4] =
3146  BuildIpv6TestPacketWithContent(IPPROTO_ICMP, 189, 48 >> 3, 0, (uint8_t *)"DDCCBBAA", 8);
3147 
3148  Packet *r = Defrag(NULL, NULL, packets[0]);
3149  FAIL_IF_NOT_NULL(r);
3150 
3151  r = Defrag(NULL, NULL, packets[1]);
3152  FAIL_IF_NOT_NULL(r);
3153 
3154  r = Defrag(NULL, NULL, packets[2]);
3155  FAIL_IF_NOT_NULL(r);
3156 
3157  r = Defrag(NULL, NULL, packets[3]);
3158  FAIL_IF_NOT_NULL(r);
3159 
3160  r = Defrag(NULL, NULL, packets[4]);
3161  FAIL_IF_NOT_NULL(r);
3162 
3163 #if 0
3164  PrintRawDataFp(stdout, GET_PKT_DATA(r) + 40, GET_PKT_LEN(r) - 40);
3165 #endif
3166 
3167  for (int i = 0; i < 5; i++) {
3168  SCFree(packets[i]);
3169  }
3170 
3171  DefragDestroy();
3172 
3173  PASS;
3174 }
3175 
3176 #endif /* UNITTESTS */
3177 
3179 {
3180 #ifdef UNITTESTS
3181  UtRegisterTest("DefragInOrderSimpleTest", DefragInOrderSimpleTest);
3182  UtRegisterTest("DefragReverseSimpleTest", DefragReverseSimpleTest);
3183  UtRegisterTest("DefragSturgesNovakBsdTest", DefragSturgesNovakBsdTest);
3184  UtRegisterTest("DefragSturgesNovakLinuxIpv4Test",
3185  DefragSturgesNovakLinuxIpv4Test);
3186  UtRegisterTest("DefragSturgesNovakWindowsIpv4Test",
3187  DefragSturgesNovakWindowsIpv4Test);
3188  UtRegisterTest("DefragSturgesNovakSolarisTest",
3189  DefragSturgesNovakSolarisTest);
3190  UtRegisterTest("DefragSturgesNovakFirstTest", DefragSturgesNovakFirstTest);
3191  UtRegisterTest("DefragSturgesNovakLastTest", DefragSturgesNovakLastTest);
3192 
3193  UtRegisterTest("DefragNoDataIpv4Test", DefragNoDataIpv4Test);
3194  UtRegisterTest("DefragTooLargeIpv4Test", DefragTooLargeIpv4Test);
3195 
3196  UtRegisterTest("DefragInOrderSimpleIpv6Test", DefragInOrderSimpleIpv6Test);
3197  UtRegisterTest("DefragReverseSimpleIpv6Test", DefragReverseSimpleIpv6Test);
3198  UtRegisterTest("DefragSturgesNovakBsdIpv6Test", DefragSturgesNovakBsdIpv6Test);
3199  UtRegisterTest("DefragSturgesNovakLinuxIpv6Test", DefragSturgesNovakLinuxIpv6Test);
3200  UtRegisterTest("DefragSturgesNovakWindowsIpv6Test", DefragSturgesNovakWindowsIpv6Test);
3201  UtRegisterTest("DefragSturgesNovakSolarisIpv6Test", DefragSturgesNovakSolarisIpv6Test);
3202  UtRegisterTest("DefragSturgesNovakFirstIpv6Test", DefragSturgesNovakFirstIpv6Test);
3203  UtRegisterTest("DefragSturgesNovakLastIpv6Test", DefragSturgesNovakLastIpv6Test);
3204 
3205  UtRegisterTest("DefragVlanTest", DefragVlanTest);
3206  UtRegisterTest("DefragVlanQinQTest", DefragVlanQinQTest);
3207  UtRegisterTest("DefragVlanQinQinQTest", DefragVlanQinQinQTest);
3208  UtRegisterTest("DefragTrackerReuseTest", DefragTrackerReuseTest);
3209  UtRegisterTest("DefragTimeoutTest", DefragTimeoutTest);
3210  UtRegisterTest("DefragMfIpv4Test", DefragMfIpv4Test);
3211  UtRegisterTest("DefragMfIpv6Test", DefragMfIpv6Test);
3212  UtRegisterTest("DefragTestBadProto", DefragTestBadProto);
3213 
3214  UtRegisterTest("DefragTestJeremyLinux", DefragTestJeremyLinux);
3215 
3216  UtRegisterTest("DefragBsdFragmentAfterNoMfIpv4Test", DefragBsdFragmentAfterNoMfIpv4Test);
3217  UtRegisterTest("DefragBsdFragmentAfterNoMfIpv6Test", DefragBsdFragmentAfterNoMfIpv6Test);
3218  UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test",
3219  DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test);
3220  UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test",
3221  DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test);
3222  UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2",
3223  DefragBsdSubsequentOverlapsStartOfOriginalIpv4Test_2);
3224  UtRegisterTest("DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2",
3225  DefragBsdSubsequentOverlapsStartOfOriginalIpv6Test_2);
3226  UtRegisterTest("DefragBsdMissingFragmentIpv4Test", DefragBsdMissingFragmentIpv4Test);
3227  UtRegisterTest("DefragBsdMissingFragmentIpv6Test", DefragBsdMissingFragmentIpv6Test);
3228 #endif /* UNITTESTS */
3229 }
ENGINE_SET_EVENT
#define ENGINE_SET_EVENT(p, e)
Definition: decode.h:1165
DEFAULT_DEFRAG_HASH_SIZE
#define DEFAULT_DEFRAG_HASH_SIZE
Definition: defrag.c:65
Frag_
Definition: defrag.h:46
DEFRAG_POLICY_LINUX
@ DEFRAG_POLICY_LINUX
Definition: defrag.c:90
DefragDestroy
void DefragDestroy(void)
Definition: defrag.c:1132
DecodeThreadVars_::counter_defrag_ipv4_reassembled
uint16_t counter_defrag_ipv4_reassembled
Definition: decode.h:999
IPV4_GET_RAW_IPID
#define IPV4_GET_RAW_IPID(ip4h)
Definition: decode-ipv4.h:99
DefragTrackerFreeFrags
void DefragTrackerFreeFrags(DefragTracker *tracker)
Free all frags associated with a tracker.
Definition: defrag.c:132
DefragLookupTrackerFromHash
DefragTracker * DefragLookupTrackerFromHash(Packet *p)
look up a tracker in the hash
Definition: defrag-hash.c:619
len
uint8_t len
Definition: app-layer-dnp3.h:2
D_7
#define D_7
Definition: defrag.c:1881
FAIL_IF_NULL
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
IPV6_GET_RAW_PLEN
#define IPV6_GET_RAW_PLEN(ip6h)
Definition: decode-ipv6.h:66
TIMEOUT_MIN
#define TIMEOUT_MIN
Definition: defrag.c:82
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:166
IPV6_GET_RAW_VER
#define IPV6_GET_RAW_VER(ip6h)
Definition: decode-ipv6.h:62
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
OS_POLICY_HPUX11
@ OS_POLICY_HPUX11
Definition: stream-tcp-reassemble.h:44
IPV4Hdr_::ip_ttl
uint8_t ip_ttl
Definition: decode-ipv4.h:78
PacketFreeOrRelease
void PacketFreeOrRelease(Packet *p)
Return a packet to where it was allocated.
Definition: decode.c:250
D_11
#define D_11
Definition: defrag.c:1885
util-hashlist.h
IPV4_GET_RAW_IPPROTO
#define IPV4_GET_RAW_IPPROTO(ip4h)
Definition: decode-ipv4.h:103
D_3_4
#define D_3_4
Definition: defrag.c:1875
IPV6_EXTHDR_GET_FH_OFFSET
#define IPV6_EXTHDR_GET_FH_OFFSET(p)
Definition: decode-ipv6.h:101
IPV6_GET_RAW_NH
#define IPV6_GET_RAW_NH(ip6h)
Definition: decode-ipv6.h:65
PacketCopyData
int PacketCopyData(Packet *p, const uint8_t *pktdata, uint32_t pktlen)
Copy data to Packet payload and set packet length.
Definition: decode.c:351
OS_POLICY_BSD_RIGHT
@ OS_POLICY_BSD_RIGHT
Definition: stream-tcp-reassemble.h:38
D_3_3
#define D_3_3
Definition: defrag.c:1874
RB_REMOVE
#define RB_REMOVE(name, x, y)
Definition: tree.h:773
OS_POLICY_LINUX
@ OS_POLICY_LINUX
Definition: stream-tcp-reassemble.h:40
IPV4_GET_RAW_FLAG_MF
#define IPV4_GET_RAW_FLAG_MF(ip4h)
Definition: decode-ipv4.h:112
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
D_4
#define D_4
Definition: defrag.c:1878
ENGINE_ISSET_EVENT
#define ENGINE_ISSET_EVENT(p, e)
Definition: decode.h:1178
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:609
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
TIMEOUT_MAX
#define TIMEOUT_MAX
Definition: defrag.c:77
PacketDefragPktSetup
Packet * PacketDefragPktSetup(Packet *parent, const uint8_t *pkt, uint32_t len, uint8_t proto)
Setup a pseudo packet (reassembled frags)
Definition: decode.c:447
OS_POLICY_MACOS
@ OS_POLICY_MACOS
Definition: stream-tcp-reassemble.h:46
Packet_::flags
uint32_t flags
Definition: decode.h:527
IPV6_SET_RAW_VER
#define IPV6_SET_RAW_VER(ip6h, value)
Definition: decode-ipv6.h:69
IPV6_FRAG_PKT_TOO_LARGE
@ IPV6_FRAG_PKT_TOO_LARGE
Definition: decode-events.h:174
threads.h
DefragTracker_::ip_hdr_offset
uint16_t ip_hdr_offset
Definition: defrag.h:89
IP_MF
#define IP_MF
Definition: defrag.c:1144
Frag_::data_len
uint16_t data_len
Definition: defrag.h:61
IPV4_FRAG_IGNORED
@ IPV4_FRAG_IGNORED
Definition: decode-events.h:180
PacketCopyDataOffset
int PacketCopyDataOffset(Packet *p, uint32_t offset, const uint8_t *data, uint32_t datalen)
Copy data to Packet payload at given offset.
Definition: decode.c:309
D_3_5
#define D_3_5
Definition: defrag.c:1876
IPV4Hdr_::ip_id
uint16_t ip_id
Definition: decode-ipv4.h:76
SCMutexLock
#define SCMutexLock(mut)
Definition: threads-debug.h:117
RB_MIN
#define RB_MIN(name, x)
Definition: tree.h:778
DefragContext_::frag_pool
Pool * frag_pool
Definition: defrag.h:37
D_3
#define D_3
Definition: defrag.c:1871
DefragTracker_::host_timeout
uint32_t host_timeout
Definition: defrag.h:111
stream-tcp-reassemble.h
IPV6_FRAG_IGNORED
@ IPV6_FRAG_IGNORED
Definition: decode-events.h:181
proto
uint8_t proto
Definition: decode-template.h:0
defrag-config.h
PacketL3::vars
union PacketL3::@22 vars
D_2
#define D_2
Definition: defrag.c:1870
TmqhOutputPacketpool
void TmqhOutputPacketpool(ThreadVars *t, Packet *p)
Definition: tmqh-packetpool.c:314
MAX
#define MAX(x, y)
Definition: suricata-common.h:404
DefragRbFragCompare
int DefragRbFragCompare(struct Frag_ *a, struct Frag_ *b)
Definition: defrag.c:537
OS_POLICY_IRIX
@ OS_POLICY_IRIX
Definition: stream-tcp-reassemble.h:45
GET_IPV6_DST_ADDR
#define GET_IPV6_DST_ADDR(p)
Definition: decode.h:204
tmqh-packetpool.h
D_10
#define D_10
Definition: defrag.c:1884
util-unittest.h
OS_POLICY_LAST
@ OS_POLICY_LAST
Definition: stream-tcp-reassemble.h:51
OS_POLICY_HPUX10
@ OS_POLICY_HPUX10
Definition: stream-tcp-reassemble.h:43
util-unittest-helper.h
FAIL_IF_NOT
#define FAIL_IF_NOT(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:82
TM_ECODE_OK
@ TM_ECODE_OK
Definition: tm-threads-common.h:81
DEFRAG_POLICY_LAST
@ DEFRAG_POLICY_LAST
Definition: defrag.c:87
Packet_::datalink
int datalink
Definition: decode.h:622
OS_POLICY_BSD
@ OS_POLICY_BSD
Definition: stream-tcp-reassemble.h:37
OS_POLICY_WINDOWS2K3
@ OS_POLICY_WINDOWS2K3
Definition: stream-tcp-reassemble.h:49
DefragTracker_::lock
SCMutex lock
Definition: defrag.h:85
PKT_SET_SRC
#define PKT_SET_SRC(p, src_val)
Definition: decode.h:1301
defrag_policies
defrag_policies
Definition: defrag.c:85
DefragGetOsPolicy
uint8_t DefragGetOsPolicy(Packet *p)
Get the defrag policy based on the destination address of the packet.
Definition: defrag.c:985
IPV4Hdr_::ip_len
uint16_t ip_len
Definition: decode-ipv4.h:75
util-fix_checksum.h
SET_PKT_LEN
#define SET_PKT_LEN(p, len)
Definition: decode.h:213
SCTIME_FROM_SECS
#define SCTIME_FROM_SECS(s)
Definition: util-time.h:69
IPV6_EXTHDR_GET_FH_FLAG
#define IPV6_EXTHDR_GET_FH_FLAG(p)
Definition: decode-ipv6.h:102
decode-ipv6.h
DefragContext_::frag_pool_lock
SCMutex frag_pool_lock
Definition: defrag.h:38
DefragTracker_::remove
uint8_t remove
Definition: defrag.h:104
decode.h
RB_EMPTY
#define RB_EMPTY(head)
Definition: tree.h:327
FAIL_IF_NOT_NULL
#define FAIL_IF_NOT_NULL(expr)
Fail a test if expression evaluates to non-NULL.
Definition: util-unittest.h:96
util-debug.h
RB_NFIND
#define RB_NFIND(name, x, y)
Definition: tree.h:775
SCHInfoGetIPv6HostOSFlavour
int SCHInfoGetIPv6HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv6 address in the raw address format.
Definition: util-host-os-info.c:261
DEFRAG_POLICY_WINDOWS
@ DEFRAG_POLICY_WINDOWS
Definition: defrag.c:91
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
GET_IPV4_DST_ADDR_PTR
#define GET_IPV4_DST_ADDR_PTR(p)
Definition: decode.h:199
Packet_::ts
SCTime_t ts
Definition: decode.h:538
DefragTracker_::seen_last
uint8_t seen_last
Definition: defrag.h:102
IPV4_GET_RAW_FRAGOFFSET
#define IPV4_GET_RAW_FRAGOFFSET(ip4h)
Definition: decode-ipv4.h:101
DefragTracker_::policy
uint8_t policy
Definition: defrag.h:97
SCMutexUnlock
#define SCMutexUnlock(mut)
Definition: threads-debug.h:119
OS_POLICY_SOLARIS
@ OS_POLICY_SOLARIS
Definition: stream-tcp-reassemble.h:42
DecodeIPV6FragHeader
void DecodeIPV6FragHeader(Packet *p, const uint8_t *pkt, uint16_t hdrextlen, uint16_t plen, uint16_t prev_hdrextlen)
Definition: decode-ipv6.c:92
DefragTracker_
Definition: defrag.h:84
SCConfGetInt
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:414
IPV4_FRAG_PKT_TOO_LARGE
@ IPV4_FRAG_PKT_TOO_LARGE
Definition: decode-events.h:173
util-print.h
RB_FOREACH_SAFE
#define RB_FOREACH_SAFE(x, name, head, y)
Definition: tree.h:791
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:209
IPV4_MAXPACKET_LEN
#define IPV4_MAXPACKET_LEN
Definition: decode-ipv4.h:30
DefragRegisterTests
void DefragRegisterTests(void)
Definition: defrag.c:3178
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:58
Pool_::outstanding
uint32_t outstanding
Definition: util-pool.h:67
DefragContext_::timeout
uint32_t timeout
Definition: defrag.h:40
SCTIME_FROM_TIMEVAL
#define SCTIME_FROM_TIMEVAL(tv)
Definition: util-time.h:79
IPV4_GET_RAW_HLEN
#define IPV4_GET_RAW_HLEN(ip4h)
Definition: decode-ipv4.h:96
PacketFree
void PacketFree(Packet *p)
Return a malloced packet.
Definition: decode.c:193
OS_POLICY_OLD_SOLARIS
@ OS_POLICY_OLD_SOLARIS
Definition: stream-tcp-reassemble.h:41
FixChecksum
uint16_t FixChecksum(uint16_t sum, uint16_t old, uint16_t new)
Fix-up an IP checksum.
Definition: util-fix_checksum.c:51
util-time.h
OS_POLICY_WINDOWS
@ OS_POLICY_WINDOWS
Definition: stream-tcp-reassemble.h:47
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:112
SET_IPV4_SRC_ADDR
#define SET_IPV4_SRC_ADDR(ip4h, a)
Definition: decode.h:140
DefragSetDefaultTimeout
void DefragSetDefaultTimeout(int timeout)
Definition: defrag-config.c:132
SET_IPV6_SRC_ADDR
#define SET_IPV6_SRC_ADDR(ip6h, a)
Definition: decode.h:159
RB_FOREACH
#define RB_FOREACH(x, name, head)
Definition: tree.h:781
IPV6Hdr_
Definition: decode-ipv6.h:32
D_3_2
#define D_3_2
Definition: defrag.c:1873
Packet_
Definition: decode.h:484
DefragTracker_::id
uint32_t id
Definition: defrag.h:92
D_8
#define D_8
Definition: defrag.c:1882
IPV4_GET_RAW_IPTTL
#define IPV4_GET_RAW_IPTTL(ip4h)
Definition: decode-ipv4.h:102
DEFRAG_POLICY_FIRST
@ DEFRAG_POLICY_FIRST
Definition: defrag.c:86
DecodeIPV6
int DecodeIPV6(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv6.c:560
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:208
PoolFree
void PoolFree(Pool *p)
Definition: util-pool.c:223
stream-tcp-private.h
conf.h
D_6
#define D_6
Definition: defrag.c:1880
IPV4_GET_RAW_VER
#define IPV4_GET_RAW_VER(ip4h)
Definition: decode-ipv4.h:95
Frag_::skip
uint8_t skip
Definition: defrag.h:55
DefragInitConfig
void DefragInitConfig(bool quiet)
initialize the configuration
Definition: defrag-hash.c:169
Frag_::pkt
uint8_t * pkt
Definition: defrag.h:66
Frag_::data_offset
uint16_t data_offset
Definition: defrag.h:60
queue.h
OS_POLICY_VISTA
@ OS_POLICY_VISTA
Definition: stream-tcp-reassemble.h:48
defrag.h
D_9
#define D_9
Definition: defrag.c:1883
DefragTrackerRelease
void DefragTrackerRelease(DefragTracker *t)
Definition: defrag-hash.c:152
D_3_6
#define D_3_6
Definition: defrag.c:1877
SCMutexInit
#define SCMutexInit(mut, mutattrs)
Definition: threads-debug.h:116
DefragContext_
Definition: defrag.h:36
Frag_::ltrim
uint16_t ltrim
Definition: defrag.h:63
util-host-os-info.h
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
IPV4Hdr_
Definition: decode-ipv4.h:72
default_packet_size
uint32_t default_packet_size
Definition: decode.c:77
PoolReturn
void PoolReturn(Pool *p, void *data)
Definition: util-pool.c:329
D_1
#define D_1
Definition: defrag.c:1869
DefragTracker_::fragment_tree
struct IP_FRAGMENTS fragment_tree
Definition: defrag.h:116
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
Definition: util-unittest.h:71
DefragTreeDestroy
void DefragTreeDestroy(void)
Definition: defrag-config.c:161
IPV6Hdr
struct IPV6Hdr_ IPV6Hdr
suricata-common.h
Frag_::len
uint32_t len
Definition: defrag.h:50
IPV4_HEADER_LEN
#define IPV4_HEADER_LEN
Definition: decode-ipv4.h:28
packet.h
DefragTracker_::timeout
SCTime_t timeout
Definition: defrag.h:110
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
DecodeThreadVars_::counter_defrag_ipv6_reassembled
uint16_t counter_defrag_ipv6_reassembled
Definition: decode.h:1001
DecodeThreadVars_::counter_defrag_no_frags
uint16_t counter_defrag_no_frags
Definition: decode.h:1003
OS_POLICY_OLD_LINUX
@ OS_POLICY_OLD_LINUX
Definition: stream-tcp-reassemble.h:39
FatalError
#define FatalError(...)
Definition: util-debug.h:502
PKT_SRC_DEFRAG
@ PKT_SRC_DEFRAG
Definition: decode.h:57
DefragPolicyLoadFromConfig
void DefragPolicyLoadFromConfig(void)
Definition: defrag-config.c:138
DEFRAG_POLICY_SOLARIS
@ DEFRAG_POLICY_SOLARIS
Definition: defrag.c:92
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
Frag_::frag_hdr_offset
uint16_t frag_hdr_offset
Definition: defrag.h:57
util-validate.h
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
IPV6_MAXPACKET
#define IPV6_MAXPACKET
Definition: decode-ipv6.h:28
Packet_::l3
struct PacketL3 l3
Definition: decode.h:583
Packet_::root
struct Packet_ * root
Definition: decode.h:636
PoolGet
void * PoolGet(Pool *p)
Definition: util-pool.c:271
PKT_REBUILT_FRAGMENT
#define PKT_REBUILT_FRAGMENT
Definition: decode.h:1278
PacketL3::ip6
struct PacketL3::@22::@23 ip6
SCFree
#define SCFree(p)
Definition: util-mem.h:61
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:946
MAX_PAYLOAD_SIZE
#define MAX_PAYLOAD_SIZE
Definition: decode.h:684
Frag_::more_frags
uint8_t more_frags
Definition: defrag.h:54
DefragTracker_::af
uint8_t af
Definition: defrag.h:99
IPV6_EXTHDR_GET_FH_NH
#define IPV6_EXTHDR_GET_FH_NH(p)
Definition: decode-ipv6.h:100
IPV6_FRAG_OVERLAP
@ IPV6_FRAG_OVERLAP
Definition: decode-events.h:176
FAIL
#define FAIL
Fail a test.
Definition: util-unittest.h:60
DefragTracker_::datalink
int datalink
Definition: defrag.h:109
DecodeThreadVars_::counter_defrag_max_hit
uint16_t counter_defrag_max_hit
Definition: decode.h:1002
SCConfSet
int SCConfSet(const char *name, const char *val)
Set a configuration value.
Definition: conf.c:239
util-random.h
SCHInfoGetIPv4HostOSFlavour
int SCHInfoGetIPv4HostOSFlavour(uint8_t *addr)
Retrieves the host os flavour, given an ipv4 address in the raw address format.
Definition: util-host-os-info.c:244
IPV4Hdr_::ip_csum
uint16_t ip_csum
Definition: decode-ipv4.h:80
DEFRAG_POLICY_DEFAULT
@ DEFRAG_POLICY_DEFAULT
Definition: defrag.c:94
suricata.h
defrag-hash.h
Packet_::dst
Address dst
Definition: decode.h:489
TIMEOUT_DEFAULT
#define TIMEOUT_DEFAULT
Definition: defrag.c:72
D_3_1
#define D_3_1
Definition: defrag.c:1872
DecodeThreadVars_::counter_defrag_ipv6_fragments
uint16_t counter_defrag_ipv6_fragments
Definition: decode.h:1000
D_5
#define D_5
Definition: defrag.c:1879
IPV6_HEADER_LEN
#define IPV6_HEADER_LEN
Definition: decode-ipv6.h:27
IPV4_GET_RAW_IPLEN
#define IPV4_GET_RAW_IPLEN(ip4h)
Definition: decode-ipv4.h:98
Packet_::vlan_id
uint16_t vlan_id[VLAN_MAX_LAYERS]
Definition: decode.h:511
af
uint16_t af
Definition: decode-gre.h:0
Frag_::hlen
uint8_t hlen
Definition: defrag.h:52
DEFAULT_DEFRAG_POOL_SIZE
#define DEFAULT_DEFRAG_POOL_SIZE
Definition: defrag.c:66
PacketDefragPktSetupParent
void PacketDefragPktSetupParent(Packet *parent)
inform defrag "parent" that a pseudo packet is now associated to it.
Definition: decode.c:486
DefragGetTrackerFromHash
DefragTracker * DefragGetTrackerFromHash(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Definition: defrag-hash.c:524
DefragHashShutdown
void DefragHashShutdown(void)
shutdown the flow engine
Definition: defrag-hash.c:291
RB_GENERATE
RB_GENERATE(IP_FRAGMENTS, Frag_, rb, DefragRbFragCompare)
IPV4Hdr_::ip_off
uint16_t ip_off
Definition: decode-ipv4.h:77
RB_FOREACH_FROM
#define RB_FOREACH_FROM(x, name, y)
Definition: tree.h:786
Defrag
Packet * Defrag(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Entry point for IPv4 and IPv6 fragments.
Definition: defrag.c:1063
SET_IPV4_DST_ADDR
#define SET_IPV4_DST_ADDR(ip4h, a)
Definition: decode.h:149
DecodeIPV4
int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p, const uint8_t *pkt, uint16_t len)
Definition: decode-ipv4.c:520
PacketInit
void PacketInit(Packet *p)
Initialize a packet structure for use.
Definition: packet.c:63
SCTIME_ADD_SECS
#define SCTIME_ADD_SECS(ts, s)
Definition: util-time.h:64
SET_IPV6_DST_ADDR
#define SET_IPV6_DST_ADDR(ip6h, a)
Definition: decode.h:168
SCCalloc
#define SCCalloc(nm, sz)
Definition: util-mem.h:53
IPV4Hdr_::ip_proto
uint8_t ip_proto
Definition: decode-ipv4.h:79
util-pool.h
PoolInit
Pool * PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void), int(*Init)(void *, void *), void *InitData, void(*Cleanup)(void *), void(*Free)(void *))
Init a Pool.
Definition: util-pool.c:84
IPV4Hdr_::ip_verhl
uint8_t ip_verhl
Definition: decode-ipv4.h:73
IPV4_FRAG_OVERLAP
@ IPV4_FRAG_OVERLAP
Definition: decode-events.h:175
DEFRAG_POLICY_BSD
@ DEFRAG_POLICY_BSD
Definition: defrag.c:88
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:102
Frag_::offset
uint16_t offset
Definition: defrag.h:47
Packet_::src
Address src
Definition: decode.h:488
DefragInit
void DefragInit(void)
Definition: defrag.c:1112
OS_POLICY_FIRST
@ OS_POLICY_FIRST
Definition: stream-tcp-reassemble.h:50
DEFRAG_POLICY_BSD_RIGHT
@ DEFRAG_POLICY_BSD_RIGHT
Definition: defrag.c:89
DecodeThreadVars_::counter_defrag_ipv4_fragments
uint16_t counter_defrag_ipv4_fragments
Definition: decode.h:998