Coverage Report

Created: 2025-11-16 07:09

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