Coverage Report

Created: 2026-03-31 07:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/suricata7/src/detect-threshold.c
Line
Count
Source
1
/* Copyright (C) 2007-2021 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
 * \ingroup threshold
20
 * @{
21
 */
22
23
/**
24
 * \file
25
 *
26
 * \author Breno Silva <breno.silva@gmail.com>
27
 * \author Victor Julien <victor@inliniac.net>
28
 *
29
 * Implements the threshold keyword.
30
 *
31
 * The feature depends on what is provided
32
 * by detect-engine-threshold.c and util-threshold-config.c
33
 */
34
35
#include "suricata-common.h"
36
#include "suricata.h"
37
#include "decode.h"
38
39
#include "host.h"
40
#include "host-storage.h"
41
42
#include "detect.h"
43
#include "detect-parse.h"
44
45
#include "flow-var.h"
46
#include "decode-events.h"
47
#include "stream-tcp.h"
48
49
#include "detect-threshold.h"
50
#include "detect-engine-threshold.h"
51
#include "detect-engine-address.h"
52
#include "detect-engine-build.h"
53
54
#include "util-unittest.h"
55
#include "util-unittest-helper.h"
56
#include "util-byte.h"
57
#include "util-debug.h"
58
59
#ifdef UNITTESTS
60
#include "util-cpu.h"
61
#endif
62
63
73
#define PARSE_REGEX "^\\s*(track|type|count|seconds)\\s+(limit|both|threshold|by_dst|by_src|by_both|by_rule|\\d+)\\s*,\\s*(track|type|count|seconds)\\s+(limit|both|threshold|by_dst|by_src|by_both|by_rule|\\d+)\\s*,\\s*(track|type|count|seconds)\\s+(limit|both|threshold|by_dst|by_src|by_both|by_rule|\\d+)\\s*,\\s*(track|type|count|seconds)\\s+(limit|both|threshold|by_dst|by_src|by_both|by_rule|\\d+)\\s*"
64
65
static DetectParseRegex parse_regex;
66
67
static int DetectThresholdMatch(DetectEngineThreadCtx *, Packet *,
68
        const Signature *, const SigMatchCtx *);
69
static int DetectThresholdSetup(DetectEngineCtx *, Signature *, const char *);
70
static void DetectThresholdFree(DetectEngineCtx *, void *);
71
#ifdef UNITTESTS
72
static void ThresholdRegisterTests(void);
73
#endif
74
75
/**
76
 * \brief Registration function for threshold: keyword
77
 */
78
79
void DetectThresholdRegister(void)
80
73
{
81
73
    sigmatch_table[DETECT_THRESHOLD].name = "threshold";
82
73
    sigmatch_table[DETECT_THRESHOLD].desc = "control the rule's alert frequency";
83
73
    sigmatch_table[DETECT_THRESHOLD].url = "/rules/thresholding.html#threshold";
84
73
    sigmatch_table[DETECT_THRESHOLD].Match = DetectThresholdMatch;
85
73
    sigmatch_table[DETECT_THRESHOLD].Setup = DetectThresholdSetup;
86
73
    sigmatch_table[DETECT_THRESHOLD].Free  = DetectThresholdFree;
87
#ifdef UNITTESTS
88
    sigmatch_table[DETECT_THRESHOLD].RegisterTests = ThresholdRegisterTests;
89
#endif
90
    /* this is compatible to ip-only signatures */
91
73
    sigmatch_table[DETECT_THRESHOLD].flags |= SIGMATCH_IPONLY_COMPAT;
92
93
73
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
94
73
}
95
96
static int DetectThresholdMatch(DetectEngineThreadCtx *det_ctx, Packet *p,
97
        const Signature *s, const SigMatchCtx *ctx)
98
0
{
99
0
    return 1;
100
0
}
101
102
/**
103
 * \internal
104
 * \brief This function is used to parse threshold options passed via threshold: keyword
105
 *
106
 * \param rawstr Pointer to the user provided threshold options
107
 *
108
 * \retval de pointer to DetectThresholdData on success
109
 * \retval NULL on failure
110
 */
111
static DetectThresholdData *DetectThresholdParse(const char *rawstr)
112
12.8k
{
113
12.8k
    DetectThresholdData *de = NULL;
114
12.8k
    int ret = 0, res = 0;
115
12.8k
    size_t pcre2_len;
116
12.8k
    const char *str_ptr = NULL;
117
12.8k
    char *args[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
118
12.8k
    char *copy_str = NULL, *threshold_opt = NULL;
119
12.8k
    int second_found = 0, count_found = 0;
120
12.8k
    int type_found = 0, track_found = 0;
121
12.8k
    int second_pos = 0, count_pos = 0;
122
12.8k
    size_t pos = 0;
123
12.8k
    int i = 0;
124
12.8k
    pcre2_match_data *match = NULL;
125
126
12.8k
    copy_str = SCStrdup(rawstr);
127
12.8k
    if (unlikely(copy_str == NULL)) {
128
0
        goto error;
129
0
    }
130
131
12.8k
    char *saveptr = NULL;
132
12.8k
    for (pos = 0, threshold_opt = strtok_r(copy_str,",", &saveptr);
133
68.3k
         pos < strlen(copy_str) && threshold_opt != NULL;
134
55.4k
         pos++, threshold_opt = strtok_r(NULL,"," , &saveptr))
135
55.4k
    {
136
55.4k
        if(strstr(threshold_opt,"count"))
137
12.5k
            count_found++;
138
55.4k
        if(strstr(threshold_opt,"second"))
139
11.5k
            second_found++;
140
55.4k
        if(strstr(threshold_opt,"type"))
141
11.6k
            type_found++;
142
55.4k
        if(strstr(threshold_opt,"track"))
143
10.9k
            track_found++;
144
55.4k
    }
145
12.8k
    SCFree(copy_str);
146
12.8k
    copy_str = NULL;
147
148
12.8k
    if(count_found != 1 || second_found != 1 || type_found != 1 || track_found != 1)
149
2.32k
        goto error;
150
151
10.5k
    ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
152
10.5k
    if (ret < 5) {
153
607
        SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr);
154
607
        goto error;
155
607
    }
156
157
9.91k
    de = SCMalloc(sizeof(DetectThresholdData));
158
9.91k
    if (unlikely(de == NULL))
159
0
        goto error;
160
161
9.91k
    memset(de,0,sizeof(DetectThresholdData));
162
163
89.2k
    for (i = 0; i < (ret - 1); i++) {
164
165
79.3k
        res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
166
167
79.3k
        if (res < 0) {
168
0
            SCLogError("pcre2_substring_get_bynumber failed");
169
0
            goto error;
170
0
        }
171
172
79.3k
        args[i] = (char *)str_ptr;
173
174
79.3k
        if (strncasecmp(args[i],"limit",strlen("limit")) == 0)
175
5.46k
            de->type = TYPE_LIMIT;
176
79.3k
        if (strncasecmp(args[i],"both",strlen("both")) == 0)
177
3.34k
            de->type = TYPE_BOTH;
178
79.3k
        if (strncasecmp(args[i],"threshold",strlen("threshold")) == 0)
179
1.28k
            de->type = TYPE_THRESHOLD;
180
79.3k
        if (strncasecmp(args[i],"by_dst",strlen("by_dst")) == 0)
181
2.13k
            de->track = TRACK_DST;
182
79.3k
        if (strncasecmp(args[i],"by_src",strlen("by_src")) == 0)
183
6.71k
            de->track = TRACK_SRC;
184
79.3k
        if (strncasecmp(args[i],"by_both",strlen("by_both")) == 0)
185
8
            de->track = TRACK_BOTH;
186
79.3k
        if (strncasecmp(args[i],"by_rule",strlen("by_rule")) == 0)
187
1.06k
            de->track = TRACK_RULE;
188
79.3k
        if (strncasecmp(args[i],"count",strlen("count")) == 0)
189
9.91k
            count_pos = i+1;
190
79.3k
        if (strncasecmp(args[i],"seconds",strlen("seconds")) == 0)
191
9.91k
            second_pos = i+1;
192
79.3k
    }
193
194
9.91k
    if (args[count_pos] == NULL || args[second_pos] == NULL) {
195
0
        goto error;
196
0
    }
197
198
9.91k
    if (StringParseUint32(&de->count, 10, strlen(args[count_pos]),
199
9.91k
                args[count_pos]) <= 0) {
200
550
        goto error;
201
550
    }
202
203
9.36k
    if (StringParseUint32(&de->seconds, 10, strlen(args[second_pos]),
204
9.36k
                args[second_pos]) <= 0) {
205
159
        goto error;
206
159
    }
207
208
82.8k
    for (i = 0; i < (ret - 1); i++){
209
73.6k
        if (args[i] != NULL)
210
73.6k
            pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
211
73.6k
    }
212
9.20k
    pcre2_match_data_free(match);
213
9.20k
    return de;
214
215
3.64k
error:
216
3.64k
    if (match) {
217
1.31k
        pcre2_match_data_free(match);
218
1.31k
    }
219
9.31k
    for (i = 0; i < (ret - 1); i++){
220
5.67k
        if (args[i] != NULL)
221
5.67k
            pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
222
5.67k
    }
223
3.64k
    if (de != NULL)
224
709
        SCFree(de);
225
3.64k
    return NULL;
226
9.36k
}
227
228
/**
229
 * \internal
230
 * \brief this function is used to add the parsed threshold into the current signature
231
 *
232
 * \param de_ctx pointer to the Detection Engine Context
233
 * \param s pointer to the Current Signature
234
 * \param rawstr pointer to the user provided threshold options
235
 *
236
 * \retval 0 on Success
237
 * \retval -1 on Failure
238
 */
