/* Copyright (C) 2007-2022 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 * \author Gurvinder Singh */ #ifndef __STREAM_TCP_H__ #define __STREAM_TCP_H__ #include "stream-tcp-private.h" #include "stream.h" #include "stream-tcp-reassemble.h" #include "suricata.h" #define STREAM_VERBOSE false /* Flag to indicate that the checksum validation for the stream engine has been enabled */ #define STREAMTCP_INIT_FLAG_CHECKSUM_VALIDATION BIT_U8(0) #define STREAMTCP_INIT_FLAG_DROP_INVALID BIT_U8(1) #define STREAMTCP_INIT_FLAG_BYPASS BIT_U8(2) #define STREAMTCP_INIT_FLAG_INLINE BIT_U8(3) /*global flow data*/ typedef struct TcpStreamCnf_ { /** stream tracking * * max stream mem usage */ SC_ATOMIC_DECLARE(uint64_t, memcap); SC_ATOMIC_DECLARE(uint64_t, reassembly_memcap); /**< max memory usage for stream reassembly */ uint16_t stream_init_flags; /**< new stream flags will be initialized to this */ /* coccinelle: TcpStreamCnf:flags:STREAMTCP_INIT_ */ uint8_t flags; uint8_t max_synack_queued; uint32_t prealloc_sessions; /**< ssns to prealloc per stream thread */ uint32_t prealloc_segments; /**< segments to prealloc per stream thread */ bool midstream; bool async_oneside; bool streaming_log_api; uint8_t max_syn_queued; uint32_t reassembly_depth; /**< Depth until when we reassemble the stream */ uint16_t reassembly_toserver_chunk_size; uint16_t reassembly_toclient_chunk_size; enum ExceptionPolicy ssn_memcap_policy; enum ExceptionPolicy reassembly_memcap_policy; enum ExceptionPolicy midstream_policy; /* default to "LINUX" timestamp behavior if true*/ bool liberal_timestamps; StreamingBufferConfig sbcnf; } TcpStreamCnf; typedef struct StreamTcpThread_ { int ssn_pool_id; uint16_t counter_tcp_active_sessions; uint16_t counter_tcp_sessions; /** sessions not picked up because memcap was reached */ uint16_t counter_tcp_ssn_memcap; uint16_t counter_tcp_ssn_from_cache; uint16_t counter_tcp_ssn_from_pool; /** pseudo packets processed */ uint16_t counter_tcp_pseudo; /** pseudo packets failed to setup */ uint16_t counter_tcp_pseudo_failed; /** packets rejected because their csum is invalid */ uint16_t counter_tcp_invalid_checksum; /** midstream pickups */ uint16_t counter_tcp_midstream_pickups; /** wrong thread */ uint16_t counter_tcp_wrong_thread; /** ack for unseen data */ uint16_t counter_tcp_ack_unseen_data; /** tcp reassembly thread data */ TcpReassemblyThreadCtx *ra_ctx; } StreamTcpThread; extern TcpStreamCnf stream_config; void StreamTcpInitConfig(bool); void StreamTcpFreeConfig(bool); void StreamTcpRegisterTests (void); void StreamTcpSessionPktFree (Packet *); void StreamTcpInitMemuse(void); void StreamTcpIncrMemuse(uint64_t); void StreamTcpDecrMemuse(uint64_t); int StreamTcpSetMemcap(uint64_t); uint64_t StreamTcpGetMemcap(void); int StreamTcpCheckMemcap(uint64_t); uint64_t StreamTcpMemuseCounter(void); uint64_t StreamTcpReassembleMemuseGlobalCounter(void); int StreamTcpSegmentForEach(const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data); int StreamTcpSegmentForSession( const Packet *p, uint8_t flag, StreamSegmentCallback CallbackFunc, void *data); void StreamTcpReassembleConfigEnableOverlapCheck(void); void TcpSessionSetReassemblyDepth(TcpSession *ssn, uint32_t size); typedef int (*StreamReassembleRawFunc)( void *data, const uint8_t *input, const uint32_t input_len, const uint64_t offset); int StreamReassembleForFrame(TcpSession *ssn, TcpStream *stream, StreamReassembleRawFunc Callback, void *cb_data, const uint64_t offset, const bool eof); int StreamReassembleLog(TcpSession *ssn, TcpStream *stream, StreamReassembleRawFunc Callback, void *cb_data, uint64_t progress_in, uint64_t *progress_out, bool eof); int StreamReassembleRaw(TcpSession *ssn, const Packet *p, StreamReassembleRawFunc Callback, void *cb_data, uint64_t *progress_out, bool respect_inspect_depth); void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, const uint64_t progress); void StreamTcpDetectLogFlush(ThreadVars *tv, StreamTcpThread *stt, Flow *f, Packet *p, PacketQueueNoLock *pq); const char *StreamTcpStateAsString(const enum TcpState); const char *StreamTcpSsnStateAsString(const TcpSession *ssn); /** ------- Inline functions: ------ */ /** * \brief If we are on IPS mode, and got a drop action triggered from * the IP only module, or from a reassembled msg and/or from an * applayer detection, then drop the rest of the packets of the * same stream and avoid inspecting it any further * \param p pointer to the Packet to check * \retval 1 if we must drop this stream * \retval 0 if the stream still legal */ static inline int StreamTcpCheckFlowDrops(Packet *p) { /* If we are on IPS mode, and got a drop action triggered from * the IP only module, or from a reassembled msg and/or from an * applayer detection, then drop the rest of the packets of the * same stream and avoid inspecting it any further */ if (EngineModeIsIPS() && (p->flow->flags & FLOW_ACTION_DROP)) return 1; return 0; } enum { /* stream has no segments for forced reassembly, nor for detection */ STREAM_HAS_UNPROCESSED_SEGMENTS_NONE = 0, /* stream has no segments for forced reassembly, but only segments that * have been sent for detection, but are stuck in the detection queues */ STREAM_HAS_UNPROCESSED_SEGMENTS_NEED_ONLY_DETECTION = 1, }; TmEcode StreamTcp (ThreadVars *, Packet *, void *, PacketQueueNoLock *); uint8_t StreamNeedsReassembly(const TcpSession *ssn, uint8_t direction); TmEcode StreamTcpThreadInit(ThreadVars *, void *, void **); TmEcode StreamTcpThreadDeinit(ThreadVars *tv, void *data); int StreamTcpPacket (ThreadVars *tv, Packet *p, StreamTcpThread *stt, PacketQueueNoLock *pq); /* clear ssn and return to pool */ void StreamTcpSessionClear(void *ssnptr); /* cleanup ssn, but don't free ssn */ void StreamTcpSessionCleanup(TcpSession *ssn); /* cleanup stream, but don't free the stream */ void StreamTcpStreamCleanup(TcpStream *stream); /* check if bypass is enabled */ int StreamTcpBypassEnabled(void); int StreamTcpInlineMode(void); int TcpSessionPacketSsnReuse(const Packet *p, const Flow *f, const void *tcp_ssn); void StreamTcpUpdateAppLayerProgress(TcpSession *ssn, char direction, const uint32_t progress); uint64_t StreamTcpGetAcked(const TcpStream *stream); uint64_t StreamTcpGetUsable(const TcpStream *stream, const bool eof); uint64_t StreamDataRightEdge(const TcpStream *stream, const bool eof); void StreamTcpThreadCacheEnable(void); void StreamTcpThreadCacheCleanup(void); #endif /* __STREAM_TCP_H__ */