• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OISF / suricata / 23350122333

20 Mar 2026 03:33PM UTC coverage: 76.492% (-2.8%) from 79.315%
23350122333

Pull #15053

github

web-flow
Merge f5bf69f97 into 6587e363a
Pull Request #15053: Flow queue/v3

113 of 129 new or added lines in 9 files covered. (87.6%)

9534 existing lines in 453 files now uncovered.

256601 of 335461 relevant lines covered (76.49%)

4680806.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.37
/src/detect-threshold.c
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
#define PARSE_REGEX_NAME "(track|type|count|seconds|multiplier)"
64
#define PARSE_REGEX_VALUE                                                                          \
65
    "(limit|both|threshold|backoff|by_dst|by_src|by_both|by_rule|by_flow|\\d+)"
66

67
#define PARSE_REGEX                                                                                \
68
    "^\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE "\\s*,\\s*" PARSE_REGEX_NAME                 \
2,222✔
69
    "\\s+" PARSE_REGEX_VALUE "\\s*,\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE                 \
2,222✔
70
    "\\s*,\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE "\\s*"
2,222✔
71

72
static DetectParseRegex parse_regex;
73

74
static int DetectThresholdMatch(
75
        DetectEngineThreadCtx *, Packet *, const Signature *, const SigMatchCtx *);
76
static int DetectThresholdSetup(DetectEngineCtx *, Signature *, const char *);
77
static void DetectThresholdFree(DetectEngineCtx *, void *);
78
#ifdef UNITTESTS
79
static void ThresholdRegisterTests(void);
80
#endif
81

82
/**
83
 * \brief Registration function for threshold: keyword
84
 */
85

86
void DetectThresholdRegister(void)
87
{
2,222✔
88
    sigmatch_table[DETECT_THRESHOLD].name = "threshold";
2,222✔
89
    sigmatch_table[DETECT_THRESHOLD].desc = "control the rule's alert frequency";
2,222✔
90
    sigmatch_table[DETECT_THRESHOLD].url = "/rules/thresholding.html#threshold";
2,222✔
91
    sigmatch_table[DETECT_THRESHOLD].Match = DetectThresholdMatch;
2,222✔
92
    sigmatch_table[DETECT_THRESHOLD].Setup = DetectThresholdSetup;
2,222✔
93
    sigmatch_table[DETECT_THRESHOLD].Free = DetectThresholdFree;
2,222✔
94
#ifdef UNITTESTS
3✔
95
    sigmatch_table[DETECT_THRESHOLD].RegisterTests = ThresholdRegisterTests;
3✔
96
#endif
3✔
97
    /* this is compatible to ip-only signatures */
98
    sigmatch_table[DETECT_THRESHOLD].flags |= SIGMATCH_IPONLY_COMPAT;
2,222✔
99

100
    DetectSetupParseRegexes(PARSE_REGEX, &parse_regex);
2,222✔
101
}
2,222✔
102

103
static int DetectThresholdMatch(
104
        DetectEngineThreadCtx *det_ctx, Packet *p, const Signature *s, const SigMatchCtx *ctx)
105
{
×
106
    return 1;
×
107
}
×
108

109
/**
110
 * \internal
111
 * \brief This function is used to parse threshold options passed via threshold: keyword
112
 *
113
 * \param rawstr Pointer to the user provided threshold options
114
 *
115
 * \retval de pointer to DetectThresholdData on success
116
 * \retval NULL on failure
117
 */