239
static int DetectThresholdSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
240
13.4k
{
241
13.4k
    DetectThresholdData *de = NULL;
242
13.4k
    SigMatch *sm = NULL;
243
13.4k
    SigMatch *tmpm = NULL;
244
245
    /* checks if there is a previous instance of detection_filter */
246
13.4k
    tmpm = DetectGetLastSMFromLists(s, DETECT_THRESHOLD, DETECT_DETECTION_FILTER, -1);
247
13.4k
    if (tmpm != NULL) {
248
595
        if (tmpm->type == DETECT_DETECTION_FILTER) {
249
0
            SCLogError("\"detection_filter\" and "
250
0
                       "\"threshold\" are not allowed in the same rule");
251
595
        } else {
252
595
            SCLogError("multiple \"threshold\" "
253
595
                       "options are not allowed in the same rule");
254
595
        }
255
595
        SCReturnInt(-1);
256
595
    }
257
258
12.8k
    de = DetectThresholdParse(rawstr);
259
12.8k
    if (de == NULL)
260
3.64k
        goto error;
261
262
9.20k
    sm = SigMatchAlloc();
263
9.20k
    if (sm == NULL)
264
0
        goto error;
265
266
9.20k
    sm->type = DETECT_THRESHOLD;
267
9.20k
    sm->ctx = (SigMatchCtx *)de;
268
269
9.20k
    SigMatchAppendSMToList(s, sm, DETECT_SM_LIST_THRESHOLD);
270
271
9.20k
    return 0;
272
273
3.64k
error:
274
3.64k
    if (de) SCFree(de);
275
3.64k
    if (sm) SCFree(sm);
276
3.64k
    return -1;
277
9.20k
}
278
279
/**
280
 * \internal
281
 * \brief this function will free memory associated with DetectThresholdData
282
 *
283
 * \param de pointer to DetectThresholdData
284
 */
285
static void DetectThresholdFree(DetectEngineCtx *de_ctx, void *de_ptr)
286
11.9k
{
287
11.9k
    DetectThresholdData *de = (DetectThresholdData *)de_ptr;
288
11.9k
    if (de) {
289
11.9k
        DetectAddressHeadCleanup(&de->addrs);
290
11.9k
        SCFree(de);
291
11.9k
    }
292
11.9k
}
293
294
/**
295
 * \brief Make a deep-copy of an extant DetectTHresholdData object.
296
 *
297
 * \param de pointer to DetectThresholdData
298
 */
299
DetectThresholdData *DetectThresholdDataCopy(DetectThresholdData *de)
300
0
{
301
0
    DetectThresholdData *new_de = SCCalloc(1, sizeof(DetectThresholdData));
302
0
    if (unlikely(new_de == NULL))
303
0
        return NULL;
304
305
0
    *new_de = *de;
306
0
    new_de->addrs.ipv4_head = NULL;
307
0
    new_de->addrs.ipv6_head = NULL;
308
309
0
    for (DetectAddress *last = NULL, *tmp_ad = de->addrs.ipv4_head; tmp_ad; tmp_ad = tmp_ad->next) {
310
0
        DetectAddress *n_addr = DetectAddressCopy(tmp_ad);
311
0
        if (n_addr == NULL)
312
0
            goto error;
313
0
        if (last == NULL) {
314
0
            new_de->addrs.ipv4_head = n_addr;
315
0
        } else {
316
0
            last->next = n_addr;
317
0
            n_addr->prev = last;
318
0
        }
319
0
        last = n_addr;
320
0
    }
321
0
    for (DetectAddress *last = NULL, *tmp_ad = de->addrs.ipv6_head; tmp_ad; tmp_ad = tmp_ad->next) {
322
0
        DetectAddress *n_addr = DetectAddressCopy(tmp_ad);
323
0
        if (n_addr == NULL)
324
0
            goto error;
325
0
        if (last == NULL) {
326
0
            new_de->addrs.ipv6_head = n_addr;
327
0
        } else {
328
0
            last->next = n_addr;
329
0
            n_addr->prev = last;
330
0
        }
331
0
        last = n_addr;
332
0
    }
333
334
0
    return new_de;
335
336
0
error:
337
0
    DetectThresholdFree(NULL, new_de);
338
    return NULL;
339
0
}
340
341
/*
342
 * ONLY TESTS BELOW THIS COMMENT
343
 */
