]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect: mpm deduplication
authorVictor Julien <victor@inliniac.net>
Mon, 5 Oct 2015 08:25:03 +0000 (10:25 +0200)
committerVictor Julien <victor@inliniac.net>
Mon, 4 Apr 2016 16:14:56 +0000 (18:14 +0200)
Create hash for mpm's that we can reuse. Have packet/stream mpms
use this.

src/detect-engine-mpm.c
src/detect-engine-mpm.h
src/detect-engine-siggroup.c
src/detect-engine.c
src/detect.c
src/detect.h

index d678e9aa9f5bad25d6af926f3a7e5ca1e0c5b453..4c37958e057385370524f21cda1af3c24cba36f5 100644 (file)
 #endif
 #include "util-validate.h"
 
-/** \todo make it possible to use multiple pattern matcher algorithms next to
-          each other. */
+const char *builtin_mpms[] = {
+    "toserver TCP packet",
+    "toclient TCP packet",
+    "toserver TCP stream",
+    "toclient TCP stream",
+    "toserver UDP packet",
+    "toclient UDP packet",
+    "other IP packet",
+
+    NULL };
+
 
 #define POPULATE_MPM_AVOID_PACKET_MPM_PATTERNS 0x01
 #define POPULATE_MPM_AVOID_STREAM_MPM_PATTERNS 0x02
@@ -1104,8 +1113,8 @@ uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
 }
 
 static void PopulateMpmHelperAddPatternToPktCtx(MpmCtx *mpm_ctx,
-                                                DetectContentData *cd,
-                                                Signature *s, uint8_t flags,
+                                                const DetectContentData *cd,
+                                                const Signature *s, uint8_t flags,
                                                 int chop)
 {
     uint16_t pat_offset = cd->offset;
@@ -1153,135 +1162,6 @@ static void PopulateMpmHelperAddPatternToPktCtx(MpmCtx *mpm_ctx,
 #define SGH_DIRECTION_TS(sgh) ((sgh)->init->direction & SIG_FLAG_TOSERVER)
 #define SGH_DIRECTION_TC(sgh) ((sgh)->init->direction & SIG_FLAG_TOCLIENT)
 
-/* TODO the sig updates don't belong here */
-static void PopulateMpmAddPatternToMpmPMATCH(const DetectEngineCtx *de_ctx,
-                                       SigGroupHead *sgh, Signature *s,
-                                       SigMatch *mpm_sm)
-{
-    DetectContentData *cd = (DetectContentData *)mpm_sm->ctx;
-
-    if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
-        if (DETECT_CONTENT_IS_SINGLE(cd) &&
-                !(cd->flags & DETECT_CONTENT_NEGATED) &&
-                !(cd->flags & DETECT_CONTENT_REPLACE) &&
-                cd->content_len == cd->fp_chop_len)
-        {
-            cd->flags |= DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED;
-        }
-    } else {
-        if (DETECT_CONTENT_IS_SINGLE(cd) &&
-                !(cd->flags & DETECT_CONTENT_NEGATED) &&
-                !(cd->flags & DETECT_CONTENT_REPLACE))
-        {
-            cd->flags |= DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED;
-        }
-    }
-
-    /* add the content to the "packet" mpm:
-     * chop is handled in PopulateMpmHelperAddPatternToPktCtx
-     */
-    if (SignatureHasPacketContent(s)) {
-        /* per TCP packet mpm */
-        if (SGH_PROTO(sgh, IPPROTO_TCP) && (s->proto.proto[IPPROTO_TCP / 8] & 1 << (IPPROTO_TCP % 8))) {
-            if (SGH_DIRECTION_TS(sgh) && s->flags & SIG_FLAG_TOSERVER) {
-                PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_ts,
-                        cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
-            }
-            if (SGH_DIRECTION_TC(sgh) && s->flags & SIG_FLAG_TOCLIENT) {
-                PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_tc,
-                        cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
-            }
-        }
-    }
-    /* per UDP packet mpm */
-    if (SGH_PROTO(sgh, IPPROTO_UDP) && (s->proto.proto[IPPROTO_UDP / 8] & 1 << (IPPROTO_UDP % 8))) {
-        if (SGH_DIRECTION_TS(sgh) && s->flags & SIG_FLAG_TOSERVER) {
-            PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_ts,
-                    cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
-        }
-        if (SGH_DIRECTION_TC(sgh) && s->flags & SIG_FLAG_TOCLIENT) {
-            PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_tc,
-                    cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
-        }
-    }
-
-    /* other IP protocols */
-    if (!(SGH_PROTO(sgh, IPPROTO_TCP) || SGH_PROTO(sgh, IPPROTO_UDP))) {
-        PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_other_ctx,
-                cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
-    }
-
-    /* tell matcher we are inspecting packet */
-    s->flags |= SIG_FLAG_MPM_PACKET;
-    s->mpm_pattern_id_div_8 = cd->id / 8;
-    s->mpm_pattern_id_mod_8 = 1 << (cd->id % 8);
-    if (cd->flags & DETECT_CONTENT_NEGATED) {
-        SCLogDebug("flagging sig %"PRIu32" to be looking for negated mpm", s->id);
-        s->flags |= SIG_FLAG_MPM_PACKET_NEG;
-    }
-    sgh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
-
-    /* for TCP, we have a special "stream" mpm as well */
-    if (SGH_PROTO(sgh, IPPROTO_TCP) && SignatureHasStreamContent(s)) {
-        if (cd->flags & DETECT_CONTENT_NOCASE) {
-            if (SGH_DIRECTION_TS(sgh) && s->flags & SIG_FLAG_TOSERVER) {
-                if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
-                    MpmAddPatternCI(sgh->mpm_stream_ctx_ts,
-                            cd->content + cd->fp_chop_offset, cd->fp_chop_len,
-                            0, 0, cd->id, s->num, 0);
-                } else {
-                    MpmAddPatternCI(sgh->mpm_stream_ctx_ts,
-                            cd->content, cd->content_len,
-                            0, 0, cd->id, s->num, 0);
-                }
-            }
-            if (SGH_DIRECTION_TC(sgh) && s->flags & SIG_FLAG_TOCLIENT) {
-                if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
-                    MpmAddPatternCI(sgh->mpm_stream_ctx_tc,
-                            cd->content + cd->fp_chop_offset, cd->fp_chop_len,
-                            0, 0, cd->id, s->num, 0);
-                } else {
-                    MpmAddPatternCI(sgh->mpm_stream_ctx_tc,
-                            cd->content, cd->content_len,
-                            0, 0, cd->id, s->num, 0);
-                }
-            }
-        } else {
-            if (SGH_DIRECTION_TS(sgh) && s->flags & SIG_FLAG_TOSERVER) {
-                if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
-                    MpmAddPatternCS(sgh->mpm_stream_ctx_ts,
-                            cd->content + cd->fp_chop_offset, cd->fp_chop_len,
-                            0, 0, cd->id, s->num, 0);
-                } else {
-                    MpmAddPatternCS(sgh->mpm_stream_ctx_ts,
-                            cd->content, cd->content_len,
-                            0, 0, cd->id, s->num, 0);
-                }
-            }
-            if (SGH_DIRECTION_TC(sgh) && s->flags & SIG_FLAG_TOCLIENT) {
-                if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
-                    MpmAddPatternCS(sgh->mpm_stream_ctx_tc,
-                            cd->content + cd->fp_chop_offset, cd->fp_chop_len,
-                            0, 0, cd->id, s->num, 0);
-                } else {
-                    MpmAddPatternCS(sgh->mpm_stream_ctx_tc,
-                            cd->content, cd->content_len,
-                            0, 0, cd->id, s->num, 0);
-                }
-            }
-        }
-        /* tell matcher we are inspecting stream */
-        s->flags |= SIG_FLAG_MPM_STREAM;
-        s->mpm_pattern_id_div_8 = cd->id / 8;
-        s->mpm_pattern_id_mod_8 = 1 << (cd->id % 8);
-        if (cd->flags & DETECT_CONTENT_NEGATED) {
-            SCLogDebug("flagging sig %"PRIu32" to be looking for negated mpm", s->id);
-            s->flags |= SIG_FLAG_MPM_STREAM_NEG;
-        }
-        sgh->flags |= SIG_GROUP_HEAD_MPM_STREAM;
-    }
-}
-
 static void PopulateMpmAddPatternToMpm(const DetectEngineCtx *de_ctx,
                                        SigGroupHead *sgh, Signature *s,
                                        SigMatch *mpm_sm)