118
static DetectThresholdData *DetectThresholdParse(const char *rawstr)
119
{
2,292✔
120
    DetectThresholdData *de = NULL;
2,292✔
121
    int ret = 0, res = 0;
2,292✔
122
    size_t pcre2_len;
2,292✔
123
    const char *str_ptr = NULL;
2,292✔
124
    char *args[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
2,292✔
125
    char *copy_str = NULL, *threshold_opt = NULL;
2,292✔
126
    int second_found = 0, count_found = 0;
2,292✔
127
    int type_found = 0, track_found = 0;
2,292✔
128
    int multiplier_found = 0;
2,292✔
129
    int second_pos = 0, count_pos = 0, multiplier_pos = 0;
2,292✔
130
    size_t pos = 0;
2,292✔
131
    int i = 0;
2,292✔
132
    pcre2_match_data *match = NULL;
2,292✔
133

134
    copy_str = SCStrdup(rawstr);
2,292✔
135
    if (unlikely(copy_str == NULL)) {
2,292✔
136
        goto error;
×
137
    }
×
138

139
    char *saveptr = NULL;
2,292✔
140
    for (pos = 0, threshold_opt = strtok_r(copy_str, ",", &saveptr);
2,292✔
141
            pos < strlen(copy_str) && threshold_opt != NULL;
11,461✔
142
            pos++, threshold_opt = strtok_r(NULL, ",", &saveptr)) {
9,169✔
143
        if (strstr(threshold_opt, "count"))
9,169✔
144
            count_found++;
2,293✔
145
        if (strstr(threshold_opt, "second"))
9,169✔
146
            second_found++;
2,276✔
147
        if (strstr(threshold_opt, "type"))
9,169✔
148
            type_found++;
2,292✔
149
        if (strstr(threshold_opt, "track"))
9,169✔
150
            track_found++;
2,292✔
151
        if (strstr(threshold_opt, "multiplier"))
9,169✔
152
            multiplier_found++;
16✔
153
    }
9,169✔
154
    SCFree(copy_str);
2,292✔
155
    copy_str = NULL;
2,292✔
156

157
    if (!(count_found == 1 && (second_found == 1 || multiplier_found == 1) && track_found == 1 &&
2,292✔
158
                type_found == 1)) {
2,292✔
159
        goto error;
1✔
160
    }
1✔
161

162
    ret = DetectParsePcreExec(&parse_regex, &match, rawstr, 0, 0);
2,291✔
163
    if (ret < 5 || ret > 9) {
2,291✔
164
        SCLogError("pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr);
1✔
165
        goto error;
1✔
166
    }
1✔
167

168
    de = SCCalloc(1, sizeof(DetectThresholdData));
2,290✔
169
    if (unlikely(de == NULL))
2,290✔
170
        goto error;
×
171

172
    for (i = 0; i < (ret - 1); i++) {
20,610✔
173

174
        res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
18,320✔
175

176
        if (res < 0) {
18,320✔
177
            SCLogError("pcre2_substring_get_bynumber failed");
×
178
            goto error;
×
179
        }
×
180

181
        args[i] = (char *)str_ptr;
18,320✔
182

183
        if (strncasecmp(args[i], "limit", strlen("limit")) == 0)
18,320✔
184
            de->type = TYPE_LIMIT;
1,494✔
185
        if (strncasecmp(args[i], "both", strlen("both")) == 0)
18,320✔
186
            de->type = TYPE_BOTH;
675✔
187
        if (strncasecmp(args[i], "threshold", strlen("threshold")) == 0)
18,320✔
188
            de->type = TYPE_THRESHOLD;
105✔
189
        if (strcasecmp(args[i], "backoff") == 0)
18,320✔
190
            de->type = TYPE_BACKOFF;
16✔
191
        if (strncasecmp(args[i], "by_dst", strlen("by_dst")) == 0)
18,320✔
192
            de->track = TRACK_DST;
230✔
193
        if (strncasecmp(args[i], "by_src", strlen("by_src")) == 0)
18,320✔
194
            de->track = TRACK_SRC;
2,035✔
195
        if (strncasecmp(args[i], "by_both", strlen("by_both")) == 0)
18,320✔
196
            de->track = TRACK_BOTH;
2✔
197
        if (strncasecmp(args[i], "by_rule", strlen("by_rule")) == 0)
18,320✔
198
            de->track = TRACK_RULE;
3✔
199
        if (strncasecmp(args[i], "by_flow", strlen("by_flow")) == 0)
18,320✔
200
            de->track = TRACK_FLOW;
20✔
201
        if (strncasecmp(args[i], "count", strlen("count")) == 0)
18,320✔
202
            count_pos = i + 1;
2,290✔
203
        if (strncasecmp(args[i], "seconds", strlen("seconds")) == 0)
18,320✔
204
            second_pos = i + 1;
2,274✔
205
        if (strcasecmp(args[i], "multiplier") == 0)
18,320✔
206
            multiplier_pos = i + 1;
16✔
207
    }
18,320✔
208

209
    if (de->type != TYPE_BACKOFF) {
2,290✔
210
        if (args[count_pos] == NULL || args[second_pos] == NULL) {
2,274✔
211
            goto error;
×
212
        }
×
213

214
        if (StringParseUint32(&de->count, 10, strlen(args[count_pos]), args[count_pos]) <= 0) {
2,274✔
UNCOV
215
            goto error;
×
UNCOV
216
        }
×
217
        if (StringParseUint32(&de->seconds, 10, strlen(args[second_pos]), args[second_pos]) <= 0) {
2,274✔
UNCOV
218
            goto error;
×
UNCOV
219
        }
×
220
    } else {
2,274✔
221
        if (args[count_pos] == NULL || args[multiplier_pos] == NULL) {
16✔
222
            goto error;
×
223
        }
×
224

225
        if (second_found) {
16✔
UNCOV
226
            goto error;
×
UNCOV
227
        }
×
228

229
        if (StringParseUint32(&de->count, 10, strlen(args[count_pos]), args[count_pos]) <= 0) {
16✔
UNCOV
230
            goto error;
×
UNCOV
231
        }
×
232
        if (StringParseUint32(
16✔
233
                    &de->multiplier, 10, strlen(args[multiplier_pos]), args[multiplier_pos]) <= 0) {
16✔
UNCOV
234
            goto error;
×
UNCOV
235
        }
×
236

237
        /* impose some sanity limits on the count and multiplier values. Upper bounds are a bit
238
         * artificial. */
239
        if (!(de->count > 0 && de->count < 65536)) {
16✔
UNCOV
240
            SCLogError("invalid count value '%u': must be in the range 1-65535", de->count);
×
UNCOV
241
            goto error;
×
UNCOV
242
        }
×
243
        if (!(de->multiplier > 1 && de->multiplier < 65536)) {
16✔
UNCOV
244
            SCLogError(
×
UNCOV
245
                    "invalid multiplier value '%u': must be in the range 2-65535", de->multiplier);
×
UNCOV
246
            goto error;
×
UNCOV
247
        }
×
248

249
        if (de->track != TRACK_FLOW) {
16✔
UNCOV
250
            SCLogError("invalid track value: type backoff only supported for track by_flow");
×
UNCOV
251
            goto error;
×
UNCOV
252
        }
×
253

254
        SCLogDebug("TYPE_BACKOFF count %u multiplier %u", de->count, de->multiplier);
16✔
255
    }
16✔
256

257
    for (i = 0; i < (ret - 1); i++) {
20,610✔
258
        if (args[i] != NULL)
18,320✔
259
            pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
18,320✔
260
    }
18,320✔
261
    pcre2_match_data_free(match);
2,290✔
262
    return de;
2,290✔
263

264
error:
2✔
265
    if (match) {
2✔
266
        pcre2_match_data_free(match);
1✔
267
    }
1✔
268
    for (i = 0; i < (ret - 1); i++) {
2✔
UNCOV
269
        if (args[i] != NULL)
×
UNCOV
270
            pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
×
UNCOV
271
    }
×
272
    if (de != NULL)
2✔
UNCOV
273
        SCFree(de);
×
274
    return NULL;
2✔
275
}
2,290✔
276

277
/**
278
 * \internal
279
 * \brief this function is used to add the parsed threshold into the current signature
280
 *
281
 * \param de_ctx pointer to the Detection Engine Context
282
 * \param s pointer to the Current Signature
283
 * \param rawstr pointer to the user provided threshold options
284
 *
285
 * \retval 0 on Success
286
 * \retval -1 on Failure
287
 */
288
static int DetectThresholdSetup(DetectEngineCtx *de_ctx, Signature *s, const char *rawstr)
289
{
2,284✔
290
    DetectThresholdData *de = NULL;
2,284✔
291
    SigMatch *tmpm = NULL;
2,284✔
292

293
    /* checks if there is a previous instance of detection_filter */
294
    tmpm = SCDetectGetLastSMFromLists(s, DETECT_THRESHOLD, DETECT_DETECTION_FILTER, -1);
2,284✔
295
    if (tmpm != NULL) {
2,284✔
296
        if (tmpm->type == DETECT_DETECTION_FILTER) {
1✔
297
            SCLogError("\"detection_filter\" and "
×
298
                       "\"threshold\" are not allowed in the same rule");
×
299
        } else {
1✔
300
            SCLogError("multiple \"threshold\" "
1✔
301
                       "options are not allowed in the same rule");
1✔
302
        }
1✔
303
        SCReturnInt(-1);
1✔
304
    }
1✔
305

306
    de = DetectThresholdParse(rawstr);
2,283✔
307
    if (de == NULL)
2,283✔
UNCOV
308
        goto error;
×
309

310
    if (SCSigMatchAppendSMToList(
2,283✔
311
                de_ctx, s, DETECT_THRESHOLD, (SigMatchCtx *)de, DETECT_SM_LIST_THRESHOLD) == NULL) {
2,283✔
312
        goto error;
×
313
    }
×
314

315
    return 0;
2,283✔
316

UNCOV
317
error:
×
UNCOV
318
    if (de)
×
319
        SCFree(de);
×
UNCOV
320
    return -1;
×
321
}
2,283✔
322

323
/**
324
 * \internal
325
 * \brief this function will free memory associated with DetectThresholdData
326
 *
327
 * \param de pointer to DetectThresholdData
328
 */
329
static void DetectThresholdFree(DetectEngineCtx *de_ctx, void *de_ptr)
330
{
2,347✔
331
    DetectThresholdData *de = (DetectThresholdData *)de_ptr;
2,347✔
332
    if (de) {
2,347✔
333
        DetectAddressHeadCleanup(&de->addrs);
2,347✔
334
        SCFree(de);
2,347✔
335
    }
2,347✔
336
}
2,347✔
337

338
/**
339
 * \brief Make a deep-copy of an extant DetectTHresholdData object.
340
 *
341
 * \param de pointer to DetectThresholdData
342
 */
343
DetectThresholdData *DetectThresholdDataCopy(DetectThresholdData *de)
344
{
41✔
345
    DetectThresholdData *new_de = SCCalloc(1, sizeof(DetectThresholdData));
41✔
346
    if (unlikely(new_de == NULL))
41✔
347
        return NULL;
×
348

349
    *new_de = *de;
41✔
350
    new_de->addrs.ipv4_head = NULL;
41✔
351
    new_de->addrs.ipv6_head = NULL;
41✔
352

353
    for (DetectAddress *last = NULL, *tmp_ad = de->addrs.ipv4_head; tmp_ad; tmp_ad = tmp_ad->next) {
20,526✔
354
        DetectAddress *n_addr = DetectAddressCopy(tmp_ad);
20,485✔
355
        if (n_addr == NULL)
20,485✔
356
            goto error;
×
357
        if (last == NULL) {
20,485✔
358
            new_de->addrs.ipv4_head = n_addr;
39✔
359
        } else {
20,455✔
360
            last->next = n_addr;
20,446✔
361
            n_addr->prev = last;
20,446✔
362
        }
20,446✔
363
        last = n_addr;
20,485✔
364
    }
20,485✔
365
    for (DetectAddress *last = NULL, *tmp_ad = de->addrs.ipv6_head; tmp_ad; tmp_ad = tmp_ad->next) {
83✔
366
        DetectAddress *n_addr = DetectAddressCopy(tmp_ad);
42✔
367
        if (n_addr == NULL)
42✔
368
            goto error;
×
369
        if (last == NULL) {
42✔
370
            new_de->addrs.ipv6_head = n_addr;
22✔
371
        } else {
22✔
372
            last->next = n_addr;
20✔
373
            n_addr->prev = last;
20✔
374
        }
20✔
375
        last = n_addr;
42✔
376
    }
42✔
377

378
    return new_de;
41✔
379

380
error:
×
381
    DetectThresholdFree(NULL, new_de);
×
382
    return NULL;
383
}
41✔
384

385
/*
386
 * ONLY TESTS BELOW THIS COMMENT
387
 */
388
#ifdef UNITTESTS
389
#include "detect-engine.h"
390
#include "detect-engine-mpm.h"
391
#include "detect-engine-alert.h"
392
#include "util-time.h"
393
#include "util-hashlist.h"
394
#include "packet.h"
395
#include "action-globals.h"
396

397
/**
398
 * \test ThresholdTestParse01 is a test for a valid threshold options
399
 *
400
 *  \retval 1 on success
401
 *  \retval 0 on failure
402
 */
403
static int ThresholdTestParse01(void)
404
{
1✔
405
    DetectThresholdData *de = NULL;
1✔
406
    de = DetectThresholdParse("type limit,track by_dst,count 10,seconds 60");
1✔
407
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) &&
1✔
408
            (de->seconds == 60)) {
1✔
409
        DetectThresholdFree(NULL, de);
1✔
410
        return 1;
1✔
411
    }
1✔
412

413
    return 0;
414
}
1✔
415