344
#ifdef UNITTESTS
345
#include "detect-engine.h"
346
#include "detect-engine-mpm.h"
347
#include "detect-engine-alert.h"
348
#include "util-time.h"
349
#include "util-hashlist.h"
350
#include "packet.h"
351
#include "action-globals.h"
352
/**
353
 * \test ThresholdTestParse01 is a test for a valid threshold options
354
 *
355
 *  \retval 1 on success
356
 *  \retval 0 on failure
357
 */
358
static int ThresholdTestParse01(void)
359
{
360
    DetectThresholdData *de = NULL;
361
    de = DetectThresholdParse("type limit,track by_dst,count 10,seconds 60");
362
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) && (de->seconds == 60)) {
363
        DetectThresholdFree(NULL, de);
364
        return 1;
365
    }
366
367
    return 0;
368
}
369
370
/**
371
 * \test ThresholdTestParse02 is a test for a invalid threshold options
372
 *
373
 *  \retval 1 on success
374
 *  \retval 0 on failure
375
 */
376
static int ThresholdTestParse02(void)
377
{
378
    DetectThresholdData *de = NULL;
379
    de = DetectThresholdParse("type any,track by_dst,count 10,seconds 60");
380
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) && (de->seconds == 60)) {
381
        DetectThresholdFree(NULL, de);
382
        return 0;
383
    }
384
385
    return 1;
386
}
387
388
/**
389
 * \test ThresholdTestParse03 is a test for a valid threshold options in any order
390
 *
391
 *  \retval 1 on success
392
 *  \retval 0 on failure
393
 */
394
static int ThresholdTestParse03(void)
395
{
396
    DetectThresholdData *de = NULL;
397
    de = DetectThresholdParse("track by_dst, type limit, seconds 60, count 10");
398
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) && (de->seconds == 60)) {
399
        DetectThresholdFree(NULL, de);
400
        return 1;
401
    }
402
403
    return 0;
404
}
405
406
407
/**
408
 * \test ThresholdTestParse04 is a test for an invalid threshold options in any order
409
 *
410
 *  \retval 1 on success
411
 *  \retval 0 on failure
412
 */
413
static int ThresholdTestParse04(void)
414
{
415
    DetectThresholdData *de = NULL;
416
    de = DetectThresholdParse("count 10, track by_dst, seconds 60, type both, count 10");
417
    if (de && (de->type == TYPE_BOTH) && (de->track == TRACK_DST) && (de->count == 10) && (de->seconds == 60)) {
418
        DetectThresholdFree(NULL, de);
419
        return 0;
420
    }
421
422
    return 1;
423
}
424
425
/**
426
 * \test ThresholdTestParse05 is a test for a valid threshold options in any order
427
 *
428
 *  \retval 1 on success
429
 *  \retval 0 on failure
430
 */
431
static int ThresholdTestParse05(void)
432
{
433
    DetectThresholdData *de = NULL;
434
    de = DetectThresholdParse("count 10, track by_dst, seconds 60, type both");
435
    if (de && (de->type == TYPE_BOTH) && (de->track == TRACK_DST) && (de->count == 10) && (de->seconds == 60)) {
436
        DetectThresholdFree(NULL, de);
437
        return 1;
438
    }
439
440
    return 0;
441
}
442
443
/**
444
 * \test ThresholdTestParse06 is a test for thresholding by_both
445
 *
446
 *  \retval 1 on success
447
 *  \retval 0 on failure
448
 */
449
static int ThresholdTestParse06(void)
450
{
451
    DetectThresholdData *de = NULL;
452
    de = DetectThresholdParse("count 10, track by_both, seconds 60, type limit");
453
    FAIL_IF_NULL(de);
454
    FAIL_IF_NOT(de->type == TYPE_LIMIT);
455
    FAIL_IF_NOT(de->track == TRACK_BOTH);
456
    FAIL_IF_NOT(de->count == 10);
457
    FAIL_IF_NOT(de->seconds == 60);
458
    DetectThresholdFree(NULL, de);
459
    PASS;
460
}
461
462
/**
463
 * \test ThresholdTestParse07 is a test for thresholding by_rule
464
 *
465
 *  \retval 1 on success
466
 *  \retval 0 on failure
467
 */
468
static int ThresholdTestParse07(void)
469
{
470
    DetectThresholdData *de = NULL;
471
    de = DetectThresholdParse("count 10, track by_rule, seconds 60, type limit");
472
    FAIL_IF_NULL(de);
473
    FAIL_IF_NOT(de->type == TYPE_LIMIT);
474
    FAIL_IF_NOT(de->track == TRACK_RULE);
475
    FAIL_IF_NOT(de->count == 10);
476
    FAIL_IF_NOT(de->seconds == 60);
477
    DetectThresholdFree(NULL, de);
478
    PASS;
479
}
480
481
/**
482
 * \test DetectThresholdTestSig1 is a test for checking the working of limit keyword
483
 *       by setting up the signature and later testing its working by matching
484
 *       the received packet against the sig.
485
 *
486
 *  \retval 1 on success
487
 *  \retval 0 on failure
488
 */
489
490
static int DetectThresholdTestSig1(void)
491
{
492
    Packet *p = NULL;
493
    Signature *s = NULL;
494
    ThreadVars th_v;
495
    DetectEngineThreadCtx *det_ctx;
496
    int result = 0;
497
    int alerts = 0;
498
499
    HostInitConfig(HOST_QUIET);
500
501
    memset(&th_v, 0, sizeof(th_v));
502
503
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
504
505
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
506
    if (de_ctx == NULL) {
507
        goto end;
508
    }
509
510
    de_ctx->flags |= DE_QUIET;
511
512
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit\"; content:\"A\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
513
    if (s == NULL) {
514
        goto end;
515
    }
516
517
    SigGroupBuild(de_ctx);
518
519
    FAIL_IF(s->type == SIG_TYPE_IPONLY);
520
521
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
522
523
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
524
    alerts = PacketAlertCheck(p, 1);
525
    if (alerts != 1) {
526
        printf("alerts %"PRIi32", expected 1: ", alerts);
527
    }
528
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
529
    alerts += PacketAlertCheck(p, 1);
530
    if (alerts != 2) {
531
        printf("alerts %"PRIi32", expected 2: ", alerts);
532
    }
533
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
534
    alerts += PacketAlertCheck(p, 1);
535
    if (alerts != 3) {
536
        printf("alerts %"PRIi32", expected 3: ", alerts);
537
    }
538
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
539
    alerts += PacketAlertCheck(p, 1);
540
    if (alerts != 4) {
541
        printf("alerts %"PRIi32", expected 4: ", alerts);
542
    }
543
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
544
    alerts += PacketAlertCheck(p, 1);
545
    if (alerts != 5) {
546
        printf("alerts %"PRIi32", expected 5: ", alerts);
547
    }
548
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
549
    alerts += PacketAlertCheck(p, 1);
550
    if (alerts != 5) {
551
        printf("alerts %"PRIi32", expected 5: ", alerts);
552
    }
553
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
554
    alerts += PacketAlertCheck(p, 1);
555
    if (alerts != 5) {
556
        printf("alerts %"PRIi32", expected 5: ", alerts);
557
    }
558
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
559
    alerts += PacketAlertCheck(p, 1);
560
    if (alerts != 5) {
561
        printf("alerts %"PRIi32", expected 5: ", alerts);
562
    }
563
564
    if(alerts == 5)
565
        result = 1;
566
    else
567
        printf("alerts %"PRIi32", expected 5: ", alerts);
568
569
    SigGroupCleanup(de_ctx);
570
    SigCleanSignatures(de_ctx);
571
572
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
573
    DetectEngineCtxFree(de_ctx);
574
575
    UTHFreePackets(&p, 1);
576
577
    HostShutdown();
578
end:
579
    return result;
580
}
581
582
/**
583
 * \test DetectThresholdTestSig2 is a test for checking the working of threshold keyword
584
 *       by setting up the signature and later testing its working by matching
585
 *       the received packet against the sig.
586
 *
587
 *  \retval 1 on success
588
 *  \retval 0 on failure
589
 */
