suricata
stream-tcp-list.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2023 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 /** \file
19  *
20  * Segment list functions for insertions, overlap handling, removal and
21  * more.
22  */
23 
24 #include "suricata-common.h"
25 #include "rust.h"
26 #include "stream-tcp-private.h"
27 #include "stream-tcp.h"
28 #include "stream-tcp-reassemble.h"
29 #include "stream-tcp-inline.h"
30 #include "stream-tcp-list.h"
31 #include "util-streaming-buffer.h"
32 #include "util-print.h"
33 #include "util-validate.h"
34 #include "app-layer-frames.h"
35 
36 static void StreamTcpRemoveSegmentFromStream(TcpStream *stream, TcpSegment *seg);
37 
38 static int check_overlap_different_data = 0;
39 
41 {
42  check_overlap_different_data = 1;
43 }
44 
45 /*
46  * Inserts and overlap handling
47  */
48 
50 
51 int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b)
52 {
53  if (SEQ_GT(a->seq, b->seq))
54  return 1;
55  else if (SEQ_LT(a->seq, b->seq))
56  return -1;
57  else {
58  if (a->payload_len == b->payload_len)
59  return 0;
60  else if (a->payload_len > b->payload_len)
61  return 1;
62  else
63  return -1;
64  }
65 }
66 
67 /** \internal
68  * \brief insert segment data into the streaming buffer
69  * \param seg segment to store stream offset in
70  * \param data segment data after overlap handling (if any)
71  * \param data_len data length
72  *
73  * \return SC_OK on success
74  * \return SC_ENOMEM on error (memory allocation error)
75  */
76 static inline int InsertSegmentDataCustom(TcpStream *stream, TcpSegment *seg, uint8_t *data, uint16_t data_len)
77 {
78  uint64_t stream_offset;
79  uint32_t data_offset;
80 
81  if (likely(SEQ_GEQ(seg->seq, stream->base_seq))) {
82  stream_offset = STREAM_BASE_OFFSET(stream) + (seg->seq - stream->base_seq);
83  data_offset = 0;
84  } else {
85  /* segment is partly before base_seq */
86  data_offset = stream->base_seq - seg->seq;
88  }
89 
90  SCLogDebug("stream %p buffer %p, stream_offset %"PRIu64", "
91  "data_offset %"PRIu16", SEQ %u BASE %u, data_len %u",
92  stream, &stream->sb, stream_offset,
93  data_offset, seg->seq, stream->base_seq, data_len);
94  DEBUG_VALIDATE_BUG_ON(data_offset > data_len);
95  if (data_len <= data_offset) {
97  }
98 
99  int ret = StreamingBufferInsertAt(&stream->sb, &stream_config.sbcnf, &seg->sbseg,
100  data + data_offset, data_len - data_offset, stream_offset);
101  if (ret != SC_OK) {
102  SCReturnInt(ret);
103  }
104 #ifdef DEBUG
105  {
106  const uint8_t *mydata;
107  uint32_t mydata_len;
108  uint64_t mydata_offset;
109  StreamingBufferGetData(&stream->sb, &mydata, &mydata_len, &mydata_offset);
110 
111  SCLogDebug("stream %p seg %p data in buffer %p of len %u and offset %"PRIu64,
112  stream, seg, &stream->sb, mydata_len, mydata_offset);
113  //PrintRawDataFp(stdout, mydata, mydata_len);
114  }
115 #endif
117 }
118 
119 /** \internal
120  * \brief check if this segments overlaps with an in-tree seg.
121  * \retval true
122  * \retval false
123  */
124 static inline bool CheckOverlap(struct TCPSEG *tree, TcpSegment *seg)
125 {
126  const uint32_t re = SEG_SEQ_RIGHT_EDGE(seg);
127  SCLogDebug("start. SEQ %u payload_len %u. Right edge: %u. Seg %p",
128  seg->seq, seg->payload_len, re, seg);
129 
130  /* check forward */
131  TcpSegment *next = TCPSEG_RB_NEXT(seg);
132  if (next) {
133  // next has same seq, so data must overlap
134  if (SEQ_EQ(next->seq, seg->seq))
135  return true;
136  // our right edge is beyond next seq, overlap
137  if (SEQ_GT(re, next->seq))
138  return true;
139  }
140  /* check backwards */
141  TcpSegment *prev = TCPSEG_RB_PREV(seg);
142  if (prev) {
143  // prev has same seq, so data must overlap
144  if (SEQ_EQ(prev->seq, seg->seq))
145  return true;
146  // prev's right edge is beyond our seq, overlap
147  const uint32_t prev_re = SEG_SEQ_RIGHT_EDGE(prev);
148  if (SEQ_GT(prev_re, seg->seq))
149  return true;
150  }
151 
152  SCLogDebug("no overlap");
153  return false;
154 }
155 
156 /** \internal
157  * \brief insert the segment into the proper place in the tree
158  * don't worry about the data or overlaps
159  *
160  * \retval 2 not inserted, data overlap
161  * \retval 1 inserted with overlap detected
162  * \retval 0 inserted, no overlap
163  * \retval -EINVAL seg out of seq range
164  */
165 static int DoInsertSegment (TcpStream *stream, TcpSegment *seg, TcpSegment **dup_seg, Packet *p)
166 {
167  /* in lossy traffic, we can get here with the wrong sequence numbers */
168  if (SEQ_LEQ(SEG_SEQ_RIGHT_EDGE(seg), stream->base_seq)) {
169  return -EINVAL;
170  }
171 
172  /* fast track */
173  if (RB_EMPTY(&stream->seg_tree)) {
174  SCLogDebug("empty tree, inserting seg %p seq %" PRIu32 ", "
175  "len %" PRIu32 "", seg, seg->seq, TCP_SEG_LEN(seg));
176  TCPSEG_RB_INSERT(&stream->seg_tree, seg);
177  stream->segs_right_edge = SEG_SEQ_RIGHT_EDGE(seg);
178  return 0;
179  }
180 
181  /* insert and then check if there was any overlap with other segments */
182  TcpSegment *res = TCPSEG_RB_INSERT(&stream->seg_tree, seg);
183  if (res) {
184  SCLogDebug("seg has a duplicate in the tree seq %u/%u",
185  res->seq, res->payload_len);
186  /* exact duplicate SEQ + payload_len */
187  *dup_seg = res;
188  return 2; // duplicate has overlap by definition.
189  } else {
190  if (SEQ_GT(SEG_SEQ_RIGHT_EDGE(seg), stream->segs_right_edge))
191  stream->segs_right_edge = SEG_SEQ_RIGHT_EDGE(seg);
192 
193  /* insert succeeded, now check if we overlap with someone */
194  if (CheckOverlap(&stream->seg_tree, seg) == true) {
195  SCLogDebug("seg %u has overlap in the tree", seg->seq);
196  return 1;
197  }
198  }
199  SCLogDebug("seg %u: no overlap", seg->seq);
200  return 0;
201 }
202 
203 /** \internal
204  * \brief handle overlap per list segment
205  *
206  * For a list segment handle the overlap according to the policy.
207  *
208  * The 'buf' parameter points to the memory that will be inserted into
209  * the stream after the overlap checks are complete. As it will
210  * unconditionally overwrite whats in the stream now, the overlap
211  * policies are applied to this buffer. It starts with the 'new' data,
212  * so when the policy states 'old' data has to be used, 'buf' is
213  * updated to contain the 'old' data here.
214  *
215  * \param buf stack allocated buffer sized p->payload_len that will be
216  * inserted into the stream buffer
217  *
218  * \retval 1 if data was different
219  * \retval 0 data was the same or we didn't check for differences
220  */
221 static int DoHandleDataOverlap(TcpStream *stream, const TcpSegment *list,
222  const TcpSegment *seg, uint8_t *buf, Packet *p)
223 {
224  SCLogDebug("handle overlap for segment %p seq %u len %u re %u, "
225  "list segment %p seq %u len %u re %u", seg, seg->seq,
227  list, list->seq, TCP_SEG_LEN(list), SEG_SEQ_RIGHT_EDGE(list));
228 
229  int data_is_different = 0;
230  int use_new_data = 0;
231 
232  if (StreamTcpInlineMode()) {
233  SCLogDebug("inline mode");
234  if (StreamTcpInlineSegmentCompare(stream, p, list) != 0) {
235  SCLogDebug("already accepted data not the same as packet data, rewrite packet");
236  StreamTcpInlineSegmentReplacePacket(stream, p, list);
237  data_is_different = 1;
238 
239  /* in inline mode we check for different data unconditionally,
240  * but setting events still depends on config */
241  if (check_overlap_different_data) {
243  }
244  }
245 
246  /* IDS mode */
247  } else {
248  if (check_overlap_different_data) {
249  if (StreamTcpInlineSegmentCompare(stream, p, list) != 0) {
250  SCLogDebug("data is different from what is in the list");
251  data_is_different = 1;
252  }
253  } else {
254  /* if we're not checking, assume it's different */
255  data_is_different = 1;
256  }
257 
258  /* apply overlap policies */
259 
260  if (stream->os_policy == OS_POLICY_LAST) {
261  /* buf will start with LAST data (from the segment),
262  * so if policy is LAST we're now done here. */
263  return (check_overlap_different_data && data_is_different);
264  }
265 
266  /* start at the same seq */
267  if (SEQ_EQ(seg->seq, list->seq)) {
268  SCLogDebug("seg starts at list segment");
269 
270  if (SEQ_LT(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
271  SCLogDebug("seg ends before list end, end overlapped by list");
272  } else {
273  if (SEQ_GT(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
274  SCLogDebug("seg ends beyond list end, list overlapped and more");
275  switch (stream->os_policy) {
276  case OS_POLICY_LINUX:
277  if (data_is_different) {
278  use_new_data = 1;
279  }
280  break;
281  }
282  } else {
283  SCLogDebug("full overlap");
284  }
285 
286  switch (stream->os_policy) {
287  case OS_POLICY_OLD_LINUX:
288  case OS_POLICY_SOLARIS:
289  case OS_POLICY_HPUX11:
290  if (data_is_different) {
291  use_new_data = 1;
292  }
293  break;
294  }
295  }
296 
297  /* new seg starts before list segment */
298  } else if (SEQ_LT(seg->seq, list->seq)) {
299  SCLogDebug("seg starts before list segment");
300 
301  if (SEQ_LT(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
302  SCLogDebug("seg ends before list end, end overlapped by list");
303  } else {
304  if (SEQ_GT(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
305  SCLogDebug("seg starts before and fully overlaps list and beyond");
306  } else {
307  SCLogDebug("seg starts before and fully overlaps list");
308  }
309 
310  switch (stream->os_policy) {
311  case OS_POLICY_SOLARIS:
312  case OS_POLICY_HPUX11:
313  if (data_is_different) {
314  use_new_data = 1;
315  }
316  break;
317  }
318  }
319 
320  switch (stream->os_policy) {
321  case OS_POLICY_BSD:
322  case OS_POLICY_HPUX10:
323  case OS_POLICY_IRIX:
324  case OS_POLICY_WINDOWS:
326  case OS_POLICY_OLD_LINUX:
327  case OS_POLICY_LINUX:
328  case OS_POLICY_MACOS:
329  if (data_is_different) {
330  use_new_data = 1;
331  }
332  break;
333  }
334 
335  /* new seg starts after list segment */
336  } else { //if (SEQ_GT(seg->seq, list->seq)) {
337  SCLogDebug("seg starts after list segment");
338 
339  if (SEQ_EQ(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
340  SCLogDebug("seg after and is fully overlapped by list");
341  } else if (SEQ_GT(SEG_SEQ_RIGHT_EDGE(seg), SEG_SEQ_RIGHT_EDGE(list))) {
342  SCLogDebug("seg starts after list and ends after list");
343 
344  switch (stream->os_policy) {
345  case OS_POLICY_SOLARIS:
346  case OS_POLICY_HPUX11:
347  if (data_is_different) {
348  use_new_data = 1;
349  }
350  break;
351  }
352  } else {
353  SCLogDebug("seg starts after list and ends before list end");
354 
355  }
356  }
357  }
358 
359  SCLogDebug("data_is_different %s, use_new_data %s",
360  data_is_different ? "yes" : "no",
361  use_new_data ? "yes" : "no");
362 
363  /* if the data is different and we don't want to use the new (seg)
364  * data, we have to update buf with the list data */
365  if (data_is_different && !use_new_data) {
366  /* we need to copy list into seg */
367  uint32_t list_offset = 0;
368  uint32_t seg_offset = 0;
369  uint32_t list_len;
370  uint16_t seg_len = p->payload_len;
371  uint32_t list_seq = list->seq;
372 
373  const uint8_t *list_data;
374  StreamingBufferSegmentGetData(&stream->sb, &list->sbseg, &list_data, &list_len);
375  DEBUG_VALIDATE_BUG_ON(list_len > USHRT_MAX);
376  if (list_data == NULL || list_len == 0 || list_len > USHRT_MAX)
377  return 0;
378 
379  /* if list seg is partially before base_seq, list_len (from stream) and
380  * TCP_SEG_LEN(list) will not be the same */
381  if (SEQ_GEQ(list->seq, stream->base_seq)) {
382  ;
383  } else {
384  list_seq = stream->base_seq;
385  list_len = SEG_SEQ_RIGHT_EDGE(list) - stream->base_seq;
386  }
387 
388  if (SEQ_LT(seg->seq, list_seq)) {
389  seg_offset = list_seq - seg->seq;
390  seg_len -= seg_offset;
391  } else if (SEQ_GT(seg->seq, list_seq)) {
392  list_offset = seg->seq - list_seq;
393  list_len -= list_offset;
394  }
395 
396  if (SEQ_LT(seg->seq + seg_offset + seg_len, list_seq + list_offset + list_len)) {
397  list_len -= (list_seq + list_offset + list_len) - (seg->seq + seg_offset + seg_len);
398  }
399  SCLogDebug("here goes nothing: list %u %u, seg %u %u", list_offset, list_len, seg_offset, seg_len);
400 
401  //PrintRawDataFp(stdout, list_data + list_offset, list_len);
402  //PrintRawDataFp(stdout, buf + seg_offset, seg_len);
403 
404  memcpy(buf + seg_offset, list_data + list_offset, list_len);
405  //PrintRawDataFp(stdout, buf, p->payload_len);
406  }
407  return (check_overlap_different_data && data_is_different);
408 }
409 
410 /** \internal
411  * \brief walk segment tree backwards to see if there are overlaps
412  *
413  * Walk back from the current segment which is already in the tree.
414  * We walk until we can't possibly overlap anymore.
415  */
416 static int DoHandleDataCheckBackwards(TcpStream *stream,
417  TcpSegment *seg, uint8_t *buf, Packet *p)
418 {
419  int retval = 0;
420 
421  SCLogDebug("check tree backwards: insert data for segment %p seq %u len %u re %u",
422  seg, seg->seq, TCP_SEG_LEN(seg), SEG_SEQ_RIGHT_EDGE(seg));
423 
424  /* check backwards */
425  TcpSegment *tree_seg = NULL, *s = seg;
426  RB_FOREACH_REVERSE_FROM(tree_seg, TCPSEG, s) {
427  if (tree_seg == seg)
428  continue;
429 
430  int overlap = 0;
431  if (SEQ_LEQ(SEG_SEQ_RIGHT_EDGE(tree_seg), stream->base_seq)) {
432  // segment entirely before base_seq
433  ;
434  } else if (SEQ_LEQ(tree_seg->seq + tree_seg->payload_len, seg->seq)) {
435  SCLogDebug("list segment too far to the left, no more overlap will be found");
436  break;
437  } else if (SEQ_GT(SEG_SEQ_RIGHT_EDGE(tree_seg), seg->seq)) {
438  overlap = 1;
439  }
440 
441  SCLogDebug("(back) tree seg %u len %u re %u overlap? %s",
442  tree_seg->seq, TCP_SEG_LEN(tree_seg),
443  SEG_SEQ_RIGHT_EDGE(tree_seg), overlap ? "yes" : "no");
444 
445  if (overlap) {
446  retval |= DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
447  }
448  }
449  return retval;
450 }
451 
452 /** \internal
453  * \brief walk segment tree in forward direction to see if there are overlaps
454  *
455  * Walk forward from the current segment which is already in the tree.
456  * We walk until the next segs start with a SEQ beyond our right edge.
457  *
458  * \retval 1 data was different
459  * \retval 0 data was the same
460  */
461 static int DoHandleDataCheckForward(TcpStream *stream,
462  TcpSegment *seg, uint8_t *buf, Packet *p)
463 {
464  int retval = 0;
465 
466  uint32_t seg_re = SEG_SEQ_RIGHT_EDGE(seg);
467 
468  SCLogDebug("check list forward: insert data for segment %p seq %u len %u re %u",
469  seg, seg->seq, TCP_SEG_LEN(seg), seg_re);
470 
471  TcpSegment *tree_seg = NULL, *s = seg;
472  RB_FOREACH_FROM(tree_seg, TCPSEG, s) {
473  if (tree_seg == seg)
474  continue;
475 
476  int overlap = 0;
477  if (SEQ_GT(seg_re, tree_seg->seq))
478  overlap = 1;
479  else if (SEQ_LEQ(seg_re, tree_seg->seq)) {
480  SCLogDebug("tree segment %u too far ahead, "
481  "no more overlaps can happen", tree_seg->seq);
482  break;
483  }
484 
485  SCLogDebug("(fwd) in-tree seg %u len %u re %u overlap? %s",
486  tree_seg->seq, TCP_SEG_LEN(tree_seg),
487  SEG_SEQ_RIGHT_EDGE(tree_seg), overlap ? "yes" : "no");
488 
489  if (overlap) {
490  retval |= DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
491  }
492  }
493  return retval;
494 }
495 
496 /**
497  * \param tree_seg in-tree duplicate of `seg`
498  * \retval res 0 ok, -1 insertion error due to memcap
499  */
500 static int DoHandleData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx,
501  TcpStream *stream, TcpSegment *seg, TcpSegment *tree_seg, Packet *p)
502 {
503  int result = 0;
504  TcpSegment *handle = seg;
505 
506  SCLogDebug("insert data for segment %p seq %u len %u re %u",
507  seg, seg->seq, TCP_SEG_LEN(seg), SEG_SEQ_RIGHT_EDGE(seg));
508 
509  /* create temporary buffer to contain the data we will insert. Overlap
510  * handling may update it. By using this we don't have to track whether
511  * parts of the data are already inserted or not. */
512  uint8_t buf[p->payload_len];
513  memcpy(buf, p->payload, p->payload_len);
514 
515  /* if tree_seg is set, we have an exact duplicate that we need to check */
516  if (tree_seg) {
517  DoHandleDataOverlap(stream, tree_seg, seg, buf, p);
518  handle = tree_seg;
519  }
520 
521  const bool is_head = !(TCPSEG_RB_PREV(handle));
522  const bool is_tail = !(TCPSEG_RB_NEXT(handle));
523 
524  /* new list head */
525  if (is_head && !is_tail) {
526  result = DoHandleDataCheckForward(stream, handle, buf, p);
527 
528  /* new list tail */
529  } else if (!is_head && is_tail) {
530  result = DoHandleDataCheckBackwards(stream, handle, buf, p);
531 
532  /* middle of the list */
533  } else if (!is_head && !is_tail) {
534  result = DoHandleDataCheckBackwards(stream, handle, buf, p);
535  result |= DoHandleDataCheckForward(stream, handle, buf, p);
536  }
537 
538  /* we had an overlap with different data */
539  if (result) {
542  }
543 
544  /* insert the temp buffer now that we've (possibly) updated
545  * it to account for the overlap policies */
546  int res = InsertSegmentDataCustom(stream, handle, buf, p->payload_len);
547  if (res != SC_OK) {
548  if (res == SC_ENOMEM) {
551  } else if (res == SC_ELIMIT) {
553  } else if (res == SC_EINVAL) {
555  } else {
557  }
558  return -1;
559  }
560 
561  return 0;
562 }
563 
564 /** \internal
565  * \brief Add the header data to the segment
566  * \param rp packet to take the headers from. Might differ from `pp` in tunnels.
567  * \param pp packet to take the payload size from.
568  */
569 static void StreamTcpSegmentAddPacketDataDo(TcpSegment *seg, const Packet *rp, const Packet *pp)
570 {
571  if (GET_PKT_DATA(rp) != NULL && GET_PKT_LEN(rp) > pp->payload_len) {
572  seg->pcap_hdr_storage->ts.tv_sec = SCTIME_SECS(rp->ts);
573  seg->pcap_hdr_storage->ts.tv_usec = SCTIME_USECS(rp->ts);
575  /*
576  * pkt_hdr members are initially allocated 64 bytes of memory. Thus,
577  * need to check that this is sufficient and allocate more memory if
578  * not.
579  */
580  if (seg->pcap_hdr_storage->pktlen > seg->pcap_hdr_storage->alloclen) {
581  uint8_t *tmp_pkt_hdr = StreamTcpReassembleRealloc(seg->pcap_hdr_storage->pkt_hdr,
583  if (tmp_pkt_hdr == NULL) {
584  SCLogDebug("Failed to realloc");
585  seg->pcap_hdr_storage->ts.tv_sec = 0;
586  seg->pcap_hdr_storage->ts.tv_usec = 0;
587  seg->pcap_hdr_storage->pktlen = 0;
588  return;
589  } else {
590  seg->pcap_hdr_storage->pkt_hdr = tmp_pkt_hdr;
592  }
593  }
594  memcpy(seg->pcap_hdr_storage->pkt_hdr, GET_PKT_DATA(rp),
595  (size_t)GET_PKT_LEN(rp) - pp->payload_len);
596  } else {
597  seg->pcap_hdr_storage->ts.tv_sec = 0;
598  seg->pcap_hdr_storage->ts.tv_usec = 0;
599  seg->pcap_hdr_storage->pktlen = 0;
600  }
601 }
602 
603 /**
604  * \brief Adds the following information to the TcpSegment from the current
605  * packet being processed: time values, packet length, and the
606  * header data of the packet. This information is added to the TcpSegment so
607  * that it can be used in pcap capturing (log-pcap-stream) to dump the tcp
608  * session at the beginning of the pcap capture.
609  * \param seg TcpSegment where information is being stored.
610  * \param p Packet being processed.
611  * \param tv Thread-specific variables.
612  * \param ra_ctx TcpReassembly thread-specific variables
613  */
614 static void StreamTcpSegmentAddPacketData(
616 {
617  if (seg->pcap_hdr_storage == NULL || seg->pcap_hdr_storage->pkt_hdr == NULL) {
618  return;
619  }
620 
621  if (PacketIsTunnelChild(p)) {
622  Packet *rp = p->root;
623  StreamTcpSegmentAddPacketDataDo(seg, rp, p);
624  } else {
625  StreamTcpSegmentAddPacketDataDo(seg, p, p);
626  }
627 }
628 
629 /**
630  * \return 0 ok
631  * \return -1 segment not inserted due to memcap issue
632  *
633  * \param seg segment, this function takes total ownership
634  *
635  * In case of error, this function returns the segment to the pool
636  */
638  TcpStream *stream, TcpSegment *seg, Packet *p,
639  uint32_t pkt_seq, uint8_t *pkt_data, uint16_t pkt_datalen)
640 {
641  SCEnter();
642 
643  TcpSegment *dup_seg = NULL;
644 
645  /* insert segment into list. Note: doesn't handle the data */
646  int r = DoInsertSegment (stream, seg, &dup_seg, p);
647 
649  StreamTcpSegmentAddPacketData(seg, p, tv, ra_ctx);
650  }
651 
652  if (likely(r == 0)) {
653  /* no overlap, straight data insert */
654  int res = InsertSegmentDataCustom(stream, seg, pkt_data, pkt_datalen);
655  if (res != SC_OK) {
657  StreamTcpRemoveSegmentFromStream(stream, seg);
659  if (res == SC_ENOMEM) {
662  }
663  SCReturnInt(-1);
664  }
665 
666  } else if (r == 1 || r == 2) {
667  SCLogDebug("overlap (%s%s)", r == 1 ? "normal" : "", r == 2 ? "duplicate" : "");
668 
669  if (r == 2) {
670  SCLogDebug("dup_seg %p", dup_seg);
671  }
672 
673  /* XXX should we exclude 'retransmissions' here? */
675 
676  /* now let's consider the data in the overlap case */
677  int res = DoHandleData(tv, ra_ctx, stream, seg, dup_seg, p);
678  if (res < 0) {
680 
681  if (r == 1) // r == 2 mean seg wasn't added to stream
682  StreamTcpRemoveSegmentFromStream(stream, seg);
683 
685  SCReturnInt(-1);
686  }
687  if (r == 2) {
688  SCLogDebug("duplicate segment %u/%u, discard it",
689  seg->seq, seg->payload_len);
690 
692 #ifdef DEBUG
693  if (SCLogDebugEnabled()) {
694  TcpSegment *s = NULL, *safe = NULL;
695  RB_FOREACH_SAFE(s, TCPSEG, &stream->seg_tree, safe)
696  {
697  SCLogDebug("tree: seg %p, SEQ %"PRIu32", LEN %"PRIu16", SUM %"PRIu32"%s%s%s",
698  s, s->seq, TCP_SEG_LEN(s),
699  (uint32_t)(s->seq + TCP_SEG_LEN(s)),
700  s->seq == seg->seq ? " DUPLICATE" : "",
701  TCPSEG_RB_PREV(s) == NULL ? " HEAD" : "",
702  TCPSEG_RB_NEXT(s) == NULL ? " TAIL" : "");
703  }
704  }
705 #endif
706  }
707  } else {
708  // EINVAL
710  }
711 
712  SCReturnInt(0);
713 }
714 
715 
716 /*
717  * Pruning & removal
718  */
719 
720 
721 static inline bool SegmentInUse(const TcpStream *stream, const TcpSegment *seg)
722 {
723  /* if proto detect isn't done, we're not returning */
724  if (!(stream->flags & STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) {
726  SCReturnInt(true);
727  }
728  }
729 
730  SCReturnInt(false);
731 }
732 
733 
734 /** \internal
735  * \brief check if we can remove a segment from our segment list
736  *
737  * \retval true
738  * \retval false
739  */
740 static inline bool StreamTcpReturnSegmentCheck(const TcpStream *stream, const TcpSegment *seg)
741 {
742  if (SegmentInUse(stream, seg)) {
743  SCReturnInt(false);
744  }
745 
746  if (!(StreamingBufferSegmentIsBeforeWindow(&stream->sb, &seg->sbseg))) {
747  SCReturnInt(false);
748  }
749 
750  SCReturnInt(true);
751 }
752 
753 static inline uint64_t GetLeftEdgeForApp(Flow *f, TcpSession *ssn, TcpStream *stream)
754 {
755  const FramesContainer *frames_container = AppLayerFramesGetContainer(f);
756  if (frames_container == NULL)
757  return STREAM_APP_PROGRESS(stream);
758 
759  const Frames *frames =
760  stream == &ssn->client ? &frames_container->toserver : &frames_container->toclient;
761  // const uint64_t x = FramesLeftEdge(stream, frames);
762  // BUG_ON(x != (frames->left_edge_rel + STREAM_BASE_OFFSET(stream)));
763  // return x;
764  const uint64_t o = (uint64_t)frames->left_edge_rel + STREAM_BASE_OFFSET(stream);
765  SCLogDebug(
766  "%s: frames left edge: %" PRIu64, &ssn->client == stream ? "toserver" : "toclient", o);
767  return o;
768 }
769 
770 static inline uint64_t GetLeftEdge(Flow *f, TcpSession *ssn, TcpStream *stream)
771 {
772  uint64_t left_edge = 0;
773  const bool use_app = !(ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED);
774  const bool use_raw = !(stream->flags & STREAMTCP_STREAM_FLAG_DISABLE_RAW);
775  const bool use_log = stream_config.streaming_log_api;
776  SCLogDebug("use_app %d use_raw %d use_log %d tcp win %u", use_app, use_raw, use_log,
777  stream->window);
778 
779  if (use_raw) {
780  uint64_t raw_progress = STREAM_RAW_PROGRESS(stream);
781 
782  if (StreamTcpInlineMode()) {
783  uint32_t chunk_size = (stream == &ssn->client) ?
786  if (raw_progress < (uint64_t)chunk_size) {
787  raw_progress = 0;
788  } else {
789  raw_progress -= (uint64_t)chunk_size;
790  }
791  }
792 
793  /* apply min inspect depth: if it is set we need to keep data
794  * before the raw progress. */
795  if (use_app && stream->min_inspect_depth && ssn->state < TCP_CLOSED) {
796  if (raw_progress < stream->min_inspect_depth)
797  raw_progress = 0;
798  else
799  raw_progress -= stream->min_inspect_depth;
800 
801  SCLogDebug("stream->min_inspect_depth %u, raw_progress %"PRIu64,
802  stream->min_inspect_depth, raw_progress);
803  }
804 
805  if (use_app) {
806  const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
807  left_edge = MIN(app_le, raw_progress);
808  SCLogDebug("left_edge %" PRIu64 ", using both app:%" PRIu64 ", raw:%" PRIu64, left_edge,
809  app_le, raw_progress);
810  } else {
811  left_edge = raw_progress;
812  SCLogDebug("left_edge %"PRIu64", using only raw:%"PRIu64,
813  left_edge, raw_progress);
814  }
815  } else if (use_app) {
816  const uint64_t app_le = GetLeftEdgeForApp(f, ssn, stream);
817  left_edge = app_le;
818  SCLogDebug("left_edge %" PRIu64 ", using only app:%" PRIu64, left_edge, app_le);
819  } else {
820  left_edge = StreamingBufferGetConsecutiveDataRightEdge(&stream->sb);
821  SCLogDebug("no app & raw: left_edge %"PRIu64" (full stream)", left_edge);
822  }
823 
824  if (use_log) {
825  if (use_app || use_raw) {
826  left_edge = MIN(left_edge, STREAM_LOG_PROGRESS(stream));
827  } else {
828  left_edge = STREAM_LOG_PROGRESS(stream);
829  }
830  }
831 
832  uint64_t last_ack_abs = STREAM_BASE_OFFSET(stream);
833  if (STREAM_LASTACK_GT_BASESEQ(stream)) {
834  last_ack_abs += (stream->last_ack - stream->base_seq);
835  }
836  /* in IDS mode we shouldn't see the base_seq pass last_ack */
837  DEBUG_VALIDATE_BUG_ON(last_ack_abs < left_edge && !StreamTcpInlineMode() && !f->ffr &&
838  ssn->state < TCP_CLOSED);
839  left_edge = MIN(left_edge, last_ack_abs);
840 
841  /* if we're told to look for overlaps with different data we should
842  * consider data that is ack'd as well. Injected packets may have
843  * been ack'd or injected packet may be too late. */
844  if (!StreamTcpInlineMode() && check_overlap_different_data) {
845  const uint32_t window = stream->window ? stream->window : 4096;
846  if (window < left_edge)
847  left_edge -= window;
848  else
849  left_edge = 0;
850 
851  SCLogDebug("stream:%p left_edge %"PRIu64, stream, left_edge);
852  }
853 
854  if (left_edge > 0) {
855  /* we know left edge based on the progress values now,
856  * lets adjust it to make sure in-use segments still have
857  * data */
858  TcpSegment *seg = NULL;
859  RB_FOREACH(seg, TCPSEG, &stream->seg_tree) {
860  if (TCP_SEG_OFFSET(seg) > left_edge) {
861  SCLogDebug("seg beyond left_edge, we're done");
862  break;
863  }
864 
865  if (SegmentInUse(stream, seg)) {
866  left_edge = TCP_SEG_OFFSET(seg);
867  SCLogDebug("in-use seg before left_edge, adjust to %"PRIu64" and bail", left_edge);
868  break;
869  }
870  }
871  }
872 
873  return left_edge;
874 }
875 
876 static void StreamTcpRemoveSegmentFromStream(TcpStream *stream, TcpSegment *seg)
877 {
878  RB_REMOVE(TCPSEG, &stream->seg_tree, seg);
879 }
880 
881 /** \brief Remove idle TcpSegments from TcpSession
882  *
883  * Checks app progress and raw progress and progresses them
884  * if needed, slides the streaming buffer, then gets rid of
885  * excess segments.
886  *
887  * \param f flow
888  * \param flags direction flags
889  */
891 {
892  SCEnter();
893 
894  if (f == NULL || f->protoctx == NULL) {
895  SCReturn;
896  }
897 
898  TcpSession *ssn = f->protoctx;
899  TcpStream *stream = NULL;
900 
901  if (flags & STREAM_TOSERVER) {
902  stream = &ssn->client;
903  } else if (flags & STREAM_TOCLIENT) {
904  stream = &ssn->server;
905  } else {
906  SCReturn;
907  }
908 
910  return;
911  }
912 
915  SCLogDebug("ssn %p / stream %p: reassembly depth reached, "
916  "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
919  return;
920 
921  } else if ((ssn->flags & STREAMTCP_FLAG_APP_LAYER_DISABLED) &&
923  SCLogDebug("ssn %p / stream %p: both app and raw are done, "
924  "STREAMTCP_STREAM_FLAG_NOREASSEMBLY set", ssn, stream);
928  return;
929  }
930 
931  const uint64_t left_edge = GetLeftEdge(f, ssn, stream);
932  SCLogDebug("buffer left_edge %" PRIu64, left_edge);
933  if (left_edge && left_edge > STREAM_BASE_OFFSET(stream)) {
934  uint32_t slide = left_edge - STREAM_BASE_OFFSET(stream);
935  SCLogDebug("buffer sliding %u to offset %"PRIu64, slide, left_edge);
936 
938  AppLayerFramesSlide(f, slide, flags & (STREAM_TOSERVER | STREAM_TOCLIENT));
939  }
940  StreamingBufferSlideToOffset(&stream->sb, &stream_config.sbcnf, left_edge);
941  stream->base_seq += slide;
942 
943  if (slide <= stream->app_progress_rel) {
944  stream->app_progress_rel -= slide;
945  } else {
946  stream->app_progress_rel = 0;
947  }
948  if (slide <= stream->raw_progress_rel) {
949  stream->raw_progress_rel -= slide;
950  } else {
951  stream->raw_progress_rel = 0;
952  }
953  if (slide <= stream->log_progress_rel) {
954  stream->log_progress_rel -= slide;
955  } else {
956  stream->log_progress_rel = 0;
957  }
958 
959  SCLogDebug("stream base_seq %u at stream offset %"PRIu64,
960  stream->base_seq, STREAM_BASE_OFFSET(stream));
961  }
962 
963  /* loop through the segments and remove all not in use */
964  TcpSegment *seg = NULL, *safe = NULL;
965  RB_FOREACH_SAFE(seg, TCPSEG, &stream->seg_tree, safe)
966  {
967  SCLogDebug("seg %p, SEQ %"PRIu32", LEN %"PRIu16", SUM %"PRIu32,
968  seg, seg->seq, TCP_SEG_LEN(seg),
969  (uint32_t)(seg->seq + TCP_SEG_LEN(seg)));
970 
971  if (StreamTcpReturnSegmentCheck(stream, seg) == 0) {
972  SCLogDebug("not removing segment");
973  break;
974  }
975 
976  StreamTcpRemoveSegmentFromStream(stream, seg);
978  SCLogDebug("removed segment");
979  continue;
980  }
981 
982  SCReturn;
983 }
984 
985 
986 /*
987  * unittests
988  */
989 
990 #ifdef UNITTESTS
991 #include "tests/stream-tcp-list.c"
992 #endif
StreamTcpSetEvent
#define StreamTcpSetEvent(p, e)
Definition: stream-tcp-private.h:270
StreamingBufferSlideToOffset
void StreamingBufferSlideToOffset(StreamingBuffer *sb, const StreamingBufferConfig *cfg, uint64_t offset)
slide to absolute offset
Definition: util-streaming-buffer.c:1000
TcpStream_
Definition: stream-tcp-private.h:106
RB_GENERATE
RB_GENERATE(TCPSEG, TcpSegment, rb, TcpSegmentCompare)
StatsIncr
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition: counters.c:167
StreamTcpSegmentReturntoPool
void StreamTcpSegmentReturntoPool(TcpSegment *seg)
Function to return the segment back to the pool.
Definition: stream-tcp-reassemble.c:379
IsTcpSessionDumpingEnabled
bool IsTcpSessionDumpingEnabled(void)
Definition: stream-tcp-reassemble.c:89
TCP_SEG_LEN
#define TCP_SEG_LEN(seg)
Definition: stream-tcp-private.h:94
stream-tcp-inline.h
stream-tcp.h
StreamTcpInlineMode
bool StreamTcpInlineMode(void)
See if stream engine is operating in inline mode.
Definition: stream-tcp.c:6853
RB_REMOVE
#define RB_REMOVE(name, x, y)
Definition: tree.h:773
StreamTcpReassembleInsertSegment
int StreamTcpReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, TcpSegment *seg, Packet *p, uint32_t pkt_seq, uint8_t *pkt_data, uint16_t pkt_datalen)
Definition: stream-tcp-list.c:637
TcpStream_::seg_tree
struct TCPSEG seg_tree
Definition: stream-tcp-private.h:136
OS_POLICY_MACOS
@ OS_POLICY_MACOS
Definition: stream-tcp-reassemble.h:45
TcpStream_::log_progress_rel
uint32_t log_progress_rel
Definition: stream-tcp-private.h:129
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:269
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
OS_POLICY_OLD_LINUX
@ OS_POLICY_OLD_LINUX
Definition: stream-tcp-reassemble.h:38
Packet_::payload
uint8_t * payload
Definition: decode.h:586
FramesContainer::toserver
Frames toserver
Definition: app-layer-frames.h:74
OS_POLICY_IRIX
@ OS_POLICY_IRIX
Definition: stream-tcp-reassemble.h:44
TcpStream_::os_policy
uint8_t os_policy
Definition: stream-tcp-private.h:110
Flow_
Flow data structure.
Definition: flow.h:350
TcpSegment::sbseg
StreamingBufferSegment sbseg
Definition: stream-tcp-private.h:77
SC_EINVAL
@ SC_EINVAL
Definition: util-error.h:30
StreamTcpReassembleConfigEnableOverlapCheck
void StreamTcpReassembleConfigEnableOverlapCheck(void)
Definition: stream-tcp-list.c:40
TcpStreamCnf_::sbcnf
StreamingBufferConfig sbcnf
Definition: stream-tcp.h:76
StreamingBufferGetData
int StreamingBufferGetData(const StreamingBuffer *sb, const uint8_t **data, uint32_t *data_len, uint64_t *stream_offset)
Definition: util-streaming-buffer.c:1754
StreamTcpInlineSegmentReplacePacket
void StreamTcpInlineSegmentReplacePacket(const TcpStream *stream, Packet *p, const TcpSegment *seg)
Replace (part of) the payload portion of a packet by the data in a TCP segment.
Definition: stream-tcp-inline.c:120
rust.h
TcpReassemblyThreadCtx_::counter_tcp_reass_overlap
uint16_t counter_tcp_reass_overlap
Definition: stream-tcp-reassemble.h:77
MIN
#define MIN(x, y)
Definition: suricata-common.h:391
Frames
Definition: app-layer-frames.h:60
FramesContainer
Definition: app-layer-frames.h:73
stream-tcp-reassemble.h
TcpSegment::seq
uint32_t seq
Definition: stream-tcp-private.h:75
TcpStream_::flags
uint16_t flags
Definition: stream-tcp-private.h:107
TcpReassemblyThreadCtx_::counter_tcp_reass_overlap_diff_data
uint16_t counter_tcp_reass_overlap_diff_data
Definition: stream-tcp-reassemble.h:79
TcpStreamCnf_::streaming_log_api
bool streaming_log_api
Definition: stream-tcp.h:61
Frames::left_edge_rel
uint32_t left_edge_rel
Definition: app-layer-frames.h:63
stream_config
TcpStreamCnf stream_config
Definition: stream-tcp.c:115
Flow_::protoctx
void * protoctx
Definition: flow.h:440
stream_offset
uint64_t stream_offset
Definition: util-streaming-buffer.h:1
Packet_::payload_len
uint16_t payload_len
Definition: decode.h:587
STREAMTCP_STREAM_FLAG_DEPTH_REACHED
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
Definition: stream-tcp-private.h:223
SC_ELIMIT
@ SC_ELIMIT
Definition: util-error.h:31
TcpSegmentPcapHdrStorage_::pktlen
uint32_t pktlen
Definition: stream-tcp-private.h:67
SC_ENOMEM
@ SC_ENOMEM
Definition: util-error.h:29
STREAM_LOG_PROGRESS
#define STREAM_LOG_PROGRESS(stream)
Definition: stream-tcp-private.h:147
TcpSession_::flags
uint32_t flags
Definition: stream-tcp-private.h:292
TCP_SEG_OFFSET
#define TCP_SEG_OFFSET(seg)
Definition: stream-tcp-private.h:95
TcpReassemblyThreadCtx_::counter_tcp_reass_data_normal_fail
uint16_t counter_tcp_reass_data_normal_fail
Definition: stream-tcp-reassemble.h:81
TcpStream_::last_ack
uint32_t last_ack
Definition: stream-tcp-private.h:115
FramesContainer::toclient
Frames toclient
Definition: app-layer-frames.h:75
RB_EMPTY
#define RB_EMPTY(head)
Definition: tree.h:327
StreamTcpReassembleRealloc
void * StreamTcpReassembleRealloc(void *optr, size_t orig_size, size_t size)
Definition: stream-tcp-reassemble.c:227
STREAM_REASSEMBLY_INSERT_INVALID
@ STREAM_REASSEMBLY_INSERT_INVALID
Definition: decode-events.h:298
StreamingBufferSegmentIsBeforeWindow
int StreamingBufferSegmentIsBeforeWindow(const StreamingBuffer *sb, const StreamingBufferSegment *seg)
Definition: util-streaming-buffer.c:1593
Packet_::ts
SCTime_t ts
Definition: decode.h:484
STREAM_BASE_OFFSET
#define STREAM_BASE_OFFSET(stream)
Definition: stream-tcp-private.h:144
TcpStream_::min_inspect_depth
uint32_t min_inspect_depth
Definition: stream-tcp-private.h:131
TcpSegmentCompare
int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b)
compare function for the Segment tree
Definition: stream-tcp-list.c:51
util-print.h
OS_POLICY_BSD
@ OS_POLICY_BSD
Definition: stream-tcp-reassemble.h:36
RB_FOREACH_SAFE
#define RB_FOREACH_SAFE(x, name, head, y)
Definition: tree.h:791
SCEnter
#define SCEnter(...)
Definition: util-debug.h:271
GET_PKT_DATA
#define GET_PKT_DATA(p)
Definition: decode.h:220
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
StreamingBufferClear
void StreamingBufferClear(StreamingBuffer *sb, const StreamingBufferConfig *cfg)
Definition: util-streaming-buffer.c:272
TcpSession_::state
uint8_t state
Definition: stream-tcp-private.h:285
TcpStream_::segs_right_edge
uint32_t segs_right_edge
Definition: stream-tcp-private.h:137
AppLayerFramesSlide
void AppLayerFramesSlide(Flow *f, const uint32_t slide, const uint8_t direction)
Definition: app-layer-frames.c:361
stream-tcp-list.h
StreamTcpPruneSession
void StreamTcpPruneSession(Flow *f, uint8_t flags)
Remove idle TcpSegments from TcpSession.
Definition: stream-tcp-list.c:890
RB_FOREACH
#define RB_FOREACH(x, name, head)
Definition: tree.h:781
SCReturn
#define SCReturn
Definition: util-debug.h:273
TcpSegment
Definition: stream-tcp-private.h:72
StreamTcpIsSetStreamFlagAppProtoDetectionCompleted
#define StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream)
Definition: stream-tcp-private.h:301
Packet_
Definition: decode.h:436
AppLayerFramesGetContainer
FramesContainer * AppLayerFramesGetContainer(Flow *f)
Definition: app-layer-parser.c:182
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:219
stream-tcp-private.h
TcpStream_::window
uint32_t window
Definition: stream-tcp-private.h:117
SC_OK
@ SC_OK
Definition: util-error.h:27
SEG_SEQ_RIGHT_EDGE
#define SEG_SEQ_RIGHT_EDGE(seg)
Definition: stream-tcp-private.h:97
STREAM_REASSEMBLY_INSERT_MEMCAP
@ STREAM_REASSEMBLY_INSERT_MEMCAP
Definition: decode-events.h:296
StreamTcpReturnStreamSegments
void StreamTcpReturnStreamSegments(TcpStream *stream)
return all segments in this stream into the pool(s)
Definition: stream-tcp-reassemble.c:396
TcpSegment::payload_len
uint16_t payload_len
Definition: stream-tcp-private.h:74
TcpStream_::raw_progress_rel
uint32_t raw_progress_rel
Definition: stream-tcp-private.h:128
stream-tcp-list.c
TCP_CLOSED
@ TCP_CLOSED
Definition: stream-tcp-private.h:162
Flow_::ffr
uint8_t ffr
Definition: flow.h:384
app-layer-frames.h
SEQ_GEQ
#define SEQ_GEQ(a, b)
Definition: stream-tcp-private.h:260
flags
uint8_t flags
Definition: decode-gre.h:0
OS_POLICY_HPUX10
@ OS_POLICY_HPUX10
Definition: stream-tcp-reassemble.h:42
suricata-common.h
SEQ_GT
#define SEQ_GT(a, b)
Definition: stream-tcp-private.h:259
util-streaming-buffer.h
TcpSegmentPcapHdrStorage_::ts
struct timeval ts
Definition: stream-tcp-private.h:66
TcpStream_::base_seq
uint32_t base_seq
Definition: stream-tcp-private.h:124
TcpStream_::sb
StreamingBuffer sb
Definition: stream-tcp-private.h:135
TcpSegmentPcapHdrStorage_::alloclen
uint32_t alloclen
Definition: stream-tcp-private.h:68
SCTIME_SECS
#define SCTIME_SECS(t)
Definition: util-time.h:57
TcpSession_::client
TcpStream client
Definition: stream-tcp-private.h:295
OS_POLICY_SOLARIS
@ OS_POLICY_SOLARIS
Definition: stream-tcp-reassemble.h:41
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
OS_POLICY_WINDOWS
@ OS_POLICY_WINDOWS
Definition: stream-tcp-reassemble.h:46
TcpStreamCnf_::reassembly_toclient_chunk_size
uint16_t reassembly_toclient_chunk_size
Definition: stream-tcp.h:67
util-validate.h
StreamTcpInlineSegmentCompare
int StreamTcpInlineSegmentCompare(const TcpStream *stream, const Packet *p, const TcpSegment *seg)
Compare the shared data portion of two segments.
Definition: stream-tcp-inline.c:49
Packet_::root
struct Packet_ * root
Definition: decode.h:634
TcpSession_::server
TcpStream server
Definition: stream-tcp-private.h:294
TcpSegmentPcapHdrStorage_::pkt_hdr
uint8_t * pkt_hdr
Definition: stream-tcp-private.h:69
OS_POLICY_LAST
@ OS_POLICY_LAST
Definition: stream-tcp-reassemble.h:50
StreamingBufferInsertAt
int StreamingBufferInsertAt(StreamingBuffer *sb, const StreamingBufferConfig *cfg, StreamingBufferSegment *seg, const uint8_t *data, uint32_t data_len, uint64_t offset)
Definition: util-streaming-buffer.c:1477
TcpSegment::pcap_hdr_storage
TcpSegmentPcapHdrStorage * pcap_hdr_storage
Definition: stream-tcp-private.h:78
SEQ_LT
#define SEQ_LT(a, b)
Definition: stream-tcp-private.h:257
STREAM_REASSEMBLY_INSERT_LIMIT
@ STREAM_REASSEMBLY_INSERT_LIMIT
Definition: decode-events.h:297
TcpStream_::app_progress_rel
uint32_t app_progress_rel
Definition: stream-tcp-private.h:127
OS_POLICY_LINUX
@ OS_POLICY_LINUX
Definition: stream-tcp-reassemble.h:39
TcpReassemblyThreadCtx_::counter_tcp_reass_data_overlap_fail
uint16_t counter_tcp_reass_data_overlap_fail
Definition: stream-tcp-reassemble.h:82
SEQ_EQ
#define SEQ_EQ(a, b)
Definition: stream-tcp-private.h:256
OS_POLICY_HPUX11
@ OS_POLICY_HPUX11
Definition: stream-tcp-reassemble.h:43
TcpReassemblyThreadCtx_
Definition: stream-tcp-reassemble.h:60
STREAMTCP_FLAG_APP_LAYER_DISABLED
#define STREAMTCP_FLAG_APP_LAYER_DISABLED
Definition: stream-tcp-private.h:201
STREAMTCP_STREAM_FLAG_NOREASSEMBLY
#define STREAMTCP_STREAM_FLAG_NOREASSEMBLY
Definition: stream-tcp-private.h:219
OS_POLICY_WINDOWS2K3
@ OS_POLICY_WINDOWS2K3
Definition: stream-tcp-reassemble.h:48
SEQ_LEQ
#define SEQ_LEQ(a, b)
Definition: stream-tcp-private.h:258
RB_FOREACH_REVERSE_FROM
#define RB_FOREACH_REVERSE_FROM(x, name, y)
Definition: tree.h:801
STREAMTCP_STREAM_FLAG_DISABLE_RAW
#define STREAMTCP_STREAM_FLAG_DISABLE_RAW
Definition: stream-tcp-private.h:238
likely
#define likely(expr)
Definition: util-optimize.h:32
STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
@ STREAM_REASSEMBLY_OVERLAP_DIFFERENT_DATA
Definition: decode-events.h:294
STREAM_APP_PROGRESS
#define STREAM_APP_PROGRESS(stream)
Definition: stream-tcp-private.h:145
TcpSession_
Definition: stream-tcp-private.h:283
RB_FOREACH_FROM
#define RB_FOREACH_FROM(x, name, y)
Definition: tree.h:786
StreamingBufferSegmentGetData
void StreamingBufferSegmentGetData(const StreamingBuffer *sb, const StreamingBufferSegment *seg, const uint8_t **data, uint32_t *data_len)
Definition: util-streaming-buffer.c:1704
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:275
TcpReassemblyThreadCtx_::counter_tcp_segment_memcap
uint16_t counter_tcp_segment_memcap
Definition: stream-tcp-reassemble.h:66
SCLogDebugEnabled
int SCLogDebugEnabled(void)
Returns whether debug messages are enabled to be logged or not.
Definition: util-debug.c:771
TcpStreamCnf_::reassembly_toserver_chunk_size
uint16_t reassembly_toserver_chunk_size
Definition: stream-tcp.h:66
DEBUG_VALIDATE_BUG_ON
#define DEBUG_VALIDATE_BUG_ON(exp)
Definition: util-validate.h:103
STREAM_RAW_PROGRESS
#define STREAM_RAW_PROGRESS(stream)
Definition: stream-tcp-private.h:146
SCTIME_USECS
#define SCTIME_USECS(t)
Definition: util-time.h:56