Coverage Report

Created: 2025-07-23 07:29

/src/suricata/src/detect-flow.c
Line
Count
Source (jump to first uncovered line)
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
136k
{
96
136k
    uint8_t cnt = 0;
97
98
136k
    if ((dflags & DETECT_FLOW_FLAG_NO_FRAG) &&
99
136k
        (!(pflags & PKT_REBUILT_FRAGMENT))) {
100
0
        cnt++;
101
136k
    } else if ((dflags & DETECT_FLOW_FLAG_ONLY_FRAG) &&
102
136k
        (pflags & PKT_REBUILT_FRAGMENT)) {
103
0
        cnt++;
104
0
    }
105
106
136k
    if ((dflags & DETECT_FLOW_FLAG_TOSERVER) && (pflowflags & FLOW_PKT_TOSERVER)) {
107
15.0k
        cnt++;
108
121k
    } else if ((dflags & DETECT_FLOW_FLAG_TOCLIENT) && (pflowflags & FLOW_PKT_TOCLIENT)) {
109
3.23k
        cnt++;
110
3.23k
    }
111
112
136k
    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
122
        cnt++;
116
35.4k
    } else if (dflags & DETECT_FLOW_FLAG_STATELESS) {
117
21.7k
        cnt++;
118
21.7k
    }
119
120
136k
    return (match_cnt == cnt) ? 1 : 0;
121
136k
}
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
158k
{
137
158k
    SCEnter();
138
139
158k
    SCLogDebug("pkt %p", p);
140
141
158k
    if (p->flowflags & FLOW_PKT_TOSERVER) {
142
96.9k
        SCLogDebug("FLOW_PKT_TOSERVER");
143
96.9k
    } else if (p->flowflags & FLOW_PKT_TOCLIENT) {
144
61.6k
        SCLogDebug("FLOW_PKT_TOCLIENT");
145
61.6k
    }
146
147
158k
    if (p->flowflags & FLOW_PKT_ESTABLISHED) {
148
139k
        SCLogDebug("FLOW_PKT_ESTABLISHED");
149
139k
    }
150
151
158k
    const DetectFlowData *fd = (const DetectFlowData *)ctx;
152
153
158k
    const int ret = FlowMatch(p->flags, p->flowflags, fd->flags, fd->match_cnt);
154
158k
    SCLogDebug("returning %" PRId32 " fd->match_cnt %" PRId32 " fd->flags 0x%02X p->flowflags 0x%02X",
155
158k
        ret, fd->match_cnt, fd->flags, p->flowflags);
156
158k
    SCReturnInt(ret);
157
158k
}
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
392k
{
172
392k
    DetectFlowData *fd = NULL;
173
392k
    char *args[3] = {NULL,NULL,NULL};
174
392k
    int res = 0;
175
392k
    size_t pcre2len;
176
392k
    char str1[16] = "", str2[16] = "", str3[16] = "";
177
392k
    pcre2_match_data *match = NULL;
178
179
392k
    int ret = DetectParsePcreExec(&parse_regex, &match, flowstr, 0, 0);
180
392k
    if (ret < 1 || ret > 4) {
181
22.3k
        SCLogError("parse error, ret %" PRId32 ", string %s", ret, flowstr);
182
22.3k
        goto error;
183
22.3k
    }
184
185
370k
    if (ret > 1) {
186
370k
        pcre2len = sizeof(str1);
187
370k
        res = SC_Pcre2SubstringCopy(match, 1, (PCRE2_UCHAR8 *)str1, &pcre2len);
188
370k
        if (res < 0) {
189
739
            SCLogError("pcre2_substring_copy_bynumber failed");
190
739
            goto error;
191
739
        }
192
369k
        args[0] = (char *)str1;
193
194
369k
        if (ret > 2) {
195
165k
            pcre2len = sizeof(str2);
196
165k
            res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)str2, &pcre2len);
197
165k
            if (res < 0) {
198
99
                SCLogError("pcre2_substring_copy_bynumber failed");
199
99
                goto error;
200
99
            }
201
164k
            args[1] = (char *)str2;
202
164k
        }
203
369k
        if (ret > 3) {
204
1.95k
            pcre2len = sizeof(str3);
205
1.95k
            res = pcre2_substring_copy_bynumber(match, 3, (PCRE2_UCHAR8 *)str3, &pcre2len);
206
1.95k
            if (res < 0) {
207
585
                SCLogError("pcre2_substring_copy_bynumber failed");
208
585
                goto error;
209
585
            }
210
1.37k
            args[2] = (char *)str3;
211
1.37k
        }
212
369k
    }
213
214
368k
    fd = SCMalloc(sizeof(DetectFlowData));
215
368k
    if (unlikely(fd == NULL))
216
0
        goto error;
217
368k
    fd->flags = 0;
218
368k
    fd->match_cnt = 0;
219
220
888k
    for (int i = 0; i < (ret - 1); i++) {
221
531k
        if (args[i]) {
222
            /* inspect our options and set the flags */
223
531k
            if (strcasecmp(args[i], "established") == 0) {
224
281k
                if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
225
67
                    SCLogError("DETECT_FLOW_FLAG_ESTABLISHED flag is already set");
226
67
                    goto error;
227
281k
                } 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
281k
                } else if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
232
74
                    SCLogError("DETECT_FLOW_FLAG_STATELESS already set");
233
74
                    goto error;
234
74
                }
235
281k
                fd->flags |= DETECT_FLOW_FLAG_ESTABLISHED;
236
281k
                fd->match_cnt++;
