diff options
Diffstat (limited to 'src/stream-tcp-private.h')
-rw-r--r-- | src/stream-tcp-private.h | 326 |
1 files changed, 326 insertions, 0 deletions
diff --git a/src/stream-tcp-private.h b/src/stream-tcp-private.h new file mode 100644 index 0000000..619398d --- /dev/null +++ b/src/stream-tcp-private.h @@ -0,0 +1,326 @@ +/* Copyright (C) 2007-2010 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 __STREAM_TCP_PRIVATE_H__ +#define __STREAM_TCP_PRIVATE_H__ + +#include "util-pool-thread.h" +#include "util-streaming-buffer.h" + +#define STREAMTCP_QUEUE_FLAG_TS 0x01 +#define STREAMTCP_QUEUE_FLAG_WS 0x02 +#define STREAMTCP_QUEUE_FLAG_SACK 0x04 + +/** Tracking SYNs and SYN/ACKs */ +typedef struct TcpStateQueue_ { + uint8_t flags; + uint8_t wscale; + uint16_t win; + uint32_t seq; + uint32_t ack; + uint32_t ts; + uint32_t pkt_ts; + struct TcpStateQueue_ *next; +} TcpStateQueue; + +typedef struct StreamTcpSackRecord { + uint32_t le; /**< left edge, host order */ + uint32_t re; /**< right edge, host order */ + RB_ENTRY(StreamTcpSackRecord) rb; +} StreamTcpSackRecord; + +int TcpSackCompare(struct StreamTcpSackRecord *a, struct StreamTcpSackRecord *b); + +/* red-black tree prototype for SACK records */ +RB_HEAD(TCPSACK, StreamTcpSackRecord); +RB_PROTOTYPE(TCPSACK, StreamTcpSackRecord, rb, TcpSackCompare); + +#define TCPSEG_PKT_HDR_DEFAULT_SIZE 64 + +/* + * Struct to add the additional information required to use TcpSegments to dump + * a packet capture to file with the stream-pcap-log output option. This is only + * used if the session-dump option is enabled. + */ +typedef struct TcpSegmentPcapHdrStorage_ { + struct timeval ts; + uint32_t pktlen; + uint32_t alloclen; + uint8_t *pkt_hdr; +} TcpSegmentPcapHdrStorage; + +typedef struct TcpSegment { + PoolThreadId pool_id; + uint16_t payload_len; /**< actual size of the payload */ + uint32_t seq; + RB_ENTRY(TcpSegment) __attribute__((__packed__)) rb; + StreamingBufferSegment sbseg; + TcpSegmentPcapHdrStorage *pcap_hdr_storage; +} __attribute__((__packed__)) TcpSegment; + +/** \brief compare function for the Segment tree + * + * Main sort point is the sequence number. When sequence numbers + * are equal compare payload_len as well. This way the tree is + * sorted by seq, and in case of duplicate seqs we are sorted + * small to large. + */ +int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b); + +/* red-black tree prototype for TcpSegment */ +RB_HEAD(TCPSEG, TcpSegment); +RB_PROTOTYPE(TCPSEG, TcpSegment, rb, TcpSegmentCompare); + +#define TCP_SEG_LEN(seg) (seg)->payload_len +#define TCP_SEG_OFFSET(seg) (seg)->sbseg.stream_offset + +#define SEG_SEQ_RIGHT_EDGE(seg) ((seg)->seq + TCP_SEG_LEN((seg))) + +/* get right edge of sequence space of seen segments. + * Only use if STREAM_HAS_SEEN_DATA is true. */ +#define STREAM_SEQ_RIGHT_EDGE(stream) (stream)->segs_right_edge +#define STREAM_RIGHT_EDGE(stream) (STREAM_BASE_OFFSET((stream)) + (STREAM_SEQ_RIGHT_EDGE((stream)) - (stream)->base_seq)) +/* return true if we have seen data. */ +#define STREAM_HAS_SEEN_DATA(stream) StreamingBufferHasData(&(stream)->sb) + +typedef struct TcpStream_ { + uint16_t flags:12; /**< Flag specific to the stream e.g. Timestamp */ + /* coccinelle: TcpStream:flags:STREAMTCP_STREAM_FLAG_ */ + uint16_t wscale:4; /**< wscale setting in this direction, 4 bits as max val is 15 */ + uint8_t os_policy; /**< target based OS policy used for reassembly and handling packets*/ + uint8_t tcp_flags; /**< TCP flags seen */ + + uint32_t isn; /**< initial sequence number */ + uint32_t next_seq; /**< next expected sequence number */ + uint32_t last_ack; /**< last ack'd sequence number in this stream */ + uint32_t next_win; /**< next max seq within window */ + uint32_t window; /**< current window setting, after wscale is applied */ + + uint32_t last_ts; /**< Time stamp (TSVAL) of the last seen packet for this stream*/ + uint32_t last_pkt_ts; /**< Time of last seen packet for this stream (needed for PAWS update) + This will be used to validate the last_ts, when connection has been idle for + longer time.(RFC 1323)*/ + /* reassembly */ + uint32_t base_seq; /**< seq where we are left with reassembly. Matches STREAM_BASE_OFFSET below. + */ + + uint32_t app_progress_rel; /**< app-layer progress relative to STREAM_BASE_OFFSET */ + uint32_t raw_progress_rel; /**< raw reassembly progress relative to STREAM_BASE_OFFSET */ + uint32_t log_progress_rel; /**< streaming logger progress relative to STREAM_BASE_OFFSET */ + + uint32_t min_inspect_depth; /**< min inspect size set by the app layer, to make sure enough data + * remains available for inspection together with app layer buffers */ + uint32_t data_required; /**< data required from STREAM_APP_PROGRESS before calling app-layer again */ + + StreamingBuffer sb; + struct TCPSEG seg_tree; /**< red black tree of TCP segments. Data is stored in TcpStream::sb */ + uint32_t segs_right_edge; + + uint32_t sack_size; /**< combined size of the SACK ranges currently in our tree. Updated + * at INSERT/REMOVE time. */ + struct TCPSACK sack_tree; /**< red back tree of TCP SACK records. */ +} TcpStream; + +#define STREAM_BASE_OFFSET(stream) ((stream)->sb.region.stream_offset) +#define STREAM_APP_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->app_progress_rel) +#define STREAM_RAW_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->raw_progress_rel) +#define STREAM_LOG_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->log_progress_rel) + +/* from /usr/include/netinet/tcp.h */ +enum TcpState { + TCP_NONE = 0, + // TCP_LISTEN = 1, + TCP_SYN_SENT = 2, + TCP_SYN_RECV = 3, + TCP_ESTABLISHED = 4, + TCP_FIN_WAIT1 = 5, + TCP_FIN_WAIT2 = 6, + TCP_TIME_WAIT = 7, + TCP_LAST_ACK = 8, + TCP_CLOSE_WAIT = 9, + TCP_CLOSING = 10, + TCP_CLOSED = 11, +}; + +/* + * Per SESSION flags + */ + +/** Flag for mid stream session */ +#define STREAMTCP_FLAG_MIDSTREAM BIT_U32(0) +/** Flag for mid stream established session */ +#define STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED BIT_U32(1) +/** Flag for mid session when syn/ack is received */ +#define STREAMTCP_FLAG_MIDSTREAM_SYNACK BIT_U32(2) +/** Flag for TCP Timestamp option */ +#define STREAMTCP_FLAG_TIMESTAMP BIT_U32(3) +/** Server supports wscale (even though it can be 0) */ +#define STREAMTCP_FLAG_SERVER_WSCALE BIT_U32(4) +/** Closed by RST */ +#define STREAMTCP_FLAG_CLOSED_BY_RST BIT_U32(5) +/** Flag to indicate that the session is handling asynchronous stream.*/ +#define STREAMTCP_FLAG_ASYNC BIT_U32(6) +/** Flag to indicate we're dealing with 4WHS: SYN, SYN, SYN/ACK, ACK + * (http://www.breakingpointsystems.com/community/blog/tcp-portals-the-three-way-handshake-is-a-lie) */ +#define STREAMTCP_FLAG_4WHS BIT_U32(7) +/** Flag to indicate that this session is possible trying to evade the detection + * (http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html) */ +#define STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT BIT_U32(8) +/** Flag to indicate the client (SYN pkt) permits SACK */ +#define STREAMTCP_FLAG_CLIENT_SACKOK BIT_U32(9) +/** Flag to indicate both sides of the session permit SACK (SYN + SYN/ACK) */ +#define STREAMTCP_FLAG_SACKOK BIT_U32(10) +/** Session is in "lossy" state, be liberal */ +#define STREAMTCP_FLAG_LOSSY_BE_LIBERAL BIT_U32(11) +/** 3WHS confirmed by server -- if suri sees 3whs ACK but server doesn't (pkt + * is lost on the way to server), SYN/ACK is retransmitted. If server sends + * normal packet we assume 3whs to be completed. Only used for SYN/ACK resend + * event. */ +#define STREAMTCP_FLAG_3WHS_CONFIRMED BIT_U32(12) +/** App Layer tracking/reassembly is disabled */ +#define STREAMTCP_FLAG_APP_LAYER_DISABLED BIT_U32(13) +/** Stream can be bypass */ +#define STREAMTCP_FLAG_BYPASS BIT_U32(14) +/** SSN uses TCP Fast Open */ +#define STREAMTCP_FLAG_TCP_FAST_OPEN BIT_U32(15) +/** SYN/ACK ignored the data while ACKing the SYN */ +#define STREAMTCP_FLAG_TFO_DATA_IGNORED BIT_U32(16) +/* zero window probe */ +#define STREAMTCP_FLAG_ZWP_TS BIT_U32(17) +#define STREAMTCP_FLAG_ZWP_TC BIT_U32(18) + +/* + * Per STREAM flags + */ + +/** Flag to indicate that we have seen gap on the stream */ +#define STREAMTCP_STREAM_FLAG_HAS_GAP BIT_U16(0) +/** Flag to avoid stream reassembly/app layer inspection for the stream */ +#define STREAMTCP_STREAM_FLAG_NOREASSEMBLY BIT_U16(1) +/** we received a keep alive */ +#define STREAMTCP_STREAM_FLAG_KEEPALIVE BIT_U16(2) +/** Stream has reached it's reassembly depth, all further packets are ignored */ +#define STREAMTCP_STREAM_FLAG_DEPTH_REACHED BIT_U16(3) +/** Trigger reassembly next time we need 'raw' */ +#define STREAMTCP_STREAM_FLAG_TRIGGER_RAW BIT_U16(4) +/** Stream supports TIMESTAMP -- used to set ssn STREAMTCP_FLAG_TIMESTAMP + * flag. */ +#define STREAMTCP_STREAM_FLAG_TIMESTAMP BIT_U16(5) +/** Flag to indicate the zero value of timestamp */ +#define STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP BIT_U16(6) +/** App proto detection completed */ +#define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED BIT_U16(7) +/** App proto detection skipped */ +#define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED BIT_U16(8) +/** Raw reassembly disabled for new segments */ +#define STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED BIT_U16(9) +/** Raw reassembly disabled completely */ +#define STREAMTCP_STREAM_FLAG_DISABLE_RAW BIT_U16(10) + +#define STREAMTCP_STREAM_FLAG_RST_RECV BIT_U16(11) + +/** NOTE: flags field is 12 bits */ + + + + +#define PAWS_24DAYS 2073600 /**< 24 days in seconds */ + +#define PKT_IS_IN_RIGHT_DIR(ssn, p) ((ssn)->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK ? \ + PKT_IS_TOSERVER(p) ? (p)->flowflags &= ~FLOW_PKT_TOSERVER \ + (p)->flowflags |= FLOW_PKT_TOCLIENT : (p)->flowflags &= ~FLOW_PKT_TOCLIENT \ + (p)->flowflags |= FLOW_PKT_TOSERVER : 0) + +/* Macro's for comparing Sequence numbers + * Page 810 from TCP/IP Illustrated, Volume 2. */ +#define SEQ_EQ(a,b) ((int32_t)((a) - (b)) == 0) +#define SEQ_LT(a,b) ((int32_t)((a) - (b)) < 0) +#define SEQ_LEQ(a,b) ((int32_t)((a) - (b)) <= 0) +#define SEQ_GT(a,b) ((int32_t)((a) - (b)) > 0) +#define SEQ_GEQ(a,b) ((int32_t)((a) - (b)) >= 0) +#define SEQ_MIN(a, b) (SEQ_LT((a), (b)) ? (a) : (b)) +#define SEQ_MAX(a, b) (SEQ_GT((a), (b)) ? (a) : (b)) + +#define STREAMTCP_SET_RA_BASE_SEQ(stream, seq) { \ + do { \ + (stream)->base_seq = (seq) + 1; \ + } while(0); \ +} + +#define StreamTcpSetEvent(p, e) \ + { \ + if ((p)->flags & PKT_STREAM_NO_EVENTS) { \ + SCLogDebug("not setting event %d on pkt %p (%" PRIu64 "), " \ + "stream in known bad condition", \ + (e), p, (p)->pcap_cnt); \ + } else { \ + SCLogDebug("setting event %d on pkt %p (%" PRIu64 ")", (e), p, (p)->pcap_cnt); \ + ENGINE_SET_EVENT((p), (e)); \ + p->tcpvars.stream_pkt_flags |= STREAM_PKT_FLAG_EVENTSET; \ + } \ + } + +typedef struct TcpSession_ { + PoolThreadId pool_id; + uint8_t state:4; /**< tcp state from state enum */ + uint8_t pstate:4; /**< previous state */ + uint8_t queue_len; /**< length of queue list below */ + int8_t data_first_seen_dir; + /** track all the tcp flags we've seen */ + uint8_t tcp_packet_flags; + /* coccinelle: TcpSession:flags:STREAMTCP_FLAG */ + uint32_t flags; + uint32_t reassembly_depth; /**< reassembly depth for the stream */ + TcpStream server; + TcpStream client; + TcpStateQueue *queue; /**< list of SYN/ACK candidates */ +} TcpSession; + +#define StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream) \ + ((stream)->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) +#define StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream) \ + ((stream)->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED) +#define StreamTcpResetStreamFlagAppProtoDetectionCompleted(stream) \ + ((stream)->flags &= ~STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED); +#define StreamTcpDisableAppLayerReassembly(ssn) do { \ + SCLogDebug("setting STREAMTCP_FLAG_APP_LAYER_DISABLED on ssn %p", ssn); \ + ((ssn)->flags |= STREAMTCP_FLAG_APP_LAYER_DISABLED); \ + } while (0); + +#define STREAM_PKT_FLAG_RETRANSMISSION BIT_U16(0) +#define STREAM_PKT_FLAG_SPURIOUS_RETRANSMISSION BIT_U16(1) +#define STREAM_PKT_FLAG_STATE_UPDATE BIT_U16(2) +#define STREAM_PKT_FLAG_KEEPALIVE BIT_U16(3) +#define STREAM_PKT_FLAG_KEEPALIVEACK BIT_U16(4) +#define STREAM_PKT_FLAG_WINDOWUPDATE BIT_U16(5) +#define STREAM_PKT_FLAG_EVENTSET BIT_U16(6) +#define STREAM_PKT_FLAG_DUP_ACK BIT_U16(7) +#define STREAM_PKT_FLAG_DSACK BIT_U16(8) +#define STREAM_PKT_FLAG_ACK_UNSEEN_DATA BIT_U16(9) +#define STREAM_PKT_FLAG_TCP_PORT_REUSE BIT_U16(10) +#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE BIT_U16(11) +#define STREAM_PKT_FLAG_TCP_ZERO_WIN_PROBE_ACK BIT_U16(12) + +#define STREAM_PKT_FLAG_SET(p, f) (p)->tcpvars.stream_pkt_flags |= (f) + +#endif /* __STREAM_TCP_PRIVATE_H__ */ |