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+)"
68 "^\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE "\\s*,\\s*" PARSE_REGEX_NAME \
69 "\\s+" PARSE_REGEX_VALUE "\\s*,\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE \
70 "\\s*,\\s*" PARSE_REGEX_NAME "\\s+" PARSE_REGEX_VALUE "\\s*"
74 static int DetectThresholdMatch(
79 static void ThresholdRegisterTests(
void);
103 static int DetectThresholdMatch(
121 int ret = 0, res = 0;
123 const char *str_ptr = NULL;
124 char *args[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
125 char *copy_str = NULL, *threshold_opt = NULL;
126 int second_found = 0, count_found = 0;
127 int type_found = 0, track_found = 0;
128 int multiplier_found = 0;
129 int second_pos = 0, count_pos = 0, multiplier_pos = 0;
132 pcre2_match_data *match = NULL;
139 char *saveptr = NULL;
140 for (pos = 0, threshold_opt = strtok_r(copy_str,
",", &saveptr);
141 pos < strlen(copy_str) && threshold_opt != NULL;
142 pos++, threshold_opt = strtok_r(NULL,
",", &saveptr)) {
143 if (strstr(threshold_opt,
"count"))
145 if (strstr(threshold_opt,
"second"))
147 if (strstr(threshold_opt,
"type"))
149 if (strstr(threshold_opt,
"track"))
151 if (strstr(threshold_opt,
"multiplier"))
157 if (!(count_found == 1 && (second_found == 1 || multiplier_found == 1) && track_found == 1 &&
163 if (ret < 5 || ret > 9) {
164 SCLogError(
"pcre_exec parse error, ret %" PRId32
", string %s", ret, rawstr);
172 for (i = 0; i < (ret - 1); i++) {
174 res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
177 SCLogError(
"pcre2_substring_get_bynumber failed");
181 args[i] = (
char *)str_ptr;
183 if (strncasecmp(args[i],
"limit", strlen(
"limit")) == 0)
185 if (strncasecmp(args[i],
"both", strlen(
"both")) == 0)
187 if (strncasecmp(args[i],
"threshold", strlen(
"threshold")) == 0)
189 if (strcasecmp(args[i],
"backoff") == 0)
191 if (strncasecmp(args[i],
"by_dst", strlen(
"by_dst")) == 0)
193 if (strncasecmp(args[i],
"by_src", strlen(
"by_src")) == 0)
195 if (strncasecmp(args[i],
"by_both", strlen(
"by_both")) == 0)
197 if (strncasecmp(args[i],
"by_rule", strlen(
"by_rule")) == 0)
199 if (strncasecmp(args[i],
"by_flow", strlen(
"by_flow")) == 0)
201 if (strncasecmp(args[i],
"count", strlen(
"count")) == 0)
203 if (strncasecmp(args[i],
"seconds", strlen(
"seconds")) == 0)
205 if (strcasecmp(args[i],
"multiplier") == 0)
206 multiplier_pos = i + 1;
210 if (args[count_pos] == NULL || args[second_pos] == NULL) {
221 if (args[count_pos] == NULL || args[multiplier_pos] == NULL) {
233 &de->
multiplier, 10, strlen(args[multiplier_pos]), args[multiplier_pos]) <= 0) {
240 SCLogError(
"invalid count value '%u': must be in the range 1-65535", de->
count);
245 "invalid multiplier value '%u': must be in the range 2-65535", de->
multiplier);
250 SCLogError(
"invalid track value: type backoff only supported for track by_flow");
257 for (i = 0; i < (ret - 1); i++) {
259 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
261 pcre2_match_data_free(match);
266 pcre2_match_data_free(match);
268 for (i = 0; i < (ret - 1); i++) {
270 pcre2_substring_free((PCRE2_UCHAR8 *)args[i]);
298 "\"threshold\" are not allowed in the same rule");
301 "options are not allowed in the same rule");
306 de = DetectThresholdParse(rawstr);
381 DetectThresholdFree(NULL, new_de);
404 static int ThresholdTestParse01(
void)
407 de = DetectThresholdParse(
"type limit,track by_dst,count 10,seconds 60");
410 DetectThresholdFree(NULL, de);
417 static int ThresholdTestParseByFlow01(
void)
419 DetectThresholdData *de = DetectThresholdParse(
"type limit,track by_flow,count 1,seconds 60");
425 DetectThresholdFree(NULL, de);
435 static int ThresholdTestParse02(
void)
438 de = DetectThresholdParse(
"type any,track by_dst,count 10,seconds 60");
441 DetectThresholdFree(NULL, de);
454 static int ThresholdTestParse03(
void)
457 de = DetectThresholdParse(
"track by_dst, type limit, seconds 60, count 10");
460 DetectThresholdFree(NULL, de);
473 static int ThresholdTestParse04(
void)
476 de = DetectThresholdParse(
"count 10, track by_dst, seconds 60, type both, count 10");
479 DetectThresholdFree(NULL, de);
492 static int ThresholdTestParse05(
void)
495 de = DetectThresholdParse(
"count 10, track by_dst, seconds 60, type both");
498 DetectThresholdFree(NULL, de);
511 static int ThresholdTestParse06(
void)
514 de = DetectThresholdParse(
"count 10, track by_both, seconds 60, type limit");
520 DetectThresholdFree(NULL, de);
530 static int ThresholdTestParse07(
void)
533 de = DetectThresholdParse(
"count 10, track by_rule, seconds 60, type limit");
539 DetectThresholdFree(NULL, de);
544 static int ThresholdTestParse08(
void)
547 DetectThresholdParse(
"count 10, track by_flow, multiplier 2, type backoff");
553 DetectThresholdFree(NULL, de);
566 static int DetectThresholdTestSig1(
void)
588 "alert tcp any any -> any 80 (msg:\"Threshold limit\"; content:\"A\"; "
589 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
600 printf(
"alerts %" PRIi32
", expected 1: ", alerts);
605 printf(
"alerts %" PRIi32
", expected 2: ", alerts);
610 printf(
"alerts %" PRIi32
", expected 3: ", alerts);
615 printf(
"alerts %" PRIi32
", expected 4: ", alerts);
620 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
625 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
630 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
635 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
662 static int DetectThresholdTestSig2(
void)
684 "alert tcp any any -> any 80 (msg:\"Threshold\"; threshold: type "
685 "threshold, track by_dst, count 5, seconds 60; sid:1;)");
734 static int DetectThresholdTestSig3(
void)
753 "alert tcp any any -> any 80 (msg:\"Threshold limit\"; threshold: type limit, "
754 "track by_dst, count 5, seconds 60; sid:10;)");
800 static int DetectThresholdTestSig4(
void)
822 "alert tcp any any -> any 80 (msg:\"Threshold both\"; threshold: type "
823 "both, track by_dst, count 2, seconds 60; sid:10;)");
870 static int DetectThresholdTestSig5(
void)
891 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
892 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
896 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
897 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
941 static int DetectThresholdTestSig6Ticks(
void)
963 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
964 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
968 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
969 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
975 uint64_t ticks_start = 0;
976 uint64_t ticks_end = 0;
1004 printf(
"test run %" PRIu64
"\n", (ticks_end - ticks_start));
1023 static int DetectThresholdTestSig7(
void)
1047 "track by_src, count 1, seconds 300; sid:10;)");
1103 static int DetectThresholdTestSig8(
void)
1127 "track by_src, count 2, seconds 300; sid:10;)");
1183 static int DetectThresholdTestSig9(
void)
1207 "track by_src, count 3, seconds 100; sid:10;)");
1263 static int DetectThresholdTestSig10(
void)
1287 "track by_src, count 5, seconds 300; sid:10;)");
1343 static int DetectThresholdTestSig11(
void)
1367 "track by_src, count 3, seconds 300; sid:10;)");
1423 static int DetectThresholdTestSig12(
void)
1447 "track by_src, count 5, seconds 300; sid:10;)");
1510 static int DetectThresholdTestSig13(
void)
1532 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1533 "threshold: type limit, track by_rule, count 2, seconds 60; sid:1;)");
1585 static int DetectThresholdTestSig14(
void)
1609 "alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1610 "threshold: type limit, track by_both, count 2, seconds 60; sid:1;)");
1663 static void ThresholdRegisterTests(
void)
1666 UtRegisterTest(
"ThresholdTestParseByFlow01", ThresholdTestParseByFlow01);
1674 UtRegisterTest(
"DetectThresholdTestSig1", DetectThresholdTestSig1);
1675 UtRegisterTest(
"DetectThresholdTestSig2", DetectThresholdTestSig2);
1676 UtRegisterTest(
"DetectThresholdTestSig3", DetectThresholdTestSig3);
1677 UtRegisterTest(
"DetectThresholdTestSig4", DetectThresholdTestSig4);
1678 UtRegisterTest(
"DetectThresholdTestSig5", DetectThresholdTestSig5);
1679 UtRegisterTest(
"DetectThresholdTestSig6Ticks", DetectThresholdTestSig6Ticks);
1680 UtRegisterTest(
"DetectThresholdTestSig7", DetectThresholdTestSig7);
1681 UtRegisterTest(
"DetectThresholdTestSig8", DetectThresholdTestSig8);
1682 UtRegisterTest(
"DetectThresholdTestSig9", DetectThresholdTestSig9);
1683 UtRegisterTest(
"DetectThresholdTestSig10", DetectThresholdTestSig10);
1684 UtRegisterTest(
"DetectThresholdTestSig11", DetectThresholdTestSig11);
1685 UtRegisterTest(
"DetectThresholdTestSig12", DetectThresholdTestSig12);
1686 UtRegisterTest(
"DetectThresholdTestSig13", DetectThresholdTestSig13);
1687 UtRegisterTest(
"DetectThresholdTestSig14", DetectThresholdTestSig14);