237
281k
            } else if (strcasecmp(args[i], "not_established") == 0) {
238
946
                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
946
                } 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
946
                fd->flags |= DETECT_FLOW_FLAG_NOT_ESTABLISHED;
247
946
                fd->match_cnt++;
248
249k
            } else if (strcasecmp(args[i], "stateless") == 0) {
249
3.95k
                if (fd->flags & DETECT_FLOW_FLAG_STATELESS) {
250
84
                    SCLogError("DETECT_FLOW_FLAG_STATELESS flag is already set");
251
84
                    goto error;
252
3.87k
                } else if (fd->flags & DETECT_FLOW_FLAG_ESTABLISHED) {
253
3
                    SCLogError("cannot set DETECT_FLOW_FLAG_STATELESS, "
254
3
                               "DETECT_FLOW_FLAG_ESTABLISHED already set");
255
3
                    goto error;
256
3
                }
257
3.87k
                fd->flags |= DETECT_FLOW_FLAG_STATELESS;
258
3.87k
                fd->match_cnt++;
259
245k
            } else if (strcasecmp(args[i], "to_client") == 0 || strcasecmp(args[i], "from_server") == 0) {
260
54.1k
                if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
261
21
                    SCLogError("cannot set DETECT_FLOW_FLAG_TOCLIENT flag is already set");
262
21
                    goto error;
263
54.1k
                } else if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
264
93
                    SCLogError("cannot set to_client, DETECT_FLOW_FLAG_TOSERVER already set");
265
93
                    goto error;
266
93
                }
267
54.0k
                fd->flags |= DETECT_FLOW_FLAG_TOCLIENT;
268
54.0k
                fd->match_cnt++;
269
191k
            } else if (strcasecmp(args[i], "to_server") == 0 || strcasecmp(args[i], "from_client") == 0){
270
178k
                if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
271
433
                    SCLogError("cannot set DETECT_FLOW_FLAG_TOSERVER flag is already set");
272
433
                    goto error;
273
177k
                } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
274
21
                    SCLogError("cannot set to_server, DETECT_FLOW_FLAG_TO_CLIENT flag already set");
275
21
                    goto error;
276
21
                }
277
177k
                fd->flags |= DETECT_FLOW_FLAG_TOSERVER;
278
177k
                fd->match_cnt++;
279
177k
            } else if (strcasecmp(args[i], "no_frag") == 0) {
280
39
                if (fd->flags & DETECT_FLOW_FLAG_NO_FRAG) {
281
0
                    SCLogError("cannot set no_frag flag is already set");
282
0
                    goto error;
283
39
                } 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
38
                fd->flags |= DETECT_FLOW_FLAG_NO_FRAG;
288
38
                fd->match_cnt++;
289
12.8k
            } else if (strcasecmp(args[i], "only_frag") == 0) {
290
397
                if (fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG) {
291
2
                    SCLogError("cannot set only_frag flag is already set");
292
2
                    goto error;
293
395
                } 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
395
                fd->flags |= DETECT_FLOW_FLAG_ONLY_FRAG;
298
395
                fd->match_cnt++;
299
300
                /* special case: these only affect parsing, not matching */
301
302
12.4k
            } else if (strcasecmp(args[i], "only_stream") == 0) {
303
1.67k
                if (*parse_flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
304
0
                    SCLogError("cannot set only_stream flag is already set");
305
0
                    goto error;
306
1.67k
                } 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.67k
                *parse_flags |= DETECT_FLOW_FLAG_ONLYSTREAM;
312
10.7k
            } else if (strcasecmp(args[i], "no_stream") == 0) {
313
208
                if (*parse_flags & DETECT_FLOW_FLAG_NOSTREAM) {
314
1
                    SCLogError("cannot set no_stream flag is already set");
315
1
                    goto error;
316
207
                } 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
207
                *parse_flags |= DETECT_FLOW_FLAG_NOSTREAM;
322
10.5k
            } else {
323
10.5k
                SCLogError("invalid flow option \"%s\"", args[i]);
324
10.5k
                goto error;
325
10.5k
            }
326
531k
        }
327
531k
    }
328
357k
    pcre2_match_data_free(match);
329
357k
    return fd;
330
331
35.1k
error:
332
35.1k
    if (match) {
333
35.1k
        pcre2_match_data_free(match);
334
35.1k
    }
335
35.1k
    if (fd != NULL)
336
11.3k
        DetectFlowFree(de_ctx, fd);
337
35.1k
    return NULL;
