Coverage Report

Created: 2026-08-14 07:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-tcp-flags.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 Breno Silva <breno.silva@gmail.com>
22
 *
23
 * Implements the flags keyword
24
 */
25
26
#include "suricata-common.h"
27
#include "suricata.h"
28
#include "decode.h"
29
30
#include "detect.h"
31
#include "detect-parse.h"
32
#include "detect-engine-prefilter.h"
33
#include "detect-engine-prefilter-common.h"
34
35
#include "flow-var.h"
36
#include "decode-events.h"
37
38
#include "detect-tcp-flags.h"
39
#include "util-unittest.h"
40
41
#include "util-debug.h"
42
43
/**
44
 *  Regex (by Brian Rectanus)
45
 *  flags: [!+*](SAPRFU120)[,SAPRFU12]
46
 */
47
74
#define PARSE_REGEX "^\\s*(?:([\\+\\*!]))?\\s*([SAPRFU120CE\\+\\*!]+)(?:\\s*,\\s*([SAPRFU12CE]+))?\\s*$"
48
49
/**
50
 * Flags args[0] *(3) +(2) !(1)
51
 *
52
 */
53
54
68.7k
#define MODIFIER_NOT  1
55
13.2k
#define MODIFIER_PLUS 2
56
2.21k
#define MODIFIER_ANY  3
57
58
static DetectParseRegex parse_regex;
59
60
static int DetectFlagsMatch (DetectEngineThreadCtx *, Packet *,
61
        const Signature *, const SigMatchCtx *);
62
static int DetectFlagsSetup (DetectEngineCtx *, Signature *, const char *);
63
static void DetectFlagsFree(DetectEngineCtx *, void *);
64
65
static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s);
66
static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh);
67
#ifdef UNITTESTS
68
static void FlagsRegisterTests(void);
69
#endif
70
71
/**
72
 * \brief Registration function for flags: keyword
73
 */
74
75
void DetectFlagsRegister (void)
76
74
{
77
74
    sigmatch_table[DETECT_FLAGS].name = "tcp.flags";
78
74
    sigmatch_table[DETECT_FLAGS].alias = "flags";
79
74
    sigmatch_table[DETECT_FLAGS].desc = "detect which flags are set in the TCP header";
80
74
    sigmatch_table[DETECT_FLAGS].url = "/rules/header-keywords.html#tcp-flags";
81
74
    sigmatch_table[DETECT_FLAGS].Match = DetectFlagsMatch;
82
74
    sigmatch_table[DETECT_FLAGS].Setup = DetectFlagsSetup;
83
74
    sigmatch_table[DETECT_FLAGS].Free  = DetectFlagsFree;
84
#ifdef UNITTESTS
85
    sigmatch_table[DETECT_FLAGS].RegisterTests = FlagsRegisterTests;
86
#endif
87
74
    sigmatch_table[DETECT_FLAGS].SupportsPrefilter = PrefilterTcpFlagsIsPrefilterable;
88
74
    sigmatch_table[DETECT_FLAGS].SetupPrefilter = PrefilterSetupTcpFlags;
89
90
74
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
91
74
}
92
93
static inline int FlagsMatch(const uint8_t pflags, const uint8_t modifier,
94
                             const uint8_t dflags, const uint8_t iflags)
95
40.5k
{
96
40.5k
    if (!dflags && pflags) {
97
39.2k
        if(modifier == MODIFIER_NOT) {
98
1.34k
            SCReturnInt(1);
99
1.34k
        }
100
101
39.2k
        SCReturnInt(0);
102
39.2k
    }
103
104
1.25k
    const uint8_t flags = pflags & iflags;
105
106
1.25k
    switch (modifier) {
107
0
        case MODIFIER_ANY:
108
0
            if ((flags & dflags) > 0) {
109
0
                SCReturnInt(1);
110
0
            }
111
0
            SCReturnInt(0);
112
113
9
        case MODIFIER_PLUS:
114
9
            if (((flags & dflags) == dflags)) {
115
0
                SCReturnInt(1);
116
0
            }
117
9
            SCReturnInt(0);
118
119
404
        case MODIFIER_NOT:
120
404
            if ((flags & dflags) != dflags) {
121
176
                SCReturnInt(1);
122
176
            }
123
404
            SCReturnInt(0);
124
125
843
        default:
126
843
            SCLogDebug("flags %"PRIu8" and de->flags %"PRIu8"", flags, dflags);
127
843
            if (flags == dflags) {
128
410
                SCReturnInt(1);
129
410
            }
130
1.25k
    }
131
132
1.25k
    SCReturnInt(0);
133
1.25k
}
134
135
/**
136
 * \internal
137
 * \brief This function is used to match flags on a packet with those passed via flags:
138
 *
139
 * \param t pointer to thread vars
140
 * \param det_ctx pointer to the pattern matcher thread
141
 * \param p pointer to the current packet
142
 * \param s pointer to the Signature
143
 * \param m pointer to the sigmatch
144
 *
145
 * \retval 0 no match
146
 * \retval 1 match
147
 */
148
static int DetectFlagsMatch (DetectEngineThreadCtx *det_ctx, Packet *p,
149
        const Signature *s, const SigMatchCtx *ctx)
150
41.4k
{
151
41.4k
    SCEnter();
152
153
41.4k
    if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
154
936
        SCReturnInt(0);
155
936
    }
156
157
40.4k
    const DetectFlagsData *de = (const DetectFlagsData *)ctx;
158
40.4k
    const uint8_t flags = p->tcph->th_flags;
159
160
40.4k
    return FlagsMatch(flags, de->modifier, de->flags, de->ignored_flags);
161
41.4k
}
162
163
/**
164
 * \internal
165
 * \brief This function is used to parse flags options passed via flags: keyword
166
 *
167
 * \param rawstr Pointer to the user provided flags options
168
 *
169
 * \retval de pointer to DetectFlagsData on success
170
 * \retval NULL on failure
171
 */
