]> git.ipfire.org Git - people/ms/suricata.git/blame - src/detect-flow.c
core: Remove unneeded consts
[people/ms/suricata.git] / src / detect-flow.c
CommitLineData
7f6af10f 1/* Copyright (C) 2007-2020 Open Information Security Foundation
ce019275
WM
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
9b4c0d05
WM
18/**
19 * \file
ce019275 20 *
9b4c0d05
WM
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * FLOW part of the detection engine.
24 */
bab4b623 25
ecf86f9c 26#include "suricata-common.h"
bab4b623
VJ
27#include "debug.h"
28#include "decode.h"
b259e362 29
bab4b623 30#include "detect.h"
b259e362 31#include "detect-parse.h"
855726f3 32#include "detect-engine.h"
822e0347 33#include "detect-engine-prefilter-common.h"
bab4b623
VJ
34
35#include "flow.h"
36#include "flow-var.h"
37
38#include "detect-flow.h"
39
9b4c0d05 40#include "util-unittest.h"
855726f3 41#include "util-unittest-helper.h"
ba6d807a 42#include "util-debug.h"
9b4c0d05
WM
43
44/**
45 * \brief Regex for parsing our flow options
46 */
47#define PARSE_REGEX "^\\s*([A-z_]+)\\s*(?:,\\s*([A-z_]+))?\\s*(?:,\\s*([A-z_]+))?\\s*$"
48
4b0085b0 49static DetectParseRegex parse_regex;
bab4b623 50
14896365 51int DetectFlowMatch (DetectEngineThreadCtx *, Packet *,
bfd4bc82 52 const Signature *, const SigMatchCtx *);
ab1200fb 53static int DetectFlowSetup (DetectEngineCtx *, Signature *, const char *);
6ab323d3
VJ
54#ifdef UNITTESTS
55static void DetectFlowRegisterTests(void);
56#endif
d3a65fe1 57void DetectFlowFree(DetectEngineCtx *, void *);
bab4b623 58
91296d1e 59static int PrefilterSetupFlow(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
be4c6b85 60static bool PrefilterFlowIsPrefilterable(const Signature *s);
822e0347 61
9b4c0d05
WM
62/**
63 * \brief Registration function for flow: keyword
9b4c0d05 64 */
8f1d7503
KS
65void DetectFlowRegister (void)
66{
bab4b623 67 sigmatch_table[DETECT_FLOW].name = "flow";
d801c3e5 68 sigmatch_table[DETECT_FLOW].desc = "match on direction and state of the flow";
26bcc975 69 sigmatch_table[DETECT_FLOW].url = "/rules/flow-keywords.html#flow";
bab4b623
VJ
70 sigmatch_table[DETECT_FLOW].Match = DetectFlowMatch;
71 sigmatch_table[DETECT_FLOW].Setup = DetectFlowSetup;
97854cf4 72 sigmatch_table[DETECT_FLOW].Free = DetectFlowFree;
6ab323d3 73#ifdef UNITTESTS
9b4c0d05 74 sigmatch_table[DETECT_FLOW].RegisterTests = DetectFlowRegisterTests;
6ab323d3 75#endif
822e0347
VJ
76 sigmatch_table[DETECT_FLOW].SupportsPrefilter = PrefilterFlowIsPrefilterable;
77 sigmatch_table[DETECT_FLOW].SetupPrefilter = PrefilterSetupFlow;
78
4b0085b0 79 DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
bab4b623
VJ
80}
81
8f56c234
JI
82/**
83 * \param pflags packet flags (p->flags)
84 * \param pflowflags packet flow flags (p->flowflags)
85 * \param tflags detection flags (det_ctx->flags)
86 * \param dflags detect flow flags
87 * \param match_cnt number of matches to trigger
88 */
89static inline int FlowMatch(const uint32_t pflags, const uint8_t pflowflags,
90 const uint16_t tflags, const uint16_t dflags, const uint8_t match_cnt)
822e0347
VJ
91{
92 uint8_t cnt = 0;
93
8f56c234
JI
94 if ((dflags & DETECT_FLOW_FLAG_NO_FRAG) &&
95 (!(pflags & PKT_REBUILT_FRAGMENT))) {
96 cnt++;
97 } else if ((dflags & DETECT_FLOW_FLAG_ONLY_FRAG) &&
98 (pflags & PKT_REBUILT_FRAGMENT)) {
99 cnt++;
100 }
101
822e0347
VJ
102 if ((dflags & DETECT_FLOW_FLAG_TOSERVER) && (pflowflags & FLOW_PKT_TOSERVER)) {
103 cnt++;
104 } else if ((dflags & DETECT_FLOW_FLAG_TOCLIENT) && (pflowflags & FLOW_PKT_TOCLIENT)) {
105 cnt++;
106 }
107
108 if ((dflags & DETECT_FLOW_FLAG_ESTABLISHED) && (pflowflags & FLOW_PKT_ESTABLISHED)) {
109 cnt++;
571f56cf
JI
110 } else if (dflags & DETECT_FLOW_FLAG_NOT_ESTABLISHED && (!(pflowflags & FLOW_PKT_ESTABLISHED))) {
111 cnt++;
822e0347
VJ
112 } else if (dflags & DETECT_FLOW_FLAG_STATELESS) {
113 cnt++;
114 }
115
116 if (tflags & DETECT_ENGINE_THREAD_CTX_STREAM_CONTENT_MATCH) {
117 if (dflags & DETECT_FLOW_FLAG_ONLYSTREAM)
118 cnt++;
119 } else {
120 if (dflags & DETECT_FLOW_FLAG_NOSTREAM)
121 cnt++;
122 }
123
124 return (match_cnt == cnt) ? 1 : 0;
125}
bab4b623 126
9b4c0d05
WM
127/**
128 * \brief This function is used to match flow flags set on a packet with those passed via flow:
9b4c0d05
WM
129 *
130 * \param t pointer to thread vars
1132ab63 131 * \param det_ctx pointer to the pattern matcher thread
9b4c0d05
WM
132 * \param p pointer to the current packet
133 * \param m pointer to the sigmatch that we will cast into DetectFlowData
134 *
135 * \retval 0 no match
136 * \retval 1 match
137 */
14896365 138int DetectFlowMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
bfd4bc82 139 const Signature *s, const SigMatchCtx *ctx)
bab4b623 140{
83b2c8ab
VJ
141 SCEnter();
142
2f29b8a7
VJ
143 SCLogDebug("pkt %p", p);
144
145 if (p->flowflags & FLOW_PKT_TOSERVER) {
146 SCLogDebug("FLOW_PKT_TOSERVER");
147 } else if (p->flowflags & FLOW_PKT_TOCLIENT) {
148 SCLogDebug("FLOW_PKT_TOCLIENT");
149 }
150
151 if (p->flowflags & FLOW_PKT_ESTABLISHED) {
152 SCLogDebug("FLOW_PKT_ESTABLISHED");
2f29b8a7
VJ
153 }
154
923a77e9 155 const DetectFlowData *fd = (const DetectFlowData *)ctx;
bab4b623 156
991ec4ed 157 const int ret = FlowMatch(p->flags, p->flowflags, det_ctx->flags, fd->flags, fd->match_cnt);
822e0347
VJ
158 SCLogDebug("returning %" PRId32 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X",
159 ret, fd->match_cnt, fd->flags, p->flowflags);
83b2c8ab 160 SCReturnInt(ret);
bab4b623
VJ
161}
162
9b4c0d05
WM
163/**
164 * \brief This function is used to parse flow options passed via flow: keyword
165 *
d3a65fe1 166 * \param de_ctx Pointer to the detection engine context
9b4c0d05
WM
167 * \param flowstr Pointer to the user provided flow options
168 *
169 * \retval fd pointer to DetectFlowData on success
170 * \retval NULL on failure
171 */
d3a65fe1 172static DetectFlowData *DetectFlowParse (DetectEngineCtx *de_ctx, const char *flowstr)
bab4b623
VJ
173{
174 DetectFlowData *fd = NULL;
9b4c0d05 175 char *args[3] = {NULL,NULL,NULL};
bab4b623 176 int ret = 0, res = 0;
3de99a21 177 size_t pcre2len;
beab8d40 178 char str1[16] = "", str2[16] = "", str3[16] = "";
bab4b623 179
3de99a21 180 ret = DetectParsePcreExec(&parse_regex, flowstr, 0, 0);
9b4c0d05 181 if (ret < 1 || ret > 4) {
ba6d807a 182 SCLogError(SC_ERR_PCRE_MATCH, "parse error, ret %" PRId32 ", string %s", ret, flowstr);
9b4c0d05
WM
183 goto error;
184 }
3f47eade 185
bab4b623 186 if (ret > 1) {
3de99a21 187 pcre2len = sizeof(str1);
56f664af 188 res = SC_Pcre2SubstringCopy(parse_regex.match, 1, (PCRE2_UCHAR8 *)str1, &pcre2len);
bab4b623 189 if (res < 0) {
3de99a21 190 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
9b4c0d05 191 goto error;
bab4b623 192 }
beab8d40 193 args[0] = (char *)str1;
bab4b623
VJ
194
195 if (ret > 2) {
3de99a21
PA
196 pcre2len = sizeof(str2);
197 res = pcre2_substring_copy_bynumber(
198 parse_regex.match, 2, (PCRE2_UCHAR8 *)str2, &pcre2len);
bab4b623 199 if (res < 0) {
3de99a21 200 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
9b4c0d05 201 goto error;
bab4b623 202 }
beab8d40 203 args[1] = (char *)str2;
bab4b623
VJ
204 }
205 if (ret > 3) {
3de99a21
PA
206 pcre2len = sizeof(str3);
207 res = pcre2_substring_copy_bynumber(
208 parse_regex.match, 3, (PCRE2_UCHAR8 *)str3, &pcre2len);
bab4b623 209 if (res < 0) {
3de99a21 210 SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre2_substring_copy_bynumber failed");
9b4c0d05 211 goto error;
bab4b623 212 }
beab8d40 213 args[2] = (char *)str3;
bab4b623
VJ
214 }
215 }
bab4b623 216
25a3a5c6 217 fd = SCMalloc(sizeof(DetectFlowData));
e176be6f 218 if (unlikely(fd == NULL))
bab4b623 219 goto error;
bab4b623 220 fd->flags = 0;
9b4c0d05
WM
221 fd->match_cnt = 0;
222
223 int i;
3f47eade 224 for (i = 0; i < (ret - 1); i++) {
9b4c0d05
WM
225 if (args[i]) {
226 /* inspect our options and set the flags */
583c6861 227 if (strcasecmp(args[i], "established") == 0) {
d834173b
VJ
228 if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
229 SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_ESTABLISHED flag is already set");
9b4c0d05 230 goto error;
d834173b
VJ
231 } else if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
232 SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS already set");
9b4c0d05
WM
233 goto error;
234 }
d834173b 235 fd->flags |= DETECT_FLOW_FLAG_ESTABLISHED;
571f56cf
JI
236 } else if (strcasecmp(args[i], "not_established") == 0) {
237 if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) {
238 SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_NOT_ESTABLISHED flag is already set");
239 goto error;
240 } else if (fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED) {
241 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_NOT_ESTABLISHED, DETECT_FLOW_FLAG_ESTABLISHED already set");
242 goto error;
243 }
244 fd->flags |= DETECT_FLOW_FLAG_NOT_ESTABLISHED;
583c6861 245 } else if (strcasecmp(args[i], "stateless") == 0) {
d834173b
VJ
246 if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
247 SCLogError(SC_ERR_FLAGS_MODIFIER, "DETECT_FLOW_FLAG_STATELESS flag is already set");
9b4c0d05 248 goto error;
d834173b
VJ
249 } else if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
250 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_STATELESS, DETECT_FLOW_FLAG_ESTABLISHED already set");
9b4c0d05
WM
251 goto error;
252 }
d834173b 253 fd->flags |= DETECT_FLOW_FLAG_STATELESS;
583c6861 254 } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) {
d834173b
VJ
255 if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
256 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOCLIENT flag is already set");
9b4c0d05 257 goto error;
d834173b
VJ
258 } else if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
259 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_client, DETECT_FLOW_FLAG_TOSERVER already set");
9b4c0d05
WM
260 goto error;
261 }
d834173b 262 fd->flags |= DETECT_FLOW_FLAG_TOCLIENT;
583c6861 263 } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){
d834173b
VJ
264 if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
265 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set DETECT_FLOW_FLAG_TOSERVER flag is already set");
9b4c0d05 266 goto error;
d834173b
VJ
267 } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
268 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set to_server, DETECT_FLOW_FLAG_TO_CLIENT flag already set");
9b4c0d05
WM
269 goto error;
270 }
d834173b 271 fd->flags |= DETECT_FLOW_FLAG_TOSERVER;
298289f4 272 } else if (strcasecmp(args[i], "only_stream") == 0) {
d834173b 273 if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
298289f4 274 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag is already set");
9b4c0d05 275 goto error;
d834173b
VJ
276 } else if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
277 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_stream flag, DETECT_FLOW_FLAG_NOSTREAM already set");
9b4c0d05
WM
278 goto error;
279 }
d834173b 280 fd->flags |= DETECT_FLOW_FLAG_ONLYSTREAM;
583c6861 281 } else if (strcasecmp(args[i], "no_stream") == 0) {
d834173b 282 if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
ba6d807a 283 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag is already set");
9b4c0d05 284 goto error;
d834173b
VJ
285 } else if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
286 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_stream flag, DETECT_FLOW_FLAG_ONLYSTREAM already set");
9b4c0d05
WM
287 goto error;
288 }
d834173b 289 fd->flags |= DETECT_FLOW_FLAG_NOSTREAM;
8f56c234
JI
290 } else if (strcasecmp(args[i], "no_frag") == 0) {
291 if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
292 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag is already set");
293 goto error;
294 } else if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
295 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set no_frag flag, only_frag already set");
296 goto error;
297 }
298 fd->flags |= DETECT_FLOW_FLAG_NO_FRAG;
299 } else if (strcasecmp(args[i], "only_frag") == 0) {
300 if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
301 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag is already set");
302 goto error;
303 } else if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
304 SCLogError(SC_ERR_FLAGS_MODIFIER, "cannot set only_frag flag, no_frag already set");
305 goto error;
306 }
307 fd->flags |= DETECT_FLOW_FLAG_ONLY_FRAG;
9b4c0d05 308 } else {
ba6d807a 309 SCLogError(SC_ERR_INVALID_VALUE, "invalid flow option \"%s\"", args[i]);
9b4c0d05
WM
310 goto error;
311 }
bab4b623 312
9b4c0d05 313 fd->match_cnt++;
fa5939ca 314 //printf("args[%" PRId32 "]: %s match_cnt: %" PRId32 " flags: 0x%02X\n", i, args[i], fd->match_cnt, fd->flags);
9b4c0d05
WM
315 }
316 }
9b4c0d05
WM
317 return fd;
318
319error:
3f47eade 320 if (fd != NULL)
d3a65fe1 321 DetectFlowFree(de_ctx, fd);
9b4c0d05
WM
322 return NULL;
323
324}
325
c8bd489a
VJ
326int DetectFlowSetupImplicit(Signature *s, uint32_t flags)
327{
328#define SIG_FLAG_BOTH (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)
329 BUG_ON(flags == 0);
330 BUG_ON(flags & ~SIG_FLAG_BOTH);
331 BUG_ON((flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH);
332
67c90954
VJ
333 SCLogDebug("want %08lx", flags & SIG_FLAG_BOTH);
334 SCLogDebug("have %08lx", s->flags & SIG_FLAG_BOTH);
c8bd489a
VJ
335
336 if (flags & SIG_FLAG_TOSERVER) {
337 if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
338 /* both is set if we just have 'flow:established' */
339 s->flags &= ~SIG_FLAG_TOCLIENT;
340 } else if (s->flags & SIG_FLAG_TOCLIENT) {
341 return -1;
342 }
343 s->flags |= SIG_FLAG_TOSERVER;
344 } else {
345 if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
346 /* both is set if we just have 'flow:established' */
347 s->flags &= ~SIG_FLAG_TOSERVER;
348 } else if (s->flags & SIG_FLAG_TOSERVER) {
349 return -1;
350 }
351 s->flags |= SIG_FLAG_TOCLIENT;
352 }
353 return 0;
354#undef SIG_FLAG_BOTH
355}
356
9b4c0d05 357/**
646262a7 358 * \brief this function is used to add the parsed flowdata into the current signature
9b4c0d05
WM
359 *
360 * \param de_ctx pointer to the Detection Engine Context
361 * \param s pointer to the Current Signature
9b4c0d05
WM
362 * \param flowstr pointer to the user provided flow options
363 *
364 * \retval 0 on Success
365 * \retval -1 on Failure
366 */
ab1200fb 367int DetectFlowSetup (DetectEngineCtx *de_ctx, Signature *s, const char *flowstr)
9b4c0d05 368{
991ec4ed 369 /* ensure only one flow option */
f370e881 370 if (s->init_data->init_flags & SIG_FLAG_INIT_FLOW) {
2c24eb9e 371 SCLogError (SC_ERR_INVALID_SIGNATURE, "A signature may have only one flow option.");
991ec4ed 372 return -1;
2c24eb9e
ED
373 }
374
d3a65fe1 375 DetectFlowData *fd = DetectFlowParse(de_ctx, flowstr);
991ec4ed
VJ
376 if (fd == NULL)
377 return -1;
378
379 SigMatch *sm = SigMatchAlloc();
bab4b623
VJ
380 if (sm == NULL)
381 goto error;
382
383 sm->type = DETECT_FLOW;
923a77e9 384 sm->ctx = (SigMatchCtx *)fd;
bab4b623 385
21ee59e6 386 /* set the signature direction flags */
d834173b 387 if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
21ee59e6 388 s->flags |= SIG_FLAG_TOSERVER;
d834173b 389 } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
21ee59e6
VJ
390 s->flags |= SIG_FLAG_TOCLIENT;
391 } else {
392 s->flags |= SIG_FLAG_TOSERVER;
393 s->flags |= SIG_FLAG_TOCLIENT;
394 }
d834173b 395 if (fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
298289f4
VJ
396 s->flags |= SIG_FLAG_REQUIRE_STREAM;
397 }
d834173b 398 if (fd->flags & DETECT_FLOW_FLAG_NOSTREAM) {
298289f4 399 s->flags |= SIG_FLAG_REQUIRE_PACKET;
d5baac3f
VJ
400 } else if (fd->flags == DETECT_FLOW_FLAG_TOSERVER ||
401 fd->flags == DETECT_FLOW_FLAG_TOCLIENT)
402 {
55e5d504
VJ
403 /* no direct flow is needed for just direction,
404 * no sigmatch is needed either. */
d3a65fe1 405 SigMatchFree(de_ctx, sm);
55e5d504 406 sm = NULL;
855726f3 407 } else {
f370e881 408 s->init_data->init_flags |= SIG_FLAG_INIT_FLOW;
298289f4
VJ
409 }
410
55e5d504
VJ
411 if (sm != NULL) {
412 SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
413 }
bab4b623
VJ
414 return 0;
415
416error:
21ee59e6 417 if (fd != NULL)
d3a65fe1 418 DetectFlowFree(de_ctx, fd);
bab4b623 419 return -1;
9b4c0d05
WM
420
421}
422
423/**
424 * \brief this function will free memory associated with DetectFlowData
425 *
426 * \param fd pointer to DetectFlowData
427 */
d3a65fe1 428void DetectFlowFree(DetectEngineCtx *de_ctx, void *ptr)
8f1d7503 429{
97854cf4 430 DetectFlowData *fd = (DetectFlowData *)ptr;
25a3a5c6 431 SCFree(fd);
9b4c0d05
WM
432}
433
822e0347
VJ
434static void
435PrefilterPacketFlowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
436{
437 const PrefilterPacketHeaderCtx *ctx = pectx;
438
1eeb9669 439 if (!PrefilterPacketHeaderExtraMatch(ctx, p))
ace8f9f5
VJ
440 return;
441
8f56c234 442 if (FlowMatch(p->flags, p->flowflags, det_ctx->flags, ctx->v1.u8[0], ctx->v1.u8[1]))
822e0347
VJ
443 {
444 PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
445 }
446}
447
448static void
449PrefilterPacketFlowSet(PrefilterPacketHeaderValue *v, void *smctx)
450{
451 const DetectFlowData *fb = smctx;
452 v->u8[0] = fb->flags;
453 v->u8[1] = fb->match_cnt;
454}
455
be4c6b85 456static bool
822e0347
VJ
457PrefilterPacketFlowCompare(PrefilterPacketHeaderValue v, void *smctx)
458{
459 const DetectFlowData *fb = smctx;
460 if (v.u8[0] == fb->flags &&
461 v.u8[1] == fb->match_cnt)
462 {
1eeb9669 463 return true;
822e0347 464 }
1eeb9669 465 return false;
822e0347
VJ
466}
467
91296d1e 468static int PrefilterSetupFlow(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
822e0347 469{
91296d1e 470 return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW,
822e0347
VJ
471 PrefilterPacketFlowSet,
472 PrefilterPacketFlowCompare,
473 PrefilterPacketFlowMatch);
474}
475
be4c6b85 476static bool PrefilterFlowIsPrefilterable(const Signature *s)
822e0347
VJ
477{
478 const SigMatch *sm;
8edc954e 479 for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
822e0347
VJ
480 switch (sm->type) {
481 case DETECT_FLOW:
1eeb9669 482 return true;
822e0347
VJ
483 }
484 }
1eeb9669 485 return false;
822e0347
VJ
486}
487
c43319c3 488#ifdef UNITTESTS
583c6861 489
9b4c0d05
WM
490/**
491 * \test DetectFlowTestParse01 is a test to make sure that we return "something"
492 * when given valid flow opt
493 */
ab1200fb 494static int DetectFlowTestParse01 (void)
8f1d7503 495{
9b4c0d05 496 DetectFlowData *fd = NULL;
d3a65fe1 497 fd = DetectFlowParse(NULL, "established");
dc762cd4 498 FAIL_IF_NULL(fd);
d3a65fe1 499 DetectFlowFree(NULL, fd);
dc762cd4 500 PASS;
9b4c0d05
WM
501}
502
503/**
504 * \test DetectFlowTestParse02 is a test for setting the established flow opt
505 */
ab1200fb 506static int DetectFlowTestParse02 (void)
8f1d7503 507{
9b4c0d05 508 DetectFlowData *fd = NULL;
d3a65fe1 509 fd = DetectFlowParse(NULL, "established");
dc762cd4
JI
510 FAIL_IF_NULL(fd);
511 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_ESTABLISHED &&
512 fd->match_cnt == 1);
513 PASS;
9b4c0d05
WM
514}
515
516/**
517 * \test DetectFlowTestParse03 is a test for setting the stateless flow opt
518 */
ab1200fb 519static int DetectFlowTestParse03 (void)
8f1d7503 520{
9b4c0d05 521 DetectFlowData *fd = NULL;
d3a65fe1 522 fd = DetectFlowParse(NULL, "stateless");
dc762cd4
JI
523 FAIL_IF_NULL(fd);
524 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_STATELESS && fd->match_cnt == 1);
d3a65fe1 525 DetectFlowFree(NULL, fd);
dc762cd4 526 PASS;
9b4c0d05
WM
527}
528
529/**
530 * \test DetectFlowTestParse04 is a test for setting the to_client flow opt
531 */
ab1200fb 532static int DetectFlowTestParse04 (void)
8f1d7503 533{
9b4c0d05 534 DetectFlowData *fd = NULL;
d3a65fe1 535 fd = DetectFlowParse(NULL, "to_client");
dc762cd4
JI
536 FAIL_IF_NULL(fd);
537 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
d3a65fe1 538 DetectFlowFree(NULL, fd);
dc762cd4 539 PASS;
9b4c0d05
WM
540}
541
542/**
543 * \test DetectFlowTestParse05 is a test for setting the to_server flow opt
544 */
ab1200fb 545static int DetectFlowTestParse05 (void)
8f1d7503 546{
9b4c0d05 547 DetectFlowData *fd = NULL;
d3a65fe1 548 fd = DetectFlowParse(NULL, "to_server");
dc762cd4
JI
549 FAIL_IF_NULL(fd);
550 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
d3a65fe1 551 DetectFlowFree(NULL, fd);
dc762cd4 552 PASS;
9b4c0d05
WM
553}
554
555/**
556 * \test DetectFlowTestParse06 is a test for setting the from_server flow opt
557 */
ab1200fb 558static int DetectFlowTestParse06 (void)
8f1d7503 559{
9b4c0d05 560 DetectFlowData *fd = NULL;
d3a65fe1 561 fd = DetectFlowParse(NULL, "from_server");
dc762cd4
JI
562 FAIL_IF_NULL(fd);
563 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
d3a65fe1 564 DetectFlowFree(NULL, fd);
dc762cd4 565 PASS;
9b4c0d05
WM
566}
567
568/**
569 * \test DetectFlowTestParse07 is a test for setting the from_client flow opt
570 */
ab1200fb 571static int DetectFlowTestParse07 (void)
8f1d7503 572{
9b4c0d05 573 DetectFlowData *fd = NULL;
d3a65fe1 574 fd = DetectFlowParse(NULL, "from_client");
dc762cd4
JI
575 FAIL_IF_NULL(fd);
576 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
d3a65fe1 577 DetectFlowFree(NULL, fd);
dc762cd4 578 PASS;
9b4c0d05
WM
579}
580
581/**
582 * \test DetectFlowTestParse08 is a test for setting the established,to_client flow opts
583 */
ab1200fb 584static int DetectFlowTestParse08 (void)
8f1d7503 585{
9b4c0d05 586 DetectFlowData *fd = NULL;
d3a65fe1 587 fd = DetectFlowParse(NULL, "established,to_client");
dc762cd4
JI
588 FAIL_IF_NULL(fd);
589 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2);
d3a65fe1 590 DetectFlowFree(NULL, fd);
dc762cd4 591 PASS;
9b4c0d05
WM
592}
593
594/**
595 * \test DetectFlowTestParse09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
596 */
ab1200fb 597static int DetectFlowTestParse09 (void)
8f1d7503 598{
9b4c0d05 599 DetectFlowData *fd = NULL;
d3a65fe1 600 fd = DetectFlowParse(NULL, "to_client,stateless");
dc762cd4
JI
601 FAIL_IF_NULL(fd);
602 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
603 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
604 fd->match_cnt == 2);
d3a65fe1 605 DetectFlowFree(NULL, fd);
dc762cd4 606 PASS;
9b4c0d05
WM
607}
608
609/**
610 * \test DetectFlowTestParse10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
611 */
ab1200fb 612static int DetectFlowTestParse10 (void)
8f1d7503 613{
9b4c0d05 614 DetectFlowData *fd = NULL;
d3a65fe1 615 fd = DetectFlowParse(NULL, "from_server,stateless");
dc762cd4
JI
616 FAIL_IF_NULL(fd);
617 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
618 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
619 fd->match_cnt == 2);
d3a65fe1 620 DetectFlowFree(NULL, fd);
dc762cd4 621 PASS;
9b4c0d05
WM
622}
623
624/**
625 * \test DetectFlowTestParse11 is a test for setting the from_server,stateless flow opts with spaces all around
626 */
ab1200fb 627static int DetectFlowTestParse11 (void)
8f1d7503 628{
9b4c0d05 629 DetectFlowData *fd = NULL;
d3a65fe1 630 fd = DetectFlowParse(NULL, " from_server , stateless ");
dc762cd4
JI
631 FAIL_IF_NULL(fd);
632 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
633 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
634 fd->match_cnt == 2);
d3a65fe1 635 DetectFlowFree(NULL, fd);
dc762cd4 636 PASS;
9b4c0d05
WM
637}
638
583c6861
PR
639/**
640 * \test DetectFlowTestParseNocase01 is a test to make sure that we return "something"
641 * when given valid flow opt
642 */
ab1200fb 643static int DetectFlowTestParseNocase01 (void)
8f1d7503 644{
583c6861 645 DetectFlowData *fd = NULL;
d3a65fe1 646 fd = DetectFlowParse(NULL, "ESTABLISHED");
dc762cd4 647 FAIL_IF_NULL(fd);
d3a65fe1 648 DetectFlowFree(NULL, fd);
dc762cd4 649 PASS;
583c6861
PR
650}
651
652/**
653 * \test DetectFlowTestParseNocase02 is a test for setting the established flow opt
654 */
ab1200fb 655static int DetectFlowTestParseNocase02 (void)
8f1d7503 656{
583c6861 657 DetectFlowData *fd = NULL;
d3a65fe1 658 fd = DetectFlowParse(NULL, "ESTABLISHED");
dc762cd4
JI
659 FAIL_IF_NULL(fd);
660 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_ESTABLISHED &&
661 fd->match_cnt == 1);
d3a65fe1 662 DetectFlowFree(NULL, fd);
dc762cd4 663 PASS;
583c6861
PR
664}
665
666/**
667 * \test DetectFlowTestParseNocase03 is a test for setting the stateless flow opt
668 */
ab1200fb 669static int DetectFlowTestParseNocase03 (void)
8f1d7503 670{
583c6861 671 DetectFlowData *fd = NULL;
d3a65fe1 672 fd = DetectFlowParse(NULL, "STATELESS");
dc762cd4 673 FAIL_IF_NULL(fd);
d3a65fe1 674 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_STATELESS && fd->match_cnt == 1); DetectFlowFree(NULL, fd);
dc762cd4 675 PASS;
583c6861
PR
676}
677
678/**
679 * \test DetectFlowTestParseNocase04 is a test for setting the to_client flow opt
680 */
ab1200fb 681static int DetectFlowTestParseNocase04 (void)
8f1d7503 682{
583c6861 683 DetectFlowData *fd = NULL;
d3a65fe1 684 fd = DetectFlowParse(NULL, "TO_CLIENT");
dc762cd4
JI
685 FAIL_IF_NULL(fd);
686 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
d3a65fe1 687 DetectFlowFree(NULL, fd);
dc762cd4 688 PASS;
583c6861
PR
689}
690
691/**
692 * \test DetectFlowTestParseNocase05 is a test for setting the to_server flow opt
693 */
ab1200fb 694static int DetectFlowTestParseNocase05 (void)
8f1d7503 695{
583c6861 696 DetectFlowData *fd = NULL;
d3a65fe1 697 fd = DetectFlowParse(NULL, "TO_SERVER");
dc762cd4
JI
698 FAIL_IF_NULL(fd);
699 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
d3a65fe1 700 DetectFlowFree(NULL, fd);
dc762cd4 701 PASS;
583c6861
PR
702}
703
704/**
705 * \test DetectFlowTestParseNocase06 is a test for setting the from_server flow opt
706 */
ab1200fb 707static int DetectFlowTestParseNocase06 (void)
8f1d7503 708{
583c6861 709 DetectFlowData *fd = NULL;
d3a65fe1 710 fd = DetectFlowParse(NULL, "FROM_SERVER");
dc762cd4
JI
711 FAIL_IF_NULL(fd);
712 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
d3a65fe1 713 DetectFlowFree(NULL, fd);
dc762cd4 714 PASS;
583c6861
PR
715}
716
717/**
718 * \test DetectFlowTestParseNocase07 is a test for setting the from_client flow opt
719 */
ab1200fb 720static int DetectFlowTestParseNocase07 (void)
8f1d7503 721{
583c6861 722 DetectFlowData *fd = NULL;
d3a65fe1 723 fd = DetectFlowParse(NULL, "FROM_CLIENT");
dc762cd4
JI
724 FAIL_IF_NULL(fd);
725 FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
d3a65fe1 726 DetectFlowFree(NULL, fd);
dc762cd4 727 PASS;
583c6861
PR
728}
729
730/**
731 * \test DetectFlowTestParseNocase08 is a test for setting the established,to_client flow opts
732 */
ab1200fb 733static int DetectFlowTestParseNocase08 (void)
8f1d7503 734{
583c6861 735 DetectFlowData *fd = NULL;
d3a65fe1 736 fd = DetectFlowParse(NULL, "ESTABLISHED,TO_CLIENT");
dc762cd4
JI
737 FAIL_IF_NULL(fd);
738 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
739 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
740 fd->match_cnt == 2);
d3a65fe1 741 DetectFlowFree(NULL, fd);
dc762cd4 742 PASS;
583c6861
PR
743}
744
745/**
746 * \test DetectFlowTestParseNocase09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
747 */
ab1200fb 748static int DetectFlowTestParseNocase09 (void)
8f1d7503 749{
583c6861 750 DetectFlowData *fd = NULL;
d3a65fe1 751 fd = DetectFlowParse(NULL, "TO_CLIENT,STATELESS");
dc762cd4
JI
752 FAIL_IF_NULL(fd);
753 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
754 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
755 fd->match_cnt == 2);
d3a65fe1 756 DetectFlowFree(NULL, fd);
dc762cd4 757 PASS;
583c6861
PR
758}
759
760/**
761 * \test DetectFlowTestParseNocase10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
762 */
ab1200fb 763static int DetectFlowTestParseNocase10 (void)
8f1d7503 764{
583c6861 765 DetectFlowData *fd = NULL;
d3a65fe1 766 fd = DetectFlowParse(NULL, "FROM_SERVER,STATELESS");
dc762cd4
JI
767 FAIL_IF_NULL(fd);
768 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
769 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
770 fd->match_cnt == 2);
d3a65fe1 771 DetectFlowFree(NULL, fd);
dc762cd4 772 PASS;
583c6861
PR
773}
774
775/**
776 * \test DetectFlowTestParseNocase11 is a test for setting the from_server,stateless flow opts with spaces all around
777 */
ab1200fb 778static int DetectFlowTestParseNocase11 (void)
8f1d7503 779{
583c6861 780 DetectFlowData *fd = NULL;
d3a65fe1 781 fd = DetectFlowParse(NULL, " FROM_SERVER , STATELESS ");
dc762cd4
JI
782 FAIL_IF_NULL(fd);
783 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
784 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
785 fd->match_cnt == 2);
d3a65fe1 786 DetectFlowFree(NULL, fd);
dc762cd4 787 PASS;
583c6861
PR
788}
789
9b4c0d05
WM
790/**
791 * \test DetectFlowTestParse12 is a test for setting an invalid seperator :
792 */
ab1200fb 793static int DetectFlowTestParse12 (void)
8f1d7503 794{
9b4c0d05 795 DetectFlowData *fd = NULL;
d3a65fe1 796 fd = DetectFlowParse(NULL, "from_server:stateless");
dc762cd4
JI
797 FAIL_IF_NOT_NULL(fd);
798 PASS;
9b4c0d05
WM
799}
800
801/**
802 * \test DetectFlowTestParse13 is a test for an invalid option
803 */
ab1200fb 804static int DetectFlowTestParse13 (void)
8f1d7503 805{
9b4c0d05 806 DetectFlowData *fd = NULL;
d3a65fe1 807 fd = DetectFlowParse(NULL, "invalidoptiontest");
dc762cd4
JI
808 FAIL_IF_NOT_NULL(fd);
809 PASS;
bab4b623 810}
dc762cd4 811
9b4c0d05
WM
812/**
813 * \test DetectFlowTestParse14 is a test for a empty option
814 */
ab1200fb 815static int DetectFlowTestParse14 (void)
8f1d7503 816{
9b4c0d05 817 DetectFlowData *fd = NULL;
d3a65fe1 818 fd = DetectFlowParse(NULL, "");
dc762cd4
JI
819 FAIL_IF_NOT_NULL(fd);
820 PASS;
9b4c0d05
WM
821}
822
823/**
824 * \test DetectFlowTestParse15 is a test for an invalid combo of options established,stateless
825 */
ab1200fb 826static int DetectFlowTestParse15 (void)
8f1d7503 827{
9b4c0d05 828 DetectFlowData *fd = NULL;
d3a65fe1 829 fd = DetectFlowParse(NULL, "established,stateless");
dc762cd4
JI
830 FAIL_IF_NOT_NULL(fd);
831 PASS;
9b4c0d05
WM
832}
833
834/**
835 * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,to_server
836 */
ab1200fb 837static int DetectFlowTestParse16 (void)
8f1d7503 838{
9b4c0d05 839 DetectFlowData *fd = NULL;
d3a65fe1 840 fd = DetectFlowParse(NULL, "to_client,to_server");
dc762cd4
JI
841 FAIL_IF_NOT_NULL(fd);
842 PASS;
9b4c0d05
WM
843}
844
845/**
846 * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,from_server
847 * flowbit flags are the same
848 */
ab1200fb 849static int DetectFlowTestParse17 (void)
8f1d7503 850{
9b4c0d05 851 DetectFlowData *fd = NULL;
d3a65fe1 852 fd = DetectFlowParse(NULL, "to_client,from_server");
dc762cd4
JI
853 FAIL_IF_NOT_NULL(fd);
854 PASS;
9b4c0d05
WM
855}
856
857/**
298289f4 858 * \test DetectFlowTestParse18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
9b4c0d05 859 */
ab1200fb 860static int DetectFlowTestParse18 (void)
8f1d7503 861{
9b4c0d05 862 DetectFlowData *fd = NULL;
d3a65fe1 863 fd = DetectFlowParse(NULL, "from_server,established,only_stream");
dc762cd4
JI
864 FAIL_IF_NULL(fd);
865 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
866 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
867 fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM &&
868 fd->match_cnt == 3);
d3a65fe1 869 DetectFlowFree(NULL, fd);
dc762cd4 870 PASS;
9b4c0d05
WM
871}
872
583c6861 873/**
298289f4 874 * \test DetectFlowTestParseNocase18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
583c6861 875 */
ab1200fb 876static int DetectFlowTestParseNocase18 (void)
8f1d7503 877{
583c6861 878 DetectFlowData *fd = NULL;
d3a65fe1 879 fd = DetectFlowParse(NULL, "FROM_SERVER,ESTABLISHED,ONLY_STREAM");
dc762cd4
JI
880 FAIL_IF_NULL(fd);
881 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
882 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
883 fd->flags & DETECT_FLOW_FLAG_ONLYSTREAM &&
884 fd->match_cnt == 3);
d3a65fe1 885 DetectFlowFree(NULL, fd);
dc762cd4 886 PASS;
583c6861
PR
887}
888
889
9b4c0d05
WM
890/**
891 * \test DetectFlowTestParse19 is a test for one to many options passed to DetectFlowParse
892 */
ab1200fb 893static int DetectFlowTestParse19 (void)
8f1d7503 894{
9b4c0d05 895 DetectFlowData *fd = NULL;
d3a65fe1 896 fd = DetectFlowParse(NULL, "from_server,established,only_stream,a");
dc762cd4
JI
897 FAIL_IF_NOT_NULL(fd);
898 PASS;
9b4c0d05 899}
583c6861 900
9b4c0d05
WM
901/**
902 * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
903 */
ab1200fb 904static int DetectFlowTestParse20 (void)
8f1d7503 905{
9b4c0d05 906 DetectFlowData *fd = NULL;
d3a65fe1 907 fd = DetectFlowParse(NULL, "from_server,established,no_stream");
dc762cd4
JI
908 FAIL_IF_NULL(fd);
909 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
910 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
911 fd->flags & DETECT_FLOW_FLAG_NOSTREAM &&
912 fd->match_cnt == 3);
d3a65fe1 913 DetectFlowFree(NULL, fd);
dc762cd4 914 PASS;
9b4c0d05
WM
915}
916
583c6861
PR
917/**
918 * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
919 */
ab1200fb 920static int DetectFlowTestParseNocase20 (void)
8f1d7503 921{
583c6861 922 DetectFlowData *fd = NULL;
d3a65fe1 923 fd = DetectFlowParse(NULL, "FROM_SERVER,ESTABLISHED,NO_STREAM");
dc762cd4
JI
924 FAIL_IF_NULL(fd);
925 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
926 fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
927 fd->flags & DETECT_FLOW_FLAG_NOSTREAM &&
928 fd->match_cnt == 3);
d3a65fe1 929 DetectFlowFree(NULL, fd);
dc762cd4 930 PASS;
583c6861
PR
931}
932
9b4c0d05
WM
933/**
934 * \test DetectFlowTestParse21 is a test for an invalid opt between to valid opts
935 */
ab1200fb 936static int DetectFlowTestParse21 (void)
8f1d7503 937{
9b4c0d05 938 DetectFlowData *fd = NULL;
d3a65fe1 939 fd = DetectFlowParse(NULL, "from_server,a,no_stream");
dc762cd4
JI
940 FAIL_IF_NOT_NULL(fd);
941 PASS;
9b4c0d05
WM
942}
943
855726f3
AS
944static int DetectFlowSigTest01(void)
945{
855726f3
AS
946 uint8_t *buf = (uint8_t *)"supernovaduper";
947 uint16_t buflen = strlen((char *)buf);
7309c97e
VJ
948 ThreadVars th_v;
949 DecodeThreadVars dtv;
950 memset(&dtv, 0, sizeof(DecodeThreadVars));
951 memset(&th_v, 0, sizeof(th_v));
3470b07e 952
855726f3 953 Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
dc762cd4 954 FAIL_IF_NULL(p);
855726f3 955
ab1200fb 956 const char *sig1 = "alert tcp any any -> any any (msg:\"dummy\"; "
855726f3
AS
957 "content:\"nova\"; flow:no_stream; sid:1;)";
958
7309c97e 959 DetectEngineCtx *de_ctx = DetectEngineCtxInit();
dc762cd4 960 FAIL_IF_NULL(de_ctx);
855726f3
AS
961 de_ctx->flags |= DE_QUIET;
962
963 de_ctx->sig_list = SigInit(de_ctx, sig1);
dc762cd4 964 FAIL_IF_NULL(de_ctx->sig_list);
855726f3
AS
965
966 SigGroupBuild(de_ctx);
7309c97e 967 DetectEngineThreadCtx *det_ctx = NULL;
855726f3 968 DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
7309c97e 969 FAIL_IF_NULL(det_ctx);
855726f3
AS
970
971 SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
dc762cd4 972 FAIL_IF(PacketAlertCheck(p, 1) != 1);
855726f3 973
7309c97e
VJ
974 DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
975 DetectEngineCtxFree(de_ctx);
976 UTHFreePacket(p);
855726f3 977
dc762cd4 978 PASS;
855726f3 979}
571f56cf
JI
980
981/**
982 * \test Test parsing of the not_established keyword.
983 */
984static int DetectFlowTestParseNotEstablished(void)
985{
986 DetectFlowData *fd = NULL;
d3a65fe1 987 fd = DetectFlowParse(NULL, "not_established");
571f56cf
JI
988 FAIL_IF_NULL(fd);
989 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED);
d3a65fe1 990 DetectFlowFree(NULL, fd);
571f56cf
JI
991 PASS;
992}
993
8f56c234
JI
994/**
995 * \test Test parsing of the "no_frag" flow argument.
996 */
997static int DetectFlowTestParseNoFrag(void)
998{
999 DetectFlowData *fd = NULL;
d3a65fe1 1000 fd = DetectFlowParse(NULL, "no_frag");
8f56c234
JI
1001 FAIL_IF_NULL(fd);
1002 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
d3a65fe1 1003 DetectFlowFree(NULL, fd);
8f56c234
JI
1004 PASS;
1005}
1006
1007/**
1008 * \test Test parsing of the "only_frag" flow argument.
1009 */
1010static int DetectFlowTestParseOnlyFrag(void)
1011{
1012 DetectFlowData *fd = NULL;
d3a65fe1 1013 fd = DetectFlowParse(NULL, "only_frag");
8f56c234
JI
1014 FAIL_IF_NULL(fd);
1015 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
d3a65fe1 1016 DetectFlowFree(NULL, fd);
8f56c234
JI
1017 PASS;
1018}
1019
1020/**
1021 * \test Test that parsing of only_frag and no_frag together fails.
1022 */
1023static int DetectFlowTestParseNoFragOnlyFrag(void)
1024{
1025 DetectFlowData *fd = NULL;
d3a65fe1 1026 fd = DetectFlowParse(NULL, "no_frag,only_frag");
8f56c234
JI
1027 FAIL_IF_NOT_NULL(fd);
1028 PASS;
1029}
1030
1031/**
1032 * \test Test no_frag matching.
1033 */
1034static int DetectFlowTestNoFragMatch(void)
1035{
1036 uint32_t pflags = 0;
d3a65fe1 1037 DetectFlowData *fd = DetectFlowParse(NULL, "no_frag");
8f56c234
JI
1038 FAIL_IF_NULL(fd);
1039 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
1040 FAIL_IF_NOT(fd->match_cnt == 1);
1041 FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1042 pflags |= PKT_REBUILT_FRAGMENT;
1043 FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1044 PASS;
1045}
1046
1047/**
1048 * \test Test only_frag matching.
1049 */
1050static int DetectFlowTestOnlyFragMatch(void)
1051{
1052 uint32_t pflags = 0;
d3a65fe1 1053 DetectFlowData *fd = DetectFlowParse(NULL, "only_frag");
8f56c234
JI
1054 FAIL_IF_NULL(fd);
1055 FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
1056 FAIL_IF_NOT(fd->match_cnt == 1);
1057 FAIL_IF(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1058 pflags |= PKT_REBUILT_FRAGMENT;
1059 FAIL_IF_NOT(FlowMatch(pflags, 0, 0, fd->flags, fd->match_cnt));
1060 PASS;
1061}
1062
9b4c0d05
WM
1063/**
1064 * \brief this function registers unit tests for DetectFlow
1065 */
6ab323d3 1066static void DetectFlowRegisterTests(void)
8f1d7503 1067{
796dd522
JI
1068 UtRegisterTest("DetectFlowTestParse01", DetectFlowTestParse01);
1069 UtRegisterTest("DetectFlowTestParse02", DetectFlowTestParse02);
1070 UtRegisterTest("DetectFlowTestParse03", DetectFlowTestParse03);
1071 UtRegisterTest("DetectFlowTestParse04", DetectFlowTestParse04);
1072 UtRegisterTest("DetectFlowTestParse05", DetectFlowTestParse05);
1073 UtRegisterTest("DetectFlowTestParse06", DetectFlowTestParse06);
1074 UtRegisterTest("DetectFlowTestParse07", DetectFlowTestParse07);
1075 UtRegisterTest("DetectFlowTestParse08", DetectFlowTestParse08);
1076 UtRegisterTest("DetectFlowTestParse09", DetectFlowTestParse09);
1077 UtRegisterTest("DetectFlowTestParse10", DetectFlowTestParse10);
1078 UtRegisterTest("DetectFlowTestParse11", DetectFlowTestParse11);
1079 UtRegisterTest("DetectFlowTestParseNocase01", DetectFlowTestParseNocase01);
1080 UtRegisterTest("DetectFlowTestParseNocase02", DetectFlowTestParseNocase02);
1081 UtRegisterTest("DetectFlowTestParseNocase03", DetectFlowTestParseNocase03);
1082 UtRegisterTest("DetectFlowTestParseNocase04", DetectFlowTestParseNocase04);
1083 UtRegisterTest("DetectFlowTestParseNocase05", DetectFlowTestParseNocase05);
1084 UtRegisterTest("DetectFlowTestParseNocase06", DetectFlowTestParseNocase06);
1085 UtRegisterTest("DetectFlowTestParseNocase07", DetectFlowTestParseNocase07);
1086 UtRegisterTest("DetectFlowTestParseNocase08", DetectFlowTestParseNocase08);
1087 UtRegisterTest("DetectFlowTestParseNocase09", DetectFlowTestParseNocase09);
1088 UtRegisterTest("DetectFlowTestParseNocase10", DetectFlowTestParseNocase10);
1089 UtRegisterTest("DetectFlowTestParseNocase11", DetectFlowTestParseNocase11);
1090 UtRegisterTest("DetectFlowTestParse12", DetectFlowTestParse12);
1091 UtRegisterTest("DetectFlowTestParse13", DetectFlowTestParse13);
1092 UtRegisterTest("DetectFlowTestParse14", DetectFlowTestParse14);
1093 UtRegisterTest("DetectFlowTestParse15", DetectFlowTestParse15);
1094 UtRegisterTest("DetectFlowTestParse16", DetectFlowTestParse16);
1095 UtRegisterTest("DetectFlowTestParse17", DetectFlowTestParse17);
1096 UtRegisterTest("DetectFlowTestParse18", DetectFlowTestParse18);
1097 UtRegisterTest("DetectFlowTestParseNocase18", DetectFlowTestParseNocase18);
1098 UtRegisterTest("DetectFlowTestParse19", DetectFlowTestParse19);
1099 UtRegisterTest("DetectFlowTestParse20", DetectFlowTestParse20);
1100 UtRegisterTest("DetectFlowTestParseNocase20", DetectFlowTestParseNocase20);
1101 UtRegisterTest("DetectFlowTestParse21", DetectFlowTestParse21);
571f56cf
JI
1102 UtRegisterTest("DetectFlowTestParseNotEstablished",
1103 DetectFlowTestParseNotEstablished);
8f56c234
JI
1104 UtRegisterTest("DetectFlowTestParseNoFrag", DetectFlowTestParseNoFrag);
1105 UtRegisterTest("DetectFlowTestParseOnlyFrag",
1106 DetectFlowTestParseOnlyFrag);
1107 UtRegisterTest("DetectFlowTestParseNoFragOnlyFrag",
1108 DetectFlowTestParseNoFragOnlyFrag);
1109 UtRegisterTest("DetectFlowTestNoFragMatch", DetectFlowTestNoFragMatch);
1110 UtRegisterTest("DetectFlowTestOnlyFragMatch", DetectFlowTestOnlyFragMatch);
796dd522
JI
1111
1112 UtRegisterTest("DetectFlowSigTest01", DetectFlowSigTest01);
9b4c0d05 1113}
1eeb9669 1114#endif /* UNITTESTS */