338
339
368k
}
340
341
int DetectFlowSetupImplicit(Signature *s, uint32_t flags)
342
358k
{
343
716k
#define SIG_FLAG_BOTH (SIG_FLAG_TOSERVER|SIG_FLAG_TOCLIENT)
344
358k
    BUG_ON(flags == 0);
345
358k
    BUG_ON(flags & ~SIG_FLAG_BOTH);
346
358k
    BUG_ON((flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH);
347
348
358k
    SCLogDebug("want %08x", flags & SIG_FLAG_BOTH);
349
358k
    SCLogDebug("have %08x", s->flags & SIG_FLAG_BOTH);
350
351
358k
    if (flags & SIG_FLAG_TOSERVER) {
352
295k
        if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
353
            /* both is set if we just have 'flow:established' */
354
271k
            s->flags &= ~SIG_FLAG_TOCLIENT;
355
271k
        } else if (s->flags & SIG_FLAG_TOCLIENT) {
356
780
            return -1;
357
780
        }
358
294k
        s->flags |= SIG_FLAG_TOSERVER;
359
294k
    } else {
360
62.4k
        if ((s->flags & SIG_FLAG_BOTH) == SIG_FLAG_BOTH) {
361
            /* both is set if we just have 'flow:established' */
362
46.3k
            s->flags &= ~SIG_FLAG_TOSERVER;
363
46.3k
        } else if (s->flags & SIG_FLAG_TOSERVER) {
364
3.70k
            return -1;
365
3.70k
        }
366
58.6k
        s->flags |= SIG_FLAG_TOCLIENT;
367
58.6k
    }
368
353k
    return 0;
369
358k
#undef SIG_FLAG_BOTH
370
358k
}
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
246k
{
384
246k
    uint16_t parse_flags = 0;
385
386
    /* ensure only one flow option */
387
246k
    if (s->init_data->init_flags & SIG_FLAG_INIT_FLOW) {
388
1.09k
        SCLogError("A signature may have only one flow option.");
389
1.09k
        return -1;
390
1.09k
    }
391
392
245k
    DetectFlowData *fd = DetectFlowParse(de_ctx, flowstr, &parse_flags);
393
245k
    if (fd == NULL)
394
21.6k
        return -1;
395
396
224k
    bool appendsm = true;
397
    /* set the signature direction flags */
398
224k
    if (fd->flags & DETECT_FLOW_FLAG_TOSERVER) {
399
115k
        if (s->flags & SIG_FLAG_TXBOTHDIR) {
400
2
            SCLogError(
401
2
                    "rule %u means to use both directions, cannot specify a flow direction", s->id);
402
2
            goto error;
403
2
        }
404
115k
        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
115k
        s->flags |= SIG_FLAG_TOSERVER;
409
115k
    } else if (fd->flags & DETECT_FLOW_FLAG_TOCLIENT) {
410
38.7k
        if (s->flags & SIG_FLAG_TXBOTHDIR) {
411
2
            SCLogError(
412
2
                    "rule %u means to use both directions, cannot specify a flow direction", s->id);
413
2
            goto error;
414
2
        }
415
38.7k
        if (s->flags & SIG_FLAG_TOSERVER) {
416
1
            SCLogError("rule %u has flow to_client but a hook to_server", s->id);
417
1
            goto error;
418
1
        }
419
38.7k
        s->flags |= SIG_FLAG_TOCLIENT;
420
69.5k
    } else {
421
        /* if direction wasn't already set, e.g. by rule hook, assume both */
422
69.5k
        if ((s->flags & (SIG_FLAG_TOSERVER | SIG_FLAG_TOCLIENT)) == 0) {
423
69.5k
            s->flags |= SIG_FLAG_TOSERVER;
424
69.5k
            s->flags |= SIG_FLAG_TOCLIENT;
425
69.5k
        }
426
69.5k
    }
427
224k
    if (fd->flags == 0 || fd->flags == DETECT_FLOW_FLAG_TOSERVER ||
428
224k
            fd->flags == DETECT_FLOW_FLAG_TOCLIENT) {
429
        /* no direct flow is needed for just direction,
430
         * no sigmatch is needed either. */
431
57.6k
        appendsm = false;
432
166k
    } else {
433
166k
        s->init_data->init_flags |= SIG_FLAG_INIT_FLOW;
434
166k
    }
435
436
224k
    if (appendsm) {
437
166k
        if (SCSigMatchAppendSMToList(
438
166k
                    de_ctx, s, DETECT_FLOW, (SigMatchCtx *)fd, DETECT_SM_LIST_MATCH) == NULL) {
439
0
            goto error;
440
0
        }
441
166k
    } else {
442
57.6k
        DetectFlowFree(de_ctx, fd);
443
57.6k
    }
444
445
224k
    if (parse_flags & DETECT_FLOW_FLAG_ONLYSTREAM) {
446
1.67k
        s->flags |= (SIG_FLAG_REQUIRE_STREAM | SIG_FLAG_REQUIRE_STREAM_ONLY);
447
1.67k
    }
448
224k
    if (parse_flags & DETECT_FLOW_FLAG_NOSTREAM) {
449
203
        s->flags |= SIG_FLAG_REQUIRE_PACKET;
450
203
    }
451
224k
    return 0;
452
453
8
error:
454
8
    if (fd != NULL)
455
8
        DetectFlowFree(de_ctx, fd);
456
8
    return -1;
457
458
224k
}
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
368k
{
467
368k
    DetectFlowData *fd = (DetectFlowData *)ptr;
468
368k
    SCFree(fd);
469
368k
}
470
471
static void
472
PrefilterPacketFlowMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
473
23.7k
{
474
23.7k
    SCEnter();
475
476
23.7k
    const PrefilterPacketHeaderCtx *ctx = pectx;
477
478
23.7k
    if (!PrefilterPacketHeaderExtraMatch(ctx, p))
479
2.28k
        return;
480
481
21.4k
    if (FlowMatch(p->flags, p->flowflags, ctx->v1.u16[0], ctx->v1.u16[1])) {
482
21.4k
        SCLogDebug("match: adding sids");
483
21.4k
        PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
484
21.4k
    }
485
21.4k
    SCReturn;
486
23.7k
}
487
488
static void
489
PrefilterPacketFlowSet(PrefilterPacketHeaderValue *v, void *smctx)
490
5.53k
{
491
5.53k
    const DetectFlowData *fb = smctx;
492
5.53k
    v->u16[0] = fb->flags;
493
5.53k
    v->u16[1] = fb->match_cnt;
494
5.53k
}
495
496
static bool
497
PrefilterPacketFlowCompare(PrefilterPacketHeaderValue v, void *smctx)
498
3.18k
{
499
3.18k
    const DetectFlowData *fb = smctx;
500
3.18k
    if (v.u16[0] == fb->flags && v.u16[1] == fb->match_cnt) {
501
3.18k
        return true;
502
3.18k
    }
503
0
    return false;
504
3.18k
}
505
506
static int PrefilterSetupFlow(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
507
4.25k
{
508
4.25k
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLOW, 0, PrefilterPacketFlowSet,
509
4.25k
            PrefilterPacketFlowCompare, PrefilterPacketFlowMatch);
510
4.25k
}
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
    PASS;
