Remove all search code from the pattern matchers, cleanup mpm api, remove unused http code, more cleanups.

remotes/origin/master-1.0.x
Victor Julien 17 years ago
parent 6990d9c91b
commit dd846c9b0e

@ -125,13 +125,6 @@ TmEcode AlertDebugLogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq
PrintRawDataFp(aft->file_ctx->fp, pv->value, pv->value_len);
}
for (i = 0; i < p->http_uri.cnt; i++) {
fprintf(aft->file_ctx->fp, "RAW URI [%2d]: ", i);
PrintRawUriFp(aft->file_ctx->fp, p->http_uri.raw[i], p->http_uri.raw_size[i]);
fprintf(aft->file_ctx->fp, "\n");
PrintRawDataFp(aft->file_ctx->fp, p->http_uri.raw[i], p->http_uri.raw_size[i]);
}
/* any stuff */
/* Sig details? */
/* pkt vars */

@ -179,21 +179,6 @@ typedef struct PacketAlerts_ {
PacketAlert alerts[PACKET_ALERT_MAX];
} PacketAlerts;
#define HTTP_URI_MAXCNT 8
#define HTTP_URI_MAXLEN 1024
typedef struct HttpUri_ {
/* the raw uri for the packet as set by pcre */
uint8_t *raw[HTTP_URI_MAXCNT];
uint16_t raw_size[HTTP_URI_MAXCNT];
/* normalized uri */
uint8_t norm[HTTP_URI_MAXCNT][HTTP_URI_MAXLEN];
uint16_t norm_size[HTTP_URI_MAXCNT];
uint8_t cnt;
} HttpUri;
typedef struct PktVar_ {
char *name;
struct PktVar_ *next; /* right now just implement this as a list,
@ -305,8 +290,6 @@ typedef struct Packet_
/* decoder events: review how many events we have */
uint8_t events[65535 / 8];
HttpUri http_uri;
PacketAlerts alerts;
/* IPS action to take */
@ -416,7 +399,6 @@ typedef struct DecodeThreadVars_
(p)->flowflags = 0; \
(p)->flags = 0; \
(p)->alerts.cnt = 0; \
PktHttpUriFree((p)); \
if ((p)->pktvar != NULL) { \
PktVarFree((p)->pktvar); \
} \

@ -2,38 +2,6 @@
*
* Copyright (C) 2008 by Victor Julien <victor@inliniac.net> */
/* This is a very important part of the detection engine, and certainly one
* of the most complex parts. String searching is complex and expensive,
* and thus worth optimizing. The way that is done here is by only running
* the pattern matcher once for every packet. In this search, all search words,
* the 'content' matches, are looked for. All results, of all the search words
* are stored in a array of lists. The array is an array of MpmMatchBucket's,
* that can be entered through the DetectContentData id field. There, it finds
* the bucket containing a list of 0, 1, or more matches of that content match.
* The list contains MpmMatch items, that contain an offset field. This field
* is the possition of the last character in the match.
*
* 03/22/2008 -- VJ:
* Recursive capture runs do something special to the depth and offset: the
* settings are only considered for the initial match. For the next matches,
* they are not. The reason is that this way we can still anchor the first
* match to a specific part of the payload, while the rest can be handled
* by content and pcre matches.
*
* 06/11/2009 -- PR:
* Now Patterns that exceed the max_pattern_length allowed by the current mpm
* are split into multiple chunk. The modifiers must be set in the first
* chunk of a group of chunks, and after a modifier is set, the modifiers of the
* next chunks must be recalculated (propagated). This way, each DETECT_CONTENT
* installed should be completely independent, as if it were loaded in another
* content option of the signature.
*
* TODO: add a 'recursive depth' to limit the depth to do the recursion on...
*
* XXX more later....
*
*/
#include "suricata-common.h"
#include "decode.h"
#include "detect.h"
@ -57,7 +25,7 @@ void DetectContentRegisterTests(void);
void DetectContentRegister (void) {
sigmatch_table[DETECT_CONTENT].name = "content";
sigmatch_table[DETECT_CONTENT].Match = DetectContentMatch;
sigmatch_table[DETECT_CONTENT].Match = NULL;
sigmatch_table[DETECT_CONTENT].Setup = DetectContentSetup;
sigmatch_table[DETECT_CONTENT].Free = DetectContentFree;
sigmatch_table[DETECT_CONTENT].RegisterTests = DetectContentRegisterTests;
@ -71,513 +39,6 @@ uint32_t DetectContentMaxId(DetectEngineCtx *de_ctx) {
return de_ctx->content_max_id;
}
#ifdef DEBUG
static void DetectContentDebugPrint(DetectContentData *co) {
char buf[2048] = "";
char tmp[4] = "";
uint16_t u = 0;
for (u = 0; u < co->content_len; u++) {
if (isprint((char)co->content[u])) {
snprintf(tmp,sizeof(tmp),"%c", (char)co->content[u]);
} else {
snprintf(tmp,sizeof(tmp),"\\%02x", co->content[u]);
}
strlcat(buf,tmp,sizeof(buf));
}
SCLogDebug("content \"%s\"",buf);
}
static void DetectContentPrintMatches(DetectEngineThreadCtx *det_ctx, DetectContentData *co) {
DetectContentDebugPrint(co);
if (det_ctx->mtc.match[co->id].len == 0)
SCLogDebug("pattern did not match");
else
SCLogDebug("matched %" PRIu32 " time(s) at offsets: ", det_ctx->mtc.match[co->id].len);
MpmMatch *tmpm = NULL;
for (tmpm = det_ctx->mtc.match[co->id].top; tmpm != NULL; tmpm = tmpm->next) {
SCLogDebug("pattern matched at offset %" PRIu32 " ", tmpm->offset);
}
}
#endif
static inline int
TestOffsetDepth(MpmMatch *m, DetectContentData *co, uint16_t pktoff) {
SCEnter();
if (m->offset >= pktoff) {
if (co->offset == 0 || (m->offset >= co->offset)) {
if (co->depth == 0 || ((m->offset + co->content_len) <= co->depth)) {
SCLogDebug("depth %" PRIu32 ", offset %" PRIu32 ", m->offset "
"%" PRIu32 ", return 1", co->depth, co->offset,
m->offset);
/* If we reach this point, it means we have obtained a depth and
* offset match, which indicates that we have a FAILURE if the
* content is negated, and SUCCESS if the content is not negated */
if (co->negated == 1)
SCReturnInt(0);
else
SCReturnInt(1);
} else {
/* We have success so far with offset, but a failure with
* depth. We can return a match at the bottom of this function
* for negated_content, provided offset is 0. If offset
* isn't 0 for negated_content, we have a failure and we return
* a no match here. If the content is not negated, we have a no
* match, which we return at the end of this function. */
if (co->offset && co->negated == 1)
SCReturnInt(0);
}
} else {
/* If offset fails, and if the content is negated, we check if depth
* succeeds. If it succeeds, we have a no match for negated content.
* Else we have a success for negated content. If the content is
* not negated, we go down till the end and return a no match. */
if (co->negated == 1) {
if (co->offset != 0) {
SCReturnInt(1);
} else if (co->depth && (m->offset+co->content_len) <= co->depth) {
SCLogDebug("depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", "
"return 0", co->depth, co->offset, m->offset);
SCReturnInt(0);
}
}
}
}
SCLogDebug("depth %" PRIu32 ", offset %" PRIu32 ", m->offset %" PRIu32 ", "
"return 0 (or 1 if negated)", co->depth, co->offset, m->offset);
/* If we reach this point, we have a match for negated content and no match
* otherwise */
if (co->negated == 1)
SCReturnInt(1);
else
SCReturnInt(0);
}
/**
* \brief test the within, distance, offset and depth of a match
*
* This function is called recursively (if necessary) to be able
* to determine whether or not a chain of content matches connected
* with 'within' and 'distance' options fully matches. The reason it
* was done like this is to make sure we can handle partial matches
* that turn out to fail being followed by full matches later in the
* packet. This adds some runtime complexity however.
*
* WITHIN
* The within check, if enabled, works as follows. The check is done
* against the current match "m". This is the pattern that we check
* the next against. So we will figure out if the next pattern exists
* within X bytes of "m".
*
* To do this, we take the next pattern (nsm) and loop through all
* matches of it. We then for each of the matches "nm" below, see if
* it is in the within limit.
*
* The within limit is checked as follows. It's checked against the
* current match "m". "m->offset" indicates the start of that match.
* So we need to consider m->offset + co->content_len. This will give
* us the end of the match "m". The next match then needs to occur
* before that point + the lenght of the pattern we're checking,
* nco->content_len.
*
* \param t thread vars
* \param det_ctx thread local data of the detection engine ctx
* \param m match we are inspecting
* \param nm current sigmatch to work with
* \param nsm next sigmatch to work with
* \param pktoff packet offset
*
* \retval 1 On success.
* \retval 0 On failure because of non-negated content.
* \retval -1 On failure because of negated content.
*/
int TestWithinDistanceOffsetDepth(ThreadVars *t,
DetectEngineThreadCtx *det_ctx,
MpmMatch *m, SigMatch *sm,
SigMatch *nsm, uint16_t pktoff)
{
int neg_success_flag = 0;
if (nsm == NULL) {
SCLogDebug("No next sigmatch, all sigmatches matched.");
return 1;
}
/** content match of current pattern */
DetectContentData *co = (DetectContentData *)sm->ctx;
if (!(co->flags & DETECT_CONTENT_DISTANCE_NEXT) && !(co->flags & DETECT_CONTENT_WITHIN_NEXT)) {
SCLogDebug("Next content does not need distance/within checking.");
return 1;
}
/** content match of next pattern */
DetectContentData *nco = (DetectContentData *)nsm->ctx;
#ifdef DEBUG
if (SCLogDebugEnabled()) {
SCLogDebug("printing matches");
DetectContentPrintMatches(det_ctx, nco);
}
#endif
/** list of matches of the next pattern */
MpmMatch *nm = det_ctx->mtc.match[nco->id].top;
/* if we have no matches and the content is negated, we can return a success */
if (nm == NULL) {
SCLogDebug("no nm to inspect");
if (nco->negated == 1)
return 1;
else
return 0;
}
/* recursively check if we have a next pattern that matches */
for ( ; nm != NULL; nm = nm->next) {
SCLogDebug("nm->offset %" PRIu32 ", m->offset %" PRIu32 ", pktoff "
"%" PRIu32 "", nm->offset, m->offset, pktoff);
SCLogDebug("nm->offset + nco->content_len = %"PRIu32" + %"PRIu32" = "
"%"PRIu32"", nm->offset, nco->content_len,
nm->offset + nco->content_len);
SCLogDebug("within (0 if disabled) = %"PRIu32" (nco->within "
"%"PRIu32" + co->content_len %"PRIu32")",
(nco->flags & DETECT_CONTENT_WITHIN) ?
(nco->within + co->content_len) : 0, nco->within,
co->content_len);
if (nm->offset >= pktoff) {
if ((!(nco->flags & DETECT_CONTENT_WITHIN) ||
(nco->within > 0 && (nm->offset > m->offset) &&
(((nm->offset + nco->content_len) - m->offset) <= (nco->within + co->content_len))))) {
SCLogDebug("MATCH: %" PRIu32 " <= WITHIN(%" PRIu32 ")",
(nm->offset + nco->content_len) - m->offset,
nco->within + co->content_len);
if (!(nco->flags & DETECT_CONTENT_DISTANCE) ||
((nm->offset >= (m->offset + co->content_len)) &&
((nm->offset - (m->offset + co->content_len)) >= nco->distance))) {
SCLogDebug("MATCH: %" PRIu32 " >= DISTANCE(%" PRIu32 ")",
nm->offset - (m->offset + co->content_len), nco->distance);
if (TestOffsetDepth(nm, nco, pktoff) == 0) {
/* if the content is not negated, we have to return a 0
* under all circumstances, because we can't afford for
* the offset and depth match to fail. If the content
* is negated, we have 2 cases. First case is when we
* have a distance or within and TestOffsetDepth() fails.
* In this case we have to return a 0, irrespective of
* whether we have a depth or offset, because we seem to
* be having a match for within or distance. If we don't
* have distance and within, and if the depth/offset
* check failed, then we still have a failure because of
* the obvious reason that in the absence of within and
* distance, offset/depth check has to succeed. */
if (nco->negated == 1)
return -1;
else
return 0;
} else {
/* if the content is negated and we had a within or a
* distance, it indicates that we passed through the
* within/distance, which is a failure */
if (nco->negated == 1 &&
((nco->flags & DETECT_CONTENT_WITHIN) ||
(nco->flags & DETECT_CONTENT_DISTANCE))) {
return -1;
} else {
return TestWithinDistanceOffsetDepth(t, det_ctx, nm,
nsm, DetectContentFindNextApplicableSM(nsm->next),
pktoff);
}
}
} else {
SCLogDebug("NO MATCH: %" PRIu32 " < DISTANCE(%" PRIu32 ")",
nm->offset - (m->offset + co->content_len),
nco->distance);
/* looks like we got through within, but failed at distance.
* An obvious failure in case of non-negated content, in which
* case we move on to the next match.
* In case of negated content, if there was a within
* previously, it indicates that we got through the within
* and we have a nomatch now with distance. If we didn't
* have within, we made it through, but we check for depth
* and offset now. If depth/offset check succeeds we have a
* temporary success and we move on to the next match. If
* it fails, we check if it failed because we didn't have
* offset and depth, in which case, it is not a failure and
* we on to the nextmatch. Otherwise it is a failure */
if (nco->negated == 1 && (nm->offset >= (m->offset + co->content_len))) {
if (nco->flags & DETECT_CONTENT_WITHIN)
return -1;
if (TestOffsetDepth(nm, nco, pktoff) == 1) {
neg_success_flag = 1;
} else {
if (nco->offset == 0 && nco->depth == 0)
neg_success_flag = 1;
else
return -1;
}
}
}
} else {
/* We have failed at within. If the content is not negated we
* have an obvious failure and we move on to the next match. If
* the content is negated, we check if distance exists. If it
* does, and if the distance check succeeds, we have a failure
* for negated content. If we don't have a failure or if distance
* doesn't exist, we move on to test offset/depth check. The
* offset/depth test is the same as in the previous else. */
if (nco->negated == 1 && nm->offset > m->offset) {
if ((nco->flags & DETECT_CONTENT_DISTANCE) &&
((nm->offset - (m->offset + co->content_len)) >= nco->distance)) {
return -1;
/* distance check meets non-negated requirements. Let
* us move on and check depth/offset */
}
if (TestOffsetDepth(nm, nco, pktoff) == 1) {
/* offset, depth success for negated content. A temp
* success for us. Let us set the flag indicating
* this and move on to the next match. */
neg_success_flag = 1;
} else {
/* looks like offset/depth failed. If it failed because
* both offset and depth weren't present, then it is not
* precisely a failure, because the existance of negated
* content is governed by the presence of within/distance.
* So we set the flag and move on to the next content.
* But if offset and depth do exist, then it indicates
* that the negated content doesn't meet the requirements
* of offset/depth and we have a failure. */
if (nco->offset == 0 && nco->depth == 0)
neg_success_flag = 1;
else
return -1;
}
}
}
} else {
SCLogDebug("pktoff %"PRIu16" > nm->offset %"PRIu32"", pktoff, nm->offset);
}
}
if (neg_success_flag == 1) {
return 1;
}
SCLogDebug("no match found, returning 0");
return 0;
}
int
DoDetectContent(ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *sm, DetectContentData *co)
{
int ret = 0;
char match = 0;
uint16_t payload_offset = det_ctx->payload_offset;
MpmMatch *temp_m = NULL;
SCLogDebug("det_ctx->mtc.match[%"PRIu32"].len %"PRIu32"", co->id, det_ctx->mtc.match[co->id].len);
/* Get the top match, we already know we have one. */
MpmMatch *m = det_ctx->mtc.match[co->id].top;
/* reset de_checking_distancewithin */
if (!(co->flags & DETECT_CONTENT_WITHIN) &&
!(co->flags & DETECT_CONTENT_DISTANCE))
{
det_ctx->de_checking_distancewithin = 0;
/* only use pkt offset of previous matches
* on relative matches. */
payload_offset = 0;
}
SCLogDebug("using payload_offset %"PRIu16"", payload_offset);
/* if we have within or distance coming up next, check this match
* for distance and/or within and check the rest of this match
* chain as well. */
if ((co->flags & DETECT_CONTENT_WITHIN_NEXT ||
co->flags & DETECT_CONTENT_DISTANCE_NEXT) &&
det_ctx->de_checking_distancewithin == 0)
{
SCLogDebug("DETECT_CONTENT_WITHIN_NEXT is %s",
co->flags & DETECT_CONTENT_WITHIN_NEXT ? "true":"false");
SCLogDebug("DETECT_CONTENT_DISTANCE_NEXT is %s",
co->flags & DETECT_CONTENT_DISTANCE_NEXT ? "true":"false");
/* indicate to the detection engine the next sigmatch(es)
* are part of this match chain */
det_ctx->de_checking_distancewithin = 1;
for (; m != NULL; m = m->next) {
/* first check our match for offset and depth */
if (TestOffsetDepth(m, co, payload_offset) == 1) {
SCLogDebug("TestOffsetDepth returned 1, for co->id %"PRIu32"", co->id);
SigMatch *real_sm_next = DetectContentFindNextApplicableSM(sm->next);
ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm, real_sm_next, payload_offset);
if (ret == 1) {
SCLogDebug("TestWithinDistanceOffsetDepth returned 1");
//det_ctx->pkt_ptr = p->payload + m->offset;
/* update both the local and ctx payload_offset */
payload_offset = det_ctx->payload_offset = m->offset;
match = 1;
break;
} else if (ret == -1) {
SCLogDebug("TestWithinDistanceOffsetDepth returned -1");
break;
}
} else {
SCLogDebug("TestOffsetDepth returned 0, for co->id %"PRIu32"", co->id);
}
}
/* Okay, this is complicated... on the first match of a match chain,
* we do the whole match of that chain (a chain here means a number
* of consecutive content matches that relate to each other with
* 'within and/or 'distance options'). But we still get to the next
* sigmatches. We have already inspected this sigmatch, even for
* offset and depth. Since the fact that we get there means we have
* had a match, we return match here too.
*/
} else if (co->flags & DETECT_CONTENT_WITHIN ||
co->flags & DETECT_CONTENT_DISTANCE)
{
SCLogDebug("distance/within checking already done, returning 1");
det_ctx->de_checking_distancewithin = 0;
match = 1;
/* Getting here means we are not in checking an within/distance chain.
* This means we can just inspect this content match on it's own. So
* Let's see if at least one of the matches within the offset and depth
* settings. If so, return a match.
*/
} else {
SCLogDebug("no distance/within checking");
/* if we have no matches, we return MATCH if the content is negated, or
* NOMATCH if the content is not negated */
if (m == NULL) {
if (co->negated == 1)
match = 1;
else
match = 0;
SCLogDebug("returning %d", match);
return match;
}
/* when in recursive capture mode don't check depth and offset
* after the first match */
if (s->flags & SIG_FLAG_RECURSIVE && det_ctx->pkt_cnt) {
for (; m != NULL; m = m->next) {
if (m->offset >= det_ctx->payload_offset) {
/* update pkt ptrs, content doesn't use this,
* but pcre does */
//det_ctx->pkt_ptr = p->payload + m->offset;
det_ctx->payload_offset = m->offset;
match = 1;
break;
}
}
} else {
temp_m = m;
for (; m != NULL; m = m->next) {
/* no offset as we inspect each match on it's own */
ret = TestOffsetDepth(m, co, 0);
/* If ret is 0 and content is negated, we have a failure and we
* break. If ret is 0 and content is not negated, we have a
* failure for this match, so we will continue in this loop
* testing other matches. If ret is 1, and the content is
* negated we have a success and we will continue along the loop
* to check that other matches also return 1 for TestOffsetDepth()
* with the negated content. But if ret is 1, and the content
* is not negated, we have a match, which is sufficient for us to
* return with a break, with match = 1. */
if (ret == 0) {
if (co->negated == 1) {
match = 0;
break;
}
} else {
if (co->negated == 0) {
/* update pkt ptrs, this content run doesn't
* use this, but pcre does */
//det_ctx->pkt_ptr = p->payload + m->offset;
det_ctx->payload_offset = m->offset;
match = 1;
break;
}
}
}
/* If there were matches, with the content being negated, and all of
* them passed TestOffsetDepth(), we have a match. This is the
* reason why we continue in the else part if ret == 1, if the
* content is negated */
if (temp_m != NULL && ret == 1 && co->negated == 1) {
SCLogDebug("setting match to true");
match = 1;
}
}
}
/* If it has matched, check if it's set a "isdataat" option and process it */
if (match == 1 && (co->flags & DETECT_CONTENT_ISDATAAT_RELATIVE) &&
co->negated == 0) {
/* if the rest of the payload (from the last match) is less than
the "isdataat" there is no data where the rule expected
so match=0
*/
SCLogDebug("isdataat: payload_len: %u, used %u, rest %u, isdataat? %u", p->payload_len, (m->offset + co->content_len),p->payload_len - (m->offset + co->content_len), co->isdataat);
if ((uint32_t)(p->payload_len - (m->offset + co->content_len)) < co->isdataat)
match = 0;
if (match) {
SCLogDebug("still matching after isdataat check");
}
}
SCLogDebug("returning %d", match);
return match;
}
/*
* returns 0: no match
* 1: match
* -1: error
*/
int DetectContentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx, Packet *p, Signature *s, SigMatch *m)
{
if (p->payload_len == 0)
return 0;
DetectContentData *co = (DetectContentData *)m->ctx;
#ifdef DEBUG
if (SCLogDebugEnabled()) {
SCLogDebug("printing matches");
DetectContentPrintMatches(det_ctx, co);
}
#endif
return DoDetectContent(t, det_ctx, p, s, m, co);
}
DetectContentData *DetectContentParse (char *contentstr)
{
DetectContentData *cd = NULL;
@ -951,6 +412,38 @@ SigMatch *DetectContentFindPrevApplicableSM(SigMatch *sm)
return NULL;
}
/** \brief get the last pattern sigmatch, content or uricontent
*
* \param s signature
*
* \retval sm sigmatch of either content or uricontent that is the last
* or NULL if none was found
*/
SigMatch *SigMatchGetLastPattern(Signature *s) {
SCEnter();
BUG_ON(s == NULL);
SigMatch *co_sm = DetectContentFindPrevApplicableSM(s->pmatch_tail);
SigMatch *ur_sm = SigMatchGetLastSM(s->match, DETECT_URICONTENT);
SigMatch *sm = NULL;
if (co_sm != NULL && ur_sm != NULL) {
BUG_ON(co_sm->idx == ur_sm->idx);
if (co_sm->idx > ur_sm->idx)
sm = co_sm;
else
sm = ur_sm;
} else if (co_sm != NULL) {
sm = co_sm;
} else if (ur_sm != NULL) {
sm = ur_sm;
}
SCReturnPtr(sm, "SigMatch");
}
/**
* \brief Count the number of chunks of a specified chunk group
* \param sm pointer to a SigMatch that belong to this chunk group

@ -81,6 +81,8 @@ SigMatch *DetectContentFindNextApplicableSM(SigMatch *);
* a Pattern before the SigMatch passed as argument */
SigMatch *DetectContentHasPrevSMPattern(SigMatch *);
SigMatch *SigMatchGetLastPattern(Signature *s);
/** After setting a new modifier, we should call one of the followings */
int DetectContentPropagateDepth(SigMatch *);
int DetectContentPropagateIsdataat(SigMatch *);