172
static DetectFlagsData *DetectFlagsParse (const char *rawstr)
173
28.3k
{
174
28.3k
    SCEnter();
175
176
28.3k
    int found = 0, ignore = 0;
177
28.3k
    char *ptr;
178
28.3k
    DetectFlagsData *de = NULL;
179
180
28.3k
    char arg1[16] = "";
181
28.3k
    char arg2[16] = "";
182
28.3k
    char arg3[16] = "";
183
184
28.3k
    pcre2_match_data *match = NULL;
185
28.3k
    int ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
186
28.3k
    SCLogDebug("input '%s', pcre said %d", rawstr, ret);
187
28.3k
    if (ret < 3) {
188
1.21k
        SCLogError("pcre match failed");
189
1.21k
        goto error;
190
1.21k
    }
191
192
27.0k
    size_t pcre2len = sizeof(arg1);
193
27.0k
    int res = SC_Pcre2SubstringCopy(match, 1, (PCRE2_UCHAR8 *)arg1, &pcre2len);
194
27.0k
    if (res < 0) {
195
0
        SCLogError("pcre2_substring_copy_bynumber failed");
196
0
        goto error;
197
0
    }
198
27.0k
    if (ret >= 2) {
199
27.0k
        pcre2len = sizeof(arg2);
200
27.0k
        res = pcre2_substring_copy_bynumber(match, 2, (PCRE2_UCHAR8 *)arg2, &pcre2len);
201
27.0k
        if (res < 0) {
202
617
            SCLogError("pcre2_substring_copy_bynumber failed");
203
617
            goto error;
204
617
        }
205
27.0k
    }
206
26.4k
    if (ret >= 3) {
207
26.4k
        pcre2len = sizeof(arg3);
208
26.4k
        res = SC_Pcre2SubstringCopy(match, 3, (PCRE2_UCHAR8 *)arg3, &pcre2len);
209
26.4k
        if (res < 0) {
210
2.55k
            SCLogError("pcre2_substring_copy_bynumber failed");
211
2.55k
            goto error;
212
2.55k
        }
213
26.4k
    }
214
23.9k
    SCLogDebug("args '%s', '%s', '%s'", arg1, arg2, arg3);
215
216
23.9k
    if (strlen(arg2) == 0) {
217
0
        SCLogDebug("empty argument");
218
0
        goto error;
219
0
    }
220
221
23.9k
    de = SCMalloc(sizeof(DetectFlagsData));
222
23.9k
    if (unlikely(de == NULL))
223
0
        goto error;
224
23.9k
    memset(de, 0, sizeof(DetectFlagsData));
225
23.9k
    de->ignored_flags = 0xff;
226
227
    /** First parse args1 */
228
23.9k
    ptr = arg1;
229
36.9k
    while (*ptr != '\0') {
230
12.9k
        switch (*ptr) {
231
0
            case 'S':
232
0
            case 's':
233
0
                de->flags |= TH_SYN;
234
0
                found++;
235
0
                break;
236
0
            case 'A':
237
0
            case 'a':
238
0
                de->flags |= TH_ACK;
239
0
                found++;
240
0
                break;
241
0
            case 'F':
242
0
            case 'f':
243
0
                de->flags |= TH_FIN;
244
0
                found++;
245
0
                break;
246
0
            case 'R':
247
0
            case 'r':
248
0
                de->flags |= TH_RST;
249
0
                found++;
250
0
                break;
251
0
            case 'P':
252
0
            case 'p':
253
0
                de->flags |= TH_PUSH;
254
0
                found++;
255
0
                break;
256
0
            case 'U':
257
0
            case 'u':
258
0
                de->flags |= TH_URG;
259
0
                found++;
260
0
                break;
261
0
            case '1':
262
0
                de->flags |= TH_CWR;
263
0
                found++;
264
0
                break;
265
0
            case '2':
266
0
                de->flags |= TH_ECN;
267
0
                found++;
268
0
                break;
269
0
            case 'C':
270
0
            case 'c':
271
0
                de->flags |= TH_CWR;
272
0
                found++;
273
0
                break;
274
0
            case 'E':
275
0
            case 'e':
276
0
                de->flags |= TH_ECN;
277
0
                found++;
278
0
                break;
279
0
            case '0':
280
0
                de->flags = 0;
281
0
                found++;
282
0
                break;
283
284
729
            case '!':
285
729
                de->modifier = MODIFIER_NOT;
286
729
                break;
287
11.4k
            case '+':
288
11.4k
                de->modifier = MODIFIER_PLUS;
289
11.4k
                break;
290
860
            case '*':
291
860
                de->modifier = MODIFIER_ANY;
292
860
                break;
293
12.9k
        }
294
12.9k
        ptr++;
295
12.9k
    }
296
297
    /** Second parse first set of flags */
298
23.9k
    if (strlen(arg2) > 0) {
299
23.9k
        ptr = arg2;
300
110k
        while (*ptr != '\0') {
301
86.9k
            switch (*ptr) {
302
5.22k
                case 'S':
303
5.22k
                case 's':
304
5.22k
                    de->flags |= TH_SYN;
305
5.22k
                    found++;
306
5.22k
                    break;
307
11.3k
                case 'A':
308
11.3k
                case 'a':
309
11.3k
                    de->flags |= TH_ACK;
310
11.3k
                    found++;
311
11.3k
                    break;
312
6.20k
                case 'F':
313
6.20k
                case 'f':
314
6.20k
                    de->flags |= TH_FIN;
315
6.20k
                    found++;
316
6.20k
                    break;
317
11.9k
                case 'R':
318
11.9k
                case 'r':
319
11.9k
                    de->flags |= TH_RST;
320
11.9k
                    found++;
321
11.9k
                    break;
322
25.8k
                case 'P':
323
25.8k
                case 'p':
324
25.8k
                    de->flags |= TH_PUSH;
325
25.8k
                    found++;
326
25.8k
                    break;
327
2.76k
                case 'U':
328
2.76k
                case 'u':
329
2.76k
                    de->flags |= TH_URG;
330
2.76k
                    found++;
331
2.76k
                    break;
332
5.91k
                case '1':
333
8.29k
                case 'C':
334
8.29k
                case 'c':
335
8.29k
                    de->flags |= TH_CWR;
336
8.29k
                    found++;
337
8.29k
                    break;
338
3.28k
                case '2':
339
6.93k
                case 'E':
340
6.93k
                case 'e':
341
6.93k
                    de->flags |= TH_ECN;
342
6.93k
                    found++;
343
6.93k
                    break;
344
4.46k
                case '0':
345
4.46k
                    de->flags = 0;
346
4.46k
                    found++;
347
4.46k
                    break;
348
349
568
                case '!':
350
568
                    if (de->modifier != 0) {
351
300
                        SCLogError("\"flags\" supports only"
352
300
                                   " one modifier at a time");
353
300
                        goto error;
354
300
                    }
355
268
                    de->modifier = MODIFIER_NOT;
356
268
                    SCLogDebug("NOT modifier is set");
357
268
                    break;
358
1.88k
                case '+':
359
1.88k
                    if (de->modifier != 0) {
360
2
                        SCLogError("\"flags\" supports only"
361
2
                                   " one modifier at a time");
362
2
                        goto error;
363
2
                    }
364
1.87k
                    de->modifier = MODIFIER_PLUS;
365
1.87k
                    SCLogDebug("PLUS modifier is set");
366
1.87k
                    break;
367
1.37k
                case '*':
368
1.37k
                    if (de->modifier != 0) {
369
21
                        SCLogError("\"flags\" supports only"
370
21
                                   " one modifier at a time");
371
21
                        goto error;
372
21
                    }
373
1.35k
                    de->modifier = MODIFIER_ANY;
374
1.35k
                    SCLogDebug("ANY modifier is set");
375
1.35k
                    break;
376
0
                default:
377
0
                    break;
378
86.9k
            }
379
86.6k
            ptr++;
380
86.6k
        }
381
382
23.5k
        if (found == 0)
383
21
            goto error;
384
23.5k
    }
385
386
    /** Finally parse ignored flags */
387
23.5k
    if (strlen(arg3) > 0) {
388
15.3k
        ptr = arg3;
389
390
125k
        while (*ptr != '\0') {
391
109k
            switch (*ptr) {
392
552
                case 'S':
393
552
                case 's':
394
552
                    de->ignored_flags &= ~TH_SYN;
395
552
                    ignore++;
396
552
                    break;
397
697
                case 'A':
398
697
                case 'a':
399
697
                    de->ignored_flags &= ~TH_ACK;
400
697
                    ignore++;
401
697
                    break;
402
3.57k
                case 'F':
403
3.57k
                case 'f':
404
3.57k
                    de->ignored_flags &= ~TH_FIN;
405
3.57k
                    ignore++;
406
3.57k
                    break;
407
51.5k
                case 'R':
408
51.5k
                case 'r':
409
51.5k
                    de->ignored_flags &= ~TH_RST;
410
51.5k
                    ignore++;
411
51.5k
                    break;
412
2.89k
                case 'P':
413
2.89k
                case 'p':
414
2.89k
                    de->ignored_flags &= ~TH_PUSH;
415
2.89k
                    ignore++;
416
2.89k
                    break;
417
14.4k
                case 'U':
418
14.4k
                case 'u':
419
14.4k
                    de->ignored_flags &= ~TH_URG;
420
14.4k
                    ignore++;
421
14.4k
                    break;
422
3.22k
                case '1':
423
3.22k
                    de->ignored_flags &= ~TH_CWR;
424
3.22k
                    ignore++;
425
3.22k
                    break;
426
23.4k
                case '2':
427
23.4k
                    de->ignored_flags &= ~TH_ECN;
428
23.4k
                    ignore++;
429
23.4k
                    break;
430
3.34k
                case 'C':
431
3.34k
                case 'c':
432
3.34k
                    de->ignored_flags &= ~TH_CWR;
433
3.34k
                    ignore++;
434
3.34k
                    break;
435
6.05k
                case 'E':
436
6.05k
                case 'e':
437
6.05k
                    de->ignored_flags &= ~TH_ECN;
438
6.05k
                    ignore++;
439
6.05k
                    break;
440
0
                case '0':
441
0
                    break;
442
0
                default:
443
0
                    break;
444
109k
            }
445
109k
            ptr++;
446
109k
        }
447
448
15.3k
        if (ignore == 0) {
449
0
            SCLogDebug("ignore == 0");
450
0
            goto error;
451
0
        }
452
15.3k
    }
453
454
23.5k
    pcre2_match_data_free(match);
455
23.5k
    SCLogDebug("found %"PRId32" ignore %"PRId32"", found, ignore);
456
23.5k
    SCReturnPtr(de, "DetectFlagsData");
457
458
4.73k
error:
459
4.73k
    if (de) {
460
344
        SCFree(de);
461
344
    }
462
4.73k
    if (match) {
463
4.73k
        pcre2_match_data_free(match);
464
4.73k
    }
465
4.73k
    SCReturnPtr(NULL, "DetectFlagsData");
466
23.5k
}
467
468
/**
469
 * \internal
470
 * \brief this function is used to add the parsed flags into the current signature
471
 *
472
 * \param de_ctx pointer to the Detection Engine Context
473
 * \param s pointer to the Current Signature
474
 * \param m pointer to the Current SigMatch
475
 * \param rawstr pointer to the user provided flags options
476
 *
477
 * \retval 0 on Success
478
 * \retval -1 on Failure
479
 */