590
591
static int DetectThresholdTestSig2(void)
592
{
593
    Packet *p = NULL;
594
    Signature *s = NULL;
595
    ThreadVars th_v;
596
    DetectEngineThreadCtx *det_ctx;
597
    int result = 0;
598
    int alerts = 0;
599
600
    HostInitConfig(HOST_QUIET);
601
602
    memset(&th_v, 0, sizeof(th_v));
603
604
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
605
606
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
607
    if (de_ctx == NULL) {
608
        goto end;
609
    }
610
611
    de_ctx->flags |= DE_QUIET;
612
613
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold\"; threshold: type threshold, track by_dst, count 5, seconds 60; sid:1;)");
614
    if (s == NULL) {
615
        goto end;
616
    }
617
618
    SigGroupBuild(de_ctx);
619
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
620
621
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
622
    alerts = PacketAlertCheck(p, 1);
623
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
624
    alerts += PacketAlertCheck(p, 1);
625
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
626
    alerts += PacketAlertCheck(p, 1);
627
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
628
    alerts += PacketAlertCheck(p, 1);
629
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
630
    alerts += PacketAlertCheck(p, 1);
631
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
632
    alerts += PacketAlertCheck(p, 1);
633
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
634
    alerts += PacketAlertCheck(p, 1);
635
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
636
    alerts += PacketAlertCheck(p, 1);
637
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
638
    alerts += PacketAlertCheck(p, 1);
639
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
640
    alerts += PacketAlertCheck(p, 1);
641
642
    if (alerts == 2)
643
        result = 1;
644
    else
645
        goto cleanup;
646
647
cleanup:
648
    SigGroupCleanup(de_ctx);
649
    SigCleanSignatures(de_ctx);
650
651
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
652
    DetectEngineCtxFree(de_ctx);
653
654
end:
655
    UTHFreePackets(&p, 1);
656
    HostShutdown();
657
    return result;
658
}
659
660
/**
661
 * \test DetectThresholdTestSig3 is a test for checking the working of limit keyword
662
 *       by setting up the signature and later testing its working by matching
663
 *       the received packet against the sig.
664
 *
665
 *  \retval 1 on success
666
 *  \retval 0 on failure
667
 */
668
669
static int DetectThresholdTestSig3(void)
670
{
671
    Packet *p = NULL;
672
    Signature *s = NULL;
673
    ThreadVars th_v;
674
    DetectEngineThreadCtx *det_ctx;
675
    int result = 0;
676
    int alerts = 0;
677
    DetectThresholdEntry *lookup_tsh = NULL;
678
679
    HostInitConfig(HOST_QUIET);
680
681
    memset(&th_v, 0, sizeof(th_v));
682
683
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
684
685
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
686
    if (de_ctx == NULL) {
687
        goto end;
688
    }
689
690
    de_ctx->flags |= DE_QUIET;
691
692
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:10;)");
693
    if (s == NULL) {
694
        goto end;
695
    }
696
697
    SigGroupBuild(de_ctx);
698
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
699
700
    p->ts = TimeGet();
701
702
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
703
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
704
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
705
706
    Host *host = HostLookupHostFromHash(&p->dst);
707
    if (host == NULL) {
708
        printf("host not found: ");
709
        goto cleanup;
710
    }
711
712
    if (!(ThresholdHostHasThreshold(host))) {
713
        HostRelease(host);
714
        printf("host has no threshold: ");
715
        goto cleanup;
716
    }
717
    HostRelease(host);
718
719
    TimeSetIncrementTime(200);
720
    p->ts = TimeGet();
721
722
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
723
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
724
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
725
726
    host = HostLookupHostFromHash(&p->dst);
727
    if (host == NULL) {
728
        printf("host not found: ");
729
        goto cleanup;
730
    }
731
    HostRelease(host);
732
733
    lookup_tsh = HostGetStorageById(host, ThresholdHostStorageId());
734
    if (lookup_tsh == NULL) {
735
        HostRelease(host);
736
        printf("lookup_tsh is NULL: ");
737
        goto cleanup;
738
    }
739
740
    alerts = lookup_tsh->current_count;
741
742
    if (alerts == 3)
743
        result = 1;
744
    else {
745
        printf("alerts %u != 3: ", alerts);
746
        goto cleanup;
747
    }
748
749
cleanup:
750
    SigGroupCleanup(de_ctx);
751
    SigCleanSignatures(de_ctx);
752
753
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
754
    DetectEngineCtxFree(de_ctx);
755
end:
756
    UTHFreePackets(&p, 1);
757
    HostShutdown();
758
    return result;
759
}
760
761
/**
762
 * \test DetectThresholdTestSig4 is a test for checking the working of both keyword
763
 *       by setting up the signature and later testing its working by matching
764
 *       the received packet against the sig.
765
 *
766
 *  \retval 1 on success
767
 *  \retval 0 on failure
768
 */
769
770
static int DetectThresholdTestSig4(void)
771
{
772
    Packet *p = NULL;
773
    Signature *s = NULL;
774
    ThreadVars th_v;
775
    DetectEngineThreadCtx *det_ctx;
776
    int result = 0;
777
    int alerts = 0;
778
779
    HostInitConfig(HOST_QUIET);
780
781
    memset(&th_v, 0, sizeof(th_v));
782
783
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
784
785
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
786
    if (de_ctx == NULL) {
787
        goto end;
788
    }
789
790
    de_ctx->flags |= DE_QUIET;
791
792
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold both\"; threshold: type both, track by_dst, count 2, seconds 60; sid:10;)");
793
    if (s == NULL) {
794
        goto end;
795
    }
796
797
    SigGroupBuild(de_ctx);
798
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
799
800
    p->ts = TimeGet();
801
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
802
    alerts = PacketAlertCheck(p, 10);
803
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
804
    alerts += PacketAlertCheck(p, 10);
805
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
806
    alerts += PacketAlertCheck(p, 10);
807
808
    TimeSetIncrementTime(200);
809
    p->ts = TimeGet();
810
811
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
812
    alerts += PacketAlertCheck(p, 10);