416
static int ThresholdTestParseByFlow01(void)
417
{
1✔
418
    DetectThresholdData *de = DetectThresholdParse("type limit,track by_flow,count 1,seconds 60");
1✔
419
    FAIL_IF_NULL(de);
1✔
420
    FAIL_IF_NOT(de->type == TYPE_LIMIT);
1✔
421
    FAIL_IF_NOT(de->track == TRACK_FLOW);
1✔
422
    FAIL_IF_NOT(de->count == 1);
1✔
423
    FAIL_IF_NOT(de->seconds == 60);
1✔
424
    DetectThresholdFree(NULL, de);
1✔
425
    PASS;
1✔
426
}
1✔
427

428
/**
429
 * \test ThresholdTestParse02 is a test for a invalid threshold options
430
 *
431
 *  \retval 1 on success
432
 *  \retval 0 on failure
433
 */
434
static int ThresholdTestParse02(void)
435
{
1✔
436
    DetectThresholdData *de = NULL;
1✔
437
    de = DetectThresholdParse("type any,track by_dst,count 10,seconds 60");
1✔
438
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) &&
1✔
439
            (de->seconds == 60)) {
1✔
440
        DetectThresholdFree(NULL, de);
441
        return 0;
442
    }
443

444
    return 1;
1✔
445
}
1✔
446

447
/**
448
 * \test ThresholdTestParse03 is a test for a valid threshold options in any order
449
 *
450
 *  \retval 1 on success
451
 *  \retval 0 on failure
452
 */
453
static int ThresholdTestParse03(void)
454
{
1✔
455
    DetectThresholdData *de = NULL;
1✔
456
    de = DetectThresholdParse("track by_dst, type limit, seconds 60, count 10");
1✔
457
    if (de && (de->type == TYPE_LIMIT) && (de->track == TRACK_DST) && (de->count == 10) &&
1✔
458
            (de->seconds == 60)) {
1✔
459
        DetectThresholdFree(NULL, de);
1✔
460
        return 1;
1✔
461
    }
1✔
462

463
    return 0;
464
}
1✔
465

466
/**
467
 * \test ThresholdTestParse04 is a test for an invalid threshold options in any order
468
 *
469
 *  \retval 1 on success
470
 *  \retval 0 on failure
471
 */
472
static int ThresholdTestParse04(void)
473
{
1✔
474
    DetectThresholdData *de = NULL;
1✔
475
    de = DetectThresholdParse("count 10, track by_dst, seconds 60, type both, count 10");
1✔
476
    if (de && (de->type == TYPE_BOTH) && (de->track == TRACK_DST) && (de->count == 10) &&
1✔
477
            (de->seconds == 60)) {
1✔
478
        DetectThresholdFree(NULL, de);
479
        return 0;
480
    }
481

482
    return 1;
1✔
483
}
1✔
484

485
/**
486
 * \test ThresholdTestParse05 is a test for a valid threshold options in any order
487
 *
488
 *  \retval 1 on success
489
 *  \retval 0 on failure
490
 */
491
static int ThresholdTestParse05(void)
492
{
1✔
493
    DetectThresholdData *de = NULL;
1✔
494
    de = DetectThresholdParse("count 10, track by_dst, seconds 60, type both");
1✔
495
    if (de && (de->type == TYPE_BOTH) && (de->track == TRACK_DST) && (de->count == 10) &&
1✔
496
            (de->seconds == 60)) {
1✔
497
        DetectThresholdFree(NULL, de);
1✔
498
        return 1;
1✔
499
    }
1✔
500

501
    return 0;
502
}
1✔
503

504
/**
505
 * \test ThresholdTestParse06 is a test for thresholding by_both
506
 *
507
 *  \retval 1 on success
508
 *  \retval 0 on failure
509
 */
510
static int ThresholdTestParse06(void)
511
{
1✔
512
    DetectThresholdData *de = NULL;
1✔
513
    de = DetectThresholdParse("count 10, track by_both, seconds 60, type limit");
1✔
514
    FAIL_IF_NULL(de);
1✔
515
    FAIL_IF_NOT(de->type == TYPE_LIMIT);
1✔
516
    FAIL_IF_NOT(de->track == TRACK_BOTH);
1✔
517
    FAIL_IF_NOT(de->count == 10);
1✔
518
    FAIL_IF_NOT(de->seconds == 60);
1✔
519
    DetectThresholdFree(NULL, de);
1✔
520
    PASS;
1✔
521
}
1✔
522

523
/**
524
 * \test ThresholdTestParse07 is a test for thresholding by_rule
525
 *
526
 *  \retval 1 on success
527
 *  \retval 0 on failure
528
 */
529
static int ThresholdTestParse07(void)
530
{
1✔
531
    DetectThresholdData *de = NULL;
1✔
532
    de = DetectThresholdParse("count 10, track by_rule, seconds 60, type limit");
1✔
533
    FAIL_IF_NULL(de);
1✔
534
    FAIL_IF_NOT(de->type == TYPE_LIMIT);
1✔
535
    FAIL_IF_NOT(de->track == TRACK_RULE);
1✔
536
    FAIL_IF_NOT(de->count == 10);
1✔
537
    FAIL_IF_NOT(de->seconds == 60);
1✔
538
    DetectThresholdFree(NULL, de);
1✔
539
    PASS;
1✔
540
}
1✔
541

542
/** \test backoff by_flow */
543
static int ThresholdTestParse08(void)
544
{
1✔
545
    DetectThresholdData *de =
1✔
546
            DetectThresholdParse("count 10, track by_flow, multiplier 2, type backoff");
1✔
547
    FAIL_IF_NULL(de);
1✔
548
    FAIL_IF_NOT(de->type == TYPE_BACKOFF);
1✔
549
    FAIL_IF_NOT(de->track == TRACK_FLOW);
1✔
550
    FAIL_IF_NOT(de->count == 10);
1✔
551
    FAIL_IF_NOT(de->multiplier == 2);
1✔
552
    DetectThresholdFree(NULL, de);
1✔
553
    PASS;
1✔
554
}
1✔
555

556
/**
557
 * \test DetectThresholdTestSig1 is a test for checking the working of limit keyword
558
 *       by setting up the signature and later testing its working by matching
559
 *       the received packet against the sig.
560
 *
561
 *  \retval 1 on success
562
 *  \retval 0 on failure
563
 */
564