480
static int DetectFlagsSetup (DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
481
28.3k
{
482
28.3k
    DetectFlagsData *de = NULL;
483
28.3k
    SigMatch *sm = NULL;
484
485
28.3k
    de = DetectFlagsParse(rawstr);
486
28.3k
    if (de == NULL)
487
4.73k
        goto error;
488
489
23.5k
    sm = SigMatchAlloc();
490
23.5k
    if (sm == NULL)
491
0
        goto error;
492
493
23.5k
    sm->type = DETECT_FLAGS;
494
23.5k
    sm->ctx = (SigMatchCtx *)de;
495
496
23.5k
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_MATCH);
497
23.5k
    s->flags |= SIG_FLAG_REQUIRE_PACKET;
498
499
23.5k
    return 0;
500
501
4.73k
error:
502
4.73k
    if (de) SCFree(de);
503
4.73k
    if (sm) SCFree(sm);
504
4.73k
    return -1;
505
23.5k
}
506
507
/**
508
 * \internal
509
 * \brief this function will free memory associated with DetectFlagsData
510
 *
511
 * \param de pointer to DetectFlagsData
512
 */
513
static void DetectFlagsFree(DetectEngineCtx *de_ctx, void *de_ptr)
514
23.5k
{
515
23.5k
    DetectFlagsData *de = (DetectFlagsData *)de_ptr;
516
23.5k
    if(de) SCFree(de);
517
23.5k
}
518
519
int DetectFlagsSignatureNeedsSynPackets(const Signature *s)
520
1.21M
{
521
1.21M
    const SigMatch *sm;
522
2.06M
    for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
523
852k
        switch (sm->type) {
524
23.3k
            case DETECT_FLAGS:
525
23.3k
            {
526
23.3k
                const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
527
528
23.3k
                if (!(fl->modifier == MODIFIER_NOT) && (fl->flags & TH_SYN)) {
529
2.82k
                    return 1;
530
2.82k
                }
531
20.4k
                break;
532
23.3k
            }
533
852k
        }
534
852k
    }