813
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
814
    alerts += PacketAlertCheck(p, 10);
815
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
816
    alerts += PacketAlertCheck(p, 10);
817
818
    if (alerts == 2)
819
        result = 1;
820
    else
821
        goto cleanup;
822
823
cleanup:
824
    SigGroupCleanup(de_ctx);
825
    SigCleanSignatures(de_ctx);
826
827
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
828
    DetectEngineCtxFree(de_ctx);
829
end:
830
    UTHFreePackets(&p, 1);
831
    HostShutdown();
832
    return result;
833
}
834
835
/**
836
 * \test DetectThresholdTestSig5 is a test for checking the working of limit keyword
837
 *       by setting up the signature and later testing its working by matching
838
 *       the received packet against the sig.
839
 *
840
 *  \retval 1 on success
841
 *  \retval 0 on failure
842
 */
843
844
static int DetectThresholdTestSig5(void)
845
{
846
    Packet *p = NULL;
847
    Signature *s = NULL;
848
    ThreadVars th_v;
849
    DetectEngineThreadCtx *det_ctx;
850
    int result = 0;
851
    int alerts = 0;
852
853
    HostInitConfig(HOST_QUIET);
854
855
    memset(&th_v, 0, sizeof(th_v));
856
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
857
858
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
859
    if (de_ctx == NULL) {
860
        goto end;
861
    }
862
863
    de_ctx->flags |= DE_QUIET;
864
865
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
866
    if (s == NULL) {
867
        goto end;
868
    }
869
870
    s = s->next = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
871
    if (s == NULL) {
872
        goto end;
873
    }
874
875
    SigGroupBuild(de_ctx);
876
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
877
878
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
879
    alerts = PacketAlertCheck(p, 1);
880
    alerts += PacketAlertCheck(p, 1000);
881
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
882
    alerts += PacketAlertCheck(p, 1);
883
    alerts += PacketAlertCheck(p, 1000);
884
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
885
    alerts += PacketAlertCheck(p, 1);
886
    alerts += PacketAlertCheck(p, 1000);
887
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
888
    alerts += PacketAlertCheck(p, 1);
889
    alerts += PacketAlertCheck(p, 1000);
890
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
891
    alerts += PacketAlertCheck(p, 1);
892
    alerts += PacketAlertCheck(p, 1000);
893
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
894
    alerts += PacketAlertCheck(p, 1);
895
    alerts += PacketAlertCheck(p, 1000);
896
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
897
    alerts += PacketAlertCheck(p, 1);
898
    alerts += PacketAlertCheck(p, 1000);
899
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
900
    alerts += PacketAlertCheck(p, 1);
901
    alerts += PacketAlertCheck(p, 1000);
902
903
    if(alerts == 10)
904
        result = 1;
905
    else {
906
        printf("alerts %d != 10: ", alerts);
907
        goto cleanup;
908
    }
909
910
cleanup:
911
    SigGroupCleanup(de_ctx);
912
    SigCleanSignatures(de_ctx);
913
914
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
915
    DetectEngineCtxFree(de_ctx);
916
917
end:
918
    UTHFreePackets(&p, 1);
919
    HostShutdown();
920
    return result;
921
}
922
923
static int DetectThresholdTestSig6Ticks(void)
924
{
925
    Packet *p = NULL;
926
    Signature *s = NULL;
927
    ThreadVars th_v;
928
    DetectEngineThreadCtx *det_ctx;
929
    int result = 0;
930
    int alerts = 0;
931
932
    HostInitConfig(HOST_QUIET);
933
934
    memset(&th_v, 0, sizeof(th_v));
935
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
936
937
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
938
    if (de_ctx == NULL) {
939
        goto end;
940
    }
941
942
    de_ctx->flags |= DE_QUIET;
943
944
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
945
    if (s == NULL) {
946
        goto end;
947
    }
948
949
    s = s->next = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
950
    if (s == NULL) {
951
        goto end;
952
    }
953
954
    SigGroupBuild(de_ctx);
955
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
956
957
    uint64_t ticks_start = 0;
958
    uint64_t ticks_end = 0;
959
960
    ticks_start = UtilCpuGetTicks();
961
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
962
    alerts = PacketAlertCheck(p, 1);
963
    alerts += PacketAlertCheck(p, 1000);
964
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
965
    alerts += PacketAlertCheck(p, 1);
966
    alerts += PacketAlertCheck(p, 1000);
967
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
968
    alerts += PacketAlertCheck(p, 1);
969
    alerts += PacketAlertCheck(p, 1000);
970
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
971
    alerts += PacketAlertCheck(p, 1);
972
    alerts += PacketAlertCheck(p, 1000);
973
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
974
    alerts += PacketAlertCheck(p, 1);
975
    alerts += PacketAlertCheck(p, 1000);
976
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
977
    alerts += PacketAlertCheck(p, 1);
978
    alerts += PacketAlertCheck(p, 1000);
979
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
980
    alerts += PacketAlertCheck(p, 1);
981
    alerts += PacketAlertCheck(p, 1000);
982
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
983
    alerts += PacketAlertCheck(p, 1);
984
    alerts += PacketAlertCheck(p, 1000);
985
    ticks_end = UtilCpuGetTicks();
986
    printf("test run %"PRIu64"\n", (ticks_end - ticks_start));
987
988
    if(alerts == 10)
989
        result = 1;
990
    else
991
        goto cleanup;
992
993
cleanup:
994
    SigGroupCleanup(de_ctx);
995
    SigCleanSignatures(de_ctx);
996
997
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
998
    DetectEngineCtxFree(de_ctx);
999
1000
end:
1001
    UTHFreePackets(&p, 1);
1002
    HostShutdown();
1003
    return result;
1004
}
1005
1006
/**
1007
 * \test Test drop action being set even if thresholded
1008
 */
1009
static int DetectThresholdTestSig7(void)
1010
{
1011
    Packet *p = NULL;
1012
    Signature *s = NULL;
1013
    ThreadVars th_v;
1014
    DetectEngineThreadCtx *det_ctx;
1015
    int result = 0;
1016
    int alerts = 0;
1017
    int drops = 0;
1018
1019
    HostInitConfig(HOST_QUIET);
1020
1021
    memset(&th_v, 0, sizeof(th_v));
1022
1023
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1024
1025
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1026
    if (de_ctx == NULL) {
1027
        goto end;
1028
    }
1029
1030
    de_ctx->flags |= DE_QUIET;
1031
1032
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type limit, track by_src, count 1, seconds 300; sid:10;)");
1033
    if (s == NULL) {
1034
        goto end;
1035
    }
1036
1037
    SigGroupBuild(de_ctx);
1038
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1039
1040
    p->ts = TimeGet();
1041
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1042
    alerts = PacketAlertCheck(p, 10);
1043
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1044
    p->action = 0;
1045
1046
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1047
    alerts += PacketAlertCheck(p, 10);
1048
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1049
    p->action = 0;
1050
1051
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1052
    alerts += PacketAlertCheck(p, 10);
1053
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1054
    p->action = 0;
1055
1056
    TimeSetIncrementTime(200);