@@ -1304,7 +1184,7 @@ static void PopulateMpmAddPatternToMpm(const DetectEngineCtx *de_ctx,
     switch (sm_list) {
         case DETECT_SM_LIST_PMATCH:
         {
-            PopulateMpmAddPatternToMpmPMATCH(de_ctx, sgh, s, mpm_sm);
+            BUG_ON(1);
             break;
         } /* case DETECT_CONTENT */
 
@@ -1666,23 +1546,481 @@ static int PatternMatchPreparePopulateMpm(const DetectEngineCtx *de_ctx,
         Signature *s = sgh->match_array[sig];
         if (s == NULL)
             continue;
+        if (s->mpm_sm == NULL)
+            continue;
+        int list = SigMatchListSMBelongsTo(s, s->mpm_sm);
+        if (list < 0)
+            continue;
+        if (list == DETECT_SM_LIST_PMATCH)
+            continue;
         PopulateMpmAddPatternToMpm(de_ctx, sgh, s, s->mpm_sm);
     } /* for (sig = 0; sig < sgh->sig_cnt; sig++) */
 
     return 0;
 }
 
+/** \internal
+ *  \brief The hash function for MpmStore
+ *
+ *  \param ht      Pointer to the hash table.
+ *  \param data    Pointer to the MpmStore.
+ *  \param datalen Not used in our case.
+ *
+ *  \retval hash The generated hash value.
+ */
+static uint32_t MpmStoreHashFunc(HashListTable *ht, void *data, uint16_t datalen)
+{
+    const MpmStore *ms = (MpmStore *)data;
+    uint32_t hash = 0;
+    uint32_t b = 0;
+
+    for (b = 0; b < ms->sid_array_size; b++)
+        hash += ms->sid_array[b];
+
+    return hash % ht->array_size;
+}
+
+/**
+ * \brief The Compare function for MpmStore
+ *
+ * \param data1 Pointer to the first MpmStore.
+ * \param len1  Not used.
+ * \param data2 Pointer to the second MpmStore.
+ * \param len2  Not used.
+ *
+ * \retval 1 If the 2 MpmStores sent as args match.
+ * \retval 0 If the 2 MpmStores sent as args do not match.
+ */
+static char MpmStoreCompareFunc(void *data1, uint16_t len1, void *data2,
+                                uint16_t len2)
+{
+    const MpmStore *ms1 = (MpmStore *)data1;
+    const MpmStore *ms2 = (MpmStore *)data2;
+
+    if (ms1->sid_array_size != ms2->sid_array_size)
+        return 0;
+
+    if (ms1->buffer != ms2->buffer)
+        return 0;
+
+    if (ms1->direction != ms2->direction)
+        return 0;
+
+    if (SCMemcmp(ms1->sid_array, ms2->sid_array,
+                 ms1->sid_array_size) != 0)
+    {
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * \brief Initializes the MpmStore 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.
+ */
+int MpmStoreInit(DetectEngineCtx *de_ctx)
+{
+    de_ctx->mpm_hash_table = HashListTableInit(4096,
+                                               MpmStoreHashFunc,
+                                               MpmStoreCompareFunc,
+                                               NULL);
+    if (de_ctx->mpm_hash_table == NULL)
+        goto error;
+
+    return 0;
+
+error:
+    return -1;
+}
+
+/**
+ * \brief Adds a MpmStore to the detection engine context MpmStore
+ *
+ * \param de_ctx Pointer to the detection engine context.
+ * \param sgh    Pointer to the MpmStore.
+ *
+ * \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
+ */
+static int MpmStoreAdd(DetectEngineCtx *de_ctx, MpmStore *s)
+{
+    int ret = HashListTableAdd(de_ctx->mpm_hash_table, (void *)s, 0);
+    return ret;
+}
+
+/**
+ * \brief Used to lookup a MpmStore from the MpmStore
+ *
+ * \param de_ctx Pointer to the detection engine context.
+ * \param sgh    Pointer to the MpmStore.
+ *
+ * \retval rsgh On success a pointer to the MpmStore if the MpmStore is
+ *              found in the hash table; NULL on failure.
+ */
+static MpmStore *MpmStoreLookup(DetectEngineCtx *de_ctx, MpmStore *s)
+{
+    MpmStore *rs = HashListTableLookup(de_ctx->mpm_hash_table,
+                                             (void *)s, 0);
+    return rs;
+}
+
+void MpmStoreReportStats(const DetectEngineCtx *de_ctx)
+{
+    HashListTableBucket *htb = NULL;
+
+    uint32_t stats[MPMB_MAX] = {0};
+
+    for (htb = HashListTableGetListHead(de_ctx->mpm_hash_table);
+            htb != NULL;
+            htb = HashListTableGetListNext(htb))
+    {
+        const MpmStore *ms = (MpmStore *)HashListTableGetListData(htb);
+        if (ms == NULL) {
+            continue;
+        }
+        stats[ms->buffer]++;
+    }
+
+    uint32_t x;
+    for (x = 0; x < MPMB_MAX; x++) {
+        SCLogInfo("Builtin MPM \"%s\": %u", builtin_mpms[x], stats[x]);
+    }
+}
+
+/**
+ * \brief Frees the hash table - DetectEngineCtx->mpm_hash_table, allocated by
+ *        MpmStoreInit() function.
+ *
+ * \param de_ctx Pointer to the detection engine context.
+ */
+void MpmStoreFree(DetectEngineCtx *de_ctx)
+{
+    if (de_ctx->mpm_hash_table == NULL)
+        return;
+
+    HashListTableFree(de_ctx->mpm_hash_table);
+    de_ctx->mpm_hash_table = NULL;
+    return;
+}
+
+void MpmStoreSetup(const DetectEngineCtx *de_ctx, MpmStore *ms)
+{
+    Signature *s = NULL; // TODO const
+    uint32_t sig;
+
+    int32_t sgh_mpm_context = 0;
+    switch (ms->buffer) {
+        case MPMB_TCP_PKT_TS:
+        case MPMB_TCP_PKT_TC:
+            sgh_mpm_context = de_ctx->sgh_mpm_context_proto_tcp_packet;
+            break;
+        case MPMB_TCP_STREAM_TS:
+        case MPMB_TCP_STREAM_TC:
+            sgh_mpm_context = de_ctx->sgh_mpm_context_stream;
+            break;
+        case MPMB_UDP_TS:
+        case MPMB_UDP_TC:
+            sgh_mpm_context = de_ctx->sgh_mpm_context_proto_udp_packet;
+            break;
+        case MPMB_OTHERIP:
+            sgh_mpm_context = de_ctx->sgh_mpm_context_proto_other_packet;
+            break;
+        default:
+            break;
+    }
+
+    int dir = 0;
+    switch (ms->buffer) {
+        /* TS is 1 */
+        case MPMB_TCP_PKT_TS:
+        case MPMB_TCP_STREAM_TS:
+        case MPMB_UDP_TS:
+            dir = 1;
+            break;
+
+        /* TC is 0 */
+        default:
+        case MPMB_UDP_TC:
+        case MPMB_TCP_STREAM_TC:
+        case MPMB_TCP_PKT_TC:
+        case MPMB_OTHERIP:          /**< use 0 for other */
+            dir = 0;
+            break;
+    }
+
+    if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+        ms->mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx, sgh_mpm_context, dir);
+    } else {
+        ms->mpm_ctx = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, dir);
+    }
+    MpmInitCtx(ms->mpm_ctx, de_ctx->mpm_matcher);
+
+    /* add the patterns */
+    for (sig = 0; sig < (ms->sid_array_size * 8); sig++) {
+        if (ms->sid_array[sig / 8] & (1 << (sig % 8))) {
+            s = de_ctx->sig_array[sig];
+            if (s == NULL)
+                continue;
+            if (s->mpm_sm == NULL)
+                continue;
+            int list = SigMatchListSMBelongsTo(s, s->mpm_sm);
+            if (list < 0)
+                continue;
+            if (list != DETECT_SM_LIST_PMATCH)
+                continue;
+
+            SCLogDebug("adding %u", s->id);
+
+            DetectContentData *cd = (DetectContentData *)s->mpm_sm->ctx; // TODO const
+            /* TODO move this into cd setup code */
+            if (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP) {
+                if (DETECT_CONTENT_IS_SINGLE(cd) &&
+                        !(cd->flags & DETECT_CONTENT_NEGATED) &&
+                        !(cd->flags & DETECT_CONTENT_REPLACE) &&
+                        cd->content_len == cd->fp_chop_len)
+                {
+                    cd->flags |= DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED;
+                }
+            } else {
+                if (DETECT_CONTENT_IS_SINGLE(cd) &&
+                        !(cd->flags & DETECT_CONTENT_NEGATED) &&
+                        !(cd->flags & DETECT_CONTENT_REPLACE))
+                {
+                    cd->flags |= DETECT_CONTENT_NO_DOUBLE_INSPECTION_REQUIRED;
+                }
+            }
+            PopulateMpmHelperAddPatternToPktCtx(ms->mpm_ctx,
+                    cd, s, 0, (cd->flags & DETECT_CONTENT_FAST_PATTERN_CHOP));
+
+            /* tell matcher we are inspecting packet */
+/* TODO remove! */
+            if (!(ms->buffer == MPMB_TCP_STREAM_TC || ms->buffer == MPMB_TCP_STREAM_TS)) {
+                s->flags |= SIG_FLAG_MPM_PACKET;
+                s->mpm_pattern_id_div_8 = cd->id / 8;
+                s->mpm_pattern_id_mod_8 = 1 << (cd->id % 8);
+                if (cd->flags & DETECT_CONTENT_NEGATED) {
+                    SCLogDebug("flagging sig %"PRIu32" to be looking for negated mpm", s->id);
+                    s->flags |= SIG_FLAG_MPM_PACKET_NEG;
+                }
+            } else {
+                /* tell matcher we are inspecting stream */
+                s->flags |= SIG_FLAG_MPM_STREAM;
+                s->mpm_pattern_id_div_8 = cd->id / 8;
+                s->mpm_pattern_id_mod_8 = 1 << (cd->id % 8);
+                if (cd->flags & DETECT_CONTENT_NEGATED) {
+                    SCLogDebug("flagging sig %"PRIu32" to be looking for negated mpm", s->id);
+                    s->flags |= SIG_FLAG_MPM_STREAM_NEG;
+                }
+            }
+        }
+    }
+
+    if (ms->mpm_ctx != NULL) {
+        if (ms->mpm_ctx->pattern_cnt == 0) {
+            MpmFactoryReClaimMpmCtx(de_ctx, ms->mpm_ctx);
+            ms->mpm_ctx = NULL;
+        } else {
+            if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+                if (mpm_table[ms->mpm_ctx->mpm_type].Prepare != NULL) {
+                    mpm_table[ms->mpm_ctx->mpm_type].Prepare(ms->mpm_ctx);
+                }
+            }
+        }
+    }
+}
+
+
+/** \brief Get MpmStore for a built-in buffer type
+ *
+ */
+MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
+                                enum MpmBuiltinBuffers buf)
+{
+    const Signature *s = NULL;
+    uint32_t sig;
+    uint32_t cnt = 0;
+    int direction = 0;
+    uint32_t max_sid = DetectEngineGetMaxSigId(de_ctx) / 8 + 1;
+    uint8_t sids_array[max_sid];
+    memset(sids_array, 0x00, max_sid);
+
+    switch(buf) {
+        case MPMB_TCP_PKT_TS:
+        case MPMB_TCP_STREAM_TS:
+        case MPMB_UDP_TS:
+            direction = SIG_FLAG_TOSERVER;
+            break;
+
+        case MPMB_TCP_PKT_TC:
+        case MPMB_TCP_STREAM_TC:
+        case MPMB_UDP_TC:
+            direction = SIG_FLAG_TOCLIENT;
+            break;
+
+        case MPMB_OTHERIP:
+            direction = (SIG_FLAG_TOCLIENT|SIG_FLAG_TOSERVER);
+            break;
+
+        case MPMB_MAX:
+            BUG_ON(1);
+            break;
+    }
+
+    for (sig = 0; sig < sgh->sig_cnt; sig++) {
+        s = sgh->match_array[sig];
+        if (s == NULL)
+            continue;
+
+        if (s->mpm_sm == NULL)
+            continue;
+
+        int list = SigMatchListSMBelongsTo(s, s->mpm_sm);
+        if (list < 0)
+            continue;
+
+        if (list != DETECT_SM_LIST_PMATCH)
+            continue;
+
+        switch (buf) {
+            case MPMB_TCP_PKT_TS:
+            case MPMB_TCP_PKT_TC:
+                if (SignatureHasPacketContent(s) == 1)
+                {
+                    sids_array[s->num / 8] |= 1 << (s->num % 8);
+                    cnt++;
+                }
+                break;
+            case MPMB_TCP_STREAM_TS:
+            case MPMB_TCP_STREAM_TC:
+                if (SignatureHasStreamContent(s) == 1)
+                {
+                    sids_array[s->num / 8] |= 1 << (s->num % 8);
+                    cnt++;
+                }
+                break;
+            case MPMB_UDP_TS:
+            case MPMB_UDP_TC:
+                sids_array[s->num / 8] |= 1 << (s->num % 8);
+                cnt++;
+                break;
+            case MPMB_OTHERIP:
+                sids_array[s->num / 8] |= 1 << (s->num % 8);
+                cnt++;
+                break;
+            default:
+                break;
+        }
+    }
+
+    if (cnt == 0)
+        return NULL;
+
+    MpmStore lookup = { sids_array, max_sid, direction, buf, NULL};
+
+    MpmStore *result = MpmStoreLookup(de_ctx, &lookup);
+    if (result == NULL) {
+        MpmStore *copy = SCCalloc(1, sizeof(MpmStore));
+        if (copy == NULL)
+            return NULL;
+        uint8_t *sids = SCCalloc(1, max_sid);
+        if (sids == NULL) {
+            SCFree(copy);
+            return NULL;
+        }
+
+        memcpy(sids, sids_array, max_sid);
+        copy->sid_array = sids;
+        copy->sid_array_size = max_sid;
+        copy->buffer = buf;
+        copy->direction = direction;
+
+        MpmStoreSetup(de_ctx, copy);
+        MpmStoreAdd(de_ctx, copy);
+        return copy;
+    } else {
+        return result;
+    }
+}
+
 /** \brief Prepare the pattern matcher ctx in a sig group head.
  *
  *  \todo determine if a content match can set the 'single' flag
  *  \todo do error checking
  *  \todo rewrite the COPY stuff
  */