535
1.21M
    return 0;
536
1.21M
}
537
538
int DetectFlagsSignatureNeedsSynOnlyPackets(const Signature *s)
539
161k
{
540
161k
    const SigMatch *sm;
541
270k
    for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
542
109k
        switch (sm->type) {
543
4.69k
            case DETECT_FLAGS:
544
4.69k
            {
545
4.69k
                const DetectFlagsData *fl = (const DetectFlagsData *)sm->ctx;
546
547
4.69k
                if (!(fl->modifier == MODIFIER_NOT) && (fl->flags == TH_SYN)) {
548
485
                    return 1;
549
485
                }
550
4.20k
                break;
551
4.69k
            }
552
109k
        }
553
109k
    }
554
161k
    return 0;
555
161k
}
556
557
static void
558
PrefilterPacketFlagsMatch(DetectEngineThreadCtx *det_ctx, Packet *p, const void *pectx)
559
1.09k
{
560
1.09k
    if (!(PKT_IS_TCP(p)) || PKT_IS_PSEUDOPKT(p)) {
561
179
        SCReturn;
562
179
    }
563
564
919
    const PrefilterPacketHeaderCtx *ctx = pectx;
565
919
    if (!PrefilterPacketHeaderExtraMatch(ctx, p))
566
855
        return;
567
568
64
    const uint8_t flags = p->tcph->th_flags;
569
64
    if (FlagsMatch(flags, ctx->v1.u8[0], ctx->v1.u8[1], ctx->v1.u8[2]))
570
0
    {
571
0
        SCLogDebug("packet matches TCP flags %02x", ctx->v1.u8[1]);
572
0
        PrefilterAddSids(&det_ctx->pmq, ctx->sigs_array, ctx->sigs_cnt);
573
0
    }
574
64
}
575
576
static void
577
PrefilterPacketFlagsSet(PrefilterPacketHeaderValue *v, void *smctx)
578
2.41k
{
579
2.41k
    const DetectFlagsData *a = smctx;
580
2.41k
    v->u8[0] = a->modifier;
581
2.41k
    v->u8[1] = a->flags;
582
2.41k
    v->u8[2] = a->ignored_flags;
583
2.41k
    SCLogDebug("v->u8[0] = %02x", v->u8[0]);
584
2.41k
}
585
586
static bool
587
PrefilterPacketFlagsCompare(PrefilterPacketHeaderValue v, void *smctx)
588
850
{
589
850
    const DetectFlagsData *a = smctx;
590
850
    if (v.u8[0] == a->modifier &&
591
850
        v.u8[1] == a->flags &&
592
850
        v.u8[2] == a->ignored_flags)
593
850
        return true;
594
0
    return false;
595
850
}
596
597
static int PrefilterSetupTcpFlags(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
598
1.26k
{
599
1.26k
    return PrefilterSetupPacketHeader(de_ctx, sgh, DETECT_FLAGS,
600
1.26k
            PrefilterPacketFlagsSet,
601
1.26k
            PrefilterPacketFlagsCompare,
602
1.26k
            PrefilterPacketFlagsMatch);
603
604
1.26k
}
605
606
static bool PrefilterTcpFlagsIsPrefilterable(const Signature *s)
607
0
{
608
0
    const SigMatch *sm;
609
0
    for (sm = s->init_data->smlists[DETECT_SM_LIST_MATCH] ; sm != NULL; sm = sm->next) {
610
0
        switch (sm->type) {
611
0
            case DETECT_FLAGS:
612
0
                return true;
613
0
        }
614
0
    }
615
0
    return false;
616
0
}
617
618
/*
619
 * ONLY TESTS BELOW THIS COMMENT
620
 */
621
622
#ifdef UNITTESTS
623
/**
624
 * \test FlagsTestParse01 is a test for a  valid flags value
625
 *
626
 *  \retval 1 on success
627
 *  \retval 0 on failure
628
 */
629
static int FlagsTestParse01 (void)
630
{
631
    DetectFlagsData *de = DetectFlagsParse("S");
632
    FAIL_IF_NULL(de);
633
    FAIL_IF_NOT(de->flags == TH_SYN);
634
    DetectFlagsFree(NULL, de);
635
    PASS;
636
}
637
638
/**
639
 * \test FlagsTestParse02 is a test for an invalid flags value
640
 *
641
 *  \retval 1 on success
642
 *  \retval 0 on failure
643
 */
644
static int FlagsTestParse02 (void)
645
{
646
    DetectFlagsData *de = NULL;
647
    de = DetectFlagsParse("G");
648
    if (de) {
649
        DetectFlagsFree(NULL, de);
650
        return 0;
651
    }
652
653
    return 1;
654
}
655
656
/**
657
 * \test FlagsTestParse03 test if ACK and PUSH are set. Must return success
658
 *
659
 *  \retval 1 on success
660
 *  \retval 0 on failure
661
 */
662
static int FlagsTestParse03 (void)
663
{
664
    Packet *p = PacketGetFromAlloc();
665
    if (unlikely(p == NULL))
666
        return 0;
667
    ThreadVars tv;
668
    int ret = 0;
669
    DetectFlagsData *de = NULL;
670
    SigMatch *sm = NULL;
671
    IPV4Hdr ipv4h;
672
    TCPHdr tcph;
673
674
    memset(&tv, 0, sizeof(ThreadVars));
675
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
676
    memset(&tcph, 0, sizeof(TCPHdr));
677
678
    p->ip4h = &ipv4h;
679
    p->tcph = &tcph;
680
    p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
681
682
    de = DetectFlagsParse("AP+");
683
684
    if (de == NULL || (de->flags != (TH_ACK|TH_PUSH)) )
685
        goto error;
686
687
    sm = SigMatchAlloc();
688
    if (sm == NULL)
689
        goto error;
690
691
    sm->type = DETECT_FLAGS;
692
    sm->ctx = (SigMatchCtx *)de;
693
694
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
695
696
    if(ret) {
697
        if (de) SCFree(de);
698
        if (sm) SCFree(sm);
699
        SCFree(p);
700
        return 1;
701
    }
702
703
error:
704
    if (de) SCFree(de);
705
    if (sm) SCFree(sm);
706
    SCFree(p);
707
    return 0;
708
}
709
710
/**
711
 * \test FlagsTestParse04 check if ACK bit is set. Must fails.
712
 *
713
 *  \retval 1 on success
714
 *  \retval 0 on failure
715
 */
716
static int FlagsTestParse04 (void)
717
{
718
    Packet *p = PacketGetFromAlloc();
719
    if (unlikely(p == NULL))
720
        return 0;
721
    ThreadVars tv;
722
    int ret = 0;
723
    DetectFlagsData *de = NULL;
724
    SigMatch *sm = NULL;
725
    IPV4Hdr ipv4h;
726
    TCPHdr tcph;
727
728
    memset(&tv, 0, sizeof(ThreadVars));
729
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
730
    memset(&tcph, 0, sizeof(TCPHdr));
731
732
    p->ip4h = &ipv4h;
733
    p->tcph = &tcph;
734
    p->tcph->th_flags = TH_SYN;
735
736
    de = DetectFlagsParse("A");
737
738
    if (de == NULL || de->flags != TH_ACK)
739
        goto error;
740
741
    sm = SigMatchAlloc();
742
    if (sm == NULL)
743
        goto error;
744
745
    sm->type = DETECT_FLAGS;
746
    sm->ctx = (SigMatchCtx *)de;
747
748
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
749
750
    if(ret) {
751
        if (de) SCFree(de);
752
        if (sm) SCFree(sm);
753
        SCFree(p);
754
        return 0;
755
    }
756
757
    /* Error expected. */
758
error:
759
    if (de) SCFree(de);
760
    if (sm) SCFree(sm);
761
    SCFree(p);
762
    return 1;
763
}
764
765
/**
766
 * \test FlagsTestParse05 test if ACK+PUSH and more flags are set. Ignore SYN and RST bits.
767
 *       Must fails.
768
 *  \retval 1 on success
769
 *  \retval 0 on failure
770
 */
771
static int FlagsTestParse05 (void)
772
{
773
    Packet *p = PacketGetFromAlloc();
774
    if (unlikely(p == NULL))
775
        return 0;
776
    ThreadVars tv;
777
    int ret = 0;
778
    DetectFlagsData *de = NULL;
779
    SigMatch *sm = NULL;
780
    IPV4Hdr ipv4h;
781
    TCPHdr tcph;
782
783
    memset(&tv, 0, sizeof(ThreadVars));
784
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
785
    memset(&tcph, 0, sizeof(TCPHdr));
786
787
    p->ip4h = &ipv4h;
788
    p->tcph = &tcph;
789
    p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
790
791
    de = DetectFlagsParse("+AP,SR");
792
793
    if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || (de->ignored_flags != (TH_SYN|TH_RST)))
794
        goto error;
795
796
    sm = SigMatchAlloc();
797
    if (sm == NULL)
798
        goto error;
799
800
    sm->type = DETECT_FLAGS;
801
    sm->ctx = (SigMatchCtx *)de;
802
803
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
804
805
    if(ret) {
806
        if (de) SCFree(de);
807
        if (sm) SCFree(sm);
808
        SCFree(p);
809
        return 0;
810
    }
811
812
    /* Error expected. */
813
error:
814
    if (de) SCFree(de);
815
    if (sm) SCFree(sm);
816
    SCFree(p);
817
    return 1;
818
}
819
820
/**
821
 * \test FlagsTestParse06 test if ACK+PUSH and more flags are set. Ignore URG and RST bits.
822
 *       Must return success.
823
 *  \retval 1 on success
824
 *  \retval 0 on failure
825
 */