565
static int DetectThresholdTestSig1(void)
566
{
1✔
567
    Packet *p = NULL;
1✔
568
    Signature *s = NULL;
1✔
569
    ThreadVars th_v;
1✔
570
    DetectEngineThreadCtx *det_ctx;
1✔
571
    int result = 0;
1✔
572
    int alerts = 0;
1✔
573

574
    ThresholdInit();
1✔
575

576
    memset(&th_v, 0, sizeof(th_v));
1✔
577
    StatsThreadInit(&th_v.stats);
1✔
578

579
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
580

581
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
582
    if (de_ctx == NULL) {
1✔
583
        goto end;
584
    }
585

586
    de_ctx->flags |= DE_QUIET;
1✔
587

588
    s = de_ctx->sig_list =
1✔
589
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit\"; content:\"A\"; "
1✔
590
                            "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
1✔
591
    if (s == NULL) {
1✔
592
        goto end;
593
    }
594

595
    SigGroupBuild(de_ctx);
1✔
596

597
    FAIL_IF(s->type == SIG_TYPE_IPONLY);
1✔
598

599
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
600

601
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
602
    alerts = PacketAlertCheck(p, 1);
1✔
603
    if (alerts != 1) {
1✔
604
        printf("alerts %" PRIi32 ", expected 1: ", alerts);
605
    }
606
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
607
    alerts += PacketAlertCheck(p, 1);
1✔
608
    if (alerts != 2) {
1✔
609
        printf("alerts %" PRIi32 ", expected 2: ", alerts);
610
    }
611
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
612
    alerts += PacketAlertCheck(p, 1);
1✔
613
    if (alerts != 3) {
1✔
614
        printf("alerts %" PRIi32 ", expected 3: ", alerts);
615
    }
616
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
617
    alerts += PacketAlertCheck(p, 1);
1✔
618
    if (alerts != 4) {
1✔
619
        printf("alerts %" PRIi32 ", expected 4: ", alerts);
620
    }
621
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
622
    alerts += PacketAlertCheck(p, 1);
1✔
623
    if (alerts != 5) {
1✔
624
        printf("alerts %" PRIi32 ", expected 5: ", alerts);
625
    }
626
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
627
    alerts += PacketAlertCheck(p, 1);
1✔
628
    if (alerts != 5) {
1✔
629
        printf("alerts %" PRIi32 ", expected 5: ", alerts);
630
    }
631
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
632
    alerts += PacketAlertCheck(p, 1);
1✔
633
    if (alerts != 5) {
1✔
634
        printf("alerts %" PRIi32 ", expected 5: ", alerts);
635
    }
636
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
637
    alerts += PacketAlertCheck(p, 1);
1✔
638
    if (alerts != 5) {
1✔
639
        printf("alerts %" PRIi32 ", expected 5: ", alerts);
640
    }
641

642
    if (alerts == 5)
1✔
643
        result = 1;
1✔
644
    else
645
        printf("alerts %" PRIi32 ", expected 5: ", alerts);
646

647
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
648
    DetectEngineCtxFree(de_ctx);
1✔
649

650
    UTHFreePackets(&p, 1);
1✔
651

652
end:
1✔
653
    ThresholdDestroy();
1✔
654
    StatsThreadCleanup(&th_v.stats);
1✔
655
    return result;
1✔
656
}
1✔
657

658
/**
659
 * \test DetectThresholdTestSig2 is a test for checking the working of threshold keyword
660
 *       by setting up the signature and later testing its working by matching
661
 *       the received packet against the sig.
662
 *
663
 *  \retval 1 on success
664
 *  \retval 0 on failure
665
 */
666

667
static int DetectThresholdTestSig2(void)
668
{
1✔
669
    Packet *p = NULL;
1✔
670
    Signature *s = NULL;
1✔
671
    ThreadVars th_v;
1✔
672
    DetectEngineThreadCtx *det_ctx;
1✔
673
    int result = 0;
1✔
674
    int alerts = 0;
1✔
675

676
    ThresholdInit();
1✔
677

678
    memset(&th_v, 0, sizeof(th_v));
1✔
679
    StatsThreadInit(&th_v.stats);
1✔
680

681
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
682

683
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
684
    if (de_ctx == NULL) {
1✔
685
        goto end;
686
    }
687

688
    de_ctx->flags |= DE_QUIET;
1✔
689

690
    s = de_ctx->sig_list =
1✔
691
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold\"; threshold: type "
1✔
692
                            "threshold, track by_dst, count 5, seconds 60; sid:1;)");
1✔
693
    if (s == NULL) {
1✔
694
        goto end;
695
    }
696

697
    SigGroupBuild(de_ctx);
1✔
698
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
699

700
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
701
    alerts = PacketAlertCheck(p, 1);
1✔
702
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
703
    alerts += PacketAlertCheck(p, 1);
1✔
704
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
705
    alerts += PacketAlertCheck(p, 1);
1✔
706
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
707
    alerts += PacketAlertCheck(p, 1);
1✔
708
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
709
    alerts += PacketAlertCheck(p, 1);
1✔
710
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
711
    alerts += PacketAlertCheck(p, 1);
1✔
712
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
713
    alerts += PacketAlertCheck(p, 1);
1✔
714
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
715
    alerts += PacketAlertCheck(p, 1);
1✔
716
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
717
    alerts += PacketAlertCheck(p, 1);
1✔
718
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
719
    alerts += PacketAlertCheck(p, 1);
1✔
720

721
    if (alerts == 2)
1✔
722
        result = 1;
1✔
723
    else
724
        goto cleanup;
725

726
cleanup:
1✔
727
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
728
    DetectEngineCtxFree(de_ctx);
1✔
729

730
end:
1✔
731
    UTHFreePackets(&p, 1);
1✔
732
    ThresholdDestroy();
1✔
733
    StatsThreadCleanup(&th_v.stats);
1✔
734
    return result;
1✔
735
}
1✔
736

737
/**
738
 * \test DetectThresholdTestSig3 is a test for checking the working of limit keyword
739
 *       by setting up the signature and later testing its working by matching
740
 *       the received packet against the sig.
741
 *
742
 *  \retval 1 on success
743
 *  \retval 0 on failure
744
 */
745

746
static int DetectThresholdTestSig3(void)
747
{
1✔
748
    ThreadVars th_v;
1✔
749
    memset(&th_v, 0, sizeof(th_v));
1✔
750
    StatsThreadInit(&th_v.stats);
1✔
751

752
    ThresholdInit();
1✔
753
    Packet *p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
754

755
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
756
    FAIL_IF_NULL(de_ctx);
1✔
757
    de_ctx->flags |= DE_QUIET;
1✔
758

759
    Signature *s = DetectEngineAppendSig(de_ctx,
1✔
760
            "alert tcp any any -> any 80 (msg:\"Threshold limit\"; threshold: type limit, "
1✔
761
            "track by_dst, count 5, seconds 60; sid:10;)");
1✔
762
    FAIL_IF_NULL(s);
1✔
763

764
    SigGroupBuild(de_ctx);
1✔
765
    DetectEngineThreadCtx *det_ctx;
1✔
766
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
767

768
    p->ts = TimeGet();
1✔
769

770
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
771
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
772
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
773
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
774
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
775
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
776

777
    TimeSetIncrementTime(200);
1✔
778
    p->ts = TimeGet();
1✔
779

780
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
781
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
782
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
783
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
784
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
785
    FAIL_IF_NOT(PacketAlertCheck(p, 10) == 1);
1✔
786

787
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
788
    DetectEngineCtxFree(de_ctx);
1✔
789
    UTHFreePackets(&p, 1);
1✔
790
    ThresholdDestroy();
1✔
791
    StatsThreadCleanup(&th_v.stats);
1✔
792
    PASS;
1✔
793
}
1✔
794

795
/**
796
 * \test DetectThresholdTestSig4 is a test for checking the working of both keyword
797
 *       by setting up the signature and later testing its working by matching
798
 *       the received packet against the sig.
799
 *
800
 *  \retval 1 on success
801
 *  \retval 0 on failure
802
 */
803

804
static int DetectThresholdTestSig4(void)
805
{
1✔
806
    Packet *p = NULL;
1✔
807
    Signature *s = NULL;
1✔
808
    ThreadVars th_v;
1✔
809
    DetectEngineThreadCtx *det_ctx;
1✔
810
    int result = 0;
1✔
811
    int alerts = 0;
1✔
812

813
    ThresholdInit();
1✔
814

815
    memset(&th_v, 0, sizeof(th_v));
1✔
816
    StatsThreadInit(&th_v.stats);
1✔
817

818
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
819

820
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
821
    if (de_ctx == NULL) {
1✔
822
        goto end;
823
    }
824

825
    de_ctx->flags |= DE_QUIET;
1✔
826

827
    s = de_ctx->sig_list =
1✔
828
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold both\"; threshold: type "
1✔
829
                            "both, track by_dst, count 2, seconds 60; sid:10;)");
1✔
830
    if (s == NULL) {
1✔
831
        goto end;
832
    }
833

834
    SigGroupBuild(de_ctx);
1✔
835
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
836

837
    p->ts = TimeGet();
1✔
838
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
839
    alerts = PacketAlertCheck(p, 10);
1✔
840
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
841
    alerts += PacketAlertCheck(p, 10);
1✔
842
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
843
    alerts += PacketAlertCheck(p, 10);
1✔
844

845
    TimeSetIncrementTime(200);
1✔
846
    p->ts = TimeGet();
1✔
847

848
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
849
    alerts += PacketAlertCheck(p, 10);
1✔
850
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
851
    alerts += PacketAlertCheck(p, 10);
1✔
852
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
853
    alerts += PacketAlertCheck(p, 10);
1✔
854

855
    if (alerts == 2)
1✔
856
        result = 1;
1✔
857
    else
858
        goto cleanup;
