From: Shivani Bhardwaj Date: Fri, 16 Feb 2024 08:57:52 +0000 (+0530) Subject: detect/port: find unique port points X-Git-Tag: suricata-8.0.0-beta1~1680 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c9a911b6f8a5822058590d62df8930ecef8df5c0;p=thirdparty%2Fsuricata.git detect/port: find unique port points 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 --- diff --git a/src/detect-engine-build.c b/src/detect-engine-build.c index 24ddc0af44..50c429c3eb 100644 --- a/src/detect-engine-build.c +++ b/src/detect-engine-build.c @@ -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)