552
}
553
554
/**
555
 * \test DetectFlowTestParse03 is a test for setting the stateless flow opt
556
 */
557
static int DetectFlowTestParse03 (void)
558
{
559
    uint16_t parsed_flags = 0;
560
    DetectFlowData *fd = DetectFlowParse(NULL, "stateless", &parsed_flags);
561
    FAIL_IF_NULL(fd);
562
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_STATELESS && fd->match_cnt == 1);
563
    DetectFlowFree(NULL, fd);
564
    PASS;
565
}
566
567
/**
568
 * \test DetectFlowTestParse04 is a test for setting the to_client flow opt
569
 */
570
static int DetectFlowTestParse04 (void)
571
{
572
    uint16_t parsed_flags = 0;
573
    DetectFlowData *fd = DetectFlowParse(NULL, "to_client", &parsed_flags);
574
    FAIL_IF_NULL(fd);
575
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
576
    DetectFlowFree(NULL, fd);
577
    PASS;
578
}
579
580
/**
581
 * \test DetectFlowTestParse05 is a test for setting the to_server flow opt
582
 */
583
static int DetectFlowTestParse05 (void)
584
{
585
    uint16_t parsed_flags = 0;
586
    DetectFlowData *fd = DetectFlowParse(NULL, "to_server", &parsed_flags);
587
    FAIL_IF_NULL(fd);
588
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
589
    DetectFlowFree(NULL, fd);
590
    PASS;
591
}
592
593
/**
594
 * \test DetectFlowTestParse06 is a test for setting the from_server flow opt
595
 */
596
static int DetectFlowTestParse06 (void)
597
{
598
    uint16_t parsed_flags = 0;
599
    DetectFlowData *fd = DetectFlowParse(NULL, "from_server", &parsed_flags);
600
    FAIL_IF_NULL(fd);
601
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
602
    DetectFlowFree(NULL, fd);
603
    PASS;
604
}
605
606
/**
607
 * \test DetectFlowTestParse07 is a test for setting the from_client flow opt
608
 */
609
static int DetectFlowTestParse07 (void)
610
{
611
    uint16_t parsed_flags = 0;
612
    DetectFlowData *fd = DetectFlowParse(NULL, "from_client", &parsed_flags);
613
    FAIL_IF_NULL(fd);
614
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
615
    DetectFlowFree(NULL, fd);
616
    PASS;
617
}
618
619
/**
620
 * \test DetectFlowTestParse08 is a test for setting the established,to_client flow opts
621
 */
622
static int DetectFlowTestParse08 (void)
623
{
624
    uint16_t parsed_flags = 0;
625
    DetectFlowData *fd = DetectFlowParse(NULL, "established,to_client", &parsed_flags);
626
    FAIL_IF_NULL(fd);
627
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 2);
628
    DetectFlowFree(NULL, fd);
629
    PASS;
630
}
631
632
/**
633
 * \test DetectFlowTestParse09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
634
 */
635
static int DetectFlowTestParse09 (void)
636
{
637
    uint16_t parsed_flags = 0;
638
    DetectFlowData *fd = DetectFlowParse(NULL, "to_client,stateless", &parsed_flags);
639
    FAIL_IF_NULL(fd);
640
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
641
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
642
        fd->match_cnt == 2);
643
    DetectFlowFree(NULL, fd);
644
    PASS;
645
}
646
647
/**
648
 * \test DetectFlowTestParse10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
649
 */
650
static int DetectFlowTestParse10 (void)
651
{
652
    uint16_t parsed_flags = 0;
653
    DetectFlowData *fd = DetectFlowParse(NULL, "from_server,stateless", &parsed_flags);
654
    FAIL_IF_NULL(fd);
655
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
656
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
657
        fd->match_cnt == 2);
658
    DetectFlowFree(NULL, fd);
659
    PASS;
660
}
661
662
/**
663
 * \test DetectFlowTestParse11 is a test for setting the from_server,stateless flow opts with spaces all around
664
 */
665
static int DetectFlowTestParse11 (void)
666
{
667
    uint16_t parsed_flags = 0;
668
    DetectFlowData *fd = DetectFlowParse(NULL, " from_server , stateless ", &parsed_flags);
669
    FAIL_IF_NULL(fd);
670
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
671
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
672
        fd->match_cnt == 2);
673
    DetectFlowFree(NULL, fd);
674
    PASS;
675
}
676
677
/**
678
 * \test DetectFlowTestParseNocase01 is a test to make sure that we return "something"
679
 *  when given valid flow opt
680
 */
681
static int DetectFlowTestParseNocase01 (void)
682
{
683
    uint16_t parsed_flags = 0;
684
    DetectFlowData *fd = DetectFlowParse(NULL, "ESTABLISHED", &parsed_flags);
685
    FAIL_IF_NULL(fd);
686
    DetectFlowFree(NULL, fd);
687
    PASS;
688
}
689
690
/**
691
 * \test DetectFlowTestParseNocase02 is a test for setting the established flow opt
692
 */