859

860
cleanup:
1✔
861
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
862
    DetectEngineCtxFree(de_ctx);
1✔
863
end:
1✔
864
    UTHFreePackets(&p, 1);
1✔
865
    ThresholdDestroy();
1✔
866
    StatsThreadCleanup(&th_v.stats);
1✔
867
    return result;
1✔
868
}
1✔
869

870
/**
871
 * \test DetectThresholdTestSig5 is a test for checking the working of limit keyword
872
 *       by setting up the signature and later testing its working by matching
873
 *       the received packet against the sig.
874
 *
875
 *  \retval 1 on success
876
 *  \retval 0 on failure
877
 */
878

879
static int DetectThresholdTestSig5(void)
880
{
1✔
881
    Packet *p = NULL;
1✔
882
    Signature *s = NULL;
1✔
883
    ThreadVars th_v;
1✔
884
    DetectEngineThreadCtx *det_ctx;
1✔
885
    int result = 0;
1✔
886
    int alerts = 0;
1✔
887

888
    ThresholdInit();
1✔
889

890
    memset(&th_v, 0, sizeof(th_v));
1✔
891
    StatsThreadInit(&th_v.stats);
1✔
892
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
893

894
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
895
    if (de_ctx == NULL) {
1✔
896
        goto end;
897
    }
898

899
    de_ctx->flags |= DE_QUIET;
1✔
900

901
    s = de_ctx->sig_list =
1✔
902
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1✔
903
                            "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
1✔
904
    if (s == NULL) {
1✔
905
        goto end;
906
    }
907

908
    s = s->next =
1✔
909
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
1✔
910
                            "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
1✔
911
    if (s == NULL) {
1✔
912
        goto end;
913
    }
914

915
    SigGroupBuild(de_ctx);
1✔
916
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
917

918
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
919
    alerts = PacketAlertCheck(p, 1);
1✔
920
    alerts += PacketAlertCheck(p, 1000);
1✔
921
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
922
    alerts += PacketAlertCheck(p, 1);
1✔
923
    alerts += PacketAlertCheck(p, 1000);
1✔
924
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
925
    alerts += PacketAlertCheck(p, 1);
1✔
926
    alerts += PacketAlertCheck(p, 1000);
1✔
927
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
928
    alerts += PacketAlertCheck(p, 1);
1✔
929
    alerts += PacketAlertCheck(p, 1000);
1✔
930
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
931
    alerts += PacketAlertCheck(p, 1);
1✔
932
    alerts += PacketAlertCheck(p, 1000);
1✔
933
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
934
    alerts += PacketAlertCheck(p, 1);
1✔
935
    alerts += PacketAlertCheck(p, 1000);
1✔
936
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
937
    alerts += PacketAlertCheck(p, 1);
1✔
938
    alerts += PacketAlertCheck(p, 1000);
1✔
939
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
940
    alerts += PacketAlertCheck(p, 1);
1✔
941
    alerts += PacketAlertCheck(p, 1000);
1✔
942

943
    if (alerts == 10)
1✔
944
        result = 1;
1✔
945
    else {
946
        printf("alerts %d != 10: ", alerts);
947
        goto cleanup;
948
    }
949

950
cleanup:
1✔
951
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
952
    DetectEngineCtxFree(de_ctx);
1✔
953

954
end:
1✔
955
    UTHFreePackets(&p, 1);
1✔
956
    ThresholdDestroy();
1✔
957
    StatsThreadCleanup(&th_v.stats);
1✔
958
    return result;
1✔
959
}
1✔
960

961
static int DetectThresholdTestSig6Ticks(void)
962
{
1✔
963
    Packet *p = NULL;
1✔
964
    Signature *s = NULL;
1✔
965
    ThreadVars th_v;
1✔
966
    DetectEngineThreadCtx *det_ctx;
1✔
967
    int result = 0;
1✔
968
    int alerts = 0;
1✔
969

970
    ThresholdInit();
1✔
971

972
    memset(&th_v, 0, sizeof(th_v));
1✔
973
    StatsThreadInit(&th_v.stats);
1✔
974
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
975

976
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
977
    if (de_ctx == NULL) {
1✔
978
        goto end;
979
    }
980

981
    de_ctx->flags |= DE_QUIET;
1✔
982

983
    s = de_ctx->sig_list =
1✔
984
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1✔
985
                            "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
1✔
986
    if (s == NULL) {
1✔
987
        goto end;
988
    }
989

990
    s = s->next =
1✔
991
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
1✔
992
                            "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
1✔
993
    if (s == NULL) {
1✔
994
        goto end;
995
    }
996

997
    SigGroupBuild(de_ctx);
1✔
998
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
999

1000
    uint64_t ticks_start = 0;
1✔
1001
    uint64_t ticks_end = 0;
1✔
1002

1003
    ticks_start = UtilCpuGetTicks();
1✔
1004
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1005
    alerts = PacketAlertCheck(p, 1);
1✔
1006
    alerts += PacketAlertCheck(p, 1000);
1✔
1007
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1008
    alerts += PacketAlertCheck(p, 1);
1✔
1009
    alerts += PacketAlertCheck(p, 1000);
1✔
1010
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1011
    alerts += PacketAlertCheck(p, 1);
1✔
1012
    alerts += PacketAlertCheck(p, 1000);
1✔
1013
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1014
    alerts += PacketAlertCheck(p, 1);
1✔
1015
    alerts += PacketAlertCheck(p, 1000);
1✔
1016
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1017
    alerts += PacketAlertCheck(p, 1);
1✔
1018
    alerts += PacketAlertCheck(p, 1000);
1✔
1019
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1020
    alerts += PacketAlertCheck(p, 1);
1✔
1021
    alerts += PacketAlertCheck(p, 1000);
1✔
1022
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1023
    alerts += PacketAlertCheck(p, 1);
1✔
1024
    alerts += PacketAlertCheck(p, 1000);
1✔
1025
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1026
    alerts += PacketAlertCheck(p, 1);
1✔
1027
    alerts += PacketAlertCheck(p, 1000);
1✔
1028
    ticks_end = UtilCpuGetTicks();
1✔
1029
    printf("test run %" PRIu64 "\n", (ticks_end - ticks_start));
1✔
1030

1031
    if (alerts == 10)
1✔
1032
        result = 1;
1✔
1033
    else
1034
        goto cleanup;
1035

1036
cleanup:
1✔
1037
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1038
    DetectEngineCtxFree(de_ctx);
1✔
1039

1040
end:
1✔
1041
    UTHFreePackets(&p, 1);
1✔
1042
    ThresholdDestroy();
1✔
1043
    StatsThreadCleanup(&th_v.stats);
1✔
1044
    return result;
1✔
1045
}
1✔
1046

1047
/**
1048
 * \test Test drop action being set even if thresholded
1049
 */
1050
static int DetectThresholdTestSig7(void)
1051
{
1✔
1052
    Packet *p = NULL;
1✔
1053
    Signature *s = NULL;
1✔
1054
    ThreadVars th_v;
1✔
1055
    DetectEngineThreadCtx *det_ctx;
1✔
1056
    int result = 0;
1✔
1057
    int alerts = 0;
1✔
1058
    int drops = 0;
1✔
1059

1060
    ThresholdInit();
1✔
1061

1062
    memset(&th_v, 0, sizeof(th_v));
1✔
1063
    StatsThreadInit(&th_v.stats);
1✔
1064

1065
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1066

1067
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1068
    if (de_ctx == NULL) {
1✔
1069
        goto end;
1070
    }
1071

1072
    de_ctx->flags |= DE_QUIET;
1✔
1073

1074
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type limit, "
1✔
1075
                                           "track by_src, count 1, seconds 300; sid:10;)");
1✔
1076
    if (s == NULL) {
1✔
1077
        goto end;
1078
    }
1079

1080
    SigGroupBuild(de_ctx);
1✔
1081
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1082

1083
    p->ts = TimeGet();
1✔
1084
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1085
    alerts = PacketAlertCheck(p, 10);
1✔
1086
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1087
    p->action = 0;
1✔
1088

1089
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1090
    alerts += PacketAlertCheck(p, 10);
1✔
1091
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1092
    p->action = 0;
1✔
1093

1094
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1095
    alerts += PacketAlertCheck(p, 10);
1✔
1096
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1097
    p->action = 0;
1✔
1098

1099
    TimeSetIncrementTime(200);
