suricata
stream-tcp-util.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2011 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  * Helper functions for the stream engine.
24  */
25 
26 #include "suricata-common.h"
27 
28 #include "stream-tcp-reassemble.h"
29 #include "stream-tcp-inline.h"
30 #include "stream-tcp.h"
31 #include "stream-tcp-util.h"
32 
33 #include "util-memcmp.h"
34 #include "util-print.h"
35 
36 #include "util-unittest.h"
37 #include "util-unittest-helper.h"
38 #include "ippair.h"
39 
40 #ifdef UNITTESTS
41 
42 /* unittest helper functions */
43 
45 {
48  *ra_ctx = StreamTcpReassembleInitThreadCtx(NULL);
49 }
50 
52 {
56 }
57 
60 }
61 
63 {
64  memset(ssn, 0x00, sizeof(TcpSession));
65 
67  ssn->client.sb = x;
68  ssn->server.sb = x;
69 }
70 
72 {
76  memset(ssn, 0x00, sizeof(TcpSession));
77 }
78 
79 void StreamTcpUTSetupStream(TcpStream *s, uint32_t isn)
80 {
81  memset(s, 0x00, sizeof(TcpStream));
82 
83  s->isn = isn;
85  s->base_seq = isn+1;
86 
88  s->sb = x;
89 }
90 
92 {
94 }
95 
96 /** \brief wrapper for StreamTcpReassembleHandleSegmentHandleData */
97 int StreamTcpUTAddPayload(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, uint32_t seq, uint8_t *payload, uint16_t len)
98 {
99  Packet *p = UTHBuildPacketReal(payload, len, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
100  if (p == NULL) {
101  return -1;
102  }
103  p->tcph->th_seq = htonl(seq);
104  p->tcph->th_ack = htonl(31);
105 
106  if (StreamTcpReassembleHandleSegmentHandleData(tv, ra_ctx, ssn, stream, p) < 0)
107  return -1;
108 
109  UTHFreePacket(p);
110  return 0;
111 }
112 
113 int StreamTcpUTAddSegmentWithPayload(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, uint32_t seq, uint8_t *payload, uint16_t len)
114 {
115  TcpSegment *s = StreamTcpGetSegment(tv, ra_ctx);
116  if (s == NULL) {
117  return -1;
118  }
119 
120  s->seq = seq;
121  TCP_SEG_LEN(s) = len;
122 
123  Packet *p = UTHBuildPacketReal(payload, len, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
124  if (p == NULL) {
125  return -1;
126  }
127  p->tcph->th_seq = htonl(seq);
128 
129  if (StreamTcpReassembleInsertSegment(tv, ra_ctx, stream, s, p, TCP_GET_SEQ(p), p->payload, p->payload_len) < 0)
130  return -1;
131 
132  UTHFreePacket(p);
133  return 0;
134 }
135 
136 int StreamTcpUTAddSegmentWithByte(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, uint32_t seq, uint8_t byte, uint16_t len)
137 {
138  TcpSegment *s = StreamTcpGetSegment(tv, ra_ctx);
139  if (s == NULL) {
140  return -1;
141  }
142 
143  s->seq = seq;
144  TCP_SEG_LEN(s) = len;
145  uint8_t buf[len];
146  memset(buf, byte, len);
147 
148  Packet *p = UTHBuildPacketReal(buf, len, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
149  if (p == NULL) {
150  return -1;
151  }
152  p->tcph->th_seq = htonl(seq);
153 
154  if (StreamTcpReassembleInsertSegment(tv, ra_ctx, stream, s, p, TCP_GET_SEQ(p), p->payload, p->payload_len) < 0)
155  return -1;
156  UTHFreePacket(p);
157  return 0;
158 }
159 
160 /* tests */
161 
162 static int StreamTcpUtilTest01(void)
163 {
164  int ret = 0;
165  TcpReassemblyThreadCtx *ra_ctx = NULL;
166 
167  StreamTcpUTInit(&ra_ctx);
168 
169  if (ra_ctx == NULL) {
170  printf("ra_ctx is NULL: ");
171  goto end;
172  }
173 
174  ret = 1;
175 end:
176  StreamTcpUTDeinit(ra_ctx);
177  return ret;
178 }
179 
180 
181 static int StreamTcpUtilStreamTest01(void)
182 {
183  TcpReassemblyThreadCtx *ra_ctx = NULL;
184  TcpStream stream;
185  ThreadVars tv;
186  memset(&tv, 0x00, sizeof(tv));
187 
188  StreamTcpUTInit(&ra_ctx);
189  StreamTcpUTSetupStream(&stream, 1);
190 
191  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 2, 'A', 5) == -1);
192  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 7, 'B', 5) == -1);
193  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 12, 'C', 5) == -1);
194 
195  TcpSegment *seg = RB_MIN(TCPSEG, &stream.seg_tree);
196  FAIL_IF_NULL(seg);
197  FAIL_IF(seg->seq != 2);
198 
199  seg = TCPSEG_RB_NEXT(seg);
200  FAIL_IF_NULL(seg);
201  FAIL_IF(seg->seq != 7);
202 
203  seg = TCPSEG_RB_NEXT(seg);
204  FAIL_IF_NULL(seg);
205  FAIL_IF(seg->seq != 12);
206 
207  StreamTcpUTClearStream(&stream);
208  StreamTcpUTDeinit(ra_ctx);
209  PASS;
210 }
211 
212 static int StreamTcpUtilStreamTest02(void)
213 {
214  TcpReassemblyThreadCtx *ra_ctx = NULL;
215  TcpStream stream;
216  ThreadVars tv;
217  memset(&tv, 0x00, sizeof(tv));
218 
219  StreamTcpUTInit(&ra_ctx);
220  StreamTcpUTSetupStream(&stream, 1);
221 
222  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 7, 'B', 5) == -1);
223  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 12, 'C', 5) == -1);
224  FAIL_IF(StreamTcpUTAddSegmentWithByte(&tv, ra_ctx, &stream, 2, 'A', 5) == -1);
225 
226  TcpSegment *seg = RB_MIN(TCPSEG, &stream.seg_tree);
227  FAIL_IF_NULL(seg);
228  FAIL_IF(seg->seq != 2);
229 
230  seg = TCPSEG_RB_NEXT(seg);
231  FAIL_IF_NULL(seg);
232  FAIL_IF(seg->seq != 7);
233 
234  seg = TCPSEG_RB_NEXT(seg);
235  FAIL_IF_NULL(seg);
236  FAIL_IF(seg->seq != 12);
237 
238  StreamTcpUTClearStream(&stream);
239  StreamTcpUTDeinit(ra_ctx);
240  PASS;
241 }
242 
243 #endif
244 
246 {
247 #ifdef UNITTESTS
248  UtRegisterTest("StreamTcpUtilTest01", StreamTcpUtilTest01);
249  UtRegisterTest("StreamTcpUtilStreamTest01", StreamTcpUtilStreamTest01);
250  UtRegisterTest("StreamTcpUtilStreamTest02", StreamTcpUtilStreamTest02);
251 #endif /* UNITTESTS */
252 }
253 
#define STREAMING_BUFFER_INITIALIZER(cfg)
TcpSegment * StreamTcpGetSegment(ThreadVars *tv, TcpReassemblyThreadCtx *)
get a segment from the pool
void StreamTcpSessionCleanup(TcpSession *ssn)
Session cleanup function. Does not free the ssn.
Definition: stream-tcp.c:215
void StreamTcpUTInit(TcpReassemblyThreadCtx **ra_ctx)
TcpStreamCnf stream_config
Definition: stream-tcp.h:106
StreamingBuffer sb
#define PASS
Pass the test.
#define FAIL_IF(expr)
Fail a test if expression evaluates to false.
Definition: util-unittest.h:71
void StreamTcpFreeConfig(char quiet)
Definition: stream-tcp.c:669
TCPHdr * tcph
Definition: decode.h:520
#define TRUE
#define STREAMTCP_SET_RA_BASE_SEQ(stream, seq)
void StreamTcpReassembleFreeThreadCtx(TcpReassemblyThreadCtx *ra_ctx)
void IPPairInitConfig(char quiet)
initialize the configuration
Definition: ippair.c:164
#define STREAMTCP_INIT_FLAG_INLINE
Definition: stream-tcp.h:39
void StreamTcpUTDeinit(TcpReassemblyThreadCtx *ra_ctx)
#define TCP_GET_SEQ(p)
Definition: decode-tcp.h:106
uint32_t seq
#define TCP_SEG_LEN(seg)
int StreamTcpReassembleInsertSegment(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, TcpSegment *seg, Packet *p, uint32_t pkt_seq, uint8_t *pkt_data, uint16_t pkt_datalen)
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
TcpReassemblyThreadCtx * StreamTcpReassembleInitThreadCtx(ThreadVars *tv)
void StreamTcpInitConfig(char)
To initialize the stream global configuration data.
Definition: stream-tcp.c:365
Packet * UTHBuildPacketReal(uint8_t *payload, uint16_t payload_len, uint8_t ipproto, const char *src, const char *dst, uint16_t sport, uint16_t dport)
UTHBuildPacketReal is a function that create tcp/udp packets for unittests specifying ip and port sou...
void StreamTcpUTInitInline(void)
#define RB_MIN(name, x)
Definition: tree.h:780
struct TCPSEG seg_tree
void StreamTcpUtilRegisterTests(void)
int StreamTcpReassembleHandleSegmentHandleData(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, Packet *p)
Insert a packets TCP data into the stream reassembly engine.
uint8_t flags
Definition: stream-tcp.h:53
void StreamTcpUTSetupStream(TcpStream *s, uint32_t isn)
void UTHFreePacket(Packet *p)
UTHFreePacket: function to release the allocated data from UTHBuildPacket and the packet itself...
#define FAIL_IF_NULL(expr)
Fail a test if expression evaluates to NULL.
Definition: util-unittest.h:89
StreamingBufferConfig sbcnf
Definition: stream-tcp.h:67
int StreamTcpUTAddSegmentWithPayload(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, uint32_t seq, uint8_t *payload, uint16_t len)
void StreamTcpUTSetupSession(TcpSession *ssn)
uint8_t len
Per thread variable structure.
Definition: threadvars.h:57
uint16_t payload_len
Definition: decode.h:541
int StreamTcpUTAddSegmentWithByte(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpStream *stream, uint32_t seq, uint8_t byte, uint16_t len)
void StreamTcpUTClearSession(TcpSession *ssn)
uint8_t * payload
Definition: decode.h:540
int StreamTcpUTAddPayload(ThreadVars *tv, TcpReassemblyThreadCtx *ra_ctx, TcpSession *ssn, TcpStream *stream, uint32_t seq, uint8_t *payload, uint16_t len)
wrapper for StreamTcpReassembleHandleSegmentHandleData
void StreamTcpUTClearStream(TcpStream *s)
void StreamTcpStreamCleanup(TcpStream *stream)
Definition: stream-tcp.c:202