693
static int DetectFlowTestParseNocase02 (void)
694
{
695
    uint16_t parsed_flags = 0;
696
    DetectFlowData *fd = DetectFlowParse(NULL, "ESTABLISHED", &parsed_flags);
697
    FAIL_IF_NULL(fd);
698
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_ESTABLISHED &&
699
        fd->match_cnt == 1);
700
    DetectFlowFree(NULL, fd);
701
    PASS;
702
}
703
704
/**
705
 * \test DetectFlowTestParseNocase03 is a test for setting the stateless flow opt
706
 */
707
static int DetectFlowTestParseNocase03 (void)
708
{
709
    uint16_t parsed_flags = 0;
710
    DetectFlowData *fd = DetectFlowParse(NULL, "STATELESS", &parsed_flags);
711
    FAIL_IF_NULL(fd);
712
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_STATELESS && fd->match_cnt == 1);
713
    DetectFlowFree(NULL, fd);
714
    PASS;
715
}
716
717
/**
718
 * \test DetectFlowTestParseNocase04 is a test for setting the to_client flow opt
719
 */
720
static int DetectFlowTestParseNocase04 (void)
721
{
722
    uint16_t parsed_flags = 0;
723
    DetectFlowData *fd = DetectFlowParse(NULL, "TO_CLIENT", &parsed_flags);
724
    FAIL_IF_NULL(fd);
725
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
726
    DetectFlowFree(NULL, fd);
727
    PASS;
728
}
729
730
/**
731
 * \test DetectFlowTestParseNocase05 is a test for setting the to_server flow opt
732
 */
733
static int DetectFlowTestParseNocase05 (void)
734
{
735
    uint16_t parsed_flags = 0;
736
    DetectFlowData *fd = DetectFlowParse(NULL, "TO_SERVER", &parsed_flags);
737
    FAIL_IF_NULL(fd);
738
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
739
    DetectFlowFree(NULL, fd);
740
    PASS;
741
}
742
743
/**
744
 * \test DetectFlowTestParseNocase06 is a test for setting the from_server flow opt
745
 */
746
static int DetectFlowTestParseNocase06 (void)
747
{
748
    uint16_t parsed_flags = 0;
749
    DetectFlowData *fd = DetectFlowParse(NULL, "FROM_SERVER", &parsed_flags);
750
    FAIL_IF_NULL(fd);
751
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOCLIENT && fd->match_cnt == 1);
752
    DetectFlowFree(NULL, fd);
753
    PASS;
754
}
755
756
/**
757
 * \test DetectFlowTestParseNocase07 is a test for setting the from_client flow opt
758
 */
759
static int DetectFlowTestParseNocase07 (void)
760
{
761
    uint16_t parsed_flags = 0;
762
    DetectFlowData *fd = DetectFlowParse(NULL, "FROM_CLIENT", &parsed_flags);
763
    FAIL_IF_NULL(fd);
764
    FAIL_IF_NOT(fd->flags == DETECT_FLOW_FLAG_TOSERVER && fd->match_cnt == 1);
765
    DetectFlowFree(NULL, fd);
766
    PASS;
767
}
768
769
/**
770
 * \test DetectFlowTestParseNocase08 is a test for setting the established,to_client flow opts
771
 */
772
static int DetectFlowTestParseNocase08 (void)
773
{
774
    uint16_t parsed_flags = 0;
775
    DetectFlowData *fd = DetectFlowParse(NULL, "ESTABLISHED,TO_CLIENT", &parsed_flags);
776
    FAIL_IF_NULL(fd);
777
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED &&
778
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
779
        fd->match_cnt == 2);
780
    DetectFlowFree(NULL, fd);
781
    PASS;
782
}
783
784
/**
785
 * \test DetectFlowTestParseNocase09 is a test for setting the to_client,stateless flow opts (order of state,dir reversed)
786
 */
787
static int DetectFlowTestParseNocase09 (void)
788
{
789
    uint16_t parsed_flags = 0;
790
    DetectFlowData *fd = DetectFlowParse(NULL, "TO_CLIENT,STATELESS", &parsed_flags);
791
    FAIL_IF_NULL(fd);
792
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
793
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
794
        fd->match_cnt == 2);
795
    DetectFlowFree(NULL, fd);
796
    PASS;
797
}
798
799
/**
800
 * \test DetectFlowTestParseNocase10 is a test for setting the from_server,stateless flow opts (order of state,dir reversed)
801
 */
802
static int DetectFlowTestParseNocase10 (void)
803
{
804
    uint16_t parsed_flags = 0;
805
    DetectFlowData *fd = DetectFlowParse(NULL, "FROM_SERVER,STATELESS", &parsed_flags);
806
    FAIL_IF_NULL(fd);
807
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
808
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
809
        fd->match_cnt == 2);
810
    DetectFlowFree(NULL, fd);
811
    PASS;
812
}
813
814
/**
815
 * \test DetectFlowTestParseNocase11 is a test for setting the from_server,stateless flow opts with spaces all around
816
 */
817
static int DetectFlowTestParseNocase11 (void)
818
{
819
    uint16_t parsed_flags = 0;
820
    DetectFlowData *fd = DetectFlowParse(NULL, " FROM_SERVER , STATELESS ", &parsed_flags);
821
    FAIL_IF_NULL(fd);
822
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_STATELESS &&
823
        fd->flags & DETECT_FLOW_FLAG_TOCLIENT &&
824
        fd->match_cnt == 2);
825
    DetectFlowFree(NULL, fd);