1✔
1100
    p->ts = TimeGet();
1✔
1101

1102
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1103
    alerts += PacketAlertCheck(p, 10);
1✔
1104
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1105
    p->action = 0;
1✔
1106

1107
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1108
    alerts += PacketAlertCheck(p, 10);
1✔
1109
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1110
    p->action = 0;
1✔
1111

1112
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1113
    alerts += PacketAlertCheck(p, 10);
1✔
1114
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1115
    p->action = 0;
1✔
1116

1117
    if (alerts == 1 && drops == 6)
1✔
1118
        result = 1;
1✔
1119
    else {
1120
        if (alerts != 1)
1121
            printf("alerts: %d != 1: ", alerts);
1122
        if (drops != 6)
1123
            printf("drops: %d != 6: ", drops);
1124
        goto cleanup;
1125
    }
1126

1127
cleanup:
1✔
1128
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1129
    DetectEngineCtxFree(de_ctx);
1✔
1130
end:
1✔
1131
    UTHFreePackets(&p, 1);
1✔
1132
    ThresholdDestroy();
1✔
1133
    StatsThreadCleanup(&th_v.stats);
1✔
1134
    return result;
1✔
1135
}
1✔
1136

1137
/**
1138
 * \test Test drop action being set even if thresholded
1139
 */
1140
static int DetectThresholdTestSig8(void)
1141
{
1✔
1142
    Packet *p = NULL;
1✔
1143
    Signature *s = NULL;
1✔
1144
    ThreadVars th_v;
1✔
1145
    DetectEngineThreadCtx *det_ctx;
1✔
1146
    int result = 0;
1✔
1147
    int alerts = 0;
1✔
1148
    int drops = 0;
1✔
1149

1150
    ThresholdInit();
1✔
1151

1152
    memset(&th_v, 0, sizeof(th_v));
1✔
1153
    StatsThreadInit(&th_v.stats);
1✔
1154

1155
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1156

1157
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1158
    if (de_ctx == NULL) {
1✔
1159
        goto end;
1160
    }
1161

1162
    de_ctx->flags |= DE_QUIET;
1✔
1163

1164
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type limit, "
1✔
1165
                                           "track by_src, count 2, seconds 300; sid:10;)");
1✔
1166
    if (s == NULL) {
1✔
1167
        goto end;
1168
    }
1169

1170
    SigGroupBuild(de_ctx);
1✔
1171
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1172

1173
    p->ts = TimeGet();
1✔
1174
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1175
    alerts = PacketAlertCheck(p, 10);
1✔
1176
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1177
    p->action = 0;
1✔
1178

1179
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1180
    alerts += PacketAlertCheck(p, 10);
1✔
1181
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1182
    p->action = 0;
1✔
1183

1184
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1185
    alerts += PacketAlertCheck(p, 10);
1✔
1186
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1187
    p->action = 0;
1✔
1188

1189
    TimeSetIncrementTime(200);
1✔
1190
    p->ts = TimeGet();
1✔
1191

1192
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1193
    alerts += PacketAlertCheck(p, 10);
1✔
1194
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1195
    p->action = 0;
1✔
1196

1197
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1198
    alerts += PacketAlertCheck(p, 10);
1✔
1199
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1200
    p->action = 0;
1✔
1201

1202
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1203
    alerts += PacketAlertCheck(p, 10);
1✔
1204
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1205
    p->action = 0;
1✔
1206

1207
    if (alerts == 2 && drops == 6)
1✔
1208
        result = 1;
1✔
1209
    else {
1210
        if (alerts != 1)
1211
            printf("alerts: %d != 1: ", alerts);
1212
        if (drops != 6)
1213
            printf("drops: %d != 6: ", drops);
1214
        goto cleanup;
1215
    }
1216

1217
cleanup:
1✔
1218
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1219
    DetectEngineCtxFree(de_ctx);
1✔
1220
end:
1✔
1221
    UTHFreePackets(&p, 1);
1✔
1222
    ThresholdDestroy();
1✔
1223
    StatsThreadCleanup(&th_v.stats);
1✔
1224
    return result;
1✔
1225
}
1✔
1226

1227
/**
1228
 * \test Test drop action being set even if thresholded
1229
 */
1230
static int DetectThresholdTestSig9(void)
1231
{
1✔
1232
    Packet *p = NULL;
1✔
1233
    Signature *s = NULL;
1✔
1234
    ThreadVars th_v;
1✔
1235
    DetectEngineThreadCtx *det_ctx;
1✔
1236
    int result = 0;
1✔
1237
    int alerts = 0;
1✔
1238
    int drops = 0;
1✔
1239

1240
    ThresholdInit();
1✔
1241

1242
    memset(&th_v, 0, sizeof(th_v));
1✔
1243
    StatsThreadInit(&th_v.stats);
1✔
1244

1245
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1246

1247
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1248
    if (de_ctx == NULL) {
1✔
1249
        goto end;
1250
    }
1251

1252
    de_ctx->flags |= DE_QUIET;
1✔
1253

1254
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type threshold, "
1✔
1255
                                           "track by_src, count 3, seconds 100; sid:10;)");
1✔
1256
    if (s == NULL) {
1✔
1257
        goto end;
1258
    }
1259

1260
    SigGroupBuild(de_ctx);
1✔
1261
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1262

1263
    p->ts = TimeGet();
1✔
1264
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1265
    alerts = PacketAlertCheck(p, 10);
1✔
1266
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1267
    p->action = 0;
1✔
1268

1269
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1270
    alerts += PacketAlertCheck(p, 10);
1✔
1271
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1272
    p->action = 0;
1✔
1273

1274
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1275
    alerts += PacketAlertCheck(p, 10);
1✔
1276
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1277
    p->action = 0;
1✔
1278

1279
    TimeSetIncrementTime(200);
1✔
1280
    p->ts = TimeGet();
1✔
1281

1282
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1283
    alerts += PacketAlertCheck(p, 10);
1✔
1284
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1285
    p->action = 0;
1✔
1286

1287
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1288
    alerts += PacketAlertCheck(p, 10);
1✔
1289
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1290
    p->action = 0;
1✔
1291

1292
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1293
    alerts += PacketAlertCheck(p, 10);
1✔
1294
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1295
    p->action = 0;
1✔
1296

1297
    if (alerts == 2 && drops == 2)
1✔
1298
        result = 1;
1✔
1299
    else {
1300
        if (alerts != 2)
1301
            printf("alerts: %d != 2: ", alerts);
1302
        if (drops != 2)
1303
            printf("drops: %d != 2: ", drops);
1304
        goto cleanup;
1305
    }
1306

1307
cleanup:
1✔
1308
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1309
    DetectEngineCtxFree(de_ctx);
1✔
1310
end:
1✔
1311
    UTHFreePackets(&p, 1);
1✔
1312
    ThresholdDestroy();
1✔
1313
    StatsThreadCleanup(&th_v.stats);
1✔
1314
    return result;
1✔
1315
}
1✔
1316

1317
/**
1318
 * \test Test drop action being set even if thresholded
1319
 */
1320
static int DetectThresholdTestSig10(void)
1321
{
1✔
1322
    Packet *p = NULL;
1✔
1323
    Signature *s = NULL;
1✔
1324
    ThreadVars th_v;
1✔
1325
    DetectEngineThreadCtx *det_ctx;
1✔
1326
    int result = 0;
1✔
1327
    int alerts = 0;
1✔
1328
    int drops = 0;
1✔
1329

1330
    ThresholdInit();
1✔
1331

1332
    memset(&th_v, 0, sizeof(th_v));
1✔
1333
    StatsThreadInit(&th_v.stats);
1✔
1334

1335
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1336

1337
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1338
    if (de_ctx == NULL) {
1✔
1339
        goto end;
1340
    }
1341

1342
    de_ctx->flags |= DE_QUIET;
1✔
1343

1344
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type threshold, "
1✔
1345
                                           "track by_src, count 5, seconds 300; sid:10;)");
1✔
1346
    if (s == NULL) {
1✔
1347
        goto end;
1348
    }
1349

1350
    SigGroupBuild(de_ctx);
1✔
1351
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1352

1353
    p->ts = TimeGet();
1✔
1354
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1355
    alerts = PacketAlertCheck(p, 10);
1✔
1356
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1357
    p->action = 0;
1✔
1358

1359
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1360
    alerts += PacketAlertCheck(p, 10);