1057
    p->ts = TimeGet();
1058
1059
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1060
    alerts += PacketAlertCheck(p, 10);
1061
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1062
    p->action = 0;
1063
1064
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1065
    alerts += PacketAlertCheck(p, 10);
1066
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1067
    p->action = 0;
1068
1069
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1070
    alerts += PacketAlertCheck(p, 10);
1071
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1072
    p->action = 0;
1073
1074
    if (alerts == 1 && drops == 6)
1075
        result = 1;
1076
    else {
1077
        if (alerts != 1)
1078
            printf("alerts: %d != 1: ", alerts);
1079
        if (drops != 6)
1080
            printf("drops: %d != 6: ", drops);
1081
        goto cleanup;
1082
    }
1083
1084
cleanup:
1085
    SigGroupCleanup(de_ctx);
1086
    SigCleanSignatures(de_ctx);
1087
1088
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1089
    DetectEngineCtxFree(de_ctx);
1090
end:
1091
    UTHFreePackets(&p, 1);
1092
    HostShutdown();
1093
    return result;
1094
}
1095
1096
/**
1097
 * \test Test drop action being set even if thresholded
1098
 */
1099
static int DetectThresholdTestSig8(void)
1100
{
1101
    Packet *p = NULL;
1102
    Signature *s = NULL;
1103
    ThreadVars th_v;
1104
    DetectEngineThreadCtx *det_ctx;
1105
    int result = 0;
1106
    int alerts = 0;
1107
    int drops = 0;
1108
1109
    HostInitConfig(HOST_QUIET);
1110
1111
    memset(&th_v, 0, sizeof(th_v));
1112
1113
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1114
1115
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1116
    if (de_ctx == NULL) {
1117
        goto end;
1118
    }
1119
1120
    de_ctx->flags |= DE_QUIET;
1121
1122
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type limit, track by_src, count 2, seconds 300; sid:10;)");
1123
    if (s == NULL) {
1124
        goto end;
1125
    }
1126
1127
    SigGroupBuild(de_ctx);
1128
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1129
1130
    p->ts = TimeGet();
1131
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1132
    alerts = PacketAlertCheck(p, 10);
1133
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1134
    p->action = 0;
1135
1136
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1137
    alerts += PacketAlertCheck(p, 10);
1138
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1139
    p->action = 0;
1140
1141
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1142
    alerts += PacketAlertCheck(p, 10);
1143
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1144
    p->action = 0;
1145
1146
    TimeSetIncrementTime(200);
1147
    p->ts = TimeGet();
1148
1149
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1150
    alerts += PacketAlertCheck(p, 10);
1151
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1152
    p->action = 0;
1153
1154
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1155
    alerts += PacketAlertCheck(p, 10);
1156
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1157
    p->action = 0;
1158
1159
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1160
    alerts += PacketAlertCheck(p, 10);
1161
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1162
    p->action = 0;
1163
1164
    if (alerts == 2 && drops == 6)
1165
        result = 1;
1166
    else {
1167
        if (alerts != 1)
1168
            printf("alerts: %d != 1: ", alerts);
1169
        if (drops != 6)
1170
            printf("drops: %d != 6: ", drops);
1171
        goto cleanup;
1172
    }
1173
1174
cleanup:
1175
    SigGroupCleanup(de_ctx);
1176
    SigCleanSignatures(de_ctx);
1177
1178
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1179
    DetectEngineCtxFree(de_ctx);
1180
end:
1181
    UTHFreePackets(&p, 1);
1182
    HostShutdown();
1183
    return result;
1184
}
1185
1186
/**
1187
 * \test Test drop action being set even if thresholded
1188
 */
1189
static int DetectThresholdTestSig9(void)
1190
{
1191
    Packet *p = NULL;
1192
    Signature *s = NULL;
1193
    ThreadVars th_v;
1194
    DetectEngineThreadCtx *det_ctx;
1195
    int result = 0;
1196
    int alerts = 0;
1197
    int drops = 0;
1198
1199
    HostInitConfig(HOST_QUIET);
1200
1201
    memset(&th_v, 0, sizeof(th_v));
1202
1203
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1204
1205
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1206
    if (de_ctx == NULL) {
1207
        goto end;
1208
    }
1209
1210
    de_ctx->flags |= DE_QUIET;
1211
1212
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type threshold, track by_src, count 3, seconds 100; sid:10;)");
1213
    if (s == NULL) {
1214
        goto end;
1215
    }
1216
1217
    SigGroupBuild(de_ctx);
1218
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1219
1220
    p->ts = TimeGet();
1221
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1222
    alerts = PacketAlertCheck(p, 10);
1223
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1224
    p->action = 0;
1225
1226
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1227
    alerts += PacketAlertCheck(p, 10);
1228
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1229
    p->action = 0;
1230
1231
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1232
    alerts += PacketAlertCheck(p, 10);
1233
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1234
    p->action = 0;
1235
1236
    TimeSetIncrementTime(200);
1237
    p->ts = TimeGet();
1238
1239
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1240
    alerts += PacketAlertCheck(p, 10);
1241
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1242
    p->action = 0;
1243
1244
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1245
    alerts += PacketAlertCheck(p, 10);
1246
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1247
    p->action = 0;
1248
1249
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1250
    alerts += PacketAlertCheck(p, 10);
1251
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1252
    p->action = 0;
1253
1254
    if (alerts == 2 && drops == 2)
1255
        result = 1;
1256
    else {
1257
        if (alerts != 2)
1258
            printf("alerts: %d != 2: ", alerts);
1259
        if (drops != 2)
1260
            printf("drops: %d != 2: ", drops);
1261
        goto cleanup;
1262
    }
1263
1264
cleanup:
1265
    SigGroupCleanup(de_ctx);
1266
    SigCleanSignatures(de_ctx);
1267
1268
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1269
    DetectEngineCtxFree(de_ctx);
1270
end:
1271
    UTHFreePackets(&p, 1);
1272
    HostShutdown();
1273
    return result;
1274
}
1275
1276
/**
1277
 * \test Test drop action being set even if thresholded
1278
 */
1279
static int DetectThresholdTestSig10(void)
1280
{
1281
    Packet *p = NULL;
1282
    Signature *s = NULL;
1283
    ThreadVars th_v;
1284
    DetectEngineThreadCtx *det_ctx;
1285
    int result = 0;
1286
    int alerts = 0;
1287
    int drops = 0;
1288
1289
    HostInitConfig(HOST_QUIET);
1290
1291
    memset(&th_v, 0, sizeof(th_v));
1292
1293
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1294
1295
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1296
    if (de_ctx == NULL) {
1297
        goto end;
1298
    }
1299
1300
    de_ctx->flags |= DE_QUIET;
1301
1302
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type threshold, track by_src, count 5, seconds 300; sid:10;)");
1303
    if (s == NULL) {
1304
        goto end;
1305
    }
1306
1307
    SigGroupBuild(de_ctx);
1308
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1309
1310
    p->ts = TimeGet();
1311
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1312
    alerts = PacketAlertCheck(p, 10);
