aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/detect-engine-mpm.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/detect-engine-mpm.c')
-rw-r--r--framework/src/suricata/src/detect-engine-mpm.c3030
1 files changed, 3030 insertions, 0 deletions
diff --git a/framework/src/suricata/src/detect-engine-mpm.c b/framework/src/suricata/src/detect-engine-mpm.c
new file mode 100644
index 00000000..c34ef252
--- /dev/null
+++ b/framework/src/suricata/src/detect-engine-mpm.c
@@ -0,0 +1,3030 @@
+/* Copyright (C) 2007-2014 Open Information Security Foundation
+ *
+ * You can copy, redistribute or modify this Program under the terms of
+ * the GNU General Public License version 2 as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+/**
+ * \file
+ *
+ * \author Victor Julien <victor@inliniac.net>
+ * \author Anoop Saldanha <anoopsaldanha@gmail.com>
+ *
+ * Multi pattern matcher
+ */
+
+#include "suricata.h"
+#include "suricata-common.h"
+
+#include "app-layer-protos.h"
+
+#include "decode.h"
+#include "detect.h"
+#include "detect-engine.h"
+#include "detect-engine-siggroup.h"
+#include "detect-engine-mpm.h"
+#include "detect-engine-iponly.h"
+#include "detect-parse.h"
+#include "util-mpm.h"
+#include "util-memcmp.h"
+#include "util-memcpy.h"
+#include "conf.h"
+#include "detect-fast-pattern.h"
+
+#include "flow.h"
+#include "flow-var.h"
+#include "detect-flow.h"
+
+#include "detect-content.h"
+#include "detect-uricontent.h"
+
+#include "stream.h"
+
+#include "util-enum.h"
+#include "util-debug.h"
+#include "util-print.h"
+#include "util-memcmp.h"
+#ifdef __SC_CUDA_SUPPORT__
+#include "util-mpm-ac.h"
+#endif
+
+/** \todo make it possible to use multiple pattern matcher algorithms next to
+ each other. */
+
+#define POPULATE_MPM_AVOID_PACKET_MPM_PATTERNS 0x01
+#define POPULATE_MPM_AVOID_STREAM_MPM_PATTERNS 0x02
+#define POPULATE_MPM_AVOID_URI_MPM_PATTERNS 0x04
+
+/**
+ * \brief check if a signature has patterns that are to be inspected
+ * against a packets payload (as opposed to the stream payload)
+ *
+ * \param s signature
+ *
+ * \retval 1 true
+ * \retval 0 false
+ */
+int SignatureHasPacketContent(Signature *s)
+{
+ SCEnter();
+
+ if (s == NULL) {
+ SCReturnInt(0);
+ }
+
+ if (!(s->proto.proto[6 / 8] & 1 << (6 % 8))) {
+ SCReturnInt(1);
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
+ SCLogDebug("no mpm");
+ SCReturnInt(0);
+ }
+
+ if (!(s->flags & SIG_FLAG_REQUIRE_PACKET)) {
+ SCReturnInt(0);
+ }
+
+ SCReturnInt(1);
+}
+
+/**
+ * \brief check if a signature has patterns that are to be inspected
+ * against the stream payload (as opposed to the individual packets
+ * payload(s))
+ *
+ * \param s signature
+ *
+ * \retval 1 true
+ * \retval 0 false
+ */
+int SignatureHasStreamContent(Signature *s)
+{
+ SCEnter();
+
+ if (s == NULL) {
+ SCReturnInt(0);
+ }
+
+ if (!(s->proto.proto[6 / 8] & 1 << (6 % 8))) {
+ SCReturnInt(0);
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_PMATCH] == NULL) {
+ SCLogDebug("no mpm");
+ SCReturnInt(0);
+ }
+
+ if (!(s->flags & SIG_FLAG_REQUIRE_STREAM)) {
+ SCReturnInt(0);
+ }
+
+ SCReturnInt(1);
+}
+
+
+/**
+ * \brief Function to return the multi pattern matcher algorithm to be
+ * used by the engine, based on the mpm-algo setting in yaml
+ * Use the default mpm if none is specified in the yaml file.
+ *
+ * \retval mpm algo value
+ */
+uint16_t PatternMatchDefaultMatcher(void)
+{
+ char *mpm_algo;
+ uint16_t mpm_algo_val = DEFAULT_MPM;
+
+ /* Get the mpm algo defined in config file by the user */
+ if ((ConfGet("mpm-algo", &mpm_algo)) == 1) {
+ uint16_t u;
+
+ if (mpm_algo != NULL) {
+ for (u = 0; u < MPM_TABLE_SIZE; u++) {
+ if (mpm_table[u].name == NULL)
+ continue;
+
+ if (strcmp(mpm_table[u].name, mpm_algo) == 0) {
+ mpm_algo_val = u;
+ goto done;
+ }
+ }
+ }
+
+ SCLogError(SC_ERR_INVALID_YAML_CONF_ENTRY, "Invalid mpm algo supplied "
+ "in the yaml conf file: \"%s\"", mpm_algo);
+ exit(EXIT_FAILURE);
+ }
+
+ done:
+#ifdef __tile__
+ if (mpm_algo_val == MPM_AC)
+ mpm_algo_val = MPM_AC_TILE;
+#endif
+
+ return mpm_algo_val;
+}
+
+uint32_t PacketPatternSearchWithStreamCtx(DetectEngineThreadCtx *det_ctx,
+ Packet *p)
+{
+ SCEnter();
+
+ uint32_t ret = 0;
+
+ if (p->flowflags & FLOW_PKT_TOSERVER) {
+ if (det_ctx->sgh->mpm_stream_ctx_ts == NULL)
+ SCReturnInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_stream_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_stream_ctx_ts, &det_ctx->mtc, &det_ctx->pmq,
+ p->payload, p->payload_len);
+ } else {
+ if (det_ctx->sgh->mpm_stream_ctx_tc == NULL)
+ SCReturnInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_stream_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_stream_ctx_tc, &det_ctx->mtc, &det_ctx->pmq,
+ p->payload, p->payload_len);
+ }
+
+ SCReturnInt(ret);
+}
+
+/** \brief Pattern match -- searches for only one pattern per signature.
+ *
+ * \param det_ctx detection engine thread ctx
+ * \param p packet to inspect
+ *
+ * \retval ret number of matches
+ */
+uint32_t PacketPatternSearch(DetectEngineThreadCtx *det_ctx, Packet *p)
+{
+ SCEnter();
+
+ uint32_t ret;
+ MpmCtx *mpm_ctx = NULL;
+
+ if (p->proto == IPPROTO_TCP) {
+ if (p->flowflags & FLOW_PKT_TOSERVER) {
+ mpm_ctx = det_ctx->sgh->mpm_proto_tcp_ctx_ts;
+ } else {
+ mpm_ctx = det_ctx->sgh->mpm_proto_tcp_ctx_tc;
+ }
+ } else if (p->proto == IPPROTO_UDP) {
+ if (p->flowflags & FLOW_PKT_TOSERVER) {
+ mpm_ctx = det_ctx->sgh->mpm_proto_udp_ctx_ts;
+ } else {
+ mpm_ctx = det_ctx->sgh->mpm_proto_udp_ctx_tc;
+ }
+ } else {
+ mpm_ctx = det_ctx->sgh->mpm_proto_other_ctx;
+ }
+
+ if (mpm_ctx == NULL)
+ SCReturnInt(0);
+
+#ifdef __SC_CUDA_SUPPORT__
+ if (p->cuda_pkt_vars.cuda_mpm_enabled && p->pkt_src == PKT_SRC_WIRE) {
+ ret = SCACCudaPacketResultsProcessing(p, mpm_ctx, &det_ctx->pmq);
+ } else {
+ ret = mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
+ &det_ctx->mtc,
+ &det_ctx->pmq,
+ p->payload,
+ p->payload_len);
+ }
+#else
+ ret = mpm_table[mpm_ctx->mpm_type].Search(mpm_ctx,
+ &det_ctx->mtc,
+ &det_ctx->pmq,
+ p->payload,
+ p->payload_len);
+#endif
+
+ SCReturnInt(ret);
+}
+
+/** \brief Uri Pattern match -- searches for one pattern per signature.
+ *
+ * \param det_ctx detection engine thread ctx
+ * \param p packet to inspect
+ *
+ * \retval ret number of matches
+ */
+uint32_t UriPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *uri, uint16_t uri_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_uri_ctx_ts == NULL)
+ SCReturnUInt(0U);
+
+ ret = mpm_table[det_ctx->sgh->mpm_uri_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_uri_ctx_ts,
+ &det_ctx->mtcu, &det_ctx->pmq, uri, uri_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ //PrintRawDataFp(stdout, uri, uri_len);
+
+ SCReturnUInt(ret);
+}
+
+/** \brief Http client body pattern match -- searches for one pattern per
+ * signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param body The request body to inspect.
+ * \param body_len Body length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpClientBodyPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *body, uint32_t body_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hcbd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hcbd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hcbd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, body, body_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/** \brief Http server body pattern match -- searches for one pattern per
+ * signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param body The request body to inspect.
+ * \param body_len Body length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpServerBodyPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *body, uint32_t body_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ BUG_ON(1);
+ } else {
+ if (det_ctx->sgh->mpm_hsbd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hsbd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hsbd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, body, body_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http header match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param headers Headers to inspect.
+ * \param headers_len Headers length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpHeaderPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *headers, uint32_t headers_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hhd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, headers, headers_len);
+ } else {
+ if (det_ctx->sgh->mpm_hhd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hhd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hhd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, headers, headers_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http raw header match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param headers Raw headers to inspect.
+ * \param headers_len Raw headers length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpRawHeaderPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *raw_headers, uint32_t raw_headers_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hrhd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hrhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, raw_headers, raw_headers_len);
+ } else {
+ if (det_ctx->sgh->mpm_hrhd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrhd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hrhd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, raw_headers, raw_headers_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http method match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param method Method to inspect.
+ * \param method_len Method length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpMethodPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *raw_method, uint32_t raw_method_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hmd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hmd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hmd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, raw_method, raw_method_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http cookie match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param cookie Cookie to inspect.
+ * \param cookie_len Cookie length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpCookiePatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *cookie, uint32_t cookie_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hcd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hcd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hcd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, cookie, cookie_len);
+ } else {
+ if (det_ctx->sgh->mpm_hcd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hcd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hcd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, cookie, cookie_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http raw uri match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param uri Raw uri to inspect.
+ * \param uri_len Raw uri length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpRawUriPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *uri, uint32_t uri_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hrud_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrud_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hrud_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, uri, uri_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http stat msg match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param stat_msg Stat msg to inspect.
+ * \param stat_msg_len Stat msg length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpStatMsgPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *stat_msg, uint32_t stat_msg_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ BUG_ON(1);
+ } else {
+ if (det_ctx->sgh->mpm_hsmd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hsmd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hsmd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, stat_msg, stat_msg_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http stat code match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param stat_code Stat code to inspect.
+ * \param stat_code_len Stat code length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpStatCodePatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *stat_code, uint32_t stat_code_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ BUG_ON(1);
+ } else {
+ if (det_ctx->sgh->mpm_hscd_ctx_tc == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hscd_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_hscd_ctx_tc, &det_ctx->mtcu,
+ &det_ctx->pmq, stat_code, stat_code_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http user agent match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param cookie User-Agent to inspect.
+ * \param cookie_len User-Agent buffer length.
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpUAPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *ua, uint32_t ua_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_huad_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_huad_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_huad_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, ua, ua_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http host header match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param hh Host header to inspect.
+ * \param hh_len Host header buffer length.
+ * \param flags Flags
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpHHPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *hh, uint32_t hh_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hhhd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hhhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hhhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, hh, hh_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief Http raw host header match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param hrh Raw hostname to inspect.
+ * \param hrh_len Raw hostname buffer length.
+ * \param flags Flags
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t HttpHRHPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *hrh, uint32_t hrh_len, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret;
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_hrhhd_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_hrhhd_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_hrhhd_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, hrh, hrh_len);
+ } else {
+ BUG_ON(1);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/**
+ * \brief DNS query match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param hrh Buffer to inspect.
+ * \param hrh_len buffer length.
+ * \param flags Flags
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t DnsQueryPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *buffer, uint32_t buffer_len,
+ uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret = 0;
+
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_dnsquery_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_dnsquery_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_dnsquery_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, buffer, buffer_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/** \brief Pattern match -- searches for only one pattern per signature.
+ *
+ * \param det_ctx detection engine thread ctx
+ * \param p packet
+ * \param smsg stream msg (reassembled stream data)
+ * \param flags stream flags
+ *
+ * \retval ret number of matches
+ */
+uint32_t StreamPatternSearch(DetectEngineThreadCtx *det_ctx, Packet *p,
+ StreamMsg *smsg, uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret = 0;
+ uint8_t cnt = 0;
+
+ //PrintRawDataFp(stdout, smsg->data.data, smsg->data.data_len);
+
+ uint32_t r;
+ if (flags & STREAM_TOSERVER) {
+ for ( ; smsg != NULL; smsg = smsg->next) {
+ r = mpm_table[det_ctx->sgh->mpm_stream_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_stream_ctx_ts, &det_ctx->mtcs,
+ &det_ctx->smsg_pmq[cnt], smsg->data, smsg->data_len);
+ if (r > 0) {
+ ret += r;
+
+ SCLogDebug("smsg match stored in det_ctx->smsg_pmq[%u]", cnt);
+
+ /* merge results with overall pmq */
+ PmqMerge(&det_ctx->smsg_pmq[cnt], &det_ctx->pmq);
+ }
+
+ cnt++;
+ }
+ } else {
+ for ( ; smsg != NULL; smsg = smsg->next) {
+ r = mpm_table[det_ctx->sgh->mpm_stream_ctx_tc->mpm_type].
+ Search(det_ctx->sgh->mpm_stream_ctx_tc, &det_ctx->mtcs,
+ &det_ctx->smsg_pmq[cnt], smsg->data, smsg->data_len);
+ if (r > 0) {
+ ret += r;
+
+ SCLogDebug("smsg match stored in det_ctx->smsg_pmq[%u]", cnt);
+
+ /* merge results with overall pmq */
+ PmqMerge(&det_ctx->smsg_pmq[cnt], &det_ctx->pmq);
+ }
+
+ cnt++;
+ }
+ }
+
+ SCReturnInt(ret);
+}
+
+/**
+ * \brief SMTP Filedata match -- searches for one pattern per signature.
+ *
+ * \param det_ctx Detection engine thread ctx.
+ * \param buffer Buffer to inspect.
+ * \param buffer_len buffer length.
+ * \param flags Flags
+ *
+ * \retval ret Number of matches.
+ */
+uint32_t SMTPFiledataPatternSearch(DetectEngineThreadCtx *det_ctx,
+ uint8_t *buffer, uint32_t buffer_len,
+ uint8_t flags)
+{
+ SCEnter();
+
+ uint32_t ret = 0;
+
+ if (flags & STREAM_TOSERVER) {
+ if (det_ctx->sgh->mpm_smtp_filedata_ctx_ts == NULL)
+ SCReturnUInt(0);
+
+ ret = mpm_table[det_ctx->sgh->mpm_smtp_filedata_ctx_ts->mpm_type].
+ Search(det_ctx->sgh->mpm_smtp_filedata_ctx_ts, &det_ctx->mtcu,
+ &det_ctx->pmq, buffer, buffer_len);
+ }
+
+ SCReturnUInt(ret);
+}
+
+/** \brief cleans up the mpm instance after a match */
+void PacketPatternCleanup(ThreadVars *t, DetectEngineThreadCtx *det_ctx)
+{
+ PmqReset(&det_ctx->pmq);
+
+ if (det_ctx->sgh == NULL)
+ return;
+
+ /* content */
+ if (det_ctx->sgh->mpm_proto_tcp_ctx_ts != NULL &&
+ mpm_table[det_ctx->sgh->mpm_proto_tcp_ctx_ts->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_proto_tcp_ctx_ts->mpm_type].Cleanup(&det_ctx->mtc);
+ }
+ if (det_ctx->sgh->mpm_proto_tcp_ctx_tc != NULL &&
+ mpm_table[det_ctx->sgh->mpm_proto_tcp_ctx_tc->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_proto_tcp_ctx_tc->mpm_type].Cleanup(&det_ctx->mtc);
+ }
+
+ if (det_ctx->sgh->mpm_proto_udp_ctx_ts != NULL &&
+ mpm_table[det_ctx->sgh->mpm_proto_udp_ctx_ts->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_proto_udp_ctx_ts->mpm_type].Cleanup(&det_ctx->mtc);
+ }
+ if (det_ctx->sgh->mpm_proto_udp_ctx_tc != NULL &&
+ mpm_table[det_ctx->sgh->mpm_proto_udp_ctx_tc->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_proto_udp_ctx_tc->mpm_type].Cleanup(&det_ctx->mtc);
+ }
+
+ if (det_ctx->sgh->mpm_proto_other_ctx != NULL &&
+ mpm_table[det_ctx->sgh->mpm_proto_other_ctx->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_proto_other_ctx->mpm_type].Cleanup(&det_ctx->mtc);
+ }
+
+ /* uricontent */
+ if (det_ctx->sgh->mpm_uri_ctx_ts != NULL && mpm_table[det_ctx->sgh->mpm_uri_ctx_ts->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_uri_ctx_ts->mpm_type].Cleanup(&det_ctx->mtcu);
+ }
+
+ /* stream content */
+ if (det_ctx->sgh->mpm_stream_ctx_ts != NULL && mpm_table[det_ctx->sgh->mpm_stream_ctx_ts->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_stream_ctx_ts->mpm_type].Cleanup(&det_ctx->mtcs);
+ }
+ if (det_ctx->sgh->mpm_stream_ctx_tc != NULL && mpm_table[det_ctx->sgh->mpm_stream_ctx_tc->mpm_type].Cleanup != NULL) {
+ mpm_table[det_ctx->sgh->mpm_stream_ctx_tc->mpm_type].Cleanup(&det_ctx->mtcs);
+ }
+
+ return;
+}
+
+void StreamPatternCleanup(ThreadVars *t, DetectEngineThreadCtx *det_ctx, StreamMsg *smsg)
+{
+ uint8_t cnt = 0;
+
+ while (smsg != NULL) {
+ PmqReset(&det_ctx->smsg_pmq[cnt]);
+
+ smsg = smsg->next;
+ cnt++;
+ }
+}
+
+void PatternMatchDestroy(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
+{
+ SCLogDebug("mpm_ctx %p, mpm_matcher %"PRIu16"", mpm_ctx, mpm_matcher);
+ mpm_table[mpm_matcher].DestroyCtx(mpm_ctx);
+}
+
+void PatternMatchPrepare(MpmCtx *mpm_ctx, uint16_t mpm_matcher)
+{
+ SCLogDebug("mpm_ctx %p, mpm_matcher %"PRIu16"", mpm_ctx, mpm_matcher);
+ MpmInitCtx(mpm_ctx, mpm_matcher);
+}
+
+void PatternMatchThreadPrint(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
+{
+ SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16" defunct", mpm_thread_ctx, mpm_matcher);
+ //mpm_table[mpm_matcher].PrintThreadCtx(mpm_thread_ctx);
+}
+void PatternMatchThreadDestroy(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher)
+{
+ SCLogDebug("mpm_thread_ctx %p, mpm_matcher %"PRIu16"", mpm_thread_ctx, mpm_matcher);
+ if (mpm_table[mpm_matcher].DestroyThreadCtx != NULL)
+ mpm_table[mpm_matcher].DestroyThreadCtx(NULL, mpm_thread_ctx);
+}
+void PatternMatchThreadPrepare(MpmThreadCtx *mpm_thread_ctx, uint16_t mpm_matcher, uint32_t max_id)
+{
+ SCLogDebug("mpm_thread_ctx %p, type %"PRIu16", max_id %"PRIu32"", mpm_thread_ctx, mpm_matcher, max_id);
+ MpmInitThreadCtx(mpm_thread_ctx, mpm_matcher, max_id);
+}
+
+
+/* free the pattern matcher part of a SigGroupHead */
+void PatternMatchDestroyGroup(SigGroupHead *sh)
+{
+ /* content */
+ if (!(sh->flags & SIG_GROUP_HEAD_MPM_COPY)) {
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_tcp_ctx_ts, sh);
+ if (sh->mpm_proto_tcp_ctx_ts != NULL &&
+ !sh->mpm_proto_tcp_ctx_ts->global) {
+ mpm_table[sh->mpm_proto_tcp_ctx_ts->mpm_type].
+ DestroyCtx(sh->mpm_proto_tcp_ctx_ts);
+ SCFree(sh->mpm_proto_tcp_ctx_ts);
+ }
+ /* ready for reuse */
+ sh->mpm_proto_tcp_ctx_ts = NULL;
+
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_tcp_ctx_tc, sh);
+ if (sh->mpm_proto_tcp_ctx_tc != NULL &&
+ !sh->mpm_proto_tcp_ctx_tc->global) {
+ mpm_table[sh->mpm_proto_tcp_ctx_tc->mpm_type].
+ DestroyCtx(sh->mpm_proto_tcp_ctx_tc);
+ SCFree(sh->mpm_proto_tcp_ctx_tc);
+ }
+ /* ready for reuse */
+ sh->mpm_proto_tcp_ctx_tc = NULL;
+
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_udp_ctx_ts, sh);
+ if (sh->mpm_proto_udp_ctx_ts != NULL &&
+ !sh->mpm_proto_udp_ctx_ts->global) {
+ mpm_table[sh->mpm_proto_udp_ctx_ts->mpm_type].
+ DestroyCtx(sh->mpm_proto_udp_ctx_ts);
+ SCFree(sh->mpm_proto_udp_ctx_ts);
+ }
+ /* ready for reuse */
+ sh->mpm_proto_udp_ctx_ts = NULL;
+
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_udp_ctx_tc, sh);
+ if (sh->mpm_proto_udp_ctx_tc != NULL &&
+ !sh->mpm_proto_udp_ctx_tc->global) {
+ mpm_table[sh->mpm_proto_udp_ctx_tc->mpm_type].
+ DestroyCtx(sh->mpm_proto_udp_ctx_tc);
+ SCFree(sh->mpm_proto_udp_ctx_tc);
+ }
+ /* ready for reuse */
+ sh->mpm_proto_udp_ctx_tc = NULL;
+
+ SCLogDebug("destroying mpm_ctx %p (sh %p)",
+ sh->mpm_proto_other_ctx, sh);
+ if (sh->mpm_proto_other_ctx != NULL &&
+ !sh->mpm_proto_other_ctx->global) {
+ mpm_table[sh->mpm_proto_other_ctx->mpm_type].
+ DestroyCtx(sh->mpm_proto_other_ctx);
+ SCFree(sh->mpm_proto_other_ctx);
+ }
+ /* ready for reuse */
+ sh->mpm_proto_other_ctx = NULL;
+ }
+
+ /* uricontent */
+ if ((sh->mpm_uri_ctx_ts != NULL) && !(sh->flags & SIG_GROUP_HEAD_MPM_URI_COPY)) {
+ if (sh->mpm_uri_ctx_ts != NULL) {
+ SCLogDebug("destroying mpm_uri_ctx %p (sh %p)", sh->mpm_uri_ctx_ts, sh);
+ if (!sh->mpm_uri_ctx_ts->global) {
+ mpm_table[sh->mpm_uri_ctx_ts->mpm_type].DestroyCtx(sh->mpm_uri_ctx_ts);
+ SCFree(sh->mpm_uri_ctx_ts);
+ }
+ /* ready for reuse */
+ sh->mpm_uri_ctx_ts = NULL;
+ }
+ }
+
+ /* stream content */
+ if ((sh->mpm_stream_ctx_ts != NULL || sh->mpm_stream_ctx_tc != NULL) &&
+ !(sh->flags & SIG_GROUP_HEAD_MPM_STREAM_COPY)) {
+ if (sh->mpm_stream_ctx_ts != NULL) {
+ SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_ts, sh);
+ if (!sh->mpm_stream_ctx_ts->global) {
+ mpm_table[sh->mpm_stream_ctx_ts->mpm_type].DestroyCtx(sh->mpm_stream_ctx_ts);
+ SCFree(sh->mpm_stream_ctx_ts);
+ }
+ /* ready for reuse */
+ sh->mpm_stream_ctx_ts = NULL;
+ }
+ if (sh->mpm_stream_ctx_tc != NULL) {
+ SCLogDebug("destroying mpm_stream_ctx %p (sh %p)", sh->mpm_stream_ctx_tc, sh);
+ if (!sh->mpm_stream_ctx_tc->global) {
+ mpm_table[sh->mpm_stream_ctx_tc->mpm_type].DestroyCtx(sh->mpm_stream_ctx_tc);
+ SCFree(sh->mpm_stream_ctx_tc);
+ }
+ /* ready for reuse */
+ sh->mpm_stream_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_hcbd_ctx_ts != NULL) {
+ if (sh->mpm_hcbd_ctx_ts != NULL) {
+ if (!sh->mpm_hcbd_ctx_ts->global) {
+ mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hcbd_ctx_ts);
+ SCFree(sh->mpm_hcbd_ctx_ts);
+ }
+ sh->mpm_hcbd_ctx_ts = NULL;
+ }
+ }
+
+ if (sh->mpm_hsbd_ctx_tc != NULL) {
+ if (sh->mpm_hsbd_ctx_tc != NULL) {
+ if (!sh->mpm_hsbd_ctx_tc->global) {
+ mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hsbd_ctx_tc);
+ SCFree(sh->mpm_hsbd_ctx_tc);
+ }
+ sh->mpm_hsbd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_smtp_filedata_ctx_ts != NULL) {
+ if (sh->mpm_smtp_filedata_ctx_ts != NULL) {
+ if (!sh->mpm_smtp_filedata_ctx_ts->global) {
+ mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].DestroyCtx(sh->mpm_smtp_filedata_ctx_ts);
+ SCFree(sh->mpm_smtp_filedata_ctx_ts);
+ }
+ sh->mpm_smtp_filedata_ctx_ts = NULL;
+ }
+ }
+
+ if (sh->mpm_hhd_ctx_ts != NULL || sh->mpm_hhd_ctx_tc != NULL) {
+ if (sh->mpm_hhd_ctx_ts != NULL) {
+ if (!sh->mpm_hhd_ctx_ts->global) {
+ mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hhd_ctx_ts);
+ SCFree(sh->mpm_hhd_ctx_ts);
+ }
+ sh->mpm_hhd_ctx_ts = NULL;
+ }
+ if (sh->mpm_hhd_ctx_tc != NULL) {
+ if (!sh->mpm_hhd_ctx_tc->global) {
+ mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hhd_ctx_tc);
+ SCFree(sh->mpm_hhd_ctx_tc);
+ }
+ sh->mpm_hhd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_hrhd_ctx_ts != NULL || sh->mpm_hrhd_ctx_tc != NULL) {
+ if (sh->mpm_hrhd_ctx_ts != NULL) {
+ if (!sh->mpm_hrhd_ctx_ts->global) {
+ mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hrhd_ctx_ts);
+ SCFree(sh->mpm_hrhd_ctx_ts);
+ }
+ sh->mpm_hrhd_ctx_ts = NULL;
+ }
+ if (sh->mpm_hrhd_ctx_tc != NULL) {
+ if (!sh->mpm_hrhd_ctx_tc->global) {
+ mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hrhd_ctx_tc);
+ SCFree(sh->mpm_hrhd_ctx_tc);
+ }
+ sh->mpm_hrhd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_hmd_ctx_ts != NULL) {
+ if (sh->mpm_hmd_ctx_ts != NULL) {
+ if (!sh->mpm_hmd_ctx_ts->global) {
+ mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hmd_ctx_ts);
+ SCFree(sh->mpm_hmd_ctx_ts);
+ }
+ sh->mpm_hmd_ctx_ts = NULL;
+ }
+ }
+
+ if (sh->mpm_hcd_ctx_ts != NULL || sh->mpm_hcd_ctx_tc != NULL) {
+ if (sh->mpm_hcd_ctx_ts != NULL) {
+ if (!sh->mpm_hcd_ctx_ts->global) {
+ mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hcd_ctx_ts);
+ SCFree(sh->mpm_hcd_ctx_ts);
+ }
+ sh->mpm_hcd_ctx_ts = NULL;
+ }
+ if (sh->mpm_hcd_ctx_tc != NULL) {
+ if (!sh->mpm_hcd_ctx_tc->global) {
+ mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hcd_ctx_tc);
+ SCFree(sh->mpm_hcd_ctx_tc);
+ }
+ sh->mpm_hcd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_hrud_ctx_ts != NULL) {
+ if (sh->mpm_hrud_ctx_ts != NULL) {
+ if (!sh->mpm_hrud_ctx_ts->global) {
+ mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].DestroyCtx(sh->mpm_hrud_ctx_ts);
+ SCFree(sh->mpm_hrud_ctx_ts);
+ }
+ sh->mpm_hrud_ctx_ts = NULL;
+ }
+ }
+
+ if (sh->mpm_hsmd_ctx_tc != NULL) {
+ if (sh->mpm_hsmd_ctx_tc != NULL) {
+ if (!sh->mpm_hsmd_ctx_tc->global) {
+ mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hsmd_ctx_tc);
+ SCFree(sh->mpm_hsmd_ctx_tc);
+ }
+ sh->mpm_hsmd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_hscd_ctx_tc != NULL) {
+ if (sh->mpm_hscd_ctx_tc != NULL) {
+ if (!sh->mpm_hscd_ctx_tc->global) {
+ mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].DestroyCtx(sh->mpm_hscd_ctx_tc);
+ SCFree(sh->mpm_hscd_ctx_tc);
+ }
+ sh->mpm_hscd_ctx_tc = NULL;
+ }
+ }
+
+ if (sh->mpm_huad_ctx_ts != NULL) {
+ if (sh->mpm_huad_ctx_ts != NULL) {
+ if (!sh->mpm_huad_ctx_ts->global) {
+ mpm_table[sh->mpm_huad_ctx_ts->mpm_type].DestroyCtx(sh->mpm_huad_ctx_ts);
+ SCFree(sh->mpm_huad_ctx_ts);
+ }
+ sh->mpm_huad_ctx_ts = NULL;
+ }
+ }
+
+ /* dns query */
+ if (sh->mpm_dnsquery_ctx_ts != NULL) {
+ if (!sh->mpm_dnsquery_ctx_ts->global) {
+ mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].DestroyCtx(sh->mpm_dnsquery_ctx_ts);
+ SCFree(sh->mpm_dnsquery_ctx_ts);
+ }
+ sh->mpm_dnsquery_ctx_ts = NULL;
+ }
+
+ return;
+}
+
+/** \brief Hash for looking up contents that are most used,
+ * always used, etc. */
+typedef struct ContentHash_ {
+ DetectContentData *ptr;
+ uint16_t cnt;
+ uint8_t use; /* use no matter what */
+} ContentHash;
+
+typedef struct UricontentHash_ {
+ DetectContentData *ptr;
+ uint16_t cnt;
+ uint8_t use; /* use no matter what */
+} UricontentHash;
+
+uint32_t ContentHashFunc(HashTable *ht, void *data, uint16_t datalen)
+{
+ ContentHash *ch = (ContentHash *)data;
+ DetectContentData *co = ch->ptr;
+ uint32_t hash = 0;
+ int i;
+ for (i = 0; i < co->content_len; i++) {
+ hash += co->content[i];
+ }
+ hash = hash % ht->array_size;
+ SCLogDebug("hash %" PRIu32 "", hash);
+ return hash;
+}
+
+uint32_t UricontentHashFunc(HashTable *ht, void *data, uint16_t datalen)
+{
+ UricontentHash *ch = (UricontentHash *)data;
+ DetectContentData *ud = ch->ptr;
+ uint32_t hash = 0;
+ int i;
+ for (i = 0; i < ud->content_len; i++) {
+ hash += ud->content[i];
+ }
+ hash = hash % ht->array_size;
+ SCLogDebug("hash %" PRIu32 "", hash);
+ return hash;
+}
+
+char ContentHashCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
+{
+ ContentHash *ch1 = (ContentHash *)data1;
+ ContentHash *ch2 = (ContentHash *)data2;
+ DetectContentData *co1 = ch1->ptr;
+ DetectContentData *co2 = ch2->ptr;
+
+ if (co1->content_len == co2->content_len &&
+ ((co1->flags & DETECT_CONTENT_NOCASE) == (co2->flags & DETECT_CONTENT_NOCASE)) &&
+ SCMemcmp(co1->content, co2->content, co1->content_len) == 0)
+ return 1;
+
+ return 0;
+}
+
+char UricontentHashCompareFunc(void *data1, uint16_t len1, void *data2, uint16_t len2)
+{
+ UricontentHash *ch1 = (UricontentHash *)data1;
+ UricontentHash *ch2 = (UricontentHash *)data2;
+ DetectContentData *ud1 = ch1->ptr;
+ DetectContentData *ud2 = ch2->ptr;
+
+ if (ud1->content_len == ud2->content_len &&
+ ((ud1->flags & DETECT_CONTENT_NOCASE) == (ud2->flags & DETECT_CONTENT_NOCASE)) &&
+ SCMemcmp(ud1->content, ud2->content, ud1->content_len) == 0)
+ return 1;
+
+ return 0;
+}
+
+ContentHash *ContentHashAlloc(DetectContentData *ptr)
+{
+ ContentHash *ch = SCMalloc(sizeof(ContentHash));
+ if (unlikely(ch == NULL))
+ return NULL;
+
+ ch->ptr = ptr;
+ ch->cnt = 1;
+ ch->use = 0;
+
+ return ch;
+}
+
+UricontentHash *UricontentHashAlloc(DetectContentData *ptr)
+{
+ UricontentHash *ch = SCMalloc(sizeof(UricontentHash));
+ if (unlikely(ch == NULL))
+ return NULL;
+
+ ch->ptr = ptr;
+ ch->cnt = 1;
+ ch->use = 0;
+
+ return ch;
+}
+
+void ContentHashFree(void *ch)
+{
+ SCFree(ch);
+}
+
+void UricontentHashFree(void *ch)
+{
+ SCFree(ch);
+}
+
+/** \brief Predict a strength value for patterns
+ *
+ * Patterns with high character diversity score higher.
+ * Alpha chars score not so high
+ * Other printable + a few common codes a little higher
+ * Everything else highest.
+ * Longer patterns score better than short patters.
+ *
+ * \param pat pattern
+ * \param patlen length of the patternn
+ *
+ * \retval s pattern score
+ */
+uint32_t PatternStrength(uint8_t *pat, uint16_t patlen)
+{
+ uint8_t a[256];
+ memset(&a, 0 ,sizeof(a));
+
+ uint32_t s = 0;
+ uint16_t u = 0;
+ for (u = 0; u < patlen; u++) {
+ if (a[pat[u]] == 0) {
+ if (isalpha(pat[u]))
+ s += 3;
+ else if (isprint(pat[u]) || pat[u] == 0x00 || pat[u] == 0x01 || pat[u] == 0xFF)
+ s += 4;
+ else
+ s += 6;
+
+ a[pat[u]] = 1;
+ } else {
+ s++;
+ }
+ }
+
+ return s;
+}
+
+static void PopulateMpmHelperAddPatternToPktCtx(MpmCtx *mpm_ctx,
+ DetectContentData *cd,
+ Signature *s, uint8_t flags,
+ int chop)
+{
+ if (cd->flags & DETECT_CONTENT_NOCASE) {
+ if (chop) {
+ MpmAddPatternCI(mpm_ctx,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ } else {
+ MpmAddPatternCI(mpm_ctx,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ } else {
+ if (chop) {
+ MpmAddPatternCS(mpm_ctx,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ } else {
+ MpmAddPatternCS(mpm_ctx,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ }
+
+ return;
+}
+
+static void PopulateMpmAddPatternToMpm(DetectEngineCtx *de_ctx,
+ SigGroupHead *sgh, Signature *s,
+ SigMatch *mpm_sm)
+{
+ s->mpm_sm = mpm_sm;
+
+ if (mpm_sm == NULL) {
+ SCLogDebug("%"PRIu32" no mpm pattern selected", s->id);
+ return;
+ }
+
+ int sm_list = SigMatchListSMBelongsTo(s, mpm_sm);
+ if (sm_list == -1)
+ BUG_ON(SigMatchListSMBelongsTo(s, mpm_sm) == -1);
+
+ uint8_t flags = 0;
+
+ DetectContentData *cd = NULL;
+
+ switch (sm_list) {
+ case DETECT_SM_LIST_PMATCH:
+ {
+ 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;
+ }
+
+ /* add the content to the "packet" mpm */
+ if (SignatureHasPacketContent(s)) {
+ if (s->proto.proto[6 / 8] & 1 << (6 % 8)) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_ts,
+ cd, s, flags, 1);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_tc,
+ cd, s, flags, 1);
+ }
+ }
+ if (s->proto.proto[17 / 8] & 1 << (17 % 8)) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_ts,
+ cd, s, flags, 1);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_tc,
+ cd, s, flags, 1);
+ }
+ }
+ int i;
+ for (i = 0; i < 256; i++) {
+ if (i == 6 || i == 17)
+ continue;
+ if (s->proto.proto[i / 8] & (1 << (i % 8))) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_other_ctx,
+ cd, s, flags, 1);
+ break;
+ }
+ }
+ /* 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;
+ }
+ }
+ if (SignatureHasStreamContent(s)) {
+ if (cd->flags & DETECT_CONTENT_NOCASE) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ MpmAddPatternCI(sgh->mpm_stream_ctx_ts,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ MpmAddPatternCI(sgh->mpm_stream_ctx_tc,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ } else {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ MpmAddPatternCS(sgh->mpm_stream_ctx_ts,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ MpmAddPatternCS(sgh->mpm_stream_ctx_tc,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ }
+ /* 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;
+ }
+ }
+ } 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;
+ }
+
+ if (SignatureHasPacketContent(s)) {
+ /* add the content to the "packet" mpm */
+ if (s->proto.proto[6 / 8] & 1 << (6 % 8)) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_ts,
+ cd, s, flags, 0);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_tcp_ctx_tc,
+ cd, s, flags, 0);
+ }
+ }
+ if (s->proto.proto[17 / 8] & 1 << (17 % 8)) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_ts,
+ cd, s, flags, 0);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_udp_ctx_tc,
+ cd, s, flags, 0);
+ }
+ }
+ int i;
+ for (i = 0; i < 256; i++) {
+ if (i == 6 || i == 17)
+ continue;
+ if (s->proto.proto[i / 8] & (1 << (i % 8))) {
+ PopulateMpmHelperAddPatternToPktCtx(sgh->mpm_proto_other_ctx,
+ cd, s, flags, 0);
+ break;
+ }
+ }
+ /* 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;
+ }
+ }
+ if (SignatureHasStreamContent(s)) {
+ /* add the content to the "packet" mpm */
+ if (cd->flags & DETECT_CONTENT_NOCASE) {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ MpmAddPatternCI(sgh->mpm_stream_ctx_ts,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ MpmAddPatternCI(sgh->mpm_stream_ctx_tc,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ } else {
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ MpmAddPatternCS(sgh->mpm_stream_ctx_ts,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ MpmAddPatternCS(sgh->mpm_stream_ctx_tc,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ }
+ /* 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 (SignatureHasPacketContent(s)) {
+ sgh->flags |= SIG_GROUP_HEAD_MPM_PACKET;
+ }
+ if (SignatureHasStreamContent(s)) {
+ sgh->flags |= SIG_GROUP_HEAD_MPM_STREAM;
+ }
+
+ break;
+ } /* case DETECT_CONTENT */
+
+ case DETECT_SM_LIST_UMATCH:
+ case DETECT_SM_LIST_HRUDMATCH:
+ case DETECT_SM_LIST_HCBDMATCH:
+ case DETECT_SM_LIST_FILEDATA:
+ case DETECT_SM_LIST_HHDMATCH:
+ case DETECT_SM_LIST_HRHDMATCH:
+ case DETECT_SM_LIST_HMDMATCH:
+ case DETECT_SM_LIST_HCDMATCH:
+ case DETECT_SM_LIST_HSMDMATCH:
+ case DETECT_SM_LIST_HSCDMATCH:
+ case DETECT_SM_LIST_HUADMATCH:
+ case DETECT_SM_LIST_HHHDMATCH:
+ case DETECT_SM_LIST_HRHHDMATCH:
+ case DETECT_SM_LIST_DNSQUERYNAME_MATCH:
+ {
+ MpmCtx *mpm_ctx_ts = NULL;
+ MpmCtx *mpm_ctx_tc = NULL;
+
+ cd = (DetectContentData *)mpm_sm->ctx;
+
+ if (sm_list == DETECT_SM_LIST_UMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_uri_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_URI;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HCBDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hcbd_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HCBD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_FILEDATA) {
+ if (s->flags & SIG_FLAG_TOCLIENT) {
+ mpm_ctx_tc = sgh->mpm_hsbd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HSBD;
+ }
+ if (s->flags & SIG_FLAG_TOSERVER) {
+ mpm_ctx_ts = sgh->mpm_smtp_filedata_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_FD_SMTP;
+ }
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HHDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hhd_ctx_ts;
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = sgh->mpm_hhd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HHD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HRHDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hrhd_ctx_ts;
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = sgh->mpm_hrhd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HRHD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HMDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hmd_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HMD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HCDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hcd_ctx_ts;
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = sgh->mpm_hcd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HCD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HRUDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hrud_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HRUD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HSMDMATCH) {
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = sgh->mpm_hsmd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HSMD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HSCDMATCH) {
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = sgh->mpm_hscd_ctx_tc;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HSCD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HUADMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_huad_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HUAD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HHHDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hhhd_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HHHD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_HRHHDMATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_hrhhd_ctx_ts;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_HRHHD;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ } else if (sm_list == DETECT_SM_LIST_DNSQUERYNAME_MATCH) {
+ if (s->flags & SIG_FLAG_TOSERVER)
+ mpm_ctx_ts = sgh->mpm_dnsquery_ctx_ts;
+ if (s->flags & SIG_FLAG_TOCLIENT)
+ mpm_ctx_tc = NULL;
+ sgh->flags |= SIG_GROUP_HEAD_MPM_DNSQUERY;
+ s->flags |= SIG_FLAG_MPM_APPLAYER;
+ if (cd->flags & DETECT_CONTENT_NEGATED)
+ s->flags |= SIG_FLAG_MPM_APPLAYER_NEG;
+ }
+
+ 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;
+ }
+
+ /* add the content to the mpm */
+ if (cd->flags & DETECT_CONTENT_NOCASE) {
+ if (mpm_ctx_ts != NULL) {
+ MpmAddPatternCI(mpm_ctx_ts,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (mpm_ctx_tc != NULL) {
+ MpmAddPatternCI(mpm_ctx_tc,
+ cd->content + cd->fp_chop_offset, cd->fp_chop_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ } else {
+ if (mpm_ctx_ts != NULL) {
+ MpmAddPatternCS(mpm_ctx_ts,
+ cd->content + cd->fp_chop_offset,
+ cd->fp_chop_len,
+ 0, 0, cd->id, s->num, flags);
+ }
+ if (mpm_ctx_tc != NULL) {
+ MpmAddPatternCS(mpm_ctx_tc,
+ cd->content + cd->fp_chop_offset,
+ cd->fp_chop_len,
+ 0, 0, cd->id, s->num, flags);
+ }
+ }
+ } 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 "uri" mpm */
+ if (cd->flags & DETECT_CONTENT_NOCASE) {
+ if (mpm_ctx_ts != NULL) {
+ MpmAddPatternCI(mpm_ctx_ts,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (mpm_ctx_tc != NULL) {
+ MpmAddPatternCI(mpm_ctx_tc,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ } else {
+ if (mpm_ctx_ts != NULL) {
+ MpmAddPatternCS(mpm_ctx_ts,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ if (mpm_ctx_tc != NULL) {
+ MpmAddPatternCS(mpm_ctx_tc,
+ cd->content, cd->content_len,
+ 0, 0,
+ cd->id, s->num, flags);
+ }
+ }
+ }
+ /* tell matcher we are inspecting uri */
+ s->mpm_pattern_id_div_8 = cd->id / 8;
+ s->mpm_pattern_id_mod_8 = 1 << (cd->id % 8);
+
+ break;
+ }
+ } /* switch (mpm_sm->type) */
+
+ SCLogDebug("%"PRIu32" adding cd->id %"PRIu32" to the mpm phase "
+ "(s->num %"PRIu32")", s->id,
+ ((DetectContentData *)mpm_sm->ctx)->id, s->num);
+
+ return;
+}
+
+SigMatch *RetrieveFPForSig(Signature *s)
+{
+ SigMatch *mpm_sm = NULL, *sm = NULL;
+ uint8_t has_non_negated_non_stream_pattern = 0;
+
+ if (s->mpm_sm != NULL)
+ return s->mpm_sm;
+
+ int list_id;
+ for (list_id = 0 ; list_id < DETECT_SM_LIST_MAX; list_id++) {
+ /* we have no keywords that support fp in this Signature sm list */
+ if (!FastPatternSupportEnabledForSigMatchList(list_id))
+ continue;
+
+ for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+ /* this keyword isn't registered for fp support */
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ if (cd->flags & DETECT_CONTENT_FAST_PATTERN)
+ return sm;
+ if (!(cd->flags & DETECT_CONTENT_NEGATED) &&
+ (list_id != DETECT_SM_LIST_PMATCH) &&
+ (list_id != DETECT_SM_LIST_HMDMATCH) &&
+ (list_id != DETECT_SM_LIST_HSMDMATCH) &&
+ (list_id != DETECT_SM_LIST_HSCDMATCH)) {
+ has_non_negated_non_stream_pattern = 1;
+ }
+ }
+ }
+
+ int max_len = 0;
+ int max_len_negated = 0;
+ int max_len_non_negated = 0;
+ for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
+ if (!FastPatternSupportEnabledForSigMatchList(list_id))
+ continue;
+
+ if (has_non_negated_non_stream_pattern &&
+ ((list_id == DETECT_SM_LIST_PMATCH) ||
+ (list_id == DETECT_SM_LIST_HMDMATCH) ||
+ (list_id == DETECT_SM_LIST_HSMDMATCH) ||
+ (list_id == DETECT_SM_LIST_HSCDMATCH))) {
+ continue;
+ }
+
+ for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ if (cd->flags & DETECT_CONTENT_NEGATED) {
+ if (max_len_negated < cd->content_len)
+ max_len_negated = cd->content_len;
+ } else {
+ if (max_len_non_negated < cd->content_len)
+ max_len_non_negated = cd->content_len;
+ }
+ }
+ }
+
+ int skip_negated_content = 0;
+ if (max_len_non_negated == 0) {
+ max_len = max_len_negated;
+ skip_negated_content = 0;
+ } else {
+ max_len = max_len_non_negated;
+ skip_negated_content = 1;
+ }
+
+ for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
+ if (!FastPatternSupportEnabledForSigMatchList(list_id))
+ continue;
+
+ if (has_non_negated_non_stream_pattern &&
+ ((list_id == DETECT_SM_LIST_PMATCH) ||
+ (list_id == DETECT_SM_LIST_HMDMATCH) ||
+ (list_id == DETECT_SM_LIST_HSMDMATCH) ||
+ (list_id == DETECT_SM_LIST_HSCDMATCH))) {
+ continue;
+ }
+
+ for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
+ continue;
+ if (cd->content_len < max_len)
+ continue;
+
+ if (mpm_sm == NULL) {
+ mpm_sm = sm;
+ } else {
+ DetectContentData *data1 = (DetectContentData *)sm->ctx;
+ DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
+ uint32_t ls = PatternStrength(data1->content, data1->content_len);
+ uint32_t ss = PatternStrength(data2->content, data2->content_len);
+ if (ls > ss) {
+ mpm_sm = sm;
+ } else if (ls == ss) {
+ /* if 2 patterns are of equal strength, we pick the longest */
+ if (data1->content_len > data2->content_len)
+ mpm_sm = sm;
+ } else {
+ SCLogDebug("sticking with mpm_sm");
+ }
+ } /* else - if (mpm == NULL) */
+ } /* for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) */
+ } /* for ( ; list_id < DETECT_SM_LIST_MAX; list_id++) */
+
+ return mpm_sm;
+}
+
+SigMatch *RetrieveFPForSigV2(Signature *s)
+{
+ if (s->mpm_sm != NULL)
+ return s->mpm_sm;
+
+
+ SigMatch *mpm_sm = NULL, *sm = NULL;
+ int nn_sm_list[DETECT_SM_LIST_MAX];
+ int n_sm_list[DETECT_SM_LIST_MAX];
+ memset(nn_sm_list, 0, sizeof(nn_sm_list));
+ memset(n_sm_list, 0, sizeof(n_sm_list));
+ int count_nn_sm_list = 0;
+ int count_n_sm_list = 0;
+ int list_id;
+
+ for (list_id = 0; list_id < DETECT_SM_LIST_MAX; list_id++) {
+ if (!FastPatternSupportEnabledForSigMatchList(list_id))
+ continue;
+
+ for (sm = s->sm_lists[list_id]; sm != NULL; sm = sm->next) {
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ if ((cd->flags & DETECT_CONTENT_FAST_PATTERN))
+ return sm;
+ if (cd->flags & DETECT_CONTENT_NEGATED) {
+ n_sm_list[list_id] = 1;
+ count_n_sm_list++;
+ } else {
+ nn_sm_list[list_id] = 1;
+ count_nn_sm_list++;
+ }
+ } /* for */
+ } /* for */
+
+ int *curr_sm_list = NULL;
+ int skip_negated_content = 1;
+ if (count_nn_sm_list > 0) {
+ curr_sm_list = nn_sm_list;
+ } else if (count_n_sm_list > 0) {
+ curr_sm_list = n_sm_list;
+ skip_negated_content = 0;
+ } else {
+ return NULL;
+ }
+
+ int final_sm_list[DETECT_SM_LIST_MAX];
+ int count_final_sm_list = 0;
+ int priority;
+
+ SCFPSupportSMList *tmp = sm_fp_support_smlist_list;
+ while (tmp != NULL) {
+ for (priority = tmp->priority;
+ tmp != NULL && priority == tmp->priority;
+ tmp = tmp->next) {
+
+ if (curr_sm_list[tmp->list_id] == 0)
+ continue;
+ final_sm_list[count_final_sm_list++] = tmp->list_id;
+ }
+ if (count_final_sm_list != 0)
+ break;
+ }
+
+ BUG_ON(count_final_sm_list == 0);
+
+ int max_len = 0;
+ int i;
+ for (i = 0; i < count_final_sm_list; i++) {
+ for (sm = s->sm_lists[final_sm_list[i]]; sm != NULL; sm = sm->next) {
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ /* skip_negated_content is only set if there's absolutely no
+ * non-negated content present in the sig */
+ if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
+ continue;
+ if (max_len < cd->content_len)
+ max_len = cd->content_len;
+ }
+ }
+
+ for (i = 0; i < count_final_sm_list; i++) {
+ for (sm = s->sm_lists[final_sm_list[i]]; sm != NULL; sm = sm->next) {
+ if (sm->type != DETECT_CONTENT)
+ continue;
+
+ DetectContentData *cd = (DetectContentData *)sm->ctx;
+ /* skip_negated_content is only set if there's absolutely no
+ * non-negated content present in the sig */
+ if ((cd->flags & DETECT_CONTENT_NEGATED) && skip_negated_content)
+ continue;
+ if (cd->content_len != max_len)
+ continue;
+
+ if (mpm_sm == NULL) {
+ mpm_sm = sm;
+ } else {
+ DetectContentData *data1 = (DetectContentData *)sm->ctx;
+ DetectContentData *data2 = (DetectContentData *)mpm_sm->ctx;
+ uint32_t ls = PatternStrength(data1->content, data1->content_len);
+ uint32_t ss = PatternStrength(data2->content, data2->content_len);
+ if (ls > ss) {
+ mpm_sm = sm;
+ } else if (ls == ss) {
+ /* if 2 patterns are of equal strength, we pick the longest */
+ if (data1->content_len > data2->content_len)
+ mpm_sm = sm;
+ } else {
+ SCLogDebug("sticking with mpm_sm");
+ }
+ } /* else - if */
+ } /* for */
+ } /* for */
+
+ return mpm_sm;
+}
+
+/**
+ * \internal
+ * \brief Setup the mpm content.
+ *
+ * \param de_ctx Pointer to the detect engine context.
+ * \param sgh Pointer to the signature group head against which we are
+ * adding patterns to the mpm ctx.
+ *
+ * \retval 0 Always.
+ */
+static int PatternMatchPreparePopulateMpm(DetectEngineCtx *de_ctx,
+ SigGroupHead *sgh)
+{
+ uint32_t sig = 0;
+ for (sig = 0; sig < sgh->sig_cnt; sig++) {
+ Signature *s = sgh->match_array[sig];
+ if (s == NULL)
+ continue;
+ PopulateMpmAddPatternToMpm(de_ctx, sgh, s, s->mpm_sm);
+ } /* for (sig = 0; sig < sgh->sig_cnt; sig++) */
+
+ return 0;
+}
+
+/** \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(DetectEngineCtx *de_ctx, SigGroupHead *sh)
+{
+ 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;
+ /* used to indicate if sgh has atleast one sig with http_server_body */
+ uint32_t has_co_hsbd = 0;
+ /* used to indicate if sgh has smtp file_data inspecting content */
+ uint32_t has_co_smtp = 0;
+ /* used to indicate if sgh has atleast one sig with http_header */
+ uint32_t has_co_hhd = 0;
+ /* used to indicate if sgh has atleast one sig with http_raw_header */
+ uint32_t has_co_hrhd = 0;
+ /* used to indicate if sgh has atleast one sig with http_method */
+ uint32_t has_co_hmd = 0;
+ /* used to indicate if sgh has atleast one sig with http_cookie */
+ uint32_t has_co_hcd = 0;
+ /* used to indicate if sgh has atleast one sig with http_raw_uri */
+ uint32_t has_co_hrud = 0;
+ /* used to indicate if sgh has atleast one sig with http_stat_msg */
+ uint32_t has_co_hsmd = 0;
+ /* used to indicate if sgh has atleast one sig with http_stat_code */
+ uint32_t has_co_hscd = 0;
+ /* used to indicate if sgh has atleast one sig with http_user_agent */
+ uint32_t has_co_huad = 0;
+ /* used to indicate if sgh has atleast one sig with http_host */
+ uint32_t has_co_hhhd = 0;
+ /* used to indicate if sgh has atleast one sig with http_raw_host */
+ uint32_t has_co_hrhhd = 0;
+ //uint32_t cnt = 0;
+ uint32_t sig = 0;
+ /* sgh has at least one sig with dns_query */
+ int has_co_dnsquery = 0;
+
+ /* see if this head has content and/or uricontent */
+ for (sig = 0; sig < sh->sig_cnt; sig++) {
+ s = sh->match_array[sig];
+ if (s == NULL)
+ continue;
+
+ if (SignatureHasPacketContent(s) == 1) {
+ has_co_packet = 1;
+ }
+ if (SignatureHasStreamContent(s) == 1) {
+ has_co_stream = 1;
+ }
+
+ 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 (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;
+ }
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HHDMATCH] != NULL) {
+ has_co_hhd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HRHDMATCH] != NULL) {
+ has_co_hrhd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HMDMATCH] != NULL) {
+ has_co_hmd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HCDMATCH] != NULL) {
+ has_co_hcd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HRUDMATCH] != NULL) {
+ has_co_hrud = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HSMDMATCH] != NULL) {
+ has_co_hsmd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HSCDMATCH] != NULL) {
+ has_co_hscd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HUADMATCH] != NULL) {
+ has_co_huad = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HHHDMATCH] != NULL) {
+ has_co_hhhd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_HRHHDMATCH] != NULL) {
+ has_co_hrhhd = 1;
+ }
+
+ if (s->sm_lists[DETECT_SM_LIST_DNSQUERYNAME_MATCH] != NULL) {
+ has_co_dnsquery = 1;
+ }
+ }
+
+ /* intialize contexes */
+ if (has_co_packet) {
+ 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);
+
+ 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) */
+
+ 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);
+ } 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);
+ }
+ MpmInitCtx(sh->mpm_stream_ctx_ts, de_ctx->mpm_matcher);
+ MpmInitCtx(sh->mpm_stream_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ 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);
+ } else {
+ sh->mpm_uri_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_uri_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_uri_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_uri_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hcbd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hcbd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hcbd, 0);
+ } else {
+ sh->mpm_hcbd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_hcbd_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hcbd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hcbd_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hsbd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hsbd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hsbd, 1);
+ } else {
+ sh->mpm_hsbd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hsbd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hsbd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hsbd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_smtp) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_smtp_filedata_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_smtp, 0);
+ } else {
+ sh->mpm_smtp_filedata_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_smtp_filedata_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_smtp_filedata_ctx_ts == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_smtp_filedata_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hhd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hhd, 0);
+ sh->mpm_hhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hhd, 1);
+ } else {
+ sh->mpm_hhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ sh->mpm_hhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hhd_ctx_ts == NULL || sh->mpm_hhd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hhd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hhd_ctx_ts, de_ctx->mpm_matcher);
+ MpmInitCtx(sh->mpm_hhd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hrhd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hrhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhd, 0);
+ sh->mpm_hrhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhd, 1);
+ } else {
+ sh->mpm_hrhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ sh->mpm_hrhd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hrhd_ctx_ts == NULL || sh->mpm_hrhd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hrhd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hrhd_ctx_ts, de_ctx->mpm_matcher);
+ MpmInitCtx(sh->mpm_hrhd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hmd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hmd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hmd, 0);
+ } else {
+ sh->mpm_hmd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_hmd_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hmd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hmd_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hcd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hcd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hcd, 0);
+ sh->mpm_hcd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hcd, 1);
+ } else {
+ sh->mpm_hcd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ sh->mpm_hcd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hcd_ctx_ts == NULL || sh->mpm_hcd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hcd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hcd_ctx_ts, de_ctx->mpm_matcher);
+ MpmInitCtx(sh->mpm_hcd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hrud) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hrud_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrud, 0);
+ } else {
+ sh->mpm_hrud_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_hrud_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hrud_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hrud_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hsmd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hsmd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hsmd, 1);
+ } else {
+ sh->mpm_hsmd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hsmd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hsmd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hsmd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hscd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hscd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hscd, 1);
+ } else {
+ sh->mpm_hscd_ctx_tc = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 1);
+ }
+ if (sh->mpm_hscd_ctx_tc == NULL) {
+ SCLogDebug("sh->mpm_hscd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hscd_ctx_tc, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_huad) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_huad_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_huad, 0);
+ } else {
+ sh->mpm_huad_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_huad_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_huad_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_huad_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hhhd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hhhd, 0);
+ } else {
+ sh->mpm_hhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_hhhd_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hhhd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hhhd_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_hrhhd) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_hrhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_hrhhd, 0);
+ } else {
+ sh->mpm_hrhhd_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_hrhhd_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hrhhd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_hrhhd_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_dnsquery) {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_SINGLE) {
+ sh->mpm_dnsquery_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, de_ctx->sgh_mpm_context_dnsquery, 0);
+ } else {
+ sh->mpm_dnsquery_ctx_ts = MpmFactoryGetMpmCtxForProfile(de_ctx, MPM_CTX_FACTORY_UNIQUE_CONTEXT, 0);
+ }
+ if (sh->mpm_dnsquery_ctx_ts == NULL) {
+ SCLogDebug("sh->mpm_hrhhd_ctx == NULL. This should never happen");
+ exit(EXIT_FAILURE);
+ }
+
+ MpmInitCtx(sh->mpm_dnsquery_ctx_ts, de_ctx->mpm_matcher);
+ }
+
+ if (has_co_packet ||
+ has_co_stream ||
+ has_co_uri ||
+ has_co_hcbd ||
+ has_co_hsbd ||
+ has_co_smtp ||
+ has_co_hhd ||
+ has_co_hrhd ||
+ has_co_hmd ||
+ has_co_hcd ||
+ has_co_hsmd ||
+ has_co_hscd ||
+ has_co_hrud ||
+ has_co_huad ||
+ has_co_hhhd ||
+ has_co_hrhhd ||
+ has_co_dnsquery)
+ {
+
+ PatternMatchPreparePopulateMpm(de_ctx, sh);
+
+ //if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ 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);
+ sh->mpm_uri_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_uri_ctx_ts->mpm_type].Prepare(sh->mpm_uri_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hcbd_ctx_ts != NULL) {
+ if (sh->mpm_hcbd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcbd_ctx_ts);
+ sh->mpm_hcbd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcbd_ctx_ts->mpm_type].Prepare(sh->mpm_hcbd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hsbd_ctx_tc != NULL) {
+ if (sh->mpm_hsbd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsbd_ctx_tc);
+ sh->mpm_hsbd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hsbd_ctx_tc->mpm_type].Prepare(sh->mpm_hsbd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_smtp_filedata_ctx_ts != NULL) {
+ if (sh->mpm_smtp_filedata_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_smtp_filedata_ctx_ts);
+ sh->mpm_smtp_filedata_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare != NULL) {
+ mpm_table[sh->mpm_smtp_filedata_ctx_ts->mpm_type].Prepare(sh->mpm_smtp_filedata_ctx_ts);
+ }
+ }
+ }
+ }
+
+ if (sh->mpm_hhd_ctx_ts != NULL) {
+ if (sh->mpm_hhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_ts);
+ sh->mpm_hhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hhd_ctx_tc != NULL) {
+ if (sh->mpm_hhd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_tc);
+ sh->mpm_hhd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhd_ctx_tc->mpm_type].Prepare(sh->mpm_hhd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hrhd_ctx_ts != NULL) {
+ if (sh->mpm_hrhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_ts);
+ sh->mpm_hrhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hrhd_ctx_tc != NULL) {
+ if (sh->mpm_hrhd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_tc);
+ sh->mpm_hrhd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhd_ctx_tc->mpm_type].Prepare(sh->mpm_hrhd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hmd_ctx_ts != NULL) {
+ if (sh->mpm_hmd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hmd_ctx_ts);
+ sh->mpm_hmd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hmd_ctx_ts->mpm_type].Prepare(sh->mpm_hmd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hcd_ctx_ts != NULL) {
+ if (sh->mpm_hcd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_ts);
+ sh->mpm_hcd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcd_ctx_ts->mpm_type].Prepare(sh->mpm_hcd_ctx_ts);
+ }
+ }
+ }
+ if (sh->mpm_hcd_ctx_tc != NULL) {
+ if (sh->mpm_hcd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_tc);
+ sh->mpm_hcd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hcd_ctx_tc->mpm_type].Prepare(sh->mpm_hcd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hrud_ctx_ts != NULL) {
+ if (sh->mpm_hrud_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrud_ctx_ts);
+ sh->mpm_hrud_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrud_ctx_ts->mpm_type].Prepare(sh->mpm_hrud_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hsmd_ctx_tc != NULL) {
+ if (sh->mpm_hsmd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsmd_ctx_tc);
+ sh->mpm_hsmd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hsmd_ctx_tc->mpm_type].Prepare(sh->mpm_hsmd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_hscd_ctx_tc != NULL) {
+ if (sh->mpm_hscd_ctx_tc->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hscd_ctx_tc);
+ sh->mpm_hscd_ctx_tc = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hscd_ctx_tc->mpm_type].Prepare(sh->mpm_hscd_ctx_tc);
+ }
+ }
+ }
+
+ if (sh->mpm_huad_ctx_ts != NULL) {
+ if (sh->mpm_huad_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_huad_ctx_ts);
+ sh->mpm_huad_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_huad_ctx_ts->mpm_type].Prepare(sh->mpm_huad_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hhhd_ctx_ts != NULL) {
+ if (sh->mpm_hhhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_ts);
+ sh->mpm_hhhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hhhd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_hrhhd_ctx_ts != NULL) {
+ if (sh->mpm_hrhhd_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts);
+ sh->mpm_hrhhd_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_hrhhd_ctx_ts->mpm_type].Prepare(sh->mpm_hrhhd_ctx_ts);
+ }
+ }
+ }
+
+ if (sh->mpm_dnsquery_ctx_ts != NULL) {
+ if (sh->mpm_dnsquery_ctx_ts->pattern_cnt == 0) {
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_dnsquery_ctx_ts);
+ sh->mpm_dnsquery_ctx_ts = NULL;
+ } else {
+ if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) {
+ if (mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare != NULL)
+ mpm_table[sh->mpm_dnsquery_ctx_ts->mpm_type].Prepare(sh->mpm_dnsquery_ctx_ts);
+ }
+ }
+ }
+ //} /* if (de_ctx->sgh_mpm_context == ENGINE_SGH_MPM_FACTORY_CONTEXT_FULL) */
+ } 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);
+ sh->mpm_hcbd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhd_ctx_ts);
+ sh->mpm_hhd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhd_ctx_ts);
+ sh->mpm_hrhd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hmd_ctx_ts);
+ sh->mpm_hmd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_ts);
+ sh->mpm_hcd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrud_ctx_ts);
+ sh->mpm_hrud_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_huad_ctx_ts);
+ sh->mpm_huad_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hhhd_ctx_ts);
+ sh->mpm_hhhd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hrhhd_ctx_ts);
+ sh->mpm_hrhhd_ctx_ts = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_dnsquery_ctx_ts);
+ sh->mpm_dnsquery_ctx_ts = NULL;
+ 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);
+ sh->mpm_hrhd_ctx_tc = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hcd_ctx_tc);
+ sh->mpm_hcd_ctx_tc = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hsmd_ctx_tc);
+ sh->mpm_hsmd_ctx_tc = NULL;
+ MpmFactoryReClaimMpmCtx(de_ctx, sh->mpm_hscd_ctx_tc);
+ sh->mpm_hscd_ctx_tc = NULL;
+ }
+
+ return 0;
+}
+
+/** \brief Pattern ID Hash for sharing pattern id's
+ *
+ * A per detection engine hash to make sure each pattern has a unique
+ * global id but patterns that are the same share id's.
+ */
+typedef struct MpmPatternIdTableElmt_ {
+ uint8_t *pattern; /**< ptr to the pattern */
+ uint16_t pattern_len; /**< pattern len */
+ PatIntId id; /**< pattern id */
+ uint16_t dup_count; /**< duplicate count */
+ uint8_t sm_list; /**< SigMatch list */
+} MpmPatternIdTableElmt;
+
+/** \brief Hash compare func for MpmPatternId api
+ * \retval 1 patterns are the same
+ * \retval 0 patterns are not the same
+ **/
+static char MpmPatternIdCompare(void *p1, uint16_t len1, void *p2, uint16_t len2)
+{
+ SCEnter();
+ BUG_ON(len1 < sizeof(MpmPatternIdTableElmt));
+ BUG_ON(len2 < sizeof(MpmPatternIdTableElmt));
+
+ MpmPatternIdTableElmt *e1 = (MpmPatternIdTableElmt *)p1;
+ MpmPatternIdTableElmt *e2 = (MpmPatternIdTableElmt *)p2;
+
+ if (e1->pattern_len != e2->pattern_len ||
+ e1->sm_list != e2->sm_list) {
+ SCReturnInt(0);
+ }
+
+ if (SCMemcmp(e1->pattern, e2->pattern, e1->pattern_len) != 0) {
+ SCReturnInt(0);
+ }
+
+ SCReturnInt(1);
+}
+
+/** \brief Hash func for MpmPatternId api
+ * \retval hash hash value
+ */
+static uint32_t MpmPatternIdHashFunc(HashTable *ht, void *p, uint16_t len)
+{
+ SCEnter();
+ BUG_ON(len < sizeof(MpmPatternIdTableElmt));
+
+ MpmPatternIdTableElmt *e = (MpmPatternIdTableElmt *)p;
+ uint32_t hash = e->pattern_len;
+ uint16_t u = 0;
+
+ for (u = 0; u < e->pattern_len; u++) {
+ hash += e->pattern[u];
+ }
+
+ SCReturnUInt(hash % ht->array_size);
+}
+
+/** \brief free a MpmPatternIdTableElmt */
+static void MpmPatternIdTableElmtFree(void *e)
+{
+ SCEnter();
+ MpmPatternIdTableElmt *c = (MpmPatternIdTableElmt *)e;
+ SCFree(c->pattern);
+ SCFree(c);
+ SCReturn;
+}
+
+/** \brief alloc initialize the MpmPatternIdHash */
+MpmPatternIdStore *MpmPatternIdTableInitHash(void)
+{
+ SCEnter();
+
+ MpmPatternIdStore *ht = SCMalloc(sizeof(MpmPatternIdStore));
+ BUG_ON(ht == NULL);
+ memset(ht, 0x00, sizeof(MpmPatternIdStore));
+
+ ht->hash = HashTableInit(65536, MpmPatternIdHashFunc, MpmPatternIdCompare, MpmPatternIdTableElmtFree);
+ BUG_ON(ht->hash == NULL);
+
+ SCReturnPtr(ht, "MpmPatternIdStore");
+}
+
+void MpmPatternIdTableFreeHash(MpmPatternIdStore *ht)
+{
+ SCEnter();
+
+ if (ht == NULL) {
+ SCReturn;
+ }
+
+ if (ht->hash != NULL) {
+ HashTableFree(ht->hash);
+ }
+
+ SCFree(ht);
+ SCReturn;
+}
+
+uint32_t MpmPatternIdStoreGetMaxId(MpmPatternIdStore *ht)
+{
+ if (ht == NULL) {
+ return 0;
+ }
+
+ return ht->max_id;
+}
+
+/**
+ * \brief Get the pattern id for a content pattern
+ *
+ * \param ht mpm pattern id hash table store
+ * \param co content pattern data
+ *
+ * \retval id pattern id
+ * \initonly
+ */
+uint32_t DetectContentGetId(MpmPatternIdStore *ht, DetectContentData *co)
+{
+ SCEnter();
+
+ BUG_ON(ht == NULL || ht->hash == NULL);
+
+ MpmPatternIdTableElmt *e = NULL;
+ MpmPatternIdTableElmt *r = NULL;
+ uint32_t id = 0;
+
+ e = SCMalloc(sizeof(MpmPatternIdTableElmt));
+ BUG_ON(e == NULL);
+ memset(e, 0, sizeof(MpmPatternIdTableElmt));
+ e->pattern = SCMalloc(co->content_len);
+ BUG_ON(e->pattern == NULL);
+ memcpy(e->pattern, co->content, co->content_len);
+ e->pattern_len = co->content_len;
+ e->id = 0;
+
+ r = HashTableLookup(ht->hash, (void *)e, sizeof(MpmPatternIdTableElmt));
+ if (r == NULL) {
+ e->id = ht->max_id;
+ ht->max_id++;
+ id = e->id;
+
+ int ret = HashTableAdd(ht->hash, e, sizeof(MpmPatternIdTableElmt));
+ BUG_ON(ret != 0);
+
+ e = NULL;
+
+ ht->unique_patterns++;
+ } else {
+ id = r->id;
+
+ ht->shared_patterns++;
+ }
+
+ if (e != NULL)
+ MpmPatternIdTableElmtFree(e);
+
+ SCReturnUInt(id);
+}
+
+typedef struct DetectFPAndItsId_ {
+ PatIntId id;
+ uint16_t content_len;
+ uint32_t flags;
+ int sm_list;
+
+ uint8_t *content;
+} DetectFPAndItsId;
+
+/**
+ * \brief Figured out the FP and their respective content ids for all the
+ * sigs in the engine.
+ *
+ * \param de_ctx Detection engine context.
+ *
+ * \retval 0 On success.
+ * \retval -1 On failure.
+ */
+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) {
+ s->mpm_sm = RetrieveFPForSigV2(s);
+ if (s->mpm_sm != NULL) {
+ DetectContentData *cd = (DetectContentData *)s->mpm_sm->ctx;
+ struct_total_size += sizeof(DetectFPAndItsId);
+ content_total_size += cd->content_len;
+ }
+ }
+
+ /* 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;
+ uint8_t content_len = 0;
+ 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->mpm_sm != NULL) {
+ int sm_list = SigMatchListSMBelongsTo(s, s->mpm_sm);
+ BUG_ON(sm_list == -1);
+
+ DetectContentData *cd = (DetectContentData *)s->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;
+ }
+
+ /* 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 relower its first argument.
+ */
+ memcpy_tolower(struct_offset->content, content, content_len);
+ } else {
+ memcpy(struct_offset->content, content, content_len);
+ }
+
+ struct_offset++;
+ } /* if (s->mpm_sm != NULL) */
+ } /* for */
+
+ de_ctx->max_fp_id = max_id;
+
+ SCFree(ahb);
+
+ return 0;
+}