From ef2ae76c42f0f411b7f63697ed0177fedb5e42bd Mon Sep 17 00:00:00 2001 From: Gerardo Iglesias Galvan Date: Fri, 12 Mar 2010 02:40:21 +0100 Subject: [PATCH] Add support for detection_filter keyword --- src/Makefile.am | 1 + src/detect-detection-filter.c | 513 ++++++++++++++++++++++++++++++++++ src/detect-detection-filter.h | 59 ++++ src/detect-engine-threshold.c | 30 +- src/detect-threshold.c | 9 + src/detect-threshold.h | 3 +- src/detect.c | 2 + src/detect.h | 1 + 8 files changed, 616 insertions(+), 2 deletions(-) create mode 100644 src/detect-detection-filter.c create mode 100644 src/detect-detection-filter.h diff --git a/src/Makefile.am b/src/Makefile.am index 0ef99e8a29..4bb857a1b3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -111,6 +111,7 @@ detect-dce-iface.c detect-dce-iface.h \ detect-dce-opnum.c detect-dce-opnum.h \ detect-dce-stub-data.c detect-dce-stub-data.h \ detect-urilen.c detect-urilen.h \ +detect-detection-filter.c detect-detection-filter.h \ util-print.c util-print.h \ util-fmemopen.c util-fmemopen.h \ util-cpu.c util-cpu.h \ diff --git a/src/detect-detection-filter.c b/src/detect-detection-filter.c new file mode 100644 index 0000000000..f10b51fa04 --- /dev/null +++ b/src/detect-detection-filter.c @@ -0,0 +1,513 @@ +/** + * Copyright (c) 2009 Open Information Security Foundation + * + * \file detect-detection-filter.c + * \author Gerardo Iglesias + * + * "detection_filter" keyword support + */ + +#include "suricata-common.h" +#include "suricata.h" +#include "debug.h" +#include "decode.h" +#include "detect.h" + +#include "detect-detection-filter.h" +#include "detect-threshold.h" +#include "detect-parse.h" + +#include "util-byte.h" +#include "util-unittest.h" +#include "util-debug.h" + +/** + *\brief Regex for parsing our detection_filter options + */ +#define PARSE_REGEX "^\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*,\\s*(track|count|seconds)\\s+(by_src|by_dst|\\d+)\\s*$" + +static pcre *parse_regex; +static pcre_extra *parse_regex_study; + +int DetectDetectionFilterMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *, Signature *, SigMatch *); +int DetectDetectionFilterSetup(DetectEngineCtx *, Signature *, SigMatch *, char *); +void DetectDetectionFilterRegisterTests(void); +void DetectDetectionFilterFree(void *); + +/** + * \brief Registration function for detection_filter: keyword + */ +void DetectDetectionFilterRegister (void) { + sigmatch_table[DETECT_DETECTION_FILTER].name = "detection_filter"; + sigmatch_table[DETECT_DETECTION_FILTER].Match = DetectDetectionFilterMatch; + sigmatch_table[DETECT_DETECTION_FILTER].Setup = DetectDetectionFilterSetup; + sigmatch_table[DETECT_DETECTION_FILTER].Free = DetectDetectionFilterFree; + sigmatch_table[DETECT_DETECTION_FILTER].RegisterTests = DetectDetectionFilterRegisterTests; + + const char *eb; + int eo; + int opts = 0; + + parse_regex = pcre_compile(PARSE_REGEX, opts, &eb, &eo, NULL); + if(parse_regex == NULL) + { + SCLogError(SC_ERR_PCRE_COMPILE, "pcre compile of \"%s\" failed at offset %" PRId32 ": %s", PARSE_REGEX, eo, eb); + goto error; + } + + parse_regex_study = pcre_study(parse_regex, 0, &eb); + if(eb != NULL) + { + SCLogError(SC_ERR_PCRE_STUDY, "pcre study failed: %s", eb); + goto error; + } + return; + +error: + return; +} + +int DetectDetectionFilterMatch (ThreadVars *thv, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *sm) { + return 1; +} + +/** + * \internal + * \brief This function is used to parse detection_filter options passed via detection_filter: keyword + * + * \param rawstr Pointer to the user provided detection_filter options + * + * \retval df pointer to DetectThresholdData on success + * \retval NULL on failure + */ +DetectThresholdData *DetectDetectionFilterParse (char *rawstr) { + DetectThresholdData *df = NULL; +#define MAX_SUBSTRINGS 30 + int ret = 0, res = 0; + int ov[MAX_SUBSTRINGS]; + const char *str_ptr = NULL; + char *args[6] = { NULL, NULL, NULL, NULL, NULL, NULL}; + char *copy_str = NULL, *df_opt = NULL; + int seconds_found = 0, count_found = 0, track_found = 0; + int seconds_pos = 0, count_pos = 0; + uint16_t pos = 0; + int i = 0; + + copy_str = SCStrdup(rawstr); + + for(pos = 0, df_opt = strtok(copy_str,","); pos < strlen(copy_str) && df_opt != NULL; pos++, df_opt = strtok(NULL,",")) { + + if(strstr(df_opt,"count")) + count_found++; + if(strstr(df_opt,"second")) + seconds_found++; + if(strstr(df_opt,"track")) + track_found++; + } + + if(copy_str) + SCFree(copy_str); + + if(count_found != 1 || seconds_found != 1 || track_found != 1) + goto error; + + ret = pcre_exec(parse_regex, parse_regex_study, rawstr, strlen(rawstr), 0, 0, ov, MAX_SUBSTRINGS); + + if (ret < 5) { + SCLogError(SC_ERR_PCRE_MATCH, "pcre_exec parse error, ret %" PRId32 ", string %s", ret, rawstr); + goto error; + } + + df = SCMalloc(sizeof(DetectDetectionFilterData)); + if (df == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "malloc failed"); + goto error; + } + + memset(df,0,sizeof(DetectDetectionFilterData)); + + df->type = TYPE_DETECTION; + + for (i = 0; i < (ret - 1); i++) { + + res = pcre_get_substring((char *)rawstr, ov, MAX_SUBSTRINGS, i + 1, &str_ptr); + + if (res < 0) { + SCLogError(SC_ERR_PCRE_GET_SUBSTRING, "pcre_get_substring failed"); + goto error; + } + + args[i] = (char *)str_ptr; + + if (strncasecmp(args[i],"by_dst",strlen("by_dst")) == 0) + df->track = TRACK_DST; + if (strncasecmp(args[i],"by_src",strlen("by_src")) == 0) + df->track = TRACK_SRC; + if (strncasecmp(args[i],"count",strlen("count")) == 0) + count_pos = i+1; + if (strncasecmp(args[i],"seconds",strlen("seconds")) == 0) + seconds_pos = i+1; + } + + if (ByteExtractStringUint32(&df->count, 10, strlen(args[count_pos]), args[count_pos]) <= 0) { + goto error; + } + + if (ByteExtractStringUint32(&df->seconds, 10, strlen(args[seconds_pos]), args[seconds_pos]) <= 0) { + goto error; + } + + if (df->count == 0 || df->seconds == 0) { + SCLogError(SC_ERR_INVALID_VALUE, "found an invalid value"); + goto error; + } + + for (i = 0; i < (ret - 1); i++){ + if (args[i] != NULL) SCFree(args[i]); + } + return df; + +error: + for (i = 0; i < (ret - 1); i++){ + if (args[i] != NULL) SCFree(args[i]); + } + if (df) SCFree(df); + return NULL; +} + +/** + * \internal + * \brief this function is used to add the parsed detection_filter into the current signature + * + * \param de_ctx pointer to the Detection Engine Context + * \param s pointer to the Current Signature + * \param m pointer to the Current SigMatch + * \param rawstr pointer to the user provided detection_filter options + * + * \retval 0 on Success + * \retval -1 on Failure + */ +int DetectDetectionFilterSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char *rawstr) { + SCEnter(); + DetectThresholdData *df = NULL; + SigMatch *sm = NULL; + SigMatch *tmpm = NULL; + + /* checks if there's a previous instance of threshold */ + tmpm = SigMatchGetLastSM(s, DETECT_THRESHOLD); + if (tmpm != NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "\"detection_filter\" and \"threshold\" are not allowed in the same rule"); + SCReturnInt(-1); + } + /* checks there's no previous instance of detection_filter */ + tmpm = SigMatchGetLastSM(s, DETECT_DETECTION_FILTER); + if (tmpm != NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "At most one \"detection_filter\" is allowed per rule"); + SCReturnInt(-1); + } + + df = DetectDetectionFilterParse(rawstr); + if (df == NULL) + goto error; + + sm = SigMatchAlloc(); + if (sm == NULL) + goto error; + + sm->type = DETECT_DETECTION_FILTER; + sm->ctx = (void *)df; + + SigMatchAppend(s,m,sm); + + return 0; + +error: + if (df) SCFree(df); + if (sm) SCFree(sm); + return -1; +} + +/** + * \internal + * \brief this function will free memory associated with DetectThresholdData + * + * \param df_ptr pointer to DetectDetectionFilterData + */ +void DetectDetectionFilterFree(void *df_ptr) { + DetectThresholdData *df = (DetectThresholdData *)df_ptr; + if (df) SCFree(df); +} + +/* + * ONLY TESTS BELOW THIS COMMENT + */ +#ifdef UNITTESTS + +#include "detect-parse.h" +#include "detect-engine.h" +#include "detect-engine-mpm.h" +#include "detect-engine-threshold.h" +#include "util-time.h" +#include "util-hashlist.h" + +/** + * \test DetectDetectionFilterTestParse01 is a test for a valid detection_filter options + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse01 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("track by_dst,count 10,seconds 60"); + if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + +/** + * \test DetectDetectionFilterTestParse02 is a test for a invalid detection_filter options + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse02 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("track both,count 10,seconds 60"); + if (df && (df->track == TRACK_DST || df->track == TRACK_SRC) && (df->count == 10) && (df->seconds == 60)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + +/** + * \test DetectDetectionfilterTestParse03 is a test for a valid detection_filter options in any order + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse03 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("track by_dst, seconds 60, count 10"); + if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + + +/** + * \test DetectDetectionFilterTestParse04 is a test for an invalid detection_filter options in any order + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse04 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("count 10, track by_dst, seconds 60, count 10"); + if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + +/** + * \test DetectDetectionFilterTestParse05 is a test for a valid detection_filter options in any order + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse05 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("count 10, track by_dst, seconds 60"); + if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 60)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + +/** + * \test DetectDetectionFilterTestParse06 is a test for an invalid value in detection_filter + * + * \retval 1 on succces + * \retval 0 on failure + */ +int DetectDetectionFilterTestParse06 (void) { + DetectThresholdData *df = NULL; + df = DetectDetectionFilterParse("count 10, track by_dst, seconds 0"); + if (df && (df->track == TRACK_DST) && (df->count == 10) && (df->seconds == 0)) { + DetectDetectionFilterFree(df); + return 1; + } + + return 0; +} + +/** + * \test DetectDetectionFilterTestSig1 is a test for checking the working of detection_filter keyword + * by setting up the signature and later testing its working by matching + * the received packet against the sig. + * + * \retval 1 on succces + * \retval 0 on failure + */ +static int DetectDetectionFilterTestSig1(void) { + + Packet p; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 0; + int alerts = 0; + IPV4Hdr ip4h; + + memset(&th_v, 0, sizeof(th_v)); + memset(&p, 0, sizeof(p)); + memset(&ip4h, 0, sizeof(ip4h)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.proto = IPPROTO_TCP; + p.ip4h = &ip4h; + p.ip4h->ip_src.s_addr = 0x01010101; + p.ip4h->ip_dst.s_addr = 0x02020202; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"detection_filter Test\"; detection_filter: track by_dst, count 4, seconds 60; sid:1;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + + alerts = PacketAlertCheck(&p, 1); + + if(alerts == 5) + result = 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + +end: + return result; +} + +/** + * \test DetectDetectionFilterTestSig2 is a test for checking the working of detection_filter keyword + * by setting up the signature and later testing its working by matching + * the received packet against the sig. + * + * \retval 1 on succces + * \retval 0 on failure + */ + +static int DetectDetectionFilterTestSig2(void) { + + Packet p; + Signature *s = NULL; + ThreadVars th_v; + DetectEngineThreadCtx *det_ctx; + int result = 0; + int alerts = 0; + IPV4Hdr ip4h; + struct timeval ts; + + memset (&ts, 0, sizeof(struct timeval)); + TimeGet(&ts); + + memset(&th_v, 0, sizeof(th_v)); + memset(&p, 0, sizeof(p)); + memset(&ip4h, 0, sizeof(ip4h)); + + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.proto = IPPROTO_TCP; + p.ip4h = &ip4h; + p.ip4h->ip_src.s_addr = 0x01010101; + p.ip4h->ip_dst.s_addr = 0x02020202; + + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->flags |= DE_QUIET; + + s = de_ctx->sig_list = SigInit(de_ctx,"alert tcp any any -> any any (msg:\"detection_filter Test 2\"; detection_filter: track by_dst, count 4, seconds 60; sid:10;)"); + if (s == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + DetectEngineThreadCtxInit(&th_v, (void *)de_ctx, (void *)&det_ctx); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + + TimeSetIncrementTime(200); + + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + SigMatchSignatures(&th_v, de_ctx, det_ctx, &p); + + alerts = PacketAlertCheck(&p, 10); + + if (alerts == 1) + result = 1; + + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&th_v, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); +end: + return result; +} + + +#endif /* UNITTESTS */ + +void DetectDetectionFilterRegisterTests(void) { +#ifdef UNITTESTS + UtRegisterTest("DetectDetectionFilterTestParse01", DetectDetectionFilterTestParse01, 1); + UtRegisterTest("DetectDetectionFilterTestParse02", DetectDetectionFilterTestParse02, 0); + UtRegisterTest("DetectDetectionFilterTestParse03", DetectDetectionFilterTestParse03, 1); + UtRegisterTest("DetectDetectionFilterTestParse04", DetectDetectionFilterTestParse04, 0); + UtRegisterTest("DetectDetectionFilterTestParse05", DetectDetectionFilterTestParse05, 1); + UtRegisterTest("DetectDetectionFilterTestParse06", DetectDetectionFilterTestParse06, 0); + UtRegisterTest("DetectDetectionFilterTestSig1", DetectDetectionFilterTestSig1, 1); + UtRegisterTest("DetectDetectionFilterTestSig2", DetectDetectionFilterTestSig2, 1); +#endif /* UNITTESTS */ +} + diff --git a/src/detect-detection-filter.h b/src/detect-detection-filter.h new file mode 100644 index 0000000000..5b3c211da7 --- /dev/null +++ b/src/detect-detection-filter.h @@ -0,0 +1,59 @@ +/** + * Copyright (c) 2009 Open Information Security Foundation + * + * \file detect-detection-filter.h + * \author Gerardo Iglesias + * + */ + +#ifndef __DETECT_DETECTION_FILTER_H__ +#define __DETECT_DETECTION_FILTER_H__ + +#include "decode-events.h" +#include "decode-ipv4.h" +#include "decode-tcp.h" + +#define TRACK_DST 1 +#define TRACK_SRC 2 + +/** + * \typedef DetectDetectionFilterData + * A typedef for DetectDetectionFilterData_ + * + */ +typedef struct DetectDetectionFilterData_ { + uint8_t track; /**< Track type: by_src, by_dst */ + uint32_t count; /**< Event count */ + uint32_t seconds; /**< Event seconds */ +} DetectDetectionFilterData; + +/** + *\typedef DetectDetectionFilterEntry + * A typedef for DetecDetectionFilterEntry_ + * + */ +typedef struct DetectDetectionFilterEntry_ { + uint8_t track; /**< Track type: by_src, by_dst */ + uint32_t seconds; /**< Event seconds */ + + Address addr; /**< Var used to store dst or src addr */ + + uint32_t tv_sec1; /**< Var for time control */ + uint32_t current_count; /**< Var for count control */ +} DetectDetectionFilterEntry; + + +/** + * Registration function for detection_filter: keyword + */ + +void DetectDetectionFilterRegister (void); + +/** + * This function registers unit tests for detection_filter + */ + +void DetectDetectionFilterRegisterTests(void); + +#endif /*__DETECT_DETECTION_FILTER_H__ */ + diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index d9493911fc..f376d58015 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -78,7 +78,7 @@ DetectThresholdData *SigGetThresholdType(Signature *sig, Packet *p) return NULL; while (sm != NULL) { - if (sm->type == DETECT_THRESHOLD) { + if (sm->type == DETECT_THRESHOLD || sm->type == DETECT_DETECTION_FILTER) { tsh = (DetectThresholdData *)sm->ctx; return tsh; } @@ -357,6 +357,34 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack } break; } + /* detection_filter */ + case TYPE_DETECTION: + { + SCLogDebug("detection_filter"); + + lookup_tsh = ThresholdHashSearch(de_ctx,ste,p); + if (lookup_tsh != NULL) { + if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { + lookup_tsh->current_count++; + if (lookup_tsh->current_count >= td->count) { + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + } + } else { + lookup_tsh->tv_sec1 = ts.tv_sec; + lookup_tsh->current_count = 1; + } + } else { + ste->current_count = 1; + ste->tv_sec1 = ts.tv_sec; + + if (td->count == 1) { + PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + } + ThresholdHashAdd(de_ctx, ste, p); + ste = NULL; + } + break; + } } SCMutexUnlock(&de_ctx->ths_ctx.threshold_table_lock); diff --git a/src/detect-threshold.c b/src/detect-threshold.c index afbc28d6fd..9aa9d2c36c 100644 --- a/src/detect-threshold.c +++ b/src/detect-threshold.c @@ -16,6 +16,7 @@ #include "stream-tcp.h" #include "detect-threshold.h" +#include "detect-parse.h" #include "util-unittest.h" #include "util-byte.h" @@ -193,6 +194,14 @@ static int DetectThresholdSetup (DetectEngineCtx *de_ctx, Signature *s, char *ra { DetectThresholdData *de = NULL; SigMatch *sm = NULL; + SigMatch *tmpm = NULL; + + /* checks if there is a previous instance of detection_filter */ + tmpm = SigMatchGetLastSM(s, DETECT_DETECTION_FILTER); + if (tmpm != NULL) { + SCLogError(SC_ERR_INVALID_SIGNATURE, "\"detection_filter\" and \"threshold\" are not allowed in the same rule"); + SCReturnInt(-1); + } de = DetectThresholdParse(rawstr); if (de == NULL) diff --git a/src/detect-threshold.h b/src/detect-threshold.h index b7025b4e54..fb6083406d 100644 --- a/src/detect-threshold.h +++ b/src/detect-threshold.h @@ -14,6 +14,7 @@ #define TYPE_LIMIT 1 #define TYPE_BOTH 2 #define TYPE_THRESHOLD 3 +#define TYPE_DETECTION 4 #define TRACK_DST 1 #define TRACK_SRC 2 @@ -24,7 +25,7 @@ */ typedef struct DetectThresholdData_ { - uint8_t type; /**< Threshold type : limit , threshold, both */ + uint8_t type; /**< Threshold type : limit , threshold, both, detection_filter */ uint8_t track; /**< Track type: by_src, by_src */ uint32_t count; /**< Event count */ uint32_t seconds; /**< Event seconds */ diff --git a/src/detect.c b/src/detect.c index 62d80ceab4..367d80980e 100644 --- a/src/detect.c +++ b/src/detect.c @@ -79,6 +79,7 @@ #include "detect-dce-opnum.h" #include "detect-dce-stub-data.h" #include "detect-urilen.h" +#include "detect-detection-filter.h" #include "util-rule-vars.h" @@ -2910,6 +2911,7 @@ void SigTableSetup(void) { DetectHttpMethodRegister(); DetectTlsVersionRegister(); DetectUrilenRegister(); + DetectDetectionFilterRegister(); uint8_t i = 0; for (i = 0; i < DETECT_TBLSIZE; i++) { diff --git a/src/detect.h b/src/detect.h index 2b90f75614..4fa884f292 100644 --- a/src/detect.h +++ b/src/detect.h @@ -549,6 +549,7 @@ enum { DETECT_ICODE, DETECT_ICMP_ID, DETECT_ICMP_SEQ, + DETECT_DETECTION_FILTER, DETECT_ADDRESS, DETECT_PROTO,