1313
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1314
    p->action = 0;
1315
1316
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1317
    alerts += PacketAlertCheck(p, 10);
1318
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1319
    p->action = 0;
1320
1321
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1322
    alerts += PacketAlertCheck(p, 10);
1323
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1324
    p->action = 0;
1325
1326
    TimeSetIncrementTime(200);
1327
    p->ts = TimeGet();
1328
1329
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1330
    alerts += PacketAlertCheck(p, 10);
1331
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1332
    p->action = 0;
1333
1334
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1335
    alerts += PacketAlertCheck(p, 10);
1336
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1337
    p->action = 0;
1338
1339
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1340
    alerts += PacketAlertCheck(p, 10);
1341
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1342
    p->action = 0;
1343
1344
    if (alerts == 1 && drops == 1)
1345
        result = 1;
1346
    else {
1347
        if (alerts != 1)
1348
            printf("alerts: %d != 1: ", alerts);
1349
        if (drops != 1)
1350
            printf("drops: %d != 1: ", drops);
1351
        goto cleanup;
1352
    }
1353
1354
cleanup:
1355
    SigGroupCleanup(de_ctx);
1356
    SigCleanSignatures(de_ctx);
1357
1358
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1359
    DetectEngineCtxFree(de_ctx);
1360
end:
1361
    UTHFreePackets(&p, 1);
1362
    HostShutdown();
1363
    return result;
1364
}
1365
1366
/**
1367
 * \test Test drop action being set even if thresholded
1368
 */
1369
static int DetectThresholdTestSig11(void)
1370
{
1371
    Packet *p = NULL;
1372
    Signature *s = NULL;
1373
    ThreadVars th_v;
1374
    DetectEngineThreadCtx *det_ctx;
1375
    int result = 0;
1376
    int alerts = 0;
1377
    int drops = 0;
1378
1379
    HostInitConfig(HOST_QUIET);
1380
1381
    memset(&th_v, 0, sizeof(th_v));
1382
1383
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1384
1385
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1386
    if (de_ctx == NULL) {
1387
        goto end;
1388
    }
1389
1390
    de_ctx->flags |= DE_QUIET;
1391
1392
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type both, track by_src, count 3, seconds 300; sid:10;)");
1393
    if (s == NULL) {
1394
        goto end;
1395
    }
1396
1397
    SigGroupBuild(de_ctx);
1398
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1399
1400
    p->ts = TimeGet();
1401
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1402
    alerts = PacketAlertCheck(p, 10);
1403
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1404
    p->action = 0;
1405
1406
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1407
    alerts += PacketAlertCheck(p, 10);
1408
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1409
    p->action = 0;
1410
1411
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1412
    alerts += PacketAlertCheck(p, 10);
1413
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1414
    p->action = 0;
1415
1416
    TimeSetIncrementTime(200);
1417
    p->ts = TimeGet();
1418
1419
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1420
    alerts += PacketAlertCheck(p, 10);
1421
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1422
    p->action = 0;
1423
1424
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1425
    alerts += PacketAlertCheck(p, 10);
1426
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1427
    p->action = 0;
1428
1429
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1430
    alerts += PacketAlertCheck(p, 10);
1431
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1432
    p->action = 0;
1433
1434
    if (alerts == 1 && drops == 4)
1435
        result = 1;
1436
    else {
1437
        if (alerts != 1)
1438
            printf("alerts: %d != 1: ", alerts);
1439
        if (drops != 4)
1440
            printf("drops: %d != 4: ", drops);
1441
        goto cleanup;
1442
    }
1443
1444
cleanup:
1445
    SigGroupCleanup(de_ctx);
1446
    SigCleanSignatures(de_ctx);
1447
1448
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1449
    DetectEngineCtxFree(de_ctx);
1450
end:
1451
    UTHFreePackets(&p, 1);
1452
    HostShutdown();
1453
    return result;
1454
}
1455
1456
/**
1457
 * \test Test drop action being set even if thresholded
1458
 */
1459
static int DetectThresholdTestSig12(void)
1460
{
1461
    Packet *p = NULL;
1462
    Signature *s = NULL;
1463
    ThreadVars th_v;
1464
    DetectEngineThreadCtx *det_ctx;
1465
    int result = 0;
1466
    int alerts = 0;
1467
    int drops = 0;
1468
1469
    HostInitConfig(HOST_QUIET);
1470
1471
    memset(&th_v, 0, sizeof(th_v));
1472
1473
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1474
1475
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1476
    if (de_ctx == NULL) {
1477
        goto end;
1478
    }
1479
1480
    de_ctx->flags |= DE_QUIET;
1481
1482
    s = de_ctx->sig_list = SigInit(de_ctx,"drop tcp any any -> any 80 (threshold: type both, track by_src, count 5, seconds 300; sid:10;)");
1483
    if (s == NULL) {
1484
        goto end;
1485
    }
1486
1487
    SigGroupBuild(de_ctx);
1488
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1489
1490
    p->ts = TimeGet();
1491
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1492
    alerts = PacketAlertCheck(p, 10);
1493
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1494
    p->action = 0;
1495
1496
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1497
    alerts += PacketAlertCheck(p, 10);
1498
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1499
    p->action = 0;
1500
1501
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1502
    alerts += PacketAlertCheck(p, 10);
1503
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1504
    p->action = 0;
1505
1506
    TimeSetIncrementTime(200);
1507
    p->ts = TimeGet();
1508
1509
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1510
    alerts += PacketAlertCheck(p, 10);
1511
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1512
    p->action = 0;
1513
1514
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1515
    alerts += PacketAlertCheck(p, 10);
1516
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1517
    p->action = 0;
1518
1519
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1520
    alerts += PacketAlertCheck(p, 10);
1521
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1522
    p->action = 0;
1523
1524
    if (alerts == 1 && drops == 2)
1525
        result = 1;
1526
    else {
1527
        if (alerts != 1)
1528
            printf("alerts: %d != 1: ", alerts);
1529
        if (drops != 2)
1530
            printf("drops: %d != 2: ", drops);
1531
        goto cleanup;
1532
    }
1533
1534
cleanup:
1535
    SigGroupCleanup(de_ctx);
1536
    SigCleanSignatures(de_ctx);
1537
1538
    DetectEngineThreadCtxDeinit(&th_v, (void*)det_ctx);
1539
    DetectEngineCtxFree(de_ctx);
1540
end:
1541
    UTHFreePackets(&p, 1);
1542
    HostShutdown();
1543
    return result;
1544
}
1545
1546
/**
1547
 * \test DetectThresholdTestSig13 is a test for checking the working by_rule limits
1548
 *       by setting up the signature and later testing its working by matching
1549
 *       received packets against the sig.
1550
 *
1551
 *  \retval 1 on success
1552
 *  \retval 0 on failure
1553
 */