826
static int FlagsTestParse06 (void)
827
{
828
    Packet *p = PacketGetFromAlloc();
829
    if (unlikely(p == NULL))
830
        return 0;
831
    ThreadVars tv;
832
    int ret = 0;
833
    DetectFlagsData *de = NULL;
834
    SigMatch *sm = NULL;
835
    IPV4Hdr ipv4h;
836
    TCPHdr tcph;
837
838
    memset(&tv, 0, sizeof(ThreadVars));
839
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
840
    memset(&tcph, 0, sizeof(TCPHdr));
841
842
    p->ip4h = &ipv4h;
843
    p->tcph = &tcph;
844
    p->tcph->th_flags = TH_ACK|TH_PUSH|TH_SYN|TH_RST;
845
846
    de = DetectFlagsParse("+AP,UR");
847
848
    if (de == NULL || (de->modifier != MODIFIER_PLUS) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_URG|TH_RST)))
849
        goto error;
850
851
    sm = SigMatchAlloc();
852
    if (sm == NULL)
853
        goto error;
854
855
    sm->type = DETECT_FLAGS;
856
    sm->ctx = (SigMatchCtx *)de;
857
858
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
859
860
    if(ret) {
861
        if (de) SCFree(de);
862
        if (sm) SCFree(sm);
863
        SCFree(p);
864
        return 1;
865
    }
