51 "^\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+" \
53 "by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)" \
54 "(?:\\s*,\\s*unique_on\\s+(src_port|dst_port))?\\s*$"
57 #define DF_PARSE_MIN_SUBMATCHES 5
61 static int DetectDetectionFilterMatch(
65 static void DetectDetectionFilterRegisterTests(
void);
76 "alert on every match after a threshold has been reached";
90 static int DetectDetectionFilterMatch(
111 const char *str_ptr = NULL;
112 char *args[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
113 char *copy_str = NULL, *df_opt = NULL;
114 int seconds_found = 0, count_found = 0, track_found = 0;
115 int seconds_pos = 0, count_pos = 0;
118 int parsed_count = 0;
120 char *saveptr = NULL;
121 pcre2_match_data *match = NULL;
128 for (pos = 0, df_opt = strtok_r(copy_str,
",", &saveptr);
129 pos < strlen(copy_str) && df_opt != NULL;
130 pos++, df_opt = strtok_r(NULL,
",", &saveptr)) {
131 if (strstr(df_opt,
"count"))
133 if (strstr(df_opt,
"second"))
135 if (strstr(df_opt,
"track"))
141 if (count_found != 1 || seconds_found != 1 || track_found != 1)
146 SCLogError(
"pcre_exec parse error, ret %" PRId32
", string %s", ret, rawstr);
156 for (i = 0; i < (ret - 1); i++) {
157 res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
159 SCLogError(
"pcre2_substring_get_bynumber failed");
163 args[i] = (
char *)str_ptr;
166 if (strncasecmp(args[i],
"by_dst", strlen(
"by_dst")) == 0)
168 if (strncasecmp(args[i],
"by_src", strlen(
"by_src")) == 0)
170 if (strncasecmp(args[i],
"by_flow", strlen(
"by_flow")) == 0)
172 if (strncasecmp(args[i],
"count", strlen(
"count")) == 0)
174 if (strncasecmp(args[i],
"seconds", strlen(
"seconds")) == 0)
176 if (strcasecmp(args[i],
"src_port") == 0)
178 if (strcasecmp(args[i],
"dst_port") == 0)
182 if (args[count_pos] == NULL || args[seconds_pos] == NULL) {
199 for (i = 0; i < parsed_count; i++) {
201 pcre2_substring_free((PCRE2_UCHAR *)args[i]);
204 pcre2_match_data_free(match);
208 for (i = 0; i < parsed_count; i++) {
210 pcre2_substring_free((PCRE2_UCHAR *)args[i]);
215 pcre2_match_data_free(match);
241 SCLogError(
"\"detection_filter\" and \"threshold\" are not allowed in the same rule");
247 SCLogError(
"At most one \"detection_filter\" is allowed per rule");
251 df = DetectDetectionFilterParse(rawstr);
261 SCLogError(
"detection_filter unique_on requires protocol tcp/udp/sctp");
314 static int DetectDetectionFilterTestParse01(
void)
321 DetectDetectionFilterFree(NULL, df);
330 static int DetectDetectionFilterTestParse02(
void)
343 static int DetectDetectionFilterTestParse03(
void)
345 DetectThresholdData *df = DetectDetectionFilterParse(
"track by_dst, seconds 60, count 10");
350 DetectDetectionFilterFree(NULL, df);
360 static int DetectDetectionFilterTestParse04(
void)
363 DetectDetectionFilterParse(
"count 10, track by_dst, seconds 60, count 10");
374 static int DetectDetectionFilterTestParse05(
void)
376 DetectThresholdData *df = DetectDetectionFilterParse(
"count 10, track by_dst, seconds 60");
381 DetectDetectionFilterFree(NULL, df);
390 static int DetectDetectionFilterTestParse06(
void)
400 static int DetectDetectionFilterUniqueOnProtoValidationFail(
void)
409 "alert ip any any -> any any (msg:\"DF proto validation\"; "
410 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:29;)");
422 static int DetectDetectionFilterTestParseUnique01(
void)
425 DetectDetectionFilterParse(
"track by_dst, count 10, seconds 60, unique_on dst_port");
431 DetectDetectionFilterFree(NULL, df);
438 static int DetectDetectionFilterDistinctBoundaryNoAlert(
void)
444 memset(&th_v, 0,
sizeof(th_v));
455 "alert tcp any any -> any any (msg:\"DF distinct boundary no alert\"; "
456 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:24;)");
479 static int DetectDetectionFilterDistinctWindowReset(
void)
485 memset(&th_v, 0,
sizeof(th_v));
493 "alert tcp any any -> any any (msg:\"DF distinct window reset\"; "
494 "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:25;)");
549 static int DetectDetectionFilterDistinctAllocFailFallback(
void)
555 memset(&th_v, 0,
sizeof(th_v));
566 "alert tcp any any -> any any (msg:\"DF alloc fail fallback\"; "
567 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:27;)");
611 static int DetectDetectionFilterTestSig1(
void)
618 memset(&th_v, 0,
sizeof(th_v));
629 "alert tcp any any -> any 80 (msg:\"detection_filter Test\"; detection_filter: "
630 "track by_dst, count 4, seconds 60; sid:1;)");
669 static int DetectDetectionFilterTestSig2(
void)
676 memset(&th_v, 0,
sizeof(th_v));
688 "alert tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
689 "detection_filter: track by_dst, count 4, seconds 60; sid:10;)");
728 static int DetectDetectionFilterTestSig3(
void)
735 memset(&th_v, 0,
sizeof(th_v));
746 "drop tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
747 "detection_filter: track by_dst, count 2, seconds 60; sid:10;)");
800 static int DetectDetectionFilterDistinctBitmapMemuseTracking(
void)
806 memset(&th_v, 0,
sizeof(th_v));
817 "alert tcp any any -> any any (msg:\"DF memuse tracking\"; "
818 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:30;)");
830 FAIL_IF_NOT(after_memuse == baseline_memuse + 8192);
848 static int DetectDetectionFilterDistinctAllocFailCounter(
void)
854 memset(&th_v, 0,
sizeof(th_v));
868 "alert tcp any any -> any any (msg:\"DF alloc fail counter\"; "
869 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:31;)");
900 static int DetectDetectionFilterDistinctMultipleTrackers(
void)
906 memset(&th_v, 0,
sizeof(th_v));
916 "alert tcp any any -> any any (msg:\"DF multi tracker\"; "
917 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:32;)");
934 FAIL_IF_NOT(after_memuse == baseline_memuse + (3 * 8192));
954 static int DetectDetectionFilterDistinctBitmapExpiry(
void)
960 memset(&th_v, 0,
sizeof(th_v));
971 "alert tcp any any -> any any (msg:\"DF bitmap expiry\"; "
972 "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:33;)");
984 FAIL_IF_NOT(after_alloc == baseline_memuse + 8192);
1005 static void DetectDetectionFilterRegisterTests(
void)
1007 UtRegisterTest(
"DetectDetectionFilterTestParse01", DetectDetectionFilterTestParse01);
1008 UtRegisterTest(
"DetectDetectionFilterTestParse02", DetectDetectionFilterTestParse02);
1009 UtRegisterTest(
"DetectDetectionFilterTestParse03", DetectDetectionFilterTestParse03);
1010 UtRegisterTest(
"DetectDetectionFilterTestParse04", DetectDetectionFilterTestParse04);
1011 UtRegisterTest(
"DetectDetectionFilterTestParse05", DetectDetectionFilterTestParse05);
1012 UtRegisterTest(
"DetectDetectionFilterTestParse06", DetectDetectionFilterTestParse06);
1014 "DetectDetectionFilterTestParseUnique01", DetectDetectionFilterTestParseUnique01);
1015 UtRegisterTest(
"DetectDetectionFilterTestSig1", DetectDetectionFilterTestSig1);
1016 UtRegisterTest(
"DetectDetectionFilterTestSig2", DetectDetectionFilterTestSig2);
1017 UtRegisterTest(
"DetectDetectionFilterTestSig3", DetectDetectionFilterTestSig3);
1019 DetectDetectionFilterDistinctBoundaryNoAlert);
1021 "DetectDetectionFilterDistinctWindowReset", DetectDetectionFilterDistinctWindowReset);
1023 DetectDetectionFilterDistinctAllocFailFallback);
1024 UtRegisterTest(
"DetectDetectionFilterUniqueOnProtoValidationFail",
1025 DetectDetectionFilterUniqueOnProtoValidationFail);
1026 UtRegisterTest(
"DetectDetectionFilterDistinctBitmapMemuseTracking",
1027 DetectDetectionFilterDistinctBitmapMemuseTracking);
1029 DetectDetectionFilterDistinctAllocFailCounter);
1031 DetectDetectionFilterDistinctMultipleTrackers);
1033 "DetectDetectionFilterDistinctBitmapExpiry", DetectDetectionFilterDistinctBitmapExpiry);