From 0c24a8a92febec7b250cac0e6eb193c6c909b81d Mon Sep 17 00:00:00 2001 From: Anoop Saldanha Date: Tue, 15 Jan 2013 23:30:19 +0530 Subject: [PATCH] fix(more like a feature update) for bug #708. Add support for flowint based sig ordering. --- src/detect-engine-sigorder.c | 164 +++++++++++++++++++++++++++++++++++ src/detect-engine-sigorder.h | 1 + 2 files changed, 165 insertions(+) diff --git a/src/detect-engine-sigorder.c b/src/detect-engine-sigorder.c index 5dbcf9fe90..5cffa1770f 100644 --- a/src/detect-engine-sigorder.c +++ b/src/detect-engine-sigorder.c @@ -26,6 +26,7 @@ #include "suricata-common.h" #include "detect.h" #include "detect-flowbits.h" +#include "detect-flowint.h" #include "detect-engine-sigorder.h" #include "detect-pcre.h" @@ -46,6 +47,10 @@ #define DETECT_FLOWBITS_TYPE_READ 2 #define DETECT_FLOWBITS_TYPE_SET 3 +#define DETECT_FLOWINT_NOT_USED 1 +#define DETECT_FLOWINT_TYPE_READ 2 +#define DETECT_FLOWINT_TYPE_SET 3 + /** * \brief Registers a keyword-based, signature ordering function @@ -150,6 +155,53 @@ static inline int SCSigGetFlowbitsType(Signature *sig) return flowbits_user_type; } +static inline int SCSigGetFlowintType(Signature *sig) +{ + SigMatch *sm = sig->sm_lists[DETECT_SM_LIST_MATCH]; + DetectFlowintData *fi = NULL; + int modifier = FLOWINT_MODIFIER_UNKNOWN; + int flowint_user_type = DETECT_FLOWINT_NOT_USED; + + while (sm != NULL) { + if (sm->type == DETECT_FLOWINT) { + fi = (DetectFlowintData *)sm->ctx; + if (modifier > fi->modifier) + modifier = fi->modifier; + } + + sm = sm->next; + } + + sm = sig->sm_lists[DETECT_SM_LIST_POSTMATCH]; + while (sm != NULL) { + if (sm->type == DETECT_FLOWINT) { + fi = (DetectFlowintData *)sm->ctx; + if (modifier > fi->modifier) + modifier = fi->modifier; + } + + sm = sm->next; + } + + if (modifier == FLOWINT_MODIFIER_SET || + modifier == FLOWINT_MODIFIER_ADD || + modifier == FLOWINT_MODIFIER_SUB) { + flowint_user_type = DETECT_FLOWINT_TYPE_SET; + } else if (modifier == FLOWINT_MODIFIER_LT || + modifier == FLOWINT_MODIFIER_LE || + modifier == FLOWINT_MODIFIER_EQ || + modifier == FLOWINT_MODIFIER_NE || + modifier == FLOWINT_MODIFIER_GE || + modifier == FLOWINT_MODIFIER_GT || + modifier == FLOWINT_MODIFIER_ISSET) { + flowint_user_type = DETECT_FLOWINT_TYPE_READ; + } + + SCLogDebug("Sig %s typeval %d", sig->msg, flowint_user_type); + + return flowint_user_type; +} + /** * \brief Returns whether the flowvar set for this rule, sets the flowvar or * reads the flowvar. If the rule sets the flowvar the function returns @@ -268,6 +320,13 @@ static inline void SCSigProcessUserDataForFlowvar(SCSigSignatureWrapper *sw) return; } +static inline void SCSigProcessUserDataForFlowint(SCSigSignatureWrapper *sw) +{ + *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWINT])) = SCSigGetFlowintType(sw->sig); + + return; +} + /** * \brief Processes the pktvar data for this signature and caches it for * future use. This is needed to optimize the sig_ordering module. @@ -719,6 +778,109 @@ static void SCSigOrderByPktvar(DetectEngineCtx *de_ctx, return; } +static void SCSigOrderByFlowint(DetectEngineCtx *de_ctx, + SCSigSignatureWrapper *sw) +{ + SCSigSignatureWrapper *min = NULL; + SCSigSignatureWrapper *max = NULL; + SCSigSignatureWrapper *prev = NULL; + + if (sw == NULL) + return; + + if (de_ctx->sc_sig_sig_wrapper == NULL) { + de_ctx->sc_sig_sig_wrapper = sw; + sw->min = NULL; + sw->max = NULL; + return; + } + + min = sw->min; + max = sw->max; + if (min == NULL) + min = de_ctx->sc_sig_sig_wrapper; + else + min = min->next; + + while (min != max) { + prev = min; + /* the sorting logic */ + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWINT])) <= + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWINT])) ) { + min = min->next; + continue; + } + + if (min->prev == sw) + break; + + if (sw->next != NULL) + sw->next->prev = sw->prev; + if (sw->prev != NULL) + sw->prev->next = sw->next; + if (de_ctx->sc_sig_sig_wrapper == sw) + de_ctx->sc_sig_sig_wrapper = sw->next; + + sw->next = min; + sw->prev = min->prev; + + if (min->prev != NULL) + min->prev->next = sw; + else + de_ctx->sc_sig_sig_wrapper = sw; + + min->prev = sw; + + break; + } + + if (min == max && prev != sw) { + if (sw->next != NULL) { + sw->next->prev = sw->prev; + } + if (sw->prev != NULL) { + sw->prev->next = sw->next; + } + + if (min == NULL) { + if (prev != NULL) + prev->next = sw; + sw->prev = prev; + sw->next = NULL; + } else { + sw->prev = min->prev; + sw->next = min; + if (min->prev != NULL) + min->prev->next = sw; + min->prev = sw; + } + } + + /* set the min signature for this keyword, for the next ordering function */ + min = sw; + while (min != NULL && min != sw->min) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWINT])) != + *((int *)(min->user[SC_RADIX_USER_DATA_FLOWINT])) ) + break; + + min = min->prev; + } + sw->min = min; + + /* set the max signature for this keyword + 1, for the next ordering func */ + max = sw; + while (max != NULL && max != sw->max) { + if ( *((int *)(sw->user[SC_RADIX_USER_DATA_FLOWINT])) != + *((int *)(max->user[SC_RADIX_USER_DATA_FLOWINT])) ) + break; + + max = max->next; + } + sw->max = max; + + return; +} + /** * \brief Orders an incoming Signature based on its priority type * @@ -862,6 +1024,7 @@ static inline SCSigSignatureWrapper *SCSigAllocSignatureWrapper(Signature *sig) * sig_ordering module */ SCSigProcessUserDataForFlowbits(sw); SCSigProcessUserDataForFlowvar(sw); + SCSigProcessUserDataForFlowint(sw); SCSigProcessUserDataForPktvar(sw); return sw; @@ -939,6 +1102,7 @@ void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx) SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByAction); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowbits); + SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowint); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvar); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvar); SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriority); diff --git a/src/detect-engine-sigorder.h b/src/detect-engine-sigorder.h index 43d0384c04..030a19656d 100644 --- a/src/detect-engine-sigorder.h +++ b/src/detect-engine-sigorder.h @@ -32,6 +32,7 @@ typedef enum{ SC_RADIX_USER_DATA_FLOWBITS, SC_RADIX_USER_DATA_FLOWVAR, SC_RADIX_USER_DATA_PKTVAR, + SC_RADIX_USER_DATA_FLOWINT, SC_RADIX_USER_DATA_MAX } SCRadixUserDataType;