-int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
+int PatternMatchPrepareGroup(DetectEngineCtx *de_ctx, SigGroupHead *sh)
 {
+    MpmStore *mpm_store = NULL;
+    if (SGH_PROTO(sh, IPPROTO_TCP)) {
+        if (SGH_DIRECTION_TS(sh)) {
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TS);
+            if (mpm_store != NULL) {
+                sh->mpm_proto_tcp_ctx_ts = mpm_store->mpm_ctx;
+                if (sh->mpm_proto_tcp_ctx_ts)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+            }
+
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_STREAM_TS);
+            if (mpm_store != NULL) {
+                BUG_ON(mpm_store == NULL);
+                sh->mpm_stream_ctx_ts = mpm_store->mpm_ctx;
+                if (sh->mpm_stream_ctx_ts)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_STREAM;
+            }
+        }
+        if (SGH_DIRECTION_TC(sh)) {
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_PKT_TC);
+            if (mpm_store != NULL) {
+                sh->mpm_proto_tcp_ctx_tc = mpm_store->mpm_ctx;
+                if (sh->mpm_proto_tcp_ctx_tc)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+            }
+
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_TCP_STREAM_TC);
+            if (mpm_store != NULL) {
+                sh->mpm_stream_ctx_tc = mpm_store->mpm_ctx;
+                if (sh->mpm_stream_ctx_tc)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_STREAM;
+            }
+       }
+    } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
+        if (SGH_DIRECTION_TS(sh)) {
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TS);
+            if (mpm_store != NULL) {
+                BUG_ON(mpm_store == NULL);
+                sh->mpm_proto_udp_ctx_ts = mpm_store->mpm_ctx;
+
+                if (sh->mpm_proto_udp_ctx_ts != NULL)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+            }
+        }
+        if (SGH_DIRECTION_TC(sh)) {
+            mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_UDP_TC);
+            if (mpm_store != NULL) {
+                sh->mpm_proto_udp_ctx_tc = mpm_store->mpm_ctx;
+
+                if (sh->mpm_proto_udp_ctx_tc != NULL)
+                    sh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+            }
+        }
+    } else {
+        mpm_store = MpmStorePrepareBuffer(de_ctx, sh, MPMB_OTHERIP);
+        if (mpm_store != NULL) {
+            sh->mpm_proto_other_ctx = mpm_store->mpm_ctx;
+
+            if (sh->mpm_proto_other_ctx != NULL)
+                sh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+        }
+    }
+
+
+
     Signature *s = NULL;
