diff options
Diffstat (limited to 'src/flow.h')
-rw-r--r-- | src/flow.h | 698 |
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__ */ |