@ -79,8 +79,6 @@ uint32_t PacketPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
{
SCEnter();
det_ctx->pmq.mode = PMQ_MODE_SCAN;
uint32_t ret;
#ifndef __SC_CUDA_SUPPORT__
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Scan(det_ctx->sgh->mpm_ctx,
@ -118,8 +116,6 @@ uint32_t UriPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
{
SCEnter();
det_ctx->pmq.mode = PMQ_MODE_SCAN;
if (det_ctx->sgh->mpm_uri_ctx == NULL)
SCReturnUInt(0U);
@ -145,78 +141,6 @@ uint32_t UriPatternScan(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
SCReturnUInt(ret);
}
/** \brief Pattern match, search part -- searches for all other patterns
* \param tv threadvars
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t PacketPatternMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
Packet *p)
{
SCEnter();
det_ctx->pmq.mode = PMQ_MODE_SEARCH;
uint32_t ret;
#ifndef __SC_CUDA_SUPPORT__
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Search(det_ctx->sgh->mpm_ctx,
&det_ctx->mtc,
&det_ctx->pmq,
p->payload,
p->payload_len);
#else
/* if the user has enabled cuda support, but is not using the cuda mpm
* algo, then we shouldn't take the path of the dispatcher. Call the mpm
* directly */
if (det_ctx->sgh->mpm_ctx->mpm_type != MPM_B2G_CUDA) {
ret = mpm_table[det_ctx->sgh->mpm_ctx->mpm_type].Search(det_ctx->sgh->mpm_ctx,
&det_ctx->mtc,
&det_ctx->pmq,
p->payload,
p->payload_len);
SCReturnInt(ret);
}
SCCudaHlProcessPacketWithDispatcher(p, det_ctx, /* search */ 1, &ret);
#endif
SCReturnInt(ret);
}
/** \brief Uri Pattern match, search part -- searches for all other patterns
* \param tv threadvars
* \param det_ctx detection engine thread ctx
* \param p packet to scan
*/
uint32_t UriPatternMatch(ThreadVars *tv, DetectEngineThreadCtx *det_ctx,
uint8_t *uri, uint16_t uri_len)
{
SCEnter();
det_ctx->pmq.mode = PMQ_MODE_SEARCH;
uint32_t ret;
#ifndef __SC_CUDA_SUPPORT__
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Search
(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, uri,
uri_len);
#else
/* if the user has enabled cuda support, but is not using the cuda mpm
* algo, then we shouldn't take the path of the dispatcher. Call the mpm
* directly */
if (det_ctx->sgh->mpm_uri_ctx->mpm_type != MPM_B2G_CUDA) {
ret = mpm_table[det_ctx->sgh->mpm_uri_ctx->mpm_type].Search
(det_ctx->sgh->mpm_uri_ctx, &det_ctx->mtcu, &det_ctx->pmq, uri,
uri_len);
SCReturnInt(ret);
}
SCCudaHlProcessUriWithDispatcher(uri, uri_len, det_ctx, /* search */ 1, &ret);
#endif
SCReturnInt(ret);
}
/** \brief cleans up the mpm instance after a match */
void PacketPatternCleanup(ThreadVars *t, DetectEngineThreadCtx *det_ctx) {
PmqReset(&det_ctx->pmq);

@ -4,11 +4,9 @@
#include "tm-modules.h"
uint16_t PatternMatchDefaultMatcher(void);
uint32_t PacketPatternScan(ThreadVars *, DetectEngineThreadCtx *, Packet *);
uint32_t PacketPatternMatch(ThreadVars *, DetectEngineThreadCtx *, Packet *);
uint32_t PacketPatternScan(ThreadVars *, DetectEngineThreadCtx *, Packet *);
uint32_t UriPatternScan(ThreadVars *, DetectEngineThreadCtx *, uint8_t *, uint16_t);
uint32_t UriPatternMatch(ThreadVars *, DetectEngineThreadCtx *, uint8_t *, uint16_t);
void PacketPatternCleanup(ThreadVars *, DetectEngineThreadCtx *);

@ -182,6 +182,8 @@ int DetectFtpbounceALMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
int DetectFtpbounceMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, Signature *s, SigMatch *m)
{
/** \todo VJ broken and no longer used */
#if 0
SCEnter();
uint16_t offset = 0;
if (!(PKT_IS_TCP(p)))
@ -204,6 +206,8 @@ int DetectFtpbounceMatch(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
return DetectFtpbounceMatchArgs(p->payload, p->payload_len,
p->src.addr_data32[0], offset);
#endif
return 0;
}
/**

@ -208,12 +208,7 @@ static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *s
memset(hd, 0, sizeof(DetectHttpCookieData));
hd->data_len = ((DetectContentData *)pm->ctx)->content_len;
hd->data = SCMalloc(hd->data_len);
if (hd->data == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed");
goto error;
}
memcpy(hd->data, ((DetectContentData *)pm->ctx)->content, hd->data_len);
hd->data = ((DetectContentData *)pm->ctx)->content;
nm->type = DETECT_AL_HTTP_COOKIE;
nm->ctx = (void *)hd;
@ -222,8 +217,9 @@ static int DetectHttpCookieSetup (DetectEngineCtx *de_ctx, Signature *s, char *s
* the new match to the match list */
SigMatchReplaceContent(s, pm, nm);
/* free the old content sigmatch */
DetectContentFree(pm->ctx);
/* free the old content sigmatch, the content pattern memory
* is taken over by the new sigmatch */
SCFree(pm->ctx);
SCFree(pm);
/* Flagged the signature as to scan the app layer data */

@ -190,13 +190,7 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st
}
data->content_len = ((DetectContentData *)pm->ctx)->content_len;
data->content = SCMalloc(data->content_len);
if (data->content == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "SCMalloc failed");
goto error;
}
memcpy(data->content,
((DetectContentData *)pm->ctx)->content, data->content_len);
data->content = ((DetectContentData *)pm->ctx)->content;
method = bstr_memdup((char *)data->content, data->content_len);
/** \todo error check */
@ -210,8 +204,9 @@ static int DetectHttpMethodSetup(DetectEngineCtx *de_ctx, Signature *s, char *st
* the new match to the match list */
SigMatchReplaceContent(s, pm, nm);
/* free the old content sigmatch */
DetectContentFree(pm->ctx);
/* free the old content sigmatch, the memory for the pattern
* is taken over by our new sigmatch */
SCFree(pm->ctx);
SCFree(pm);
/* Flagged the signature as to scan the app layer data */

@ -27,49 +27,48 @@ void DetectNocaseRegister (void) {
sigmatch_table[DETECT_NOCASE].flags |= SIGMATCH_PAYLOAD;
}
/** \todo uricontent needs fixing */
/** \internal
* \brief Apply the nocase keyword to the last pattern match, either content or uricontent
* \param det_ctx detection engine ctx
* \param s signature
* \param nullstr should be null
* \retval 0 ok
* \retval -1 failure
*/
static int DetectNocaseSetup (DetectEngineCtx *de_ctx, Signature *s, char *nullstr)
{
SCEnter();
int ret = 0;
if (nullstr != NULL) {
SCLogError(SC_ERR_INVALID_VALUE, "nocase has no value");
SCReturnInt(-1);
}
SigMatch *co_sm = DetectContentFindPrevApplicableSM(s->pmatch_tail);
SigMatch *ur_sm = SigMatchGetLastSM(s->match, DETECT_URICONTENT);
char uri = 0;
if (co_sm != NULL && ur_sm != NULL) {
BUG_ON(co_sm->idx == ur_sm->idx);
if (co_sm->idx > ur_sm->idx)
uri = 0;
else
uri = 1;
} else if (co_sm != NULL) {
uri = 0;
} else if (ur_sm != NULL) {
uri = 1;
} else {
SigMatch *pm = SigMatchGetLastPattern(s);
if (pm == NULL) {
SCLogError(SC_ERR_NOCASE_MISSING_PATTERN, "\"nocase\" needs a preceeding content or uricontent option.");
SCReturnInt(-1);
}
if (uri == 0) {
DetectContentData *cd = (DetectContentData *)co_sm->ctx;
cd->flags |= DETECT_CONTENT_NOCASE;
goto end;
} else {
DetectUricontentData *cd = (DetectUricontentData *)ur_sm->ctx;
cd->flags |= DETECT_URICONTENT_NOCASE;
goto end;
switch (pm->type) {
case DETECT_CONTENT:
{
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_NOCASE;
break;
}
case DETECT_URICONTENT:
{
DetectUricontentData *cd = (DetectUricontentData *)pm->ctx;
cd->flags |= DETECT_URICONTENT_NOCASE;
break;
}
/* should never happen */
default:
BUG_ON(1);
break;
}
ret = -1;
end:
SCReturnInt(ret);
SCReturnInt(0);
}

@ -24,24 +24,33 @@ void DetectRawbytesRegister (void) {
sigmatch_table[DETECT_RAWBYTES].flags |= SIGMATCH_PAYLOAD;
}
int DetectRawbytesSetup (DetectEngineCtx *de_ctx, Signature *s, char *nullstr)
static int DetectRawbytesSetup (DetectEngineCtx *de_ctx, Signature *s, char *nullstr)
{
SCEnter();
if (nullstr != NULL) {
SCLogError(SC_ERR_INVALID_VALUE, "nocase has no value");
return -1;
}
if (s->pmatch_tail == NULL)
return -1;
SigMatch *pm = DetectContentFindPrevApplicableSM(s->pmatch_tail);
if (pm != NULL) {
if (pm->type == DETECT_CONTENT) {
if (pm == NULL) {
SCLogError(SC_ERR_RAWBYTES_MISSING_CONTENT, "\"rawbytes\" needs a preceeding content option");
SCReturnInt(-1);
}
switch (pm->type) {
case DETECT_CONTENT:
{
DetectContentData *cd = (DetectContentData *)pm->ctx;
cd->flags |= DETECT_CONTENT_RAWBYTES;
break;
}
default:
SCLogError(SC_ERR_RAWBYTES_MISSING_CONTENT, "\"rawbytes\" needs a preceeding content option");
SCReturnInt(-1);
}
return 0;
SCReturnInt(0);
}

@ -70,195 +70,6 @@ uint32_t DetectUricontentMaxId(DetectEngineCtx *de_ctx)
return de_ctx->uricontent_max_id;
}
/**
* \brief Free the stored http_uri in the given packet
* \param p pointer to the given packet whose uri has to be SCFreed
*/
void PktHttpUriFree(Packet *p)
{
int i;
for (i = 0; i < p->http_uri.cnt; i++) {
SCFree(p->http_uri.raw[i]);
p->http_uri.raw[i] = NULL;
}
p->http_uri.cnt = 0;
}
static inline int TestOffsetDepth(MpmMatch *m, DetectUricontentData *co)
{
if (co->offset == 0 ||
(co->offset && ((m->offset+1) - co->uricontent_len) >= co->offset))
{
if (co->depth == 0 ||
(co->depth && (m->offset+1) <= co->depth))
{
return 1;
}
}
return 0;
}
/* This function is called recursively (if necessary) to be able
* to determite whether or not a chain of content matches connected
* with 'within' and 'distance' options fully matches. The reason it
* was done like this is to make sure we can handle partial matches
* that turn out to fail being followed by full matches later in the
* packet. This adds some runtime complexity however. */
static inline int TestWithinDistanceOffsetDepth(ThreadVars *t,
DetectEngineThreadCtx *det_ctx,
MpmMatch *m, SigMatch *nsm)
{
//printf("test_nextsigmatch m:%p, nsm:%p\n", m,nsm);
if (nsm == NULL)
return 1;
DetectUricontentData *co = (DetectUricontentData *)nsm->ctx;
MpmMatch *nm = det_ctx->mtcu.match[co->id].top;
for (; nm; nm = nm->next) {
SCLogDebug("(nm->offset+1) %" PRIu32 ", (m->offset+1) %" PRIu32 "",
(nm->offset+1), (m->offset+1));
if ((co->within == 0 || (co->within &&
((nm->offset+1) > (m->offset+1)) &&
((nm->offset+1) - (m->offset+1) <= co->within))))
{
SCLogDebug("WITHIN (nm->offset+1) %" PRIu32 ", (m->offset+1) "
"%" PRIu32 "", (nm->offset+1), (m->offset+1));
if (co->distance == 0 || (co->distance &&
((nm->offset+1) > (m->offset+1)) &&
((nm->offset+1) - (m->offset+1) >= co->distance)))
{
if (TestOffsetDepth(nm, co) == 1) {
SCLogDebug("DISTANCE (nm->offset+1) %" PRIu32 ", "
"(m->offset+1) %" PRIu32 "", (nm->offset+1),
(m->offset+1));
return TestWithinDistanceOffsetDepth(t, det_ctx, nm,
nsm->next);
}
}
}
}
return 0;
}
static inline int DoDetectUricontent(ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, SigMatch *sm,
DetectUricontentData *co)
{
int ret = 0;
char match = 0;
/* Get the top match, we already know we have one. */
MpmMatch *m = det_ctx->mtcu.match[co->id].top;
/* if we have within or distance coming up next, check this match
* for distance and/or within and check the rest of this match
* chain as well. */
if ((co->flags & DETECT_URICONTENT_WITHIN_NEXT ||
co->flags & DETECT_URICONTENT_DISTANCE_NEXT) &&
det_ctx->de_checking_distancewithin == 0)
{
/* indicate to the detection engine the next sigmatch(es)
* are part of this match chain */
det_ctx->de_checking_distancewithin = 1;
for (; m != NULL; m = m->next) {
/* first check our match for offset and depth */
if (TestOffsetDepth(m, co) == 1) {
ret = TestWithinDistanceOffsetDepth(t, det_ctx, m, sm->next);
if (ret == 1) {
/* update payload offset */
det_ctx->payload_offset = m->offset;
match = 1;
break;
}
}
}
/* Okay, this is complicated... on the first match of a match chain,
* we do the whole match of that chain (a chain here means a number
* of consecutive content matches that relate to each other with
* 'within and/or 'distance options'). But we still get to the next
* sigmatches. We have already inspected this sigmatch, even for
* offset and depth. Since the fact that we get there means we have
* had a match, we return match here too.
*/
} else if (co->flags & DETECT_URICONTENT_WITHIN ||
co->flags & DETECT_URICONTENT_DISTANCE)
{
det_ctx->de_checking_distancewithin = 0;
match = 1;
/* Getting here means we are not in checking an within/distance chain.
* This means we can just inspect this content match on it's own. So
* Let's see if at least one of the matches within the offset and depth
* settings. If so, return a match.
*/
} else {
for (; m != NULL; m = m->next) {
ret = TestOffsetDepth(m,co);
if (ret == 1) {
/* update payload offset */
det_ctx->payload_offset = m->offset;
match = 1;
break;
}
}
}
return match;
}
/**
* \brief Checks if the packet sent as the argument, has a uricontent which
* has been provided in the signature
*
* \param t Pointer to the tv for this detection module instance
* \param det_ctx Pointer to the detection engine thread context
* \param p Pointer to the Packet currently being matched
* \param s Pointer to the Signature, the packet is being currently
* matched with
* \param m Pointer to the keyword_structure(SigMatch) from the above
* Signature, the Packet is being currently matched with
*
* \retval 1 if the Packet contents match; 0 no match
*/
int DetectUricontentMatch (ThreadVars *t, DetectEngineThreadCtx *det_ctx,
Packet *p, Signature *s, SigMatch *m)
{
SCEnter();
uint32_t len = 0;
DetectUricontentData *co = (DetectUricontentData *)m->ctx;
/* see if we had a match */
len = det_ctx->mtcu.match[co->id].len;
if (len == 0) {
SCLogDebug("We don't have match");
SCReturnInt(0);
}
#if 0
if (SCLogDebugEnabled()) {
printf("uricontent \'");
PrintRawUriFp(stdout, co->uricontent, co->uricontent_len);
printf("\' matched %" PRIu32 " time(s) at offsets: ", len);
MpmMatch *tmpm = NULL;
for (tmpm = det_ctx->mtcu.match[co->id].top; tmpm != NULL;
tmpm = tmpm->next)
{
printf("%" PRIu32 " ", tmpm->offset);
}
printf("\n");
}
#endif
SCReturnInt(DoDetectUricontent(t, det_ctx, p, m, co));
}
/**
* \brief Setup the detecturicontent keyword data from the string defined in
* the rule set.

@ -25,7 +25,6 @@ typedef struct DetectUricontentData_ {
/* prototypes */
void DetectUricontentRegister (void);
uint32_t DetectUricontentMaxId(DetectEngineCtx *);
void PktHttpUriFree(Packet *p);
uint32_t DetectUricontentInspectMpm(ThreadVars *th_v, DetectEngineThreadCtx *det_ctx, void *alstate);
#endif /* __DETECT_URICONTENT_H__ */

@ -81,6 +81,8 @@ const char * SCErrorToString(SCError err)
CASE_CODE (SC_ERR_WITHIN_MISSING_CONTENT);
CASE_CODE (SC_ERR_DEPTH_MISSING_CONTENT);
CASE_CODE (SC_ERR_OFFSET_MISSING_CONTENT);
CASE_CODE (SC_ERR_NOCASE_MISSING_PATTERN);
CASE_CODE (SC_ERR_RAWBYTES_MISSING_CONTENT);
CASE_CODE (SC_ERR_NO_URICONTENT_NEGATION);
CASE_CODE (SC_ERR_HASH_TABLE_INIT);
CASE_CODE (SC_ERR_STAT);

@ -104,6 +104,8 @@ typedef enum {
SC_ERR_OFFSET_MISSING_CONTENT,
SC_ERR_DEPTH_MISSING_CONTENT,
SC_ERR_BYTETEST_MISSING_CONTENT,
SC_ERR_NOCASE_MISSING_PATTERN,
SC_ERR_RAWBYTES_MISSING_CONTENT,
SC_ERR_NO_URICONTENT_NEGATION,
SC_ERR_HASH_TABLE_INIT,
SC_ERR_STAT,

@ -70,7 +70,7 @@ void MpmB2gRegister (void) {
mpm_table[MPM_B2G].Prepare = B2gPreparePatterns;
mpm_table[MPM_B2G].Scan = B2gScanWrap;
//mpm_table[MPM_B2G].Search = B2gSearchWrap;
mpm_table[MPM_B2G].Cleanup = MpmMatchCleanup;
//mpm_table[MPM_B2G].Cleanup = MpmMatchCleanup;
mpm_table[MPM_B2G].PrintCtx = B2gPrintInfo;
mpm_table[MPM_B2G].PrintThreadCtx = B2gPrintSearchStats;
mpm_table[MPM_B2G].RegisterUnittests = B2gRegisterTests;
@ -120,10 +120,6 @@ static inline void B2gEndMatchAppend(MpmCtx *mpm_ctx, B2gPattern *p,
SCLogDebug("m %p m->sig_id %"PRIu32"", m, m->sig_id);
}
p->em_len++;
if (p->flags & B2G_SCAN) {
//BUG_ON(p->em_len > 500);
}
}
#ifdef PRINTMATCH
@ -377,34 +373,9 @@ static inline int B2gAddPattern(MpmCtx *mpm_ctx, uint8_t *pat, uint16_t patlen,
if (scan) mpm_ctx->scan_pattern_cnt++;
mpm_ctx->pattern_cnt++;
if (scan) { /* SCAN */
if (mpm_ctx->scan_maxlen < patlen) mpm_ctx->scan_maxlen = patlen;
if (mpm_ctx->scan_minlen == 0) mpm_ctx->scan_minlen = patlen;
else if (mpm_ctx->scan_minlen > patlen) mpm_ctx->scan_minlen = patlen;
p->flags |= B2G_SCAN;
} else { /* SEARCH */
if (mpm_ctx->search_maxlen < patlen) mpm_ctx->search_maxlen = patlen;
if (mpm_ctx->search_minlen == 0) mpm_ctx->search_minlen = patlen;
else if (mpm_ctx->search_minlen > patlen) mpm_ctx->search_minlen = patlen;
}
#if 0
} else {
/* if we're reusing a pattern, check we need to check that it is a
* scan pattern if that is what we're adding. If so we set the pattern
* to be a scan pattern. */
//printf("reusing B2gAddPattern: ci \""); prt(p->ci,p->len);
//printf("\" cs \""); prt(p->cs,p->len);
//printf("\"\n");
if (scan) {
p->flags |= B2G_SCAN;
if (mpm_ctx->scan_maxlen < patlen) mpm_ctx->scan_maxlen = patlen;
if (mpm_ctx->scan_minlen == 0) mpm_ctx->scan_minlen = patlen;
else if (mpm_ctx->scan_minlen > patlen) mpm_ctx->scan_minlen = patlen;
}
#endif
if (mpm_ctx->scan_maxlen < patlen) mpm_ctx->scan_maxlen = patlen;
if (mpm_ctx->scan_minlen == 0) mpm_ctx->scan_minlen = patlen;
else if (mpm_ctx->scan_minlen > patlen) mpm_ctx->scan_minlen = patlen;
}
/* we need a match */
@ -477,12 +448,6 @@ static void B2gPrepareScanHash(MpmCtx *mpm_ctx) {
for (i = 0; i < mpm_ctx->pattern_cnt; i++)
{
/* ignore patterns that don't have the scan flag set */
if (!(ctx->parray[i]->flags & B2G_SCAN))
continue;
//BUG_ON(ctx->parray[i]->em_len > 500);
if(ctx->parray[i]->len == 1) {
idx8 = (uint8_t)ctx->parray[i]->ci[0];
if (ctx->scan_hash1[idx8].flags == 0) {
@ -604,9 +569,6 @@ int B2gBuildScanMatchArray(MpmCtx *mpm_ctx) {
/* fill the match array */
for (j = 0; j <= (ctx->scan_m - B2G_Q); j++) {
for (a = 0; a < mpm_ctx->pattern_cnt; a++) {
if (!(ctx->parray[a]->flags & B2G_SCAN))
continue;
if (ctx->parray[a]->len < ctx->scan_m)
continue;
@ -894,25 +856,6 @@ void B2gThreadInitCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, uint32_t ma
mpm_thread_ctx->memory_cnt++;
mpm_thread_ctx->memory_size += sizeof(B2gThreadCtx);
}
/* alloc an array with the size of _all_ keys in all instances.
* this is done so the detect engine won't have to care about
* what instance it's looking up in. The matches all have a
* unique id and is the array lookup key at the same time */
uint32_t keys = matchsize + 1;
if (keys > 0) {
mpm_thread_ctx->match = SCMalloc(keys * sizeof(MpmMatchBucket));
if (mpm_thread_ctx->match == NULL) {
SCLogError(SC_ERR_MEM_ALLOC, "memory alloc failed");
exit(1);
}
memset(mpm_thread_ctx->match, 0, keys * sizeof(MpmMatchBucket));
mpm_thread_ctx->memory_cnt++;
mpm_thread_ctx->memory_size += (keys * sizeof(MpmMatchBucket));
}
mpm_thread_ctx->matchsize = matchsize;
}
void B2gThreadDestroyCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx) {
@ -925,15 +868,6 @@ void B2gThreadDestroyCtx(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx) {
mpm_thread_ctx->memory_size -= sizeof(B2gThreadCtx);
SCFree(mpm_thread_ctx->ctx);
}
if (mpm_thread_ctx->match != NULL) {
mpm_thread_ctx->memory_cnt--;
mpm_thread_ctx->memory_size -= ((mpm_thread_ctx->matchsize + 1) * sizeof(MpmMatchBucket));
SCFree(mpm_thread_ctx->match);
}
MpmMatchFreeSpares(mpm_thread_ctx, mpm_thread_ctx->sparelist);
MpmMatchFreeSpares(mpm_thread_ctx, mpm_thread_ctx->qlist);
}
inline uint32_t B2gScanWrap(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQueue *pmq, uint8_t *buf, uint16_t buflen) {
@ -1013,12 +947,7 @@ uint32_t B2gScanBNDMq(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatc
#endif
COUNT(tctx->scan_stat_loop_match++);
MpmEndMatch *em;
for (em = p->em; em; em = em->next) {
SCLogDebug("em %p id %" PRIu32 "", em, em->id);
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id], j, p->len))
matches++;
}
matches += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, j, p->len);
} else {
COUNT(tctx->scan_stat_loop_no_match++);
}
@ -1032,12 +961,7 @@ uint32_t B2gScanBNDMq(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatc
#endif
COUNT(tctx->scan_stat_loop_match++);
MpmEndMatch *em;
for (em = p->em; em; em = em->next) {
SCLogDebug("em %p pid %" PRIu32 ", sid %"PRIu32"", em, em->id, em->sig_id);
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id], j, p->len))
matches++;
}
matches += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, j, p->len);
} else {
COUNT(tctx->scan_stat_loop_no_match++);
}
@ -1131,23 +1055,9 @@ uint32_t B2gScan(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQu
continue;
if (memcmp_lowercase(p->ci, buf+pos, p->len) == 0) {
#ifdef PRINTMATCH
printf("CI Exact match: \""); prt(p->ci, p->len); printf("\" ");
#endif
COUNT(tctx->scan_stat_loop_match++);
MpmEndMatch *em;
for (em = p->em; em; em = em->next) {
#ifdef PRINTMATCH
printf("(%" PRIu32 "%s) ", g_de_ctx->sig_array[em->sig_id]->id, em->flags & MPM_ENDMATCH_NOSEARCH ? "" : " (searchable)");
printf("em %p id %" PRIu32 "\n", em, em->id);
#endif
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id], pos, p->len))
matches++;
}
#ifdef PRINTMATCH
printf("\n");
#endif
matches += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, pos, p->len);
} else {
COUNT(tctx->scan_stat_loop_no_match++);
}
@ -1156,23 +1066,9 @@ printf("\n");
continue;
if (memcmp(p->cs, buf+pos, p->len) == 0) {
#ifdef PRINTMATCH
printf("CS Exact match: \""); prt(p->cs, p->len); printf("\" ");
#endif
COUNT(tctx->scan_stat_loop_match++);
MpmEndMatch *em;
for (em = p->em; em; em = em->next) {
#ifdef PRINTMATCH
printf("(%" PRIu32 "%s) ", g_de_ctx->sig_array[em->sig_id]->id, em->flags & MPM_ENDMATCH_NOSEARCH ? "" : " (searchable)");
printf("em %p id %" PRIu32 "\n", em, em->id);
#endif
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id], pos, p->len))
matches++;
}
#ifdef PRINTMATCH
printf("\n");
#endif
matches += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, pos, p->len);
} else {
COUNT(tctx->scan_stat_loop_no_match++);
}
@ -1200,7 +1096,7 @@ uint32_t B2gScan2(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
uint8_t *bufend = buf + buflen - 1;
uint32_t cnt = 0;
B2gPattern *p;
MpmEndMatch *em;
MpmEndMatch *em;
B2gHashItem *thi, *hi;
if (buflen < 2)
@ -1218,19 +1114,11 @@ uint32_t B2gScan2(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
if (p->flags & B2G_NOCASE) {
if (h8 == p->ci[0]) {
//printf("CI Exact match: "); prt(p->ci, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
cnt++;
}
cnt += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, (buf+1 - bufmin), p->len);
}
} else {
if (*buf == p->cs[0]) {
//printf("CS Exact match: "); prt(p->cs, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
cnt++;
}
cnt += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, (buf+1 - bufmin), p->len);
}
}
}
@ -1247,7 +1135,7 @@ uint32_t B2gScan2(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
if (h8 == p->ci[0] && u8_tolower(*(buf+1)) == p->ci[1]) {
//printf("CI Exact match: "); prt(p->ci, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
if (MpmVerifyMatch(mpm_thread_ctx, pmq, em, (buf+1 - bufmin), p->len))
cnt++;
}
}
@ -1255,7 +1143,7 @@ uint32_t B2gScan2(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
if (*buf == p->cs[0] && *(buf+1) == p->cs[1]) {
//printf("CS Exact match: "); prt(p->cs, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
if (MpmVerifyMatch(mpm_thread_ctx, pmq, em, (buf+1 - bufmin), p->len))
cnt++;
}
}
@ -1283,7 +1171,6 @@ uint32_t B2gScan1(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
uint8_t *bufend = buf + buflen - 1;
uint32_t cnt = 0;
B2gPattern *p;
MpmEndMatch *em;
B2gHashItem *thi, *hi;
if (buflen == 0)
@ -1304,19 +1191,11 @@ uint32_t B2gScan1(MpmCtx *mpm_ctx, MpmThreadCtx *mpm_thread_ctx, PatternMatcherQ
if (p->flags & B2G_NOCASE) {
if (u8_tolower(*buf) == p->ci[0]) {
//printf("CI Exact match: "); prt(p->ci, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
cnt++;
}
cnt += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, (buf+1 - bufmin), p->len);
}
} else {
if (*buf == p->cs[0]) {
//printf("CS Exact match: "); prt(p->cs, p->len); printf(" in buf "); prt(buf, p->len);printf(" (B2gSearch1)\n");
for (em = p->em; em; em = em->next) {
if (MpmMatchAppend(mpm_thread_ctx, pmq, em, &mpm_thread_ctx->match[em->id],(buf+1 - bufmin), p->len))
cnt++;
}
cnt += MpmVerifyMatch(mpm_thread_ctx, pmq, p->em, (buf+1 - bufmin), p->len);
}
}
}
@ -1478,8 +1357,6 @@ static int B2gTestScan01 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghjiklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1505,8 +1382,6 @@ static int B2gTestScan02 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghjiklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 0)
result = 1;
else
@ -1534,8 +1409,6 @@ static int B2gTestScan03 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghjiklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 3)
result = 1;
else
@ -1564,8 +1437,6 @@ static int B2gTestScan04 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghjiklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1594,8 +1465,6 @@ static int B2gTestScan05 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghjiklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 3)
result = 1;
else
@ -1621,8 +1490,6 @@ static int B2gTestScan06 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcd", 4);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1654,8 +1521,6 @@ static int B2gTestScan07 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 135)
result = 1;
else
@ -1681,8 +1546,6 @@ static int B2gTestScan08 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"a", 1);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 0)
result = 1;
else
@ -1708,8 +1571,6 @@ static int B2gTestScan09 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"ab", 2);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1740,8 +1601,6 @@ static int B2gTestScan10 (void) {
"01234567890123456789012345678901234567890123456789";
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)buf, strlen(buf));
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1768,8 +1627,6 @@ static int B2gTestScan11 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 2)
result = 1;
else
@ -1796,8 +1653,6 @@ static int B2gTestScan12 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyz", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 2)
result = 1;
else
@ -1823,8 +1678,6 @@ static int B2gTestScan13 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyzABCD", 30);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1850,8 +1703,6 @@ static int B2gTestScan14 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyzABCDE", 31);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1877,8 +1728,6 @@ static int B2gTestScan15 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyzABCDEF", 32);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1904,8 +1753,6 @@ static int B2gTestScan16 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyzABC", 29);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1931,8 +1778,6 @@ static int B2gTestScan17 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcdefghijklmnopqrstuvwxyzAB", 28);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1958,8 +1803,6 @@ static int B2gTestScan18 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"abcde""fghij""klmno""pqrst""uvwxy""z", 26);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -1985,8 +1828,6 @@ static int B2gTestScan19 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 30);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -2014,8 +1855,6 @@ static int B2gTestScan20 (void) {
//uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 32);
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AAAAA""AA", 32);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else
@ -2041,8 +1880,6 @@ static int B2gTestScan21 (void) {
uint32_t cnt = ctx->Scan(&mpm_ctx, &mpm_thread_ctx, NULL, (uint8_t *)"AA", 2);
MpmMatchCleanup(&mpm_thread_ctx);
if (cnt == 1)
result = 1;
else

@ -5,7 +5,6 @@
#include "util-bloomfilter.h"
#define B2G_NOCASE 0x01
#define B2G_SCAN 0x02
//#define B2G_HASHSHIFT 8
//#define B2G_HASHSHIFT 7

File diff suppressed because it is too large Load Diff

@ -5,7 +5,6 @@
#include "util-bloomfilter.h"
#define B3G_NOCASE 0x01
#define B3G_SCAN 0x02
//#define B3G_HASHSHIFT 8
//#define B3G_HASHSHIFT 7
@ -26,9 +25,6 @@
//#define B3G_SCANFUNC B3gScan
#define B3G_SCANFUNC B3gScanBNDMq
//#define B3G_SEARCHFUNC B3gSearch
#define B3G_SEARCHFUNC B3gSearchBNDMq
//#define B3G_COUNTERS
typedef struct B3gPattern_ {
@ -51,21 +47,14 @@ typedef struct B3gCtx_ {
B3gPattern **init_hash;
B3G_TYPE scan_m;
B3G_TYPE search_m;
B3G_TYPE *scan_B3G;
B3G_TYPE *search_B3G;
uint8_t scan_s0;
uint8_t search_s0;
uint16_t scan_1_pat_cnt;
uint16_t scan_2_pat_cnt;
uint16_t scan_x_pat_cnt;
uint16_t search_1_pat_cnt;
uint16_t search_2_pat_cnt;
uint16_t search_x_pat_cnt;
uint32_t scan_hash_size;
B3gHashItem **scan_hash;
BloomFilter **scan_bloom;
@ -75,24 +64,11 @@ typedef struct B3gCtx_ {
B3gHashItem scan_hash1[256];
B3gHashItem **scan_hash2;
uint32_t search_hash_size;
B3gHashItem **search_hash;
BloomFilter **search_bloom;
uint8_t *search_pminlen; /* array containing the minimal length
of the patters in a hash bucket. Used
for the BloomFilter. */
B3gHashItem search_hash1[256];
B3gHashItem **search_hash2;
uint32_t (*Scan)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
uint32_t (*Search)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* we store our own multi byte scan ptr here for B3gSearch1 */
uint32_t (*MBScan2)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
uint32_t (*MBScan)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* we store our own multi byte search ptr here for B3gSearch1 */
uint32_t (*MBSearch2)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
uint32_t (*MBSearch)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* pattern arrays */
B3gPattern **parray;
@ -112,17 +88,10 @@ typedef struct B3gThreadCtx_ {
uint32_t scan_stat_loop_no_match;
uint32_t scan_stat_num_shift;
uint32_t scan_stat_total_shift;
uint32_t search_stat_d0;
uint32_t search_stat_loop_match;
uint32_t search_stat_loop_no_match;
uint32_t search_stat_num_shift;
uint32_t search_stat_total_shift;
#endif /* B3G_COUNTERS */
} B3gThreadCtx;
void MpmB3gRegister(void);
#endif

File diff suppressed because it is too large Load Diff

@ -7,7 +7,6 @@
#include "util-bloomfilter.h"
#define WUMANBER_NOCASE 0x01
#define WUMANBER_SCAN 0x02
//#define WUMANBER_COUNTERS
@ -33,7 +32,6 @@ typedef struct WmCtx_ {
WmPattern **init_hash;
uint16_t scan_shiftlen;
uint16_t search_shiftlen;
uint32_t scan_hash_size;
WmHashItem **scan_hash;
@ -42,25 +40,17 @@ typedef struct WmCtx_ {
of the patters in a hash bucket. Used
for the BloomFilter. */
WmHashItem scan_hash1[256];
uint32_t search_hash_size;
WmHashItem **search_hash;
WmHashItem search_hash1[256];
/* we store our own scan ptr here for WmSearch1 */
uint32_t (*Scan)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* we store our own search ptr here for WmSearch1 */
uint32_t (*Search)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* we store our own multi byte scan ptr here for WmSearch1 */
uint32_t (*MBScan)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* we store our own multi byte search ptr here for WmSearch1 */
uint32_t (*MBSearch)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
/* pattern arrays */
WmPattern **parray;
/* only used for multibyte pattern search */
uint16_t *scan_shifttable;
uint16_t *search_shifttable;
} WmCtx;
typedef struct WmThreadCtx_ {
@ -74,12 +64,6 @@ typedef struct WmThreadCtx_ {
uint32_t scan_stat_loop_no_match;
uint32_t scan_stat_num_shift;
uint32_t scan_stat_total_shift;
uint32_t search_stat_shift_null;
uint32_t search_stat_loop_match;
uint32_t search_stat_loop_no_match;
uint32_t search_stat_num_shift;
uint32_t search_stat_total_shift;
#endif /* WUMANBER_COUNTERS */
} WmThreadCtx;

@ -89,157 +89,58 @@ void PmqFree(PatternMatcherQueue *pmq) {
SCFree(pmq);
}
/* cleanup list with all matches
/** \brief Verify and store a match
*
* used at search runtime (or actually once per search) */
void
MpmMatchCleanup(MpmThreadCtx *thread_ctx) {
SCLogDebug("mem %" PRIu32 "", thread_ctx->memory_size);
MpmMatch *nxt;
MpmMatch *m = thread_ctx->qlist;
while (m != NULL) {
BUG_ON(m == m->qnext);
nxt = m->qnext;
/* clear the bucket */
m->mb->top = NULL;
m->mb->bot = NULL;
m->mb->len = 0;
thread_ctx->qlist = m->qnext;
/* add to the spare list */
if (thread_ctx->sparelist == NULL) {
thread_ctx->sparelist = m;
m->qnext = NULL;
} else {
m->qnext = thread_ctx->sparelist;
thread_ctx->sparelist = m;
}
m = nxt;
}
}
/** \brief allocate a match
* used at search runtime
*
* used at search runtime */
inline MpmMatch *
MpmMatchAlloc(MpmThreadCtx *thread_ctx) {
MpmMatch *m = SCMalloc(sizeof(MpmMatch));
if (m == NULL)
return NULL;
thread_ctx->memory_cnt++;
thread_ctx->memory_size += sizeof(MpmMatch);
m->offset = 0;
m->next = NULL;
m->qnext = NULL;
m->mb = NULL;
return m;
}
/** \brief append a match to a bucket
* \param thread_ctx mpm thread ctx
* \param pmq storage for match results
* \param list end match to check against (entire list will be checked)
* \param offset match offset in the buffer
* \param patlen length of the pattern we're checking
*
* used at search runtime */
* \retval 0 no match after all
* \retval 1 (new) match
*/
inline int
MpmMatchAppend(MpmThreadCtx *thread_ctx, PatternMatcherQueue *pmq, MpmEndMatch *em, MpmMatchBucket *mb, uint16_t offset, uint16_t patlen)
MpmVerifyMatch(MpmThreadCtx *thread_ctx, PatternMatcherQueue *pmq, MpmEndMatch *list, uint16_t offset, uint16_t patlen)
{
/* don't bother looking at sigs that didn't match
* when we scanned. There's no matching anyway. */
if (pmq != NULL && pmq->mode == PMQ_MODE_SEARCH) {
if (!(pmq->sig_bitarray[(em->sig_id / 8)] & (1<<(em->sig_id % 8))))
return 0;
}
/* if our endmatch is set to a single match being enough,
we're not going to add more if we already have one */
if (em->flags & MPM_ENDMATCH_SINGLE && mb->len)
return 0;
/* check offset */
if (offset < em->offset)
return 0;
/* check depth */
if (em->depth && (offset+patlen) > em->depth)
return 0;
#if 0
/* ok all checks passed, now append the match */
MpmMatch *m;
/* pull a match from the spare list */
if (thread_ctx->sparelist != NULL) {
m = thread_ctx->sparelist;
thread_ctx->sparelist = m->qnext;
} else {
m = MpmMatchAlloc(thread_ctx);
if (m == NULL)
return 0;
}
m->offset = offset;
m->mb = mb;
m->next = NULL;
m->qnext = NULL;
/* append to the mb list */
if (mb->bot == NULL) { /* empty list */
mb->top = m;
mb->bot = m;
} else { /* more items in list */
mb->bot->next = m;
mb->bot = m;
}
mb->len++;
/* put in the queue list */
if (thread_ctx->qlist == NULL) { /* empty list */
thread_ctx->qlist = m;
} else { /* more items in list */
m->qnext = thread_ctx->qlist;
thread_ctx->qlist = m;
}
SCEnter();
BUG_ON(m == m->qnext);
#endif
if (pmq != NULL) {
/* make sure we only append a sig with a matching pattern once,
* so we won't inspect it more than once. For this we keep a
* bitarray of sig internal id's and flag each sig that matched */
if (!(pmq->sig_bitarray[(em->sig_id / 8)] & (1<<(em->sig_id % 8)))) {
/* flag this sig_id as being added now */
pmq->sig_bitarray[(em->sig_id / 8)] |= (1<<(em->sig_id % 8));
/* append the sig_id to the array with matches */
pmq->sig_id_array[pmq->sig_id_array_cnt] = em->sig_id;
pmq->sig_id_array_cnt++;
MpmEndMatch *em = list;
int ret = 0;
for ( ; em != NULL; em = em->next) {
/* check offset */
if (offset < em->offset)
continue;
/* check depth */
if (em->depth && (offset+patlen) > em->depth)
continue;
if (pmq != NULL) {
/* make sure we only append a sig with a matching pattern once,
* so we won't inspect it more than once. For this we keep a
* bitarray of sig internal id's and flag each sig that matched */
if (!(pmq->sig_bitarray[(em->sig_id / 8)] & (1<<(em->sig_id % 8)))) {
/* flag this sig_id as being added now */
pmq->sig_bitarray[(em->sig_id / 8)] |= (1<<(em->sig_id % 8));
/* append the sig_id to the array with matches */
pmq->sig_id_array[pmq->sig_id_array_cnt] = em->sig_id;
pmq->sig_id_array_cnt++;
}
/* nosearch flag */
if (!(em->flags & MPM_ENDMATCH_NOSEARCH)) {
pmq->searchable++;
}
}
/* nosearch flag */
if (pmq->mode == PMQ_MODE_SCAN && !(em->flags & MPM_ENDMATCH_NOSEARCH)) {
pmq->searchable++;
}
ret++;
}
// SCLogDebug("len %" PRIu32 " (offset %" PRIu32 ")", mb->len, m->offset);
return 1;
}
void MpmMatchFree(MpmThreadCtx *ctx, MpmMatch *m) {
ctx->memory_cnt--;
ctx->memory_size -= sizeof(MpmMatch);
SCFree(m);
}
void MpmMatchFreeSpares(MpmThreadCtx *mpm_ctx, MpmMatch *m) {
while(m) {
MpmMatch *tm = m->qnext;
MpmMatchFree(mpm_ctx, m);
m = tm;
}
SCReturnInt(ret);
}
/* allocate an endmatch

@ -52,18 +52,7 @@ typedef struct MpmEndMatch_ {
uint8_t flags;
} MpmEndMatch;
typedef struct MpmMatch_ {
struct MpmMatch_ *next; /**< match list -- used to connect a match to a
* pattern id. */
struct MpmMatch_ *qnext; /**< queue list -- used to cleanup all matches
* after the inspection. */
struct MpmMatchBucket_ *mb; /**< pointer back to the bucket */
uint16_t offset; /**< offset of this match in the search buffer */
} MpmMatch;
typedef struct MpmMatchBucket_ {
MpmMatch *top;
MpmMatch *bot;
uint32_t len;
} MpmMatchBucket;
@ -72,19 +61,8 @@ typedef struct MpmThreadCtx_ {
uint32_t memory_cnt;
uint32_t memory_size;
MpmMatchBucket *match;
/* list of all matches */
MpmMatch *qlist;
/* spare list */
MpmMatch *sparelist;
uint32_t matchsize;
} MpmThreadCtx;
#define PMQ_MODE_SCAN 0
#define PMQ_MODE_SEARCH 1
/** \brief helper structure for the pattern matcher engine. The Pattern Matcher
* thread has this and passes a pointer to it to the pattern matcher.
* The actual pattern matcher will fill the structure. */
@ -94,9 +72,8 @@ typedef struct PatternMatcherQueue_ {
futher by the detection engine. */
uint32_t sig_id_array_cnt;
uint8_t *sig_bitarray;
char mode; /* 0: scan, 1: search */
uint32_t searchable; /* counter of the number of matches that
require a search-followup */
require a search-followup */
} PatternMatcherQueue;
typedef struct MpmCtx_ {
@ -114,8 +91,6 @@ typedef struct MpmCtx_ {
uint16_t scan_minlen;
uint16_t scan_maxlen;
uint16_t search_minlen;
uint16_t search_maxlen;
} MpmCtx;
typedef struct MpmTableElmt_ {
@ -127,11 +102,11 @@ typedef struct MpmTableElmt_ {
void (*DestroyThreadCtx)(struct MpmCtx_ *, struct MpmThreadCtx_ *);
int (*AddScanPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t, uint8_t);
int (*AddScanPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t, uint8_t);
int (*AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t);
int (*AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t);
// int (*AddPattern)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t);
// int (*AddPatternNocase)(struct MpmCtx_ *, uint8_t *, uint16_t, uint16_t, uint16_t, uint32_t, uint32_t);
int (*Prepare)(struct MpmCtx_ *);
uint32_t (*Scan)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
uint32_t (*Search)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
// uint32_t (*Search)(struct MpmCtx_ *, struct MpmThreadCtx_ *, PatternMatcherQueue *, uint8_t *, uint16_t);
void (*Cleanup)(struct MpmThreadCtx_ *);
void (*PrintCtx)(struct MpmCtx_ *);
void (*PrintThreadCtx)(struct MpmThreadCtx_ *);
@ -146,12 +121,10 @@ void PmqReset(PatternMatcherQueue *);
void PmqCleanup(PatternMatcherQueue *);
void PmqFree(PatternMatcherQueue *);
void MpmMatchCleanup(MpmThreadCtx *);
MpmMatch *MpmMatchAlloc(MpmThreadCtx *);
int MpmMatchAppend(MpmThreadCtx *, PatternMatcherQueue *, MpmEndMatch *, MpmMatchBucket *, uint16_t, uint16_t);
int MpmVerifyMatch(MpmThreadCtx *, PatternMatcherQueue *, MpmEndMatch *, uint16_t, uint16_t);
MpmEndMatch *MpmAllocEndMatch (MpmCtx *);
void MpmEndMatchFreeAll(MpmCtx *mpm_ctx, MpmEndMatch *em);
void MpmMatchFreeSpares(MpmThreadCtx *mpm_ctx, MpmMatch *m);
void MpmTableSetup(void);
void MpmRegisterTests(void);

Loading…
Cancel
Save