suricata
stream-tcp-reassemble.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2021 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 #include "../suricata-common.h"
19 #include "../stream-tcp-private.h"
20 #include "../stream-tcp.h"
21 #include "../stream-tcp-reassemble.h"
22 #include "../stream-tcp-inline.h"
23 #include "../stream-tcp-list.h"
24 #include "../stream-tcp-util.h"
25 #include "../util-streaming-buffer.h"
26 #include "../util-print.h"
27 #include "../util-unittest.h"
28 
30  const uint8_t *expect_data;
31  const uint32_t expect_data_len;
32 };
33 
34 static int TestReassembleRawCallback(
35  void *cb_data, const uint8_t *data, const uint32_t data_len, const uint64_t offset)
36 {
37  struct TestReassembleRawCallbackData *cb = cb_data;
38 
39  SCLogNotice("have %u expect %u", data_len, cb->expect_data_len);
40 
41  if (data_len == cb->expect_data_len &&
42  memcmp(data, cb->expect_data, data_len) == 0) {
43  return 1;
44  } else {
45  SCLogNotice("data mismatch. Expected:");
46  PrintRawDataFp(stdout, cb->expect_data, cb->expect_data_len);
47  SCLogNotice("Got:");
48  PrintRawDataFp(stdout, data, data_len);
49  return -1;
50  }
51 }
52 
53 static int TestReassembleRawValidate(TcpSession *ssn, Packet *p,
54  const uint8_t *data, const uint32_t data_len)
55 {
56  struct TestReassembleRawCallbackData cb = { data, data_len };
57  uint64_t progress = 0;
58  int r = StreamReassembleRaw(ssn, p, TestReassembleRawCallback, &cb, &progress, false);
59  if (r == 1) {
60  StreamReassembleRawUpdateProgress(ssn, p, progress);
61  }
62  SCLogNotice("r %d", r);
63  return r;
64 }
65 
66 #define RAWREASSEMBLY_START(isn) \
67  TcpReassemblyThreadCtx *ra_ctx = NULL; \
68  TcpSession ssn; \
69  ThreadVars tv; \
70  memset(&tv, 0, sizeof(tv)); \
71  Packet *p = NULL; \
72  \
73  \
74  StreamTcpUTInit(&ra_ctx); \
75  StreamTcpUTInitInline(); \
76  stream_config.reassembly_toserver_chunk_size = 9; \
77  stream_config.reassembly_toclient_chunk_size = 9; \
78  StreamTcpUTSetupSession(&ssn); \
79  StreamTcpUTSetupStream(&ssn.server, (isn)); \
80  StreamTcpUTSetupStream(&ssn.client, (isn)); \
81  ssn.server.last_ack = (isn) + 1; \
82  ssn.client.last_ack = (isn) + 1; \
83  \
84  TcpStream *stream = &ssn.client;
85 
86 #define RAWREASSEMBLY_END \
87  StreamTcpUTClearSession(&ssn); \
88  StreamTcpUTDeinit(ra_ctx); \
89  PASS
90 
91 #define RAWREASSEMBLY_STEP(seq, seg, seglen, buf, buflen) \
92  p = PacketGetFromAlloc(); \
93  FAIL_IF_NULL(p); \
94  { \
95  SCLogNotice("SEQ %u block of %u", (seq), (seglen)); \
96  p->flowflags = FLOW_PKT_TOSERVER; \
97  TCPHdr tcphdr; \
98  memset(&tcphdr, 0, sizeof(tcphdr)); \
99  UTHSetTCPHdr(p, &tcphdr); \
100  tcphdr.th_seq = htonl((seq)); \
101  tcphdr.th_ack = htonl(10); \
102  p->payload_len = (seglen); \
103  \
104  FAIL_IF(StreamTcpUTAddPayload( \
105  &tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)) != 0); \
106  p->flags |= PKT_STREAM_ADD; \
107  FAIL_IF(!(TestReassembleRawValidate(&ssn, p, (uint8_t *)(buf), (buflen)))); \
108  } \
109  PacketFree(p);
110 
111 #define RAWREASSEMBLY_STEP_WITH_PROGRESS(seq, seg, seglen, buf, buflen, lastack, progress) \
112  stream->last_ack = (lastack); \
113  RAWREASSEMBLY_STEP((seq),(seg),(seglen),(buf),(buflen)); \
114  FAIL_IF(STREAM_RAW_PROGRESS(stream) != (progress));
115 
116 static int StreamTcpReassembleRawTest01 (void)
117 {
119  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
120  RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
121  RAWREASSEMBLY_STEP(8, "CCC", 3, "AAABBBCCC", 9);
123 }
124 
125 static int StreamTcpReassembleRawTest02 (void)
126 {
128  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
129  RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
130  RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
131  RAWREASSEMBLY_STEP(8, "CCC", 3, "BBBCCCDDD", 9);
133 }
134 
135 static int StreamTcpReassembleRawTest03 (void)
136 {
138  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
139  RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
140  RAWREASSEMBLY_STEP(8, "CCC", 3, "CCCDDD", 6);
142 }
143 
144 static int StreamTcpReassembleRawTest04 (void)
145 {
147  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
148  RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
149  RAWREASSEMBLY_STEP(7, "BBB", 3, "AAABBBCCC", 9);
151 }
152 
153 static int StreamTcpReassembleRawTest05 (void)
154 {
156  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
157  RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
158  RAWREASSEMBLY_STEP(2, "EEEEEEEEEEEEE", 13, "AAAAAEEECCCCC", 13);
160 }
161 
162 static int StreamTcpReassembleRawTest06 (void)
163 {
165  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
166  RAWREASSEMBLY_STEP(16,"CCCCC", 5, "CCCCC", 5);
167  RAWREASSEMBLY_STEP(7, "BBBBBBBBB", 9, "ABBBBBBBBBC", 11);
168  RAWREASSEMBLY_STEP(21,"DDDDDDDDDD",10,"CCCDDDDDDDDDD", 13);
170 }
171 
172 static int StreamTcpReassembleRawTest07 (void)
173 {
175  RAWREASSEMBLY_STEP(2, "AAAAAAA", 7, "AAAAAAA", 7);
176  RAWREASSEMBLY_STEP(9, "BBBBBBB", 7, "AAABBBBBBB", 10);
177  RAWREASSEMBLY_STEP(16,"C", 1, "ABBBBBBBC", 9);
178  RAWREASSEMBLY_STEP(17,"DDDDDDDD",8,"BBCDDDDDDDD", 11);
180 }
181 
182 static int StreamTcpReassembleRawTest08 (void)
183 {
185  RAWREASSEMBLY_STEP_WITH_PROGRESS(2, "AAA", 3, "AAA", 3, 3, 3);
186  RAWREASSEMBLY_STEP_WITH_PROGRESS(8, "CCC", 3, "CCC", 3, 3, 3);
187  // segment lost, last_ack updated
188  RAWREASSEMBLY_STEP_WITH_PROGRESS(11, "DDD", 3, "CCCDDD", 6, 8, 12);
190 }
191 
192 static void StreamTcpReassembleRawRegisterTests(void)
193 {
194  UtRegisterTest("StreamTcpReassembleRawTest01",
195  StreamTcpReassembleRawTest01);
196  UtRegisterTest("StreamTcpReassembleRawTest02",
197  StreamTcpReassembleRawTest02);
198  UtRegisterTest("StreamTcpReassembleRawTest03",
199  StreamTcpReassembleRawTest03);
200  UtRegisterTest("StreamTcpReassembleRawTest04",
201  StreamTcpReassembleRawTest04);
202  UtRegisterTest("StreamTcpReassembleRawTest05",
203  StreamTcpReassembleRawTest05);
204  UtRegisterTest("StreamTcpReassembleRawTest06",
205  StreamTcpReassembleRawTest06);
206  UtRegisterTest("StreamTcpReassembleRawTest07",
207  StreamTcpReassembleRawTest07);
208  UtRegisterTest("StreamTcpReassembleRawTest08",
209  StreamTcpReassembleRawTest08);
210 }
StreamReassembleRaw
int StreamReassembleRaw(TcpSession *ssn, const Packet *p, StreamReassembleRawFunc Callback, void *cb_data, uint64_t *progress_out, bool respect_inspect_depth)
Definition: stream-tcp-reassemble.c:1904
offset
uint64_t offset
Definition: util-streaming-buffer.h:0
UtRegisterTest
void UtRegisterTest(const char *name, int(*TestFn)(void))
Register unit test.
Definition: util-unittest.c:103
TestReassembleRawCallbackData::expect_data
const uint8_t * expect_data
Definition: stream-tcp-reassemble.c:30
RAWREASSEMBLY_STEP
#define RAWREASSEMBLY_STEP(seq, seg, seglen, buf, buflen)
Definition: stream-tcp-reassemble.c:91
TestReassembleRawCallbackData
Definition: stream-tcp-reassemble.c:29
PrintRawDataFp
void PrintRawDataFp(FILE *fp, const uint8_t *buf, uint32_t buflen)
Definition: util-print.c:111
Packet_
Definition: decode.h:476
RAWREASSEMBLY_STEP_WITH_PROGRESS
#define RAWREASSEMBLY_STEP_WITH_PROGRESS(seq, seg, seglen, buf, buflen, lastack, progress)
Definition: stream-tcp-reassemble.c:111
RAWREASSEMBLY_START
#define RAWREASSEMBLY_START(isn)
Definition: stream-tcp-reassemble.c:66
StreamReassembleRawUpdateProgress
void StreamReassembleRawUpdateProgress(TcpSession *ssn, Packet *p, const uint64_t progress)
update stream engine after detection
Definition: stream-tcp-reassemble.c:1555
RAWREASSEMBLY_END
#define RAWREASSEMBLY_END
Definition: stream-tcp-reassemble.c:86
TestReassembleRawCallbackData::expect_data_len
const uint32_t expect_data_len
Definition: stream-tcp-reassemble.c:31
TcpSession_
Definition: stream-tcp-private.h:283
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:237