1554
1555
static int DetectThresholdTestSig13(void)
1556
{
1557
    Packet *p = NULL;
1558
    Signature *s = NULL;
1559
    ThreadVars th_v;
1560
    DetectEngineThreadCtx *det_ctx;
1561
    int alerts = 0;
1562
1563
    HostInitConfig(HOST_QUIET);
1564
1565
    memset(&th_v, 0, sizeof(th_v));
1566
    p = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1567
    FAIL_IF_NULL(p);
1568
1569
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1570
    FAIL_IF_NULL(de_ctx);
1571
1572
    de_ctx->flags |= DE_QUIET;
1573
1574
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; threshold: type limit, track by_rule, count 2, seconds 60; sid:1;)");
1575
    FAIL_IF_NULL(s);
1576
1577
    SigGroupBuild(de_ctx);
1578
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1579
1580
    /* should alert twice */
1581
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1582
    alerts += PacketAlertCheck(p, 1);
1583
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1584
    alerts += PacketAlertCheck(p, 1);
1585
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1586
    alerts += PacketAlertCheck(p, 1);
1587
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1588
    alerts += PacketAlertCheck(p, 1);
1589
1590
    FAIL_IF(alerts != 2);
1591
1592
    TimeSetIncrementTime(70);
1593
    p->ts = TimeGet();
1594
1595
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1596
    alerts += PacketAlertCheck(p, 1);
1597
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1598
    alerts += PacketAlertCheck(p, 1);
1599
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1600
    alerts += PacketAlertCheck(p, 1);
1601
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1602
    alerts += PacketAlertCheck(p, 1);
1603
1604
    FAIL_IF(alerts != 4);
1605
1606
    SigGroupCleanup(de_ctx);
1607
    SigCleanSignatures(de_ctx);
1608
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1609
    DetectEngineCtxFree(de_ctx);
1610
    UTHFreePackets(&p, 1);
1611
    HostShutdown();
1612
    PASS;
1613
}
1614
1615
/**
1616
 * \test DetectThresholdTestSig14 is a test for checking the working by_both limits
1617
 *       by setting up the signature and later testing its working by matching
1618
 *       received packets against the sig.
1619
 *
1620
 *  \retval 1 on success
1621
 *  \retval 0 on failure
1622
 */
1623
1624
static int DetectThresholdTestSig14(void)
1625
{
1626
    Packet *p1 = NULL;
1627
    Packet *p2 = NULL;
1628
    Signature *s = NULL;
1629
    ThreadVars th_v;
1630
    DetectEngineThreadCtx *det_ctx;
1631
    int alerts1 = 0;
1632
    int alerts2 = 0;
1633
1634
    HostInitConfig(HOST_QUIET);
1635
    IPPairInitConfig(IPPAIR_QUIET);
1636
1637
    memset(&th_v, 0, sizeof(th_v));
1638
    p1 = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1639
    p2 = UTHBuildPacketReal((uint8_t *)"A",1,IPPROTO_TCP, "1.1.1.1", "3.3.3.3", 1024, 80);
1640
    FAIL_IF_NULL(p1);
1641
    FAIL_IF_NULL(p2);
1642
1643
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1644
    FAIL_IF_NULL(de_ctx);
1645
1646
    de_ctx->flags |= DE_QUIET;
1647
1648
    s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; threshold: type limit, track by_both, count 2, seconds 60; sid:1;)");
1649
    FAIL_IF_NULL(s);
1650
1651
    SigGroupBuild(de_ctx);
1652
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1653
1654
    /* Both p1 and p2 should alert twice */
1655
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1656
    alerts1 += PacketAlertCheck(p1, 1);
1657
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1658
    alerts1 += PacketAlertCheck(p1, 1);
1659
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1660
    alerts1 += PacketAlertCheck(p1, 1);
1661
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1662
    alerts1 += PacketAlertCheck(p1, 1);
1663
1664
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1665
    alerts2 += PacketAlertCheck(p2, 1);
1666
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1667
    alerts2 += PacketAlertCheck(p2, 1);
1668
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1669
    alerts2 += PacketAlertCheck(p2, 1);
1670
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1671
    alerts2 += PacketAlertCheck(p2, 1);
1672
1673
    FAIL_IF(alerts1 != 2);
1674
    FAIL_IF(alerts2 != 2);
1675
1676
    TimeSetIncrementTime(70);
1677
    p1->ts = TimeGet();
1678
    p2->ts = TimeGet();
1679
1680
    /* Now they should both alert again after previous alerts expire */
1681
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1682
    alerts1 += PacketAlertCheck(p1, 1);
1683
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1684
    alerts2 += PacketAlertCheck(p2, 1);
1685
1686
    FAIL_IF(alerts1 != 3);
1687
    FAIL_IF(alerts2 != 3);
1688
1689
    SigGroupCleanup(de_ctx);
1690
    SigCleanSignatures(de_ctx);
1691
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1692
    DetectEngineCtxFree(de_ctx);
1693
    UTHFreePackets(&p1, 1);
1694
    UTHFreePackets(&p2, 1);
1695
    HostShutdown();
1696
    PASS;
1697
}
1698
1699
static void ThresholdRegisterTests(void)
1700
{
1701
    UtRegisterTest("ThresholdTestParse01", ThresholdTestParse01);
1702
    UtRegisterTest("ThresholdTestParse02", ThresholdTestParse02);
1703
    UtRegisterTest("ThresholdTestParse03", ThresholdTestParse03);
1704
    UtRegisterTest("ThresholdTestParse04", ThresholdTestParse04);
1705
    UtRegisterTest("ThresholdTestParse05", ThresholdTestParse05);
1706
    UtRegisterTest("ThresholdTestParse06", ThresholdTestParse06);
1707
    UtRegisterTest("ThresholdTestParse07", ThresholdTestParse07);
1708
    UtRegisterTest("DetectThresholdTestSig1", DetectThresholdTestSig1);
1709
    UtRegisterTest("DetectThresholdTestSig2", DetectThresholdTestSig2);
1710
    UtRegisterTest("DetectThresholdTestSig3", DetectThresholdTestSig3);
1711
    UtRegisterTest("DetectThresholdTestSig4", DetectThresholdTestSig4);
1712
    UtRegisterTest("DetectThresholdTestSig5", DetectThresholdTestSig5);
1713
    UtRegisterTest("DetectThresholdTestSig6Ticks",
1714
                   DetectThresholdTestSig6Ticks);
1715
    UtRegisterTest("DetectThresholdTestSig7", DetectThresholdTestSig7);
1716
    UtRegisterTest("DetectThresholdTestSig8", DetectThresholdTestSig8);
1717
    UtRegisterTest("DetectThresholdTestSig9", DetectThresholdTestSig9);
1718
    UtRegisterTest("DetectThresholdTestSig10", DetectThresholdTestSig10);
1719
    UtRegisterTest("DetectThresholdTestSig11", DetectThresholdTestSig11);
1720
    UtRegisterTest("DetectThresholdTestSig12", DetectThresholdTestSig12);
1721
    UtRegisterTest("DetectThresholdTestSig13", DetectThresholdTestSig13);
1722
    UtRegisterTest("DetectThresholdTestSig14", DetectThresholdTestSig14);
1723
}
1724
#endif /* UNITTESTS */
1725
1726
/**
1727
 * @}
1728
 */