suricata
flow.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 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 Victor Julien <victor@inliniac.net>
22  *
23  * Flow implementation.
24  */
25 
26 #include "suricata-common.h"
27 #include "suricata.h"
28 #include "decode.h"
29 #include "conf.h"
30 #include "threadvars.h"
31 #include "tm-threads.h"
32 #include "runmodes.h"
33 
34 #include "util-random.h"
35 #include "util-time.h"
36 
37 #include "flow.h"
38 #include "flow-queue.h"
39 #include "flow-hash.h"
40 #include "flow-util.h"
41 #include "flow-var.h"
42 #include "flow-private.h"
43 #include "flow-timeout.h"
44 #include "flow-manager.h"
45 #include "flow-storage.h"
46 #include "flow-bypass.h"
47 
48 #include "stream-tcp-private.h"
49 #include "stream-tcp-reassemble.h"
50 #include "stream-tcp.h"
51 
52 #include "util-unittest.h"
53 #include "util-unittest-helper.h"
54 #include "util-byte.h"
55 #include "util-misc.h"
56 
57 #include "util-debug.h"
58 #include "util-privs.h"
59 
60 #include "detect.h"
61 #include "detect-engine-state.h"
62 #include "stream.h"
63 
64 #include "app-layer-parser.h"
65 #include "app-layer-expectation.h"
66 
67 #define FLOW_DEFAULT_EMERGENCY_RECOVERY 30
68 
69 //#define FLOW_DEFAULT_HASHSIZE 262144
70 #define FLOW_DEFAULT_HASHSIZE 65536
71 //#define FLOW_DEFAULT_MEMCAP 128 * 1024 * 1024 /* 128 MB */
72 #define FLOW_DEFAULT_MEMCAP (32 * 1024 * 1024) /* 32 MB */
73 
74 #define FLOW_DEFAULT_PREALLOC 10000
75 
76 /** atomic int that is used when freeing a flow from the hash. In this
77  * case we walk the hash to find a flow to free. This var records where
78  * we left off in the hash. Without this only the top rows of the hash
79  * are freed. This isn't just about fairness. Under severe presure, the
80  * hash rows on top would be all freed and the time to find a flow to
81  * free increased with every run. */
82 SC_ATOMIC_DECLARE(unsigned int, flow_prune_idx);
83 
84 /** atomic flags */
85 SC_ATOMIC_DECLARE(unsigned int, flow_flags);
86 
87 /** FlowProto specific timeouts and free/state functions */
88 
92 
93 /** spare/unused/prealloced flows live here */
95 
97 
98 /** flow memuse counter (atomic), for enforcing memcap limit */
99 SC_ATOMIC_DECLARE(uint64_t, flow_memuse);
100 
101 void FlowRegisterTests(void);
102 void FlowInitFlowProto(void);
103 int FlowSetProtoFreeFunc(uint8_t, void (*Free)(void *));
104 
105 /* Run mode selected at suricata.c */
106 extern int run_mode;
107 
108 /**
109  * \brief Update memcap value
110  *
111  * \param size new memcap value
112  */
113 int FlowSetMemcap(uint64_t size)
114 {
115  if ((uint64_t)SC_ATOMIC_GET(flow_memuse) < size) {
116  SC_ATOMIC_SET(flow_config.memcap, size);
117  return 1;
118  }
119 
120  return 0;
121 }
122 
123 /**
124  * \brief Return memcap value
125  *
126  * \retval memcap value
127  */
128 uint64_t FlowGetMemcap(void)
129 {
130  uint64_t memcapcopy = SC_ATOMIC_GET(flow_config.memcap);
131  return memcapcopy;
132 }
133 
134 uint64_t FlowGetMemuse(void)
135 {
136  uint64_t memusecopy = SC_ATOMIC_GET(flow_memuse);
137  return memusecopy;
138 }
139 
141 {
142  if (f == NULL || f->proto == 0)
143  return;
144 
146  f->alstate = NULL;
147  f->alparser = NULL;
148  return;
149 }
150 
151 /** \brief Make sure we have enough spare flows.
152  *
153  * Enforce the prealloc parameter, so keep at least prealloc flows in the
154  * spare queue and free flows going over the limit.
155  *
156  * \retval 1 if the queue was properly updated (or if it already was in good shape)
157  * \retval 0 otherwise.
158  */
160 {
161  SCEnter();
162  uint32_t toalloc = 0, tofree = 0, len;
163 
165  len = flow_spare_q.len;
167 
168  if (len < flow_config.prealloc) {
169  toalloc = flow_config.prealloc - len;
170 
171  uint32_t i;
172  for (i = 0; i < toalloc; i++) {
173  Flow *f = FlowAlloc();
174  if (f == NULL)
175  return 0;
176 
178  }
179  } else if (len > flow_config.prealloc) {
180  tofree = len - flow_config.prealloc;
181 
182  uint32_t i;
183  for (i = 0; i < tofree; i++) {
184  /* FlowDequeue locks the queue */
186  if (f == NULL)
187  return 1;
188 
189  FlowFree(f);
190  }
191  }
192 
193  return 1;
194 }
195 
196 /** \brief Set the IPOnly scanned flag for 'direction'.
197  *
198  * \param f Flow to set the flag in
199  * \param direction direction to set the flag in
200  */
201 void FlowSetIPOnlyFlag(Flow *f, int direction)
202 {
203  direction ? (f->flags |= FLOW_TOSERVER_IPONLY_SET) :
205  return;
206 }
207 
208 /** \brief Set flag to indicate that flow has alerts
209  *
210  * \param f flow
211  */
213 {
214  f->flags |= FLOW_HAS_ALERTS;
215 }
216 
217 /** \brief Check if flow has alerts
218  *
219  * \param f flow
220  * \retval 1 has alerts
221  * \retval 0 has not alerts
222  */
223 int FlowHasAlerts(const Flow *f)
224 {
225  if (f->flags & FLOW_HAS_ALERTS) {
226  return 1;
227  }
228 
229  return 0;
230 }
231 
232 /** \brief Set flag to indicate to change proto for the flow
233  *
234  * \param f flow
235  */
237 {
238  f->flags |= FLOW_CHANGE_PROTO;
239 }
240 
241 /** \brief Unset flag to indicate to change proto for the flow
242  *
243  * \param f flow
244  */
246 {
247  f->flags &= ~FLOW_CHANGE_PROTO;
248 }
249 
250 /** \brief Check if change proto flag is set for flow
251  * \param f flow
252  * \retval 1 change proto flag is set
253  * \retval 0 change proto flag is not set
254  */
256 {
257  if (f->flags & FLOW_CHANGE_PROTO) {
258  return 1;
259  }
260 
261  return 0;
262 }
263 
264 static inline void FlowSwapFlags(Flow *f)
265 {
269 
274 
276 }
277 
278 static inline void FlowSwapFileFlags(Flow *f)
279 {
284 }
285 
286 static inline void TcpStreamFlowSwap(Flow *f)
287 {
288  TcpSession *ssn = f->protoctx;
289  SWAP_VARS(TcpStream, ssn->server, ssn->client);
292  } else if (ssn->data_first_seen_dir & STREAM_TOCLIENT) {
294  }
295 }
296 
297 /** \brief swap the flow's direction
298  * \note leaves the 'header' untouched. Interpret that based
299  * on FLOW_DIR_REVERSED flag.
300  * \warning: only valid before applayer parsing started. This
301  * function doesn't swap anything in Flow::alparser,
302  * Flow::alstate
303  */
304 void FlowSwap(Flow *f)
305 {
306  f->flags |= FLOW_DIR_REVERSED;
307 
310 
311  FlowSwapFlags(f);
312  FlowSwapFileFlags(f);
313 
314  if (f->proto == IPPROTO_TCP) {
315  TcpStreamFlowSwap(f);
316  }
317 
321 
322  /* not touching Flow::alparser and Flow::alstate */
323 
324  SWAP_VARS(const void *, f->sgh_toclient, f->sgh_toserver);
325 
326  SWAP_VARS(uint32_t, f->todstpktcnt, f->tosrcpktcnt);
327  SWAP_VARS(uint64_t, f->todstbytecnt, f->tosrcbytecnt);
328 }
329 
330 /**
331  * \brief determine the direction of the packet compared to the flow
332  * \retval 0 to_server
333  * \retval 1 to_client
334  */
335 int FlowGetPacketDirection(const Flow *f, const Packet *p)
336 {
337  const int reverse = (f->flags & FLOW_DIR_REVERSED) != 0;
338 
339  if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
340  if (!(CMP_PORT(p->sp,p->dp))) {
341  /* update flags and counters */
342  if (CMP_PORT(f->sp,p->sp)) {
343  return TOSERVER ^ reverse;
344  } else {
345  return TOCLIENT ^ reverse;
346  }
347  } else {
348  if (CMP_ADDR(&f->src,&p->src)) {
349  return TOSERVER ^ reverse;
350  } else {
351  return TOCLIENT ^ reverse;
352  }
353  }
354  } else if (p->proto == IPPROTO_ICMP || p->proto == IPPROTO_ICMPV6) {
355  if (CMP_ADDR(&f->src,&p->src)) {
356  return TOSERVER ^ reverse;
357  } else {
358  return TOCLIENT ^ reverse;
359  }
360  }
361 
362  /* default to toserver */
363  return TOSERVER;
364 }
365 
366 /**
367  * \brief Check to update "seen" flags
368  *
369  * \param p packet
370  *
371  * \retval 1 true
372  * \retval 0 false
373  */
374 static inline int FlowUpdateSeenFlag(const Packet *p)
375 {
376  if (PKT_IS_ICMPV4(p)) {
377  if (ICMPV4_IS_ERROR_MSG(p)) {
378  return 0;
379  }
380  }
381 
382  return 1;
383 }
384 
385 static inline void FlowUpdateTTL(Flow *f, Packet *p, uint8_t ttl)
386 {
387  if (FlowGetPacketDirection(f, p) == TOSERVER) {
388  if (f->min_ttl_toserver == 0) {
389  f->min_ttl_toserver = ttl;
390  } else {
391  f->min_ttl_toserver = MIN(f->min_ttl_toserver, ttl);
392  }
393  f->max_ttl_toserver = MAX(f->max_ttl_toserver, ttl);
394  } else {
395  if (f->min_ttl_toclient == 0) {
396  f->min_ttl_toclient = ttl;
397  } else {
398  f->min_ttl_toclient = MIN(f->min_ttl_toclient, ttl);
399  }
400  f->max_ttl_toclient = MAX(f->max_ttl_toclient, ttl);
401  }
402 }
403 
404 /** \brief Update Packet and Flow
405  *
406  * Updates packet and flow based on the new packet.
407  *
408  * \param f locked flow
409  * \param p packet
410  *
411  * \note overwrites p::flowflags
412  */
414 {
415  SCLogDebug("packet %"PRIu64" -- flow %p", p->pcap_cnt, f);
416 
417 #ifdef CAPTURE_OFFLOAD
418  int state = SC_ATOMIC_GET(f->flow_state);
419 
420  if (state != FLOW_STATE_CAPTURE_BYPASSED) {
421 #endif
422  /* update the last seen timestamp of this flow */
423  COPY_TIMESTAMP(&p->ts, &f->lastts);
424 #ifdef CAPTURE_OFFLOAD
425  } else {
426  /* still seeing packet, we downgrade to local bypass */
427  if (p->ts.tv_sec - f->lastts.tv_sec > FLOW_BYPASSED_TIMEOUT / 2) {
428  SCLogDebug("Downgrading flow to local bypass");
429  COPY_TIMESTAMP(&p->ts, &f->lastts);
431  } else {
432  /* In IPS mode the packet could come from the other interface so it would
433  * need to be bypassed */
434  if (EngineModeIsIPS()) {
435  BypassedFlowUpdate(f, p);
436  }
437  }
438  }
439 #endif
440  /* update flags and counters */
441  if (FlowGetPacketDirection(f, p) == TOSERVER) {
442  f->todstpktcnt++;
443  f->todstbytecnt += GET_PKT_LEN(p);
445  if (!(f->flags & FLOW_TO_DST_SEEN)) {
446  if (FlowUpdateSeenFlag(p)) {
447  f->flags |= FLOW_TO_DST_SEEN;
449  }
450  }
451  /* xfer proto detect ts flag to first packet in ts dir */
452  if (f->flags & FLOW_PROTO_DETECT_TS_DONE) {
455  }
456  } else {
457  f->tosrcpktcnt++;
458  f->tosrcbytecnt += GET_PKT_LEN(p);
460  if (!(f->flags & FLOW_TO_SRC_SEEN)) {
461  if (FlowUpdateSeenFlag(p)) {
462  f->flags |= FLOW_TO_SRC_SEEN;
464  }
465  }
466  /* xfer proto detect tc flag to first packet in tc dir */
467  if (f->flags & FLOW_PROTO_DETECT_TC_DONE) {
470  }
471  }
472 
473  if (SC_ATOMIC_GET(f->flow_state) == FLOW_STATE_ESTABLISHED) {
474  SCLogDebug("pkt %p FLOW_PKT_ESTABLISHED", p);
476 
477  } else if ((f->flags & (FLOW_TO_DST_SEEN|FLOW_TO_SRC_SEEN)) ==
479  SCLogDebug("pkt %p FLOW_PKT_ESTABLISHED", p);
481 
482  if (f->proto != IPPROTO_TCP) {
484  }
485  }
486 
487  /*set the detection bypass flags*/
488  if (f->flags & FLOW_NOPACKET_INSPECTION) {
489  SCLogDebug("setting FLOW_NOPACKET_INSPECTION flag on flow %p", f);
491  }
492  if (f->flags & FLOW_NOPAYLOAD_INSPECTION) {
493  SCLogDebug("setting FLOW_NOPAYLOAD_INSPECTION flag on flow %p", f);
495  }
496 
497 
498  /* update flow's ttl fields if needed */
499  if (PKT_IS_IPV4(p)) {
500  FlowUpdateTTL(f, p, IPV4_GET_IPTTL(p));
501  } else if (PKT_IS_IPV6(p)) {
502  FlowUpdateTTL(f, p, IPV6_GET_HLIM(p));
503  }
504 }
505 
506 /** \brief Entry point for packet flow handling
507  *
508  * This is called for every packet.
509  *
510  * \param tv threadvars
511  * \param dtv decode thread vars (for flow output api thread data)
512  * \param p packet to handle flow for
513  */
515 {
516  /* Get this packet's flow from the hash. FlowHandlePacket() will setup
517  * a new flow if nescesary. If we get NULL, we're out of flow memory.
518  * The returned flow is locked. */
519  Flow *f = FlowGetFlowFromHash(tv, dtv, p, &p->flow);
520  if (f == NULL)
521  return;
522 
523  /* set the flow in the packet */
524  p->flags |= PKT_HAS_FLOW;
525  return;
526 }
527 
528 /** \brief initialize the configuration
529  * \warning Not thread safe */
530 void FlowInitConfig(char quiet)
531 {
532  SCLogDebug("initializing flow engine...");
533 
534  memset(&flow_config, 0, sizeof(flow_config));
535  SC_ATOMIC_INIT(flow_flags);
536  SC_ATOMIC_INIT(flow_memuse);
537  SC_ATOMIC_INIT(flow_prune_idx);
538  SC_ATOMIC_INIT(flow_config.memcap);
541 
542  /* set defaults */
543  flow_config.hash_rand = (uint32_t)RandomGet();
547 
548  /* If we have specific config, overwrite the defaults with them,
549  * otherwise, leave the default values */
550  intmax_t val = 0;
551  if (ConfGetInt("flow.emergency-recovery", &val) == 1) {
552  if (val <= 100 && val >= 1) {
553  flow_config.emergency_recovery = (uint8_t)val;
554  } else {
555  SCLogError(SC_ERR_INVALID_VALUE, "flow.emergency-recovery must be in the range of 1 and 100 (as percentage)");
557  }
558  } else {
559  SCLogDebug("flow.emergency-recovery, using default value");
561  }
562 
563  /* Check if we have memcap and hash_size defined at config */
564  const char *conf_val;
565  uint32_t configval = 0;
566 
567  /** set config values for memcap, prealloc and hash_size */
568  uint64_t flow_memcap_copy;
569  if ((ConfGet("flow.memcap", &conf_val)) == 1)
570  {
571  if (conf_val == NULL) {
572  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,"Invalid value for flow.memcap: NULL");
573  exit(EXIT_FAILURE);
574  }
575 
576  if (ParseSizeStringU64(conf_val, &flow_memcap_copy) < 0) {
577  SCLogError(SC_ERR_SIZE_PARSE, "Error parsing flow.memcap "
578  "from conf file - %s. Killing engine",
579  conf_val);
580  exit(EXIT_FAILURE);
581  } else {
582  SC_ATOMIC_SET(flow_config.memcap, flow_memcap_copy);
583  }
584  }
585  if ((ConfGet("flow.hash-size", &conf_val)) == 1)
586  {
587  if (conf_val == NULL) {
588  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,"Invalid value for flow.hash-size: NULL");
589  exit(EXIT_FAILURE);
590  }
591 
592  if (StringParseUint32(&configval, 10, strlen(conf_val),
593  conf_val) > 0) {
594  flow_config.hash_size = configval;
595  }
596  }
597  if ((ConfGet("flow.prealloc", &conf_val)) == 1)
598  {
599  if (conf_val == NULL) {
600  SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY,"Invalid value for flow.prealloc: NULL");
601  exit(EXIT_FAILURE);
602  }
603 
604  if (StringParseUint32(&configval, 10, strlen(conf_val),
605  conf_val) > 0) {
606  flow_config.prealloc = configval;
607  }
608  }
609  SCLogDebug("Flow config from suricata.yaml: memcap: %"PRIu64", hash-size: "
610  "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(flow_config.memcap),
612 
613  /* alloc hash memory */
614  uint64_t hash_size = flow_config.hash_size * sizeof(FlowBucket);
615  if (!(FLOW_CHECK_MEMCAP(hash_size))) {
616  SCLogError(SC_ERR_FLOW_INIT, "allocating flow hash failed: "
617  "max flow memcap is smaller than projected hash size. "
618  "Memcap: %"PRIu64", Hash table size %"PRIu64". Calculate "
619  "total hash size by multiplying \"flow.hash-size\" with %"PRIuMAX", "
620  "which is the hash bucket size.", SC_ATOMIC_GET(flow_config.memcap), hash_size,
621  (uintmax_t)sizeof(FlowBucket));
622  exit(EXIT_FAILURE);
623  }
624  flow_hash = SCMallocAligned(flow_config.hash_size * sizeof(FlowBucket), CLS);
625  if (unlikely(flow_hash == NULL)) {
626  SCLogError(SC_ERR_FATAL, "Fatal error encountered in FlowInitConfig. Exiting...");
627  exit(EXIT_FAILURE);
628  }
629  memset(flow_hash, 0, flow_config.hash_size * sizeof(FlowBucket));
630 
631  uint32_t i = 0;
632  for (i = 0; i < flow_config.hash_size; i++) {
633  FBLOCK_INIT(&flow_hash[i]);
634  SC_ATOMIC_INIT(flow_hash[i].next_ts);
635  }
636  (void) SC_ATOMIC_ADD(flow_memuse, (flow_config.hash_size * sizeof(FlowBucket)));
637 
638  if (quiet == FALSE) {
639  SCLogConfig("allocated %"PRIu64" bytes of memory for the flow hash... "
640  "%" PRIu32 " buckets of size %" PRIuMAX "",
641  SC_ATOMIC_GET(flow_memuse), flow_config.hash_size,
642  (uintmax_t)sizeof(FlowBucket));
643  }
644 
645  /* pre allocate flows */
646  for (i = 0; i < flow_config.prealloc; i++) {
647  if (!(FLOW_CHECK_MEMCAP(sizeof(Flow) + FlowStorageSize()))) {
648  SCLogError(SC_ERR_FLOW_INIT, "preallocating flows failed: "
649  "max flow memcap reached. Memcap %"PRIu64", "
650  "Memuse %"PRIu64".", SC_ATOMIC_GET(flow_config.memcap),
651  ((uint64_t)SC_ATOMIC_GET(flow_memuse) + (uint64_t)sizeof(Flow)));
652  exit(EXIT_FAILURE);
653  }
654 
655  Flow *f = FlowAlloc();
656  if (f == NULL) {
657  SCLogError(SC_ERR_FLOW_INIT, "preallocating flow failed: %s", strerror(errno));
658  exit(EXIT_FAILURE);
659  }
660 
662  }
663 
664  if (quiet == FALSE) {
665  SCLogConfig("preallocated %" PRIu32 " flows of size %" PRIuMAX "",
666  flow_spare_q.len, (uintmax_t)(sizeof(Flow) + + FlowStorageSize()));
667  SCLogConfig("flow memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
668  SC_ATOMIC_GET(flow_memuse), SC_ATOMIC_GET(flow_config.memcap));
669  }
670 
672 
673  return;
674 }
675 
676 /** \brief print some flow stats
677  * \warning Not thread safe */
678 static void FlowPrintStats (void)
679 {
680  return;
681 }
682 
683 /** \brief shutdown the flow engine
684  * \warning Not thread safe */
685 void FlowShutdown(void)
686 {
687  Flow *f;
688  uint32_t u;
689 
690  FlowPrintStats();
691 
692  /* free queues */
693  while((f = FlowDequeue(&flow_spare_q))) {
694  FlowFree(f);
695  }
696  while((f = FlowDequeue(&flow_recycle_q))) {
697  FlowFree(f);
698  }
699 
700  /* clear and free the hash */
701  if (flow_hash != NULL) {
702  /* clean up flow mutexes */
703  for (u = 0; u < flow_config.hash_size; u++) {
704  f = flow_hash[u].head;
705  while (f) {
706 #ifdef DEBUG_VALIDATION
707  BUG_ON(SC_ATOMIC_GET(f->use_cnt) != 0);
708 #endif
709  Flow *n = f->hnext;
710  uint8_t proto_map = FlowGetProtoMapping(f->proto);
711  FlowClearMemory(f, proto_map);
712  FlowFree(f);
713  f = n;
714  }
715 
717  SC_ATOMIC_DESTROY(flow_hash[u].next_ts);
718  }
720  flow_hash = NULL;
721  }
722  (void) SC_ATOMIC_SUB(flow_memuse, flow_config.hash_size * sizeof(FlowBucket));
725 
727  SC_ATOMIC_DESTROY(flow_prune_idx);
728  SC_ATOMIC_DESTROY(flow_memuse);
729  SC_ATOMIC_DESTROY(flow_flags);
730  return;
731 }
732 
733 /**
734  * \brief Function to set the default timeout, free function and flow state
735  * function for all supported flow_proto.
736  */
737 
739 {
741 
742 #define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be) \
743  flow_timeouts_normal[(p)].new_timeout = (n); \
744  flow_timeouts_normal[(p)].est_timeout = (e); \
745  flow_timeouts_normal[(p)].closed_timeout = (c); \
746  flow_timeouts_normal[(p)].bypassed_timeout = (b); \
747  flow_timeouts_emerg[(p)].new_timeout = (ne); \
748  flow_timeouts_emerg[(p)].est_timeout = (ee); \
749  flow_timeouts_emerg[(p)].closed_timeout = (ce); \
750  flow_timeouts_emerg[(p)].bypassed_timeout = (be); \
751 
772 
777 
778  /* Let's see if we have custom timeouts defined from config */
779  const char *new = NULL;
780  const char *established = NULL;
781  const char *closed = NULL;
782  const char *bypassed = NULL;
783  const char *emergency_new = NULL;
784  const char *emergency_established = NULL;
785  const char *emergency_closed = NULL;
786  const char *emergency_bypassed = NULL;
787 
788  ConfNode *flow_timeouts = ConfGetNode("flow-timeouts");
789  if (flow_timeouts != NULL) {
790  ConfNode *proto = NULL;
791  uint32_t configval = 0;
792 
793  /* Defaults. */
794  proto = ConfNodeLookupChild(flow_timeouts, "default");
795  if (proto != NULL) {
796  new = ConfNodeLookupChildValue(proto, "new");
797  established = ConfNodeLookupChildValue(proto, "established");
798  closed = ConfNodeLookupChildValue(proto, "closed");
799  bypassed = ConfNodeLookupChildValue(proto, "bypassed");
800  emergency_new = ConfNodeLookupChildValue(proto, "emergency-new");
801  emergency_established = ConfNodeLookupChildValue(proto,
802  "emergency-established");
803  emergency_closed = ConfNodeLookupChildValue(proto,
804  "emergency-closed");
805  emergency_bypassed = ConfNodeLookupChildValue(proto,
806  "emergency-bypassed");
807 
808  if (new != NULL &&
809  StringParseUint32(&configval, 10, strlen(new), new) > 0) {
810 
812  }
813  if (established != NULL &&
814  StringParseUint32(&configval, 10, strlen(established),
815  established) > 0) {
816 
818  }
819  if (closed != NULL &&
820  StringParseUint32(&configval, 10, strlen(closed),
821  closed) > 0) {
822 
824  }
825  if (bypassed != NULL &&
826  StringParseUint32(&configval, 10,
827  strlen(bypassed),
828  bypassed) > 0) {
829 
831  }
832  if (emergency_new != NULL &&
833  StringParseUint32(&configval, 10, strlen(emergency_new),
834  emergency_new) > 0) {
835 
837  }
838  if (emergency_established != NULL &&
839  StringParseUint32(&configval, 10,
840  strlen(emergency_established),
841  emergency_established) > 0) {
842 
844  }
845  if (emergency_closed != NULL &&
846  StringParseUint32(&configval, 10,
847  strlen(emergency_closed),
848  emergency_closed) > 0) {
849 
851  }
852  if (emergency_bypassed != NULL &&
853  StringParseUint32(&configval, 10,
854  strlen(emergency_bypassed),
855  emergency_bypassed) > 0) {
856 
858  }
859  }
860 
861  /* TCP. */
862  proto = ConfNodeLookupChild(flow_timeouts, "tcp");
863  if (proto != NULL) {
864  new = ConfNodeLookupChildValue(proto, "new");
865  established = ConfNodeLookupChildValue(proto, "established");
866  closed = ConfNodeLookupChildValue(proto, "closed");
867  bypassed = ConfNodeLookupChildValue(proto, "bypassed");
868  emergency_new = ConfNodeLookupChildValue(proto, "emergency-new");
869  emergency_established = ConfNodeLookupChildValue(proto,
870  "emergency-established");
871  emergency_closed = ConfNodeLookupChildValue(proto,
872  "emergency-closed");
873  emergency_bypassed = ConfNodeLookupChildValue(proto,
874  "emergency-bypassed");
875 
876  if (new != NULL &&
877  StringParseUint32(&configval, 10, strlen(new), new) > 0) {
878 
880  }
881  if (established != NULL &&
882  StringParseUint32(&configval, 10, strlen(established),
883  established) > 0) {
884 
886  }
887  if (closed != NULL &&
888  StringParseUint32(&configval, 10, strlen(closed),
889  closed) > 0) {
890 
892  }
893  if (bypassed != NULL &&
894  StringParseUint32(&configval, 10,
895  strlen(bypassed),
896  bypassed) > 0) {
897 
899  }
900  if (emergency_new != NULL &&
901  StringParseUint32(&configval, 10, strlen(emergency_new),
902  emergency_new) > 0) {
903 
905  }
906  if (emergency_established != NULL &&
907  StringParseUint32(&configval, 10,
908  strlen(emergency_established),
909  emergency_established) > 0) {
910 
912  }
913  if (emergency_closed != NULL &&
914  StringParseUint32(&configval, 10,
915  strlen(emergency_closed),
916  emergency_closed) > 0) {
917 
919  }
920  if (emergency_bypassed != NULL &&
921  StringParseUint32(&configval, 10,
922  strlen(emergency_bypassed),
923  emergency_bypassed) > 0) {
924 
926  }
927  }
928 
929  /* UDP. */
930  proto = ConfNodeLookupChild(flow_timeouts, "udp");
931  if (proto != NULL) {
932  new = ConfNodeLookupChildValue(proto, "new");
933  established = ConfNodeLookupChildValue(proto, "established");
934  bypassed = ConfNodeLookupChildValue(proto, "bypassed");
935  emergency_new = ConfNodeLookupChildValue(proto, "emergency-new");
936  emergency_established = ConfNodeLookupChildValue(proto,
937  "emergency-established");
938  emergency_bypassed = ConfNodeLookupChildValue(proto,
939  "emergency-bypassed");
940 
941  if (new != NULL &&
942  StringParseUint32(&configval, 10, strlen(new), new) > 0) {
943 
945  }
946  if (established != NULL &&
947  StringParseUint32(&configval, 10, strlen(established),
948  established) > 0) {
949 
951  }
952  if (bypassed != NULL &&
953  StringParseUint32(&configval, 10,
954  strlen(bypassed),
955  bypassed) > 0) {
956 
958  }
959  if (emergency_new != NULL &&
960  StringParseUint32(&configval, 10, strlen(emergency_new),
961  emergency_new) > 0) {
962 
964  }
965  if (emergency_established != NULL &&
966  StringParseUint32(&configval, 10,
967  strlen(emergency_established),
968  emergency_established) > 0) {
969 
971  }
972  if (emergency_bypassed != NULL &&
973  StringParseUint32(&configval, 10,
974  strlen(emergency_bypassed),
975  emergency_bypassed) > 0) {
976 
978  }
979  }
980 
981  /* ICMP. */
982  proto = ConfNodeLookupChild(flow_timeouts, "icmp");
983  if (proto != NULL) {
984  new = ConfNodeLookupChildValue(proto, "new");
985  established = ConfNodeLookupChildValue(proto, "established");
986  bypassed = ConfNodeLookupChildValue(proto, "bypassed");
987  emergency_new = ConfNodeLookupChildValue(proto, "emergency-new");
988  emergency_established = ConfNodeLookupChildValue(proto,
989  "emergency-established");
990  emergency_bypassed = ConfNodeLookupChildValue(proto,
991  "emergency-bypassed");
992 
993  if (new != NULL &&
994  StringParseUint32(&configval, 10, strlen(new), new) > 0) {
995 
997  }
998  if (established != NULL &&
999  StringParseUint32(&configval, 10, strlen(established),
1000  established) > 0) {
1001 
1003  }
1004  if (bypassed != NULL &&
1005  StringParseUint32(&configval, 10,
1006  strlen(bypassed),
1007  bypassed) > 0) {
1008 
1010  }
1011  if (emergency_new != NULL &&
1012  StringParseUint32(&configval, 10, strlen(emergency_new),
1013  emergency_new) > 0) {
1014 
1016  }
1017  if (emergency_established != NULL &&
1018  StringParseUint32(&configval, 10,
1019  strlen(emergency_established),
1020  emergency_established) > 0) {
1021 
1023  }
1024  if (emergency_bypassed != NULL &&
1025  StringParseUint32(&configval, 10,
1026  strlen(emergency_bypassed),
1027  emergency_bypassed) > 0) {
1028 
1030  }
1031  }
1032  }
1033 
1034  return;
1035 }
1036 
1037 /**
1038  * \brief Function clear the flow memory before queueing it to spare flow
1039  * queue.
1040  *
1041  * \param f pointer to the flow needed to be cleared.
1042  * \param proto_map mapped value of the protocol to FLOW_PROTO's.
1043  */
1044 
1045 int FlowClearMemory(Flow* f, uint8_t proto_map)
1046 {
1047  SCEnter();
1048 
1049  if (unlikely(f->flags & FLOW_HAS_EXPECTATION)) {
1051  }
1052 
1053  /* call the protocol specific free function if we have one */
1054  if (flow_freefuncs[proto_map].Freefunc != NULL) {
1055  flow_freefuncs[proto_map].Freefunc(f->protoctx);
1056  }
1057 
1058  FlowFreeStorage(f);
1059 
1060  FLOW_RECYCLE(f);
1061 
1062  SCReturnInt(1);
1063 }
1064 
1065 /**
1066  * \brief Function to set the function to get protocol specific flow state.
1067  *
1068  * \param proto protocol of which function is needed to be set.
1069  * \param Free Function pointer which will be called to free the protocol
1070  * specific memory.
1071  */
1072 
1073 int FlowSetProtoFreeFunc (uint8_t proto, void (*Free)(void *))
1074 {
1075  uint8_t proto_map;
1076  proto_map = FlowGetProtoMapping(proto);
1077 
1078  flow_freefuncs[proto_map].Freefunc = Free;
1079  return 1;
1080 }
1081 
1083 {
1084  return f->alproto;
1085 }
1086 
1087 void *FlowGetAppState(const Flow *f)
1088 {
1089  return f->alstate;
1090 }
1091 
1092 /**
1093  * \brief get 'disruption' flags: GAP/DEPTH/PASS
1094  * \param f locked flow
1095  * \param flags existing flags to be ammended
1096  * \retval flags original flags + disrupt flags (if any)
1097  * \TODO handle UDP
1098  */
1099 uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
1100 {
1101  if (f->proto != IPPROTO_TCP) {
1102  return flags;
1103  }
1104  if (f->protoctx == NULL) {
1105  return flags;
1106  }
1107 
1108  uint8_t newflags = flags;
1109  TcpSession *ssn = f->protoctx;
1110  TcpStream *stream = flags & STREAM_TOSERVER ? &ssn->client : &ssn->server;
1111 
1113  newflags |= STREAM_DEPTH;
1114  }
1115  if (stream->flags & STREAMTCP_STREAM_FLAG_GAP) {
1116  newflags |= STREAM_GAP;
1117  }
1118  /* todo: handle pass case (also for UDP!) */
1119 
1120  return newflags;
1121 }
1122 
1124 {
1125  /* set the state */
1126  SC_ATOMIC_SET(f->flow_state, s);
1127 
1128  if (f->fb) {
1129  /* and reset the flow buckup next_ts value so that the flow manager
1130  * has to revisit this row */
1131  SC_ATOMIC_SET(f->fb->next_ts, 0);
1132  }
1133 }
1134 
1135 /**
1136  * \brief Get flow last time as individual values.
1137  *
1138  * Instead of returning a pointer to the timeval copy the timeval
1139  * parts into output pointers to make it simpler to call from Rust
1140  * over FFI using only basic data types.
1141  */
1142 void FlowGetLastTimeAsParts(Flow *flow, uint64_t *secs, uint64_t *usecs)
1143 {
1144  *secs = (uint64_t)flow->lastts.tv_sec;
1145  *usecs = (uint64_t)flow->lastts.tv_usec;
1146 }
1147 
1148 /************************************Unittests*******************************/
1149 
1150 #ifdef UNITTESTS
1151 #include "threads.h"
1152 
1153 /**
1154  * \test Test the setting of the per protocol timeouts.
1155  *
1156  * \retval On success it returns 1 and on failure 0.
1157  */
1158 
1159 static int FlowTest01 (void)
1160 {
1161  uint8_t proto_map;
1162 
1164  proto_map = FlowGetProtoMapping(IPPROTO_TCP);
1165  FAIL_IF(flow_timeouts_normal[proto_map].new_timeout != FLOW_IPPROTO_TCP_NEW_TIMEOUT);
1166  FAIL_IF(flow_timeouts_normal[proto_map].est_timeout != FLOW_IPPROTO_TCP_EST_TIMEOUT);
1169 
1170  proto_map = FlowGetProtoMapping(IPPROTO_UDP);
1171  FAIL_IF(flow_timeouts_normal[proto_map].new_timeout != FLOW_IPPROTO_UDP_NEW_TIMEOUT);
1172  FAIL_IF(flow_timeouts_normal[proto_map].est_timeout != FLOW_IPPROTO_UDP_EST_TIMEOUT);
1175 
1176  proto_map = FlowGetProtoMapping(IPPROTO_ICMP);
1177  FAIL_IF(flow_timeouts_normal[proto_map].new_timeout != FLOW_IPPROTO_ICMP_NEW_TIMEOUT);
1178  FAIL_IF(flow_timeouts_normal[proto_map].est_timeout != FLOW_IPPROTO_ICMP_EST_TIMEOUT);
1181 
1182  proto_map = FlowGetProtoMapping(IPPROTO_DCCP);
1183  FAIL_IF(flow_timeouts_normal[proto_map].new_timeout != FLOW_DEFAULT_NEW_TIMEOUT);
1184  FAIL_IF(flow_timeouts_normal[proto_map].est_timeout != FLOW_DEFAULT_EST_TIMEOUT);
1185  FAIL_IF(flow_timeouts_emerg[proto_map].new_timeout != FLOW_DEFAULT_EMERG_NEW_TIMEOUT);
1186  FAIL_IF(flow_timeouts_emerg[proto_map].est_timeout != FLOW_DEFAULT_EMERG_EST_TIMEOUT);
1187 
1188  PASS;
1189 }
1190 
1191 /*Test function for the unit test FlowTest02*/
1192 
1193 static void test(void *f) {}
1194 
1195 /**
1196  * \test Test the setting of the per protocol free function to free the
1197  * protocol specific memory.
1198  *
1199  * \retval On success it returns 1 and on failure 0.
1200  */
1201 
1202 static int FlowTest02 (void)
1203 {
1204  FlowSetProtoFreeFunc(IPPROTO_DCCP, test);
1205  FlowSetProtoFreeFunc(IPPROTO_TCP, test);
1206  FlowSetProtoFreeFunc(IPPROTO_UDP, test);
1207  FlowSetProtoFreeFunc(IPPROTO_ICMP, test);
1208 
1209  FAIL_IF(flow_freefuncs[FLOW_PROTO_DEFAULT].Freefunc != test);
1210  FAIL_IF(flow_freefuncs[FLOW_PROTO_TCP].Freefunc != test);
1211  FAIL_IF(flow_freefuncs[FLOW_PROTO_UDP].Freefunc != test);
1212  FAIL_IF(flow_freefuncs[FLOW_PROTO_ICMP].Freefunc != test);
1213 
1214  PASS;
1215 }
1216 
1217 /**
1218  * \test Test flow allocations when it reach memcap
1219  *
1220  *
1221  * \retval On success it returns 1 and on failure 0.
1222  */
1223 
1224 static int FlowTest07 (void)
1225 {
1226  int result = 0;
1227 
1229  FlowConfig backup;
1230  memcpy(&backup, &flow_config, sizeof(FlowConfig));
1231 
1232  uint32_t ini = 0;
1233  uint32_t end = flow_spare_q.len;
1234  SC_ATOMIC_SET(flow_config.memcap, 10000);
1235  flow_config.prealloc = 100;
1236 
1237  /* Let's get the flow_spare_q empty */
1238  UTHBuildPacketOfFlows(ini, end, 0);
1239 
1240  /* And now let's try to reach the memcap val */
1241  while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1242  ini = end + 1;
1243  end = end + 2;
1244  UTHBuildPacketOfFlows(ini, end, 0);
1245  }
1246 
1247  /* should time out normal */
1248  TimeSetIncrementTime(2000);
1249  ini = end + 1;
1250  end = end + 2;;
1251  UTHBuildPacketOfFlows(ini, end, 0);
1252 
1253  /* This means that the engine entered emerg mode: should happen as easy
1254  * with flow mgr activated */
1255  if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1256  result = 1;
1257 
1258  memcpy(&flow_config, &backup, sizeof(FlowConfig));
1259  FlowShutdown();
1260 
1261  return result;
1262 }
1263 
1264 /**
1265  * \test Test flow allocations when it reach memcap
1266  *
1267  *
1268  * \retval On success it returns 1 and on failure 0.
1269  */
1270 
1271 static int FlowTest08 (void)
1272 {
1273  int result = 0;
1274 
1276  FlowConfig backup;
1277  memcpy(&backup, &flow_config, sizeof(FlowConfig));
1278 
1279  uint32_t ini = 0;
1280  uint32_t end = flow_spare_q.len;
1281  SC_ATOMIC_SET(flow_config.memcap, 10000);
1282  flow_config.prealloc = 100;
1283 
1284  /* Let's get the flow_spare_q empty */
1285  UTHBuildPacketOfFlows(ini, end, 0);
1286 
1287  /* And now let's try to reach the memcap val */
1288  while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1289  ini = end + 1;
1290  end = end + 2;
1291  UTHBuildPacketOfFlows(ini, end, 0);
1292  }
1293 
1294  /* By default we use 30 for timing out new flows. This means
1295  * that the Emergency mode should be set */
1297  ini = end + 1;
1298  end = end + 2;
1299  UTHBuildPacketOfFlows(ini, end, 0);
1300 
1301  /* This means that the engine released 5 flows by emergency timeout */
1302  if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1303  result = 1;
1304 
1305  memcpy(&flow_config, &backup, sizeof(FlowConfig));
1306  FlowShutdown();
1307 
1308  return result;
1309 }
1310 
1311 /**
1312  * \test Test flow allocations when it reach memcap
1313  *
1314  *
1315  * \retval On success it returns 1 and on failure 0.
1316  */
1317 
1318 static int FlowTest09 (void)
1319 {
1320  int result = 0;
1321 
1323  FlowConfig backup;
1324  memcpy(&backup, &flow_config, sizeof(FlowConfig));
1325 
1326  uint32_t ini = 0;
1327  uint32_t end = flow_spare_q.len;
1328  SC_ATOMIC_SET(flow_config.memcap, 10000);
1329  flow_config.prealloc = 100;
1330 
1331  /* Let's get the flow_spare_q empty */
1332  UTHBuildPacketOfFlows(ini, end, 0);
1333 
1334  /* And now let's try to reach the memcap val */
1335  while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1336  ini = end + 1;
1337  end = end + 2;
1338  UTHBuildPacketOfFlows(ini, end, 0);
1339  }
1340 
1341  /* No timeout will work */
1343  ini = end + 1;
1344  end = end + 2;
1345  UTHBuildPacketOfFlows(ini, end, 0);
1346 
1347  /* engine in emerg mode */
1348  if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1349  result = 1;
1350 
1351  memcpy(&flow_config, &backup, sizeof(FlowConfig));
1352  FlowShutdown();
1353 
1354  return result;
1355 }
1356 
1357 #endif /* UNITTESTS */
1358 
1359 /**
1360  * \brief Function to register the Flow Unitests.
1361  */
1363 {
1364 #ifdef UNITTESTS
1365  UtRegisterTest("FlowTest01 -- Protocol Specific Timeouts", FlowTest01);
1366  UtRegisterTest("FlowTest02 -- Setting Protocol Specific Free Function",
1367  FlowTest02);
1368  UtRegisterTest("FlowTest07 -- Test flow Allocations when it reach memcap",
1369  FlowTest07);
1370  UtRegisterTest("FlowTest08 -- Test flow Allocations when it reach memcap",
1371  FlowTest08);
1372  UtRegisterTest("FlowTest09 -- Test flow Allocations when it reach memcap",
1373  FlowTest09);
1374 
1377 #endif /* UNITTESTS */
1378 }
util-byte.h
FlowUnsetChangeProtoFlag
void FlowUnsetChangeProtoFlag(Flow *f)
Unset flag to indicate to change proto for the flow.
Definition: flow.c:245
FlowMgrRegisterTests
void FlowMgrRegisterTests(void)
Function to register the Flow Unitests.
Definition: flow-manager.c:1427
FBLOCK_DESTROY
#define FBLOCK_DESTROY(fb)
Definition: flow-hash.h:67
FLOW_DEFAULT_NEW_TIMEOUT
#define FLOW_DEFAULT_NEW_TIMEOUT
Definition: flow-private.h:40
tm-threads.h
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:437
Packet_::proto
uint8_t proto
Definition: decode.h:431
DecodeSetNoPacketInspectionFlag
#define DecodeSetNoPacketInspectionFlag(p)
Set the No packet inspection Flag for the packet.
Definition: decode.h:968
FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT
#define FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT
Definition: flow-private.h:57
TcpStream_
Definition: stream-tcp-private.h:94
flow-bypass.h
FLOW_PROTO_MAX
@ FLOW_PROTO_MAX
Definition: flow-private.h:75
FLOW_HAS_EXPECTATION
#define FLOW_HAS_EXPECTATION
Definition: flow.h:108
len
uint8_t len
Definition: app-layer-dnp3.h:4
FlowSetHasAlertsFlag
void FlowSetHasAlertsFlag(Flow *f)
Set flag to indicate that flow has alerts.
Definition: flow.c:212
FlowCleanupAppLayer
void FlowCleanupAppLayer(Flow *f)
Definition: flow.c:140
SC_ATOMIC_DESTROY
#define SC_ATOMIC_DESTROY(name)
Destroy the lock used to protect this variable.
Definition: util-atomic.h:97
FlowSetChangeProtoFlag
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
Definition: flow.c:236
FLOW_DEFAULT_CLOSED_TIMEOUT
#define FLOW_DEFAULT_CLOSED_TIMEOUT
Definition: flow-private.h:42
PKT_HAS_FLOW
#define PKT_HAS_FLOW
Definition: decode.h:1077
SC_ERR_INVALID_VALUE
@ SC_ERR_INVALID_VALUE
Definition: util-error.h:160
FlowGetPacketDirection
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
Definition: flow.c:335
FLOW_STATE_ESTABLISHED
@ FLOW_STATE_ESTABLISHED
Definition: flow.h:484
flow-util.h
SC_ATOMIC_INIT
#define SC_ATOMIC_INIT(name)
Initialize the previously declared atomic variable and it's lock.
Definition: util-atomic.h:81
FBLOCK_INIT
#define FBLOCK_INIT(fb)
Definition: flow-hash.h:66
PKT_IS_IPV6
#define PKT_IS_IPV6(p)
Definition: decode.h:253
CLS
#define CLS
Definition: suricata-common.h:45
stream-tcp.h
FLOW_DEFAULT_HASHSIZE
#define FLOW_DEFAULT_HASHSIZE
Definition: flow.c:70
unlikely
#define unlikely(expr)
Definition: util-optimize.h:35
FlowCnf_::emergency_recovery
uint32_t emergency_recovery
Definition: flow.h:290
FLOW_DEFAULT_PREALLOC
#define FLOW_DEFAULT_PREALLOC
Definition: flow.c:74
SC_ATOMIC_SET
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
Definition: util-atomic.h:207
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
FlowCnf_::hash_size
uint32_t hash_size
Definition: flow.h:281
FlowRegisterTests
void FlowRegisterTests(void)
Function to register the Flow Unitests.
Definition: flow.c:1362
SCLogDebug
#define SCLogDebug(...)
Definition: util-debug.h:335
FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT
Definition: flow-private.h:60
FLOW_SGH_TOCLIENT
#define FLOW_SGH_TOCLIENT
Definition: flow.h:69
Flow_::hnext
struct Flow_ * hnext
Definition: flow.h:467
Packet_::pcap_cnt
uint64_t pcap_cnt
Definition: decode.h:562
ParseSizeStringU64
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition: util-misc.c:203
SCFreeAligned
#define SCFreeAligned(a)
Free aligned memory.
Definition: util-mem.h:388
Flow_::proto
uint8_t proto
Definition: flow.h:361
AppProto
uint16_t AppProto
Definition: app-layer-protos.h:71
FLOW_PROTO_ICMP
@ FLOW_PROTO_ICMP
Definition: flow-private.h:70
FLOWFILE_NO_MAGIC_TS
#define FLOWFILE_NO_MAGIC_TS
Definition: flow.h:115
Packet_::flags
uint32_t flags
Definition: decode.h:444
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:176
threads.h
flow-private.h
Flow_
Flow data structure.
Definition: flow.h:342
run_mode
int run_mode
Definition: suricata.c:201
SC_ATOMIC_ADD
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
Definition: util-atomic.h:107
FlowInitConfig
void FlowInitConfig(char quiet)
initialize the configuration
Definition: flow.c:530
FlowProtoTimeout_
Definition: flow.h:492
flow-hash.h
FLOW_NOPAYLOAD_INSPECTION
#define FLOW_NOPAYLOAD_INSPECTION
Definition: flow.h:61
FLOW_TS_PM_ALPROTO_DETECT_DONE
#define FLOW_TS_PM_ALPROTO_DETECT_DONE
Definition: flow.h:80
FLOW_DEFAULT_EMERG_NEW_TIMEOUT
#define FLOW_DEFAULT_EMERG_NEW_TIMEOUT
Definition: flow-private.h:54
FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT
Definition: flow-private.h:58
BypassedFlowUpdate
void BypassedFlowUpdate(Flow *f, Packet *p)
Definition: flow-bypass.c:203
FlowProtoTimeout_::bypassed_timeout
uint32_t bypassed_timeout
Definition: flow.h:496
FLOW_DEFAULT_EST_TIMEOUT
#define FLOW_DEFAULT_EST_TIMEOUT
Definition: flow-private.h:41
FLOW_PKT_TOSERVER
#define FLOW_PKT_TOSERVER
Definition: flow.h:218
FlowGetMemuse
uint64_t FlowGetMemuse(void)
Definition: flow.c:134
MIN
#define MIN(x, y)
Definition: suricata-common.h:360
FlowGetMemcap
uint64_t FlowGetMemcap(void)
Return memcap value.
Definition: flow.c:128
FlowQueueDestroy
void FlowQueueDestroy(FlowQueue *q)
Destroy a flow queue.
Definition: flow-queue.c:61
util-privs.h
stream-tcp-reassemble.h
TcpStream_::flags
uint16_t flags
Definition: stream-tcp-private.h:95
RandomGet
long int RandomGet(void)
Definition: util-random.c:129
FLOW_TOSERVER_DROP_LOGGED
#define FLOW_TOSERVER_DROP_LOGGED
Definition: flow.h:72
Flow_::max_ttl_toserver
uint8_t max_ttl_toserver
Definition: flow.h:446
proto
uint8_t proto
Definition: decode-template.h:2
FLOW_TC_PE_ALPROTO_DETECT_DONE
#define FLOW_TC_PE_ALPROTO_DETECT_DONE
Definition: flow.h:90
FLOW_DEFAULT_BYPASSED_TIMEOUT
#define FLOW_DEFAULT_BYPASSED_TIMEOUT
Definition: flow-private.h:43
Packet_::flowflags
uint8_t flowflags
Definition: decode.h:440
MAX
#define MAX(x, y)
Definition: suricata-common.h:364
Flow_::protoctx
void * protoctx
Definition: flow.h:416
FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT
Definition: flow-private.h:49
STREAMTCP_STREAM_FLAG_DEPTH_REACHED
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
Definition: stream-tcp-private.h:204
FlowEnqueue
void FlowEnqueue(FlowQueue *q, Flow *f)
add a flow to a queue
Definition: flow-queue.c:72
FlowQueue_::len
uint32_t len
Definition: flow-queue.h:45
util-unittest.h
FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT
#define FLOW_DEFAULT_EMERG_CLOSED_TIMEOUT
Definition: flow-private.h:56
FLOW_BYPASSED_TIMEOUT
#define FLOW_BYPASSED_TIMEOUT
Definition: flow-private.h:65
FlowGetAppState
void * FlowGetAppState(const Flow *f)
Definition: flow.c:1087
util-unittest-helper.h
FLOW_IPPROTO_ICMP_EST_TIMEOUT
#define FLOW_IPPROTO_ICMP_EST_TIMEOUT
Definition: flow-private.h:51
FlowCnf_::prealloc
uint32_t prealloc
Definition: flow.h:283
UTHBuildPacketOfFlows
uint32_t UTHBuildPacketOfFlows(uint32_t start, uint32_t end, uint8_t dir)
Definition: util-unittest-helper.c:902
AppLayerExpectationClean
void AppLayerExpectationClean(Flow *f)
Definition: app-layer-expectation.c:359
PKT_PROTO_DETECT_TS_DONE
#define PKT_PROTO_DETECT_TS_DONE
Definition: decode.h:1101
FQLOCK_LOCK
#define FQLOCK_LOCK(q)
Definition: flow-queue.h:67
Flow_::sgh_toserver
const struct SigGroupHead_ * sgh_toserver
Definition: flow.h:461
FLOW_CHECK_MEMCAP
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition: flow-util.h:137
FLOW_RECYCLE
#define FLOW_RECYCLE(f)
macro to recycle a flow before it goes into the spare queue for reuse.
Definition: flow-util.h:84
Flow_::tosrcbytecnt
uint64_t tosrcbytecnt
Definition: flow.h:479
SC_ERR_SIZE_PARSE
@ SC_ERR_SIZE_PARSE
Definition: util-error.h:230
ConfGet
int ConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition: conf.c:331
Flow_::alparser
AppLayerParserState * alparser
Definition: flow.h:453
FLOW_IPPROTO_ICMP_EMERG_EST_TIMEOUT
#define FLOW_IPPROTO_ICMP_EMERG_EST_TIMEOUT
Definition: flow-private.h:63
Flow_::fb
struct FlowBucket_ * fb
Definition: flow.h:469
app-layer-expectation.h
FLOW_IPPROTO_UDP_EST_TIMEOUT
#define FLOW_IPPROTO_UDP_EST_TIMEOUT
Definition: flow-private.h:48
SC_ERR_FLOW_INIT
@ SC_ERR_FLOW_INIT
Definition: util-error.h:237
FLOW_STATE_LOCAL_BYPASSED
@ FLOW_STATE_LOCAL_BYPASSED
Definition: flow.h:486
Flow_::min_ttl_toserver
uint8_t min_ttl_toserver
Definition: flow.h:445
decode.h
util-debug.h
TOSERVER
#define TOSERVER
Definition: flow.h:41
PASS
#define PASS
Pass the test.
Definition: util-unittest.h:105
Flow_::todstpktcnt
uint32_t todstpktcnt
Definition: flow.h:476
DecodeSetNoPayloadInspectionFlag
#define DecodeSetNoPayloadInspectionFlag(p)
Set the No payload inspection Flag for the packet.
Definition: decode.h:956
STREAM_TOSERVER
#define STREAM_TOSERVER
Definition: stream.h:31
SCEnter
#define SCEnter(...)
Definition: util-debug.h:337
FLOW_CHANGE_PROTO
#define FLOW_CHANGE_PROTO
Definition: flow.h:102
detect.h
ThreadVars_
Per thread variable structure.
Definition: threadvars.h:57
FlowStorageSize
unsigned int FlowStorageSize(void)
Definition: flow-storage.c:34
Packet_::sp
Port sp
Definition: decode.h:416
FlowCnf_
Definition: flow.h:278
FLOW_PKT_TOCLIENT_FIRST
#define FLOW_PKT_TOCLIENT_FIRST
Definition: flow.h:224
FlowQueueInit
FlowQueue * FlowQueueInit(FlowQueue *q)
Definition: flow-queue.c:47
FlowState
FlowState
Definition: flow.h:482
FlowProtoTimeout_::new_timeout
uint32_t new_timeout
Definition: flow.h:493
FlowProtoTimeout_::closed_timeout
uint32_t closed_timeout
Definition: flow.h:495
util-time.h
app-layer-parser.h
AppLayerParserStateCleanup
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
Definition: app-layer-parser.c:1451
FLOW_PROTO_DETECT_TC_DONE
#define FLOW_PROTO_DETECT_TC_DONE
Definition: flow.h:99
Flow_::todstbytecnt
uint64_t todstbytecnt
Definition: flow.h:478
FLOW_TC_PP_ALPROTO_DETECT_DONE
#define FLOW_TC_PP_ALPROTO_DETECT_DONE
Definition: flow.h:88
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:265
Flow_::sgh_toclient
const struct SigGroupHead_ * sgh_toclient
Definition: flow.h:458
SC_ATOMIC_SUB
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
Definition: util-atomic.h:124
FALSE
#define FALSE
Definition: suricata-common.h:34
stream.h
TimeSetIncrementTime
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition: util-time.c:182
FlowGetProtoMapping
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition: flow-util.c:95
Packet_
Definition: decode.h:408
STREAM_DEPTH
#define STREAM_DEPTH
Definition: stream.h:34
FLOW_DEFAULT_MEMCAP
#define FLOW_DEFAULT_MEMCAP
Definition: flow.c:72
GET_PKT_LEN
#define GET_PKT_LEN(p)
Definition: decode.h:225
stream-tcp-private.h
conf.h
FlowSetIPOnlyFlag
void FlowSetIPOnlyFlag(Flow *f, int direction)
Set the IPOnly scanned flag for 'direction'.
Definition: flow.c:201
FLOW_TOSERVER_IPONLY_SET
#define FLOW_TOSERVER_IPONLY_SET
Definition: flow.h:54
FLOW_IPPROTO_TCP_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_NEW_TIMEOUT
Definition: flow-private.h:44
FLOW_PROTO_DEFAULT
@ FLOW_PROTO_DEFAULT
Definition: flow-private.h:72
FlowProtoFreeFunc_::Freefunc
void(* Freefunc)(void *)
Definition: flow.h:500
FlowClearMemory
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
Definition: flow.c:1045
FlowGetFlowFromHash
Flow * FlowGetFlowFromHash(ThreadVars *tv, DecodeThreadVars *dtv, const Packet *p, Flow **dest)
Get Flow for packet.
Definition: flow-hash.c:604
FlowCnf_::hash_rand
uint32_t hash_rand
Definition: flow.h:280
detect-engine-state.h
Data structures and function prototypes for keeping state for the detection engine.
STREAM_GAP
#define STREAM_GAP
Definition: stream.h:33
flow-timeout.h
Flow_::min_ttl_toclient
uint8_t min_ttl_toclient
Definition: flow.h:447
flow-queue.h
Flow_::probing_parser_toclient_alproto_masks
uint32_t probing_parser_toclient_alproto_masks
Definition: flow.h:394
FLOW_PKT_TOCLIENT
#define FLOW_PKT_TOCLIENT
Definition: flow.h:219
runmodes.h
FLOW_TO_DST_SEEN
#define FLOW_TO_DST_SEEN
Definition: flow.h:49
SC_ERR_INVALID_YAML_CONF_ENTRY
@ SC_ERR_INVALID_YAML_CONF_ENTRY
Definition: util-error.h:169
Flow_::src
FlowAddress src
Definition: flow.h:346
FlowQueue_
Definition: flow-queue.h:41
Flow_::probing_parser_toserver_alproto_masks
uint32_t probing_parser_toserver_alproto_masks
Definition: flow.h:393
dtv
DecodeThreadVars * dtv
Definition: fuzz_decodepcapfile.c:33
Flow_::lastts
struct timeval lastts
Definition: flow.h:375
ConfNodeLookupChild
ConfNode * ConfNodeLookupChild(const ConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition: conf.c:815
flow_hash
FlowBucket * flow_hash
Definition: flow-hash.c:52
FlowDequeue
Flow * FlowDequeue(FlowQueue *q)
remove a flow from the queue
Definition: flow-queue.c:105
FLOW_TO_SRC_SEEN
#define FLOW_TO_SRC_SEEN
Definition: flow.h:47
StringParseUint32
int StringParseUint32(uint32_t *res, int base, uint16_t len, const char *str)
Definition: util-byte.c:304
flow-storage.h
FLOW_TS_PE_ALPROTO_DETECT_DONE
#define FLOW_TS_PE_ALPROTO_DETECT_DONE
Definition: flow.h:84
Packet_::flow
struct Flow_ * flow
Definition: decode.h:446
FLOW_IPPROTO_UDP_NEW_TIMEOUT
#define FLOW_IPPROTO_UDP_NEW_TIMEOUT
Definition: flow-private.h:47
FlowSetProtoFreeFunc
int FlowSetProtoFreeFunc(uint8_t, void(*Free)(void *))
Function to set the function to get protocol specific flow state.
Definition: flow.c:1073
FLOW_IPPROTO_ICMP_NEW_TIMEOUT
#define FLOW_IPPROTO_ICMP_NEW_TIMEOUT
Definition: flow-private.h:50
FAIL_IF
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
flow_timeouts_normal
FlowProtoTimeout flow_timeouts_normal[FLOW_PROTO_MAX]
Definition: flow.c:89
CMP_ADDR
#define CMP_ADDR(a1, a2)
Definition: decode.h:240
flow_spare_q
FlowQueue flow_spare_q
Definition: flow.c:94
FLOWFILE_NO_MAGIC_TC
#define FLOWFILE_NO_MAGIC_TC
Definition: flow.h:116
flags
uint8_t flags
Definition: decode-gre.h:2
FLOW_TOCLIENT_IPONLY_SET
#define FLOW_TOCLIENT_IPONLY_SET
Definition: flow.h:56
Packet_::ts
struct timeval ts
Definition: decode.h:452
flow-manager.h
suricata-common.h
FlowFree
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition: flow-util.c:80
flow_config
FlowConfig flow_config
Definition: flow.c:96
FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT
Definition: flow-private.h:46
FLOW_HAS_ALERTS
#define FLOW_HAS_ALERTS
Definition: flow.h:77
FlowShutdown
void FlowShutdown(void)
shutdown the flow engine
Definition: flow.c:685
SWAP_VARS
#define SWAP_VARS(type, a, b)
Definition: suricata-common.h:389
FlowTimeoutsInit
void FlowTimeoutsInit(void)
Definition: flow-manager.c:98
STREAM_TOCLIENT
#define STREAM_TOCLIENT
Definition: stream.h:32
FLOW_PROTO_DETECT_TS_DONE
#define FLOW_PROTO_DETECT_TS_DONE
Definition: flow.h:98
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
Flow_::max_ttl_toclient
uint8_t max_ttl_toclient
Definition: flow.h:448
TcpSession_::client
TcpStream client
Definition: stream-tcp-private.h:272
FLOW_TS_PP_ALPROTO_DETECT_DONE
#define FLOW_TS_PP_ALPROTO_DETECT_DONE
Definition: flow.h:82
PKT_PROTO_DETECT_TC_DONE
#define PKT_PROTO_DETECT_TC_DONE
Definition: decode.h:1102
FlowGetLastTimeAsParts
void FlowGetLastTimeAsParts(Flow *flow, uint64_t *secs, uint64_t *usecs)
Get flow last time as individual values.
Definition: flow.c:1142
FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT
Definition: flow-private.h:59
FlowHandlePacketUpdate
void FlowHandlePacketUpdate(Flow *f, Packet *p)
Update Packet and Flow.
Definition: flow.c:413
tv
ThreadVars * tv
Definition: fuzz_decodepcapfile.c:32
PKT_IS_ICMPV4
#define PKT_IS_ICMPV4(p)
Definition: decode.h:256
threadvars.h
FLOW_PROTO_UDP
@ FLOW_PROTO_UDP
Definition: flow-private.h:69
FlowSwap
void FlowSwap(Flow *f)
swap the flow's direction
Definition: flow.c:304
FlowGetAppProtocol
AppProto FlowGetAppProtocol(const Flow *f)
Definition: flow.c:1082
FlowHandlePacket
void FlowHandlePacket(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p)
Entry point for packet flow handling.
Definition: flow.c:514
FLOW_PROTO_TCP
@ FLOW_PROTO_TCP
Definition: flow-private.h:68
ICMPV4_IS_ERROR_MSG
#define ICMPV4_IS_ERROR_MSG(p)
Definition: decode-icmpv4.h:264
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
FlowInitFlowProto
void FlowInitFlowProto(void)
Function to set the default timeout, free function and flow state function for all supported flow_pro...
Definition: flow.c:738
TcpSession_::server
TcpStream server
Definition: stream-tcp-private.h:271
flow_recycle_q
FlowQueue flow_recycle_q
Definition: flow-manager.c:75
SWAP_FLAGS
#define SWAP_FLAGS(flags, a, b)
Definition: suricata-common.h:378
FLOW_SGH_TOSERVER
#define FLOW_SGH_TOSERVER
Definition: flow.h:67
CMP_PORT
#define CMP_PORT(p1, p2)
Definition: decode.h:245
DecodeThreadVars_
Structure to hold thread specific data for all decode modules.
Definition: decode.h:622
Flow_::alproto_ts
AppProto alproto_ts
Definition: flow.h:426
ConfNode_
Definition: conf.h:32
Flow_::alstate
void * alstate
Definition: flow.h:454
flow_freefuncs
FlowProtoFreeFunc flow_freefuncs[FLOW_PROTO_MAX]
Definition: flow.c:91
SC_ERR_FATAL
@ SC_ERR_FATAL
Definition: util-error.h:203
flow_timeouts_emerg
FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX]
Definition: flow.c:90
Flow_::flags
uint32_t flags
Definition: flow.h:396
FLOW_IPPROTO_UDP_EMERG_EST_TIMEOUT
#define FLOW_IPPROTO_UDP_EMERG_EST_TIMEOUT
Definition: flow-private.h:61
FlowFreeStorage
void FlowFreeStorage(Flow *f)
Definition: flow-storage.c:59
SCMallocAligned
#define SCMallocAligned(a, b)
wrapper for allocing aligned mem
Definition: util-mem.h:363
SC_ATOMIC_DECLARE
SC_ATOMIC_DECLARE(unsigned int, flow_prune_idx)
FLOW_IPPROTO_ICMP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_ICMP_EMERG_NEW_TIMEOUT
Definition: flow-private.h:62
FLOW_TOCLIENT_DROP_LOGGED
#define FLOW_TOCLIENT_DROP_LOGGED
Definition: flow.h:74
util-random.h
FLOW_PKT_ESTABLISHED
#define FLOW_PKT_ESTABLISHED
Definition: flow.h:220
IPV6_GET_HLIM
#define IPV6_GET_HLIM(p)
Definition: decode-ipv6.h:90
EngineModeIsIPS
int EngineModeIsIPS(void)
Definition: suricata.c:244
FLOW_EMERGENCY
#define FLOW_EMERGENCY
Definition: flow-private.h:37
suricata.h
FLOW_QUIET
#define FLOW_QUIET
Definition: flow.h:38
FLOW_TC_PM_ALPROTO_DETECT_DONE
#define FLOW_TC_PM_ALPROTO_DETECT_DONE
Definition: flow.h:86
FLOW_DEFAULT_EMERGENCY_RECOVERY
#define FLOW_DEFAULT_EMERGENCY_RECOVERY
Definition: flow.c:67
FlowHasAlerts
int FlowHasAlerts(const Flow *f)
Check if flow has alerts.
Definition: flow.c:223
COPY_TIMESTAMP
#define COPY_TIMESTAMP(src, dst)
Definition: flow-util.h:30
STREAMTCP_STREAM_FLAG_GAP
#define STREAMTCP_STREAM_FLAG_GAP
Definition: stream-tcp-private.h:198
FLOW_DEFAULT_EMERG_EST_TIMEOUT
#define FLOW_DEFAULT_EMERG_EST_TIMEOUT
Definition: flow-private.h:55
FLOW_NOPACKET_INSPECTION
#define FLOW_NOPACKET_INSPECTION
Definition: flow.h:59
FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT
Definition: flow-private.h:52
FlowProtoTimeout_::est_timeout
uint32_t est_timeout
Definition: flow.h:494
FlowChangeProto
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition: flow.c:255
Flow_::sp
Port sp
Definition: flow.h:348
SC_ATOMIC_GET
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
Definition: util-atomic.h:192
FlowUpdateSpareFlows
int FlowUpdateSpareFlows(void)
Make sure we have enough spare flows.
Definition: flow.c:159
FlowGetDisruptionFlags
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
Definition: flow.c:1099
TcpSession_
Definition: stream-tcp-private.h:260
util-misc.h
TcpSession_::data_first_seen_dir
int8_t data_first_seen_dir
Definition: stream-tcp-private.h:265
flow.h
FlowAlloc
Flow * FlowAlloc(void)
allocate a flow
Definition: flow-util.c:51
Flow_::alproto_tc
AppProto alproto_tc
Definition: flow.h:427
Flow_::file_flags
uint16_t file_flags
Definition: flow.h:398
Flow_::alproto
AppProto alproto
application level protocol
Definition: flow.h:425
Packet_::dp
Port dp
Definition: decode.h:424
FLOW_DIR_REVERSED
#define FLOW_DIR_REVERSED
Definition: flow.h:106
SCReturnInt
#define SCReturnInt(x)
Definition: util-debug.h:341
FLOW_IPPROTO_TCP_EST_TIMEOUT
#define FLOW_IPPROTO_TCP_EST_TIMEOUT
Definition: flow-private.h:45
RegisterFlowStorageTests
void RegisterFlowStorageTests(void)
Definition: flow-storage.c:289
SET_DEFAULTS
#define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be)
flow-var.h
PKT_IS_IPV4
#define PKT_IS_IPV4(p)
Definition: decode.h:252
TOCLIENT
#define TOCLIENT
Definition: flow.h:42
FLOW_PKT_TOSERVER_FIRST
#define FLOW_PKT_TOSERVER_FIRST
Definition: flow.h:223
Packet_::src
Address src
Definition: decode.h:413
Flow_::tosrcpktcnt
uint32_t tosrcpktcnt
Definition: flow.h:477
FlowUpdateState
void FlowUpdateState(Flow *f, enum FlowState s)
Definition: flow.c:1123
IPV4_GET_IPTTL
#define IPV4_GET_IPTTL(p)
Definition: decode-ipv4.h:146
FlowSetMemcap
int FlowSetMemcap(uint64_t size)
Update memcap value.
Definition: flow.c:113
FlowProtoFreeFunc_
Definition: flow.h:499
FQLOCK_UNLOCK
#define FQLOCK_UNLOCK(q)
Definition: flow-queue.h:69
ConfNodeLookupChildValue
const char * ConfNodeLookupChildValue(const ConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition: conf.c:843