]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/port: merge port ranges for same signatures
authorShivani Bhardwaj <shivani@oisf.net>
Wed, 21 Feb 2024 06:42:30 +0000 (12:12 +0530)
committerVictor Julien <victor@inliniac.net>
Mon, 4 Mar 2024 10:50:30 +0000 (11:50 +0100)
To avoid getting multiple entries in the final port list and to also
make the next step more efficient by reducing the size of the items to
traverse over.

Ticket 6792
Bug 6414

src/detect-engine-build.c
src/detect-engine-siggroup.c
src/detect-engine-siggroup.h
src/util-port-interval-tree.c

index bc399f2e507de9f0b254d01c67e40bdd2df7d55a..e812f861226e9f0414b0c260a1768d3c7906f6d6 100644 (file)
@@ -1163,9 +1163,7 @@ static inline uint32_t SetUniquePortPoints(
     }
 
     /* Treat right boundary as single point to avoid creating unneeded
-     * ranges later on
-     * TODO merge the extra entry created in the rulegroup
-     * for such points in *CreateGroupedPortList* fn */
+     * ranges later on */
     if (unique_list[p->port2] == 0) {
         size_list++;
     }
index 52073cf0bfdad951fe6d405a0683364803a5d06d..004659b1b192fd0956f2df5290c2807d25074f23 100644 (file)
@@ -435,6 +435,31 @@ void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx)
     return;
 }
 
+/**
+ * \brief Finds if two Signature Group Heads are the same.
+ *
+ * \param sgha First SGH to be compared
+ * \param sghb Secornd SGH to be compared
+ *
+ * \return true if they're a match, false otherwise
+ */
+bool SigGroupHeadEqual(const SigGroupHead *sgha, const SigGroupHead *sghb)
+{
+    if (sgha == NULL || sghb == NULL)
+        return false;
+
+    if (sgha->init->sig_size != sghb->init->sig_size)
+        return false;
+
+    if (sgha->init->max_sig_id != sghb->init->max_sig_id)
+        return false;
+
+    if (SCMemcmp(sgha->init->sig_array, sghb->init->sig_array, sgha->init->sig_size) != 0)
+        return false;
+
+    return true;
+}
+
 void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh,
                                       uint8_t ipproto, int dir)
 {
index 45887edbfb00216038e0925a12e1097893a69b97..f0638293a6ef8f7a6cd572358437ae6912213f09 100644 (file)
@@ -42,6 +42,7 @@ int SigGroupHeadHashRemove(DetectEngineCtx *, SigGroupHead *);
 
 void SigGroupHeadInitDataFree(SigGroupHeadInitData *sghid);
 void SigGroupHeadSetSigCnt(SigGroupHead *sgh, uint32_t max_idx);
+bool SigGroupHeadEqual(const SigGroupHead *, const SigGroupHead *);
 void SigGroupHeadSetProtoAndDirection(SigGroupHead *sgh,
                                       uint8_t ipproto, int dir);
 int SigGroupHeadBuildMatchArray(DetectEngineCtx *de_ctx, SigGroupHead *sgh, uint32_t max_idx);
index 53f8ef55085d5379a5b91c933bba8a152673bd91..d4c770585a6eeb2640f7996b4fb39af2949248e9 100644 (file)
@@ -127,6 +127,35 @@ int SCPortIntervalInsert(DetectEngineCtx *de_ctx, SCPortIntervalTree *it, const
     return SC_OK;
 }
 
+/**
+ * \brief Function to remove multiple sig entries corresponding to the same
+ *        signature group and merge them into one.
+ *
+ * \param de_ctx Detection Engine Context
+ * \param list Pointer to the list to be modified
+ */
+static void SCPortIntervalSanitizeList(DetectEngineCtx *de_ctx, DetectPort **list)
+{
+    DetectPort *cur = (*list)->last;
+    if (cur == NULL)
+        return;
+
+    DetectPort *prev = (*list)->last->prev;
+    if (prev == NULL)
+        return;
+
+    /* rulegroup IDs are assigned much later so, compare SGHs */
+    if (SigGroupHeadEqual(prev->sh, cur->sh)) {
+        if (prev->port2 == (cur->port - 1)) {
+            /* Merge the port objects */
+            prev->port2 = cur->port2;
+            (*list)->last = prev;
+            (*list)->last->next = NULL;
+            DetectPortFree(de_ctx, cur);
+        }
+    }
+}
+
 /**
  * \brief Function to check if a port range overlaps with a given set of ports
  *
@@ -226,6 +255,7 @@ static void SCPortIntervalFindOverlaps(DetectEngineCtx *de_ctx, const uint16_t p
                            ((*list)->last->port2 != new_port->port)) {
                     DEBUG_VALIDATE_BUG_ON(new_port->port < (*list)->last->port);
                     (*list)->last->next = new_port;
+                    new_port->prev = (*list)->last;
                     (*list)->last = new_port;
                 } else {
                     SCLogDebug("Port already exists in the list");
@@ -260,6 +290,8 @@ static void SCPortIntervalFindOverlaps(DetectEngineCtx *de_ctx, const uint16_t p
         BUG_ON(popped == NULL);
         current = IRB_RIGHT(popped, irb);
     }
+    if (new_port != NULL)
+        SCPortIntervalSanitizeList(de_ctx, list);
     if (stack != NULL)
         SCFree(stack);
     return;