]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
hostbits: implement sigorder
authorVictor Julien <victor@inliniac.net>
Sat, 13 Dec 2014 23:04:14 +0000 (00:04 +0100)
committerVictor Julien <victor@inliniac.net>
Thu, 16 Apr 2015 08:07:27 +0000 (10:07 +0200)
Like with flowbits, make sure that 'set's are evaluated before
'isset's, etc.

src/detect-engine-sigorder.c
src/detect-engine-sigorder.h

index 4a980ad66da39520bde4dd218d3de205bbf7a4f2..edca49c353e4142c88a7a140bf8c0fcf273374b0 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "suricata-common.h"
 #include "detect.h"
+#include "detect-hostbits.h"
 #include "detect-flowbits.h"
 #include "detect-flowint.h"
 #include "detect-parse.h"
 #define DETECT_FLOWINT_TYPE_SET_READ 3
 #define DETECT_FLOWINT_TYPE_SET      4
 
+#define DETECT_HOSTBITS_NOT_USED      1
+#define DETECT_HOSTBITS_TYPE_READ     2
+#define DETECT_HOSTBITS_TYPE_SET_READ 3
+#define DETECT_HOSTBITS_TYPE_SET      4
+
 
 /**
  * \brief Registers a keyword-based, signature ordering function
@@ -340,6 +346,75 @@ static inline int SCSigGetPktvarType(Signature *sig)
     return type;
 }
 
+/**
+ * \brief Returns the hostbit type set for this signature.  If more than one
+ *        hostbit has been set for the same rule, we return the hostbit type of
+ *        the maximum priority/value, where priority/value is maximum for the
+ *        ones that set the value and the lowest for ones that read the value.
+ *        If no hostbit has been set for the rule, we return 0, which indicates
+ *        the least value amongst hostbit types.
+ *
+ * \param sig Pointer to the Signature from which the hostbit value has to be
+ *            returned.
+ *
+ * \retval hostbits The hostbits type for this signature if it is set; if it is
+ *                  not set, return 0
+ */
+static inline int SCSigGetHostbitsType(Signature *sig)
+{
+    DetectHostbitsData *fb = NULL;
+    int hostbits_user_type = DETECT_HOSTBITS_NOT_USED;
+    int read = 0;
+    int write = 0;
+    SigMatch *sm = sig->sm_lists[DETECT_SM_LIST_MATCH];
+
+    while (sm != NULL) {
+        if (sm->type == DETECT_HOSTBITS) {
+            fb = (DetectHostbitsData *)sm->ctx;
+            if (fb->cmd == DETECT_HOSTBITS_CMD_ISNOTSET ||
+                fb->cmd == DETECT_HOSTBITS_CMD_ISSET) {
+                read++;
+            } else {
+#ifdef DEBUG
+                BUG_ON(1);
+#endif
+            }
+        }
+
+        sm = sm->next;
+    }
+
+    sm = sig->sm_lists[DETECT_SM_LIST_POSTMATCH];
+    while (sm != NULL) {
+        if (sm->type == DETECT_HOSTBITS) {
+            fb = (DetectHostbitsData *)sm->ctx;
+            if (fb->cmd == DETECT_HOSTBITS_CMD_SET ||
+                fb->cmd == DETECT_HOSTBITS_CMD_UNSET ||
+                fb->cmd == DETECT_HOSTBITS_CMD_TOGGLE) {
+                write++;
+            } else {
+#ifdef DEBUG
+                BUG_ON(1);
+#endif
+            }
+        }
+
+        sm = sm->next;
+    }
+
+    if (read > 0 && write == 0) {
+        hostbits_user_type = DETECT_HOSTBITS_TYPE_READ;
+    } else if (read == 0 && write > 0) {
+        hostbits_user_type = DETECT_HOSTBITS_TYPE_SET;
+    } else if (read > 0 && write > 0) {
+        hostbits_user_type = DETECT_HOSTBITS_TYPE_SET_READ;
+    }
+
+    SCLogDebug("Sig %s typeval %d", sig->msg, hostbits_user_type);
+
+    return hostbits_user_type;
+}
+
 /**
  * \brief Processes the flowbits data for this signature and caches it for
  *        future use.  This is needed to optimize the sig_ordering module.
@@ -381,6 +456,18 @@ static inline void SCSigProcessUserDataForPktvar(SCSigSignatureWrapper *sw)
     sw->user[SC_RADIX_USER_DATA_PKTVAR] = SCSigGetPktvarType(sw->sig);
 }
 
+/**
+ * \brief Processes the flowbits data for this signature and caches it for
+ *        future use.  This is needed to optimize the sig_ordering module.
+ *
+ * \param sw The sigwrapper/signature for which the flowbits data has to be
+ *           cached
+ */
+static inline void SCSigProcessUserDataForHostbits(SCSigSignatureWrapper *sw)
+{
+    sw->user[SC_RADIX_USER_DATA_HOSTBITS] = SCSigGetHostbitsType(sw->sig);
+}
+
 /* Return 1 if sw1 comes before sw2 in the final list. */
 static int SCSigLessThan(SCSigSignatureWrapper *sw1,
                          SCSigSignatureWrapper *sw2,
@@ -528,6 +615,20 @@ static int SCSigOrderByFlowintCompare(SCSigSignatureWrapper *sw1,
         sw2->user[SC_RADIX_USER_DATA_FLOWINT];
 }
 
+/**
+ * \brief Orders an incoming Signature based on its hostbits type
+ *
+ * \param de_ctx Pointer to the detection engine context from which the
+ *               signatures have to be ordered.
+ * \param sw     The new signature that has to be ordered based on its hostbits
+ */
+static int SCSigOrderByHostbitsCompare(SCSigSignatureWrapper *sw1,
+                                       SCSigSignatureWrapper *sw2)
+{
+    return sw1->user[SC_RADIX_USER_DATA_HOSTBITS] -
+        sw2->user[SC_RADIX_USER_DATA_HOSTBITS];
+}
+
 /**
  * \brief Orders an incoming Signature based on its priority type
  *
@@ -564,6 +665,7 @@ static inline SCSigSignatureWrapper *SCSigAllocSignatureWrapper(Signature *sig)
     SCSigProcessUserDataForFlowvar(sw);
     SCSigProcessUserDataForFlowint(sw);
     SCSigProcessUserDataForPktvar(sw);
+    SCSigProcessUserDataForHostbits(sw);
 
     return sw;
 }
@@ -643,6 +745,7 @@ void SCSigRegisterSignatureOrderingFuncs(DetectEngineCtx *de_ctx)
     SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowintCompare);
     SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByFlowvarCompare);
     SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPktvarCompare);
+    SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByHostbitsCompare);
     SCSigRegisterSignatureOrderingFunc(de_ctx, SCSigOrderByPriorityCompare);
 }
 
index 1451dfc3fae3e9ad1495ad7482e8ad9db6fadd79..312165a04bf13cd7c7368fc902626364988da6de 100644 (file)
@@ -33,6 +33,7 @@ typedef enum{
     SC_RADIX_USER_DATA_FLOWVAR,
     SC_RADIX_USER_DATA_PKTVAR,
     SC_RADIX_USER_DATA_FLOWINT,
+    SC_RADIX_USER_DATA_HOSTBITS,
     SC_RADIX_USER_DATA_MAX
 } SCRadixUserDataType;