1✔
1361
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1362
    p->action = 0;
1✔
1363

1364
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1365
    alerts += PacketAlertCheck(p, 10);
1✔
1366
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1367
    p->action = 0;
1✔
1368

1369
    TimeSetIncrementTime(200);
1✔
1370
    p->ts = TimeGet();
1✔
1371

1372
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1373
    alerts += PacketAlertCheck(p, 10);
1✔
1374
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1375
    p->action = 0;
1✔
1376

1377
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1378
    alerts += PacketAlertCheck(p, 10);
1✔
1379
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1380
    p->action = 0;
1✔
1381

1382
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1383
    alerts += PacketAlertCheck(p, 10);
1✔
1384
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1385
    p->action = 0;
1✔
1386

1387
    if (alerts == 1 && drops == 1)
1✔
1388
        result = 1;
1✔
1389
    else {
1390
        if (alerts != 1)
1391
            printf("alerts: %d != 1: ", alerts);
1392
        if (drops != 1)
1393
            printf("drops: %d != 1: ", drops);
1394
        goto cleanup;
1395
    }
1396

1397
cleanup:
1✔
1398
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1399
    DetectEngineCtxFree(de_ctx);
1✔
1400
end:
1✔
1401
    UTHFreePackets(&p, 1);
1✔
1402
    ThresholdDestroy();
1✔
1403
    StatsThreadCleanup(&th_v.stats);
1✔
1404
    return result;
1✔
1405
}
1✔
1406

1407
/**
1408
 * \test Test drop action being set even if thresholded
1409
 */
1410
static int DetectThresholdTestSig11(void)
1411
{
1✔
1412
    Packet *p = NULL;
1✔
1413
    Signature *s = NULL;
1✔
1414
    ThreadVars th_v;
1✔
1415
    DetectEngineThreadCtx *det_ctx;
1✔
1416
    int result = 0;
1✔
1417
    int alerts = 0;
1✔
1418
    int drops = 0;
1✔
1419

1420
    ThresholdInit();
1✔
1421

1422
    memset(&th_v, 0, sizeof(th_v));
1✔
1423
    StatsThreadInit(&th_v.stats);
1✔
1424

1425
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1426

1427
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1428
    if (de_ctx == NULL) {
1✔
1429
        goto end;
1430
    }
1431

1432
    de_ctx->flags |= DE_QUIET;
1✔
1433

1434
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type both, "
1✔
1435
                                           "track by_src, count 3, seconds 300; sid:10;)");
1✔
1436
    if (s == NULL) {
1✔
1437
        goto end;
1438
    }
1439

1440
    SigGroupBuild(de_ctx);
1✔
1441
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1442

1443
    p->ts = TimeGet();
1✔
1444
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1445
    alerts = PacketAlertCheck(p, 10);
1✔
1446
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1447
    p->action = 0;
1✔
1448

1449
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1450
    alerts += PacketAlertCheck(p, 10);
1✔
1451
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1452
    p->action = 0;
1✔
1453

1454
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1455
    alerts += PacketAlertCheck(p, 10);
1✔
1456
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1457
    p->action = 0;
1✔
1458

1459
    TimeSetIncrementTime(200);
1✔
1460
    p->ts = TimeGet();
1✔
1461

1462
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1463
    alerts += PacketAlertCheck(p, 10);
1✔
1464
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1465
    p->action = 0;
1✔
1466

1467
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1468
    alerts += PacketAlertCheck(p, 10);
1✔
1469
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1470
    p->action = 0;
1✔
1471

1472
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1473
    alerts += PacketAlertCheck(p, 10);
1✔
1474
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1475
    p->action = 0;
1✔
1476

1477
    if (alerts == 1 && drops == 4)
1✔
1478
        result = 1;
1✔
1479
    else {
1480
        if (alerts != 1)
1481
            printf("alerts: %d != 1: ", alerts);
1482
        if (drops != 4)
1483
            printf("drops: %d != 4: ", drops);
1484
        goto cleanup;
1485
    }
1486

1487
cleanup:
1✔
1488
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1489
    DetectEngineCtxFree(de_ctx);
1✔
1490
end:
1✔
1491
    UTHFreePackets(&p, 1);
1✔
1492
    ThresholdDestroy();
1✔
1493
    StatsThreadCleanup(&th_v.stats);
1✔
1494
    return result;
1✔
1495
}
1✔
1496

1497
/**
1498
 * \test Test drop action being set even if thresholded
1499
 */
1500
static int DetectThresholdTestSig12(void)
1501
{
1✔
1502
    Packet *p = NULL;
1✔
1503
    Signature *s = NULL;
1✔
1504
    ThreadVars th_v;
1✔
1505
    DetectEngineThreadCtx *det_ctx;
1✔
1506
    int result = 0;
1✔
1507
    int alerts = 0;
1✔
1508
    int drops = 0;
1✔
1509

1510
    ThresholdInit();
1✔
1511

1512
    memset(&th_v, 0, sizeof(th_v));
1✔
1513
    StatsThreadInit(&th_v.stats);
1✔
1514

1515
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1516

1517
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1518
    if (de_ctx == NULL) {
1✔
1519
        goto end;
1520
    }
1521

1522
    de_ctx->flags |= DE_QUIET;
1✔
1523

1524
    s = de_ctx->sig_list = SigInit(de_ctx, "drop tcp any any -> any 80 (threshold: type both, "
1✔
1525
                                           "track by_src, count 5, seconds 300; sid:10;)");
1✔
1526
    if (s == NULL) {
1✔
1527
        goto end;
1528
    }
1529

1530
    SigGroupBuild(de_ctx);
1✔
1531
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1532

1533
    p->ts = TimeGet();
1✔
1534
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1535
    alerts = PacketAlertCheck(p, 10);
1✔
1536
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1537
    p->action = 0;
1✔
1538

1539
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1540
    alerts += PacketAlertCheck(p, 10);
1✔
1541
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1542
    p->action = 0;
1✔
1543

1544
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1545
    alerts += PacketAlertCheck(p, 10);
1✔
1546
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1547
    p->action = 0;
1✔
1548

1549
    TimeSetIncrementTime(200);
1✔
1550
    p->ts = TimeGet();
1✔
1551

1552
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1553
    alerts += PacketAlertCheck(p, 10);
1✔
1554
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1555
    p->action = 0;
1✔
1556

1557
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1558
    alerts += PacketAlertCheck(p, 10);
1✔
1559
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1560
    p->action = 0;
1✔
1561

1562
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1563
    alerts += PacketAlertCheck(p, 10);
1✔
1564
    drops += ((PacketTestAction(p, ACTION_DROP)) ? 1 : 0);
1✔
1565
    p->action = 0;
1✔
1566

1567
    if (alerts == 1 && drops == 2)
1✔
1568
        result = 1;
1✔
1569
    else {
1570
        if (alerts != 1)
1571
            printf("alerts: %d != 1: ", alerts);
1572
        if (drops != 2)
1573
            printf("drops: %d != 2: ", drops);
1574
        goto cleanup;
1575
    }
1576

1577
cleanup:
1✔
1578
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1579
    DetectEngineCtxFree(de_ctx);
1✔
1580
end:
1✔
1581
    UTHFreePackets(&p, 1);
1✔
1582
    HostShutdown();
1✔
1583
    ThresholdDestroy();
1✔
1584
    StatsThreadCleanup(&th_v.stats);
1✔
1585
    return result;
1✔
1586
}
1✔
1587

1588
/**
1589
 * \test DetectThresholdTestSig13 is a test for checking the working by_rule limits
1590
 *       by setting up the signature and later testing its working by matching
1591
 *       received packets against the sig.
1592
 *
1593
 *  \retval 1 on success
1594
 *  \retval 0 on failure
1595
 */
1596

1597
static int DetectThresholdTestSig13(void)
1598
{
1✔
1599
    Packet *p = NULL;
1✔
1600
    Signature *s = NULL;
1✔
1601
    ThreadVars th_v;
1✔
1602
    DetectEngineThreadCtx *det_ctx;
1✔
1603
    int alerts = 0;
1✔
1604

1605
    ThresholdInit();
1✔
1606

1607
    memset(&th_v, 0, sizeof(th_v));
1✔
1608
    StatsThreadInit(&th_v.stats);
1✔
1609
    p = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1610
    FAIL_IF_NULL(p);
1✔
1611

1612
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1613
    FAIL_IF_NULL(de_ctx);
1✔
1614

1615
    de_ctx->flags |= DE_QUIET;
1✔
1616

1617
    s = de_ctx->sig_list =
1✔
1618
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1✔
1619
                            "threshold: type limit, track by_rule, count 2, seconds 60; sid:1;)");
