]> 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>
Fri, 24 May 2024 17:11:03 +0000 (19:11 +0200)
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

(cherry picked from commit 643ae85b5faa91958fe9ee79987fa20f06849059)

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

index e8ca516ec25d2abb2a10f356174ad97d833059b9..1fc5190dc8fd69e2b00324e25a654aa92660dfae 100644 (file)
@@ -1190,9 +1190,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 c75a5d0ed856838d2904c4281dd71ee5f0f43d99..c05b6c3daac9c247b22ea75bc4e65548b684d9e6 100644 (file)
@@ -438,6 +438,28 @@ 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 (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 d4c9e93c677104f9a1a9c3235398ca8cb88cd792..456979aed2fdb4e0528e961ed10b8b7bef452495 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;