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  p->tcph = &tcphdr; \
100  p->tcph->th_seq = htonl((seq)); \
101  p->tcph->th_ack = htonl(10); \
102  p->payload_len = (seglen); \
103  \
104  FAIL_IF(StreamTcpUTAddPayload(&tv, ra_ctx, &ssn, stream, (seq), (uint8_t *)(seg), (seglen)) != 0); \
105  p->flags |= PKT_STREAM_ADD; \
106  FAIL_IF(!(TestReassembleRawValidate(&ssn, p, (uint8_t *)(buf), (buflen)))); \
107  }\
108  PacketFree(p);
109 
110 #define RAWREASSEMBLY_STEP_WITH_PROGRESS(seq, seg, seglen, buf, buflen, lastack, progress) \
111  stream->last_ack = (lastack); \
112  RAWREASSEMBLY_STEP((seq),(seg),(seglen),(buf),(buflen)); \
113  FAIL_IF(STREAM_RAW_PROGRESS(stream) != (progress));
114 
115 static int StreamTcpReassembleRawTest01 (void)
116 {
118  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
119  RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
120  RAWREASSEMBLY_STEP(8, "CCC", 3, "AAABBBCCC", 9);
122 }
123 
124 static int StreamTcpReassembleRawTest02 (void)
125 {
127  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
128  RAWREASSEMBLY_STEP(5, "BBB", 3, "AAABBB", 6);
129  RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
130  RAWREASSEMBLY_STEP(8, "CCC", 3, "BBBCCCDDD", 9);
132 }
133 
134 static int StreamTcpReassembleRawTest03 (void)
135 {
137  RAWREASSEMBLY_STEP(2, "AAA", 3, "AAA", 3);
138  RAWREASSEMBLY_STEP(11,"DDD", 3, "DDD", 3);
139  RAWREASSEMBLY_STEP(8, "CCC", 3, "CCCDDD", 6);
141 }
142 
143 static int StreamTcpReassembleRawTest04 (void)
144 {
146  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
147  RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
148  RAWREASSEMBLY_STEP(7, "BBB", 3, "AAABBBCCC", 9);
150 }
151 
152 static int StreamTcpReassembleRawTest05 (void)
153 {
155  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
156  RAWREASSEMBLY_STEP(10,"CCCCC", 5, "CCCCC", 5);
157  RAWREASSEMBLY_STEP(2, "EEEEEEEEEEEEE", 13, "AAAAAEEECCCCC", 13);
159 }
160 
161 static int StreamTcpReassembleRawTest06 (void)
162 {
164  RAWREASSEMBLY_STEP(2, "AAAAA", 5, "AAAAA", 5);
165  RAWREASSEMBLY_STEP(16,"CCCCC", 5, "CCCCC", 5);
166  RAWREASSEMBLY_STEP(7, "BBBBBBBBB", 9, "ABBBBBBBBBC", 11);
167  RAWREASSEMBLY_STEP(21,"DDDDDDDDDD",10,"CCCDDDDDDDDDD", 13);
169 }
170 
171 static int StreamTcpReassembleRawTest07 (void)
172 {
174  RAWREASSEMBLY_STEP(2, "AAAAAAA", 7, "AAAAAAA", 7);
175  RAWREASSEMBLY_STEP(9, "BBBBBBB", 7, "AAABBBBBBB", 10);
176  RAWREASSEMBLY_STEP(16,"C", 1, "ABBBBBBBC", 9);
177  RAWREASSEMBLY_STEP(17,"DDDDDDDD",8,"BBCDDDDDDDD", 11);
179 }
180 
181 static int StreamTcpReassembleRawTest08 (void)
182 {
184  RAWREASSEMBLY_STEP_WITH_PROGRESS(2, "AAA", 3, "AAA", 3, 3, 3);
185  RAWREASSEMBLY_STEP_WITH_PROGRESS(8, "CCC", 3, "CCC", 3, 3, 3);
186  // segment lost, last_ack updated
187  RAWREASSEMBLY_STEP_WITH_PROGRESS(11, "DDD", 3, "CCCDDD", 6, 8, 12);
189 }
190 
191 static void StreamTcpReassembleRawRegisterTests(void)
192 {
193  UtRegisterTest("StreamTcpReassembleRawTest01",
194  StreamTcpReassembleRawTest01);
195  UtRegisterTest("StreamTcpReassembleRawTest02",
196  StreamTcpReassembleRawTest02);
197  UtRegisterTest("StreamTcpReassembleRawTest03",
198  StreamTcpReassembleRawTest03);
199  UtRegisterTest("StreamTcpReassembleRawTest04",
200  StreamTcpReassembleRawTest04);
201  UtRegisterTest("StreamTcpReassembleRawTest05",
202  StreamTcpReassembleRawTest05);
203  UtRegisterTest("StreamTcpReassembleRawTest06",
204  StreamTcpReassembleRawTest06);
205  UtRegisterTest("StreamTcpReassembleRawTest07",
206  StreamTcpReassembleRawTest07);
207  UtRegisterTest("StreamTcpReassembleRawTest08",
208  StreamTcpReassembleRawTest08);
209 }
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:1851
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:114
Packet_
Definition: decode.h:437
RAWREASSEMBLY_STEP_WITH_PROGRESS
#define RAWREASSEMBLY_STEP_WITH_PROGRESS(seq, seg, seglen, buf, buflen, lastack, progress)
Definition: stream-tcp-reassemble.c:110
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:1506
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