-    uint32_t has_co_packet = 0; /**< our sgh has packet payload inspecting content */
-    uint32_t has_co_stream = 0; /**< our sgh has stream inspecting content */
     uint32_t has_co_uri = 0;    /**< our sgh has uri inspecting content */
     /* used to indicate if sgh has atleast one sig with http_client_body */
     uint32_t has_co_hcbd = 0;
@@ -1720,145 +2058,106 @@ int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
         s = sh->match_array[sig];
         if (s == NULL)
             continue;
-        if (!(SGH_PROTO(sh, IPPROTO_TCP)) ||
-            (SGH_PROTO(sh, IPPROTO_TCP) && SignatureHasPacketContent(s) == 1))
-        {
-            has_co_packet = 1;
-        }
+        if (s->mpm_sm == NULL)
+            continue;
 
-        if (SGH_PROTO(sh, IPPROTO_TCP)) {
-            if (SignatureHasStreamContent(s) == 1) {
-                has_co_stream = 1;
-            }
+        int list = SigMatchListSMBelongsTo(s, s->mpm_sm);
+        if (list < 0)
+            continue;
+        if (list == DETECT_SM_LIST_PMATCH)
+            continue;
 
-            if (s->sm_lists[DETECT_SM_LIST_UMATCH] != NULL) {
-                has_co_uri = 1;
-            }
 
-            if (s->sm_lists[DETECT_SM_LIST_HCBDMATCH] != NULL) {
-                has_co_hcbd = 1;
-            }
+        if (SGH_PROTO(sh, IPPROTO_TCP)) {
+            switch (list) {
+                case DETECT_SM_LIST_UMATCH:
+                    has_co_uri = 1;
+                    break;
+
+                case DETECT_SM_LIST_HCBDMATCH:
+                    has_co_hcbd = 1;
+                    break;
+
+                case DETECT_SM_LIST_FILEDATA:
+                    if (s->alproto == ALPROTO_SMTP)
+                        has_co_smtp = 1;
+                    else if (s->alproto == ALPROTO_HTTP)
+                        has_co_hsbd = 1;
+                    else if (s->alproto == ALPROTO_UNKNOWN) {
+                        has_co_smtp = 1;
+                        has_co_hsbd = 1;
+                    }
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_FILEDATA] != NULL) {
-                if (s->alproto == ALPROTO_SMTP)
-                    has_co_smtp = 1;
-                else if (s->alproto == ALPROTO_HTTP)
-                    has_co_hsbd = 1;
-                else if (s->alproto == ALPROTO_UNKNOWN) {
-                    has_co_smtp = 1;
-                    has_co_hsbd = 1;
-                }
-            }
+                case DETECT_SM_LIST_HHDMATCH:
+                    has_co_hhd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) {
-                has_co_hhd = 1;
-            }
+                case DETECT_SM_LIST_HRHDMATCH:
+                    has_co_hrhd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) {
-                has_co_hrhd = 1;
-            }
+                case DETECT_SM_LIST_HMDMATCH:
+                    has_co_hmd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) {
-                has_co_hmd = 1;
-            }
+                case DETECT_SM_LIST_HCDMATCH:
+                    has_co_hcd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) {
-                has_co_hcd = 1;
-            }
+                case DETECT_SM_LIST_HRUDMATCH:
+                    has_co_hrud = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HRUDMATCH] != NULL) {
-                has_co_hrud = 1;
-            }
+                case DETECT_SM_LIST_HSMDMATCH:
+                    has_co_hsmd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HSMDMATCH] != NULL) {
-                has_co_hsmd = 1;
-            }
+                case DETECT_SM_LIST_HSCDMATCH:
+                    has_co_hscd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HSCDMATCH] != NULL) {
-                has_co_hscd = 1;
-            }
+                case DETECT_SM_LIST_HUADMATCH:
+                    has_co_huad = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HUADMATCH] != NULL) {
-                has_co_huad = 1;
-            }
+                case DETECT_SM_LIST_HHHDMATCH:
+                    has_co_hhhd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL) {
-                has_co_hhhd = 1;
-            }
+                case DETECT_SM_LIST_HRHHDMATCH:
+                    has_co_hrhhd = 1;
+                    break;
 
