suricata
flow.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2024 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * Flow implementation.
24 */
25
26#include "suricata-common.h"
27#include "suricata.h"
28
29#include "action-globals.h"
30#include "packet.h"
31#include "decode.h"
32#include "conf.h"
33#include "threadvars.h"
34
35#include "util-random.h"
36#include "util-time.h"
37
38#include "flow.h"
39#include "flow-queue.h"
40#include "flow-hash.h"
41#include "flow-util.h"
42#include "flow-private.h"
43#include "flow-manager.h"
44#include "flow-storage.h"
45#include "flow-bypass.h"
46#include "flow-spare-pool.h"
47#include "flow-callbacks.h"
48
49#include "stream-tcp-private.h"
50
51#include "util-unittest.h"
53#include "util-byte.h"
54#include "util-misc.h"
55#include "util-macset.h"
56#include "util-flow-rate.h"
57
58#include "util-debug.h"
59
60#include "rust.h"
61#include "app-layer-parser.h"
63
64#define FLOW_DEFAULT_EMERGENCY_RECOVERY 30
65
66//#define FLOW_DEFAULT_HASHSIZE 262144
67#define FLOW_DEFAULT_HASHSIZE 65536
68//#define FLOW_DEFAULT_MEMCAP 128 * 1024 * 1024 /* 128 MB */
69#define FLOW_DEFAULT_MEMCAP (32 * 1024 * 1024) /* 32 MB */
70
71#define FLOW_DEFAULT_PREALLOC 10000
72
74
75/** atomic int that is used when freeing a flow from the hash. In this
76 * case we walk the hash to find a flow to free. This var records where
77 * we left off in the hash. Without this only the top rows of the hash
78 * are freed. This isn't just about fairness. Under severe pressure, the
79 * hash rows on top would be all freed and the time to find a flow to
80 * free increased with every run. */
81SC_ATOMIC_DECLARE(unsigned int, flow_prune_idx);
82
83/** atomic flags */
84SC_ATOMIC_DECLARE(unsigned int, flow_flags);
85
86/** FlowProto specific timeouts and free/state functions */
87
92
94
95/** flow memuse counter (atomic), for enforcing memcap limit */
96SC_ATOMIC_DECLARE(uint64_t, flow_memuse);
97
98void FlowRegisterTests(void);
99void FlowInitFlowProto(void);
100int FlowSetProtoFreeFunc(uint8_t, void (*Free)(void *));
101
102/**
103 * \brief Update memcap value
104 *
105 * \param size new memcap value
106 */
107int FlowSetMemcap(uint64_t size)
108{
109 if ((uint64_t)SC_ATOMIC_GET(flow_memuse) < size) {
110 SC_ATOMIC_SET(flow_config.memcap, size);
111 return 1;
112 }
113
114 return 0;
115}
116
117/**
118 * \brief Return memcap value
119 *
120 * \retval memcap value
121 */
122uint64_t FlowGetMemcap(void)
123{
124 uint64_t memcapcopy = SC_ATOMIC_GET(flow_config.memcap);
125 return memcapcopy;
126}
127
128uint64_t FlowGetMemuse(void)
129{
130 uint64_t memusecopy = SC_ATOMIC_GET(flow_memuse);
131 return memusecopy;
132}
133
138
140{
141 if (f == NULL || f->proto == 0)
142 return;
143
145 f->alstate = NULL;
146 f->alparser = NULL;
147}
148
149/** \brief Set flag to indicate that flow has alerts
150 *
151 * \param f flow
152 */
154{
156}
157
158/** \brief Check if flow has alerts
159 *
160 * \param f flow
161 * \retval 1 has alerts
162 * \retval 0 has not alerts
163 */
164int FlowHasAlerts(const Flow *f)
165{
166 if (f->flags & FLOW_HAS_ALERTS) {
167 return 1;
168 }
169
170 return 0;
171}
172
173/** \brief Set flag to indicate to change proto for the flow
174 *
175 * \param f flow
176 */
181
182/** \brief Unset flag to indicate to change proto for the flow
183 *
184 * \param f flow
185 */
187{
188 f->flags &= ~FLOW_CHANGE_PROTO;
189}
190
191/** \brief Check if change proto flag is set for flow
192 * \param f flow
193 * \retval 1 change proto flag is set
194 * \retval 0 change proto flag is not set
195 */
197{
198 if (f->flags & FLOW_CHANGE_PROTO) {
199 return 1;
200 }
201
202 return 0;
203}
204
205static inline void FlowSwapFlags(Flow *f)
206{
209
214
216}
217
218static inline void FlowSwapFileFlags(Flow *f)
219{
226}
227
228static inline void TcpStreamFlowSwap(Flow *f)
229{
230 TcpSession *ssn = f->protoctx;
231 SWAP_VARS(TcpStream, ssn->server, ssn->client);
232 if (ssn->data_first_seen_dir & STREAM_TOSERVER) {
233 ssn->data_first_seen_dir = STREAM_TOCLIENT;
234 } else if (ssn->data_first_seen_dir & STREAM_TOCLIENT) {
235 ssn->data_first_seen_dir = STREAM_TOSERVER;
236 }
237}
238
239/** \brief swap the flow's direction
240 * \note leaves the 'header' untouched. Interpret that based
241 * on FLOW_DIR_REVERSED flag.
242 * \warning: only valid before applayer parsing started. This
243 * function doesn't swap anything in Flow::alparser,
244 * Flow::alstate
245 */
247{
249
252
253 FlowSwapFlags(f);
254 FlowSwapFileFlags(f);
255
257
258 if (f->proto == IPPROTO_TCP) {
259 TcpStreamFlowSwap(f);
260 }
261
265
266 /* not touching Flow::alparser and Flow::alstate */
267
268 SWAP_VARS(const void *, f->sgh_toclient, f->sgh_toserver);
269
270 SWAP_VARS(uint32_t, f->todstpktcnt, f->tosrcpktcnt);
271 SWAP_VARS(uint64_t, f->todstbytecnt, f->tosrcbytecnt);
272}
273
274/**
275 * \brief determine the direction of the packet compared to the flow
276 * \retval 0 to_server
277 * \retval 1 to_client
278 */
279int FlowGetPacketDirection(const Flow *f, const Packet *p)
280{
281 const int reverse = (f->flags & FLOW_DIR_REVERSED) != 0;
282
283 if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP || p->proto == IPPROTO_SCTP) {
284 if (!(CMP_PORT(p->sp,p->dp))) {
285 /* update flags and counters */
286 if (CMP_PORT(f->sp,p->sp)) {
287 return TOSERVER ^ reverse;
288 } else {
289 return TOCLIENT ^ reverse;
290 }
291 } else {
292 if (CMP_ADDR(&f->src,&p->src)) {
293 return TOSERVER ^ reverse;
294 } else {
295 return TOCLIENT ^ reverse;
296 }
297 }
298 } else if (p->proto == IPPROTO_ICMP || p->proto == IPPROTO_ICMPV6) {
299 if (CMP_ADDR(&f->src,&p->src)) {
300 return TOSERVER ^ reverse;
301 } else {
302 return TOCLIENT ^ reverse;
303 }
304 }
305
306 /* default to toserver */
307 return TOSERVER;
308}
309
310/**
311 * \brief Check to update "seen" flags
312 *
313 * \param p packet
314 *
315 * \retval 1 true
316 * \retval 0 false
317 */
318static inline int FlowUpdateSeenFlag(const Packet *p)
319{
320 if (PacketIsICMPv4(p)) {
322 return 0;
323 }
324 }
325
326 return 1;
327}
328
329static inline void FlowUpdateTtlTS(Flow *f, uint8_t ttl)
330{
331 if (f->min_ttl_toserver == 0) {
332 f->min_ttl_toserver = ttl;
333 } else {
335 }
337}
338
339static inline void FlowUpdateTtlTC(Flow *f, uint8_t ttl)
340{
341 if (f->min_ttl_toclient == 0) {
342 f->min_ttl_toclient = ttl;
343 } else {
345 }
347}
348
349static inline void FlowUpdateFlowRate(
350 ThreadVars *tv, DecodeThreadVars *dtv, Flow *f, const Packet *p, int dir)
351{
353 /* No need to update the struct if flow is already marked as elephant flow */
354 if (f->flags & FLOW_IS_ELEPHANT)
355 return;
357 if (frs != NULL) {
358 FlowRateStoreUpdate(frs, p->ts, GET_PKT_LEN(p), dir);
359 bool fr_exceeds = FlowRateIsExceeding(frs, dir);
360 if (fr_exceeds) {
361 SCLogDebug("Flow rate for flow %p exceeds the configured values, marking it as an "
362 "elephant flow",
363 f);
365 if (tv != NULL) {
367 }
368 }
369 }
370 }
371}
372
373static inline void FlowUpdateEthernet(
374 ThreadVars *tv, DecodeThreadVars *dtv, Flow *f, const Packet *p, bool toserver)
375{
376 if (PacketIsEthernet(p) && MacSetFlowStorageEnabled()) {
377 const EthernetHdr *ethh = PacketGetEthernet(p);
379 if (ms != NULL) {
380 if (toserver) {
381 MacSetAddWithCtr(ms, ethh->eth_src, ethh->eth_dst, tv,
384 } else {
385 MacSetAddWithCtr(ms, ethh->eth_dst, ethh->eth_src, tv,
388 }
389 }
390 }
391}
392
393/** \brief Update Packet and Flow
394 *
395 * Updates packet and flow based on the new packet.
396 *
397 * \param f locked flow
398 * \param p packet
399 *
400 * \note overwrites p::flowflags
401 */
403{
404 SCLogDebug("packet %"PRIu64" -- flow %p", p->pcap_cnt, f);
405
406 const int pkt_dir = FlowGetPacketDirection(f, p);
407#ifdef CAPTURE_OFFLOAD
408 int state = f->flow_state;
409
410 if (state != FLOW_STATE_CAPTURE_BYPASSED) {
411#endif
412 /* update the last seen timestamp of this flow */
413 if (SCTIME_CMP_GT(p->ts, f->lastts)) {
414 f->lastts = p->ts;
415 }
416#ifdef CAPTURE_OFFLOAD
417 } else {
418 /* still seeing packet, we downgrade to local bypass */
420 SCLogDebug("Downgrading flow to local bypass");
421 f->lastts = p->ts;
423 } else {
424 /* In IPS mode the packet could come from the other interface so it would
425 * need to be bypassed */
426 if (EngineModeIsIPS()) {
427 BypassedFlowUpdate(f, p);
428 }
429 }
430 }
431#endif
432 /* update flags and counters */
433 if (pkt_dir == TOSERVER) {
434 f->todstpktcnt++;
435 f->todstbytecnt += GET_PKT_LEN(p);
436 FlowUpdateFlowRate(tv, dtv, f, p, TOSERVER);
438 if (!(f->flags & FLOW_TO_DST_SEEN)) {
439 if (FlowUpdateSeenFlag(p)) {
443 }
444 }
445 /* xfer proto detect ts flag to first packet in ts dir */
447 f->flags &= ~FLOW_PROTO_DETECT_TS_DONE;
449 }
450 FlowUpdateEthernet(tv, dtv, f, p, true);
451 /* update flow's ttl fields if needed */
452 if (PacketIsIPv4(p)) {
453 const IPV4Hdr *ip4h = PacketGetIPv4(p);
454 FlowUpdateTtlTS(f, IPV4_GET_RAW_IPTTL(ip4h));
455 } else if (PacketIsIPv6(p)) {
456 const IPV6Hdr *ip6h = PacketGetIPv6(p);
457 FlowUpdateTtlTS(f, IPV6_GET_RAW_HLIM(ip6h));
458 }
459 } else {
460 f->tosrcpktcnt++;
461 f->tosrcbytecnt += GET_PKT_LEN(p);
462 FlowUpdateFlowRate(tv, dtv, f, p, TOCLIENT);
464 if (!(f->flags & FLOW_TO_SRC_SEEN)) {
465 if (FlowUpdateSeenFlag(p)) {
469 }
470 }
471 /* xfer proto detect tc flag to first packet in tc dir */
473 f->flags &= ~FLOW_PROTO_DETECT_TC_DONE;
475 }
476 FlowUpdateEthernet(tv, dtv, f, p, false);
477 /* update flow's ttl fields if needed */
478 if (PacketIsIPv4(p)) {
479 const IPV4Hdr *ip4h = PacketGetIPv4(p);
480 FlowUpdateTtlTC(f, IPV4_GET_RAW_IPTTL(ip4h));
481 } else if (PacketIsIPv6(p)) {
482 const IPV6Hdr *ip6h = PacketGetIPv6(p);
483 FlowUpdateTtlTC(f, IPV6_GET_RAW_HLIM(ip6h));
484 }
485 }
486 if (f->thread_id[pkt_dir] == 0) {
487 f->thread_id[pkt_dir] = (FlowThreadId)tv->id;
488 }
489
491 SCLogDebug("pkt %p FLOW_PKT_ESTABLISHED", p);
493
494 } else if (f->proto == IPPROTO_TCP) {
495 TcpSession *ssn = (TcpSession *)f->protoctx;
496 if (ssn != NULL && ssn->state >= TCP_ESTABLISHED) {
498 }
499 } else if ((f->flags & (FLOW_TO_DST_SEEN|FLOW_TO_SRC_SEEN)) ==
501 SCLogDebug("pkt %p FLOW_PKT_ESTABLISHED", p);
503
504 if (
505#ifdef CAPTURE_OFFLOAD
506 (f->flow_state != FLOW_STATE_CAPTURE_BYPASSED) &&
507#endif
510 }
511 }
512
513 if (f->flags & FLOW_ACTION_DROP) {
515 }
516
518 SCLogDebug("setting FLOW_NOPAYLOAD_INSPECTION flag on flow %p", f);
519 DecodeSetNoPayloadInspectionFlag(p);
520 }
521
523}
524
525/** \brief Entry point for packet flow handling
526 *
527 * This is called for every packet.
528 *
529 * \param tv threadvars
530 * \param dtv decode thread vars (for flow output api thread data)
531 * \param p packet to handle flow for
532 */
534{
535 /* Get this packet's flow from the hash. FlowHandlePacket() will setup
536 * a new flow if necessary. If we get NULL, we're out of flow memory.
537 * The returned flow is locked. */
538 Flow *f = FlowGetFlowFromHash(tv, fls, p, &p->flow);
539 if (f != NULL) {
540 /* set the flow in the packet */
541 p->flags |= PKT_HAS_FLOW;
542 }
543}
544
545/** \brief initialize the configuration
546 * \warning Not thread safe */
547void FlowInitConfig(bool quiet)
548{
549 SCLogDebug("initializing flow engine...");
550
551 memset(&flow_config, 0, sizeof(flow_config));
552 SC_ATOMIC_INIT(flow_flags);
553 SC_ATOMIC_INIT(flow_memuse);
554 SC_ATOMIC_INIT(flow_prune_idx);
557
558 /* set defaults */
559 flow_config.hash_rand = (uint32_t)RandomGet();
563
564 /* If we have specific config, overwrite the defaults with them,
565 * otherwise, leave the default values */
566 intmax_t val = 0;
567 if (SCConfGetInt("flow.emergency-recovery", &val) == 1) {
568 if (val <= 100 && val >= 1) {
569 flow_config.emergency_recovery = (uint8_t)val;
570 } else {
571 SCLogError("flow.emergency-recovery must be in the range of "
572 "1 and 100 (as percentage)");
574 }
575 } else {
576 SCLogDebug("flow.emergency-recovery, using default value");
578 }
579
580 /* Check if we have memcap and hash_size defined at config */
581 const char *conf_val;
582 uint32_t configval = 0;
583
584 /** set config values for memcap, prealloc and hash_size */
585 uint64_t flow_memcap_copy = 0;
586 if ((SCConfGet("flow.memcap", &conf_val)) == 1) {
587 if (conf_val == NULL) {
588 FatalError("Invalid value for flow.memcap: NULL");
589 }
590
591 if (ParseSizeStringU64(conf_val, &flow_memcap_copy) < 0) {
592 SCLogError("Error parsing flow.memcap "
593 "from conf file - %s. Killing engine",
594 conf_val);
595 exit(EXIT_FAILURE);
596 } else {
597 SC_ATOMIC_SET(flow_config.memcap, flow_memcap_copy);
598 }
599 }
600 if ((SCConfGet("flow.hash-size", &conf_val)) == 1) {
601 if (conf_val == NULL) {
602 FatalError("Invalid value for flow.hash-size: NULL");
603 }
604
605 if (StringParseUint32(&configval, 10, strlen(conf_val), conf_val) && configval != 0) {
606 flow_config.hash_size = configval;
607 } else {
608 FatalError("Invalid value for flow.hash-size. Must be a numeric value in the range "
609 "1-4294967295");
610 }
611 }
612 if ((SCConfGet("flow.prealloc", &conf_val)) == 1) {
613 if (conf_val == NULL) {
614 FatalError("Invalid value for flow.prealloc: NULL");
615 }
616
617 if (StringParseUint32(&configval, 10, strlen(conf_val),
618 conf_val) > 0) {
619 flow_config.prealloc = configval;
620 }
621 }
622
623 flow_config.memcap_policy = ExceptionPolicyParse("flow.memcap-policy", false);
624
625 SCLogDebug("Flow config from suricata.yaml: memcap: %"PRIu64", hash-size: "
626 "%"PRIu32", prealloc: %"PRIu32, SC_ATOMIC_GET(flow_config.memcap),
628
629 /* alloc hash memory */
630 uint64_t hash_size = flow_config.hash_size * sizeof(FlowBucket);
631 if (!(FLOW_CHECK_MEMCAP(hash_size))) {
632 SCLogError("allocating flow hash failed: "
633 "max flow memcap is smaller than projected hash size. "
634 "Memcap: %" PRIu64 ", Hash table size %" PRIu64 ". Calculate "
635 "total hash size by multiplying \"flow.hash-size\" with %" PRIuMAX ", "
636 "which is the hash bucket size.",
637 SC_ATOMIC_GET(flow_config.memcap), hash_size, (uintmax_t)sizeof(FlowBucket));
638 exit(EXIT_FAILURE);
639 }
640 flow_hash = SCMallocAligned(flow_config.hash_size * sizeof(FlowBucket), CLS);
641 if (unlikely(flow_hash == NULL)) {
642 FatalError("Fatal error encountered in FlowInitConfig. Exiting...");
643 }
644 memset(flow_hash, 0, flow_config.hash_size * sizeof(FlowBucket));
645
646 uint32_t i = 0;
647 for (i = 0; i < flow_config.hash_size; i++) {
649 SC_ATOMIC_INIT(flow_hash[i].next_ts);
650 }
651 (void) SC_ATOMIC_ADD(flow_memuse, (flow_config.hash_size * sizeof(FlowBucket)));
652
653 if (!quiet) {
654 SCLogConfig("allocated %"PRIu64" bytes of memory for the flow hash... "
655 "%" PRIu32 " buckets of size %" PRIuMAX "",
656 SC_ATOMIC_GET(flow_memuse), flow_config.hash_size,
657 (uintmax_t)sizeof(FlowBucket));
658 }
660 if (!quiet) {
661 SCLogConfig("flow memory usage: %"PRIu64" bytes, maximum: %"PRIu64,
662 SC_ATOMIC_GET(flow_memuse), SC_ATOMIC_GET(flow_config.memcap));
663 }
664
666
667 uint32_t sz = sizeof(Flow) + FlowStorageSize();
668 SCLogConfig("flow size %u, memcap allows for %" PRIu64 " flows. Per hash row in perfect "
669 "conditions %" PRIu64,
670 sz, flow_memcap_copy / sz, (flow_memcap_copy / sz) / flow_config.hash_size);
671}
672
673void FlowReset(void)
674{
675 // resets the flows (for reuse by fuzzing)
676 for (uint32_t u = 0; u < flow_config.hash_size; u++) {
677 Flow *f = flow_hash[u].head;
678 while (f) {
679 Flow *n = f->next;
680 uint8_t proto_map = FlowGetProtoMapping(f->proto);
681 FlowClearMemory(f, proto_map);
682 FlowFree(f);
683 f = n;
684 }
685 flow_hash[u].head = NULL;
686 }
687}
688
689/** \brief shutdown the flow engine
690 * \warning Not thread safe */
691void FlowShutdown(void)
692{
693 Flow *f;
694 while ((f = FlowDequeue(&flow_recycle_q))) {
695 FlowFree(f);
696 }
697
698 /* clear and free the hash */
699 if (flow_hash != NULL) {
700 /* clean up flow mutexes */
701 for (uint32_t u = 0; u < flow_config.hash_size; u++) {
702 f = flow_hash[u].head;
703 while (f) {
704 Flow *n = f->next;
705 uint8_t proto_map = FlowGetProtoMapping(f->proto);
706 FlowClearMemory(f, proto_map);
707 FlowFree(f);
708 f = n;
709 }
710 f = flow_hash[u].evicted;
711 while (f) {
712 Flow *n = f->next;
713 uint8_t proto_map = FlowGetProtoMapping(f->proto);
714 FlowClearMemory(f, proto_map);
715 FlowFree(f);
716 f = n;
717 }
718
720 }
722 flow_hash = NULL;
723 }
724 (void) SC_ATOMIC_SUB(flow_memuse, flow_config.hash_size * sizeof(FlowBucket));
727 DEBUG_VALIDATE_BUG_ON(SC_ATOMIC_GET(flow_memuse) != 0);
728}
729
730/**
731 * \brief Function to set the default timeout, free function and flow state
732 * function for all supported flow_proto.
733 */
734
736{
738
739#define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be) \
740 flow_timeouts_normal[(p)].new_timeout = (n); \
741 flow_timeouts_normal[(p)].est_timeout = (e); \
742 flow_timeouts_normal[(p)].closed_timeout = (c); \
743 flow_timeouts_normal[(p)].bypassed_timeout = (b); \
744 flow_timeouts_emerg[(p)].new_timeout = (ne); \
745 flow_timeouts_emerg[(p)].est_timeout = (ee); \
746 flow_timeouts_emerg[(p)].closed_timeout = (ce); \
747 flow_timeouts_emerg[(p)].bypassed_timeout = (be); \
748
769
774
775 /* Let's see if we have custom timeouts defined from config */
776 const char *new = NULL;
777 const char *established = NULL;
778 const char *closed = NULL;
779 const char *bypassed = NULL;
780 const char *emergency_new = NULL;
781 const char *emergency_established = NULL;
782 const char *emergency_closed = NULL;
783 const char *emergency_bypassed = NULL;
784
785 SCConfNode *flow_timeouts = SCConfGetNode("flow-timeouts");
786 if (flow_timeouts != NULL) {
787 SCConfNode *proto = NULL;
788 uint32_t configval = 0;
789
790 /* Defaults. */
791 proto = SCConfNodeLookupChild(flow_timeouts, "default");
792 if (proto != NULL) {
793 new = SCConfNodeLookupChildValue(proto, "new");
794 established = SCConfNodeLookupChildValue(proto, "established");
795 closed = SCConfNodeLookupChildValue(proto, "closed");
796 bypassed = SCConfNodeLookupChildValue(proto, "bypassed");
797 emergency_new = SCConfNodeLookupChildValue(proto, "emergency-new");
798 emergency_established = SCConfNodeLookupChildValue(proto, "emergency-established");
799 emergency_closed = SCConfNodeLookupChildValue(proto, "emergency-closed");
800 emergency_bypassed = SCConfNodeLookupChildValue(proto, "emergency-bypassed");
801
802 if (new != NULL &&
803 StringParseUint32(&configval, 10, strlen(new), new) > 0) {
804
806 }
807 if (established != NULL &&
808 StringParseUint32(&configval, 10, strlen(established),
809 established) > 0) {
810
812 }
813 if (closed != NULL &&
814 StringParseUint32(&configval, 10, strlen(closed),
815 closed) > 0) {
816
818 }
819 if (bypassed != NULL &&
820 StringParseUint32(&configval, 10,
821 strlen(bypassed),
822 bypassed) > 0) {
823
825 }
826 if (emergency_new != NULL &&
827 StringParseUint32(&configval, 10, strlen(emergency_new),
828 emergency_new) > 0) {
829
831 }
832 if (emergency_established != NULL &&
833 StringParseUint32(&configval, 10,
834 strlen(emergency_established),
835 emergency_established) > 0) {
836
838 }
839 if (emergency_closed != NULL &&
840 StringParseUint32(&configval, 10,
841 strlen(emergency_closed),
842 emergency_closed) > 0) {
843
845 }
846 if (emergency_bypassed != NULL &&
847 StringParseUint32(&configval, 10,
848 strlen(emergency_bypassed),
849 emergency_bypassed) > 0) {
850
852 }
853 }
854
855 /* TCP. */
856 proto = SCConfNodeLookupChild(flow_timeouts, "tcp");
857 if (proto != NULL) {
858 new = SCConfNodeLookupChildValue(proto, "new");
859 established = SCConfNodeLookupChildValue(proto, "established");
860 closed = SCConfNodeLookupChildValue(proto, "closed");
861 bypassed = SCConfNodeLookupChildValue(proto, "bypassed");
862 emergency_new = SCConfNodeLookupChildValue(proto, "emergency-new");
863 emergency_established = SCConfNodeLookupChildValue(proto, "emergency-established");
864 emergency_closed = SCConfNodeLookupChildValue(proto, "emergency-closed");
865 emergency_bypassed = SCConfNodeLookupChildValue(proto, "emergency-bypassed");
866
867 if (new != NULL &&
868 StringParseUint32(&configval, 10, strlen(new), new) > 0) {
869
871 }
872 if (established != NULL &&
873 StringParseUint32(&configval, 10, strlen(established),
874 established) > 0) {
875
877 }
878 if (closed != NULL &&
879 StringParseUint32(&configval, 10, strlen(closed),
880 closed) > 0) {
881
883 }
884 if (bypassed != NULL &&
885 StringParseUint32(&configval, 10,
886 strlen(bypassed),
887 bypassed) > 0) {
888
890 }
891 if (emergency_new != NULL &&
892 StringParseUint32(&configval, 10, strlen(emergency_new),
893 emergency_new) > 0) {
894
896 }
897 if (emergency_established != NULL &&
898 StringParseUint32(&configval, 10,
899 strlen(emergency_established),
900 emergency_established) > 0) {
901
903 }
904 if (emergency_closed != NULL &&
905 StringParseUint32(&configval, 10,
906 strlen(emergency_closed),
907 emergency_closed) > 0) {
908
910 }
911 if (emergency_bypassed != NULL &&
912 StringParseUint32(&configval, 10,
913 strlen(emergency_bypassed),
914 emergency_bypassed) > 0) {
915
917 }
918 }
919
920 /* UDP. */
921 proto = SCConfNodeLookupChild(flow_timeouts, "udp");
922 if (proto != NULL) {
923 new = SCConfNodeLookupChildValue(proto, "new");
924 established = SCConfNodeLookupChildValue(proto, "established");
925 bypassed = SCConfNodeLookupChildValue(proto, "bypassed");
926 emergency_new = SCConfNodeLookupChildValue(proto, "emergency-new");
927 emergency_established = SCConfNodeLookupChildValue(proto, "emergency-established");
928 emergency_bypassed = SCConfNodeLookupChildValue(proto, "emergency-bypassed");
929
930 if (new != NULL &&
931 StringParseUint32(&configval, 10, strlen(new), new) > 0) {
932
934 }
935 if (established != NULL &&
936 StringParseUint32(&configval, 10, strlen(established),
937 established) > 0) {
938
940 }
941 if (bypassed != NULL &&
942 StringParseUint32(&configval, 10,
943 strlen(bypassed),
944 bypassed) > 0) {
945
947 }
948 if (emergency_new != NULL &&
949 StringParseUint32(&configval, 10, strlen(emergency_new),
950 emergency_new) > 0) {
951
953 }
954 if (emergency_established != NULL &&
955 StringParseUint32(&configval, 10,
956 strlen(emergency_established),
957 emergency_established) > 0) {
958
960 }
961 if (emergency_bypassed != NULL &&
962 StringParseUint32(&configval, 10,
963 strlen(emergency_bypassed),
964 emergency_bypassed) > 0) {
965
967 }
968 }
969
970 /* ICMP. */
971 proto = SCConfNodeLookupChild(flow_timeouts, "icmp");
972 if (proto != NULL) {
973 new = SCConfNodeLookupChildValue(proto, "new");
974 established = SCConfNodeLookupChildValue(proto, "established");
975 bypassed = SCConfNodeLookupChildValue(proto, "bypassed");
976 emergency_new = SCConfNodeLookupChildValue(proto, "emergency-new");
977 emergency_established = SCConfNodeLookupChildValue(proto, "emergency-established");
978 emergency_bypassed = SCConfNodeLookupChildValue(proto, "emergency-bypassed");
979
980 if (new != NULL &&
981 StringParseUint32(&configval, 10, strlen(new), new) > 0) {
982
984 }
985 if (established != NULL &&
986 StringParseUint32(&configval, 10, strlen(established),
987 established) > 0) {
988
990 }
991 if (bypassed != NULL &&
992 StringParseUint32(&configval, 10,
993 strlen(bypassed),
994 bypassed) > 0) {
995
997 }
998 if (emergency_new != NULL &&
999 StringParseUint32(&configval, 10, strlen(emergency_new),
1000 emergency_new) > 0) {
1001
1003 }
1004 if (emergency_established != NULL &&
1005 StringParseUint32(&configval, 10,
1006 strlen(emergency_established),
1007 emergency_established) > 0) {
1008
1010 }
1011 if (emergency_bypassed != NULL &&
1012 StringParseUint32(&configval, 10,
1013 strlen(emergency_bypassed),
1014 emergency_bypassed) > 0) {
1015
1017 }
1018 }
1019 }
1020
1021 /* validate and if needed update emergency timeout values */
1022 for (uint8_t i = 0; i < FLOW_PROTO_MAX; i++) {
1025
1026 if (e->est_timeout > n->est_timeout) {
1027 SCLogWarning("emergency timeout value %u for \'established\' "
1028 "must be below regular value %u",
1029 e->est_timeout, n->est_timeout);
1030 e->est_timeout = n->est_timeout / 10;
1031 }
1032
1033 if (e->new_timeout > n->new_timeout) {
1034 SCLogWarning("emergency timeout value %u for \'new\' must be "
1035 "below regular value %u",
1036 e->new_timeout, n->new_timeout);
1037 e->new_timeout = n->new_timeout / 10;
1038 }
1039
1040 if (e->closed_timeout > n->closed_timeout) {
1041 SCLogWarning("emergency timeout value %u for \'closed\' must "
1042 "be below regular value %u",
1044 e->closed_timeout = n->closed_timeout / 10;
1045 }
1046
1047 if (e->bypassed_timeout > n->bypassed_timeout) {
1048 SCLogWarning("emergency timeout value %u for \'bypassed\' "
1049 "must be below regular value %u",
1052 }
1053 }
1054
1055 for (uint8_t i = 0; i < FLOW_PROTO_MAX; i++) {
1059
1060 if (e->est_timeout > n->est_timeout) {
1061 SCLogWarning("emergency timeout value for \'established\' must be below normal value");
1062 e->est_timeout = n->est_timeout / 10;
1063 }
1064 d->est_timeout = n->est_timeout - e->est_timeout;
1065
1066 if (e->new_timeout > n->new_timeout) {
1067 SCLogWarning("emergency timeout value for \'new\' must be below normal value");
1068 e->new_timeout = n->new_timeout / 10;
1069 }
1070 d->new_timeout = n->new_timeout - e->new_timeout;
1071
1072 if (e->closed_timeout > n->closed_timeout) {
1073 SCLogWarning("emergency timeout value for \'closed\' must be below normal value");
1074 e->closed_timeout = n->closed_timeout / 10;
1075 }
1077
1078 if (e->bypassed_timeout > n->bypassed_timeout) {
1079 SCLogWarning("emergency timeout value for \'bypassed\' must be below normal value");
1081 }
1083
1084 SCLogDebug("deltas: new: -%u est: -%u closed: -%u bypassed: -%u",
1086 }
1087}
1088
1089/**
1090 * \brief Function clear the flow memory before queueing it to spare flow
1091 * queue.
1092 *
1093 * \param f pointer to the flow needed to be cleared.
1094 * \param proto_map mapped value of the protocol to FLOW_PROTO's.
1095 */
1096
1097int FlowClearMemory(Flow* f, uint8_t proto_map)
1098{
1099 SCEnter();
1100
1103 }
1104
1105 /* call the protocol specific free function if we have one */
1106 if (flow_freefuncs[proto_map].Freefunc != NULL) {
1107 flow_freefuncs[proto_map].Freefunc(f->protoctx);
1108 }
1109
1110 FlowFreeStorage(f);
1111
1112 FLOW_RECYCLE(f);
1113
1114 SCReturnInt(1);
1115}
1116
1117/**
1118 * \brief Function to set the function to get protocol specific flow state.
1119 *
1120 * \param proto protocol of which function is needed to be set.
1121 * \param Free Function pointer which will be called to free the protocol
1122 * specific memory.
1123 */
1124
1125int FlowSetProtoFreeFunc (uint8_t proto, void (*Free)(void *))
1126{
1127 uint8_t proto_map;
1128 proto_map = FlowGetProtoMapping(proto);
1129
1130 flow_freefuncs[proto_map].Freefunc = Free;
1131 return 1;
1132}
1133
1134/**
1135 * \brief get 'disruption' flags: GAP/DEPTH/PASS
1136 * \param f locked flow
1137 * \param flags existing flags to be amended
1138 * \retval flags original flags + disrupt flags (if any)
1139 * \TODO handle UDP
1140 */
1141uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
1142{
1143 if (f->proto != IPPROTO_TCP) {
1144 return flags;
1145 }
1146 if (f->protoctx == NULL) {
1147 return flags;
1148 }
1149
1150 uint8_t newflags = flags;
1151 TcpSession *ssn = f->protoctx;
1152 TcpStream *stream = flags & STREAM_TOSERVER ? &ssn->client : &ssn->server;
1153
1155 newflags |= STREAM_DEPTH;
1156 }
1157 /* todo: handle pass case (also for UDP!) */
1158
1159 return newflags;
1160}
1161
1162void FlowUpdateState(Flow *f, const enum FlowState s)
1163{
1164 if (s != f->flow_state) {
1165 /* set the state */
1166 // Explicit cast from the enum type to the compact version
1167 f->flow_state = (FlowStateType)s;
1168
1169 /* update timeout policy and value */
1170 const uint32_t timeout_policy = FlowGetTimeoutPolicy(f);
1171 if (timeout_policy != f->timeout_policy) {
1172 f->timeout_policy = timeout_policy;
1173 }
1174 }
1175#ifdef UNITTESTS
1176 if (f->fb != NULL) {
1177#endif
1178 /* and reset the flow bucket next_ts value so that the flow manager
1179 * has to revisit this row */
1180 SC_ATOMIC_SET(f->fb->next_ts, 0);
1181#ifdef UNITTESTS
1182 }
1183#endif
1184}
1185
1186/**
1187 * \brief Get flow last time as individual values.
1188 *
1189 * Instead of returning a pointer to the timeval copy the timeval
1190 * parts into output pointers to make it simpler to call from Rust
1191 * over FFI using only basic data types.
1192 */
1193void FlowGetLastTimeAsParts(Flow *flow, uint64_t *secs, uint64_t *usecs)
1194{
1195 *secs = (uint64_t)SCTIME_SECS(flow->lastts);
1196 *usecs = (uint64_t)SCTIME_USECS(flow->lastts);
1197}
1198
1199/**
1200 * \brief Get flow source port.
1201 *
1202 * A function to get the flow sport useful when the caller only has an
1203 * opaque pointer to the flow structure.
1204 */
1206{
1207 return flow->sp;
1208}
1209
1210/**
1211 * \brief Get flow destination port.
1212 *
1213 * A function to get the flow dport useful when the caller only has an
1214 * opaque pointer to the flow structure.
1215 */
1216
1218{
1219 return flow->dp;
1220}
1221/**
1222 * \brief Get flow flags.
1223 *
1224 * A function to get the flow flags useful when the caller only has an
1225 * opaque pointer to the flow structure.
1226 */
1227
1228uint32_t FlowGetFlags(Flow *flow)
1229{
1230 return flow->flags;
1231}
1232/************************************Unittests*******************************/
1233
1234#ifdef UNITTESTS
1235#include "threads.h"
1236
1237/**
1238 * \test Test the setting of the per protocol timeouts.
1239 *
1240 * \retval On success it returns 1 and on failure 0.
1241 */
1242
1243static int FlowTest01 (void)
1244{
1245 uint8_t proto_map;
1246
1248 proto_map = FlowGetProtoMapping(IPPROTO_TCP);
1253
1254 proto_map = FlowGetProtoMapping(IPPROTO_UDP);
1259
1260 proto_map = FlowGetProtoMapping(IPPROTO_ICMP);
1265
1266 proto_map = FlowGetProtoMapping(IPPROTO_DCCP);
1267 FAIL_IF(flow_timeouts_normal[proto_map].new_timeout != FLOW_DEFAULT_NEW_TIMEOUT);
1268 FAIL_IF(flow_timeouts_normal[proto_map].est_timeout != FLOW_DEFAULT_EST_TIMEOUT);
1271
1272 PASS;
1273}
1274
1275/*Test function for the unit test FlowTest02*/
1276
1277static void test(void *f) {}
1278
1279/**
1280 * \test Test the setting of the per protocol free function to free the
1281 * protocol specific memory.
1282 *
1283 * \retval On success it returns 1 and on failure 0.
1284 */
1285
1286static int FlowTest02 (void)
1287{
1289 FlowSetProtoFreeFunc(IPPROTO_TCP, test);
1290 FlowSetProtoFreeFunc(IPPROTO_UDP, test);
1291 FlowSetProtoFreeFunc(IPPROTO_ICMP, test);
1292
1293 FAIL_IF(flow_freefuncs[FLOW_PROTO_DEFAULT].Freefunc != test);
1294 FAIL_IF(flow_freefuncs[FLOW_PROTO_TCP].Freefunc != test);
1295 FAIL_IF(flow_freefuncs[FLOW_PROTO_UDP].Freefunc != test);
1296 FAIL_IF(flow_freefuncs[FLOW_PROTO_ICMP].Freefunc != test);
1297
1298 PASS;
1299}
1300
1301/**
1302 * \test Test flow allocations when it reach memcap
1303 *
1304 *
1305 * \retval On success it returns 1 and on failure 0.
1306 */
1307
1308static int FlowTest07 (void)
1309{
1310 int result = 0;
1312 FlowConfig backup;
1313 memcpy(&backup, &flow_config, sizeof(FlowConfig));
1314
1315 uint32_t ini = 0;
1316 uint32_t end = FlowSpareGetPoolSize();
1317 SC_ATOMIC_SET(flow_config.memcap, 10000);
1318 flow_config.prealloc = 100;
1319
1320 /* Let's get the flow spare pool empty */
1321 UTHBuildPacketOfFlows(ini, end, 0);
1322
1323 /* And now let's try to reach the memcap val */
1324 while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1325 ini = end + 1;
1326 end = end + 2;
1327 UTHBuildPacketOfFlows(ini, end, 0);
1328 }
1329
1330 /* should time out normal */
1332 ini = end + 1;
1333 end = end + 2;
1334 UTHBuildPacketOfFlows(ini, end, 0);
1335
1336 /* This means that the engine entered emerg mode: should happen as easy
1337 * with flow mgr activated */
1338 if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1339 result = 1;
1340
1341 FlowShutdown();
1342 memcpy(&flow_config, &backup, sizeof(FlowConfig));
1343
1344 return result;
1345}
1346
1347/**
1348 * \test Test flow allocations when it reach memcap
1349 *
1350 *
1351 * \retval On success it returns 1 and on failure 0.
1352 */
1353
1354static int FlowTest08 (void)
1355{
1356 int result = 0;
1357
1359 FlowConfig backup;
1360 memcpy(&backup, &flow_config, sizeof(FlowConfig));
1361
1362 uint32_t ini = 0;
1363 uint32_t end = FlowSpareGetPoolSize();
1364 SC_ATOMIC_SET(flow_config.memcap, 10000);
1365 flow_config.prealloc = 100;
1366
1367 /* Let's get the flow spare pool empty */
1368 UTHBuildPacketOfFlows(ini, end, 0);
1369
1370 /* And now let's try to reach the memcap val */
1371 while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1372 ini = end + 1;
1373 end = end + 2;
1374 UTHBuildPacketOfFlows(ini, end, 0);
1375 }
1376
1377 /* By default we use 30 for timing out new flows. This means
1378 * that the Emergency mode should be set */
1380 ini = end + 1;
1381 end = end + 2;
1382 UTHBuildPacketOfFlows(ini, end, 0);
1383
1384 /* This means that the engine released 5 flows by emergency timeout */
1385 if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1386 result = 1;
1387
1388 memcpy(&flow_config, &backup, sizeof(FlowConfig));
1389 FlowShutdown();
1390
1391 return result;
1392}
1393
1394/**
1395 * \test Test flow allocations when it reach memcap
1396 *
1397 *
1398 * \retval On success it returns 1 and on failure 0.
1399 */
1400
1401static int FlowTest09 (void)
1402{
1403 int result = 0;
1404
1406 FlowConfig backup;
1407 memcpy(&backup, &flow_config, sizeof(FlowConfig));
1408
1409 uint32_t ini = 0;
1410 uint32_t end = FlowSpareGetPoolSize();
1411 SC_ATOMIC_SET(flow_config.memcap, 10000);
1412 flow_config.prealloc = 100;
1413
1414 /* Let's get the flow spare pool empty */
1415 UTHBuildPacketOfFlows(ini, end, 0);
1416
1417 /* And now let's try to reach the memcap val */
1418 while (FLOW_CHECK_MEMCAP(sizeof(Flow))) {
1419 ini = end + 1;
1420 end = end + 2;
1421 UTHBuildPacketOfFlows(ini, end, 0);
1422 }
1423
1424 /* No timeout will work */
1426 ini = end + 1;
1427 end = end + 2;
1428 UTHBuildPacketOfFlows(ini, end, 0);
1429
1430 /* engine in emerg mode */
1431 if (SC_ATOMIC_GET(flow_flags) & FLOW_EMERGENCY)
1432 result = 1;
1433
1434 memcpy(&flow_config, &backup, sizeof(FlowConfig));
1435 FlowShutdown();
1436
1437 return result;
1438}
1439
1440#endif /* UNITTESTS */
1441
1442/**
1443 * \brief Function to register the Flow Unitests.
1444 */
1446{
1447#ifdef UNITTESTS
1448 UtRegisterTest("FlowTest01 -- Protocol Specific Timeouts", FlowTest01);
1449 UtRegisterTest("FlowTest02 -- Setting Protocol Specific Free Function",
1450 FlowTest02);
1451 UtRegisterTest("FlowTest07 -- Test flow Allocations when it reach memcap",
1452 FlowTest07);
1453 UtRegisterTest("FlowTest08 -- Test flow Allocations when it reach memcap",
1454 FlowTest08);
1455 UtRegisterTest("FlowTest09 -- Test flow Allocations when it reach memcap",
1456 FlowTest09);
1457
1459#endif /* UNITTESTS */
1460}
#define ACTION_DROP
struct Flow_ Flow
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
uint16_t AppProto
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Definition conf.c:796
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
Definition conf.c:181
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition conf.c:414
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
Definition conf.c:824
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
Definition conf.c:350
void StatsIncr(ThreadVars *tv, uint16_t id)
Increments the local counter.
Definition counters.c:166
uint8_t flags
Definition decode-gre.h:0
#define ICMPV4_IS_ERROR_MSG(type)
#define IPV4_GET_RAW_IPTTL(ip4h)
#define IPV6_GET_RAW_HLIM(ip6h)
Definition decode-ipv6.h:67
uint8_t proto
#define PKT_HAS_FLOW
Definition decode.h:1266
@ PKT_DROP_REASON_FLOW_DROP
Definition decode.h:386
#define PKT_PROTO_DETECT_TS_DONE
Definition decode.h:1299
#define PKT_PROTO_DETECT_TC_DONE
Definition decode.h:1300
#define CMP_ADDR(a1, a2)
Definition decode.h:222
#define GET_PKT_LEN(p)
Definition decode.h:208
#define IPPROTO_DCCP
Definition decode.h:1220
#define CMP_PORT(p1, p2)
Definition decode.h:227
#define IPPROTO_SCTP
Definition decode.h:1228
@ SIGNATURE_HOOK_PKT_FLOW_START
Definition detect.h:540
void BypassedFlowUpdate(Flow *f, Packet *p)
void SCFlowRunUpdateCallbacks(ThreadVars *tv, Flow *f, Packet *p)
FlowBucket * flow_hash
Definition flow-hash.c:59
Flow * FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow **dest)
Get Flow for packet.
Definition flow-hash.c:903
#define FBLOCK_INIT(fb)
Definition flow-hash.h:71
#define FBLOCK_DESTROY(fb)
Definition flow-hash.h:72
void FlowTimeoutsInit(void)
FlowQueue flow_recycle_q
#define FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT
#define FLOW_DEFAULT_BYPASSED_TIMEOUT
@ FLOW_PROTO_UDP
@ FLOW_PROTO_DEFAULT
@ FLOW_PROTO_TCP
@ FLOW_PROTO_ICMP
@ FLOW_PROTO_MAX
#define FLOW_BYPASSED_TIMEOUT
#define FLOW_DEFAULT_EST_TIMEOUT
#define FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_UDP_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_UDP_EMERG_EST_TIMEOUT
#define FLOW_DEFAULT_EMERG_EST_TIMEOUT
#define FLOW_EMERGENCY
#define FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_ICMP_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_ICMP_EST_TIMEOUT
#define FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_ICMP_EMERG_EST_TIMEOUT
#define FLOW_IPPROTO_ICMP_NEW_TIMEOUT
#define FLOW_DEFAULT_EMERG_NEW_TIMEOUT
#define FLOW_DEFAULT_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT
#define FLOW_IPPROTO_TCP_CLOSED_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_CLOSED_TIMEOUT
#define FLOW_IPPROTO_TCP_EST_TIMEOUT
#define FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT
#define FLOW_IPPROTO_UDP_EST_TIMEOUT
Flow * FlowDequeue(FlowQueue *q)
remove a flow from the queue
Definition flow-queue.c:191
FlowQueue * FlowQueueInit(FlowQueue *q)
Definition flow-queue.c:46
void FlowQueueDestroy(FlowQueue *q)
Destroy a flow queue.
Definition flow-queue.c:60
void FlowSparePoolDestroy(void)
uint32_t FlowSpareGetPoolSize(void)
void FlowSparePoolInit(void)
void * FlowGetStorageById(const Flow *f, FlowStorageId id)
void RegisterFlowStorageTests(void)
void FlowFreeStorage(Flow *f)
unsigned int FlowStorageSize(void)
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
Definition flow-util.c:99
void FlowFree(Flow *f)
cleanup & free the memory of a flow
Definition flow-util.c:84
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
Definition flow-util.h:134
#define FLOW_RECYCLE(f)
macro to recycle a flow before it goes into the spare queue for reuse.
Definition flow-util.h:80
void FlowHandlePacket(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
Entry point for packet flow handling.
Definition flow.c:533
int FlowSetProtoFreeFunc(uint8_t, void(*Free)(void *))
Function to set the function to get protocol specific flow state.
Definition flow.c:1125
#define FLOW_DEFAULT_MEMCAP
Definition flow.c:69
void FlowUpdateState(Flow *f, const enum FlowState s)
Definition flow.c:1162
enum ExceptionPolicy FlowGetMemcapExceptionPolicy(void)
Definition flow.c:134
void FlowInitConfig(bool quiet)
initialize the configuration
Definition flow.c:547
#define FLOW_DEFAULT_EMERGENCY_RECOVERY
Definition flow.c:64
void FlowRegisterTests(void)
Function to register the Flow Unitests.
Definition flow.c:1445
FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX]
Definition flow.c:90
void FlowSetHasAlertsFlag(Flow *f)
Set flag to indicate that flow has alerts.
Definition flow.c:153
void FlowGetLastTimeAsParts(Flow *flow, uint64_t *secs, uint64_t *usecs)
Get flow last time as individual values.
Definition flow.c:1193
#define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be)
int FlowSetMemcap(uint64_t size)
Update memcap value.
Definition flow.c:107
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
Definition flow.c:1097
uint64_t FlowGetMemuse(void)
Definition flow.c:128
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
Definition flow.c:279
uint16_t FlowGetSourcePort(Flow *flow)
Get flow source port.
Definition flow.c:1205
void FlowUnsetChangeProtoFlag(Flow *f)
Unset flag to indicate to change proto for the flow.
Definition flow.c:186
void FlowInitFlowProto(void)
Function to set the default timeout, free function and flow state function for all supported flow_pro...
Definition flow.c:735
int FlowHasAlerts(const Flow *f)
Check if flow has alerts.
Definition flow.c:164
#define FLOW_DEFAULT_HASHSIZE
Definition flow.c:67
void FlowShutdown(void)
shutdown the flow engine
Definition flow.c:691
FlowConfig flow_config
Definition flow.c:93
uint32_t FlowGetFlags(Flow *flow)
Get flow flags.
Definition flow.c:1228
uint64_t FlowGetMemcap(void)
Return memcap value.
Definition flow.c:122
FlowProtoTimeout flow_timeouts_normal[FLOW_PROTO_MAX]
Definition flow.c:88
FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX]
Definition flow.c:89
void FlowCleanupAppLayer(Flow *f)
Definition flow.c:139
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
Definition flow.c:1141
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
Definition flow.c:196
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
Definition flow.c:177
void FlowReset(void)
Definition flow.c:673
FlowProtoFreeFunc flow_freefuncs[FLOW_PROTO_MAX]
Definition flow.c:91
void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars *dtv)
Update Packet and Flow.
Definition flow.c:402
uint16_t FlowGetDestinationPort(Flow *flow)
Get flow destination port.
Definition flow.c:1217
#define FLOW_DEFAULT_PREALLOC
Definition flow.c:71
void FlowSwap(Flow *f)
swap the flow's direction
Definition flow.c:246
#define FLOW_TC_PM_ALPROTO_DETECT_DONE
Definition flow.h:92
#define FLOW_SGH_TOCLIENT
Definition flow.h:75
#define FLOW_NOPAYLOAD_INSPECTION
Definition flow.h:67
#define FLOW_TS_PP_ALPROTO_DETECT_DONE
Definition flow.h:88
FlowState
Definition flow.h:503
@ FLOW_STATE_LOCAL_BYPASSED
Definition flow.h:507
@ FLOW_STATE_ESTABLISHED
Definition flow.h:505
#define FLOW_PKT_TOSERVER
Definition flow.h:233
#define FLOWFILE_NO_SIZE_TC
Definition flow.h:150
unsigned short FlowStateType
Definition flow.h:330
#define FLOW_TS_PM_ALPROTO_DETECT_DONE
Definition flow.h:86
#define FLOW_HAS_ALERTS
Definition flow.h:83
#define FLOW_DIR_REVERSED
Definition flow.h:112
#define FLOW_QUIET
Definition flow.h:43
#define FLOW_ACTION_DROP
Definition flow.h:70
#define FLOW_IS_ELEPHANT
Definition flow.h:59
#define FLOWFILE_NO_STORE_TC
Definition flow.h:135
#define FLOW_SGH_TOSERVER
Definition flow.h:73
#define FLOW_HAS_EXPECTATION
Definition flow.h:114
#define FLOWFILE_NO_SIZE_TS
Definition flow.h:149
#define FLOW_TOCLIENT_DROP_LOGGED
Definition flow.h:80
#define FLOWFILE_NO_SHA1_TS
Definition flow.h:141
#define FLOWFILE_NO_STORE_TS
Definition flow.h:134
#define FLOW_PROTO_DETECT_TS_DONE
Definition flow.h:104
uint16_t FlowThreadId
Definition flow.h:333
#define FLOWFILE_NO_SHA256_TS
Definition flow.h:145
#define FLOWFILE_NO_SHA256_TC
Definition flow.h:146
#define FLOW_PKT_TOCLIENT_FIRST
Definition flow.h:237
#define FLOW_TO_DST_SEEN
Definition flow.h:53
#define FLOW_CHANGE_PROTO
Definition flow.h:108
#define FLOW_TOSERVER_DROP_LOGGED
Definition flow.h:78
#define FLOW_PKT_ESTABLISHED
Definition flow.h:235
#define FLOW_TC_PP_ALPROTO_DETECT_DONE
Definition flow.h:94
#define FLOW_PKT_TOSERVER_FIRST
Definition flow.h:236
#define FLOWFILE_NO_SHA1_TC
Definition flow.h:142
#define FLOWFILE_NO_MD5_TS
Definition flow.h:137
#define FLOW_PROTO_DETECT_TC_DONE
Definition flow.h:105
#define FLOW_TO_SRC_SEEN
Definition flow.h:51
#define TOCLIENT
Definition flow.h:46
#define TOSERVER
Definition flow.h:45
#define FLOWFILE_NO_MAGIC_TS
Definition flow.h:130
#define FLOW_TS_PE_ALPROTO_DETECT_DONE
Definition flow.h:90
#define FLOW_PKT_TOCLIENT
Definition flow.h:234
#define FLOWFILE_NO_MD5_TC
Definition flow.h:138
#define FLOWFILE_NO_MAGIC_TC
Definition flow.h:131
#define FLOW_TC_PE_ALPROTO_DETECT_DONE
Definition flow.h:96
DecodeThreadVars * dtv
ThreadVars * tv
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
void AppLayerExpectationClean(Flow *f)
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
Definition packet.c:33
@ TCP_ESTABLISHED
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
Structure to hold thread specific data for all decode modules.
Definition decode.h:963
uint16_t counter_flow_elephant
Definition decode.h:1040
uint16_t counter_max_mac_addrs_dst
Definition decode.h:973
uint16_t counter_max_mac_addrs_src
Definition decode.h:972
enum ExceptionPolicy memcap_policy
Definition flow.h:302
uint32_t hash_rand
Definition flow.h:293
uint32_t prealloc
Definition flow.h:295
uint32_t emergency_recovery
Definition flow.h:300
uint32_t hash_size
Definition flow.h:294
void(* Freefunc)(void *)
Definition flow.h:526
uint32_t bypassed_timeout
Definition flow.h:522
uint32_t est_timeout
Definition flow.h:520
uint32_t closed_timeout
Definition flow.h:521
uint32_t new_timeout
Definition flow.h:519
Flow data structure.
Definition flow.h:356
AppProto alproto_ts
Definition flow.h:451
const struct SigGroupHead_ * sgh_toclient
Definition flow.h:483
Port dp
Definition flow.h:372
uint8_t max_ttl_toclient
Definition flow.h:470
AppProto alproto_tc
Definition flow.h:452
uint8_t proto
Definition flow.h:378
uint32_t flags
Definition flow.h:421
uint8_t min_ttl_toserver
Definition flow.h:467
uint8_t max_ttl_toserver
Definition flow.h:468
uint16_t file_flags
Definition flow.h:423
void * alstate
Definition flow.h:479
FlowStateType flow_state
Definition flow.h:412
uint32_t probing_parser_toclient_alproto_masks
Definition flow.h:419
uint8_t min_ttl_toclient
Definition flow.h:469
uint32_t timeout_policy
Definition flow.h:405
uint64_t tosrcbytecnt
Definition flow.h:498
const struct SigGroupHead_ * sgh_toserver
Definition flow.h:486
void * protoctx
Definition flow.h:441
uint64_t todstbytecnt
Definition flow.h:497
AppLayerParserState * alparser
Definition flow.h:478
SCTime_t lastts
Definition flow.h:410
uint32_t todstpktcnt
Definition flow.h:495
uint32_t probing_parser_toserver_alproto_masks
Definition flow.h:418
struct FlowBucket_ * fb
Definition flow.h:491
FlowThreadId thread_id[2]
Definition flow.h:394
FlowAddress src
Definition flow.h:359
struct Flow_ * next
Definition flow.h:396
Port sp
Definition flow.h:361
uint32_t tosrcpktcnt
Definition flow.h:496
struct Packet_::@33::@40 icmp_s
uint8_t flowflags
Definition decode.h:532
uint64_t pcap_cnt
Definition decode.h:626
SCTime_t ts
Definition decode.h:555
Address src
Definition decode.h:505
Port sp
Definition decode.h:508
uint8_t type
Definition decode.h:511
struct Flow_ * flow
Definition decode.h:546
uint16_t pkt_hooks
Definition decode.h:541
uint32_t flags
Definition decode.h:544
uint8_t proto
Definition decode.h:523
Port dp
Definition decode.h:516
Per thread variable structure.
Definition threadvars.h:58
#define SWAP_VARS(type, a, b)
#define MIN(x, y)
#define MAX(x, y)
#define CLS
#define BIT_U16(n)
#define SWAP_FLAGS(flags, a, b)
int EngineModeIsIPS(void)
Definition suricata.c:242
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
#define SC_ATOMIC_DECLARE(type, name)
wrapper for declaring atomic variables.
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
Definition util-byte.c:313
#define SCEnter(...)
Definition util-debug.h:277
#define FatalError(...)
Definition util-debug.h:510
#define SCLogDebug(...)
Definition util-debug.h:275
#define SCReturnInt(x)
Definition util-debug.h:281
#define SCLogWarning(...)
Macro used to log WARNING messages.
Definition util-debug.h:255
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
#define SCLogConfig(...)
Definition util-debug.h:229
enum ExceptionPolicy ExceptionPolicyParse(const char *option, bool support_flow)
FlowStorageId FlowRateGetStorageID(void)
bool FlowRateIsExceeding(FlowRateStore *frs, int direction)
bool FlowRateStorageEnabled(void)
void FlowRateStoreUpdate(FlowRateStore *frs, SCTime_t p_ts, uint32_t pkt_len, int direction)
FlowStorageId MacSetGetFlowStorageID(void)
bool MacSetFlowStorageEnabled(void)
Definition util-macset.c:86
void MacSetAddWithCtr(MacSet *ms, const uint8_t *src_addr, const uint8_t *dst_addr, ThreadVars *tv, uint16_t ctr_src, uint16_t ctr_dst)
#define SCFreeAligned(p)
Definition util-mem.h:77
#define SCMallocAligned(size, align)
Definition util-mem.h:68
int ParseSizeStringU64(const char *size, uint64_t *res)
Definition util-misc.c:190
#define unlikely(expr)
long int RandomGet(void)
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
Definition util-time.c:180
#define SCTIME_CMP_GT(a, b)
Definition util-time.h:104
#define SCTIME_SECS(t)
Definition util-time.h:57
#define SCTIME_USECS(t)
Definition util-time.h:56
uint32_t UTHBuildPacketOfFlows(uint32_t start, uint32_t end, uint8_t dir)
#define DEBUG_VALIDATE_BUG_ON(exp)