From 4284276b11c71fe13312edbc925b3b85e3e50da5 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Thu, 21 Jan 2010 14:43:26 +0100 Subject: [PATCH] Merge applayer detect function into normal match function. Should speed up detection. --- src/detect-content.c | 6 - src/detect-parse.c | 46 +++++++- src/detect-uricontent.c | 2 - src/detect.c | 252 ++++++++-------------------------------- 4 files changed, 90 insertions(+), 216 deletions(-) diff --git a/src/detect-content.c b/src/detect-content.c index 483a0dd704..f205ca0bc9 100644 --- a/src/detect-content.c +++ b/src/detect-content.c @@ -1465,8 +1465,6 @@ int DetectContentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char aux->id = de_ctx->content_max_id; de_ctx->content_max_id++; - s->flags |= SIG_FLAG_MPM; - /** We need to setup the modifiers for the chunks respect * the last chunk installed inmediatelly before * so do the propagation from the first one @@ -1507,10 +1505,6 @@ int DetectContentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, char cd->id = de_ctx->content_max_id; de_ctx->content_max_id++; - s->flags |= SIG_FLAG_MPM; - if (cd->negated == 1) - s->flags |= SIG_FLAG_MPM_NEGCONTENT; - DetectContentPrint(cd); } diff --git a/src/detect-parse.c b/src/detect-parse.c index 7cff5c1f59..6de5a5239f 100644 --- a/src/detect-parse.c +++ b/src/detect-parse.c @@ -617,6 +617,28 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { sig->num = de_ctx->signum; de_ctx->signum++; + /* see if need to set the SIG_FLAG_MPM flag */ + SigMatch *sm; + for (sm = sig->match; sm != NULL; sm = sm->next) { + if (sm->type == DETECT_CONTENT) { + DetectContentData *cd = (DetectContentData *)sm->ctx; + if (cd == NULL) + continue; + + sig->flags |= SIG_FLAG_MPM; + + if (cd->negated == 1) { + sig->flags |= SIG_FLAG_MPM_NEGCONTENT; + } + } else if (sm->type == DETECT_URICONTENT) { + DetectUricontentData *ud = (DetectUricontentData *)sm->ctx; + if (ud == NULL) + continue; + + sig->flags |= SIG_FLAG_MPM; + } + } + /* set mpm_content_len */ /* determine the length of the longest pattern in the sig */ @@ -624,7 +646,6 @@ Signature *SigInit(DetectEngineCtx *de_ctx, char *sigstr) { sig->mpm_content_maxlen = 0; sig->mpm_uricontent_maxlen = 0; - SigMatch *sm; for (sm = sig->match; sm != NULL; sm = sm->next) { if (sm->type == DETECT_CONTENT) { DetectContentData *cd = (DetectContentData *)sm->ctx; @@ -705,6 +726,28 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { sig->num = de_ctx->signum; de_ctx->signum++; + /* see if need to set the SIG_FLAG_MPM flag */ + SigMatch *sm; + for (sm = sig->match; sm != NULL; sm = sm->next) { + if (sm->type == DETECT_CONTENT) { + DetectContentData *cd = (DetectContentData *)sm->ctx; + if (cd == NULL) + continue; + + sig->flags |= SIG_FLAG_MPM; + + if (cd->negated == 1) { + sig->flags |= SIG_FLAG_MPM_NEGCONTENT; + } + } else if (sm->type == DETECT_URICONTENT) { + DetectUricontentData *ud = (DetectUricontentData *)sm->ctx; + if (ud == NULL) + continue; + + sig->flags |= SIG_FLAG_MPM; + } + } + /* set mpm_content_len */ /* determine the length of the longest pattern in the sig */ @@ -712,7 +755,6 @@ Signature *SigInitReal(DetectEngineCtx *de_ctx, char *sigstr) { sig->mpm_content_maxlen = 0; sig->mpm_uricontent_maxlen = 0; - SigMatch *sm; for (sm = sig->match; sm != NULL; sm = sm->next) { if (sm->type == DETECT_CONTENT) { DetectContentData *cd = (DetectContentData *)sm->ctx; diff --git a/src/detect-uricontent.c b/src/detect-uricontent.c index dc71ba7a47..ba1f1cd50c 100644 --- a/src/detect-uricontent.c +++ b/src/detect-uricontent.c @@ -340,8 +340,6 @@ int DetectUricontentSetup (DetectEngineCtx *de_ctx, Signature *s, SigMatch *m, c cd->id = de_ctx->uricontent_max_id; de_ctx->uricontent_max_id++; - s->flags |= SIG_FLAG_MPM; - if (dubbed) free(str); return 0; diff --git a/src/detect.c b/src/detect.c index 3dcc849469..0d8b1089f4 100644 --- a/src/detect.c +++ b/src/detect.c @@ -509,199 +509,40 @@ inline SigGroupHead *SigMatchSignaturesGetSgh(ThreadVars *th_v, DetectEngineCtx SCReturnPtr(sgh, "SigGroupHead"); } -/** \brief application layer detection - * - * \param sgh signature group head for this proto/addrs/ports - * \warning Make sure to exit this function using "goto end" if the flow - * use_cnt has already been incremented. - */ -static int SigMatchSignaturesAppLayer(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, SigGroupHead *sgh, Packet *p) -{ - SCEnter(); - - int match = 0, fmatch = 0; - Signature *s = NULL; - SigMatch *sm = NULL; - uint32_t idx, sig; - uint8_t flags = 0; - uint16_t alproto = ALPROTO_UNKNOWN; - void *alstate = NULL; - - /* if we didn't get a sig group head, we - * have nothing to do.... */ - if (sgh == NULL) { - SCLogDebug("no sgh to detect"); - SCReturnInt(0); - } - - /* grab the protocol state we will detect on */ - if (p->flow == NULL) { - SCReturnInt(0); - } - - SCMutexLock(&p->flow->m); - p->flow->use_cnt++; - alstate = AppLayerGetProtoStateFromPacket(p); - alproto = AppLayerGetProtoFromPacket(p); - SCMutexUnlock(&p->flow->m); - - if (alproto == ALPROTO_UNKNOWN) { - SCLogDebug("application layer state proto still unknown"); - goto end; - } - if (alstate == NULL) { - SCLogDebug("no application layer state to detect"); - goto end; - } - - if (p->flowflags & FLOW_PKT_TOSERVER) { - flags |= STREAM_TOSERVER; - } else if (p->flowflags & FLOW_PKT_TOCLIENT) { - flags |= STREAM_TOCLIENT; - } - - SCLogDebug("p->flowflags 0x%02X flags 0x%02X", p->flowflags, flags); - - /* inspect the sigs against the packet */ - for (idx = 0; idx < sgh->sig_cnt; idx++) { - sig = sgh->match_array[idx]; - s = de_ctx->sig_array[sig]; - - SCLogDebug("s->id %"PRIu32"", s->id); - - /* only inspect app layer sigs here */ - if (!(s->flags & SIG_FLAG_APPLAYER)) - continue; - - /* filter out the sigs that inspects the payload, if packet - no payload inspection flag is set*/ - if ((p->flags & PKT_NOPAYLOAD_INSPECTION) && (s->flags & SIG_FLAG_PAYLOAD)) { - continue; - } - - /* check the source & dst port in the sig */ - if (p->proto == IPPROTO_TCP || p->proto == IPPROTO_UDP) { - if (!(s->flags & SIG_FLAG_DP_ANY)) { - DetectPort *dport = DetectPortLookupGroup(s->dp,p->dp); - if (dport == NULL) - continue; - - } - if (!(s->flags & SIG_FLAG_SP_ANY)) { - DetectPort *sport = DetectPortLookupGroup(s->sp,p->sp); - if (sport == NULL) - continue; - } - } - - /* check the source address */ - if (!(s->flags & SIG_FLAG_SRC_ANY)) { - DetectAddress *saddr = DetectAddressLookupInHead(&s->src,&p->src); - if (saddr == NULL) - continue; - } - /* check the destination address */ - if (!(s->flags & SIG_FLAG_DST_ANY)) { - DetectAddress *daddr = DetectAddressLookupInHead(&s->dst,&p->dst); - if (daddr == NULL) - continue; - } - - /* if we don't have sigmatches at this point we're a match - * XXX VJ can we ever get here? Applayer inspection w/o sigmatches */ - if (s->match == NULL) { - fmatch = 1; - if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertHandle(de_ctx,s,p); - - /* set verdict on packet */ - p->action = s->action; - } - } else { - /* reset pkt ptr and offset */ - det_ctx->pkt_ptr = NULL; - det_ctx->pkt_off = 0; - - sm = s->match; - while (sm) { - if (sigmatch_table[sm->type].AppLayerMatch == NULL) { - /* if no match function we assume this sm is a match */ - match = 1; - SCLogDebug("no app layer match function, sigmatch is (pkt)Match only"); - } else if (sigmatch_table[sm->type].alproto != alproto) { - match = 0; - SCLogDebug("app layer match function %s is for proto " - "%"PRIu16", got proto %"PRIu16"", - sigmatch_table[sm->type].name, - sigmatch_table[sm->type].alproto, alproto); - } else { - match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm); - SCLogDebug("sigmatch AppLayerMatch function returned match %"PRIu32"", match); - } - - if (match) { - /* okay, try the next match */ - sm = sm->next; - - /* only if the last matched as well, we have a hit */ - if (sm == NULL) { - fmatch = 1; - - SCLogDebug("DE : sig %" PRIu32 " matched", s->id); - - if (!(s->flags & SIG_FLAG_NOALERT)) { - /* if the sig also has a packet portion see if that has matched already */ - if (s->flags & SIG_FLAG_PACKET) { - SCLogDebug("checking sid %"PRIu32"", s->id); - - if (FlowAlertSidIsset(p->flow, s->id) ) { - SCLogDebug("flowalertsid sid %"PRIu32", isset", s->id); - - PacketAlertHandle(de_ctx,s,p); - - /* set verdict on packet */ - p->action = s->action; - } - } else { - PacketAlertHandle(de_ctx,s,p); - - /* set verdict on packet */ - p->action = s->action; - } - } - } - } else { - /* done with this sig */ - sm = NULL; - } - } - } - } - -end: - SCMutexLock(&p->flow->m); - p->flow->use_cnt--; - SCMutexUnlock(&p->flow->m); - SCReturnInt(fmatch); -} - int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, Packet *p) { int match = 0, fmatch = 0; Signature *s = NULL; SigMatch *sm = NULL; uint32_t idx,sig; + uint16_t alproto = ALPROTO_UNKNOWN; + void *alstate = NULL; + uint8_t flags = 0; SCEnter(); det_ctx->pkts++; - SCLogDebug("p->flowflags 0x%02x", p->flowflags); + /* grab the protocol state we will detect on */ + if (p->flow != NULL) { + SCMutexLock(&p->flow->m); + p->flow->use_cnt++; + alstate = AppLayerGetProtoStateFromPacket(p); + alproto = AppLayerGetProtoFromPacket(p); + SCMutexUnlock(&p->flow->m); + + if (p->flowflags & FLOW_PKT_TOSERVER) { + flags |= STREAM_TOSERVER; + } else if (p->flowflags & FLOW_PKT_TOCLIENT) { + flags |= STREAM_TOCLIENT; + } + SCLogDebug("p->flowflags 0x%02x", p->flowflags); + } /* match the ip only signatures */ if ((p->flowflags & FLOW_PKT_TOSERVER && !(p->flowflags & FLOW_PKT_TOSERVER_IPONLY_SET)) || (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) { - SCLogDebug("testing against \"ip-only\""); + SCLogDebug("testing against \"ip-only\" signatures"); IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); /* save in the flow that we scanned this direction... locking is @@ -718,7 +559,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh * have nothing to do.... */ if (det_ctx->sgh == NULL) { SCLogDebug("no sgh for this packet, nothing to match against"); - SCReturnInt(0); + goto end; } if (p->payload_len > 0 && det_ctx->sgh->mpm_ctx != NULL && !(p->flags & PKT_NOPAYLOAD_INSPECTION)) { @@ -772,12 +613,6 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh continue; } - /* don't inspect app layer only sigs here */ - if (!(s->flags & SIG_FLAG_PACKET)) { - SCLogDebug("sig id %"PRIu32" is app layer inspecting only", s->id); - continue; - } - /* filter out sigs that want pattern matches, but * have no matches */ if (!(det_ctx->pmq.sig_bitarray[(sig / 8)] & (1<<(sig % 8))) && @@ -849,12 +684,17 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh do { sm = s->match; while (sm) { - if (sigmatch_table[sm->type].Match == NULL) { - /* if no match function we assume this sm is a match */ - match = 1; - } else { + match = 0; + + /* app layer match has preference */ + if (sigmatch_table[sm->type].AppLayerMatch != NULL && + alproto == sigmatch_table[sm->type].alproto && + alstate != NULL) { + match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm); + } else if (sigmatch_table[sm->type].Match != NULL) { match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm); } + if (match) { /* okay, try the next match */ sm = sm->next; @@ -888,12 +728,17 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh SCLogDebug("running match functions, sm %p", sm); while (sm) { - /* if this sm has no Match function we assume it's a match */ - if (sigmatch_table[sm->type].Match == NULL) { - match = 1; - } else { + match = 0; + + /* app layer match has preference */ + if (sigmatch_table[sm->type].AppLayerMatch != NULL && + alproto == sigmatch_table[sm->type].alproto && + alstate != NULL) { + match = sigmatch_table[sm->type].AppLayerMatch(th_v, det_ctx, p->flow, flags, alstate, s, sm); + } else if (sigmatch_table[sm->type].Match != NULL) { match = sigmatch_table[sm->type].Match(th_v, det_ctx, p, s, sm); } + if (match) { /* okay, try the next match */ sm = sm->next; @@ -902,18 +747,12 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (sm == NULL) { fmatch = 1; if (!(s->flags & SIG_FLAG_NOALERT)) { - SCLogDebug("sig matched, applayer flag set ? %s", s->flags & SIG_FLAG_APPLAYER ? "yes":"no"); /* set flowbit for this match */ - if (s->flags & SIG_FLAG_APPLAYER) { - SCLogDebug("setting flowalertsid for sig %"PRIu32"", s->id); - FlowAlertSidSet(p->flow, s->id); - } else { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx,s,p); - /* set verdict on packet */ - p->action = s->action; - } + /* set verdict on packet */ + p->action = s->action; } } } else { @@ -929,10 +768,11 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh /* cleanup pkt specific part of the patternmatcher */ PacketPatternCleanup(th_v, det_ctx); - SCLogDebug("Running Application Layer match functions, sm %p", sm); - match = SigMatchSignaturesAppLayer(th_v, de_ctx, det_ctx, det_ctx->sgh, p); - if (match > 0) { - fmatch = 1; +end: + if (p->flow != NULL) { + SCMutexLock(&p->flow->m); + p->flow->use_cnt--; + SCMutexUnlock(&p->flow->m); } SCReturnInt(fmatch);