diff --git a/src/detect-engine-mpm.c b/src/detect-engine-mpm.c index 93aeb78e7c..d907095943 100644 --- a/src/detect-engine-mpm.c +++ b/src/detect-engine-mpm.c @@ -361,8 +361,10 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) { if (sh->flags & SIG_GROUP_HAVECONTENT && sh->mpm_ctx != NULL && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) { SCLogDebug("destroying mpm_ctx %p (sh %p)", sh->mpm_ctx, sh); - mpm_table[sh->mpm_ctx->mpm_type].DestroyCtx(sh->mpm_ctx); - SCFree(sh->mpm_ctx); + if (!MpmFactoryIsMpmCtxAvailable(sh->mpm_ctx)) { + mpm_table[sh->mpm_ctx->mpm_type].DestroyCtx(sh->mpm_ctx); + SCFree(sh->mpm_ctx); + } /* ready for reuse */ sh->mpm_ctx = NULL; @@ -373,8 +375,10 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) { if (sh->flags & SIG_GROUP_HAVEURICONTENT && sh->mpm_uri_ctx != NULL && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) { SCLogDebug("destroying mpm_uri_ctx %p (sh %p)", sh->mpm_uri_ctx, sh); - mpm_table[sh->mpm_uri_ctx->mpm_type].DestroyCtx(sh->mpm_uri_ctx); - SCFree(sh->mpm_uri_ctx); + if (!MpmFactoryIsMpmCtxAvailable(sh->mpm_uri_ctx)) { + mpm_table[sh->mpm_uri_ctx->mpm_type].DestroyCtx(sh->mpm_uri_ctx); + SCFree(sh->mpm_uri_ctx); + } /* ready for reuse */ sh->mpm_uri_ctx = NULL; @@ -386,8 +390,10 @@ void PatternMatchDestroyGroup(SigGroupHead *sh) { if (sh->mpm_stream_ctx != NULL) { if (!(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) { SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx, sh); - mpm_table[sh->mpm_stream_ctx->mpm_type].DestroyCtx(sh->mpm_stream_ctx); - SCFree(sh->mpm_stream_ctx); + if (!MpmFactoryIsMpmCtxAvailable(sh->mpm_stream_ctx)) { + mpm_table[sh->mpm_stream_ctx->mpm_type].DestroyCtx(sh->mpm_stream_ctx); + SCFree(sh->mpm_stream_ctx); + } /* ready for reuse */ sh->mpm_stream_ctx = NULL; @@ -1344,12 +1350,12 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) /* intialize contexes */ if (sh->flags & SIG_GROUP_HAVECONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) { - /* search */ - sh->mpm_ctx = SCMalloc(sizeof(MpmCtx)); - if (sh->mpm_ctx == NULL) - goto error; + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_packet); + } else { + sh->mpm_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } - memset(sh->mpm_ctx, 0x00, sizeof(MpmCtx)); #ifndef __SC_CUDA_SUPPORT__ MpmInitCtx(sh->mpm_ctx, de_ctx->mpm_matcher, -1); #else @@ -1358,11 +1364,12 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } if (sh->flags & SIG_GROUP_HAVESTREAMCONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) { - sh->mpm_stream_ctx = SCMalloc(sizeof(MpmCtx)); - if (sh->mpm_stream_ctx == NULL) - goto error; + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_stream_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_stream); + } else { + sh->mpm_stream_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } - memset(sh->mpm_stream_ctx, 0x00, sizeof(MpmCtx)); #ifndef __SC_CUDA_SUPPORT__ MpmInitCtx(sh->mpm_stream_ctx, de_ctx->mpm_matcher, -1); #else @@ -1371,11 +1378,12 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) } if (sh->flags & SIG_GROUP_HAVEURICONTENT && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) { - sh->mpm_uri_ctx = SCMalloc(sizeof(MpmCtx)); - if (sh->mpm_uri_ctx == NULL) - goto error; + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + sh->mpm_uri_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_uri); + } else { + sh->mpm_uri_ctx = MpmFactoryGetMpmCtxForProfile(MPM_CTX_FACTORY_UNIQUE_CONTEXT); + } - memset(sh->mpm_uri_ctx, 0x00, sizeof(MpmCtx)); #ifndef __SC_CUDA_SUPPORT__ MpmInitCtx(sh->mpm_uri_ctx, de_ctx->mpm_matcher, -1); #else @@ -1517,7 +1525,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) PatternMatchPreprarePopulateMpmUri(de_ctx, sh); if (mpm_table[sh->mpm_uri_ctx->mpm_type].Prepare != NULL) { - mpm_table[sh->mpm_uri_ctx->mpm_type].Prepare(sh->mpm_uri_ctx); + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) { + mpm_table[sh->mpm_uri_ctx->mpm_type].Prepare(sh->mpm_uri_ctx); + } } //sh->mpm_uri_ctx->PrintCtx(sh->mpm_uri_ctx); @@ -1529,7 +1539,9 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) PatternMatchPreprarePopulateMpm(de_ctx, sh); if (mpm_table[sh->mpm_ctx->mpm_type].Prepare != NULL) { - mpm_table[sh->mpm_ctx->mpm_type].Prepare(sh->mpm_ctx); + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) { + mpm_table[sh->mpm_ctx->mpm_type].Prepare(sh->mpm_ctx); + } } } @@ -1538,14 +1550,16 @@ int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh) PatternMatchPreprarePopulateMpmStream(de_ctx, sh); SCLogDebug("preparing mpm_stream_ctx %p", sh->mpm_stream_ctx); if (mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare != NULL) { - mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare(sh->mpm_stream_ctx); + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) { + mpm_table[sh->mpm_stream_ctx->mpm_type].Prepare(sh->mpm_stream_ctx); + } } } return 0; -error: + //error: /* XXX */ - return -1; + //return -1; } /** \brief Pattern ID Hash for sharing pattern id's diff --git a/src/detect-engine.c b/src/detect-engine.c index c7fda04177..a0ea8b8ba9 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -178,21 +178,20 @@ static uint8_t DetectEngineCtxLoadConf(DetectEngineCtx *de_ctx) { if (sgh_mpm_context != NULL) { if (strcmp(sgh_mpm_context, "single") == 0) { - de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_CONTEXT_SINGLE; + de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE; } else if (strcmp(sgh_mpm_context, "full") == 0) { - de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_CONTEXT_FULL; + de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL; } else if (strcmp(sgh_mpm_context, "auto") == 0) { - de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_CONTEXT_AUTO; + de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_AUTO; } else { SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "You have supplied an " "invalid conf value for detect-engine.sgh-mpm-context-" "%s", sgh_mpm_context); } } else { - SCLogWarning(SC_ERR_INVALID_YAML_CONF_ENTRY, "You have supplied a " - "value for detect-engine.sgh-mpm-context. Using " - "default value of full\n"); - de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_CONTEXT_FULL; + SCLogInfo("You have not supplied a value for " + "detect-engine.sgh-mpm-context. Using default value of full"); + de_ctx->sgh_mpm_context = ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL; } diff --git a/src/detect.c b/src/detect.c index f07fc7ba7c..535959c833 100644 --- a/src/detect.c +++ b/src/detect.c @@ -1658,6 +1658,23 @@ static int SignatureCreateMask(Signature *s) { SCReturnInt(0); } +static void SigInitStandardMpmFactoryContexts(DetectEngineCtx *de_ctx) +{ + de_ctx->sgh_mpm_context_packet = + MpmFactoryRegisterMpmCtxProfile("packet", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_uri = + MpmFactoryRegisterMpmCtxProfile("uri", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_stream = + MpmFactoryRegisterMpmCtxProfile("stream", + MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD); + de_ctx->sgh_mpm_context_app_proto_detect = + MpmFactoryRegisterMpmCtxProfile("app_proto_detect", 0); + + return; +} + /** * \brief Add all signatures to their own source address group * @@ -3511,6 +3528,12 @@ int SigAddressPrepareStage5(DetectEngineCtx *de_ctx) { * \retval 0 Always */ int SigGroupBuild (DetectEngineCtx *de_ctx) { + /* if we are using single sgh_mpm_context then let us init the standard mpm + * contexts using the mpm_ctx factory */ + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + SigInitStandardMpmFactoryContexts(de_ctx); + } + if (SigAddressPrepareStage1(de_ctx) != 0) { SCLogError(SC_ERR_DETECT_PREPARE, "initializing the detection engine failed"); exit(EXIT_FAILURE); @@ -3580,6 +3603,24 @@ int SigGroupBuild (DetectEngineCtx *de_ctx) { } #endif + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + MpmCtx *mpm_ctx = NULL; + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_packet); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_uri); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + + mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx->sgh_mpm_context_stream); + if (mpm_table[de_ctx->mpm_matcher].Prepare != NULL) { + mpm_table[de_ctx->mpm_matcher].Prepare(mpm_ctx); + } + } + // SigAddressPrepareStage5(de_ctx); // DetectAddressPrintMemory(); // DetectSigGroupPrintMemory(); diff --git a/src/detect.h b/src/detect.h index dc87a080c7..77ac7e9287 100644 --- a/src/detect.h +++ b/src/detect.h @@ -568,6 +568,7 @@ typedef struct DetectEngineCtx_ { uint16_t max_uniq_small_toserver_dp_groups; */ + /* specify the configuration for mpm context factory */ uint8_t sgh_mpm_context; /** hash table for looking up patterns for @@ -580,6 +581,11 @@ typedef struct DetectEngineCtx_ { uint32_t sgh_array_cnt; uint32_t sgh_array_size; + int32_t sgh_mpm_context_packet; + int32_t sgh_mpm_context_stream; + int32_t sgh_mpm_context_uri; + int32_t sgh_mpm_context_app_proto_detect; + /** sgh for signatures that match against invalid packets. In those cases * we can't lookup by proto, address, port as we don't have these */ struct SigGroupHead_ *decoder_event_sgh; @@ -597,9 +603,9 @@ enum { /* Siggroup mpm context profile */ enum { - ENGINE_SGH_MPM_CONTEXT_FULL, - ENGINE_SGH_MPM_CONTEXT_SINGLE, - ENGINE_SGH_MPM_CONTEXT_AUTO + ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL, + ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE, + ENGINE_SGH_MPM_FACTORY_CONTEXT_AUTO }; /** diff --git a/src/suricata.c b/src/suricata.c index 8f793d85e7..8e8e486009 100644 --- a/src/suricata.c +++ b/src/suricata.c @@ -1261,6 +1261,9 @@ int main(int argc, char **argv) #endif SigCleanSignatures(de_ctx); + if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) { + MpmFactoryDeRegisterAllMpmCtxProfiles(); + } DetectEngineCtxFree(de_ctx); AlpProtoDestroy(); diff --git a/src/util-mpm-ac.c b/src/util-mpm-ac.c index 274096f125..1078771abf 100644 --- a/src/util-mpm-ac.c +++ b/src/util-mpm-ac.c @@ -366,11 +366,11 @@ static int SCACAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen, /* put in the pattern hash */ SCACInitHashAdd(ctx, p); - if (mpm_ctx->pattern_cnt == 65535) { - SCLogError(SC_ERR_AHO_CORASICK, "Max search words reached. Can't " - "insert anymore. Exiting"); - exit(EXIT_FAILURE); - } + //if (mpm_ctx->pattern_cnt == 65535) { + // SCLogError(SC_ERR_AHO_CORASICK, "Max search words reached. Can't " + // "insert anymore. Exiting"); + // exit(EXIT_FAILURE); + //} mpm_ctx->pattern_cnt++; if (mpm_ctx->maxlen < patlen) @@ -810,6 +810,26 @@ static inline void SCACCreateDeltaTable(MpmCtx *mpm_ctx) return; } +static inline void SCACClubOutputStatePresenceWithDeltaTable(MpmCtx *mpm_ctx) +{ + SCACCtx *ctx = (SCACCtx *)mpm_ctx->ctx; + int ascii_code = 0; + uint32_t state = 0; + uint32_t temp_state = 0; + + if (ctx->state_count > 65535) { + for (state = 0; state < ctx->state_count; state++) { + for (ascii_code = 0; ascii_code < 256; ascii_code++) { + temp_state = ctx->state_table_u32[state & 0x00FFFFFF][ascii_code]; + if (ctx->output_table[temp_state & 0x00FFFFFF].no_of_entries != 0) + ctx->state_table_u32[state & 0x00FFFFFF][ascii_code] |= (1 << 24); + } + } + } /* if (state->count > 65535) */ + + return; +} + #if 0 static void SCACPrintDeltaTable(MpmCtx *mpm_ctx) { @@ -848,6 +868,8 @@ static inline void SCACPrepareStateTable(MpmCtx *mpm_ctx) SCACCreateFailureTable(mpm_ctx); /* create the final state(delta) table */ SCACCreateDeltaTable(mpm_ctx); + /* club the output state presence with delta transition entries */ + SCACClubOutputStatePresenceWithDeltaTable(mpm_ctx); #if 0 SCACPrintDeltaTable(mpm_ctx); @@ -956,6 +978,9 @@ void SCACInitThreadCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, uint32_t m */ void SCACInitCtx(MpmCtx *mpm_ctx, int module_handle) { + if (mpm_ctx->ctx != NULL) + return; + mpm_ctx->ctx = SCMalloc(sizeof(SCACCtx)); if (mpm_ctx->ctx == NULL) { SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); @@ -1090,12 +1115,6 @@ uint32_t SCACSearch(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, for (k = 0; k < ctx->output_table[state].no_of_entries; k++) { matches += MpmVerifyMatch(mpm_thread_ctx, pmq, ctx->output_table[state].pids[k]); -#ifdef SC_AC_COUNTERS - if (mpm_thread_ctx->ctx != NULL) { - SCACThreadCtx *tctx = (SCACThreadCtx *)mpm_thread_ctx->ctx; - tctx->total_matches++; - } -#endif /* SC_AC_COUNTERS */ } } } /* for (i = 0; i < buflen; i++) */ @@ -1103,32 +1122,27 @@ uint32_t SCACSearch(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, /* \todo tried loop unrolling with register var, with no perf increase. Need * to dig deeper */ /* \todo Change it for stateful MPM. Supply the state using mpm_thread_ctx */ + SC_AC_STATE_TYPE_U32 (*state_table_u32)[256] = ctx->state_table_u32; register SC_AC_STATE_TYPE_U32 state = 0; for (i = 0; i < buflen; i++) { - state = ctx->state_table_u32[state][buf[i]]; - if (ctx->output_table[state].no_of_entries != 0) { - uint32_t k = 0; - for (k = 0; k < ctx->output_table[state].no_of_entries; k++) { - matches += MpmVerifyMatch(mpm_thread_ctx, pmq, - ctx->output_table[state].pids[k]); -#ifdef SC_AC_COUNTERS - if (mpm_thread_ctx->ctx != NULL) { - SCACThreadCtx *tctx = (SCACThreadCtx *)mpm_thread_ctx->ctx; - tctx->total_matches++; + state = state_table_u32[state & 0x00FFFFFF][buf[i]]; + if (state & 0xFF000000) { + uint32_t no_of_entries = ctx->output_table[state & 0x00FFFFFF].no_of_entries; + uint32_t *pids = ctx->output_table[state & 0x00FFFFFF].pids; + uint32_t k; + for (k = 0; k < no_of_entries; k++) { + if (pmq->pattern_id_bitarray[pids[k] / 8] & (1 << (pids[k] % 8))) { + ; + } else { + pmq->pattern_id_bitarray[pids[k] / 8] |= (1 << (pids[k] % 8)); + pmq->pattern_id_array[pmq->pattern_id_array_cnt++] = pids[k]; } -#endif /* SC_AC_COUNTERS */ } + matches += no_of_entries; } } /* for (i = 0; i < buflen; i++) */ } /* else - if (ctx->state_count < 65536) */ -#ifdef SC_AC_COUNTERS - if (mpm_thread_ctx->ctx != NULL) { - SCACThreadCtx *tctx = (SCACThreadCtx *)mpm_thread_ctx->ctx; - tctx->total_calls++; - } -#endif /* SC_AC_COUNTERS */ - return matches; } diff --git a/src/util-mpm-ac.h b/src/util-mpm-ac.h index 28b7b05816..ba60b832be 100644 --- a/src/util-mpm-ac.h +++ b/src/util-mpm-ac.h @@ -55,7 +55,7 @@ typedef struct SCACCtx_ { SCACPattern **parray; /* no of states used by ac */ - int32_t state_count; + uint32_t state_count; /* the all important memory hungry state_table */ SC_AC_STATE_TYPE_U16 (*state_table_u16)[256]; /* the all important memory hungry state_table */ diff --git a/src/util-mpm.c b/src/util-mpm.c index 0e51bffa02..c243b93fad 100644 --- a/src/util-mpm.c +++ b/src/util-mpm.c @@ -38,6 +38,166 @@ #include "util-mpm-ac-gfbs.h" #include "util-hashlist.h" +MpmCtxFactoryContainer *mpm_ctx_factory_container = NULL; + +/** + * \brief Register a new Mpm Context. + * + * \param name A new profile to be registered to store this MpmCtx. + * + * \retval id Return the id created for the new MpmCtx profile. + */ +int32_t MpmFactoryRegisterMpmCtxProfile(const char *name, uint8_t flags) +{ + /* the very first entry */ + if (mpm_ctx_factory_container == NULL) { + mpm_ctx_factory_container = malloc(sizeof(MpmCtxFactoryContainer)); + if (mpm_ctx_factory_container == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + memset(mpm_ctx_factory_container, 0, sizeof(MpmCtxFactoryContainer)); + + MpmCtxFactoryItem *item = malloc(sizeof(MpmCtxFactoryItem)); + if (item == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + + item[0].name = strdup(name); + if (item[0].name == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + + item[0].mpm_ctx = malloc(sizeof(MpmCtx)); + if (item[0].mpm_ctx == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + memset(item[0].mpm_ctx, 0, sizeof(MpmCtx)); + + /* our id starts from 0 always. Helps us with the ctx retrieval from + * the array */ + item[0].id = 0; + + /* store the flag */ + item[0].flags = flags; + + /* store the newly created item */ + mpm_ctx_factory_container->items = item; + mpm_ctx_factory_container->no_of_items++; + + /* the first id is always 0 */ + return item[0].id; + } else { + int i; + MpmCtxFactoryItem *items = mpm_ctx_factory_container->items; + for (i = 0; i < mpm_ctx_factory_container->no_of_items; i++) { + if (items[i].name != NULL && strcmp(items[i].name, name) == 0) { + /* looks like we have this mpm_ctx freed */ + if (items[i].mpm_ctx == NULL) { + items[i].mpm_ctx = malloc(sizeof(MpmCtx)); + if (items[i].mpm_ctx == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + memset(items[i].mpm_ctx, 0, sizeof(MpmCtx)); + } + items[i].flags = flags; + return items[i].id; + } + } + + /* let's make the new entry */ + if ((items = realloc(items, (mpm_ctx_factory_container->no_of_items + 1) * + sizeof(MpmCtxFactoryItem))) == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + + MpmCtxFactoryItem *new_item = &items[mpm_ctx_factory_container->no_of_items]; + new_item[0].name = strdup(name); + if (new_item[0].name == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + + new_item[0].mpm_ctx = malloc(sizeof(MpmCtx)); + if (new_item[0].mpm_ctx == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + memset(new_item[0].mpm_ctx, 0, sizeof(MpmCtx)); + + new_item[0].id = mpm_ctx_factory_container->no_of_items; + new_item[0].flags = flags; + mpm_ctx_factory_container->no_of_items++; + + /* the newly created id */ + return new_item[0].id; + } +} + +int32_t MpmFactoryIsMpmCtxAvailable(MpmCtx *mpm_ctx) +{ + if (mpm_ctx == NULL) + return 0; + + if (mpm_ctx_factory_container == NULL) { + return 0; + } else { + int i; + for (i = 0; i < mpm_ctx_factory_container->no_of_items; i++) { + if (mpm_ctx == mpm_ctx_factory_container->items[i].mpm_ctx) + return 1; + } + return 0; + } +} + +MpmCtx *MpmFactoryGetMpmCtxForProfile(int32_t id) +{ + if (id == MPM_CTX_FACTORY_UNIQUE_CONTEXT) { + MpmCtx *mpm_ctx = malloc(sizeof(MpmCtx)); + if (mpm_ctx == NULL) { + SCLogError(SC_ERR_MEM_ALLOC, "Error allocating memory"); + exit(EXIT_FAILURE); + } + memset(mpm_ctx, 0, sizeof(MpmCtx)); + return mpm_ctx; + } else if (id < -1) { + SCLogError(SC_ERR_INVALID_ARGUMENTS, "Invalid argument - %d\n", id); + return NULL; + } else if (id >= mpm_ctx_factory_container->no_of_items) { + /* this id does not exist */ + return NULL; + } else { + return mpm_ctx_factory_container->items[id].mpm_ctx; + } +} + +void MpmFactoryDeRegisterAllMpmCtxProfiles(void) +{ + if (mpm_ctx_factory_container == NULL) + return; + + int i = 0; + MpmCtxFactoryItem *items = mpm_ctx_factory_container->items; + for (i = 0; i < mpm_ctx_factory_container->no_of_items; i++) { + if (items[i].name != NULL) + free(items[i].name); + if (items[i].mpm_ctx != NULL) + free(items[i].mpm_ctx); + } + + free(mpm_ctx_factory_container->items); + free(mpm_ctx_factory_container); + mpm_ctx_factory_container = NULL; + + return; +} + /** * \brief Setup a pmq * diff --git a/src/util-mpm.h b/src/util-mpm.h index 87028f6ae6..4ef97c21be 100644 --- a/src/util-mpm.h +++ b/src/util-mpm.h @@ -102,7 +102,7 @@ typedef struct MpmCtx_ { void *ctx; uint16_t mpm_type; - uint16_t pattern_cnt; /* unique patterns */ + uint32_t pattern_cnt; /* unique patterns */ uint16_t minlen; uint16_t maxlen; @@ -111,6 +111,24 @@ typedef struct MpmCtx_ { uint32_t memory_size; } MpmCtx; +/* if we want to retrieve an unique mpm context from the mpm context factory + * we should supply this as the key */ +#define MPM_CTX_FACTORY_UNIQUE_CONTEXT -1 + +#define MPM_CTX_FACTORY_FLAGS_PREPARE_WITH_SIG_GROUP_BUILD 0x01 + +typedef struct MpmCtxFactoryItem_ { + char *name; + MpmCtx *mpm_ctx; + int32_t id; + uint8_t flags; +} MpmCtxFactoryItem; + +typedef struct MpmCtxFactoryContainer_ { + MpmCtxFactoryItem *items; + int32_t no_of_items; +} MpmCtxFactoryContainer; + /** pattern is case insensitive */ #define MPM_PATTERN_FLAG_NOCASE 0x01 /** pattern is negated */ @@ -154,6 +172,11 @@ typedef struct MpmTableElmt_ { MpmTableElmt mpm_table[MPM_TABLE_SIZE]; +int32_t MpmFactoryRegisterMpmCtxProfile(const char *, uint8_t flags); +MpmCtx *MpmFactoryGetMpmCtxForProfile(int32_t); +void MpmFactoryDeRegisterAllMpmCtxProfiles(void); +int32_t MpmFactoryIsMpmCtxAvailable(MpmCtx *); + int PmqSetup(PatternMatcherQueue *, uint32_t, uint32_t); void PmqMerge(PatternMatcherQueue *src, PatternMatcherQueue *dst); void PmqReset(PatternMatcherQueue *);