From ee3c054b05b5fb08e3e2e817b780b16bb1952bb7 Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Fri, 16 Apr 2010 12:13:15 +0530 Subject: [PATCH] fix for bug 115 --- src/counters.c | 36 ++++++++++++++++++++ src/counters.h | 1 + src/detect-engine-iponly.c | 6 ++- src/detect-engine-iponly.h | 4 ++- src/detect-engine-threshold.c | 29 +++++++++------- src/detect-engine-threshold.h | 6 ++- src/detect-engine.c | 3 ++ src/detect.c | 73 +++++++++++++++++++++++++++++++++++++--- src/detect.h | 7 +++- 9 files changed, 139 insertions(+), 26 deletions(-) diff --git a/src/counters.c b/src/counters.c index 5fb41f7..6652557 100644 --- a/src/counters.c +++ b/src/counters.c @@ -1536,6 +1536,42 @@ int SCPerfUpdateCounterArray(SCPerfCounterArray *pca, SCPerfContext *pctx, return 1; } +/* + * \brief Get the value of the local copy of the counter that hold this id. + * + * \param id The counter id. + * \param pca Pointer to the SCPerfCounterArray. + * + * \retval 0 on success. + * \retval -1 on error. + */ +double SCPerfGetLocalCounterValue(uint16_t id, SCPerfCounterArray *pca) +{ + if (pca == NULL) { + SCLogDebug("pca NULL inside SCPerfUpdateCounterArray"); + return -1; + } + + if ((id < 1) || (id > pca->size)) { + SCLogDebug("counter doesn't exist"); + return -1; + } + + /* we check the type of the counter. Whether it's a counter that holds an + * unsigned_int_64 value or double value */ + switch (pca->head[id].pc->value->type) { + /* the counter holds an unsigned_int_64 value */ + case SC_PERF_TYPE_UINT64: + return pca->head[id].ui64_cnt; + /* the counter holds a double */ + case SC_PERF_TYPE_DOUBLE: + return pca->head[id].d_cnt; + default: + /* this can never happen */ + return -1; + } +} + /** * \brief The output interface dispatcher for the counter api */ diff --git a/src/counters.h b/src/counters.h index ee6a908..ff44a96 100644 --- a/src/counters.h +++ b/src/counters.h @@ -229,6 +229,7 @@ inline void SCPerfCounterSetUI64(uint16_t, SCPerfCounterArray *, uint64_t); inline void SCPerfCounterSetDouble(uint16_t, SCPerfCounterArray *, double); int SCPerfUpdateCounterArray(SCPerfCounterArray *, SCPerfContext *, int); +double SCPerfGetLocalCounterValue(uint16_t, SCPerfCounterArray *); void SCPerfOutputCounters(void); diff --git a/src/detect-engine-iponly.c b/src/detect-engine-iponly.c index 6cb0491..9c18840 100644 --- a/src/detect-engine-iponly.c +++ b/src/detect-engine-iponly.c @@ -859,7 +859,9 @@ void DetectEngineIPOnlyThreadDeinit(DetectEngineIPOnlyThreadCtx *io_tctx) { * \param io_ctx Pointer to the current ip only thread detection engine * \param p Pointer to the Packet to match against */ -void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, +void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, + DetectEngineThreadCtx *det_ctx, + DetectEngineIPOnlyCtx *io_ctx, DetectEngineIPOnlyThreadCtx *io_tctx, Packet *p) { SCRadixNode *srcnode = NULL, *dstnode = NULL; @@ -933,7 +935,7 @@ void IPOnlyMatchPacket(DetectEngineCtx *de_ctx, DetectEngineIPOnlyCtx *io_ctx, u * 8 + i, s->id, s->msg); if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; diff --git a/src/detect-engine-iponly.h b/src/detect-engine-iponly.h index 9704572..be8086d 100644 --- a/src/detect-engine-iponly.h +++ b/src/detect-engine-iponly.h @@ -28,7 +28,9 @@ int IPOnlyCIDRItemParseSingle(IPOnlyCIDRItem *dd, char *str); int IPOnlyCIDRItemSetup(IPOnlyCIDRItem *gh, char *s); void IPOnlyCIDRListPrint(IPOnlyCIDRItem *); -void IPOnlyMatchPacket(DetectEngineCtx *, DetectEngineIPOnlyCtx *, DetectEngineIPOnlyThreadCtx *, Packet *); +void IPOnlyMatchPacket(DetectEngineCtx *, DetectEngineThreadCtx *, + DetectEngineIPOnlyCtx *, DetectEngineIPOnlyThreadCtx *, + Packet *); void IPOnlyInit(DetectEngineCtx *, DetectEngineIPOnlyCtx *); void IPOnlyPrint(DetectEngineCtx *, DetectEngineIPOnlyCtx *); void IPOnlyDeinit(DetectEngineCtx *, DetectEngineIPOnlyCtx *); diff --git a/src/detect-engine-threshold.c b/src/detect-engine-threshold.c index f376d58..1675757 100644 --- a/src/detect-engine-threshold.c +++ b/src/detect-engine-threshold.c @@ -42,7 +42,8 @@ * \param p Packet structure * */ -void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p) +void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + Signature *sig, Packet *p) { SCEnter(); @@ -53,9 +54,10 @@ void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p) /* if have none just alert, otherwise handle thresholding */ if (td == NULL) { - PacketAlertAppend(p, sig->gid, sig->id, sig->rev, sig->prio, sig->msg, sig->class_msg); + PacketAlertAppend(p, det_ctx, sig->gid, sig->id, sig->rev, sig->prio, + sig->msg, sig->class_msg); } else { - PacketAlertThreshold(de_ctx, td, p, sig); + PacketAlertThreshold(de_ctx, det_ctx, td, p, sig); } SCReturn; @@ -224,7 +226,8 @@ void ThresholdHashAdd(DetectEngineCtx *de_ctx, DetectThresholdEntry *tsh_ptr, Pa * \param s Signature structure * */ -void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Packet *p, Signature *s) +void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *det_ctx, + DetectThresholdData *td, Packet *p, Signature *s) { SCEnter(); @@ -277,20 +280,20 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if (lookup_tsh != NULL) { if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { if (lookup_tsh->current_count < td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); } lookup_tsh->current_count++; } else { lookup_tsh->tv_sec1 = ts.tv_sec; lookup_tsh->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); } } else { ste->tv_sec1 = ts.tv_sec; ste->current_count = 1; - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); ThresholdHashAdd(de_ctx, ste, p); ste = NULL; @@ -307,7 +310,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); lookup_tsh->current_count = 0; } } else { @@ -319,7 +322,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -337,7 +340,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count == td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -348,7 +351,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); ste->current_count = 0; } else { ThresholdHashAdd(de_ctx,ste,p); @@ -367,7 +370,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack if ((ts.tv_sec - lookup_tsh->tv_sec1) < td->seconds) { lookup_tsh->current_count++; if (lookup_tsh->current_count >= td->count) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); } } else { lookup_tsh->tv_sec1 = ts.tv_sec; @@ -378,7 +381,7 @@ void PacketAlertThreshold(DetectEngineCtx *de_ctx, DetectThresholdData *td, Pack ste->tv_sec1 = ts.tv_sec; if (td->count == 1) { - PacketAlertAppend(p, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); + PacketAlertAppend(p, det_ctx, s->gid, s->id, s->rev, s->prio, s->msg, s->class_msg); } ThresholdHashAdd(de_ctx, ste, p); ste = NULL; diff --git a/src/detect-engine-threshold.h b/src/detect-engine-threshold.h index 6fcf013..1e72e05 100644 --- a/src/detect-engine-threshold.h +++ b/src/detect-engine-threshold.h @@ -12,9 +12,11 @@ #define THRESHOLD_HASH_SIZE 0xffff -void PacketAlertHandle(DetectEngineCtx *de_ctx, Signature *sig, Packet *p); +void PacketAlertHandle(DetectEngineCtx *de_ctx, DetectEngineThreadCtx *, + Signature *sig, Packet *p); DetectThresholdData *SigGetThresholdType(Signature *, Packet *); -void PacketAlertThreshold(DetectEngineCtx *,DetectThresholdData *, Packet *, Signature *); +void PacketAlertThreshold(DetectEngineCtx *, DetectEngineThreadCtx *, + DetectThresholdData *, Packet *, Signature *); void ThresholdFreeFunc(void *data); char ThresholdCompareFunc(void *data1, uint16_t len1, void *data2,uint16_t len2); uint32_t ThresholdHashFunc(HashListTable *ht, void *data, uint16_t datalen); diff --git a/src/detect-engine.c b/src/detect-engine.c index c0c3b6f..1785f65 100644 --- a/src/detect-engine.c +++ b/src/detect-engine.c @@ -437,6 +437,9 @@ TmEcode DetectEngineThreadCtxInit(ThreadVars *tv, void *initdata, void **data) { tv->sc_perf_pca = SCPerfGetAllCountersArray(&tv->sc_perf_pctx); SCPerfAddToClubbedTMTable(tv->name, &tv->sc_perf_pctx); + /* this detection engine context belongs to this thread instance */ + det_ctx->tv = tv; + *data = (void *)det_ctx; #ifdef __SC_CUDA_SUPPORT__ diff --git a/src/detect.c b/src/detect.c index 0781877..2f2cf15 100644 --- a/src/detect.c +++ b/src/detect.c @@ -388,7 +388,8 @@ int PacketAlertCheck(Packet *p, uint32_t sid) return match; } -int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, +int PacketAlertAppend(Packet *p, DetectEngineThreadCtx *det_ctx, + uint32_t gid, uint32_t sid, uint8_t rev, uint8_t prio, char *msg, char *class_msg) { if (p->alerts.cnt == PACKET_ALERT_MAX) @@ -408,6 +409,8 @@ int PacketAlertAppend(Packet *p, uint32_t gid, uint32_t sid, uint8_t rev, p->alerts.alerts[p->alerts.cnt].class_msg = class_msg; p->alerts.cnt++; + SCPerfCounterIncr(det_ctx->counter_alerts, det_ctx->tv->sc_perf_pca); + return 0; } @@ -506,7 +509,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh (p->flowflags & FLOW_PKT_TOCLIENT && !(p->flowflags & FLOW_PKT_TOCLIENT_IPONLY_SET))) { SCLogDebug("testing against \"ip-only\" signatures"); - IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); + IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); /* save in the flow that we scanned this direction... locking is * done in the FlowSetIPOnlyFlag function. */ if (p->flow != NULL) { @@ -520,7 +523,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (p->flow->flags & FLOW_ACTION_DROP) p->action |= ACTION_DROP; } else { /* Even without flow we should match the packet src/dst */ - IPOnlyMatchPacket(de_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); + IPOnlyMatchPacket(de_ctx, det_ctx, &de_ctx->io_ctx, &det_ctx->io_ctx, p); } /* we assume we have an uri when we start inspection */ @@ -680,7 +683,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh fmatch = 1; if (!(s->flags & SIG_FLAG_NOALERT)) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; } @@ -718,7 +721,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (!(s->flags & SIG_FLAG_NOALERT)) { /* only add once */ if (rmatch == 0) { - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; } @@ -764,7 +767,7 @@ int SigMatchSignatures(ThreadVars *th_v, DetectEngineCtx *de_ctx, DetectEngineTh if (!(s->flags & SIG_FLAG_NOALERT)) { /* set flowbit for this match */ - PacketAlertHandle(de_ctx,s,p); + PacketAlertHandle(de_ctx, det_ctx, s, p); /* set verdict on packet */ p->action |= s->action; @@ -8462,6 +8465,62 @@ static int SigTestDepthOffset01Wm (void) { return SigTestDepthOffset01Real(MPM_WUMANBER); } +static int SigTestDetectAlertCounter(void) +{ + Packet p; + ThreadVars tv; + DetectEngineThreadCtx *det_ctx = NULL; + int result = 0; + + memset(&tv, 0, sizeof(tv)); + DetectEngineCtx *de_ctx = DetectEngineCtxInit(); + if (de_ctx == NULL) { + goto end; + } + + de_ctx->mpm_matcher = MPM_B2G; + de_ctx->flags |= DE_QUIET; + + de_ctx->sig_list = SigInit(de_ctx, "alert tcp any any -> any any (msg:\"Test counter\"; " + "content:\"boo\"; sid:1;)"); + if (de_ctx->sig_list == NULL) { + goto end; + } + + SigGroupBuild(de_ctx); + tv.name = "detect_test"; + DetectEngineThreadCtxInit(&tv, de_ctx, (void *)&det_ctx); + + memset(&p, 0, sizeof(p)); + p.src.family = AF_INET; + p.dst.family = AF_INET; + p.payload = (uint8_t *)"boo"; + p.payload_len = strlen((char *)p.payload); + p.proto = IPPROTO_TCP; + Detect(&tv, &p, det_ctx, NULL); + result = (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 1); + + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 2); + + p.payload = (uint8_t *)"roo"; + p.payload_len = strlen((char *)p.payload); + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 2); + + p.payload = (uint8_t *)"laboosa"; + p.payload_len = strlen((char *)p.payload); + Detect(&tv, &p, det_ctx, NULL); + result &= (SCPerfGetLocalCounterValue(det_ctx->counter_alerts, tv.sc_perf_pca) == 3); + +end: + SigGroupCleanup(de_ctx); + SigCleanSignatures(de_ctx); + + DetectEngineThreadCtxDeinit(&tv, (void *)det_ctx); + DetectEngineCtxFree(de_ctx); + return result; +} #endif /* UNITTESTS */ @@ -8663,6 +8722,8 @@ void SigRegisterTests(void) { UtRegisterTest("SigTestDepthOffset01B3g", SigTestDepthOffset01B3g, 1); UtRegisterTest("SigTestDepthOffset01Wm", SigTestDepthOffset01Wm, 1); + UtRegisterTest("SigTestDetectAlertCounter", SigTestDetectAlertCounter, 1); + #endif /* UNITTESTS */ } diff --git a/src/detect.h b/src/detect.h index 6fb5394..0515c95 100644 --- a/src/detect.h +++ b/src/detect.h @@ -411,6 +411,9 @@ enum { * Detection engine thread data. */ typedef struct DetectionEngineThreadCtx_ { + /* the thread to which this detection engine thread belongs */ + ThreadVars *tv; + /* detection engine variables */ /** offset into the payload of the last match by: @@ -659,8 +662,8 @@ int SigGroupBuild(DetectEngineCtx *); int SigGroupCleanup(); void SigAddressPrepareBidirectionals (DetectEngineCtx *); -int PacketAlertAppend(Packet *, uint32_t, uint32_t, uint8_t, uint8_t, char *, - char *); +int PacketAlertAppend(Packet *, DetectEngineThreadCtx *, uint32_t, uint32_t, + uint8_t, uint8_t, char *, char *); int SigLoadSignatures (DetectEngineCtx *, char *); void SigTableSetup(void); -- 1.7.0.2