Coverage Report

Created: 2026-09-06 07:25

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