-            if (s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) {
-                has_co_hrhhd = 1;
-            }
-        }
+                case DETECT_SM_LIST_DNSQUERYNAME_MATCH:
+                    has_co_dnsquery = 1;
+                    break;
 
-        if (SGH_PROTO(sh, IPPROTO_TCP) || SGH_PROTO(sh, IPPROTO_UDP)) {
-            if (s->sm_lists[DETECT_SM_LIST_DNSQUERYNAME_MATCH] != NULL) {
-                has_co_dnsquery = 1;
+                default:
+                    BUG_ON(1);
             }
-        }
-    }
 
-    /* intialize contexes */
-    if (has_co_packet) {
-        if (SGH_PROTO(sh, IPPROTO_TCP)) {
-            if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
-                sh->mpm_proto_tcp_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_proto_tcp_packet, 0);
-                sh->mpm_proto_tcp_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_proto_tcp_packet, 1);
-            } else {
-                sh->mpm_proto_tcp_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
-                sh->mpm_proto_tcp_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
-            }
-            if (sh->mpm_proto_tcp_ctx_ts == NULL || sh->mpm_proto_tcp_ctx_tc == NULL) {
-                SCLogDebug("sh->mpm_proto_tcp_ctx == NULL. This should never happen");
-                exit(EXIT_FAILURE);
-            }
-            MpmInitCtx(sh->mpm_proto_tcp_ctx_ts, de_ctx->mpm_matcher);
-            MpmInitCtx(sh->mpm_proto_tcp_ctx_tc, de_ctx->mpm_matcher);
-        }
-        if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
-            sh->mpm_proto_udp_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_proto_udp_packet, 0);
-            sh->mpm_proto_udp_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_proto_udp_packet, 1);
-        } else {
-            sh->mpm_proto_udp_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
-            sh->mpm_proto_udp_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
-        }
-        if (sh->mpm_proto_udp_ctx_ts == NULL || sh->mpm_proto_udp_ctx_tc == NULL) {
-            SCLogDebug("sh->mpm_proto_udp_ctx == NULL. This should never happen");
-            exit(EXIT_FAILURE);
-        }
-        MpmInitCtx(sh->mpm_proto_udp_ctx_ts, de_ctx->mpm_matcher);
-        MpmInitCtx(sh->mpm_proto_udp_ctx_tc, de_ctx->mpm_matcher);
+        /* UDP */
+        } else if (SGH_PROTO(sh, IPPROTO_UDP)) {
+            switch (list) {
+                case DETECT_SM_LIST_DNSQUERYNAME_MATCH:
+                    has_co_dnsquery = 1;
+                    break;
 
-        if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
-            sh->mpm_proto_other_ctx =
-                MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_proto_other_packet, 0);
-        } else {
-            sh->mpm_proto_other_ctx =
-                MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
-        }
-        if (sh->mpm_proto_other_ctx == NULL) {
-            SCLogDebug("sh->mpm_proto_other_ctx == NULL. This should never happen");
-            exit(EXIT_FAILURE);
-        }
-        MpmInitCtx(sh->mpm_proto_other_ctx, de_ctx->mpm_matcher);
-    } /* if (has_co_packet) */
+                default:
+                    BUG_ON(1);
+            }
 
