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) {
217 if (
StringParseUint32(&
de->seconds, 10, strlen(args[second_pos]), args[second_pos]) <= 0) {
221 if (args[count_pos] == NULL || args[multiplier_pos] == NULL) {
233 &
de->multiplier, 10, strlen(args[multiplier_pos]), args[multiplier_pos]) <= 0) {
239 if (!(
de->count > 0 &&
de->count < 65536)) {
240 SCLogError(
"invalid count value '%u': must be in the range 1-65535",
de->count);
243 if (!(
de->multiplier > 1 &&
de->multiplier < 65536)) {
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");
254 SCLogDebug(
"TYPE_BACKOFF count %u multiplier %u",
de->count,
de->multiplier);
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);
353 for (
DetectAddress *last = NULL, *tmp_ad =
de->addrs.ipv4_head; tmp_ad; tmp_ad = tmp_ad->next) {
365 for (
DetectAddress *last = NULL, *tmp_ad =
de->addrs.ipv6_head; tmp_ad; tmp_ad = tmp_ad->next) {
381 DetectThresholdFree(NULL, new_de);
403 static int ThresholdTestParse01(
void)
406 de = DetectThresholdParse(
"type limit,track by_dst,count 10,seconds 60");
408 (
de->seconds == 60)) {
409 DetectThresholdFree(NULL,
de);
416 static int ThresholdTestParseByFlow01(
void)
424 DetectThresholdFree(NULL,
de);
434 static int ThresholdTestParse02(
void)
437 de = DetectThresholdParse(
"type any,track by_dst,count 10,seconds 60");
439 (
de->seconds == 60)) {
440 DetectThresholdFree(NULL,
de);
453 static int ThresholdTestParse03(
void)
456 de = DetectThresholdParse(
"track by_dst, type limit, seconds 60, count 10");
458 (
de->seconds == 60)) {
459 DetectThresholdFree(NULL,
de);
472 static int ThresholdTestParse04(
void)
475 de = DetectThresholdParse(
"count 10, track by_dst, seconds 60, type both, count 10");
477 (
de->seconds == 60)) {
478 DetectThresholdFree(NULL,
de);
491 static int ThresholdTestParse05(
void)
494 de = DetectThresholdParse(
"count 10, track by_dst, seconds 60, type both");
496 (
de->seconds == 60)) {
497 DetectThresholdFree(NULL,
de);
510 static int ThresholdTestParse06(
void)
513 de = DetectThresholdParse(
"count 10, track by_both, seconds 60, type limit");
519 DetectThresholdFree(NULL,
de);
529 static int ThresholdTestParse07(
void)
532 de = DetectThresholdParse(
"count 10, track by_rule, seconds 60, type limit");
538 DetectThresholdFree(NULL,
de);
543 static int ThresholdTestParse08(
void)
546 DetectThresholdParse(
"count 10, track by_flow, multiplier 2, type backoff");
552 DetectThresholdFree(NULL,
de);
565 static int DetectThresholdTestSig1(
void)
576 memset(&th_v, 0,
sizeof(th_v));
578 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
588 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit\"; content:\"A\"; "
589 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
603 printf(
"alerts %" PRIi32
", expected 1: ", alerts);
608 printf(
"alerts %" PRIi32
", expected 2: ", alerts);
613 printf(
"alerts %" PRIi32
", expected 3: ", alerts);
618 printf(
"alerts %" PRIi32
", expected 4: ", alerts);
623 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
628 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
633 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
638 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
644 printf(
"alerts %" PRIi32
", expected 5: ", alerts);
668 static int DetectThresholdTestSig2(
void)
679 memset(&th_v, 0,
sizeof(th_v));
681 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
691 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold\"; threshold: type "
692 "threshold, track by_dst, count 5, seconds 60; sid:1;)");
745 static int DetectThresholdTestSig3(
void)
748 memset(&th_v, 0,
sizeof(th_v));
758 "alert tcp any any -> any 80 (msg:\"Threshold limit\"; threshold: type limit, "
759 "track by_dst, count 5, seconds 60; sid:10;)");
801 static int DetectThresholdTestSig4(
void)
812 memset(&th_v, 0,
sizeof(th_v));
814 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
824 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold both\"; threshold: type "
825 "both, track by_dst, count 2, seconds 60; sid:10;)");
874 static int DetectThresholdTestSig5(
void)
885 memset(&th_v, 0,
sizeof(th_v));
886 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
896 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
897 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
903 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
904 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
940 printf(
"alerts %d != 10: ", alerts);
954 static int DetectThresholdTestSig6Ticks(
void)
965 memset(&th_v, 0,
sizeof(th_v));
966 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
976 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
977 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1;)");
983 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1000\"; "
984 "threshold: type limit, track by_dst, count 5, seconds 60; sid:1000;)");
992 uint64_t ticks_start = 0;
993 uint64_t ticks_end = 0;
1021 printf(
"test run %" PRIu64
"\n", (ticks_end - ticks_start));
1041 static int DetectThresholdTestSig7(
void)
1053 memset(&th_v, 0,
sizeof(th_v));
1055 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1065 "track by_src, count 1, seconds 300; sid:10;)");
1076 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1081 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1086 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1094 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1099 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1104 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1107 if (alerts == 1 && drops == 6)
1111 printf(
"alerts: %d != 1: ", alerts);
1113 printf(
"drops: %d != 6: ", drops);
1129 static int DetectThresholdTestSig8(
void)
1141 memset(&th_v, 0,
sizeof(th_v));
1143 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1153 "track by_src, count 2, seconds 300; sid:10;)");
1164 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1169 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1174 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1182 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1187 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1192 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1195 if (alerts == 2 && drops == 6)
1199 printf(
"alerts: %d != 1: ", alerts);
1201 printf(
"drops: %d != 6: ", drops);
1217 static int DetectThresholdTestSig9(
void)
1229 memset(&th_v, 0,
sizeof(th_v));
1231 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1241 "track by_src, count 3, seconds 100; sid:10;)");
1252 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1257 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1262 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1270 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1275 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1280 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1283 if (alerts == 2 && drops == 2)
1287 printf(
"alerts: %d != 2: ", alerts);
1289 printf(
"drops: %d != 2: ", drops);
1305 static int DetectThresholdTestSig10(
void)
1317 memset(&th_v, 0,
sizeof(th_v));
1319 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1329 "track by_src, count 5, seconds 300; sid:10;)");
1340 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1345 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1350 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1358 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1363 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1368 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1371 if (alerts == 1 && drops == 1)
1375 printf(
"alerts: %d != 1: ", alerts);
1377 printf(
"drops: %d != 1: ", drops);
1393 static int DetectThresholdTestSig11(
void)
1405 memset(&th_v, 0,
sizeof(th_v));
1407 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1417 "track by_src, count 3, seconds 300; sid:10;)");
1428 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1433 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1438 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1446 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1451 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1456 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1459 if (alerts == 1 && drops == 4)
1463 printf(
"alerts: %d != 1: ", alerts);
1465 printf(
"drops: %d != 4: ", drops);
1481 static int DetectThresholdTestSig12(
void)
1493 memset(&th_v, 0,
sizeof(th_v));
1495 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1505 "track by_src, count 5, seconds 300; sid:10;)");
1516 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1521 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1526 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1534 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1539 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1544 drops += ((PacketTestAction(p,
ACTION_DROP)) ? 1 : 0);
1547 if (alerts == 1 && drops == 2)
1551 printf(
"alerts: %d != 1: ", alerts);
1553 printf(
"drops: %d != 2: ", drops);
1576 static int DetectThresholdTestSig13(
void)
1586 memset(&th_v, 0,
sizeof(th_v));
1587 p =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1596 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1597 "threshold: type limit, track by_rule, count 2, seconds 60; sid:1;)");
1645 static int DetectThresholdTestSig14(
void)
1657 memset(&th_v, 0,
sizeof(th_v));
1658 p1 =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"2.2.2.2", 1024, 80);
1659 p2 =
UTHBuildPacketReal((uint8_t *)
"A", 1, IPPROTO_TCP,
"1.1.1.1",
"3.3.3.3", 1024, 80);
1669 SigInit(
de_ctx,
"alert tcp any any -> any 80 (msg:\"Threshold limit sid 1\"; "
1670 "threshold: type limit, track by_both, count 2, seconds 60; sid:1;)");
1719 static void ThresholdRegisterTests(
void)
1722 UtRegisterTest(
"ThresholdTestParseByFlow01", ThresholdTestParseByFlow01);
1730 UtRegisterTest(
"DetectThresholdTestSig1", DetectThresholdTestSig1);
1731 UtRegisterTest(
"DetectThresholdTestSig2", DetectThresholdTestSig2);
1732 UtRegisterTest(
"DetectThresholdTestSig3", DetectThresholdTestSig3);
1733 UtRegisterTest(
"DetectThresholdTestSig4", DetectThresholdTestSig4);
1734 UtRegisterTest(
"DetectThresholdTestSig5", DetectThresholdTestSig5);
1735 UtRegisterTest(
"DetectThresholdTestSig6Ticks", DetectThresholdTestSig6Ticks);
1736 UtRegisterTest(
"DetectThresholdTestSig7", DetectThresholdTestSig7);
1737 UtRegisterTest(
"DetectThresholdTestSig8", DetectThresholdTestSig8);
1738 UtRegisterTest(
"DetectThresholdTestSig9", DetectThresholdTestSig9);
1739 UtRegisterTest(
"DetectThresholdTestSig10", DetectThresholdTestSig10);
1740 UtRegisterTest(
"DetectThresholdTestSig11", DetectThresholdTestSig11);
1741 UtRegisterTest(
"DetectThresholdTestSig12", DetectThresholdTestSig12);
1742 UtRegisterTest(
"DetectThresholdTestSig13", DetectThresholdTestSig13);
1743 UtRegisterTest(
"DetectThresholdTestSig14", DetectThresholdTestSig14);