866
867
error:
868
    if (de) SCFree(de);
869
    if (sm) SCFree(sm);
870
    SCFree(p);
871
    return 0;
872
}
873
874
/**
875
 * \test FlagsTestParse07 test if SYN or RST are set. Must fails.
876
 *
877
 *  \retval 1 on success
878
 *  \retval 0 on failure
879
 */
880
static int FlagsTestParse07 (void)
881
{
882
    Packet *p = PacketGetFromAlloc();
883
    if (unlikely(p == NULL))
884
        return 0;
885
    ThreadVars tv;
886
    int ret = 0;
887
    DetectFlagsData *de = NULL;
888
    SigMatch *sm = NULL;
889
    IPV4Hdr ipv4h;
890
    TCPHdr tcph;
891
892
    memset(&tv, 0, sizeof(ThreadVars));
893
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
894
    memset(&tcph, 0, sizeof(TCPHdr));
895
896
    p->ip4h = &ipv4h;
897
    p->tcph = &tcph;
898
    p->tcph->th_flags = TH_SYN|TH_RST;
899
900
    de = DetectFlagsParse("*AP");
901
902
    if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)))
903
        goto error;
904
905
    sm = SigMatchAlloc();
906
    if (sm == NULL)
907
        goto error;
908
909
    sm->type = DETECT_FLAGS;
910
    sm->ctx = (SigMatchCtx *)de;
911
912
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
913
914
    if(ret) {
915
        if (de) SCFree(de);
916
        if (sm) SCFree(sm);
917
        SCFree(p);
918
        return 0;
919
    }
920
921
    /* Error expected. */
922
error:
923
    if (de) SCFree(de);
924
    if (sm) SCFree(sm);
925
    SCFree(p);
926
    return 1;
927
}
928
929
/**
930
 * \test FlagsTestParse08 test if SYN or RST are set. Must return success.
931
 *
932
 *  \retval 1 on success
933
 *  \retval 0 on failure
934
 */
935
static int FlagsTestParse08 (void)
936
{
937
    Packet *p = PacketGetFromAlloc();
938
    if (unlikely(p == NULL))
939
        return 0;
940
    ThreadVars tv;
941
    int ret = 0;
942
    DetectFlagsData *de = NULL;
943
    SigMatch *sm = NULL;
944
    IPV4Hdr ipv4h;
945
    TCPHdr tcph;
946
947
    memset(&tv, 0, sizeof(ThreadVars));
948
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
949
    memset(&tcph, 0, sizeof(TCPHdr));
950
951
    p->ip4h = &ipv4h;
952
    p->tcph = &tcph;
953
    p->tcph->th_flags = TH_SYN|TH_RST;
954
955
    de = DetectFlagsParse("*SA");
956
957
    if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_SYN)))
958
        goto error;
959
960
    sm = SigMatchAlloc();
961
    if (sm == NULL)
962
        goto error;
963
964
    sm->type = DETECT_FLAGS;
965
    sm->ctx = (SigMatchCtx *)de;
966
967
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
968
969
    if(ret) {
970
        if (de) SCFree(de);
971
        if (sm) SCFree(sm);
972
        SCFree(p);
973
        return 1;
974
    }
975
976
error:
977
    if (de) SCFree(de);
978
    if (sm) SCFree(sm);
979
    SCFree(p);
980
    return 0;
981
}
982
983
/**
984
 * \test FlagsTestParse09 test if SYN and RST are not set. Must fails.
985
 *
986
 *  \retval 1 on success
987
 *  \retval 0 on failure
988
 */
989
static int FlagsTestParse09 (void)
990
{
991
    Packet *p = PacketGetFromAlloc();
992
    if (unlikely(p == NULL))
993
        return 0;
994
    ThreadVars tv;
995
    int ret = 0;
996
    DetectFlagsData *de = NULL;
997
    SigMatch *sm = NULL;
998
    IPV4Hdr ipv4h;
999
    TCPHdr tcph;
1000
1001
    memset(&tv, 0, sizeof(ThreadVars));
1002
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1003
    memset(&tcph, 0, sizeof(TCPHdr));
1004
1005
    p->ip4h = &ipv4h;
1006
    p->tcph = &tcph;
1007
    p->tcph->th_flags = TH_SYN|TH_RST;
1008
1009
    de = DetectFlagsParse("!PA");
1010
1011
    if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1012
        goto error;
1013
1014
    sm = SigMatchAlloc();
1015
    if (sm == NULL)
1016
        goto error;
1017
1018
    sm->type = DETECT_FLAGS;
1019
    sm->ctx = (SigMatchCtx *)de;
1020
1021
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1022
1023
    if(ret) {
1024
        if (de) SCFree(de);
1025
        if (sm) SCFree(sm);
1026
        SCFree(p);
1027
        return 1;
1028
    }
1029
1030
error:
1031
    if (de) SCFree(de);
1032
    if (sm) SCFree(sm);
1033
    SCFree(p);
1034
    return 0;
1035
}
1036
1037
/**
1038
 * \test FlagsTestParse10 test if ACK and PUSH are not set. Must return success.
1039
 *
1040
 *  \retval 1 on success
1041
 *  \retval 0 on failure
1042
 */
