50 "^\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+" \
52 "by_dst|by_flow|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|by_flow|\\d+)" \
53 "(?:\\s*,\\s*unique_on\\s+(src_port|dst_port))?\\s*$"
56 #define DF_PARSE_MIN_SUBMATCHES 5
60 static int DetectDetectionFilterMatch(
64 static void DetectDetectionFilterRegisterTests(
void);
75 "alert on every match after a threshold has been reached";
89 static int DetectDetectionFilterMatch(
110 const char *str_ptr = NULL;
111 char *args[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
112 char *copy_str = NULL, *df_opt = NULL;
113 int seconds_found = 0, count_found = 0, track_found = 0;
114 int seconds_pos = 0, count_pos = 0;
117 int parsed_count = 0;
119 char *saveptr = NULL;
120 pcre2_match_data *match = NULL;
127 for (pos = 0, df_opt = strtok_r(copy_str,
",", &saveptr);
128 pos < strlen(copy_str) && df_opt != NULL;
129 pos++, df_opt = strtok_r(NULL,
",", &saveptr)) {
130 if (strstr(df_opt,
"count"))
132 if (strstr(df_opt,
"second"))
134 if (strstr(df_opt,
"track"))
140 if (count_found != 1 || seconds_found != 1 || track_found != 1)
145 SCLogError(
"pcre_exec parse error, ret %" PRId32
", string %s", ret, rawstr);
155 for (i = 0; i < (ret - 1); i++) {
156 res = pcre2_substring_get_bynumber(match, i + 1, (PCRE2_UCHAR8 **)&str_ptr, &pcre2_len);
158 SCLogError(
"pcre2_substring_get_bynumber failed");
162 args[i] = (
char *)str_ptr;
165 if (strncasecmp(args[i],
"by_dst", strlen(
"by_dst")) == 0)
167 if (strncasecmp(args[i],
"by_src", strlen(
"by_src")) == 0)
169 if (strncasecmp(args[i],
"by_flow", strlen(
"by_flow")) == 0)
171 if (strncasecmp(args[i],
"count", strlen(
"count")) == 0)
173 if (strncasecmp(args[i],
"seconds", strlen(
"seconds")) == 0)
175 if (strcasecmp(args[i],
"src_port") == 0)
177 if (strcasecmp(args[i],
"dst_port") == 0)
181 if (args[count_pos] == NULL || args[seconds_pos] == NULL) {
198 for (i = 0; i < parsed_count; i++) {
200 pcre2_substring_free((PCRE2_UCHAR *)args[i]);
203 pcre2_match_data_free(match);
207 for (i = 0; i < parsed_count; i++) {
209 pcre2_substring_free((PCRE2_UCHAR *)args[i]);
214 pcre2_match_data_free(match);
240 SCLogError(
"\"detection_filter\" and \"threshold\" are not allowed in the same rule");
246 SCLogError(
"At most one \"detection_filter\" is allowed per rule");
250 df = DetectDetectionFilterParse(rawstr);
259 if (!(has_tcp || has_udp || has_sctp)) {
260 SCLogError(
"detection_filter unique_on requires protocol tcp/udp/sctp");
312 static int DetectDetectionFilterTestParse01(
void)
319 DetectDetectionFilterFree(NULL, df);
328 static int DetectDetectionFilterTestParse02(
void)
341 static int DetectDetectionFilterTestParse03(
void)
343 DetectThresholdData *df = DetectDetectionFilterParse(
"track by_dst, seconds 60, count 10");
348 DetectDetectionFilterFree(NULL, df);
358 static int DetectDetectionFilterTestParse04(
void)
361 DetectDetectionFilterParse(
"count 10, track by_dst, seconds 60, count 10");
372 static int DetectDetectionFilterTestParse05(
void)
374 DetectThresholdData *df = DetectDetectionFilterParse(
"count 10, track by_dst, seconds 60");
379 DetectDetectionFilterFree(NULL, df);
388 static int DetectDetectionFilterTestParse06(
void)
398 static int DetectDetectionFilterUniqueOnProtoValidationFail(
void)
407 "alert ip any any -> any any (msg:\"DF proto validation\"; "
408 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:29;)");
420 static int DetectDetectionFilterTestParseUnique01(
void)
423 DetectDetectionFilterParse(
"track by_dst, count 10, seconds 60, unique_on dst_port");
429 DetectDetectionFilterFree(NULL, df);
436 static int DetectDetectionFilterDistinctBoundaryNoAlert(
void)
453 "alert tcp any any -> any any (msg:\"DF distinct boundary no alert\"; "
454 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:24;)");
477 static int DetectDetectionFilterDistinctWindowReset(
void)
491 "alert tcp any any -> any any (msg:\"DF distinct window reset\"; "
492 "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:25;)");
547 static int DetectDetectionFilterDistinctAllocFailFallback(
void)
564 "alert tcp any any -> any any (msg:\"DF alloc fail fallback\"; "
565 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:27;)");
609 static int DetectDetectionFilterTestSig1(
void)
627 "alert tcp any any -> any 80 (msg:\"detection_filter Test\"; detection_filter: "
628 "track by_dst, count 4, seconds 60; sid:1;)");
667 static int DetectDetectionFilterTestSig2(
void)
686 "alert tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
687 "detection_filter: track by_dst, count 4, seconds 60; sid:10;)");
726 static int DetectDetectionFilterTestSig3(
void)
744 "drop tcp any any -> any 80 (msg:\"detection_filter Test 2\"; "
745 "detection_filter: track by_dst, count 2, seconds 60; sid:10;)");
798 static int DetectDetectionFilterDistinctBitmapMemuseTracking(
void)
815 "alert tcp any any -> any any (msg:\"DF memuse tracking\"; "
816 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:30;)");
828 FAIL_IF_NOT(after_memuse == baseline_memuse + 8192);
846 static int DetectDetectionFilterDistinctAllocFailCounter(
void)
866 "alert tcp any any -> any any (msg:\"DF alloc fail counter\"; "
867 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:31;)");
898 static int DetectDetectionFilterDistinctMultipleTrackers(
void)
914 "alert tcp any any -> any any (msg:\"DF multi tracker\"; "
915 "detection_filter: track by_dst, count 2, seconds 60, unique_on dst_port; sid:32;)");
932 FAIL_IF_NOT(after_memuse == baseline_memuse + (3 * 8192));
952 static int DetectDetectionFilterDistinctBitmapExpiry(
void)
969 "alert tcp any any -> any any (msg:\"DF bitmap expiry\"; "
970 "detection_filter: track by_dst, count 2, seconds 2, unique_on dst_port; sid:33;)");
982 FAIL_IF_NOT(after_alloc == baseline_memuse + 8192);
1003 static void DetectDetectionFilterRegisterTests(
void)
1005 UtRegisterTest(
"DetectDetectionFilterTestParse01", DetectDetectionFilterTestParse01);
1006 UtRegisterTest(
"DetectDetectionFilterTestParse02", DetectDetectionFilterTestParse02);
1007 UtRegisterTest(
"DetectDetectionFilterTestParse03", DetectDetectionFilterTestParse03);
1008 UtRegisterTest(
"DetectDetectionFilterTestParse04", DetectDetectionFilterTestParse04);
1009 UtRegisterTest(
"DetectDetectionFilterTestParse05", DetectDetectionFilterTestParse05);
1010 UtRegisterTest(
"DetectDetectionFilterTestParse06", DetectDetectionFilterTestParse06);
1012 "DetectDetectionFilterTestParseUnique01", DetectDetectionFilterTestParseUnique01);
1013 UtRegisterTest(
"DetectDetectionFilterTestSig1", DetectDetectionFilterTestSig1);
1014 UtRegisterTest(
"DetectDetectionFilterTestSig2", DetectDetectionFilterTestSig2);
1015 UtRegisterTest(
"DetectDetectionFilterTestSig3", DetectDetectionFilterTestSig3);
1017 DetectDetectionFilterDistinctBoundaryNoAlert);
1019 "DetectDetectionFilterDistinctWindowReset", DetectDetectionFilterDistinctWindowReset);
1021 DetectDetectionFilterDistinctAllocFailFallback);
1022 UtRegisterTest(
"DetectDetectionFilterUniqueOnProtoValidationFail",
1023 DetectDetectionFilterUniqueOnProtoValidationFail);
1024 UtRegisterTest(
"DetectDetectionFilterDistinctBitmapMemuseTracking",
1025 DetectDetectionFilterDistinctBitmapMemuseTracking);
1027 DetectDetectionFilterDistinctAllocFailCounter);
1029 DetectDetectionFilterDistinctMultipleTrackers);
1031 "DetectDetectionFilterDistinctBitmapExpiry", DetectDetectionFilterDistinctBitmapExpiry);