-    if (has_co_stream) {
-        if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
-            sh->mpm_stream_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_stream, 0);
-            sh->mpm_stream_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_stream, 1);
+        /* all other protos just support PMATCH */
         } else {
-            sh->mpm_stream_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
-            sh->mpm_stream_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
-        }
-        if (sh->mpm_stream_ctx_tc == NULL || sh->mpm_stream_ctx_ts == NULL) {
-            SCLogDebug("sh->mpm_stream_ctx == NULL. This should never happen");
-            exit(EXIT_FAILURE);
+            switch (list) {
+                default:
+                    BUG_ON(1);
+            }
         }
-        MpmInitCtx(sh->mpm_stream_ctx_ts, de_ctx->mpm_matcher);
-        MpmInitCtx(sh->mpm_stream_ctx_tc, de_ctx->mpm_matcher);
     }
 
+    /* intialize contexes */
     if (has_co_uri) {
         if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
             sh->mpm_uri_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_uri, 0);
@@ -2078,9 +2377,7 @@ int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
         MpmInitCtx(sh->mpm_dnsquery_ctx_ts, de_ctx->mpm_matcher);
     }
 
-    if (has_co_packet ||
-        has_co_stream ||
-        has_co_uri ||
+    if (has_co_uri ||
         has_co_hcbd ||
         has_co_hsbd ||
         has_co_smtp ||
@@ -2099,97 +2396,6 @@ int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
         /* add the patterns of all the rules to the mpms of this sgh */
         PatternMatchPreparePopulateMpm(de_ctx, sh);
 
-        if (sh->mpm_proto_tcp_ctx_ts != NULL) {
-            if (sh->mpm_proto_tcp_ctx_ts->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_ts);
-                sh->mpm_proto_tcp_ctx_ts = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].Prepare != NULL) {
-                        mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].
-                            Prepare(sh->mpm_proto_tcp_ctx_ts);
-                    }
-                }
-            }
-        }
-        if (sh->mpm_proto_tcp_ctx_tc != NULL) {
-            if (sh->mpm_proto_tcp_ctx_tc->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_tc);
-                sh->mpm_proto_tcp_ctx_tc = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].Prepare != NULL) {
-                        mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].
-                            Prepare(sh->mpm_proto_tcp_ctx_tc);
-                    }
-                }
-            }
-        }
-
-        if (sh->mpm_proto_udp_ctx_ts != NULL) {
-            if (sh->mpm_proto_udp_ctx_ts->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_ts);
-                sh->mpm_proto_udp_ctx_ts = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].Prepare != NULL) {
-                        mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].
-                            Prepare(sh->mpm_proto_udp_ctx_ts);
-                    }
-                }
-            }
-        }
-        if (sh->mpm_proto_udp_ctx_tc != NULL) {
-            if (sh->mpm_proto_udp_ctx_tc->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_tc);
-                sh->mpm_proto_udp_ctx_tc = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].Prepare != NULL) {
-                        mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].
-                            Prepare(sh->mpm_proto_udp_ctx_tc);
-                    }
-                }
-            }
-        }
-
-        if (sh->mpm_proto_other_ctx != NULL) {
-            if (sh->mpm_proto_other_ctx->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx);
-                sh->mpm_proto_other_ctx = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_proto_other_ctx->mpm_type].Prepare != NULL) {
-                        mpm_table[sh->mpm_proto_other_ctx->mpm_type].
-                            Prepare(sh->mpm_proto_other_ctx);
-                    }
-                }
-            }
-        }
-
-        if (sh->mpm_stream_ctx_ts != NULL) {
-            if (sh->mpm_stream_ctx_ts->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_ts);
-                sh->mpm_stream_ctx_ts = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare != NULL)
-                        mpm_table[sh->mpm_stream_ctx_ts->mpm_type].Prepare(sh->mpm_stream_ctx_ts);
-                }
-            }
-        }
-        if (sh->mpm_stream_ctx_tc != NULL) {
-            if (sh->mpm_stream_ctx_tc->pattern_cnt == 0) {
-                MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_tc);
-                sh->mpm_stream_ctx_tc = NULL;
-            } else {
-                if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
-                    if (mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare != NULL)
-                        mpm_table[sh->mpm_stream_ctx_tc->mpm_type].Prepare(sh->mpm_stream_ctx_tc);
-                }
-            }
-        }
-
         if (sh->mpm_uri_ctx_ts != NULL) {
             if (sh->mpm_uri_ctx_ts->pattern_cnt == 0) {
                 MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_uri_ctx_ts);
@@ -2404,15 +2610,6 @@ int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
             }
         }
     } else {
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_other_ctx);
-        sh->mpm_proto_other_ctx = NULL;
-
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_ts);
-        sh->mpm_proto_tcp_ctx_ts = NULL;
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_ts);
-        sh->mpm_proto_udp_ctx_ts = NULL;
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_ts);
-        sh->mpm_stream_ctx_ts = NULL;
         MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_uri_ctx_ts);
         sh->mpm_uri_ctx_ts = NULL;
         MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcbd_ctx_ts);