1043
static int FlagsTestParse10 (void)
1044
{
1045
    Packet *p = PacketGetFromAlloc();
1046
    if (unlikely(p == NULL))
1047
        return 0;
1048
    ThreadVars tv;
1049
    int ret = 0;
1050
    DetectFlagsData *de = NULL;
1051
    SigMatch *sm = NULL;
1052
    IPV4Hdr ipv4h;
1053
    TCPHdr tcph;
1054
1055
    memset(&tv, 0, sizeof(ThreadVars));
1056
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1057
    memset(&tcph, 0, sizeof(TCPHdr));
1058
1059
    p->ip4h = &ipv4h;
1060
    p->tcph = &tcph;
1061
    p->tcph->th_flags = TH_SYN|TH_RST;
1062
1063
    de = DetectFlagsParse("!AP");
1064
1065
    if (de == NULL || (de->modifier != MODIFIER_NOT) || (de->flags != (TH_ACK|TH_PUSH)))
1066
        goto error;
1067
1068
    sm = SigMatchAlloc();
1069
    if (sm == NULL)
1070
        goto error;
1071
1072
    sm->type = DETECT_FLAGS;
1073
    sm->ctx = (SigMatchCtx *)de;
1074
1075
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1076
1077
    if(ret) {
1078
        if (de) SCFree(de);
1079
        if (sm) SCFree(sm);
1080
        SCFree(p);
1081
        return 1;
1082
    }
1083
1084
error:
1085
    if (de) SCFree(de);
1086
    if (sm) SCFree(sm);
1087
    SCFree(p);
1088
    return 0;
1089
}
1090
1091
/**
1092
 * \test FlagsTestParse11 test if ACK or PUSH are set. Ignore SYN and RST. Must fails.
1093
 *
1094
 *  \retval 1 on success
1095
 *  \retval 0 on failure
1096
 */
1097
static int FlagsTestParse11 (void)
1098
{
1099
    Packet *p = PacketGetFromAlloc();
1100
    if (unlikely(p == NULL))
1101
        return 0;
1102
    ThreadVars tv;
1103
    int ret = 0;
1104
    DetectFlagsData *de = NULL;
1105
    SigMatch *sm = NULL;
1106
    IPV4Hdr ipv4h;
1107
    TCPHdr tcph;
1108
1109
    memset(&tv, 0, sizeof(ThreadVars));
1110
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1111
    memset(&tcph, 0, sizeof(TCPHdr));
1112
1113
    p->ip4h = &ipv4h;
1114
    p->tcph = &tcph;
1115
    p->tcph->th_flags = TH_SYN|TH_RST|TH_URG;
1116
1117
    de = DetectFlagsParse("*AP,SR");
1118
1119
    if (de == NULL || (de->modifier != MODIFIER_ANY) || (de->flags != (TH_ACK|TH_PUSH)) || ((0xff - de->ignored_flags) != (TH_SYN|TH_RST)))
1120
        goto error;
1121
1122
    sm = SigMatchAlloc();
1123
    if (sm == NULL)
1124
        goto error;
1125
1126
    sm->type = DETECT_FLAGS;
1127
    sm->ctx = (SigMatchCtx *)de;
1128
1129
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1130
1131
    if(ret) {
1132
        if (de) SCFree(de);
1133
        if (sm) SCFree(sm);
1134
        SCFree(p);
1135
        return 0;
1136
    }
1137
1138
    /* Expected. */
1139
error:
1140
    if (de) SCFree(de);
1141
    if (sm) SCFree(sm);
1142
    SCFree(p);
1143
    return 1;
1144
}
1145
1146
/**
1147
 * \test FlagsTestParse12 check if no flags are set. Must fails.
1148
 *
1149
 *  \retval 1 on success
1150
 *  \retval 0 on failure
1151
 */
1152
static int FlagsTestParse12 (void)
1153
{
1154
    Packet *p = PacketGetFromAlloc();
1155
    if (unlikely(p == NULL))
1156
        return 0;
1157
    ThreadVars tv;
1158
    int ret = 0;
1159
    DetectFlagsData *de = NULL;
1160
    SigMatch *sm = NULL;
1161
    IPV4Hdr ipv4h;
1162
    TCPHdr tcph;
1163
1164
    memset(&tv, 0, sizeof(ThreadVars));
1165
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1166
    memset(&tcph, 0, sizeof(TCPHdr));
1167
1168
    p->ip4h = &ipv4h;
1169
    p->tcph = &tcph;
1170
    p->tcph->th_flags = TH_SYN;
1171
1172
    de = DetectFlagsParse("0");
1173
1174
    if (de == NULL || de->flags != 0) {
1175
        printf("de setup: ");
1176
        goto error;
1177
    }
1178
1179
    sm = SigMatchAlloc();
1180
    if (sm == NULL)
1181
        goto error;
1182
1183
    sm->type = DETECT_FLAGS;
1184
    sm->ctx = (SigMatchCtx *)de;
1185
1186
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1187
1188
    if(ret) {
1189
        if (de) SCFree(de);
1190
        if (sm) SCFree(sm);
1191
        SCFree(p);
1192
        return 0;
1193
    }
1194
1195
    /* Expected. */
1196
error:
1197
    if (de) SCFree(de);
1198
    if (sm) SCFree(sm);
1199
    SCFree(p);
1200
    return 1;
1201
}
1202
1203
/**
1204
 * \test test for a  valid flags value
1205
 *
1206
 *  \retval 1 on success
1207
 *  \retval 0 on failure
1208
 */
1209
static int FlagsTestParse13 (void)
1210
{
1211
    DetectFlagsData *de = NULL;
1212
    de = DetectFlagsParse("+S*");
1213
    if (de != NULL) {
1214
        DetectFlagsFree(NULL, de);
1215
        return 0;
1216
    }
1217
1218
    return 1;
1219
}
1220
1221
/**
1222
 * \test Parse 'C' and 'E' flags.
1223
 *
1224
 *  \retval 1 on success.
1225
 *  \retval 0 on failure.
1226
 */