826
    PASS;
827
}
828
829
/**
830
 * \test DetectFlowTestParse12 is a test for setting an invalid separator :
831
 */
832
static int DetectFlowTestParse12 (void)
833
{
834
    uint16_t parsed_flags = 0;
835
    DetectFlowData *fd = DetectFlowParse(NULL, "from_server:stateless", &parsed_flags);
836
    FAIL_IF_NOT_NULL(fd);
837
    PASS;
838
}
839
840
/**
841
 * \test DetectFlowTestParse13 is a test for an invalid option
842
 */
843
static int DetectFlowTestParse13 (void)
844
{
845
    uint16_t parsed_flags = 0;
846
    DetectFlowData *fd = DetectFlowParse(NULL, "invalidoptiontest", &parsed_flags);
847
    FAIL_IF_NOT_NULL(fd);
848
    PASS;
849
}
850
851
/**
852
 * \test DetectFlowTestParse14 is a test for a empty option
853
 */
854
static int DetectFlowTestParse14 (void)
855
{
856
    uint16_t parsed_flags = 0;
857
    DetectFlowData *fd = DetectFlowParse(NULL, "", &parsed_flags);
858
    FAIL_IF_NOT_NULL(fd);
859
    PASS;
860
}
861
862
/**
863
 * \test DetectFlowTestParse15 is a test for an invalid combo of options established,stateless
864
 */
865
static int DetectFlowTestParse15 (void)
866
{
867
    uint16_t parsed_flags = 0;
868
    DetectFlowData *fd = DetectFlowParse(NULL, "established,stateless", &parsed_flags);
869
    FAIL_IF_NOT_NULL(fd);
870
    PASS;
871
}
872
873
/**
874
 * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,to_server
875
 */
876
static int DetectFlowTestParse16 (void)
877
{
878
    uint16_t parsed_flags = 0;
879
    DetectFlowData *fd = DetectFlowParse(NULL, "to_client,to_server", &parsed_flags);
880
    FAIL_IF_NOT_NULL(fd);
881
    PASS;
882
}
883
884
/**
885
 * \test DetectFlowTestParse16 is a test for an invalid combo of options to_client,from_server
886
 * flowbit flags are the same
887
 */
888
static int DetectFlowTestParse17 (void)
889
{
890
    uint16_t parsed_flags = 0;
891
    DetectFlowData *fd = DetectFlowParse(NULL, "to_client,from_server", &parsed_flags);
892
    FAIL_IF_NOT_NULL(fd);
893
    PASS;
894
}
895
896
/**
897
 * \test DetectFlowTestParse18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
898
 */
899
static int DetectFlowTestParse18 (void)
900
{
901
    uint16_t parsed_flags = 0;
902
    DetectFlowData *fd =
903
            DetectFlowParse(NULL, "from_server,established,only_stream", &parsed_flags);
904
    FAIL_IF_NULL(fd);
905
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT);
906
    FAIL_IF_NOT(parsed_flags == DETECT_FLOW_FLAG_ONLYSTREAM);
907
    FAIL_IF_NOT(fd->match_cnt == 2);
908
    DetectFlowFree(NULL, fd);
909
    PASS;
910
}
911
912
/**
913
 * \test DetectFlowTestParseNocase18 is a test for setting the from_server,stateless,only_stream flow opts (order of state,dir reversed)
914
 */
915
static int DetectFlowTestParseNocase18 (void)
916
{
917
    uint16_t parsed_flags = 0;
918
    DetectFlowData *fd =
919
            DetectFlowParse(NULL, "FROM_SERVER,ESTABLISHED,ONLY_STREAM", &parsed_flags);
920
    FAIL_IF_NULL(fd);
921
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT);
922
    FAIL_IF_NOT(parsed_flags == DETECT_FLOW_FLAG_ONLYSTREAM);
923
    FAIL_IF_NOT(fd->match_cnt == 2);
924
    DetectFlowFree(NULL, fd);
925
    PASS;
926
}
927
928
929
/**
930
 * \test DetectFlowTestParse19 is a test for one to many options passed to DetectFlowParse
931
 */
932
static int DetectFlowTestParse19 (void)
933
{
934
    uint16_t parsed_flags = 0;
935
    DetectFlowData *fd =
936
            DetectFlowParse(NULL, "from_server,established,only_stream,a", &parsed_flags);
937
    FAIL_IF_NOT_NULL(fd);
938
    PASS;
939
}
940
941
/**
942
 * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
943
 */
944
static int DetectFlowTestParse20 (void)
945
{
946
    uint16_t parsed_flags = 0;
947
    DetectFlowData *fd = DetectFlowParse(NULL, "from_server,established,no_stream", &parsed_flags);
948
    FAIL_IF_NULL(fd);
949
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT);
950
    FAIL_IF_NOT(parsed_flags == DETECT_FLOW_FLAG_NOSTREAM);
951
    FAIL_IF_NOT(fd->match_cnt == 2);
952
    DetectFlowFree(NULL, fd);
953
    PASS;
954
}
955
956
/**
957
 * \test DetectFlowTestParse20 is a test for setting from_server, established, no_stream
958
 */
959
static int DetectFlowTestParseNocase20 (void)
960
{
961
    uint16_t parsed_flags = 0;
962
    DetectFlowData *fd = DetectFlowParse(NULL, "FROM_SERVER,ESTABLISHED,NO_STREAM", &parsed_flags);
963
    FAIL_IF_NULL(fd);
964
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ESTABLISHED && fd->flags & DETECT_FLOW_FLAG_TOCLIENT);
965
    FAIL_IF_NOT(parsed_flags == DETECT_FLOW_FLAG_NOSTREAM);