@@ -2438,12 +2635,6 @@ int PatternMatchPrepareGroup(const DetectEngineCtx *de_ctx, SigGroupHead *sh)
         MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_smtp_filedata_ctx_ts);
         sh->mpm_smtp_filedata_ctx_ts = NULL;
 
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_tcp_ctx_tc);
-        sh->mpm_proto_tcp_ctx_tc = NULL;
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_proto_udp_ctx_tc);
-        sh->mpm_proto_udp_ctx_tc = NULL;
-        MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_stream_ctx_tc);
-        sh->mpm_stream_ctx_tc = NULL;
         MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_tc);
         sh->mpm_hhd_ctx_tc = NULL;
         MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_tc);
index b0d9f12fca6166a26be93ccb4e8acd06657c85bc..235b96da08f43ceadb42408a5ec32f6dae4755ad 100644 (file)
@@ -64,7 +64,7 @@ void PatternMatchDestroy(MpmCtx *, uint16_t);
 void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t);
 void PatternMatchThreadPrint(MpmThreadCtx *, uint16_t);
 
-int PatternMatchPrepareGroup(const DetectEngineCtx *, SigGroupHead *);
+int PatternMatchPrepareGroup(DetectEngineCtx *, SigGroupHead *);
 void DetectEngineThreadCtxInfo(ThreadVars *, DetectEngineThreadCtx *);
 void PatternMatchDestroyGroup(SigGroupHead *);
 
@@ -83,6 +83,11 @@ int SignatureHasStreamContent(const Signature *);
 
 SigMatch *RetrieveFPForSig(Signature *s);
 
+int MpmStoreInit(DetectEngineCtx *);
+void MpmStoreFree(DetectEngineCtx *);
+void MpmStoreReportStats(const DetectEngineCtx *de_ctx);
+MpmStore *MpmStorePrepareBuffer(DetectEngineCtx *de_ctx, SigGroupHead *sgh, enum MpmBuiltinBuffers buf);
+
 /**
  * \brief Figured out the FP and their respective content ids for all the
  *        sigs in the engine.
index fd2f404bd420bb07d64a615c8e6a08c2c39a0b97..9d04697cc93773a01640316a7fd893928abf0b50 100644 (file)
@@ -203,133 +203,6 @@ void SigGroupHeadFree(SigGroupHead *sgh)
     return;
 }
 
-/**
- * \brief The hash function to be the used by the mpm SigGroupHead hash table -
- *        DetectEngineCtx->sgh_mpm_hash_table.
- *
- * \param ht      Pointer to the hash table.
- * \param data    Pointer to the SigGroupHead.
- * \param datalen Not used in our case.
- *
- * \retval hash The generated hash value.
- */
-uint32_t SigGroupHeadMpmHashFunc(HashListTable *ht, void *data, uint16_t datalen)
-{
-    SigGroupHead *sgh = (SigGroupHead *)data;
-    uint32_t hash = 0;
-    uint32_t b = 0;
-
-    for (b = 0; b < sgh->init->content_size; b++)
-        hash += sgh->init->content_array[b];
-
-    return hash % ht->array_size;
-}
-
-/**
- * \brief The Compare function to be used by the mpm SigGroupHead hash table -
- *        DetectEngineCtx->sgh_mpm_hash_table.
- *
- * \param data1 Pointer to the first SigGroupHead.
- * \param len1  Not used.
- * \param data2 Pointer to the second SigGroupHead.
- * \param len2  Not used.
- *
- * \retval 1 If the 2 SigGroupHeads sent as args match.
- * \retval 0 If the 2 SigGroupHeads sent as args do not match.
- */
-char SigGroupHeadMpmCompareFunc(void *data1, uint16_t len1, void *data2,
-                                uint16_t len2)
-{
-    SigGroupHead *sgh1 = (SigGroupHead *)data1;
-    SigGroupHead *sgh2 = (SigGroupHead *)data2;
-
-    if (sgh1->init->content_size != sgh2->init->content_size)
-        return 0;
-
-    if (SCMemcmp(sgh1->init->content_array, sgh2->init->content_array,
-               sgh1->init->content_size) != 0) {
-        return 0;
-    }
-
-    return 1;
-}
-
-/**
- * \brief Initializes the SigGroupHead 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.
- */
-int SigGroupHeadMpmHashInit(DetectEngineCtx *de_ctx)
-{
-    de_ctx->sgh_mpm_hash_table = HashListTableInit(4096, SigGroupHeadMpmHashFunc,
-                                                   SigGroupHeadMpmCompareFunc,
-                                                   NULL);
-
-    if (de_ctx->sgh_mpm_hash_table == NULL)
-        goto error;
-
-    return 0;
-
-error:
-    return -1;
-}
-
-/**
- * \brief Adds a SigGroupHead to the detection engine context SigGroupHead
- *        mpm hash table.
- *
- * \param de_ctx Pointer to the detection engine context.
- * \param sgh    Pointer to the SigGroupHead.
- *
- * \retval ret 0 on Successfully adding the argument sgh; -1 on failure.
- */
-int SigGroupHeadMpmHashAdd(DetectEngineCtx *de_ctx, SigGroupHead *sgh)
-{
-    int ret = HashListTableAdd(de_ctx->sgh_mpm_hash_table, (void *)sgh, 0);
-
-    return ret;
-}
-
-/**
- * \brief Used to lookup a SigGroupHead from the detection engine context
- *        SigGroupHead mpm hash table.
- *
- * \param de_ctx Pointer to the detection engine context.
- * \param sgh    Pointer to the SigGroupHead.
- *
- * \retval rsgh On success a pointer to the SigGroupHead if the SigGroupHead is
- *              found in the hash table; NULL on failure.
- */
-SigGroupHead *SigGroupHeadMpmHashLookup(DetectEngineCtx *de_ctx,
-                                        SigGroupHead *sgh)
-{
-    SigGroupHead *rsgh = HashListTableLookup(de_ctx->sgh_mpm_hash_table,
-                                             (void *)sgh, 0);
-
-    return rsgh;
-}
-
-/**
- * \brief Frees the hash table - DetectEngineCtx->sgh_mpm_hash_table, allocated by
- *        SigGroupHeadMpmHashInit() function.
- *
- * \param de_ctx Pointer to the detection engine context.
- */
-void SigGroupHeadMpmHashFree(DetectEngineCtx *de_ctx)
-{
-    if (de_ctx->sgh_mpm_hash_table == NULL)
-        return;
-
-    HashListTableFree(de_ctx->sgh_mpm_hash_table);
-    de_ctx->sgh_mpm_hash_table = NULL;
-
-    return;
-}
-
 /**
  * \brief The hash function to be the used by the hash table -
  *        DetectEngineCtx->sgh_hash_table.
@@ -1192,28 +1065,6 @@ int SigGroupHeadContainsSigId(DetectEngineCtx *de_ctx, SigGroupHead *sgh,
 
 int SigAddressPrepareStage1(DetectEngineCtx *);
 
-/**
- * \test Check if a SigGroupHead mpm hash table is properly allocated and
- *       deallocated when calling SigGroupHeadMpmHashInit() and
- *       SigGroupHeadMpmHashFree() respectively.
- */
-static int SigGroupHeadTest01(void)
-{
-    int result = 1;
-
-    DetectEngineCtx de_ctx;
-
-    SigGroupHeadMpmHashInit(&de_ctx);
-
-    result &= (de_ctx.sgh_mpm_hash_table != NULL);
-
-    SigGroupHeadMpmHashFree(&de_ctx);
-
-    result &= (de_ctx.sgh_mpm_hash_table == NULL);
-
-    return result;
-}
-
 /**
  * \test Check if a SigGroupHead hash table is properly allocated and
  *       deallocated when calling SigGroupHeadHashInit() and
@@ -1720,7 +1571,6 @@ end:
 void SigGroupHeadRegisterTests(void)
 {
 #ifdef UNITTESTS
-    UtRegisterTest("SigGroupHeadTest01", SigGroupHeadTest01, 1);
     UtRegisterTest("SigGroupHeadTest03", SigGroupHeadTest03, 1);
     UtRegisterTest("SigGroupHeadTest04", SigGroupHeadTest04, 1);
     UtRegisterTest("SigGroupHeadTest06", SigGroupHeadTest06, 1);
index 0885e590c04ca79a05783fcb19d6dbcbbfa3ae88..80a701e7e9c96461dc8298bb9f5251dee7015a6f 100644 (file)
@@ -871,7 +871,7 @@ static DetectEngineCtx *DetectEngineCtxInitReal(int minimal, const char *prefix)
     DetectEngineCtxLoadConf(de_ctx);
 
     SigGroupHeadHashInit(de_ctx);
-    SigGroupHeadMpmHashInit(de_ctx);
+    MpmStoreInit(de_ctx);
     SigGroupHeadDPortHashInit(de_ctx);
     ThresholdHashInit(de_ctx);
     VariableNameInitHash(de_ctx);
@@ -956,7 +956,7 @@ void DetectEngineCtxFree(DetectEngineCtx *de_ctx)
      * to be sure look at them again here.
      */
     SigGroupHeadHashFree(de_ctx);