1227
static int FlagsTestParse14(void)
1228
{
1229
    DetectFlagsData *de = DetectFlagsParse("CE");
1230
    if (de != NULL && (de->flags == (TH_CWR | TH_ECN)) ) {
1231
        DetectFlagsFree(NULL, de);
1232
        return 1;
1233
    }
1234
1235
    return 0;
1236
}
1237
1238
static int FlagsTestParse15(void)
1239
{
1240
    Packet *p = PacketGetFromAlloc();
1241
    if (unlikely(p == NULL))
1242
        return 0;
1243
    ThreadVars tv;
1244
    int ret = 0;
1245
    DetectFlagsData *de = NULL;
1246
    SigMatch *sm = NULL;
1247
    IPV4Hdr ipv4h;
1248
    TCPHdr tcph;
1249
1250
    memset(&tv, 0, sizeof(ThreadVars));
1251
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1252
    memset(&tcph, 0, sizeof(TCPHdr));
1253
1254
    p->ip4h = &ipv4h;
1255
    p->tcph = &tcph;
1256
    p->tcph->th_flags = TH_ECN | TH_CWR | TH_SYN | TH_RST;
1257
1258
    de = DetectFlagsParse("EC+");
1259
1260
    if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1261
        goto error;
1262
1263
    sm = SigMatchAlloc();
1264
    if (sm == NULL)
1265
        goto error;
1266
1267
    sm->type = DETECT_FLAGS;
1268
    sm->ctx = (SigMatchCtx *)de;
1269
1270
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1271
1272
    if (ret) {
1273
        if (de)
1274
            SCFree(de);
1275
        if (sm)
1276
            SCFree(sm);
1277
        SCFree(p);
1278
        return 1;
1279
    }
1280
1281
error:
1282
    if (de)
1283
        SCFree(de);
1284
    if (sm)
1285
        SCFree(sm);
1286
    SCFree(p);
1287
    return 0;
1288
}
1289
1290
static int FlagsTestParse16(void)
1291
{
1292
    Packet *p = PacketGetFromAlloc();
1293
    if (unlikely(p == NULL))
1294
        return 0;
1295
    ThreadVars tv;
1296
    int ret = 0;
1297
    DetectFlagsData *de = NULL;
1298
    SigMatch *sm = NULL;
1299
    IPV4Hdr ipv4h;
1300
    TCPHdr tcph;
1301
1302
    memset(&tv, 0, sizeof(ThreadVars));
1303
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1304
    memset(&tcph, 0, sizeof(TCPHdr));
1305
1306
    p->ip4h = &ipv4h;
1307
    p->tcph = &tcph;
1308
    p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1309
1310
    de = DetectFlagsParse("EC*");
1311
1312
    if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1313
        goto error;
1314
1315
    sm = SigMatchAlloc();
1316
    if (sm == NULL)
1317
        goto error;
1318
1319
    sm->type = DETECT_FLAGS;
1320
    sm->ctx = (SigMatchCtx *)de;
1321
1322
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1323
1324
    if (ret) {
1325
        if (de)
1326
            SCFree(de);
1327
        if (sm)
1328
            SCFree(sm);
1329
        SCFree(p);
1330
        return 1;
1331
    }
1332
1333
error:
1334
    if (de)
1335
        SCFree(de);
1336
    if (sm)
1337
        SCFree(sm);
1338
    SCFree(p);
1339
    return 0;
1340
}
1341
1342
/**
1343
 * \test Negative test.
1344
 */
1345
static int FlagsTestParse17(void)
1346
{
1347
    Packet *p = PacketGetFromAlloc();
1348
    if (unlikely(p == NULL))
1349
        return 0;
1350
    ThreadVars tv;
1351
    int ret = 0;
1352
    DetectFlagsData *de = NULL;
1353
    SigMatch *sm = NULL;
1354
    IPV4Hdr ipv4h;
1355
    TCPHdr tcph;
1356
1357
    memset(&tv, 0, sizeof(ThreadVars));
1358
    memset(&ipv4h, 0, sizeof(IPV4Hdr));
1359
    memset(&tcph, 0, sizeof(TCPHdr));
1360
1361
    p->ip4h = &ipv4h;
1362
    p->tcph = &tcph;
1363
    p->tcph->th_flags = TH_ECN | TH_SYN | TH_RST;
1364
1365
    de = DetectFlagsParse("EC+");
1366
1367
    if (de == NULL || (de->flags != (TH_ECN | TH_CWR)) )
1368
        goto error;
1369
1370
    sm = SigMatchAlloc();
1371
    if (sm == NULL)
1372
        goto error;
1373
1374
    sm->type = DETECT_FLAGS;
1375
    sm->ctx = (SigMatchCtx *)de;
1376
1377
    ret = DetectFlagsMatch(NULL, p, NULL, sm->ctx);
1378
1379
    if (ret == 0) {
1380
        if (de)
1381
            SCFree(de);
1382
        if (sm)
1383
            SCFree(sm);
1384
        SCFree(p);
1385
        return 1;
1386
    }
1387
1388
error:
1389
    if (de)
1390
        SCFree(de);
1391
    if (sm)
1392
        SCFree(sm);
1393
    SCFree(p);
1394
    return 0;
1395
}
1396
1397
/**
1398
 * \brief this function registers unit tests for Flags
1399
 */
1400
static void FlagsRegisterTests(void)
1401
{
1402
    UtRegisterTest("FlagsTestParse01", FlagsTestParse01);
1403
    UtRegisterTest("FlagsTestParse02", FlagsTestParse02);
1404
    UtRegisterTest("FlagsTestParse03", FlagsTestParse03);
1405
    UtRegisterTest("FlagsTestParse04", FlagsTestParse04);
1406
    UtRegisterTest("FlagsTestParse05", FlagsTestParse05);
1407
    UtRegisterTest("FlagsTestParse06", FlagsTestParse06);
1408
    UtRegisterTest("FlagsTestParse07", FlagsTestParse07);
1409
    UtRegisterTest("FlagsTestParse08", FlagsTestParse08);
1410
    UtRegisterTest("FlagsTestParse09", FlagsTestParse09);
1411
    UtRegisterTest("FlagsTestParse10", FlagsTestParse10);
1412
    UtRegisterTest("FlagsTestParse11", FlagsTestParse11);
1413
    UtRegisterTest("FlagsTestParse12", FlagsTestParse12);
1414
    UtRegisterTest("FlagsTestParse13", FlagsTestParse13);
1415
    UtRegisterTest("FlagsTestParse14", FlagsTestParse14);
1416
    UtRegisterTest("FlagsTestParse15", FlagsTestParse15);
1417
    UtRegisterTest("FlagsTestParse16", FlagsTestParse16);
1418
    UtRegisterTest("FlagsTestParse17", FlagsTestParse17);
1419
}
1420
#endif /* UNITTESTS */