suricata
stream-tcp-private.h
Go to the documentation of this file.
1 /* Copyright (C) 2007-2010 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  */
23 
24 #ifndef __STREAM_TCP_PRIVATE_H__
25 #define __STREAM_TCP_PRIVATE_H__
26 
27 #include "tree.h"
28 #include "decode.h"
29 #include "util-pool.h"
30 #include "util-pool-thread.h"
31 #include "util-streaming-buffer.h"
32 
33 #define STREAMTCP_QUEUE_FLAG_TS 0x01
34 #define STREAMTCP_QUEUE_FLAG_WS 0x02
35 #define STREAMTCP_QUEUE_FLAG_SACK 0x04
36 
37 /** currently only SYN/ACK */
38 typedef struct TcpStateQueue_ {
39  uint8_t flags;
40  uint8_t wscale;
41  uint16_t win;
42  uint32_t seq;
43  uint32_t ack;
44  uint32_t ts;
45  uint32_t pkt_ts;
48 
49 typedef struct StreamTcpSackRecord {
50  uint32_t le; /**< left edge, host order */
51  uint32_t re; /**< right edge, host order */
54 
56 
57 /* red-black tree prototype for SACK records */
59 RB_PROTOTYPE(TCPSACK, StreamTcpSackRecord, rb, TcpSackCompare);
60 
61 typedef struct TcpSegment {
63  uint16_t payload_len; /**< actual size of the payload */
64  uint32_t seq;
65  RB_ENTRY(TcpSegment) __attribute__((__packed__)) rb;
66  StreamingBufferSegment sbseg;
67 } __attribute__((__packed__)) TcpSegment;
68 
69 /** \brief compare function for the Segment tree
70  *
71  * Main sort point is the sequence number. When sequence numbers
72  * are equal compare payload_len as well. This way the tree is
73  * sorted by seq, and in case of duplicate seqs we are sorted
74  * small to large.
75  */
76 int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b);
77 
78 /* red-black tree prototype for TcpSegment */
79 RB_HEAD(TCPSEG, TcpSegment);
80 RB_PROTOTYPE(TCPSEG, TcpSegment, rb, TcpSegmentCompare);
81 
82 #define TCP_SEG_LEN(seg) (seg)->payload_len
83 #define TCP_SEG_OFFSET(seg) (seg)->sbseg.stream_offset
84 
85 #define SEG_SEQ_RIGHT_EDGE(seg) ((seg)->seq + TCP_SEG_LEN((seg)))
86 
87 /* get right edge of sequence space of seen segments.
88  * Only use if STREAM_HAS_SEEN_DATA is true. */
89 #define STREAM_SEQ_RIGHT_EDGE(stream) (stream)->segs_right_edge
90 #define STREAM_RIGHT_EDGE(stream) (STREAM_BASE_OFFSET((stream)) + (STREAM_SEQ_RIGHT_EDGE((stream)) - (stream)->base_seq))
91 /* return true if we have seen data segments. */
92 #define STREAM_HAS_SEEN_DATA(stream) (!RB_EMPTY(&(stream)->sb.sbb_tree) || (stream)->sb.stream_offset)
93 
94 typedef struct TcpStream_ {
95  uint16_t flags:12; /**< Flag specific to the stream e.g. Timestamp */
96  /* coccinelle: TcpStream:flags:STREAMTCP_STREAM_FLAG_ */
97  uint16_t wscale:4; /**< wscale setting in this direction, 4 bits as max val is 15 */
98  uint8_t os_policy; /**< target based OS policy used for reassembly and handling packets*/
99  uint8_t tcp_flags; /**< TCP flags seen */
100 
101  uint32_t isn; /**< initial sequence number */
102  uint32_t next_seq; /**< next expected sequence number */
103  uint32_t last_ack; /**< last ack'd sequence number in this stream */
104  uint32_t next_win; /**< next max seq within window */
105  uint32_t window; /**< current window setting, after wscale is applied */
106 
107  uint32_t last_ts; /**< Time stamp (TSVAL) of the last seen packet for this stream*/
108  uint32_t last_pkt_ts; /**< Time of last seen packet for this stream (needed for PAWS update)
109  This will be used to validate the last_ts, when connection has been idle for
110  longer time.(RFC 1323)*/
111  /* reassembly */
112  uint32_t base_seq; /**< seq where we are left with reassebly. Matches STREAM_BASE_OFFSET below. */
113 
114  uint32_t app_progress_rel; /**< app-layer progress relative to STREAM_BASE_OFFSET */
115  uint32_t raw_progress_rel; /**< raw reassembly progress relative to STREAM_BASE_OFFSET */
116  uint32_t log_progress_rel; /**< streaming logger progress relative to STREAM_BASE_OFFSET */
117 
118  uint32_t min_inspect_depth; /**< min inspect size set by the app layer, to make sure enough data
119  * remains available for inspection together with app layer buffers */
120 
122  struct TCPSEG seg_tree; /**< red black tree of TCP segments. Data is stored in TcpStream::sb */
123  uint32_t segs_right_edge;
124 
125  uint32_t sack_size; /**< combined size of the SACK ranges currently in our tree. Updated
126  * at INSERT/REMOVE time. */
127  struct TCPSACK sack_tree; /**< red back tree of TCP SACK records. */
128 } TcpStream;
129 
130 #define STREAM_BASE_OFFSET(stream) ((stream)->sb.stream_offset)
131 #define STREAM_APP_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->app_progress_rel)
132 #define STREAM_RAW_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->raw_progress_rel)
133 #define STREAM_LOG_PROGRESS(stream) (STREAM_BASE_OFFSET((stream)) + (stream)->log_progress_rel)
134 
135 /* from /usr/include/netinet/tcp.h */
136 enum
137 {
150 };
151 
152 /*
153  * Per SESSION flags
154  */
155 
156 /** Flag for mid stream session */
157 #define STREAMTCP_FLAG_MIDSTREAM 0x0001
158 /** Flag for mid stream established session */
159 #define STREAMTCP_FLAG_MIDSTREAM_ESTABLISHED 0x0002
160 /** Flag for mid session when syn/ack is received */
161 #define STREAMTCP_FLAG_MIDSTREAM_SYNACK 0x0004
162 /** Flag for TCP Timestamp option */
163 #define STREAMTCP_FLAG_TIMESTAMP 0x0008
164 /** Server supports wscale (even though it can be 0) */
165 #define STREAMTCP_FLAG_SERVER_WSCALE 0x0010
166 // vacancy
167 /** Flag to indicate that the session is handling asynchronous stream.*/
168 #define STREAMTCP_FLAG_ASYNC 0x0040
169 /** Flag to indicate we're dealing with 4WHS: SYN, SYN, SYN/ACK, ACK
170  * (http://www.breakingpointsystems.com/community/blog/tcp-portals-the-three-way-handshake-is-a-lie) */
171 #define STREAMTCP_FLAG_4WHS 0x0080
172 /** Flag to indicate that this session is possible trying to evade the detection
173  * (http://www.packetstan.com/2010/06/recently-ive-been-on-campaign-to-make.html) */
174 #define STREAMTCP_FLAG_DETECTION_EVASION_ATTEMPT 0x0100
175 /** Flag to indicate the client (SYN pkt) permits SACK */
176 #define STREAMTCP_FLAG_CLIENT_SACKOK 0x0200
177 /** Flag to indicate both sides of the session permit SACK (SYN + SYN/ACK) */
178 #define STREAMTCP_FLAG_SACKOK 0x0400
179 // vacancy
180 /** 3WHS confirmed by server -- if suri sees 3whs ACK but server doesn't (pkt
181  * is lost on the way to server), SYN/ACK is retransmitted. If server sends
182  * normal packet we assume 3whs to be completed. Only used for SYN/ACK resend
183  * event. */
184 #define STREAMTCP_FLAG_3WHS_CONFIRMED 0x1000
185 /** App Layer tracking/reassembly is disabled */
186 #define STREAMTCP_FLAG_APP_LAYER_DISABLED 0x2000
187 /** Stream can be bypass */
188 #define STREAMTCP_FLAG_BYPASS 0x4000
189 
190 /*
191  * Per STREAM flags
192  */
193 
194 /** stream is in a gap state */
195 #define STREAMTCP_STREAM_FLAG_GAP 0x0001
196 /** Flag to avoid stream reassembly/app layer inspection for the stream */
197 #define STREAMTCP_STREAM_FLAG_NOREASSEMBLY 0x0002
198 /** we received a keep alive */
199 #define STREAMTCP_STREAM_FLAG_KEEPALIVE 0x0004
200 /** Stream has reached it's reassembly depth, all further packets are ignored */
201 #define STREAMTCP_STREAM_FLAG_DEPTH_REACHED 0x0008
202 /** Trigger reassembly next time we need 'raw' */
203 #define STREAMTCP_STREAM_FLAG_TRIGGER_RAW 0x0010
204 /** Stream supports TIMESTAMP -- used to set ssn STREAMTCP_FLAG_TIMESTAMP
205  * flag. */
206 #define STREAMTCP_STREAM_FLAG_TIMESTAMP 0x0020
207 /** Flag to indicate the zero value of timestamp */
208 #define STREAMTCP_STREAM_FLAG_ZERO_TIMESTAMP 0x0040
209 /** App proto detection completed */
210 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED 0x0080
211 /** App proto detection skipped */
212 #define STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_SKIPPED 0x0100
213 /** Raw reassembly disabled for new segments */
214 #define STREAMTCP_STREAM_FLAG_NEW_RAW_DISABLED 0x0200
215 /** Raw reassembly disabled completely */
216 #define STREAMTCP_STREAM_FLAG_DISABLE_RAW 0x400
217 
218 #define STREAMTCP_STREAM_FLAG_RST_RECV 0x800
219 
220 /** NOTE: flags field is 12 bits */
221 
222 
223 
224 
225 #define PAWS_24DAYS 2073600 /**< 24 days in seconds */
226 
227 #define PKT_IS_IN_RIGHT_DIR(ssn, p) ((ssn)->flags & STREAMTCP_FLAG_MIDSTREAM_SYNACK ? \
228  PKT_IS_TOSERVER(p) ? (p)->flowflags &= ~FLOW_PKT_TOSERVER \
229  (p)->flowflags |= FLOW_PKT_TOCLIENT : (p)->flowflags &= ~FLOW_PKT_TOCLIENT \
230  (p)->flowflags |= FLOW_PKT_TOSERVER : 0)
231 
232 /* Macro's for comparing Sequence numbers
233  * Page 810 from TCP/IP Illustrated, Volume 2. */
234 #define SEQ_EQ(a,b) ((int32_t)((a) - (b)) == 0)
235 #define SEQ_LT(a,b) ((int32_t)((a) - (b)) < 0)
236 #define SEQ_LEQ(a,b) ((int32_t)((a) - (b)) <= 0)
237 #define SEQ_GT(a,b) ((int32_t)((a) - (b)) > 0)
238 #define SEQ_GEQ(a,b) ((int32_t)((a) - (b)) >= 0)
239 
240 #define STREAMTCP_SET_RA_BASE_SEQ(stream, seq) { \
241  do { \
242  (stream)->base_seq = (seq) + 1; \
243  } while(0); \
244 }
245 
246 #define StreamTcpSetEvent(p, e) { \
247  if ((p)->flags & PKT_STREAM_NO_EVENTS) { \
248  SCLogDebug("not setting event %"PRIu8" on pkt %p (%"PRIu64"), " \
249  "stream in known bad condition", (e), p, (p)->pcap_cnt); \
250  } else { \
251  SCLogDebug("setting event %"PRIu8" on pkt %p (%"PRIu64")", \
252  (e), p, (p)->pcap_cnt); \
253  ENGINE_SET_EVENT((p), (e)); \
254  } \
255 }
256 
257 typedef struct TcpSession_ {
259  uint8_t state:4; /**< tcp state from state enum */
260  uint8_t pstate:4; /**< previous state */
261  uint8_t queue_len; /**< length of queue list below */
263  /** track all the tcp flags we've seen */
265  /* coccinelle: TcpSession:flags:STREAMTCP_FLAG */
266  uint16_t flags;
267  uint32_t reassembly_depth; /**< reassembly depth for the stream */
268  TcpStream server;
269  TcpStream client;
270  TcpStateQueue *queue; /**< list of SYN/ACK candidates */
271 } TcpSession;
272 
273 #define StreamTcpSetStreamFlagAppProtoDetectionCompleted(stream) \
274  ((stream)->flags |= STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)
275 #define StreamTcpIsSetStreamFlagAppProtoDetectionCompleted(stream) \
276  ((stream)->flags & STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED)
277 #define StreamTcpResetStreamFlagAppProtoDetectionCompleted(stream) \
278  ((stream)->flags &= ~STREAMTCP_STREAM_FLAG_APPPROTO_DETECTION_COMPLETED);
279 #define StreamTcpDisableAppLayerReassembly(ssn) do { \
280  SCLogDebug("setting STREAMTCP_FLAG_APP_LAYER_DISABLED on ssn %p", ssn); \
281  ((ssn)->flags |= STREAMTCP_FLAG_APP_LAYER_DISABLED); \
282  } while (0);
283 
284 #endif /* __STREAM_TCP_PRIVATE_H__ */
StreamingBufferSegment sbseg
StreamingBuffer sb
RB_HEAD(TCPSACK, StreamTcpSackRecord)
RB_PROTOTYPE(TCPSACK, StreamTcpSackRecord, rb, TcpSackCompare)
uint32_t min_inspect_depth
uint32_t raw_progress_rel
uint32_t app_progress_rel
uint16_t payload_len
PoolThreadReserved res
uint32_t reassembly_depth
struct TcpStateQueue_ * next
int8_t data_first_seen_dir
uint32_t last_pkt_ts
struct TcpStream_ TcpStream
uint32_t log_progress_rel
PoolThreadReserved res
int TcpSackCompare(struct StreamTcpSackRecord *a, struct StreamTcpSackRecord *b)
uint32_t sack_size
uint32_t segs_right_edge
TcpStateQueue * queue
int TcpSegmentCompare(struct TcpSegment *a, struct TcpSegment *b)
compare function for the Segment tree
struct TcpStateQueue_ TcpStateQueue
uint16_t PoolThreadReserved
struct TcpSession_ TcpSession
RB_ENTRY(TcpSegment) __attribute__((__packed__)) rb
uint8_t tcp_packet_flags
struct TcpSegment __attribute__((__packed__)) TcpSegment
DNP3 link header.