Go to the documentation of this file.
62 #define FLOW_DEFAULT_EMERGENCY_RECOVERY 30
65 #define FLOW_DEFAULT_HASHSIZE 65536
67 #define FLOW_DEFAULT_MEMCAP (32 * 1024 * 1024)
69 #define FLOW_DEFAULT_PREALLOC 10000
139 if (
f == NULL ||
f->
proto == 0)
203 static inline void FlowSwapFlags(
Flow *
f)
216 static inline void FlowSwapFileFlags(
Flow *
f)
225 static inline void TcpStreamFlowSwap(
Flow *
f)
251 FlowSwapFileFlags(
f);
255 if (
f->
proto == IPPROTO_TCP) {
256 TcpStreamFlowSwap(
f);
302 }
else if (
p->
proto == IPPROTO_ICMP ||
p->
proto == IPPROTO_ICMPV6) {
322 static inline int FlowUpdateSeenFlag(
const Packet *
p)
324 if (PacketIsICMPv4(
p)) {
333 static inline void FlowUpdateTtlTS(
Flow *
f, uint8_t ttl)
343 static inline void FlowUpdateTtlTC(
Flow *
f, uint8_t ttl)
353 static inline void FlowUpdateFlowRate(
367 SCLogDebug(
"Flow rate for flow %p exceeds the configured values, marking it as an "
392 static inline void FlowUpdateEthernet(
396 const EthernetHdr *ethh = PacketGetEthernet(
p);
426 #ifdef CAPTURE_OFFLOAD
429 if (state != FLOW_STATE_CAPTURE_BYPASSED) {
435 #ifdef CAPTURE_OFFLOAD
441 SCLogDebug(
"Downgrading flow to local bypass");
460 if (FlowUpdateSeenFlag(
p)) {
471 FlowUpdateEthernet(
tv,
dtv,
f,
p,
true);
473 if (PacketIsIPv4(
p)) {
474 const IPV4Hdr *ip4h = PacketGetIPv4(
p);
476 }
else if (PacketIsIPv6(
p)) {
477 const IPV6Hdr *ip6h = PacketGetIPv6(
p);
486 if (FlowUpdateSeenFlag(
p)) {
497 FlowUpdateEthernet(
tv,
dtv,
f,
p,
false);
499 if (PacketIsIPv4(
p)) {
500 const IPV4Hdr *ip4h = PacketGetIPv4(
p);
502 }
else if (PacketIsIPv6(
p)) {
503 const IPV6Hdr *ip6h = PacketGetIPv6(
p);
515 }
else if (
f->
proto == IPPROTO_TCP) {
526 #ifdef CAPTURE_OFFLOAD
545 SCLogDebug(
"setting FLOW_NOPAYLOAD_INSPECTION flag on flow %p",
f);
546 DecodeSetNoPayloadInspectionFlag(
p);
594 if (
SCConfGetInt(
"flow.emergency-recovery", &val) == 1) {
595 if (val <= 100 && val >= 1) {
598 SCLogError(
"flow.emergency-recovery must be in the range of "
599 "1 and 100 (as percentage)");
603 SCLogDebug(
"flow.emergency-recovery, using default value");
608 const char *conf_val;
609 uint32_t configval = 0;
612 uint64_t flow_memcap_copy = 0;
613 if ((
SCConfGet(
"flow.memcap", &conf_val)) == 1) {
614 if (conf_val == NULL) {
615 FatalError(
"Invalid value for flow.memcap: NULL");
620 "from conf file - %s. Killing engine",
627 if ((
SCConfGet(
"flow.hash-size", &conf_val)) == 1) {
628 if (conf_val == NULL) {
629 FatalError(
"Invalid value for flow.hash-size: NULL");
632 if (
StringParseUint32(&configval, 10, strlen(conf_val), conf_val) && configval != 0) {
635 FatalError(
"Invalid value for flow.hash-size. Must be a numeric value in the range "
639 if ((
SCConfGet(
"flow.prealloc", &conf_val)) == 1) {
640 if (conf_val == NULL) {
641 FatalError(
"Invalid value for flow.prealloc: NULL");
652 SCLogDebug(
"Flow config from suricata.yaml: memcap: %"PRIu64
", hash-size: "
660 "max flow memcap is smaller than projected hash size. "
661 "Memcap: %" PRIu64
", Hash table size %" PRIu64
". Calculate "
662 "total hash size by multiplying \"flow.hash-size\" with %" PRIuMAX
", "
663 "which is the hash bucket size.",
669 FatalError(
"Fatal error encountered in FlowInitConfig. Exiting...");
681 SCLogConfig(
"allocated %"PRIu64
" bytes of memory for the flow hash... "
682 "%" PRIu32
" buckets of size %" PRIuMAX
"",
684 (uintmax_t)
sizeof(FlowBucket));
688 SCLogConfig(
"flow memory usage: %"PRIu64
" bytes, maximum: %"PRIu64,
695 SCLogConfig(
"flow size %u, memcap allows for %" PRIu64
" flows. Per hash row in perfect "
696 "conditions %" PRIu64,
766 #define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be) \
767 flow_timeouts_normal[(p)].new_timeout = (n); \
768 flow_timeouts_normal[(p)].est_timeout = (e); \
769 flow_timeouts_normal[(p)].closed_timeout = (c); \
770 flow_timeouts_normal[(p)].bypassed_timeout = (b); \
771 flow_timeouts_emerg[(p)].new_timeout = (ne); \
772 flow_timeouts_emerg[(p)].est_timeout = (ee); \
773 flow_timeouts_emerg[(p)].closed_timeout = (ce); \
774 flow_timeouts_emerg[(p)].bypassed_timeout = (be); \
803 const char *
new = NULL;
804 const char *established = NULL;
805 const char *closed = NULL;
806 const char *bypassed = NULL;
807 const char *emergency_new = NULL;
808 const char *emergency_established = NULL;
809 const char *emergency_closed = NULL;
810 const char *emergency_bypassed = NULL;
813 if (flow_timeouts != NULL) {
815 uint32_t configval = 0;
834 if (established != NULL &&
840 if (closed != NULL &&
846 if (bypassed != NULL &&
853 if (emergency_new != NULL &&
855 emergency_new) > 0) {
859 if (emergency_established != NULL &&
861 strlen(emergency_established),
862 emergency_established) > 0) {
866 if (emergency_closed != NULL &&
868 strlen(emergency_closed),
869 emergency_closed) > 0) {
873 if (emergency_bypassed != NULL &&
875 strlen(emergency_bypassed),
876 emergency_bypassed) > 0) {
899 if (established != NULL &&
905 if (closed != NULL &&
911 if (bypassed != NULL &&
918 if (emergency_new != NULL &&
920 emergency_new) > 0) {
924 if (emergency_established != NULL &&
926 strlen(emergency_established),
927 emergency_established) > 0) {
931 if (emergency_closed != NULL &&
933 strlen(emergency_closed),
934 emergency_closed) > 0) {
938 if (emergency_bypassed != NULL &&
940 strlen(emergency_bypassed),
941 emergency_bypassed) > 0) {
962 if (established != NULL &&
968 if (bypassed != NULL &&
975 if (emergency_new != NULL &&
977 emergency_new) > 0) {
981 if (emergency_established != NULL &&
983 strlen(emergency_established),
984 emergency_established) > 0) {
988 if (emergency_bypassed != NULL &&
990 strlen(emergency_bypassed),
991 emergency_bypassed) > 0) {
1012 if (established != NULL &&
1018 if (bypassed != NULL &&
1025 if (emergency_new != NULL &&
1027 emergency_new) > 0) {
1031 if (emergency_established != NULL &&
1033 strlen(emergency_established),
1034 emergency_established) > 0) {
1038 if (emergency_bypassed != NULL &&
1040 strlen(emergency_bypassed),
1041 emergency_bypassed) > 0) {
1054 SCLogWarning(
"emergency timeout value %u for \'established\' "
1055 "must be below regular value %u",
1061 SCLogWarning(
"emergency timeout value %u for \'new\' must be "
1062 "below regular value %u",
1068 SCLogWarning(
"emergency timeout value %u for \'closed\' must "
1069 "be below regular value %u",
1075 SCLogWarning(
"emergency timeout value %u for \'bypassed\' "
1076 "must be below regular value %u",
1088 SCLogWarning(
"emergency timeout value for \'established\' must be below normal value");
1094 SCLogWarning(
"emergency timeout value for \'new\' must be below normal value");
1100 SCLogWarning(
"emergency timeout value for \'closed\' must be below normal value");
1106 SCLogWarning(
"emergency timeout value for \'bypassed\' must be below normal value");
1111 SCLogDebug(
"deltas: new: -%u est: -%u closed: -%u bypassed: -%u",
1170 if (
f->
proto != IPPROTO_TCP) {
1177 uint8_t newflags =
flags;
1182 newflags |= STREAM_DEPTH;
1186 newflags |= STREAM_ASYNC;
1201 #ifdef CAPTURE_OFFLOAD
1202 || s == FLOW_STATE_CAPTURE_BYPASSED
1214 const uint32_t timeout_policy = FlowGetTimeoutPolicy(
f);
1220 if (
f->
fb != NULL) {
1342 static int FlowTest01 (
void)
1376 static void test(
void *
f) {}
1385 static int FlowTest02 (
void)
1407 static int FlowTest07 (
void)
1453 static int FlowTest08 (
void)
1500 static int FlowTest09 (
void)
1547 UtRegisterTest(
"FlowTest01 -- Protocol Specific Timeouts", FlowTest01);
1548 UtRegisterTest(
"FlowTest02 -- Setting Protocol Specific Free Function",
1550 UtRegisterTest(
"FlowTest07 -- Test flow Allocations when it reach memcap",
1552 UtRegisterTest(
"FlowTest08 -- Test flow Allocations when it reach memcap",
1554 UtRegisterTest(
"FlowTest09 -- Test flow Allocations when it reach memcap",
#define FLOWFILE_NO_MD5_TS
void FlowUnsetChangeProtoFlag(Flow *f)
Unset flag to indicate to change proto for the flow.
#define FLOWFILE_NO_MD5_TC
#define FBLOCK_DESTROY(fb)
#define FLOW_DEFAULT_NEW_TIMEOUT
void MacSetAddWithCtr(MacSet *ms, const uint8_t *src_addr, const uint8_t *dst_addr, ThreadVars *tv, StatsCounterMaxId ctr_src, StatsCounterMaxId ctr_dst)
#define FLOW_DEFAULT_EMERG_BYPASSED_TIMEOUT
#define FLOW_HAS_EXPECTATION
void FlowSetHasAlertsFlag(Flow *f)
Set flag to indicate that flow has alerts.
#define FLOW_ACTION_BY_FIREWALL
void FlowCleanupAppLayer(Flow *f)
void FlowSetChangeProtoFlag(Flow *f)
Set flag to indicate to change proto for the flow.
const uint8_t * SCFlowGetDestinationAddressAsRawPtr(const Flow *flow)
Returns a borrowed raw pointer to the flow destination address.
@ PKT_DROP_REASON_FW_FLOW_DROP
#define IPV6_GET_RAW_HLIM(ip6h)
uint32_t FlowSpareGetPoolSize(void)
int FlowGetPacketDirection(const Flow *f, const Packet *p)
determine the direction of the packet compared to the flow
#define SC_ATOMIC_INIT(name)
wrapper for initializing an atomic variable.
uint32_t SCFlowGetToClientPacketCount(const Flow *flow)
Get the number of packets seen toclient.
#define FLOW_DEFAULT_HASHSIZE
SC_ATOMIC_DECLARE(FlowProtoTimeoutPtr, flow_timeouts)
uint32_t emergency_recovery
#define FLOW_DEFAULT_PREALLOC
#define SC_ATOMIC_SET(name, val)
Set the value for the atomic variable.
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
void * SCFlowGetStorageById(const Flow *f, SCFlowStorageId id)
uint64_t PcapPacketCntGet(const Packet *p)
#define FLOW_IS_ELEPHANT_TOCLIENT
void FlowRegisterTests(void)
Function to register the Flow Unitests.
#define FLOW_IPPROTO_UDP_EMERG_NEW_TIMEOUT
#define FLOW_SGH_TOCLIENT
int ParseSizeStringU64(const char *size, uint64_t *res)
#define FLOWFILE_NO_MAGIC_TS
unsigned int SCFlowStorageSize(void)
#define SC_ATOMIC_ADD(name, val)
add a value to our atomic variable
int SCConfGet(const char *name, const char **vptr)
Retrieve the value of a configuration node.
#define FLOW_NOPAYLOAD_INSPECTION
#define FLOW_TS_PM_ALPROTO_DETECT_DONE
#define FLOW_DEFAULT_EMERG_NEW_TIMEOUT
#define FLOW_IPPROTO_TCP_EMERG_NEW_TIMEOUT
void BypassedFlowUpdate(Flow *f, Packet *p)
uint32_t bypassed_timeout
#define FLOW_DEFAULT_EST_TIMEOUT
SCFlowStorageId FlowRateGetStorageID(void)
#define FLOW_PKT_TOSERVER
uint64_t FlowGetMemuse(void)
uint64_t FlowGetMemcap(void)
Return memcap value.
void FlowQueueDestroy(FlowQueue *q)
Destroy a flow queue.
#define FLOW_APP_LAYER_FLUSH_PENDING
void FlowHandlePacket(ThreadVars *tv, FlowLookupStruct *fls, Packet *p)
Entry point for packet flow handling.
void SCFlowRunUpdateCallbacks(ThreadVars *tv, Flow *f, Packet *p)
#define FLOW_TOSERVER_DROP_LOGGED
const char * SCConfNodeLookupChildValue(const SCConfNode *node, const char *name)
Lookup the value of a child configuration node by name.
#define FLOW_TC_PE_ALPROTO_DETECT_DONE
#define FLOW_DEFAULT_BYPASSED_TIMEOUT
enum ExceptionPolicy ExceptionPolicyParse(const char *option, bool support_flow)
#define FLOW_IPPROTO_UDP_BYPASSED_TIMEOUT
#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED
#define FLOW_IPPROTO_TCP_EMERG_CLOSED_TIMEOUT
#define FLOW_IPPROTO_ICMP_EST_TIMEOUT
uint32_t UTHBuildPacketOfFlows(uint32_t start, uint32_t end, uint8_t dir)
void AppLayerExpectationClean(Flow *f)
#define PKT_PROTO_DETECT_TS_DONE
struct Packet_::@32::@39 icmp_s
const struct SigGroupHead_ * sgh_toserver
#define FLOW_CHECK_MEMCAP(size)
check if a memory alloc would fit in the memcap
#define FLOW_RECYCLE(f)
macro to recycle a flow before it goes into the spare queue for reuse.
AppLayerParserState * alparser
void FlowRateStoreUpdate(FlowRateStore *frs, SCTime_t p_ts, uint32_t pkt_len, int direction)
StatsCounterId counter_flow_elephant
#define FLOWFILE_NO_SHA1_TC
#define FLOW_IPPROTO_ICMP_EMERG_EST_TIMEOUT
void FlowInitConfig(bool quiet)
initialize the configuration
#define FLOW_IPPROTO_UDP_EST_TIMEOUT
@ FLOW_STATE_LOCAL_BYPASSED
#define PASS
Pass the test.
#define STREAMTCP_FLAG_ASYNC
#define FLOW_IPPROTO_TCP_CLOSED_TIMEOUT
void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars *dtv)
Update Packet and Flow.
int SCConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
#define FLOW_CHANGE_PROTO
Per thread variable structure.
#define FLOWFILE_NO_SHA256_TS
#define FLOW_PKT_TOCLIENT_FIRST
void StatsCounterIncr(StatsThreadContext *stats, StatsCounterId id)
Increments the local counter.
FlowQueue * FlowQueueInit(FlowQueue *q)
int StringParseUint32(uint32_t *res, int base, size_t len, const char *str)
#define SCLogWarning(...)
Macro used to log WARNING messages.
void AppLayerParserStateCleanup(const Flow *f, void *alstate, AppLayerParserState *pstate)
#define FLOW_PROTO_DETECT_TC_DONE
#define FLOW_TC_PP_ALPROTO_DETECT_DONE
const struct SigGroupHead_ * sgh_toclient
bool MacSetFlowStorageEnabled(void)
#define SC_ATOMIC_SUB(name, val)
sub a value from our atomic variable
void TimeSetIncrementTime(uint32_t tv_sec)
increment the time in the engine
uint8_t FlowGetProtoMapping(uint8_t proto)
Function to map the protocol to the defined FLOW_PROTO_* enumeration.
#define IPV4_GET_RAW_IPTTL(ip4h)
#define FLOW_DEFAULT_MEMCAP
void SCFlowFreeStorage(Flow *f)
#define FLOW_IPPROTO_TCP_NEW_TIMEOUT
int FlowClearMemory(Flow *f, uint8_t proto_map)
Function clear the flow memory before queueing it to spare flow queue.
FlowProtoTimeout flow_timeouts_delta[FLOW_PROTO_MAX]
void SCFlowGetLastTimeAsParts(const Flow *flow, uint64_t *secs, uint64_t *usecs)
Get flow last time as individual values.
uint32_t probing_parser_toclient_alproto_masks
#define FLOW_PKT_TOCLIENT
uint16_t SCFlowGetDestinationPort(const Flow *flow)
Get flow destination port.
@ PKT_DROP_REASON_EP_FLOW_DROP
void FlowUpdateState(Flow *f, const enum FlowState s)
StatsCounterMaxId counter_max_mac_addrs_dst
uint32_t probing_parser_toserver_alproto_masks
#define FLOWFILE_NO_SHA256_TC
StatsCounterMaxId counter_max_mac_addrs_src
SCConfNode * SCConfNodeLookupChild(const SCConfNode *node, const char *name)
Lookup a child configuration node by name.
Flow * FlowDequeue(FlowQueue *q)
remove a flow from the queue
#define FLOW_TS_PE_ALPROTO_DETECT_DONE
#define FLOW_IPPROTO_UDP_NEW_TIMEOUT
int FlowSetProtoFreeFunc(uint8_t, void(*Free)(void *))
Function to set the function to get protocol specific flow state.
#define FLOW_IPPROTO_ICMP_NEW_TIMEOUT
#define FAIL_IF(expr)
Fail a test if expression evaluates to true.
FlowProtoTimeout flow_timeouts_normal[FLOW_PROTO_MAX]
unsigned short FlowStateType
#define FLOWFILE_NO_MAGIC_TC
enum ExceptionPolicy FlowGetMemcapExceptionPolicy(void)
uint64_t SCFlowGetFlags(const Flow *flow)
Get flow flags.
void FlowFree(Flow *f)
cleanup & free the memory of a flow
#define FLOW_IPPROTO_TCP_BYPASSED_TIMEOUT
uint16_t SCFlowGetSourcePort(const Flow *flow)
Get flow source port.
void FlowShutdown(void)
shutdown the flow engine
void FlowSparePoolDestroy(void)
#define SCMallocAligned(size, align)
#define SWAP_VARS(type, a, b)
void FlowTimeoutsInit(void)
#define FLOW_PROTO_DETECT_TS_DONE
bool FlowRateIsExceeding(FlowRateStore *frs, int direction)
void SCRegisterFlowStorageTests(void)
#define FLOW_TS_PP_ALPROTO_DETECT_DONE
#define PKT_PROTO_DETECT_TC_DONE
Flow * FlowGetFlowFromHash(ThreadVars *tv, FlowLookupStruct *fls, Packet *p, Flow **dest)
Get Flow for packet.
uint32_t SCFlowGetToServerPacketCount(const Flow *flow)
Get the number of packets seen toserver.
#define FLOW_IPPROTO_TCP_EMERG_EST_TIMEOUT
void FlowSwap(Flow *f)
swap the flow's direction
enum ExceptionPolicy memcap_policy
void MacSetSwap(MacSet *ms)
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
void FlowInitFlowProto(void)
Function to set the default timeout, free function and flow state function for all supported flow_pro...
#define SCTIME_CMP_GT(a, b)
uint8_t address_un_data8[16]
#define FLOWFILE_NO_SHA1_TS
SCConfNode * SCConfGetNode(const char *name)
Get a SCConfNode by name.
#define SCLogError(...)
Macro used to log ERROR messages.
#define SWAP_FLAGS(flags, a, b)
#define FLOW_SGH_TOSERVER
Structure to hold thread specific data for all decode modules.
FlowProtoFreeFunc flow_freefuncs[FLOW_PROTO_MAX]
bool SCFlowIsIPv4(const Flow *flow)
Return true if the flow is IPv4.
FlowProtoTimeout flow_timeouts_emerg[FLOW_PROTO_MAX]
AppProto SCFlowGetAppProtocol(const Flow *f)
#define FLOW_IPPROTO_UDP_EMERG_EST_TIMEOUT
const uint8_t * SCFlowGetSourceAddressAsRawPtr(const Flow *flow)
Returns a borrowed raw pointer to the flow source address.
union FlowAddress_::@125 address
#define FLOW_IPPROTO_ICMP_EMERG_NEW_TIMEOUT
#define FLOW_TOCLIENT_DROP_LOGGED
#define FLOW_PKT_ESTABLISHED
bool FlowRateStorageEnabled(void)
void PacketDrop(Packet *p, const uint8_t action, enum PacketDropReason r)
issue drop action
int EngineModeIsIPS(void)
@ SIGNATURE_HOOK_PKT_FLOW_START
#define FLOW_TC_PM_ALPROTO_DETECT_DONE
#define FLOW_DEFAULT_EMERGENCY_RECOVERY
int FlowHasAlerts(const Flow *f)
Check if flow has alerts.
void FlowSparePoolInit(void)
#define FLOW_DEFAULT_EMERG_EST_TIMEOUT
#define FLOW_ACTION_BY_EXCEPTION_POLICY
#define FLOW_IPPROTO_ICMP_BYPASSED_TIMEOUT
uint8_t SCFlowGetIPProtocol(const Flow *flow)
Get flow IP protocol.
int FlowChangeProto(Flow *f)
Check if change proto flag is set for flow.
#define SC_ATOMIC_GET(name)
Get the value from the atomic variable.
StatsCounterId counter_flow_elephant_toclient
StatsCounterId counter_flow_elephant_toserver
uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags)
get 'disruption' flags: GAP/DEPTH/PASS
int8_t data_first_seen_dir
AppProto alproto
application level protocol
#define FLOW_DIR_REVERSED
#define ICMPV4_IS_ERROR_MSG(type)
#define FLOW_IPPROTO_TCP_EST_TIMEOUT
#define SET_DEFAULTS(p, n, e, c, b, ne, ee, ce, be)
#define FLOW_PKT_TOSERVER_FIRST
#define DEBUG_VALIDATE_BUG_ON(exp)
@ PKT_DROP_REASON_FLOW_DROP
#define FLOW_IS_ELEPHANT_TOSERVER
bool SCFlowIsIPv6(const Flow *flow)
Return true if the flow is IPv6.
FlowThreadId thread_id[2]
int FlowSetMemcap(uint64_t size)
Update memcap value.
SCFlowStorageId MacSetGetFlowStorageID(void)