1✔
1620
    FAIL_IF_NULL(s);
1✔
1621

1622
    SigGroupBuild(de_ctx);
1✔
1623
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1624

1625
    /* should alert twice */
1626
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1627
    alerts += PacketAlertCheck(p, 1);
1✔
1628
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1629
    alerts += PacketAlertCheck(p, 1);
1✔
1630
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1631
    alerts += PacketAlertCheck(p, 1);
1✔
1632
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1633
    alerts += PacketAlertCheck(p, 1);
1✔
1634

1635
    FAIL_IF(alerts != 2);
1✔
1636

1637
    TimeSetIncrementTime(70);
1✔
1638
    p->ts = TimeGet();
1✔
1639

1640
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1641
    alerts += PacketAlertCheck(p, 1);
1✔
1642
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1643
    alerts += PacketAlertCheck(p, 1);
1✔
1644
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1645
    alerts += PacketAlertCheck(p, 1);
1✔
1646
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p);
1✔
1647
    alerts += PacketAlertCheck(p, 1);
1✔
1648

1649
    FAIL_IF(alerts != 4);
1✔
1650

1651
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1652
    DetectEngineCtxFree(de_ctx);
1✔
1653
    UTHFreePackets(&p, 1);
1✔
1654
    ThresholdDestroy();
1✔
1655
    StatsThreadCleanup(&th_v.stats);
1✔
1656
    PASS;
1✔
1657
}
1✔
1658

1659
/**
1660
 * \test DetectThresholdTestSig14 is a test for checking the working by_both limits
1661
 *       by setting up the signature and later testing its working by matching
1662
 *       received packets against the sig.
1663
 *
1664
 *  \retval 1 on success
1665
 *  \retval 0 on failure
1666
 */
1667

1668
static int DetectThresholdTestSig14(void)
1669
{
1✔
1670
    Packet *p1 = NULL;
1✔
1671
    Packet *p2 = NULL;
1✔
1672
    Signature *s = NULL;
1✔
1673
    ThreadVars th_v;
1✔
1674
    DetectEngineThreadCtx *det_ctx;
1✔
1675
    int alerts1 = 0;
1✔
1676
    int alerts2 = 0;
1✔
1677

1678
    ThresholdInit();
1✔
1679

1680
    memset(&th_v, 0, sizeof(th_v));
1✔
1681
    StatsThreadInit(&th_v.stats);
1✔
1682
    p1 = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "2.2.2.2", 1024, 80);
1✔
1683
    p2 = UTHBuildPacketReal((uint8_t *)"A", 1, IPPROTO_TCP, "1.1.1.1", "3.3.3.3", 1024, 80);
1✔
1684
    FAIL_IF_NULL(p1);
1✔
1685
    FAIL_IF_NULL(p2);
1✔
1686

1687
    DetectEngineCtx *de_ctx = DetectEngineCtxInit();
1✔
1688
    FAIL_IF_NULL(de_ctx);
1✔
1689

1690
    de_ctx->flags |= DE_QUIET;
1✔
1691

1692
    s = de_ctx->sig_list =
1✔
1693
            SigInit(de_ctx, "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1✔
1694
                            "threshold: type limit, track by_both, count 2, seconds 60; sid:1;)");
1✔
1695
    FAIL_IF_NULL(s);
1✔
1696

1697
    SigGroupBuild(de_ctx);
1✔
1698
    DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx);
1✔
1699

1700
    /* Both p1 and p2 should alert twice */
1701
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1✔
1702
    alerts1 += PacketAlertCheck(p1, 1);
1✔
1703
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1✔
1704
    alerts1 += PacketAlertCheck(p1, 1);
1✔
1705
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1✔
1706
    alerts1 += PacketAlertCheck(p1, 1);
1✔
1707
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1✔
1708
    alerts1 += PacketAlertCheck(p1, 1);
1✔
1709

1710
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1✔
1711
    alerts2 += PacketAlertCheck(p2, 1);
1✔
1712
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1✔
1713
    alerts2 += PacketAlertCheck(p2, 1);
1✔
1714
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1✔
1715
    alerts2 += PacketAlertCheck(p2, 1);
1✔
1716
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1✔
1717
    alerts2 += PacketAlertCheck(p2, 1);
1✔
1718

1719
    FAIL_IF(alerts1 != 2);
1✔
1720
    FAIL_IF(alerts2 != 2);
1✔
1721

1722
    TimeSetIncrementTime(70);
1✔
1723
    p1->ts = TimeGet();
1✔
1724
    p2->ts = TimeGet();
1✔
1725

1726
    /* Now they should both alert again after previous alerts expire */
1727
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p1);
1✔
1728
    alerts1 += PacketAlertCheck(p1, 1);
1✔
1729
    SigMatchSignatures(&th_v, de_ctx, det_ctx, p2);
1✔
1730
    alerts2 += PacketAlertCheck(p2, 1);
1✔
1731

1732
    FAIL_IF(alerts1 != 3);
1✔
1733
    FAIL_IF(alerts2 != 3);
1✔
1734

1735
    DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx);
1✔
1736
    DetectEngineCtxFree(de_ctx);
1✔
1737
    UTHFreePackets(&p1, 1);
1✔
1738
    UTHFreePackets(&p2, 1);
1✔
1739
    ThresholdDestroy();
1✔
1740
    StatsThreadCleanup(&th_v.stats);
1✔
1741
    PASS;
1✔
1742
}
1✔
1743

1744
static void ThresholdRegisterTests(void)
1745
{
1✔
1746
    UtRegisterTest("ThresholdTestParse01", ThresholdTestParse01);
1✔
1747
    UtRegisterTest("ThresholdTestParseByFlow01", ThresholdTestParseByFlow01);
1✔
1748
    UtRegisterTest("ThresholdTestParse02", ThresholdTestParse02);
1✔
1749
    UtRegisterTest("ThresholdTestParse03", ThresholdTestParse03);
1✔
1750
    UtRegisterTest("ThresholdTestParse04", ThresholdTestParse04);
1✔
1751
    UtRegisterTest("ThresholdTestParse05", ThresholdTestParse05);
1✔
1752
    UtRegisterTest("ThresholdTestParse06", ThresholdTestParse06);
1✔
1753
    UtRegisterTest("ThresholdTestParse07", ThresholdTestParse07);
1✔
1754
    UtRegisterTest("ThresholdTestParse08", ThresholdTestParse08);
1✔
1755
    UtRegisterTest("DetectThresholdTestSig1", DetectThresholdTestSig1);
1✔
1756
    UtRegisterTest("DetectThresholdTestSig2", DetectThresholdTestSig2);
1✔
1757
    UtRegisterTest("DetectThresholdTestSig3", DetectThresholdTestSig3);
1✔
1758
    UtRegisterTest("DetectThresholdTestSig4", DetectThresholdTestSig4);
1✔
1759
    UtRegisterTest("DetectThresholdTestSig5", DetectThresholdTestSig5);
1✔
1760
    UtRegisterTest("DetectThresholdTestSig6Ticks", DetectThresholdTestSig6Ticks);
1✔
1761
    UtRegisterTest("DetectThresholdTestSig7", DetectThresholdTestSig7);
1✔
1762
    UtRegisterTest("DetectThresholdTestSig8", DetectThresholdTestSig8);
1✔
1763
    UtRegisterTest("DetectThresholdTestSig9", DetectThresholdTestSig9);
1✔
1764
    UtRegisterTest("DetectThresholdTestSig10", DetectThresholdTestSig10);
1✔
1765
    UtRegisterTest("DetectThresholdTestSig11", DetectThresholdTestSig11);
1✔
1766
    UtRegisterTest("DetectThresholdTestSig12", DetectThresholdTestSig12);
1✔
1767
    UtRegisterTest("DetectThresholdTestSig13", DetectThresholdTestSig13);
1✔
1768
    UtRegisterTest("DetectThresholdTestSig14", DetectThresholdTestSig14);
1✔
1769
}
1✔
1770
#endif /* UNITTESTS */
1771

1772
/**
1773
 * @}
1774
 */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc