]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4174: filters: updated dyn array with vector
authorRaza Shafiq (rshafiq) <rshafiq@cisco.com>
Mon, 4 Mar 2024 21:21:51 +0000 (21:21 +0000)
committerSteven Baigal (sbaigal) <sbaigal@cisco.com>
Mon, 4 Mar 2024 21:21:51 +0000 (21:21 +0000)
Merge in SNORT/snort3 from ~RSHAFIQ/snort3:dyn_vector to master

Squashed commit of the following:

commit ebf9adff7693f9073fe08e63862779e9722232c4
Author: rshafiq <rshafiq@cisco.com>
Date:   Wed Jan 24 19:11:05 2024 -0500

    filters: updated dyn array with vector

src/detection/signature.cc
src/filters/sfthd.cc
src/filters/sfthd.h
src/utils/CMakeLists.txt
src/utils/dyn_array.cc [deleted file]
src/utils/dyn_array.h [deleted file]

index 8207a3dd89186eec9537ddf5ec5e4a09dabeafbc..f7c4f4ff2ba30f1fc8573c733a404dc91a3c98d0 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "actions/actions.h"
 #include "framework/decode_data.h"
+#include "filters/sfthd.h"
 #include "hash/hash_defs.h"
 #include "hash/ghash.h"
 #include "helpers/json_stream.h"
@@ -162,7 +163,7 @@ OptTreeNode::~OptTreeNode()
         snort_free(proto_nodes);
 
     if (detection_filter)
-        snort_free(detection_filter);
+        sfthd_node_free(detection_filter);
 
     delete sigInfo.body;
     delete[] buffer_setters;
index cf8fe221cb2feba8b9ef080e5b456d4b69588314..c0bdcafe4f223904a69f1b60e5abcb099fad580f 100644 (file)
  * sfthd.cc author Marc Norton
  *
  * An Abstracted Event Thresholding System
- *
- * 3/5/07 - man - fixed memory leak in global config to limit
- * of one gid=0, or multiple gid!=0 but not both.
- * Boris Lytochkin found it.
+ * 01/24/2024 -  updated the arrays with STL containers (Raza Shafiq: rshafiq@cisco.com)
  */
 
 #ifdef HAVE_CONFIG_H
 #include "sfthd.h"
 
 #include <cassert>
+#include <set>
 
 #include "hash/ghash.h"
 #include "hash/hash_defs.h"
 #include "hash/xhash.h"
 #include "main/thread.h"
 #include "sfip/sf_ipvar.h"
-#include "utils/dyn_array.h"
 #include "utils/sflsq.h"
 #include "utils/util.h"
 
 using namespace snort;
 
-//  Debug Printing
-//#define THD_DEBUG
-
 THREAD_LOCAL EventFilterStats event_filter_stats;
 
 XHash* sfthd_new_hash(unsigned nbytes, size_t key, size_t data)
@@ -82,11 +76,6 @@ XHash* sfthd_local_new(unsigned bytes)
         sizeof(THD_IP_NODE_KEY),
         sizeof(THD_IP_NODE));
 
-#ifdef THD_DEBUG
-    if ( !local_hash )
-        printf("Could not allocate the sfxhash table\n");
-#endif
-
     return local_hash;
 }
 
@@ -97,11 +86,6 @@ XHash* sfthd_global_new(unsigned bytes)
         sizeof(THD_IP_GNODE_KEY),
         sizeof(THD_IP_NODE));
 
-#ifdef THD_DEBUG
-    if ( !global_hash )
-        printf("Could not allocate the sfxhash table\n");
-#endif
-
     return global_hash;
 }
 
@@ -116,9 +100,6 @@ THD_STRUCT* sfthd_new(unsigned lbytes, unsigned gbytes)
     thd->ip_nodes = sfthd_local_new(lbytes);
     if ( !thd->ip_nodes )
     {
-#ifdef THD_DEBUG
-        printf("Could not allocate the sfxhash table\n");
-#endif
         snort_free(thd);
         return nullptr;
     }
@@ -130,9 +111,6 @@ THD_STRUCT* sfthd_new(unsigned lbytes, unsigned gbytes)
     thd->ip_gnodes = sfthd_global_new(gbytes);
     if ( !thd->ip_gnodes )
     {
-#ifdef THD_DEBUG
-        printf("Could not allocate the sfxhash table\n");
-#endif
         delete thd->ip_nodes;
         snort_free(thd);
         return nullptr;
@@ -143,7 +121,7 @@ THD_STRUCT* sfthd_new(unsigned lbytes, unsigned gbytes)
 
 ThresholdObjects* sfthd_objs_new()
 {
-    return (ThresholdObjects*)snort_calloc(sizeof(ThresholdObjects));
+    return new ThresholdObjects;
 }
 
 void sfthd_node_free(THD_NODE* sfthd_node)
@@ -152,9 +130,11 @@ void sfthd_node_free(THD_NODE* sfthd_node)
         return;
 
     if ( sfthd_node->ip_address )
+    {
         sfvar_free(sfthd_node->ip_address);
-
-    snort_free(sfthd_node);
+        sfthd_node->ip_address = nullptr;
+    }
+    delete sfthd_node;
 }
 
 static void sfthd_node_free(void* node)
@@ -162,63 +142,49 @@ static void sfthd_node_free(void* node)
 
 void sfthd_objs_free(ThresholdObjects* thd_objs)
 {
-    if (thd_objs == nullptr)
+    if ( thd_objs == nullptr )
         return;
 
-    for (int i = 0; i < THD_MAX_GENID; i++)
+    for ( const auto* hash : thd_objs->sfthd_vector )
     {
-        if ( thd_objs->sfthd_array[i] )
-            delete thd_objs->sfthd_array[i];
+        if ( hash )
+            delete hash;
     }
 
-    for (PolicyId policy_id = 0; policy_id < thd_objs->numPoliciesAllocated; policy_id++)
+    std::set<sfip_var_t*> deleted_ip_vars;
+    for (auto& policy_map : thd_objs->sfthd_gvector)
     {
-        if ( !thd_objs->sfthd_garray[policy_id] )
-            continue;
-
-        if ( thd_objs->sfthd_garray[policy_id][0] )
-        {
-            sfthd_node_free(thd_objs->sfthd_garray[policy_id][0]);
-
-            /* Free any individuals */
-            for (int i = 0; i < THD_MAX_GENID; i++)
-            {
-                if ( thd_objs->sfthd_garray[policy_id][i] !=
-                    thd_objs->sfthd_garray[policy_id][0] )
-                {
-                    sfthd_node_free(thd_objs->sfthd_garray[policy_id][i]);
-                }
-            }
-        }
-        else
+        for (auto& gen_id_and_node : policy_map)
         {
-            /* Anything other GID will be allocated individually */
-            for (int i = 1; i < THD_MAX_GENID; i++)
+            THD_NODE* node = gen_id_and_node.second.get();
+            if ( node )
             {
-                if ( thd_objs->sfthd_garray[policy_id][i] )
-                    sfthd_node_free(thd_objs->sfthd_garray[policy_id][i]);
+                auto ip_deleted = deleted_ip_vars.insert(node->ip_address);
+                if ( ip_deleted.second ) 
+                    sfvar_free(node->ip_address);
             }
         }
-
-        snort_free(thd_objs->sfthd_garray[policy_id]);
+        // Clear the map after handling ip_address in all nodes.
+        policy_map.clear();
     }
 
-    if ( thd_objs->sfthd_garray )
-        snort_free(thd_objs->sfthd_garray);
+    // If there's anything else in thd_objs that needs manual deletion or cleanup, do it here.
 
-    snort_free(thd_objs);
+    delete thd_objs;  // Finally, delete the container itself if necessary.
 }
 
