detect: pattern id assignment through hash table

Only consider active part of the pattern for mpm (so consider chop).

Move data structure to hash list table over the custom array logic.
pull/7204/head
Victor Julien 3 years ago
parent a14854bce9
commit 54a6dd09dd

@ -683,15 +683,11 @@ static void DumpMatches(RuleAnalyzer *ctx, JsonBuilder *js, const SigMatchData *
jb_close(js);
}
static void EngineAnalysisRulePatterns(const DetectEngineCtx *de_ctx, const Signature *s);
SCMutex g_rules_analyzer_write_m = SCMUTEX_INITIALIZER;
void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
{
SCEnter();
EngineAnalysisRulePatterns(de_ctx, s);
RuleAnalyzer ctx = { NULL, NULL, NULL };
ctx.js = jb_new_object();
@ -977,98 +973,6 @@ void EngineAnalysisRules2(const DetectEngineCtx *de_ctx, const Signature *s)
SCReturn;
}
struct PatternItem {
const DetectContentData *cd;
int sm_list;
uint32_t cnt;
uint32_t mpm;
};
static inline uint32_t ContentFlagsForHash(const DetectContentData *cd)
{
return cd->flags & (DETECT_CONTENT_NOCASE | DETECT_CONTENT_OFFSET | DETECT_CONTENT_DEPTH |
DETECT_CONTENT_NEGATED | DETECT_CONTENT_ENDS_WITH);
}
/** \internal
* \brief The hash function for Pattern
*
* \param ht Pointer to the hash table.
* \param data Pointer to the Pattern.
* \param datalen Not used in our case.
*
* \retval hash The generated hash value.
*/
static uint32_t PatternHashFunc(HashListTable *ht, void *data, uint16_t datalen)
{
struct PatternItem *p = (struct PatternItem *)data;
uint32_t hash = p->sm_list + ContentFlagsForHash(p->cd);
for (uint32_t b = 0; b < p->cd->content_len; b++)
hash += p->cd->content[b];
return hash % ht->array_size;
}
/**
* \brief The Compare function for Pattern
*
* \param data1 Pointer to the first Pattern.
* \param len1 Not used.
* \param data2 Pointer to the second Pattern.
* \param len2 Not used.
*
* \retval 1 If the 2 Patterns sent as args match.
* \retval 0 If the 2 Patterns sent as args do not match.
*/
static char PatternCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
{
const struct PatternItem *p1 = (struct PatternItem *)data1;
const struct PatternItem *p2 = (struct PatternItem *)data2;
if (p1->sm_list != p2->sm_list)
return 0;
if (ContentFlagsForHash(p1->cd) != ContentFlagsForHash(p2->cd))
return 0;
if (p1->cd->content_len != p2->cd->content_len)
return 0;
if (memcmp(p1->cd->content, p2->cd->content, p1->cd->content_len) != 0) {
return 0;
}
return 1;
}
static void PatternFreeFunc(void *ptr)
{
SCFree(ptr);
}
/**
* \brief Initializes the Pattern mpm hash table to be used by the detection
* engine context.
*
* \param de_ctx Pointer to the detection engine context.
*
* \retval 0 On success.
* \retval -1 On failure.
*/
static int PatternInit(DetectEngineCtx *de_ctx)
{
de_ctx->pattern_hash_table =
HashListTableInit(4096, PatternHashFunc, PatternCompareFunc, PatternFreeFunc);
if (de_ctx->pattern_hash_table == NULL)
goto error;
return 0;
error:
return -1;
}
void DumpPatterns(DetectEngineCtx *de_ctx)
{
if (de_ctx->pattern_hash_table == NULL)
@ -1083,7 +987,7 @@ void DumpPatterns(DetectEngineCtx *de_ctx)
for (HashListTableBucket *htb = HashListTableGetListHead(de_ctx->pattern_hash_table);
htb != NULL; htb = HashListTableGetListNext(htb)) {
char str[1024] = "";
struct PatternItem *p = HashListTableGetListData(htb);
DetectPatternTracker *p = HashListTableGetListData(htb);
DetectContentPatternPrettyPrint(p->cd, str, sizeof(str));
JsonBuilder *jb = arrays[p->sm_list];
@ -1148,156 +1052,6 @@ void DumpPatterns(DetectEngineCtx *de_ctx)
de_ctx->pattern_hash_table = NULL;
}
static void EngineAnalysisRulePatterns(const DetectEngineCtx *de_ctx, const Signature *s)
{
SCEnter();
if (de_ctx->pattern_hash_table == NULL)
PatternInit((DetectEngineCtx *)de_ctx); // TODO hack const
if (s->sm_arrays[DETECT_SM_LIST_PMATCH]) {
SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_PMATCH];
do {
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
struct PatternItem lookup = {
.cd = cd, .sm_list = DETECT_SM_LIST_PMATCH, .cnt = 0, .mpm = 0
};
struct PatternItem *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
struct PatternItem *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = DETECT_SM_LIST_PMATCH;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEngineAppInspectionEngine *app = s->app_inspect;
for (; app != NULL; app = app->next) {
SigMatchData *smd = app->smd;
do {
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
struct PatternItem lookup = {
.cd = cd, .sm_list = app->sm_list, .cnt = 0, .mpm = 0
};
struct PatternItem *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
struct PatternItem *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = app->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEnginePktInspectionEngine *pkt = s->pkt_inspect;
for (; pkt != NULL; pkt = pkt->next) {
SigMatchData *smd = pkt->smd;
do {
if (smd == NULL) {
BUG_ON(!(pkt->sm_list < DETECT_SM_LIST_DYNAMIC_START));
smd = s->sm_arrays[pkt->sm_list];
}
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
struct PatternItem lookup = {
.cd = cd, .sm_list = pkt->sm_list, .cnt = 0, .mpm = 0
};
struct PatternItem *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
struct PatternItem *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = pkt->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEngineFrameInspectionEngine *frame = s->frame_inspect;
for (; frame != NULL; frame = frame->next) {
SigMatchData *smd = frame->smd;
do {
if (smd == NULL) {
BUG_ON(!(frame->sm_list < DETECT_SM_LIST_DYNAMIC_START));
smd = s->sm_arrays[frame->sm_list];
}
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
struct PatternItem lookup = {
.cd = cd, .sm_list = frame->sm_list, .cnt = 0, .mpm = 0
};
struct PatternItem *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
struct PatternItem *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = frame->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
SCReturn;
}
static void EngineAnalysisItemsReset(void)
{
for (size_t i = 0; i < ARRAY_SIZE(analyzer_items); i++) {

@ -1901,6 +1901,7 @@ static int SigMatchPrepare(DetectEngineCtx *de_ctx)
DetectEnginePktInspectionSetup(s);
if (rule_engine_analysis_set) {
EngineAnalysisAddAllRulePatterns(de_ctx, s);
EngineAnalysisRules2(de_ctx, s);
}
/* free lists. Ctx' are xferred to sm_arrays so won't get freed */

@ -61,6 +61,7 @@
#include "util-debug.h"
#include "util-print.h"
#include "util-validate.h"
#include "util-hash-string.h"
const char *builtin_mpms[] = {
"toserver TCP packet",
@ -2101,14 +2102,133 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
return 0;
}
typedef struct DetectFPAndItsId_ {
PatIntId id;
uint16_t content_len;
uint32_t flags;
int sm_list;
static inline uint32_t ContentFlagsForHash(const DetectContentData *cd)
{
return cd->flags & (DETECT_CONTENT_NOCASE | DETECT_CONTENT_OFFSET | DETECT_CONTENT_DEPTH |
DETECT_CONTENT_NEGATED | DETECT_CONTENT_ENDS_WITH);
}
/** \internal
* \brief The hash function for Pattern. Hashes pattern after chop is applied.
*
* \param ht Pointer to the hash table.
* \param data Pointer to the Pattern.
* \param datalen Not used in our case.
*
* \retval hash The generated hash value.
*/
static uint32_t PatternChopHashFunc(HashListTable *ht, void *data, uint16_t datalen)
{
const DetectPatternTracker *p = (DetectPatternTracker *)data;
uint32_t hash = p->sm_list + ContentFlagsForHash(p->cd);
uint16_t content_len = p->cd->content_len;
const uint8_t *content = p->cd->content;
if (p->cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
content += p->cd->fp_chop_offset;
content_len = p->cd->fp_chop_len;
}
hash += StringHashDjb2(content, content_len);
return hash % ht->array_size;
}
/** \internal
* \brief The hash function for Pattern. Ignores chop.
*
* \param ht Pointer to the hash table.
* \param data Pointer to the Pattern.
* \param datalen Not used in our case.
*
* \retval hash The generated hash value.
*/
static uint32_t PatternNoChopHashFunc(HashListTable *ht, void *data, uint16_t datalen)
{
const DetectPatternTracker *p = (DetectPatternTracker *)data;
uint32_t hash = p->sm_list + ContentFlagsForHash(p->cd);
hash += StringHashDjb2(p->cd->content, p->cd->content_len);
return hash % ht->array_size;
}
/**
* \brief The Compare function for Pattern. Compares patterns after chop is applied.
*
* \param data1 Pointer to the first Pattern.
* \param len1 Not used.
* \param data2 Pointer to the second Pattern.
* \param len2 Not used.
*
* \retval 1 If the 2 Patterns sent as args match.
* \retval 0 If the 2 Patterns sent as args do not match.
*/
static char PatternChopCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
{
const DetectPatternTracker *p1 = (DetectPatternTracker *)data1;
const DetectPatternTracker *p2 = (DetectPatternTracker *)data2;
if (p1->sm_list != p2->sm_list)
return 0;
if (ContentFlagsForHash(p1->cd) != ContentFlagsForHash(p2->cd))
return 0;
uint16_t p1_content_len = p1->cd->content_len;
uint8_t *p1_content = p1->cd->content;
if (p1->cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
p1_content += p1->cd->fp_chop_offset;
p1_content_len = p1->cd->fp_chop_len;
}
uint16_t p2_content_len = p2->cd->content_len;
uint8_t *p2_content = p2->cd->content;
if (p2->cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
p2_content += p2->cd->fp_chop_offset;
p2_content_len = p2->cd->fp_chop_len;
}
if (p1_content_len != p2_content_len)
return 0;
if (memcmp(p1_content, p2_content, p1_content_len) != 0) {
return 0;
}
return 1;
}
/**
* \brief The Compare function for Pattern. Ignores chop settings
*
* \param data1 Pointer to the first Pattern.
* \param len1 Not used.
* \param data2 Pointer to the second Pattern.
* \param len2 Not used.
*
* \retval 1 If the 2 Patterns sent as args match.
* \retval 0 If the 2 Patterns sent as args do not match.
*/
static char PatternNoChopCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
{
const DetectPatternTracker *p1 = (DetectPatternTracker *)data1;
const DetectPatternTracker *p2 = (DetectPatternTracker *)data2;
if (p1->sm_list != p2->sm_list)
return 0;
if (ContentFlagsForHash(p1->cd) != ContentFlagsForHash(p2->cd))
return 0;
if (p1->cd->content_len != p2->cd->content_len)
return 0;
if (memcmp(p1->cd->content, p2->cd->content, p1->cd->content_len) != 0) {
return 0;
}
uint8_t *content;
} DetectFPAndItsId;
return 1;
}
static void PatternFreeFunc(void *ptr)
{
SCFree(ptr);
}
/**
* \brief Figured out the FP and their respective content ids for all the
@ -2121,116 +2241,212 @@ typedef struct DetectFPAndItsId_ {
*/
int DetectSetFastPatternAndItsId(DetectEngineCtx *de_ctx)
{
uint32_t struct_total_size = 0;
uint32_t content_total_size = 0;
Signature *s = NULL;
/* Count the amount of memory needed to store all the structures
* and the content of those structures. This will over estimate the
* true size, since duplicates are removed below, but counted here.
*/
for (s = de_ctx->sig_list; s != NULL; s = s->next) {
uint32_t cnt = 0;
for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
if (s->flags & SIG_FLAG_PREFILTER)
continue;
RetrieveFPForSig(de_ctx, s);
if (s->init_data->mpm_sm != NULL) {
DetectContentData *cd = (DetectContentData *)s->init_data->mpm_sm->ctx;
struct_total_size += sizeof(DetectFPAndItsId);
content_total_size += cd->content_len;
s->flags |= SIG_FLAG_PREFILTER;
cnt++;
}
}
/* no rules */
if (struct_total_size + content_total_size == 0)
/* no mpm rules */
if (cnt == 0)
return 0;
/* array hash buffer - I've run out of ideas to name it */
uint8_t *ahb = SCMalloc(sizeof(uint8_t) * (struct_total_size + content_total_size));
if (unlikely(ahb == NULL))
return -1;
uint8_t *content = NULL;
uint16_t content_len = 0;
HashListTable *ht =
HashListTableInit(4096, PatternChopHashFunc, PatternChopCompareFunc, PatternFreeFunc);
BUG_ON(ht == NULL);
PatIntId max_id = 0;
DetectFPAndItsId *struct_offset = (DetectFPAndItsId *)ahb;
uint8_t *content_offset = ahb + struct_total_size;
for (s = de_ctx->sig_list; s != NULL; s = s->next) {
if (s->init_data->mpm_sm != NULL) {
int sm_list = s->init_data->mpm_sm_list;
BUG_ON(sm_list == -1);
DetectContentData *cd = (DetectContentData *)s->init_data->mpm_sm->ctx;
DetectFPAndItsId *dup = (DetectFPAndItsId *)ahb;
if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
content = cd->content + cd->fp_chop_offset;
content_len = cd->fp_chop_len;
} else {
content = cd->content;
content_len = cd->content_len;
}
uint32_t flags = cd->flags & DETECT_CONTENT_NOCASE;
/* Check for content already found on the same list */
for (; dup != struct_offset; dup++) {
if (dup->content_len != content_len)
continue;
if (dup->sm_list != sm_list)
continue;
if (dup->flags != flags)
continue;
/* Check for pattern matching a duplicate. Use case insensitive matching
* for case insensitive patterns. */
if (flags & DETECT_CONTENT_NOCASE) {
if (SCMemcmpLowercase(dup->content, content, content_len) != 0)
continue;
} else {
/* Case sensitive matching */
if (SCMemcmp(dup->content, content, content_len) != 0)
continue;
}
/* Found a match with a previous pattern. */
break;
}
if (dup != struct_offset) {
/* Exited for-loop before the end, so found an existing match.
* Use its ID. */
cd->id = dup->id;
continue;
}
for (Signature *s = de_ctx->sig_list; s != NULL; s = s->next) {
if (s->init_data->mpm_sm == NULL)
continue;
/* Not found, so new content. Give it a new ID and add it
* to the array. Copy the content at the end of the
* content array.
*/
struct_offset->id = max_id++;
cd->id = struct_offset->id;
struct_offset->content_len = content_len;
struct_offset->sm_list = sm_list;
struct_offset->content = content_offset;
struct_offset->flags = flags;
content_offset += content_len;
if (flags & DETECT_CONTENT_NOCASE) {
/* Need to store case-insensitive patterns as lower case
* because SCMemcmpLowercase() above assumes that all
* patterns are stored lower case so that it doesn't
* need to re-lower its first argument.
*/
memcpy_tolower(struct_offset->content, content, content_len);
} else {
memcpy(struct_offset->content, content, content_len);
}
const int sm_list = s->init_data->mpm_sm_list;
BUG_ON(sm_list == -1);
DetectContentData *cd = (DetectContentData *)s->init_data->mpm_sm->ctx;
DetectPatternTracker lookup = { .cd = cd, .sm_list = sm_list, .cnt = 0, .mpm = 0 };
DetectPatternTracker *res = HashListTableLookup(ht, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
cd->id = res->cd->id;
SCLogDebug("%u: res id %u cnt %u", s->id, res->cd->id, res->cnt);
} else {
DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(ht, (void *)add, 0);
struct_offset++;
} /* if (s->mpm_sm != NULL) */
} /* for */
cd->id = max_id++;
SCLogDebug("%u: add id %u cnt %u", s->id, add->cd->id, add->cnt);
}
}
de_ctx->max_fp_id = max_id;
SCFree(ahb);
HashListTableFree(ht);
return 0;
}
/** \brief add all patterns on our stats hash
* Used to fill the hash later used by DumpPatterns()
* \note sets up the hash table on first call
*/
void EngineAnalysisAddAllRulePatterns(DetectEngineCtx *de_ctx, const Signature *s)
{
if (de_ctx->pattern_hash_table == NULL) {
de_ctx->pattern_hash_table = HashListTableInit(
4096, PatternNoChopHashFunc, PatternNoChopCompareFunc, PatternFreeFunc);
BUG_ON(de_ctx->pattern_hash_table == NULL);
}
if (s->sm_arrays[DETECT_SM_LIST_PMATCH]) {
SigMatchData *smd = s->sm_arrays[DETECT_SM_LIST_PMATCH];
do {
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
DetectPatternTracker lookup = {
.cd = cd, .sm_list = DETECT_SM_LIST_PMATCH, .cnt = 0, .mpm = 0
};
DetectPatternTracker *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = DETECT_SM_LIST_PMATCH;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEngineAppInspectionEngine *app = s->app_inspect;
for (; app != NULL; app = app->next) {
SigMatchData *smd = app->smd;
do {
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
DetectPatternTracker lookup = {
.cd = cd, .sm_list = app->sm_list, .cnt = 0, .mpm = 0
};
DetectPatternTracker *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = app->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEnginePktInspectionEngine *pkt = s->pkt_inspect;
for (; pkt != NULL; pkt = pkt->next) {
SigMatchData *smd = pkt->smd;
do {
if (smd == NULL) {
BUG_ON(!(pkt->sm_list < DETECT_SM_LIST_DYNAMIC_START));
smd = s->sm_arrays[pkt->sm_list];
}
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
DetectPatternTracker lookup = {
.cd = cd, .sm_list = pkt->sm_list, .cnt = 0, .mpm = 0
};
DetectPatternTracker *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = pkt->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
const DetectEngineFrameInspectionEngine *frame = s->frame_inspect;
for (; frame != NULL; frame = frame->next) {
SigMatchData *smd = frame->smd;
do {
if (smd == NULL) {
BUG_ON(!(frame->sm_list < DETECT_SM_LIST_DYNAMIC_START));
smd = s->sm_arrays[frame->sm_list];
}
switch (smd->type) {
case DETECT_CONTENT: {
const DetectContentData *cd = (const DetectContentData *)smd->ctx;
DetectPatternTracker lookup = {
.cd = cd, .sm_list = frame->sm_list, .cnt = 0, .mpm = 0
};
DetectPatternTracker *res =
HashListTableLookup(de_ctx->pattern_hash_table, &lookup, 0);
if (res) {
res->cnt++;
res->mpm += ((cd->flags & DETECT_CONTENT_MPM) != 0);
} else {
DetectPatternTracker *add = SCCalloc(1, sizeof(*add));
BUG_ON(add == NULL);
add->cd = cd;
add->sm_list = frame->sm_list;
add->cnt = 1;
add->mpm = ((cd->flags & DETECT_CONTENT_MPM) != 0);
HashListTableAdd(de_ctx->pattern_hash_table, (void *)add, 0);
}
break;
}
}
if (smd->is_last)
break;
smd++;
} while (1);
}
}

@ -144,5 +144,7 @@ struct MpmListIdDataArgs {
void *txv;
};
void EngineAnalysisAddAllRulePatterns(DetectEngineCtx *de_ctx, const Signature *s);
#endif /* __DETECT_ENGINE_MPM_H__ */

@ -673,6 +673,14 @@ typedef struct DetectBufferMpmRegistery_ {
struct DetectBufferMpmRegistery_ *next;
} DetectBufferMpmRegistery;
/* helper structure to track pattern stats and assign pattern id's. */
typedef struct DetectPatternTracker {
const struct DetectContentData_ *cd;
int sm_list;
uint32_t cnt;
uint32_t mpm;
} DetectPatternTracker;
typedef struct DetectReplaceList_ {
struct DetectContentData_ *cd;
uint8_t *found;

Loading…
Cancel
Save