-    SigGroupHeadMpmHashFree(de_ctx);
+    MpmStoreFree(de_ctx);
     SigGroupHeadDPortHashFree(de_ctx);
     DetectParseDupSigHashFree(de_ctx);
     SCSigSignatureOrderingModuleCleanup(de_ctx);
index 10180e438ba0525c2e2b3ed7bc3e5ab3f275845c..1abf9d5459fc368e560d82f3fccf8f608244507d 100644 (file)
@@ -3534,6 +3534,7 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx)
         SigGroupHead *sgh = de_ctx->sgh_array[idx];
         if (sgh == NULL)
             continue;
+
         SigGroupHeadSetFilemagicFlag(de_ctx, sgh);
         SigGroupHeadSetFileMd5Flag(de_ctx, sgh);
         SigGroupHeadSetFilesizeFlag(de_ctx, sgh);
@@ -3549,6 +3550,8 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx)
     }
     SCLogInfo("Unique rule groups: %u", cnt);
 
+    MpmStoreReportStats(de_ctx);
+
     if (de_ctx->decoder_event_sgh != NULL) {
         /* no need to set filestore count here as that would make a
          * signature not decode event only. */
@@ -3563,7 +3566,7 @@ int SigAddressPrepareStage4(DetectEngineCtx *de_ctx)
      * after the initialization phase. */
     SigGroupHeadHashFree(de_ctx);
     SigGroupHeadDPortHashFree(de_ctx);
-    SigGroupHeadMpmHashFree(de_ctx);
+    MpmStoreFree(de_ctx);
 
     SCFree(de_ctx->sgh_array);
     de_ctx->sgh_array_cnt = 0;
index ae4011c2685f1f4b642e6019ec2c41043163d3f2..e1c441b0dafd307d42699e8717ff84d1d73677d1 100644 (file)
@@ -606,7 +606,7 @@ typedef struct DetectEngineCtx_ {
     /* init phase vars */
     HashListTable *sgh_hash_table;
 
-    HashListTable *sgh_mpm_hash_table;
+    HashListTable *mpm_hash_table;
 
     HashListTable *sgh_dport_hash_table;
 
@@ -959,10 +959,30 @@ typedef struct SigTableElmt_ {
 #define SIG_GROUP_HEAD_MPM_DNSQUERY     (1 << 23)
 #define SIG_GROUP_HEAD_MPM_FD_SMTP      (1 << 24)
 
+enum MpmBuiltinBuffers {
+    MPMB_TCP_PKT_TS,
+    MPMB_TCP_PKT_TC,
+    MPMB_TCP_STREAM_TS,
+    MPMB_TCP_STREAM_TC,
+    MPMB_UDP_TS,
+    MPMB_UDP_TC,
+    MPMB_OTHERIP,
+    MPMB_MAX,
+};
+
+typedef struct MpmStore_ {
+    uint8_t *sid_array;
+    uint32_t sid_array_size;
+
+    int direction;
+    enum MpmBuiltinBuffers buffer;
+
+    MpmCtx *mpm_ctx;
+
+} MpmStore;
+
 typedef struct SigGroupHeadInitData_ {
-    /* list of content containers */
-    uint8_t *content_array;
-    uint32_t content_size;
+    MpmStore mpm_store[MPMB_MAX];
 
     uint8_t *sig_array; /**< bit array of sig nums (internal id's) */
     uint32_t sig_size; /**< size in bytes */