* 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)
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;
}
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;
}
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;
}
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;
ThresholdObjects* sfthd_objs_new()
{
- return (ThresholdObjects*)snort_calloc(sizeof(ThresholdObjects));
+ return new ThresholdObjects;
}
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)
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 )
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;
@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;
}
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
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;
}
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;
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 )
}
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 */
}
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 )
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 */
}
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 )
{
}
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 )
{
}
}
-#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 */
}
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;
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);
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;
/* 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
*/
/* 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();
/* 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 */
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.
*