966
    FAIL_IF_NOT(fd->match_cnt == 2);
967
    DetectFlowFree(NULL, fd);
968
    PASS;
969
}
970
971
/**
972
 * \test DetectFlowTestParse21 is a test for an invalid opt between to valid opts
973
 */
974
static int DetectFlowTestParse21 (void)
975
{
976
    uint16_t parsed_flags = 0;
977
    DetectFlowData *fd = DetectFlowParse(NULL, "from_server,a,no_stream", &parsed_flags);
978
    FAIL_IF_NOT_NULL(fd);
979
    PASS;
980
}
981
982
/**
983
 * \test DetectFlowTestParse22 is a test for setting the established,not_established flow opts both
984
 */
985
static int DetectFlowTestParse22(void)
986
{
987
    uint16_t parsed_flags = 0;
988
    DetectFlowData *fd = DetectFlowParse(NULL, "established,not_established", &parsed_flags);
989
    FAIL_IF_NOT_NULL(fd);
990
    fd = DetectFlowParse(NULL, "not_established,established", &parsed_flags);
991
    FAIL_IF_NOT_NULL(fd);
992
    PASS;
993
}
994
995
static int DetectFlowSigTest01(void)
996
{
997
    uint8_t *buf = (uint8_t *)"supernovaduper";
998
    uint16_t buflen = strlen((char *)buf);
999
    ThreadVars th_v;
1000
    DecodeThreadVars dtv;
1001
    memset(&dtv, 0, sizeof(DecodeThreadVars));
1002
    memset(&th_v, 0, sizeof(th_v));
1003
1004
    Packet *p = UTHBuildPacket(buf, buflen, IPPROTO_TCP);
1005
    FAIL_IF_NULL(p);
1006
1007
    const char *sig1 = "alert tcp any any -> any any (msg:\"dummy\"; "
1008
        "content:\"nova\"; flow:no_stream; sid:1;)";
1009
1010
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1011
    FAIL_IF_NULL(de_ctx);
1012
    de_ctx->flags |= DE_QUIET;
1013
1014
    de_ctx->sig_list = SigInit(de_ctx, sig1);
1015
    FAIL_IF_NULL(de_ctx->sig_list);
1016
1017
    SigGroupBuild(de_ctx);
1018
    DetectEngineThreadCtx *det_ctx = NULL;
1019
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1020
    FAIL_IF_NULL(det_ctx);
1021
1022
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1023
    FAIL_IF(PacketAlertCheck(p, 1) != 1);
1024
1025
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1026
    DetectEngineCtxFree(de_ctx);
1027
    UTHFreePacket(p);
1028
1029
    PASS;
1030
}
1031
1032
/**
1033
 * \test Test parsing of the not_established keyword.
1034
 */
1035
static int DetectFlowTestParseNotEstablished(void)
1036
{
1037
    uint16_t parsed_flags = 0;
1038
    DetectFlowData *fd = DetectFlowParse(NULL, "not_established", &parsed_flags);
1039
    FAIL_IF_NULL(fd);
1040
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NOT_ESTABLISHED);
1041
    DetectFlowFree(NULL, fd);
1042
    PASS;
1043
}
1044
1045
/**
1046
 * \test Test parsing of the "no_frag" flow argument.
1047
 */
1048
static int DetectFlowTestParseNoFrag(void)
1049
{
1050
    uint16_t parsed_flags = 0;
1051
    DetectFlowData *fd = DetectFlowParse(NULL, "no_frag", &parsed_flags);
1052
    FAIL_IF_NULL(fd);
1053
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
1054
    DetectFlowFree(NULL, fd);
1055
    PASS;
1056
}
1057
1058
/**
1059
 * \test Test parsing of the "only_frag" flow argument.
1060
 */
1061
static int DetectFlowTestParseOnlyFrag(void)
1062
{
1063
    uint16_t parsed_flags = 0;
1064
    DetectFlowData *fd = DetectFlowParse(NULL, "only_frag", &parsed_flags);
1065
    FAIL_IF_NULL(fd);
1066
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
1067
    DetectFlowFree(NULL, fd);
1068
    PASS;
1069
}
1070
1071
/**
1072
 * \test Test that parsing of only_frag and no_frag together fails.
1073
 */
1074
static int DetectFlowTestParseNoFragOnlyFrag(void)
1075
{
1076
    uint16_t parsed_flags = 0;
1077
    DetectFlowData *fd = DetectFlowParse(NULL, "no_frag,only_frag", &parsed_flags);
1078
    FAIL_IF_NOT_NULL(fd);
1079
    PASS;
1080
}
1081
1082
/**
1083
 * \test Test no_frag matching.
1084
 */
1085
static int DetectFlowTestNoFragMatch(void)
1086
{
1087
    uint16_t parsed_flags = 0;
1088
    uint32_t pflags = 0;
1089
    DetectFlowData *fd = DetectFlowParse(NULL, "no_frag", &parsed_flags);
1090
    FAIL_IF_NULL(fd);
1091
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_NO_FRAG);
1092
    FAIL_IF_NOT(fd->match_cnt == 1);
1093
    FAIL_IF_NOT(FlowMatch(pflags, 0, fd->flags, fd->match_cnt));
1094
    pflags |= PKT_REBUILT_FRAGMENT;
1095
    FAIL_IF(FlowMatch(pflags, 0, fd->flags, fd->match_cnt));
1096
    PASS;
