]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
detect/port: find unique port points
authorShivani Bhardwaj <shivani@oisf.net>
Fri, 16 Feb 2024 08:57:52 +0000 (14:27 +0530)
committerVictor Julien <victor@inliniac.net>
Mon, 4 Mar 2024 10:50:30 +0000 (11:50 +0100)
In order to create the smallest possible port ranges, it is convenient
to first have a list of unique ports. Then, the work becomes simple. See
below:

Given, a port range P1 = [1, 8]; SGH1
and another, P2 = [3, 94]; SGH2

right now, the code will follow a logic of recursively cutting port
ranges until we create the small ranges. But, with the help of unique
port points, we get, unique_port_points = [1, 3, 8, 94]

So, now, in a later stage, we can create the ranges as
[1, 2], [3, 7], [8, 8], [9, 94] and copy the designated SGHs where they
belong. Note that the intervals are closed which means that the range
is inclusive of both the points.

The final result becomes:
1. [1, 2]; SGH1
2. [3, 7]; SGH1 + SGH2
3. [8, 8]; SGH1 + SGH2
4. [9, 94]; SGH2

There would be 3 unique rule groups made for the case above.
Group 1: [1, 2]
Group 2: [3, 7], [8, 8]
Group 3: [9, 94]

Ticket 6792
Bug 6414

src/detect-engine-build.c

index 24ddc0af4469df9af93556e0149f54c6a83bf67b..50c429c3ebff122411f0a58dd496bccba16c18e3 100644 (file)
@@ -1129,6 +1129,44 @@ int CreateGroupedPortList(DetectEngineCtx *de_ctx, DetectPort *port_list, Detect
         uint32_t unique_groups, int (*CompareFunc)(DetectPort *, DetectPort *));
 int CreateGroupedPortListCmpCnt(DetectPort *a, DetectPort *b);
 
+#define RANGE_PORT  1
+#define SINGLE_PORT 2
+
+/**
+ * \brief Function to set unique port points. Consider all the ports
+ *        flattened out on one line, set the points that correspond
+ *        to a valid port. Also store whether the port point stored
+ *        was a single port or part of a range.
+ *
+ * \param p Port object to be set
+ * \param unique_list List of unique port points to be updated
+ * \param size_list Current size of the list
+ *
+ * \return Updated size of the list
+ */
+static inline uint32_t SetUniquePortPoints(
+        const DetectPort *p, uint8_t *unique_list, uint32_t size_list)
+{
+    if (unique_list[p->port] == 0) {
+        if (p->port == p->port2) {
+            unique_list[p->port] = SINGLE_PORT;
+        } else {
+            unique_list[p->port] = RANGE_PORT;
+        }
+        size_list++;
+    }
+
+    /* 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 */
+    if (unique_list[p->port2] == 0) {
+        size_list++;
+    }
+    unique_list[p->port2] = SINGLE_PORT;
+    return size_list;
+}
+
 static DetectPort *RulesGroupByPorts(DetectEngineCtx *de_ctx, uint8_t ipproto, uint32_t direction)
 {
     /* step 1: create a hash of 'DetectPort' objects based on all the
@@ -1136,8 +1174,14 @@ static DetectPort *RulesGroupByPorts(DetectEngineCtx *de_ctx, uint8_t ipproto, u
      *         that belong to the SGH. */
     DetectPortHashInit(de_ctx);
 
+    uint32_t size_unique_port_arr = 0;
     const Signature *s = de_ctx->sig_list;
     DetectPort *list = NULL;
+
+    uint8_t *unique_port_points = (uint8_t *)SCCalloc(UINT16_MAX + 1, sizeof(uint8_t));
+    if (unique_port_points == NULL)
+        return NULL;
+
     while (s) {
         /* IP Only rules are handled separately */
         if (s->type == SIG_TYPE_IPONLY)
@@ -1190,6 +1234,8 @@ static DetectPort *RulesGroupByPorts(DetectEngineCtx *de_ctx, uint8_t ipproto, u
                 SigGroupHeadAppendSig(de_ctx, &tmp2->sh, s);
                 tmp2->sh->init->score = pwl;
                 DetectPortHashAdd(de_ctx, tmp2);
+                size_unique_port_arr =
+                        SetUniquePortPoints(tmp2, unique_port_points, size_unique_port_arr);
             }
 
             p = p->next;
@@ -1268,6 +1314,10 @@ static DetectPort *RulesGroupByPorts(DetectEngineCtx *de_ctx, uint8_t ipproto, u
             direction == SIG_FLAG_TOSERVER ? "toserver" : "toclient",
             cnt, own, ref);
     return list;
+
+error:
+    if (unique_port_points != NULL)
+        SCFree(unique_port_points);
 }
 
 void SignatureSetType(DetectEngineCtx *de_ctx, Signature *s)