summaryrefslogtreecommitdiffstats
path: root/src/flow.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/flow.h')
-rw-r--r--src/flow.h698
1 files changed, 698 insertions, 0 deletions
diff --git a/src/flow.h b/src/flow.h
new file mode 100644
index 0000000..0a730e0
--- /dev/null
+++ b/src/flow.h
@@ -0,0 +1,698 @@
+/* Copyright (C) 2007-2013 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ */
+
+#ifndef __FLOW_H__
+#define __FLOW_H__
+
+/* forward declaration for macset include */
+typedef struct FlowStorageId FlowStorageId;
+
+#include "decode.h"
+#include "util-time.h"
+#include "util-exception-policy.h"
+#include "util-var.h"
+#include "util-optimize.h"
+#include "app-layer-protos.h"
+
+/* Part of the flow structure, so we declare it here.
+ * The actual declaration is in app-layer-parser.c */
+typedef struct AppLayerParserState_ AppLayerParserState;
+
+#define FLOW_QUIET true
+
+#define TOSERVER 0
+#define TOCLIENT 1
+
+/* per flow flags */
+
+/** At least one packet from the source address was seen */
+#define FLOW_TO_SRC_SEEN BIT_U32(0)
+/** At least one packet from the destination address was seen */
+#define FLOW_TO_DST_SEEN BIT_U32(1)
+
+// vacancy
+
+/** Flow was inspected against IP-Only sigs in the toserver direction */
+#define FLOW_TOSERVER_IPONLY_SET BIT_U32(3)
+/** Flow was inspected against IP-Only sigs in the toclient direction */
+#define FLOW_TOCLIENT_IPONLY_SET BIT_U32(4)
+
+/** Packet belonging to this flow should not be inspected at all */
+#define FLOW_NOPACKET_INSPECTION BIT_U32(5)
+/** Packet payloads belonging to this flow should not be inspected */
+#define FLOW_NOPAYLOAD_INSPECTION BIT_U32(6)
+
+/** All packets in this flow should be dropped */
+#define FLOW_ACTION_DROP BIT_U32(7)
+
+/** Sgh for toserver direction set (even if it's NULL) */
+#define FLOW_SGH_TOSERVER BIT_U32(8)
+/** Sgh for toclient direction set (even if it's NULL) */
+#define FLOW_SGH_TOCLIENT BIT_U32(9)
+
+/** packet to server direction has been logged in drop file (only in IPS mode) */
+#define FLOW_TOSERVER_DROP_LOGGED BIT_U32(10)
+/** packet to client direction has been logged in drop file (only in IPS mode) */
+#define FLOW_TOCLIENT_DROP_LOGGED BIT_U32(11)
+
+/** flow has alerts */
+#define FLOW_HAS_ALERTS BIT_U32(12)
+
+/** Pattern matcher alproto detection done */
+#define FLOW_TS_PM_ALPROTO_DETECT_DONE BIT_U32(13)
+/** Probing parser alproto detection done */
+#define FLOW_TS_PP_ALPROTO_DETECT_DONE BIT_U32(14)
+/** Expectation alproto detection done */
+#define FLOW_TS_PE_ALPROTO_DETECT_DONE BIT_U32(15)
+/** Pattern matcher alproto detection done */
+#define FLOW_TC_PM_ALPROTO_DETECT_DONE BIT_U32(16)
+/** Probing parser alproto detection done */
+#define FLOW_TC_PP_ALPROTO_DETECT_DONE BIT_U32(17)
+/** Expectation alproto detection done */
+#define FLOW_TC_PE_ALPROTO_DETECT_DONE BIT_U32(18)
+#define FLOW_TIMEOUT_REASSEMBLY_DONE BIT_U32(19)
+
+/** flow is ipv4 */
+#define FLOW_IPV4 BIT_U32(20)
+/** flow is ipv6 */
+#define FLOW_IPV6 BIT_U32(21)
+
+#define FLOW_PROTO_DETECT_TS_DONE BIT_U32(22)
+#define FLOW_PROTO_DETECT_TC_DONE BIT_U32(23)
+
+/** Indicate that alproto detection for flow should be done again */
+#define FLOW_CHANGE_PROTO BIT_U32(24)
+
+#define FLOW_WRONG_THREAD BIT_U32(25)
+/** Protocol detection told us flow is picked up in wrong direction (midstream) */
+#define FLOW_DIR_REVERSED BIT_U32(26)
+/** Indicate that the flow did trigger an expectation creation */
+#define FLOW_HAS_EXPECTATION BIT_U32(27)
+
+/** All packets in this flow should be passed */
+#define FLOW_ACTION_PASS BIT_U32(28)
+
+#define FLOW_TS_APP_UPDATED BIT_U32(29)
+#define FLOW_TC_APP_UPDATED BIT_U32(30)
+
+/* File flags */
+
+#define FLOWFILE_INIT 0
+
+/** no magic on files in this flow */
+#define FLOWFILE_NO_MAGIC_TS BIT_U16(0)
+#define FLOWFILE_NO_MAGIC_TC BIT_U16(1)
+
+/** even if the flow has files, don't store 'm */
+#define FLOWFILE_NO_STORE_TS BIT_U16(2)
+#define FLOWFILE_NO_STORE_TC BIT_U16(3)
+/** no md5 on files in this flow */
+#define FLOWFILE_NO_MD5_TS BIT_U16(4)
+#define FLOWFILE_NO_MD5_TC BIT_U16(5)
+
+/** no sha1 on files in this flow */
+#define FLOWFILE_NO_SHA1_TS BIT_U16(6)
+#define FLOWFILE_NO_SHA1_TC BIT_U16(7)
+
+/** no sha256 on files in this flow */
+#define FLOWFILE_NO_SHA256_TS BIT_U16(8)
+#define FLOWFILE_NO_SHA256_TC BIT_U16(9)
+
+/** no size tracking of files in this flow */
+#define FLOWFILE_NO_SIZE_TS BIT_U16(10)
+#define FLOWFILE_NO_SIZE_TC BIT_U16(11)
+
+/** store all files in the flow */
+#define FLOWFILE_STORE BIT_U16(12)
+
+#define FLOWFILE_NONE_TS (FLOWFILE_NO_MAGIC_TS | \
+ FLOWFILE_NO_STORE_TS | \
+ FLOWFILE_NO_MD5_TS | \
+ FLOWFILE_NO_SHA1_TS | \
+ FLOWFILE_NO_SHA256_TS| \
+ FLOWFILE_NO_SIZE_TS)
+#define FLOWFILE_NONE_TC (FLOWFILE_NO_MAGIC_TC | \
+ FLOWFILE_NO_STORE_TC | \
+ FLOWFILE_NO_MD5_TC | \
+ FLOWFILE_NO_SHA1_TC | \
+ FLOWFILE_NO_SHA256_TC| \
+ FLOWFILE_NO_SIZE_TC)
+#define FLOWFILE_NONE (FLOWFILE_NONE_TS|FLOWFILE_NONE_TC)
+
+#define FLOW_IS_IPV4(f) \
+ (((f)->flags & FLOW_IPV4) == FLOW_IPV4)
+#define FLOW_IS_IPV6(f) \
+ (((f)->flags & FLOW_IPV6) == FLOW_IPV6)
+
+#define FLOW_GET_SP(f) \
+ ((f)->flags & FLOW_DIR_REVERSED) ? (f)->dp : (f)->sp;
+#define FLOW_GET_DP(f) \
+ ((f)->flags & FLOW_DIR_REVERSED) ? (f)->sp : (f)->dp;
+
+#define FLOW_COPY_IPV4_ADDR_TO_PACKET(fa, pa) do { \
+ (pa)->family = AF_INET; \
+ (pa)->addr_data32[0] = (fa)->addr_data32[0]; \
+ } while (0)
+
+#define FLOW_COPY_IPV6_ADDR_TO_PACKET(fa, pa) do { \
+ (pa)->family = AF_INET6; \
+ (pa)->addr_data32[0] = (fa)->addr_data32[0]; \
+ (pa)->addr_data32[1] = (fa)->addr_data32[1]; \
+ (pa)->addr_data32[2] = (fa)->addr_data32[2]; \
+ (pa)->addr_data32[3] = (fa)->addr_data32[3]; \
+ } while (0)
+
+/* Set the IPv4 addressesinto the Addrs of the Packet.
+ * Make sure p->ip4h is initialized and validated.
+ *
+ * We set the rest of the struct to 0 so we can
+ * prevent using memset. */
+#define FLOW_SET_IPV4_SRC_ADDR_FROM_PACKET(p, a) do { \
+ (a)->addr_data32[0] = (uint32_t)(p)->ip4h->s_ip_src.s_addr; \
+ (a)->addr_data32[1] = 0; \
+ (a)->addr_data32[2] = 0; \
+ (a)->addr_data32[3] = 0; \
+ } while (0)
+
+#define FLOW_SET_IPV4_DST_ADDR_FROM_PACKET(p, a) do { \
+ (a)->addr_data32[0] = (uint32_t)(p)->ip4h->s_ip_dst.s_addr; \
+ (a)->addr_data32[1] = 0; \
+ (a)->addr_data32[2] = 0; \
+ (a)->addr_data32[3] = 0; \
+ } while (0)
+
+/* Set the IPv6 addressesinto the Addrs of the Packet.
+ * Make sure p->ip6h is initialized and validated. */
+#define FLOW_SET_IPV6_SRC_ADDR_FROM_PACKET(p, a) do { \
+ (a)->addr_data32[0] = (p)->ip6h->s_ip6_src[0]; \
+ (a)->addr_data32[1] = (p)->ip6h->s_ip6_src[1]; \
+ (a)->addr_data32[2] = (p)->ip6h->s_ip6_src[2]; \
+ (a)->addr_data32[3] = (p)->ip6h->s_ip6_src[3]; \
+ } while (0)
+
+#define FLOW_SET_IPV6_DST_ADDR_FROM_PACKET(p, a) do { \
+ (a)->addr_data32[0] = (p)->ip6h->s_ip6_dst[0]; \
+ (a)->addr_data32[1] = (p)->ip6h->s_ip6_dst[1]; \
+ (a)->addr_data32[2] = (p)->ip6h->s_ip6_dst[2]; \
+ (a)->addr_data32[3] = (p)->ip6h->s_ip6_dst[3]; \
+ } while (0)
+
+/* pkt flow flags */
+#define FLOW_PKT_TOSERVER 0x01
+#define FLOW_PKT_TOCLIENT 0x02
+#define FLOW_PKT_ESTABLISHED 0x04
+#define FLOW_PKT_TOSERVER_IPONLY_SET 0x08
+#define FLOW_PKT_TOCLIENT_IPONLY_SET 0x10
+#define FLOW_PKT_TOSERVER_FIRST 0x20
+#define FLOW_PKT_TOCLIENT_FIRST 0x40
+/** last pseudo packet in the flow. Can be used to trigger final clean,
+ * logging, etc. */
+#define FLOW_PKT_LAST_PSEUDO 0x80
+
+#define FLOW_END_FLAG_STATE_NEW 0x01
+#define FLOW_END_FLAG_STATE_ESTABLISHED 0x02
+#define FLOW_END_FLAG_STATE_CLOSED 0x04
+#define FLOW_END_FLAG_EMERGENCY 0x08
+#define FLOW_END_FLAG_TIMEOUT 0x10
+#define FLOW_END_FLAG_FORCED 0x20
+#define FLOW_END_FLAG_SHUTDOWN 0x40
+#define FLOW_END_FLAG_STATE_BYPASSED 0x80
+
+/** Mutex or RWLocks for the flow. */
+//#define FLOWLOCK_RWLOCK
+#define FLOWLOCK_MUTEX
+
+#ifdef FLOWLOCK_RWLOCK
+ #ifdef FLOWLOCK_MUTEX
+ #error Cannot enable both FLOWLOCK_RWLOCK and FLOWLOCK_MUTEX
+ #endif
+#endif
+
+#ifdef FLOWLOCK_RWLOCK
+ #define FLOWLOCK_INIT(fb) SCRWLockInit(&(fb)->r, NULL)
+ #define FLOWLOCK_DESTROY(fb) SCRWLockDestroy(&(fb)->r)
+ #define FLOWLOCK_RDLOCK(fb) SCRWLockRDLock(&(fb)->r)
+ #define FLOWLOCK_WRLOCK(fb) SCRWLockWRLock(&(fb)->r)
+ #define FLOWLOCK_TRYRDLOCK(fb) SCRWLockTryRDLock(&(fb)->r)
+ #define FLOWLOCK_TRYWRLOCK(fb) SCRWLockTryWRLock(&(fb)->r)
+ #define FLOWLOCK_UNLOCK(fb) SCRWLockUnlock(&(fb)->r)
+#elif defined FLOWLOCK_MUTEX
+ #define FLOWLOCK_INIT(fb) SCMutexInit(&(fb)->m, NULL)
+ #define FLOWLOCK_DESTROY(fb) SCMutexDestroy(&(fb)->m)
+ #define FLOWLOCK_RDLOCK(fb) SCMutexLock(&(fb)->m)
+ #define FLOWLOCK_WRLOCK(fb) SCMutexLock(&(fb)->m)
+ #define FLOWLOCK_TRYRDLOCK(fb) SCMutexTrylock(&(fb)->m)
+ #define FLOWLOCK_TRYWRLOCK(fb) SCMutexTrylock(&(fb)->m)
+ #define FLOWLOCK_UNLOCK(fb) SCMutexUnlock(&(fb)->m)
+#else
+ #error Enable FLOWLOCK_RWLOCK or FLOWLOCK_MUTEX
+#endif
+
+#define FLOW_IS_PM_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags & FLOW_TS_PM_ALPROTO_DETECT_DONE) : ((f)->flags & FLOW_TC_PM_ALPROTO_DETECT_DONE))
+#define FLOW_IS_PP_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags & FLOW_TS_PP_ALPROTO_DETECT_DONE) : ((f)->flags & FLOW_TC_PP_ALPROTO_DETECT_DONE))
+#define FLOW_IS_PE_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags & FLOW_TS_PE_ALPROTO_DETECT_DONE) : ((f)->flags & FLOW_TC_PE_ALPROTO_DETECT_DONE))
+
+#define FLOW_SET_PM_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags |= FLOW_TS_PM_ALPROTO_DETECT_DONE) : ((f)->flags |= FLOW_TC_PM_ALPROTO_DETECT_DONE))
+#define FLOW_SET_PP_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags |= FLOW_TS_PP_ALPROTO_DETECT_DONE) : ((f)->flags |= FLOW_TC_PP_ALPROTO_DETECT_DONE))
+#define FLOW_SET_PE_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags |= FLOW_TS_PE_ALPROTO_DETECT_DONE) : ((f)->flags |= FLOW_TC_PE_ALPROTO_DETECT_DONE))
+
+#define FLOW_RESET_PM_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags &= ~FLOW_TS_PM_ALPROTO_DETECT_DONE) : ((f)->flags &= ~FLOW_TC_PM_ALPROTO_DETECT_DONE))
+#define FLOW_RESET_PP_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags &= ~FLOW_TS_PP_ALPROTO_DETECT_DONE) : ((f)->flags &= ~FLOW_TC_PP_ALPROTO_DETECT_DONE))
+#define FLOW_RESET_PE_DONE(f, dir) (((dir) & STREAM_TOSERVER) ? ((f)->flags &= ~FLOW_TS_PE_ALPROTO_DETECT_DONE) : ((f)->flags &= ~FLOW_TC_PE_ALPROTO_DETECT_DONE))
+
+/* global flow config */
+typedef struct FlowCnf_
+{
+ uint32_t hash_rand;
+ uint32_t hash_size;
+ uint32_t prealloc;
+
+ uint32_t timeout_new;
+ uint32_t timeout_est;
+
+ uint32_t emergency_recovery;
+
+ enum ExceptionPolicy memcap_policy;
+
+ SC_ATOMIC_DECLARE(uint64_t, memcap);
+} FlowConfig;
+
+/* Hash key for the flow hash */
+typedef struct FlowKey_
+{
+ Address src, dst;
+ Port sp, dp;
+ uint8_t proto;
+ uint8_t recursion_level;
+ uint16_t livedev_id;
+ uint16_t vlan_id[VLAN_MAX_LAYERS];
+} FlowKey;
+
+typedef struct FlowAddress_ {
+ union {
+ uint32_t address_un_data32[4]; /* type-specific field */
+ uint16_t address_un_data16[8]; /* type-specific field */
+ uint8_t address_un_data8[16]; /* type-specific field */
+ } address;
+} FlowAddress;
+
+#define addr_data32 address.address_un_data32
+#define addr_data16 address.address_un_data16
+#define addr_data8 address.address_un_data8
+
+typedef unsigned short FlowStateType;
+
+/** Local Thread ID */
+typedef uint16_t FlowThreadId;
+
+/**
+ * \brief Flow data structure.
+ *
+ * The flow is a global data structure that is created for new packets of a
+ * flow and then looked up for the following packets of a flow.
+ *
+ * Locking
+ *
+ * The flow is updated/used by multiple packets at the same time. This is why
+ * there is a flow-mutex. It's a mutex and not a spinlock because some
+ * operations on the flow can be quite expensive, thus spinning would be
+ * too expensive.
+ *
+ * The flow "header" (addresses, ports, proto, recursion level) are static
+ * after the initialization and remain read-only throughout the entire live
+ * of a flow. This is why we can access those without protection of the lock.
+ */
+
+typedef struct Flow_
+{
+ /* flow "header", used for hashing and flow lookup. Static after init,
+ * so safe to look at without lock */
+ FlowAddress src, dst;
+ union {
+ Port sp; /**< tcp/udp source port */
+ struct {
+ uint8_t type; /**< icmp type */
+ uint8_t code; /**< icmp code */
+ } icmp_s;
+
+ struct {
+ uint32_t spi; /**< esp spi */
+ } esp;
+ };
+ union {
+ Port dp; /**< tcp/udp destination port */
+ struct {
+ uint8_t type; /**< icmp type */
+ uint8_t code; /**< icmp code */
+ } icmp_d;
+ };
+ uint8_t proto;
+ uint8_t recursion_level;
+ uint16_t vlan_id[VLAN_MAX_LAYERS];
+
+ uint8_t vlan_idx;
+
+ /* track toserver/toclient flow timeout needs */
+ union {
+ struct {
+ uint8_t ffr_ts:4;
+ uint8_t ffr_tc:4;
+ };
+ uint8_t ffr;
+ };
+
+ /** timestamp in seconds of the moment this flow will timeout
+ * according to the timeout policy. Does *not* take emergency
+ * mode into account. */
+ uint32_t timeout_at;
+
+ /** Thread ID for the stream/detect portion of this flow */
+ FlowThreadId thread_id[2];
+
+ struct Flow_ *next; /* (hash) list next */
+ /** Incoming interface */
+ struct LiveDevice_ *livedev;
+
+ /** flow hash - the flow hash before hash table size mod. */
+ uint32_t flow_hash;
+
+ /** timeout policy value in seconds to add to the lastts.tv_sec
+ * when a packet has been received. */
+ uint32_t timeout_policy;
+
+ /* time stamp of last update (last packet). Set/updated under the
+ * flow and flow hash row locks, safe to read under either the
+ * flow lock or flow hash row lock. */
+ SCTime_t lastts;
+
+ FlowStateType flow_state;
+
+ /** flow tenant id, used to setup flow timeout and stream pseudo
+ * packets with the correct tenant id set */
+ uint32_t tenant_id;
+
+ uint32_t probing_parser_toserver_alproto_masks;
+ uint32_t probing_parser_toclient_alproto_masks;
+
+ uint32_t flags; /**< generic flags */
+
+ uint16_t file_flags; /**< file tracking/extraction flags */
+
+ /** destination port to be used in protocol detection. This is meant
+ * for use with STARTTLS and HTTP CONNECT detection */
+ uint16_t protodetect_dp; /**< 0 if not used */
+
+ /* Parent flow id for protocol like ftp */
+ int64_t parent_id;
+
+#ifdef FLOWLOCK_RWLOCK
+ SCRWLock r;
+#elif defined FLOWLOCK_MUTEX
+ SCMutex m;
+#else
+ #error Enable FLOWLOCK_RWLOCK or FLOWLOCK_MUTEX
+#endif
+
+ /** protocol specific data pointer, e.g. for TcpSession */
+ void *protoctx;
+
+ /** mapping to Flow's protocol specific protocols for timeouts
+ and state and free functions. */
+ uint8_t protomap;
+
+ uint8_t flow_end_flags;
+ /* coccinelle: Flow:flow_end_flags:FLOW_END_FLAG_ */
+
+ AppProto alproto; /**< \brief application level protocol */
+ AppProto alproto_ts;
+ AppProto alproto_tc;
+
+ /** original application level protocol. Used to indicate the previous
+ protocol when changing to another protocol , e.g. with STARTTLS. */
+ AppProto alproto_orig;
+ /** expected app protocol: used in protocol change/upgrade like in
+ * STARTTLS. */
+ AppProto alproto_expect;
+
+ /** detection engine ctx version used to inspect this flow. Set at initial
+ * inspection. If it doesn't match the currently in use de_ctx, the
+ * stored sgh ptrs are reset. */
+ uint32_t de_ctx_version;
+
+ /** ttl tracking */
+ uint8_t min_ttl_toserver;
+ uint8_t max_ttl_toserver;
+ uint8_t min_ttl_toclient;
+ uint8_t max_ttl_toclient;
+
+ /** application level storage ptrs.
+ *
+ */
+ AppLayerParserState *alparser; /**< parser internal state */
+ void *alstate; /**< application layer state */
+
+ /** toclient sgh for this flow. Only use when FLOW_SGH_TOCLIENT flow flag
+ * has been set. */
+ const struct SigGroupHead_ *sgh_toclient;
+ /** toserver sgh for this flow. Only use when FLOW_SGH_TOSERVER flow flag
+ * has been set. */
+ const struct SigGroupHead_ *sgh_toserver;
+
+ /* pointer to the var list */
+ GenericVar *flowvar;
+
+ struct FlowBucket_ *fb;
+
+ SCTime_t startts;
+
+ uint32_t todstpktcnt;
+ uint32_t tosrcpktcnt;
+ uint64_t todstbytecnt;
+ uint64_t tosrcbytecnt;
+} Flow;
+
+enum FlowState {
+ FLOW_STATE_NEW = 0,
+ FLOW_STATE_ESTABLISHED,
+ FLOW_STATE_CLOSED,
+ FLOW_STATE_LOCAL_BYPASSED,
+#ifdef CAPTURE_OFFLOAD
+ FLOW_STATE_CAPTURE_BYPASSED,
+#endif
+};
+#ifdef CAPTURE_OFFLOAD
+#define FLOW_STATE_SIZE 5
+#else
+#define FLOW_STATE_SIZE 4
+#endif
+
+typedef struct FlowProtoTimeout_ {
+ uint32_t new_timeout;
+ uint32_t est_timeout;
+ uint32_t closed_timeout;
+ uint32_t bypassed_timeout;
+} FlowProtoTimeout;
+
+typedef struct FlowProtoFreeFunc_ {
+ void (*Freefunc)(void *);
+} FlowProtoFreeFunc;
+
+typedef struct FlowBypassInfo_ {
+ bool (* BypassUpdate)(Flow *f, void *data, time_t tsec);
+ void (* BypassFree)(void *data);
+ void *bypass_data;
+ uint64_t tosrcpktcnt;
+ uint64_t tosrcbytecnt;
+ uint64_t todstpktcnt;
+ uint64_t todstbytecnt;
+} FlowBypassInfo;
+
+#include "flow-queue.h"
+
+typedef struct FlowLookupStruct_ // TODO name
+{
+ /** thread store of spare queues */
+ FlowQueuePrivate spare_queue;
+ DecodeThreadVars *dtv;
+ FlowQueuePrivate work_queue;
+ uint32_t emerg_spare_sync_stamp;
+} FlowLookupStruct;
+
+/** \brief prepare packet for a life with flow
+ * Set PKT_WANTS_FLOW flag to indicate workers should do a flow lookup
+ * and calc the hash value to be used in the lookup and autofp flow
+ * balancing. */
+void FlowSetupPacket(Packet *p);
+void FlowHandlePacket (ThreadVars *, FlowLookupStruct *, Packet *);
+void FlowInitConfig(bool);
+void FlowReset(void);
+void FlowShutdown(void);
+void FlowSetIPOnlyFlag(Flow *, int);
+void FlowSetHasAlertsFlag(Flow *);
+int FlowHasAlerts(const Flow *);
+bool FlowHasGaps(const Flow *, uint8_t way);
+void FlowSetChangeProtoFlag(Flow *);
+void FlowUnsetChangeProtoFlag(Flow *);
+int FlowChangeProto(Flow *);
+void FlowSwap(Flow *);
+
+void FlowRegisterTests(void);
+int FlowSetProtoFreeFunc(uint8_t, void (*Free)(void *));
+
+static inline void FlowSetNoPacketInspectionFlag(Flow *);
+static inline void FlowSetNoPayloadInspectionFlag(Flow *);
+
+int FlowGetPacketDirection(const Flow *, const Packet *);
+
+void FlowCleanupAppLayer(Flow *);
+
+void FlowUpdateState(Flow *f, enum FlowState s);
+
+int FlowSetMemcap(uint64_t size);
+uint64_t FlowGetMemcap(void);
+uint64_t FlowGetMemuse(void);
+
+FlowStorageId GetFlowBypassInfoID(void);
+void RegisterFlowBypassInfo(void);
+
+void FlowGetLastTimeAsParts(Flow *flow, uint64_t *secs, uint64_t *usecs);
+uint32_t FlowGetFlags(Flow *flow);
+uint16_t FlowGetSourcePort(Flow *flow);
+uint16_t FlowGetDestinationPort(Flow *flow);
+
+/** ----- Inline functions ----- */
+
+static inline AppProto FlowGetAppProtocol(const Flow *f)
+{
+ return f->alproto;
+}
+
+static inline void *FlowGetAppState(const Flow *f)
+{
+ return f->alstate;
+}
+
+/** \brief Set the No Packet Inspection Flag without locking the flow.
+ *
+ * \param f Flow to set the flag in
+ */
+static inline void FlowSetNoPacketInspectionFlag(Flow *f)
+{
+ SCEnter();
+
+ SCLogDebug("flow %p", f);
+ f->flags |= FLOW_NOPACKET_INSPECTION;
+
+ SCReturn;
+}
+
+/** \brief Set the No payload inspection Flag without locking the flow.
+ *
+ * \param f Flow to set the flag in
+ */
+static inline void FlowSetNoPayloadInspectionFlag(Flow *f)
+{
+ SCEnter();
+
+ SCLogDebug("flow %p", f);
+ f->flags |= FLOW_NOPAYLOAD_INSPECTION;
+
+ SCReturn;
+}
+
+/** \brief Reference the flow
+ * \note This should only be called once for a destination
+ * pointer */
+static inline void FlowReference(Flow **d, Flow *f)
+{
+ if (likely(f != NULL)) {
+#ifdef DEBUG_VALIDATION
+ BUG_ON(*d == f);
+#else
+ if (*d == f)
+ return;
+#endif
+ *d = f;
+ }
+}
+
+static inline void FlowDeReference(Flow **d)
+{
+ if (likely(*d != NULL)) {
+ *d = NULL;
+ }
+}
+
+/** \brief create a flow id that is as unique as possible
+ * \retval flow_id signed 64bit id
+ * \note signed because of the signedness of json_integer_t in
+ * the json output
+ */
+static inline int64_t FlowGetId(const Flow *f)
+{
+ int64_t id = (uint64_t)(SCTIME_SECS(f->startts) & 0x0000FFFF) << 48 |
+ (uint64_t)(SCTIME_USECS(f->startts) & 0x0000FFFF) << 32 | (int64_t)f->flow_hash;
+ /* reduce to 51 bits as JavaScript and even JSON often seem to
+ * max out there. */
+ id &= 0x7ffffffffffffLL;
+ return id;
+}
+
+static inline void FlowSetEndFlags(Flow *f)
+{
+ const int state = f->flow_state;
+ if (state == FLOW_STATE_NEW)
+ f->flow_end_flags |= FLOW_END_FLAG_STATE_NEW;
+ else if (state == FLOW_STATE_ESTABLISHED)
+ f->flow_end_flags |= FLOW_END_FLAG_STATE_ESTABLISHED;
+ else if (state == FLOW_STATE_CLOSED)
+ f->flow_end_flags |= FLOW_END_FLAG_STATE_CLOSED;
+ else if (state == FLOW_STATE_LOCAL_BYPASSED)
+ f->flow_end_flags |= FLOW_END_FLAG_STATE_BYPASSED;
+#ifdef CAPTURE_OFFLOAD
+ else if (state == FLOW_STATE_CAPTURE_BYPASSED)
+ f->flow_end_flags = FLOW_END_FLAG_STATE_BYPASSED;
+#endif
+}
+
+static inline bool FlowIsBypassed(const Flow *f)
+{
+ if (
+#ifdef CAPTURE_OFFLOAD
+ f->flow_state == FLOW_STATE_CAPTURE_BYPASSED ||
+#endif
+ f->flow_state == FLOW_STATE_LOCAL_BYPASSED) {
+ return true;
+ }
+ return false;
+}
+
+int FlowClearMemory(Flow *,uint8_t );
+
+AppProto FlowGetAppProtocol(const Flow *f);
+void *FlowGetAppState(const Flow *f);
+uint8_t FlowGetDisruptionFlags(const Flow *f, uint8_t flags);
+
+void FlowHandlePacketUpdate(Flow *f, Packet *p, ThreadVars *tv, DecodeThreadVars *dtv);
+
+#endif /* __FLOW_H__ */