+
+
 static void sfthd_item_free(void* item)
 {
     THD_ITEM* sfthd_item = (THD_ITEM*)item;
     sflist_free_all(sfthd_item->sfthd_node_list, sfthd_node_free);
-    snort_free(sfthd_item);
+    delete sfthd_item;
 }
 
 void sfthd_free(THD_STRUCT* thd)
 {
-    if (thd == nullptr)
+    if ( thd == nullptr )
         return;
 
     if ( thd->ip_nodes )
@@ -236,8 +202,8 @@ THD_NODE* sfthd_create_rule_threshold(int id,
     int count,
     unsigned int seconds)
 {
-    THD_NODE* sfthd_node = (THD_NODE*)snort_calloc(sizeof(THD_NODE));
-
+    THD_NODE* sfthd_node = new THD_NODE();
+    
     sfthd_node->thd_id    = id;
     sfthd_node->tracking  = tracking;
     sfthd_node->type      = type;
@@ -272,190 +238,100 @@ the current event should be logged or dropped.
 @return integer
 @retval  0 successfully added the thresholding object
 @retval !0 failed
-
 */
 static int sfthd_create_threshold_local(
     SnortConfig*, ThresholdObjects* thd_objs, THD_NODE* config, PolicyId policy_id)
 {
-    GHash* sfthd_hash;
-    THD_ITEM* sfthd_item;
-    THD_NODE* sfthd_node;
-    tThdItemKey key;
-
-    if (thd_objs == nullptr )
+    
+    if ( thd_objs == nullptr or config == nullptr )
         return -1;
-
+    
     if ( config->gen_id >= THD_MAX_GENID )
         return -1;
-
-    /* Check for an existing 'gen_id' entry, if none found create one. */
-    if (thd_objs->sfthd_array[config->gen_id] == nullptr)
-    {
-        int nrows;
-
-        if ( config->gen_id == 1 ) /* patmatch rules gen_id, many rules */
-        {
-            nrows= THD_GEN_ID_1_ROWS;
-        }
-        else  /* other gen_id's */
-        {
-            nrows= THD_GEN_ID_ROWS;
-        }
-
-        /* Create the hash table for this gen_id */
+    
+    if ( thd_objs->sfthd_vector.size() <= config->gen_id )
+        thd_objs->sfthd_vector.resize(config->gen_id + 1, nullptr);
+    
+    auto& sfthd_hash = thd_objs->sfthd_vector[config->gen_id];
+    if ( sfthd_hash == nullptr )
+    {
+        int nrows = (config->gen_id == 1) ? THD_GEN_ID_1_ROWS : THD_GEN_ID_ROWS;
         sfthd_hash = new GHash(nrows, sizeof(tThdItemKey), false, sfthd_item_free);
-        thd_objs->sfthd_array[config->gen_id] = sfthd_hash;
-    }
-    else
-    {
-        /* Get the hash table for this gen_id */
-        sfthd_hash = thd_objs->sfthd_array[config->gen_id];
     }
 
-    if (sfthd_hash == nullptr)
-        return -2;
-
+    tThdItemKey key;
     key.sig_id = config->sig_id;
     key.policyId = policy_id;
 
-    /* Check if sig_id is already in the table - if not allocate and add it */
-    sfthd_item = (THD_ITEM*)sfthd_hash->find((void*)&key);
+    
+    THD_ITEM* sfthd_item = static_cast<THD_ITEM*>(sfthd_hash->find(&key));
     if ( !sfthd_item )
     {
-        /* Create the sfthd_item hash node data */
-        sfthd_item = (THD_ITEM*)snort_calloc(sizeof(THD_ITEM));
-
-        sfthd_item->gen_id = config->gen_id;
-        sfthd_item->sig_id = config->sig_id;
-        sfthd_item->policyId = policy_id;
-        sfthd_item->sfthd_node_list = sflist_new();
-
-        if (!sfthd_item->sfthd_node_list)
+        sfthd_item = new THD_ITEM{ policy_id, config->gen_id, config->sig_id, sflist_new() };
+        if ( sfthd_item->sfthd_node_list == nullptr )
         {
-            snort_free(sfthd_item);
+            delete sfthd_item;
             return -4;
         }
 
-        /* Add the sfthd_item to the hash table */
-        if ( sfthd_hash->insert((void*)&key, sfthd_item) )
+        if ( sfthd_hash->insert(&key, sfthd_item) != HASH_OK )
         {
-            sflist_free(sfthd_item->sfthd_node_list);
-            snort_free(sfthd_item);
+            sflist_free_all(sfthd_item->sfthd_node_list, sfthd_node_free);
+            delete sfthd_item;
             return -5;
         }
     }
-
     /*
      * Test that we only have one Limit/Threshold/Both Object at the tail,
      * we can have multiple suppression nodes at the head
      */
-    if ( sfthd_item->sfthd_node_list->count > 0  )
+    if ( sfthd_item->sfthd_node_list->count > 0 )
     {
         THD_NODE* p;
-        if ( !sfthd_item->sfthd_node_list->tail)
+        if ( !sfthd_item->sfthd_node_list->tail )
         {
-            /* can you say paranoid- if there is a count, there should be a tail */
+            // Paranoid check: if there is a count, there should be a tail
             return -10;
         }
-        p = (THD_NODE*)sfthd_item->sfthd_node_list->tail->ndata;
-        if (p) /* just to be safe- if there is a tail, there is is node data */
+        p = static_cast<THD_NODE*>(sfthd_item->sfthd_node_list->tail->ndata);
+        if ( p ) // Ensure there is node data if there is a tail
         {
-            if ( p->type != THD_TYPE_SUPPRESS && config->type != THD_TYPE_SUPPRESS )
+            if ( p->type != THD_TYPE_SUPPRESS and config->type != THD_TYPE_SUPPRESS )
             {
-#ifdef THD_DEBUG
-                printf("THD_DEBUG: Could not add a 2nd Threshold object, "
-                    "you can only have 1 per sid: gid=%u, sid=%u\n",
-                    config->gen_id, config->sig_id);
-#endif
-                /* cannot add more than one threshold per sid in
-                   version 3.0, wait for 3.2 and CIDR blocks */
+                // Cannot add more than one threshold per sid in version 3.0
                 return THD_TOO_MANY_THDOBJ;
             }
         }
     }
 
-    /* Create a THD_NODE for this THD_ITEM (Object) */
-    sfthd_node = (THD_NODE*)snort_calloc(sizeof(THD_NODE));
-
-    /* Limit priorities to force suppression nodes to highest priority */
+    THD_NODE* sfthd_node = new THD_NODE(*config);  // Copy the node parameters
     if ( config->priority >= THD_PRIORITY_SUPPRESS )
-    {
-        config->priority  = THD_PRIORITY_SUPPRESS - 1;
-    }
-
-    /* Copy the node parameters */
-    sfthd_node->thd_id    = config->thd_id;
-    sfthd_node->gen_id    = config->gen_id;
-    sfthd_node->sig_id    = config->sig_id;
-    sfthd_node->tracking  = config->tracking; /* by_src, by_dst */
-    sfthd_node->type      = config->type;
-    sfthd_node->priority  = config->priority;
-    sfthd_node->count     = config->count;
-    sfthd_node->seconds   = config->seconds;
-    sfthd_node->ip_address= config->ip_address;
-
-    if ( config->type == THD_TYPE_SUPPRESS )
-    {
-        sfthd_node->priority = THD_PRIORITY_SUPPRESS;
-    }
-
-    /*
-      add the sfthd_node using priority to determine where in the list
-      it belongs
-
-      3.0 we can have only 1 threshold object but several suppression objects
-      plus a single threshold object is ok.  Blocking multiple threshold
-      objects is done above.
+        sfthd_node->priority = THD_PRIORITY_SUPPRESS - 1;
 
-      Suppressions have the highest priority and are at the front of the
-      list, the tail node is either a suppression node or the only pure
-      thresholding node.
-    */
+    if ( sfthd_item->sfthd_node_list->count > 0 )
     {
         SF_LNODE* lnode;
-        NODE_DATA ndata;
-
-        /* Walk the list and insert based on priorities if suppress */
-        for ( ndata = sflist_first(sfthd_item->sfthd_node_list, &lnode);
-            ndata;
-            ndata = sflist_next(&lnode) )
+        for ( auto ndata = sflist_first(sfthd_item->sfthd_node_list, &lnode);
+             ndata != nullptr; ndata = sflist_next(&lnode) )
         {
-            THD_NODE* sfthd_n = (THD_NODE*)ndata;
-
-            /* check if the new node is higher priority */
-            if ( sfthd_node->priority > sfthd_n->priority  )
+            THD_NODE* sfthd_n = static_cast<THD_NODE*>(ndata);
+            if ( sfthd_node->priority > sfthd_n->priority )
             {
-                /* insert before current node */
-#ifdef THD_DEBUG
-                printf("Threshold node added after based on priority\n"); fflush(stdout);
-#endif
-                sflist_add_before(sfthd_item->sfthd_node_list,lnode,sfthd_node);
+                sflist_add_before(sfthd_item->sfthd_node_list, lnode, sfthd_node);
                 return 0;
             }
 
-            /* last node, just insert it here */
-            if ( !lnode->next  )
+            if ( lnode->next == nullptr )
             {
-                /* if last node, insert at end of list */
-#ifdef THD_DEBUG
-                printf("Threshold node added to tail\n"); fflush(stdout);
-#endif
-                sflist_add_tail(sfthd_item->sfthd_node_list,sfthd_node);
+                sflist_add_tail(sfthd_item->sfthd_node_list, sfthd_node);
                 return 0;
             }
         }
+        delete sfthd_node;
+        return -11;
     }
-
-    /*
-     sfthd_node list is empty - add as head node
-     */
-    assert(!sfthd_item->sfthd_node_list->count);
-    {
-#ifdef THD_DEBUG
-        printf("Threshold node added to head of list\n"); fflush(stdout);
-#endif
-        sflist_add_head(sfthd_item->sfthd_node_list,sfthd_node);
-    }
+    else
+        sflist_add_head(sfthd_item->sfthd_node_list, sfthd_node);
 
     return 0;
 }
@@ -465,80 +341,27 @@ static int sfthd_create_threshold_local(
 static int sfthd_create_threshold_global(
     SnortConfig*, ThresholdObjects* thd_objs, THD_NODE* config, PolicyId policy_id)
 {
-    THD_NODE* sfthd_node;
-
-    if (thd_objs == nullptr)
+    if ( thd_objs == nullptr or config == nullptr or config->gen_id >= THD_MAX_GENID )
         return -1;
 
-    if (config->gen_id >= THD_MAX_GENID)
-        return -1;
+    if ( thd_objs->sfthd_gvector.size() <= policy_id )
+        thd_objs->sfthd_gvector.resize(policy_id + 1);
 
-    if (thd_objs->sfthd_garray[policy_id] == nullptr)
-    {
-        thd_objs->sfthd_garray[policy_id] =
-            (THD_NODE**)(snort_calloc(THD_MAX_GENID, sizeof(THD_NODE*)));
-    }
+    auto& map = thd_objs->sfthd_gvector[policy_id];
 
-    if ((config->gen_id == 0) &&
-        (thd_objs->sfthd_garray[policy_id][config->gen_id] != nullptr))
-    {
-        return THD_TOO_MANY_THDOBJ;
-    }
-    /* Reset the current threshold */
-    if (thd_objs->sfthd_garray[policy_id][config->gen_id] ==
-        thd_objs->sfthd_garray[policy_id][0])
-    {
-        thd_objs->sfthd_garray[policy_id][config->gen_id] = nullptr;
-    }
-    else if (thd_objs->sfthd_garray[policy_id][config->gen_id])
-    {
-        return THD_TOO_MANY_THDOBJ;
-    }
+    // Check if there is an existing entry for config->gen_id
+    if ( config->gen_id == 0 and map.find(0) != map.end() )
+        map.erase(config->gen_id);
 
-    sfthd_node = (THD_NODE*)snort_calloc(sizeof(THD_NODE));
-
-    /* Copy the node parameters */
-    sfthd_node->thd_id = config->thd_id;
-    sfthd_node->gen_id = config->gen_id;
-    sfthd_node->sig_id = config->sig_id;      /* -1 for global thresholds */
-    sfthd_node->tracking = config->tracking;  /* by_src, by_dst */
-    sfthd_node->type = config->type;
-    sfthd_node->priority = config->priority;
-    sfthd_node->count = config->count;
-    sfthd_node->seconds = config->seconds;
-    sfthd_node->ip_address = config->ip_address;
-
-    /* need a hash of these where
-     * key=[gen_id,sig_id] => THD_GNODE_KEY
-     * data = THD_NODE's
-     */
-    if (config->gen_id == 0) /* do em all */
-    {
-        int i;
+    if ( map.find(config->gen_id) != map.end() )
+            return THD_TOO_MANY_THDOBJ;
 
-        for (i = 0; i < THD_MAX_GENID; i++)
-        {
-            /* only assign if there wasn't a value */
-            if (thd_objs->sfthd_garray[policy_id][i] == nullptr)
-            {
-                thd_objs->sfthd_garray[policy_id][i] = sfthd_node;
-            }
-        }
-    }
-    else
-    {
-        thd_objs->sfthd_garray[policy_id][config->gen_id] = sfthd_node;
-    }
-
-#ifdef THD_DEBUG
-    printf("THD_DEBUG-GLOBAL: created global threshold object "
-        "for gen_id=%u\n",config->gen_id);
-    fflush(stdout);
-#endif
+    map.emplace(config->gen_id, std::make_unique<THD_NODE>(*config));
 
     return 0;
 }
 
+
 /*!
 Add a permanent threshold object to the threshold table. Multiple
 objects may be defined for each gen_id and sig_id pair. Internally
@@ -577,63 +400,40 @@ int sfthd_create_threshold(
     int type,
     int priority,
     int count,
-    int seconds,
+    unsigned seconds,
     sfip_var_t* ip_address, PolicyId policy_id)
 {
-    //allocate memory fpr sfthd_array if needed.
-    THD_NODE sfthd_node;
-    memset(&sfthd_node, 0, sizeof(sfthd_node));
-
-    thd_objs->count++;
-
-    sfthd_node.thd_id    = thd_objs->count;  /* produce a unique thd_id for this node */
-    sfthd_node.gen_id    = gen_id;
-    sfthd_node.sig_id    = sig_id;
-    sfthd_node.tracking  = tracking; /* by_src, by_dst */
-    sfthd_node.type      = type;
-    sfthd_node.priority  = priority;
-    sfthd_node.count     = count;
-    sfthd_node.seconds   = seconds;
-    sfthd_node.ip_address= ip_address;
-
-    // FIXIT-L convert to std::vector
-    sfDynArrayCheckBounds ((void**)&thd_objs->sfthd_garray, policy_id,
-        &thd_objs->numPoliciesAllocated);
-
-    if (thd_objs->sfthd_garray[policy_id] == nullptr)
-    {
-        thd_objs->sfthd_garray[policy_id] =
-            (THD_NODE**)snort_calloc(THD_MAX_GENID, sizeof(THD_NODE*));
-    }
+    
+    if ( thd_objs == nullptr ) 
+        return -1;
+
+    if ( thd_objs->sfthd_gvector.size() <= policy_id ) 
+        thd_objs->sfthd_gvector.resize(policy_id + 1);
 
+    if ( thd_objs->sfthd_vector.size() <= gen_id ) 
+        thd_objs->sfthd_vector.resize(gen_id + 1, nullptr);
+
+    THD_NODE sfthd_node { thd_objs->count++, // Increment count and use it as thd_id
+    gen_id, sig_id, tracking, // by_src, by_dst
+    type, priority, count, seconds, ip_address };
+    
     if ( sig_id == 0 )
-    {
         return sfthd_create_threshold_global(sc, thd_objs, &sfthd_node, policy_id);
-    }
 
-    if ( gen_id == 0 )
+    if ( gen_id == 0 ) 
         return -1;
 
     return sfthd_create_threshold_local(sc, thd_objs, &sfthd_node, policy_id);
 }
 
-#ifdef THD_DEBUG
-static char* printIP(unsigned u, char* buf, unsigned len)
-{
-    SnortSnprintf(buf, len, "%d.%d.%d.%d", (u>>24)&0xff, (u>>16)&0xff, (u>>8)&0xff, u&0xff);
-    return s;
-}
-
-#endif
 
 int sfthd_test_rule(XHash* rule_hash, THD_NODE* sfthd_node,
     const SfIp* sip, const SfIp* dip, long curtime, PolicyId policy_id)
 {
-    if ((rule_hash == nullptr) || (sfthd_node == nullptr))
+    if ( rule_hash == nullptr or sfthd_node == nullptr )
         return 0;
 
     int status = sfthd_test_local(rule_hash, sfthd_node, sip, dip, curtime, policy_id);
-
     return (status < -1) ? 1 : status;
 }
 
@@ -641,13 +441,9 @@ static inline int sfthd_test_suppress(
     THD_NODE* sfthd_node,
     const SfIp* ip)
 {
-    if ( !sfthd_node->ip_address ||
+    if ( !sfthd_node->ip_address or
         sfvar_ip_in(sfthd_node->ip_address, ip) )
     {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: SUPPRESS NODE, do not log events with this IP\n");
-        fflush(stdout);
-#endif
         /* Don't log, and stop looking( event's to this address
          * for this gen_id+sig_id) */
         return -1;
@@ -667,10 +463,6 @@ static inline int sfthd_test_non_suppress(
 
     if ( sfthd_node->type == THD_TYPE_DETECT )
     {
-#ifdef THD_DEBUG
-        printf("\n...Detect Test\n");
-        fflush(stdout);
-#endif
         dt = (unsigned)(curtime - sfthd_ip_node->tstart);
 
         if ( dt >= sfthd_node->seconds )
@@ -684,13 +476,7 @@ static inline int sfthd_test_non_suppress(
         }
         sfthd_ip_node->tlast = curtime;
 
-#ifdef THD_DEBUG
-        printf("...dt=%u, sfthd_node->seconds=%u\n",dt, sfthd_node->seconds);
-        printf("...sfthd_ip_node->count=%u, sfthd_node->count=%d\n",
-            sfthd_ip_node->count,sfthd_node->count);
-        fflush(stdout);
-#endif
-        if ( (int)sfthd_ip_node->count > sfthd_node->count ||
+        if ( (int)sfthd_ip_node->count > sfthd_node->count or
             (int)sfthd_ip_node->prev > sfthd_node->count )
         {
             return 0; /* Log it, stop looking: log all > 'count' events */
@@ -702,10 +488,6 @@ static inline int sfthd_test_non_suppress(
     }
     if ( sfthd_node->type == THD_TYPE_LIMIT )
     {
-#ifdef THD_DEBUG
-        printf("\n...Limit Test\n");
-        fflush(stdout);
-#endif
         dt = (unsigned)(curtime - sfthd_ip_node->tstart);
 
         if ( dt >= sfthd_node->seconds )
@@ -714,12 +496,6 @@ static inline int sfthd_test_non_suppress(
             sfthd_ip_node->count  = 1;
         }
 
-#ifdef THD_DEBUG
-        printf("...dt=%u, sfthd_node->seconds=%u\n",dt, sfthd_node->seconds);
-        printf("...sfthd_ip_node->count=%u, sfthd_node->count=%d\n",
-            sfthd_ip_node->count,sfthd_node->count);
-        fflush(stdout);
-#endif
         if ( (int)sfthd_ip_node->count <= sfthd_node->count )
         {
             return 0; /* Log it, stop looking: only log the 1st 'count' events */
@@ -731,10 +507,6 @@ static inline int sfthd_test_non_suppress(
     }
     else if ( sfthd_node->type == THD_TYPE_THRESHOLD )
     {
-#ifdef THD_DEBUG
-        printf("\n...Threshold Test\n");
-        fflush(stdout);
-#endif
         dt = (unsigned)(curtime - sfthd_ip_node->tstart);
         if ( dt >= sfthd_node->seconds )
         {
@@ -752,10 +524,6 @@ static inline int sfthd_test_non_suppress(
     }
     else if ( sfthd_node->type == THD_TYPE_BOTH )
     {
-#ifdef THD_DEBUG
-        printf("\n...Threshold+Limit Test\n");
-        fflush(stdout);
-#endif
         dt = (unsigned)(curtime - sfthd_ip_node->tstart);
         if ( dt >= sfthd_node->seconds )
         {
@@ -789,11 +557,6 @@ static inline int sfthd_test_non_suppress(
         }
     }
 
-#ifdef THD_DEBUG
-    printf("THD_DEBUG: You should not be here...\n");
-    fflush(stdout);
-#endif
-
     return 0;  /* should not get here, so log it just to be safe */
 }
 
@@ -826,50 +589,23 @@ int sfthd_test_local(
     THD_IP_NODE data,* sfthd_ip_node;
     const SfIp* ip;
 
-#ifdef THD_DEBUG
-    char buf[24];
-    printf("THD_DEBUG: Key THD_NODE IP=%s,",
-        printIP((unsigned)sfthd_node->ip_address, buf, sizeof(buf)) );
-    printf(" MASK=%s\n", printIP((unsigned)sfthd_node->ip_mask, buf, sizeof(buf)) );
-    printf("THD_DEBUG:        PKT  SIP=%s\n", printIP((unsigned)sip, buf, sizeof(buf)) );
-    printf("THD_DEBUG:        PKT  DIP=%s\n", printIP((unsigned)dip, buf, sizeof(buf)) );
-    fflush(stdout);
-#endif
-
-    /* -1 means don't do any limit or thresholding */
-    if ( sfthd_node->count == THD_NO_THRESHOLD)
-    {
-#ifdef THD_DEBUG
-        printf("\n...No Threshold applied for this object\n");
-        fflush(stdout);
-#endif
+    // -1 means don't do any limit or thresholding 
+    if ( sfthd_node->count == THD_NO_THRESHOLD )
         return 0;
-    }
 
-    /*
-     *  Get The correct IP
-     */
-    if (sfthd_node->tracking == THD_TRK_SRC)
+    // Get The correct IP
+    if ( sfthd_node->tracking == THD_TRK_SRC )
         ip = sip;
     else
         ip = dip;
 
-    /*
-     *  Check for and test Suppression of this event to this IP
-     */
+    // Check for and test Suppression of this event to this IP
     if ( sfthd_node->type == THD_TYPE_SUPPRESS )
-    {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: SUPPRESS NODE Testing...\n"); fflush(stdout);
-#endif
         return sfthd_test_suppress(sfthd_node, ip);
-    }
-
-    /*
-    *  Go on and do standard thresholding
-    */
+    
+    // Go on and do standard thresholding
 
-    /* Set up the key */
+    // Set up the key 
     key.policyId = policy_id;
     key.ip = *ip;
     key.thd_id = sfthd_node->thd_id;
@@ -880,10 +616,8 @@ int sfthd_test_local(
     data.prev   = 0;
     data.tstart = data.tlast = curtime; /* Event time */
 
-    /*
-     * Check for any Permanent sig_id objects for this gen_id  or add this one ...
-     */
-
+    // Check for any Permanent sig_id objects for this gen_id  or add this one ...
+    
     std::lock_guard<std::mutex> lock(sfthd_hash_mutex);
 
     int status = local_hash->insert((void*)&key, &data);
@@ -931,26 +665,10 @@ static inline int sfthd_test_global(
     THD_IP_NODE* sfthd_ip_node;
     const SfIp* ip;
 
-#ifdef THD_DEBUG
-    char buf[24];
-    printf("THD_DEBUG: Global THD_NODE IP=%s,",
-        printIP((unsigned)sfthd_node->ip_address, buf, sizeof(buf)) );
-    printf(" MASK=%s\n", printIP((unsigned)sfthd_node->ip_mask, buf, sizeof(buf)) );
-    printf("THD_DEBUG:        PKT  SIP=%s\n", printIP((unsigned)sip, buf, sizeof(buf)) );
-    printf("THD_DEBUG:        PKT  DIP=%s\n", printIP((unsigned)dip, buf, sizeof(buf)) );
-    fflush(stdout);
-#endif
-
     /* -1 means don't do any limit or thresholding */
     if ( sfthd_node->count == THD_NO_THRESHOLD)
-    {
-#ifdef THD_DEBUG
-        printf("\n...No Threshold applied for this object\n");
-        fflush(stdout);
-#endif
         return 0;
-    }
-
+    
     /* Get The correct IP */
     if (sfthd_node->tracking == THD_TRK_SRC)
         ip = sip;
@@ -959,13 +677,8 @@ static inline int sfthd_test_global(
 
     /* Check for and test Suppression of this event to this IP */
     if ( sfthd_node->type == THD_TYPE_SUPPRESS )
-    {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: G-SUPPRESS NODE Testing...\n"); fflush(stdout);
-#endif
         return sfthd_test_suppress(sfthd_node, ip);
-    }
-
+    
     /*
     *  Go on and do standard thresholding
     */
@@ -984,7 +697,7 @@ static inline int sfthd_test_global(
 
     /* Check for any Permanent sig_id objects for this gen_id  or add this one ...  */
     int status = global_hash->insert((void*)&key, &data);
-    if (status == HASH_INTABLE)
+    if ( status == HASH_INTABLE )
     {
         /* Already in the table */
         sfthd_ip_node = (THD_IP_NODE*)global_hash->get_user_data();
@@ -992,12 +705,12 @@ static inline int sfthd_test_global(
         /* Increment the event count */
         sfthd_ip_node->count++;
     }
-    else if (status == HASH_NOMEM)
+    else if ( status == HASH_NOMEM )
     {
         event_filter_stats.xhash_nomem_peg_global++;
         return 1;
     }
-    else if (status != HASH_OK)
+    else if ( status != HASH_OK )
     {
         /* hash error */
         return 1; /*  check the next threshold object */
@@ -1039,163 +752,67 @@ int sfthd_test_threshold(
     long curtime,
     PolicyId policy_id)
 {
-    tThdItemKey key;
-    GHash* sfthd_hash;
-    THD_ITEM* sfthd_item;
-    THD_NODE* sfthd_node;
-    THD_NODE* g_thd_node = nullptr;
-#ifdef THD_DEBUG
-    int cnt;
-#endif
-
-    if ((thd_objs == nullptr) || (thd == nullptr))
-        return 0;
+    if ( thd_objs == nullptr or thd == nullptr or gen_id >= THD_MAX_GENID )
+        return 0; // Invalid parameters or gen_id
 
-#ifdef THD_DEBUG
-    printf("sfthd_test_threshold...\n"); fflush(stdout);
-#endif
-
-    if ( gen_id >= THD_MAX_GENID )
+    // Check if the gen_id exists in sfthd_vector
+    if ( gen_id < thd_objs->sfthd_vector.size() )
     {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: invalid gen_id=%u\n",gen_id);
-        fflush(stdout);
-#endif
-        return 0; /* bogus gen_id */
-    }
+        GHash* sfthd_hash = thd_objs->sfthd_vector[gen_id];
 
-    /*
-     *  Get the hash table for this gen_id
-     */
-    sfthd_hash = thd_objs->sfthd_array[gen_id];
-    if (sfthd_hash == nullptr)
-    {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: no hash table entry for gen_id=%u\n",gen_id);
-        fflush(stdout);
-#endif
-        goto global_test;
-        /* return 0; */ /* no threshold objects for this gen_id, log it ! */
-    }
+        if ( sfthd_hash != nullptr )
+        {
+            tThdItemKey key = { policy_id, sig_id };
+            THD_ITEM* sfthd_item = static_cast<THD_ITEM*>(sfthd_hash->find(&key));
 
-    key.sig_id = sig_id;
-    key.policyId = policy_id;
-    /*
-     * Check for any Permanent sig_id objects for this gen_id
-     */
-    sfthd_item = (THD_ITEM*)sfthd_hash->find((void*)&key);
-    if (sfthd_item == nullptr)
-    {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG: no THD objects for gen_id=%u, sig_id=%u\n",gen_id,sig_id);
-        fflush(stdout);
-#endif
-        /* no matching permanent sig_id objects so, log it ! */
-        goto global_test;
+            if ( sfthd_item != nullptr and sfthd_item->sfthd_node_list != nullptr )
+            {
+                SF_LNODE* cursor;
+                for ( THD_NODE* sfthd_node = static_cast<THD_NODE*>(sflist_first(sfthd_item->sfthd_node_list, &cursor));
+                     sfthd_node != nullptr;
+                     sfthd_node = static_cast<THD_NODE*>(sflist_next(&cursor)) )
+                {
+                    int status = sfthd_test_local(thd->ip_nodes, sfthd_node, sip, dip, curtime, policy_id);
+                    if ( status <= 0 )
+                        return (status < -1) ? 1 : status;
+                }
+            }
+        }
     }
 
-    /* No List of Threshold objects - bail and log it */
-    if (sfthd_item->sfthd_node_list == nullptr)
+    // Global threshold test
+    if (policy_id < thd_objs->sfthd_gvector.size())
     {
-        goto global_test;
-    }
-
-    /* For each permanent thresholding object, test/add/update the thd object
-       We maintain a list of thd objects for each gen_id+sig_id
-       each object has it's own unique thd_id
-       Suppression nodes have a very high priority, so they are tested 1st */
-#ifdef THD_DEBUG
-    cnt=0;
-#endif
-    SF_LNODE* cursor;
+        auto& g_thd_map = thd_objs->sfthd_gvector[policy_id];
 
-    for (sfthd_node = (THD_NODE*)sflist_first(sfthd_item->sfthd_node_list, &cursor);
-        sfthd_node != nullptr;
-        sfthd_node = (THD_NODE*)sflist_next(&cursor))
-    {
-#ifdef THD_DEBUG
-        cnt++;
-        printf("THD_DEBUG: gen_id=%u sig_id=%u testing thd_id=%d thd_type=%d\n",
-            gen_id, sig_id, sfthd_node->thd_id, sfthd_node->type);
-        fflush(stdout);
-#endif
-        /*
-         *   Test SUPPRESSION and THRESHOLDING
-         */
-        int status = sfthd_test_local(thd->ip_nodes, sfthd_node, sip, dip, curtime, policy_id);
+        auto it = g_thd_map.find(gen_id);
+        if ( gen_id != 0 and it == g_thd_map.end() )
+            it = g_thd_map.find(0);
 
-        if ( status < 0 ) /* -1 == Don't log and stop looking */
-        {
-#ifdef THD_DEBUG
-            printf("THD_DEBUG: gen_id=%u sig_id=%u, UnLoggable %d\n\n",gen_id, sig_id,cnt);
-            fflush(stdout);
-#endif
-            return (status < -1) ? 1 : -1;  /* !0 == Don't log it*/
-        }
-        else if ( status == 0 )  /* Log it and stop looking */
+        if ( it != g_thd_map.end() )
         {
-#ifdef THD_DEBUG
-            printf("THD_DEBUG: gen_id=%u sig_id=%u tested %d THD_NODE's, "
-                "Loggable\n\n",sfthd_item->gen_id, sfthd_item->sig_id,cnt);
-            fflush(stdout);
-#endif
-            return 0; /* 0 == Log the event */
+            THD_NODE* g_thd_node = it->second.get(); // Get the raw pointer from the unique_ptr
+            if ( g_thd_node != nullptr )
+            {
+                int status = sfthd_test_global(thd->ip_gnodes, g_thd_node, sig_id, sip, dip, curtime, policy_id);
+                if ( status <= 0 )
+                    return (status < -1) ? 1 : status;
+            }
         }
-        /* status > 0 : Log it later but Keep looking
-         * check the next threshold object for a blocking action ...
-         */
     }
 
-    /*
-     * Test for a global threshold object
-     * we're here cause there were no threshold objects for this gen_id/sig_id pair
-     */
-global_test:
-
-#ifdef THD_DEBUG
-    printf("THD_DEBUG-GLOBAL: doing global object test\n");
-#endif
 
-    if (thd_objs->sfthd_garray && thd_objs->sfthd_garray[policy_id])
-    {
-        g_thd_node = thd_objs->sfthd_garray[policy_id][gen_id];
-    }
+    return 0; // Default to loggable if no blocking action is found
+}
 
-    if ( g_thd_node )
-    {
-        int status = sfthd_test_global(thd->ip_gnodes, g_thd_node, sig_id,
-                sip, dip, curtime, policy_id);
 
-        if ( status < 0 ) /* -1 == Don't log and stop looking */
-        {
 #ifdef THD_DEBUG
-            printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u THD_NODE's, "
-                "UnLoggable\n\n",gen_id, sig_id);
-            fflush(stdout);
-#endif
-            return (status < -1) ? 1 : -1;  /* !0 == Don't log it*/
-        }
 
-        /* Log it ! */
-#ifdef THD_DEBUG
-        printf("THD_DEBUG-GLOBAL: gen_id=%u sig_id=%u  THD_NODE's, "
-            "Loggable\n\n",gen_id, sig_id);
-        fflush(stdout);
-#endif
-    }
-    else
-    {
-#ifdef THD_DEBUG
-        printf("THD_DEBUG-GLOBAL: no Global THD Object for gen_id=%u, "
-            "sig_id=%u\n\n",gen_id, sig_id);
-        fflush(stdout);
-#endif
-    }
-
-    return 0; /* Default: Log it if we did not block the logging action */
+static char* printIP(unsigned u, char* buf, unsigned len)
+{
+    SnortSnprintf(buf, len, "%d.%d.%d.%d", (u>>24)&0xff, (u>>16)&0xff, (u>>8)&0xff, u&0xff);
+    return s;
 }
-
-#ifdef THD_DEBUG
 /*!
  *   A function to print the thresholding objects to stdout.
  *
index 0e3d8368a16d2dc7d734e9cddb5b567c0919e52c..f28316f8ad183a9e68181a0ba3f4293ea50765fc 100644 (file)
@@ -29,6 +29,7 @@
 #include "utils/cpp_macros.h"
 
 #include <mutex>
+#include <vector>
 
 namespace snort
 {
@@ -129,15 +130,15 @@ PADDING_GUARD_END
 */
 struct THD_NODE
 {
-    int thd_id;        /* Id of this node */
-    unsigned gen_id;   /* Keep these around if needed */
-    unsigned sig_id;
-    int tracking;      /* by_src, by_dst */
-    int type;
-    int priority;
-    int count;
-    unsigned seconds;
-    sfip_var_t* ip_address;
+    int thd_id = 0;        /* Id of this node */
+    unsigned gen_id = 0;   /* Keep these around if needed */
+    unsigned sig_id = 0;
+    int tracking = 0;      /* by_src, by_dst */
+    int type = 0;
+    int priority = 0;
+    int count = 0;
+    unsigned seconds = 0;
+    sfip_var_t* ip_address = nullptr;
 };
 
 /*!
@@ -198,19 +199,19 @@ struct THD_STRUCT
 
 struct ThresholdObjects
 {
-    int count;  /* Total number of thresholding/suppression objects */
-    snort::GHash* sfthd_array[THD_MAX_GENID];    /* Local Hash of THD_ITEM nodes,  lookup by key=sig_id
-                                              */
-
-    /* Double array of THD_NODE pointers. First index is policyId and therefore variable length.
-     * Second index is genId and of fixed length, A simpler definition could be
-     * THD_NODE * sfthd_garray[0][THD_MAX_GENID] and we could intentionally overflow first index,
-     * but we may have to deal with compiler warnings if the array is indexed by value known at
-     * compile time.
-     */
-    //THD_NODE * (*sfthd_garray)[THD_MAX_GENID];
-    THD_NODE*** sfthd_garray;
-    PolicyId numPoliciesAllocated;
+    int count = 0;  /* Total number of thresholding/suppression objects */
+    std::vector<snort::GHash*> sfthd_vector;    /* Local Hash of THD_ITEM nodes,  lookup by key=sig_id */
+    /*
+    * Vector of unordered maps, each map indexed by generator ID (genId) and containing 
+    * unique pointers to THD_NODE structures. The outer vector is indexed by policyId 
+    * and can dynamically vary in size. Each map represents THD_NODE structures for a specific 
+    * policyId, with the key being the genId. This allows direct access to THD_NODE structures 
+    * by their generator ID within a given policy context, optimizing lookup and management 
+    * of thresholding nodes.
+    */
+    std::vector<std::unordered_map<uint32_t, std::unique_ptr<THD_NODE>>> sfthd_gvector;
+
+    PolicyId numPoliciesAllocated = 0;
 };
 
 struct EventFilterStats
@@ -245,7 +246,7 @@ void sfthd_node_free(THD_NODE*);
 
 int sfthd_create_threshold(snort::SnortConfig*, ThresholdObjects*, unsigned gen_id,
     unsigned sig_id, int tracking, int type, int priority, int count,
-    int seconds, sfip_var_t* ip_address, PolicyId policy_id);
+    unsigned seconds, sfip_var_t* ip_address, PolicyId policy_id);
 
 //  1: don't log due to event_filter
 //  0: log
index 9973a56c23c7f5754dfca9c0a476082d073b7bce..8e9766f735dfcfbd0122f5e045e67b113e5ae299 100644 (file)
@@ -24,8 +24,6 @@ add_library ( utils OBJECT
     ${SNPRINTF_SOURCES}
     boyer_moore.cc
     dnet_header.h
-    dyn_array.cc
-    dyn_array.h
     kmap.cc
     sflsq.cc
     snort_bounds.h
diff --git a/src/utils/dyn_array.cc b/src/utils/dyn_array.cc
deleted file mode 100644 (file)
index 1253ce3..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2024 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2008-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "dyn_array.h"
-
-#include "util.h"
-
-// number of additional policies allocated with each re-alloc operation
-#define POLICY_ALLOCATION_CHUNK 10
-
-int sfDynArrayCheckBounds(  // FIXIT-L replace with vector
-    void** dynArray,
-    unsigned int index,
-    unsigned int* maxElements
-    )
-{
-    void* ppTmp = nullptr;
-
-    if (index >= *maxElements)
-    {
-        //expand the array
-        ppTmp = snort_calloc(index+POLICY_ALLOCATION_CHUNK, sizeof(void*));
-
-        if (*maxElements)
-        {
-            memcpy(ppTmp, *dynArray, sizeof(void*)*(*maxElements));
-            snort_free(*dynArray);
-        }
-
-        *dynArray = ppTmp;
-        *maxElements = index + POLICY_ALLOCATION_CHUNK;
-    }
-
-    return 0;
-}
-
diff --git a/src/utils/dyn_array.h b/src/utils/dyn_array.h
deleted file mode 100644 (file)
index e38756a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-//--------------------------------------------------------------------------
-// Copyright (C) 2014-2024 Cisco and/or its affiliates. All rights reserved.
-// Copyright (C) 2008-2013 Sourcefire, Inc.
-//
-// This program is free software; you can redistribute it and/or modify it
-// under the terms of the GNU General Public License Version 2 as published
-// by the Free Software Foundation.  You may not use, modify or distribute
-// this program under any other version of the GNU General Public License.
-//
-// This program is distributed in the hope that it will be useful, but
-// WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
-//--------------------------------------------------------------------------
-
-#ifndef DYN_ARRAY_H
-#define DYN_ARRAY_H
-
-int sfDynArrayCheckBounds(  // FIXIT-L change return type to bool
-    void** dynArray, unsigned int index, unsigned int* maxElements);
-
-#endif
-