1097
}
1098
1099
/**
1100
 * \test Test only_frag matching.
1101
 */
1102
static int DetectFlowTestOnlyFragMatch(void)
1103
{
1104
    uint16_t parsed_flags = 0;
1105
    uint32_t pflags = 0;
1106
    DetectFlowData *fd = DetectFlowParse(NULL, "only_frag", &parsed_flags);
1107
    FAIL_IF_NULL(fd);
1108
    FAIL_IF_NOT(fd->flags & DETECT_FLOW_FLAG_ONLY_FRAG);
1109
    FAIL_IF_NOT(fd->match_cnt == 1);
1110
    FAIL_IF(FlowMatch(pflags, 0, fd->flags, fd->match_cnt));
1111
    pflags |= PKT_REBUILT_FRAGMENT;
1112
    FAIL_IF_NOT(FlowMatch(pflags, 0, fd->flags, fd->match_cnt));
1113
    PASS;
1114
}
1115
1116
/**
1117
 * \brief this function registers unit tests for DetectFlow
1118
 */
1119
static void DetectFlowRegisterTests(void)
1120
{
1121
    UtRegisterTest("DetectFlowTestParse01", DetectFlowTestParse01);
1122
    UtRegisterTest("DetectFlowTestParse02", DetectFlowTestParse02);
1123
    UtRegisterTest("DetectFlowTestParse03", DetectFlowTestParse03);
1124
    UtRegisterTest("DetectFlowTestParse04", DetectFlowTestParse04);
1125
    UtRegisterTest("DetectFlowTestParse05", DetectFlowTestParse05);
1126
    UtRegisterTest("DetectFlowTestParse06", DetectFlowTestParse06);
1127
    UtRegisterTest("DetectFlowTestParse07", DetectFlowTestParse07);
1128
    UtRegisterTest("DetectFlowTestParse08", DetectFlowTestParse08);
1129
    UtRegisterTest("DetectFlowTestParse09", DetectFlowTestParse09);
1130
    UtRegisterTest("DetectFlowTestParse10", DetectFlowTestParse10);
1131
    UtRegisterTest("DetectFlowTestParse11", DetectFlowTestParse11);
1132
    UtRegisterTest("DetectFlowTestParseNocase01", DetectFlowTestParseNocase01);
1133
    UtRegisterTest("DetectFlowTestParseNocase02", DetectFlowTestParseNocase02);
1134
    UtRegisterTest("DetectFlowTestParseNocase03", DetectFlowTestParseNocase03);
1135
    UtRegisterTest("DetectFlowTestParseNocase04", DetectFlowTestParseNocase04);
1136
    UtRegisterTest("DetectFlowTestParseNocase05", DetectFlowTestParseNocase05);
1137
    UtRegisterTest("DetectFlowTestParseNocase06", DetectFlowTestParseNocase06);
1138
    UtRegisterTest("DetectFlowTestParseNocase07", DetectFlowTestParseNocase07);
1139
    UtRegisterTest("DetectFlowTestParseNocase08", DetectFlowTestParseNocase08);
1140
    UtRegisterTest("DetectFlowTestParseNocase09", DetectFlowTestParseNocase09);
1141
    UtRegisterTest("DetectFlowTestParseNocase10", DetectFlowTestParseNocase10);
1142
    UtRegisterTest("DetectFlowTestParseNocase11", DetectFlowTestParseNocase11);
1143
    UtRegisterTest("DetectFlowTestParse12", DetectFlowTestParse12);
1144
    UtRegisterTest("DetectFlowTestParse13", DetectFlowTestParse13);
1145
    UtRegisterTest("DetectFlowTestParse14", DetectFlowTestParse14);
1146
    UtRegisterTest("DetectFlowTestParse15", DetectFlowTestParse15);
1147
    UtRegisterTest("DetectFlowTestParse16", DetectFlowTestParse16);
1148
    UtRegisterTest("DetectFlowTestParse17", DetectFlowTestParse17);
1149
    UtRegisterTest("DetectFlowTestParse18", DetectFlowTestParse18);
1150
    UtRegisterTest("DetectFlowTestParseNocase18", DetectFlowTestParseNocase18);
1151
    UtRegisterTest("DetectFlowTestParse19", DetectFlowTestParse19);
1152
    UtRegisterTest("DetectFlowTestParse20", DetectFlowTestParse20);
1153
    UtRegisterTest("DetectFlowTestParseNocase20", DetectFlowTestParseNocase20);
1154
    UtRegisterTest("DetectFlowTestParse21", DetectFlowTestParse21);
1155
    UtRegisterTest("DetectFlowTestParse22", DetectFlowTestParse22);
1156
    UtRegisterTest("DetectFlowTestParseNotEstablished",
1157
        DetectFlowTestParseNotEstablished);
1158
    UtRegisterTest("DetectFlowTestParseNoFrag", DetectFlowTestParseNoFrag);
1159
    UtRegisterTest("DetectFlowTestParseOnlyFrag",
1160
        DetectFlowTestParseOnlyFrag);
1161
    UtRegisterTest("DetectFlowTestParseNoFragOnlyFrag",
1162
        DetectFlowTestParseNoFragOnlyFrag);
1163
    UtRegisterTest("DetectFlowTestNoFragMatch", DetectFlowTestNoFragMatch);
1164
    UtRegisterTest("DetectFlowTestOnlyFragMatch", DetectFlowTestOnlyFragMatch);
1165
1166
    UtRegisterTest("DetectFlowSigTest01", DetectFlowSigTest01);
1167
}
1168
#endif /* UNITTESTS */