#define HASH_RULE_OPTIONS 16384
#define HASH_RULE_TREE 8192
-#define HASH_EQUAL 0
-#define HASH_NOT_EQUAL 1
-
struct detection_option_key_t
{
option_type_t option_type;
return 0;
}
-static int detection_option_key_compare_func(const void* k1, const void* k2, size_t)
+static bool detection_option_key_compare_func(const void* k1, const void* k2, size_t)
{
const detection_option_key_t* key1 = (const detection_option_key_t*)k1;
const detection_option_key_t* key2 = (const detection_option_key_t*)k2;
- if ( !key1 || !key2 )
- return HASH_NOT_EQUAL;
+ assert(key1 && key2);
if ( key1->option_type != key2->option_type )
- return HASH_NOT_EQUAL;
+ return false;
if ( key1->option_type != RULE_OPTION_TYPE_LEAF_NODE )
{
IpsOption* opt2 = (IpsOption*)key2->option_data;
if ( *opt1 == *opt2 )
- return HASH_EQUAL;
+ return true;
}
- return HASH_NOT_EQUAL;
+ return false;
}
static int detection_hash_free_func(void* option_key, void*)
static XHash* DetectionHashTableNew()
{
- XHash* doht = xhash_new(HASH_RULE_OPTIONS,
- sizeof(detection_option_key_t),
- 0, /* Data size == 0, just store the ptr */
- 0, /* Memcap */
- 0, /* Auto node recovery */
- nullptr, /* Auto free function */
- detection_hash_free_func, /* User free function */
- 1); /* Recycle nodes */
-
- if (doht == nullptr)
- FatalError("Failed to create rule detection option hash table");
+ XHash* doht = new XHash(HASH_RULE_OPTIONS, sizeof(detection_option_key_t),
+ 0, 0, false, nullptr, detection_hash_free_func, true);
- xhash_set_keyops(doht, detection_option_hash_func, detection_option_key_compare_func);
+ doht->set_key_opcodes(detection_option_hash_func, detection_option_key_compare_func);
return doht;
}
void DetectionHashTableFree(XHash* doht)
{
- if (doht != nullptr)
- xhash_delete(doht);
+ delete doht;
}
void* add_detection_option(SnortConfig* sc, option_type_t type, void* option_data)
key.option_type = type;
key.option_data = option_data;
- if ( void* p = xhash_find(sc->detection_option_hash_table, &key) )
+ if ( void* p = sc->detection_option_hash_table->get_user_data(&key) )
return p;
- xhash_add(sc->detection_option_hash_table, &key, option_data);
+ sc->detection_option_hash_table->insert(&key, option_data);
return nullptr;
}
static bool detection_option_tree_compare(
const detection_option_tree_node_t* r, const detection_option_tree_node_t* l)
{
- if ( !r and !l )
- return HASH_EQUAL;
-
- if ( !r or !l )
- return HASH_NOT_EQUAL;
+ assert(r and l);
if ( r->option_data != l->option_data )
- return HASH_NOT_EQUAL;
+ return false;
if ( r->num_children != l->num_children )
- return HASH_NOT_EQUAL;
+ return false;
- for ( int i=0; i<r->num_children; i++ )
+ for ( int i = 0; i < r->num_children; i++ )
{
/* Recurse & check the children for equality */
- int ret = detection_option_tree_compare(r->children[i], l->children[i]);
-
- if ( ret != HASH_EQUAL )
- return ret;
+ if ( !detection_option_tree_compare(r->children[i], l->children[i]) )
+ return false;
}
- return HASH_EQUAL;
+ return true;
}
-static int detection_option_tree_compare_func(const void* k1, const void* k2, size_t)
+static bool detection_option_tree_compare_func(const void* k1, const void* k2, size_t)
{
const detection_option_key_t* key_r = (const detection_option_key_t*)k1;
const detection_option_key_t* key_l = (const detection_option_key_t*)k2;
if ( !key_r or !key_l )
- return HASH_NOT_EQUAL;
+ return false;
const detection_option_tree_node_t* r = (const detection_option_tree_node_t*)key_r->option_data;
const detection_option_tree_node_t* l = (const detection_option_tree_node_t*)key_l->option_data;
void DetectionTreeHashTableFree(XHash* dtht)
{
- if (dtht != nullptr)
- xhash_delete(dtht);
+ delete dtht;
}
static XHash* DetectionTreeHashTableNew()
{
- XHash* dtht = xhash_new(
- HASH_RULE_TREE,
- sizeof(detection_option_key_t),
- 0, /* Data size == 0, just store the ptr */
- 0, /* Memcap */
- 0, /* Auto node recovery */
- nullptr, /* Auto free function */
- detection_option_tree_free_func, /* User free function */
- 1); /* Recycle nodes */
-
- if (dtht == nullptr)
- FatalError("Failed to create rule detection option hash table");
+ XHash* dtht = new XHash(HASH_RULE_TREE, sizeof(detection_option_key_t),
+ 0, 0, false, nullptr, detection_option_tree_free_func, true);
- xhash_set_keyops(dtht, detection_option_tree_hash_func, detection_option_tree_compare_func);
+ dtht->set_key_opcodes(detection_option_tree_hash_func, detection_option_tree_compare_func);
return dtht;
}
key.option_data = (void*)option_tree;
key.option_type = RULE_OPTION_TYPE_LEAF_NODE;
- if ( void* p = xhash_find(sc->detection_option_tree_hash_table, &key) )
+ if ( void* p = sc->detection_option_tree_hash_table->get_user_data(&key) )
return p;
- xhash_add(sc->detection_option_tree_hash_table, &key, option_tree);
+ sc->detection_option_tree_hash_table->insert(&key, option_tree);
return nullptr;
}
if ( !doth )
return;
- for ( auto hnode = xhash_findfirst(doth); hnode; hnode = xhash_findnext(doth) )
+ for ( auto hnode = doth->find_first_node(); hnode; hnode = doth->find_next_node() )
{
auto* node = (detection_option_tree_node_t*)hnode->data;
assert(node);
{
struct Packet;
struct SnortConfig;
-struct XHash;
+class XHash;
}
struct RuleLatencyState;
return 0;
}
-static int fpFinishPortGroup(
- SnortConfig* sc, PortGroup* pg, FastPatternConfig* fp)
+static int fpFinishPortGroup(SnortConfig* sc, PortGroup* pg, FastPatternConfig* fp)
{
int i;
int rules = 0;
PortGroup* group;
};
-static int fpCreateInitRuleMap(
+static void fpCreateInitRuleMap(
PORT_RULE_MAP* prm, PortTable* src, PortTable* dst, PortObject* any)
{
/* setup the any-port content port group */
/* Process src PORT groups */
if ( src )
{
- for ( GHashNode* node = ghash_findfirst(src->pt_mpxo_hash);
- node;
- node=ghash_findnext(src->pt_mpxo_hash) )
+ for (GHashNode* node = src->pt_mpxo_hash->find_first();
+ node;
+ node = src->pt_mpxo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
continue;
/* Add up the total src rules */
- prm->prmNumSrcRules += po->rule_hash->count;
+ prm->prmNumSrcRules += po->rule_hash->get_count();
/* Increment the port group count */
prm->prmNumSrcGroups++;
/* process destination port groups */
if ( dst )
{
- for ( GHashNode* node=ghash_findfirst(dst->pt_mpxo_hash);
- node;
- node=ghash_findnext(dst->pt_mpxo_hash) )
+ for (GHashNode* node = dst->pt_mpxo_hash->find_first();
+ node;
+ node = dst->pt_mpxo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
continue;
/* Add up the total src rules */
- prm->prmNumDstRules += po->rule_hash->count;
+ prm->prmNumDstRules += po->rule_hash->get_count();
/* Increment the port group count */
prm->prmNumDstGroups++;
PortObject2Iterate(po, PortIteratorData::set, &pit_data);
}
}
-
- return 0;
}
/*
* Create and initialize the rule maps
*/
-static int fpCreateRuleMaps(SnortConfig* sc, RulePortTables* p)
+static void fpCreateRuleMaps(SnortConfig* sc, RulePortTables* p)
{
sc->prmIpRTNX = prmNewMap();
sc->prmIcmpRTNX = prmNewMap();
sc->prmTcpRTNX = prmNewMap();
sc->prmUdpRTNX = prmNewMap();
- if (fpCreateInitRuleMap(sc->prmIpRTNX, p->ip.src, p->ip.dst, p->ip.any))
- return -1;
-
- if (fpCreateInitRuleMap(sc->prmIcmpRTNX, p->icmp.src, p->icmp.dst, p->icmp.any))
- return -1;
-
- if (fpCreateInitRuleMap(sc->prmTcpRTNX, p->tcp.src, p->tcp.dst, p->tcp.any))
- return -1;
-
- if (fpCreateInitRuleMap(sc->prmUdpRTNX, p->udp.src, p->udp.dst, p->udp.any))
- return -1;
-
- return 0;
+ fpCreateInitRuleMap(sc->prmIpRTNX, p->ip.src, p->ip.dst, p->ip.any);
+ fpCreateInitRuleMap(sc->prmIcmpRTNX, p->icmp.src, p->icmp.dst, p->icmp.any);
+ fpCreateInitRuleMap(sc->prmTcpRTNX, p->tcp.src, p->tcp.dst, p->tcp.any);
+ fpCreateInitRuleMap(sc->prmUdpRTNX, p->udp.src, p->udp.dst, p->udp.any);
}
static void fpFreeRuleMaps(SnortConfig* sc)
* content and uricontent based on the rules in the PortObjects
* hash table.
*/
-static int fpCreatePortObject2PortGroup(
- SnortConfig* sc, PortObject2* po, PortObject2* poaa)
+static void fpCreatePortObject2PortGroup(SnortConfig* sc, PortObject2* po, PortObject2* poaa)
{
- GHashNode* node;
- unsigned sid, gid;
- OptTreeNode* otn;
- PortGroup* pg;
- PortObject2* pox;
- FastPatternConfig* fp = sc->fast_pattern_config;
-
- /* verify we have a port object */
- if (po == nullptr)
- return 0;
+ assert( po );
po->group = nullptr;
-
- if (fp->get_debug_print_rule_group_build_details())
+ FastPatternConfig* fp = sc->fast_pattern_config;
+ if ( fp->get_debug_print_rule_group_build_details() )
PortObject2PrintPorts(po);
/* Check if we have any rules */
- if (po->rule_hash == nullptr)
- return 0;
+ if ( !po->rule_hash )
+ return;
/* create a port_group */
- pg = PortGroup::alloc();
+ PortGroup* pg = PortGroup::alloc();
s_group = "port";
/*
* (src/dst or any-any ports)
*
*/
- pox = po;
-
- while (pox != nullptr)
+ PortObject2* pox = po;
+ while ( pox )
{
- for (node = ghash_findfirst(pox->rule_hash);
- node;
- node = ghash_findnext(pox->rule_hash))
+ for (GHashNode* node = pox->rule_hash->find_first();
+ node;
+ node = pox->rule_hash->find_next())
{
+ unsigned sid, gid;
int* prindex = (int*)node->data;
/* be safe - no rule index, ignore it */
parser_get_rule_ids(*prindex, gid, sid);
/* look up otn */
- otn = OtnLookup(sc->otn_map, gid, sid);
+ OptTreeNode* otn = OtnLookup(sc->otn_map, gid, sid);
assert(otn);
if ( is_network_protocol(otn->snort_protocol_id) )
pox = poaa;
}
- /* This might happen if there was ip proto only rules
- * Don't return failure */
+ // This might happen if there was ip proto only rules...Don't return failure
if (fpFinishPortGroup(sc, pg, fp) != 0)
- return 0;
+ return;
po->group = pg;
- return 0;
+ return;
}
/*
* Create the port groups for this port table
*/
-static int fpCreatePortTablePortGroups(
- SnortConfig* sc, PortTable* p, PortObject2* poaa)
+static void fpCreatePortTablePortGroups(SnortConfig* sc, PortTable* p, PortObject2* poaa)
{
- GHashNode* node;
- int cnt=1;
+ int cnt = 1;
FastPatternConfig* fp = sc->fast_pattern_config;
+ if ( fp->get_debug_print_rule_group_build_details() )
+ LogMessage("%d Port Groups in Port Table\n",p->pt_mpo_hash->get_count());
- if (fp->get_debug_print_rule_group_build_details())
- LogMessage("%d Port Groups in Port Table\n",p->pt_mpo_hash->count);
-
- for (node=ghash_findfirst(p->pt_mpo_hash);
- node;
- node=ghash_findnext(p->pt_mpo_hash) )
+ for (GHashNode* node = p->pt_mpo_hash->find_first();
+ node;
+ node = p->pt_mpo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
-
if ( !po )
continue;
if (fp->get_debug_print_rule_group_build_details())
- LogMessage("Creating Port Group Object %d of %d\n",cnt++,p->pt_mpo_hash->count);
+ LogMessage("Creating Port Group Object %d of %d\n", cnt++, p->pt_mpo_hash->get_count());
/* if the object is not referenced, don't add it to the PortGroups
* as it may overwrite other objects that are more inclusive. */
- if (!po->port_cnt)
+ if ( !po->port_cnt )
continue;
- if (fpCreatePortObject2PortGroup(sc, po, poaa))
- {
- LogMessage("fpCreatePortObject2PortGroup() failed\n");
- return -1;
- }
+ fpCreatePortObject2PortGroup(sc, po, poaa);
}
-
- return 0;
}
/*
*/
static int fpCreatePortGroups(SnortConfig* sc, RulePortTables* p)
{
- PortObject2* po2, * add_any_any;
- FastPatternConfig* fp = sc->fast_pattern_config;
-
if (!get_rule_count())
return 0;
- /* IP */
- if ( !(po2 = PortObject2Dup(p->ip.any)) )
- FatalError("Could not create a PortObject2 for ip-any rules\n");
+ FastPatternConfig* fp = sc->fast_pattern_config;
+ bool log_rule_group_details = fp->get_debug_print_rule_group_build_details();
- add_any_any = fp->get_split_any_any() ? nullptr : po2;
+ /* IP */
+ PortObject2* po2 = PortObject2Dup(*p->ip.any);
+ PortObject2* add_any_any = fp->get_split_any_any() ? nullptr : po2;
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nIP-SRC ");
- if (fpCreatePortTablePortGroups(sc, p->ip.src, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-ip.src\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->ip.src, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nIP-DST ");
- if (fpCreatePortTablePortGroups(sc, p->ip.dst, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-ip.dst\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->ip.dst, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nIP-ANY ");
- if (fpCreatePortObject2PortGroup(sc, po2, nullptr))
- {
- LogMessage("fpCreatePorTablePortGroups failed-ip any\n");
- return -1;
- }
-
+ fpCreatePortObject2PortGroup(sc, po2, nullptr);
p->ip.any->group = po2->group;
po2->group = nullptr;
PortObject2Free(po2);
/* ICMP */
- if ( !(po2 = PortObject2Dup(p->icmp.any)) )
- FatalError("Could not create a PortObject2 for icmp-any rules\n");
-
+ po2 = PortObject2Dup(*p->icmp.any);
add_any_any = fp->get_split_any_any() ? nullptr : po2;
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nICMP-SRC ");
- if (fpCreatePortTablePortGroups(sc, p->icmp.src, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-icmp.src\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->icmp.src, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nICMP-DST ");
- if (fpCreatePortTablePortGroups(sc, p->icmp.dst, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-icmp.src\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->icmp.dst, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nICMP-ANY ");
- if (fpCreatePortObject2PortGroup(sc, po2, nullptr))
- {
- LogMessage("fpCreatePorTablePortGroups failed-icmp any\n");
- return -1;
- }
-
+ fpCreatePortObject2PortGroup(sc, po2, nullptr);
p->icmp.any->group = po2->group;
po2->group = nullptr;
PortObject2Free(po2);
- if ( !(po2 = PortObject2Dup(p->tcp.any)) )
- FatalError("Could not create a PortObject2 for tcp-any rules\n");
-
+ po2 = PortObject2Dup(*p->tcp.any);
add_any_any = fp->get_split_any_any() ? nullptr : po2;
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nTCP-SRC ");
- if (fpCreatePortTablePortGroups(sc, p->tcp.src, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-tcp.src\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->tcp.src, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nTCP-DST ");
- if (fpCreatePortTablePortGroups(sc, p->tcp.dst, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-tcp.dst\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->tcp.dst, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nTCP-ANY ");
- if (fpCreatePortObject2PortGroup(sc, po2, nullptr))
- {
- LogMessage("fpCreatePorTablePortGroups failed-tcp any\n");
- return -1;
- }
-
+ fpCreatePortObject2PortGroup(sc, po2, nullptr);
p->tcp.any->group = po2->group;
po2->group = nullptr;
PortObject2Free(po2);
/* UDP */
- if ( !(po2 = PortObject2Dup(p->udp.any)) )
- FatalError("Could not create a PortObject2 for udp-any rules\n");
-
+ po2 = PortObject2Dup(*p->udp.any);
add_any_any = fp->get_split_any_any() ? nullptr : po2;
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nUDP-SRC ");
- if (fpCreatePortTablePortGroups(sc, p->udp.src, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-udp.src\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->udp.src, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nUDP-DST ");
- if (fpCreatePortTablePortGroups(sc, p->udp.dst, add_any_any))
- {
- LogMessage("fpCreatePorTablePortGroups failed-udp.dst\n");
- return -1;
- }
+ fpCreatePortTablePortGroups(sc, p->udp.dst, add_any_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nUDP-ANY ");
- if (fpCreatePortObject2PortGroup(sc, po2, nullptr))
- {
- LogMessage("fpCreatePorTablePortGroups failed-udp.any\n");
- return -1;
- }
-
+ fpCreatePortObject2PortGroup(sc, po2, nullptr);
p->udp.any->group = po2->group;
po2->group = nullptr;
PortObject2Free(po2);
/* SVC */
- if ( !(po2 = PortObject2Dup(p->svc_any)) )
- FatalError("Could not create a PortObject2 for svc-any rules\n");
+ po2 = PortObject2Dup(*p->svc_any);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("\nSVC-ANY ");
- if (fpCreatePortObject2PortGroup(sc, po2, nullptr))
- {
- LogMessage("fpCreatePorTablePortGroups failed-svc_any\n");
- return -1;
- }
-
+ fpCreatePortObject2PortGroup(sc, po2, nullptr);
p->svc_any->group = po2->group;
po2->group = nullptr;
PortObject2Free(po2);
*/
SF_LNODE* cursor;
- for ( OptTreeNode* otn = (OptTreeNode*)sflist_first(list, &cursor);
- otn;
- otn = (OptTreeNode*)sflist_next(&cursor) )
+ for (OptTreeNode* otn = (OptTreeNode*)sflist_first(list, &cursor);
+ otn;
+ otn = (OptTreeNode*)sflist_next(&cursor) )
{
fpAddPortGroupRule(sc, pg, otn, fp, true);
}
return;
/* Add the port_group using it's service name */
- ghash_add(p, srvc, pg);
+ p->insert(srvc, pg);
}
/*
static void fpBuildServicePortGroups(
SnortConfig* sc, GHash* spg, PortGroupVector& sopg, GHash* srm, FastPatternConfig* fp)
{
- for ( GHashNode* n = ghash_findfirst(srm);
- n;
- n=ghash_findnext(srm) )
+ for (GHashNode* n = srm->find_first(); n; n = srm->find_next())
{
SF_LIST* list = (SF_LIST*)n->data;
const char* srvc = (const char*)n->key;
fpBuildServicePortGroupByServiceOtnList(sc, spg, srvc, list, fp);
/* Add this PortGroup to the protocol-ordinal -> port_group table */
- PortGroup* pg = (PortGroup*)ghash_find(spg, srvc);
+ PortGroup* pg = (PortGroup*)spg->find(srvc);
if ( !pg )
{
ParseError("*** failed to create and find a port group for '%s'",srvc);
{
GHashNode* n;
- if ( !p || !p->count )
+ if ( !p || !p->get_count() )
return;
std::string label = "service rule counts - ";
label += dir;
LogLabel(label.c_str());
- for ( n = ghash_findfirst(p);
- n;
- n = ghash_findnext(p) )
+ for (n = p->find_first(); n; n = p->find_next())
{
SF_LIST* list;
static void fp_print_service_rules(SnortConfig* sc, GHash* cli, GHash* srv)
{
- if ( !cli->count and !srv->count )
+ if ( !cli->get_count() and !srv->get_count() )
return;
LogLabel("service rule counts to-srv to-cli");
while ( const char* svc = sc->proto_ref->get_name_sorted(idx++) )
{
- SF_LIST* clist = (SF_LIST*)ghash_find(cli, svc);
- SF_LIST* slist = (SF_LIST*)ghash_find(srv, svc);
+ SF_LIST* clist = (SF_LIST*)cli->find(svc);
+ SF_LIST* slist = (SF_LIST*)srv->find(svc);
if ( !clist and !slist )
continue;
static void fp_sum_service_groups(GHash* h, unsigned c[PM_TYPE_MAX])
{
- for ( GHashNode* node=ghash_findfirst(h);
- node; node=ghash_findnext(h) )
+ for (GHashNode* node = h->find_first();
+ node;
+ node = h->find_next())
{
PortGroup* pg = (PortGroup*)node->data;
fp_sum_port_groups(pg, c);
static void fp_sum_port_groups(PortTable* tab, unsigned c[PM_TYPE_MAX])
{
- for ( GHashNode* node=ghash_findfirst(tab->pt_mpxo_hash);
- node; node=ghash_findnext(tab->pt_mpxo_hash) )
+ for (GHashNode* node = tab->pt_mpxo_hash->find_first();
+ node;
+ node = tab->pt_mpxo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
fp_sum_port_groups(po->group, c);
* Build Service based PortGroups using the rules
* metadata option service parameter.
*/
-static int fpCreateServicePortGroups(SnortConfig* sc)
+static void fpCreateServicePortGroups(SnortConfig* sc)
{
FastPatternConfig* fp = sc->fast_pattern_config;
sc->srmmTable = ServiceMapNew();
- if (fpCreateServiceMaps(sc))
- return -1;
-
+ fpCreateServiceMaps(sc);
fp_print_service_rules_by_proto(sc);
if ( fp->get_debug_print_rule_group_build_details() )
ServiceMapFree(sc->srmmTable);
sc->srmmTable = nullptr;
- return 0;
}
static unsigned can_build_mt(FastPatternConfig* fp)
RulePortTables* port_tables = sc->port_tables;
FastPatternConfig* fp = sc->fast_pattern_config;
+ bool log_rule_group_details = fp->get_debug_print_rule_group_build_details();
assert(port_tables);
assert(fp);
MpseManager::start_search_engine(fp->get_search_api());
/* Use PortObjects to create PortGroups */
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("Creating Port Groups....\n");
- if (fpCreatePortGroups(sc, port_tables))
- FatalError("Could not create PortGroup objects for PortObjects\n");
+ fpCreatePortGroups(sc, port_tables);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
+ {
LogMessage("Port Groups Done....\n");
-
- /* Create rule_maps */
- if (fp->get_debug_print_rule_group_build_details())
LogMessage("Creating Rule Maps....\n");
+ }
- if (fpCreateRuleMaps(sc, port_tables))
- FatalError("Could not create rule maps\n");
+ /* Create rule_maps */
+ fpCreateRuleMaps(sc, port_tables);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
+ {
LogMessage("Rule Maps Done....\n");
-
- if (fp->get_debug_print_rule_group_build_details())
LogMessage("Creating Service Based Rule Maps....\n");
+ }
/* Build Service based port groups - rules require service metdata
* i.e. 'metatdata: service [=] service-name, ... ;'
*
* Also requires a service attribute for lookup ...
*/
- if (fpCreateServicePortGroups(sc))
- FatalError("Could not create service based port groups\n");
+ fpCreateServicePortGroups(sc);
- if (fp->get_debug_print_rule_group_build_details())
+ if ( log_rule_group_details )
LogMessage("Service Based Rule Maps Done....\n");
if ( !sc->test_mode() or sc->mem_check() )
LogLabel("search engine");
MpseManager::print_mpse_summary(fp->get_search_api());
}
+
if ( offload_mpse_count and (fp->get_offload_search_api()))
{
LogLabel("offload search engine");
static inline void init_match_info(OtnxMatchData* omd)
{
- for ( int i = 0; i < SnortConfig::get_conf()->num_rule_types; i++ )
+ for ( unsigned i = 0; i < SnortConfig::get_conf()->num_rule_types; i++ )
omd->matchInfo[i].iMatchCount = 0;
omd->have_match = false;
* If its order is lower than 'pass', it should have been passed.
* This is consistent with other detection rules */
if ( (p->packet_flags & PKT_PASS_RULE)
- &&(SnortConfig::get_eval_index(rtn->action) > SnortConfig::get_eval_index(Actions::PASS)))
+ && (SnortConfig::get_eval_index(rtn->action) > SnortConfig::get_eval_index(Actions::PASS)) )
{
fpLogOther(p, rtn, otn, rtn->action);
return 1;
int fpAddMatch(OtnxMatchData* omd, const OptTreeNode* otn)
{
RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
- int evalIndex = rtn->listhead->ruleListNode->evalIndex;
+ unsigned evalIndex = rtn->listhead->ruleListNode->evalIndex;
/* bounds check index */
if ( evalIndex >= SnortConfig::get_conf()->num_rule_types )
** If we hit the max number of unique events for any rule type alert,
** log or pass, then we don't add it to the list.
*/
- if ( pmi->iMatchCount >= (int)SnortConfig::get_conf()->fast_pattern_config->get_max_queue_events() ||
+ if ( pmi->iMatchCount >= SnortConfig::get_conf()->fast_pattern_config->get_max_queue_events() ||
pmi->iMatchCount >= MAX_EVENT_MATCH)
{
pc.match_limit++;
}
// don't store the same otn again
- for ( int i=0; i< pmi->iMatchCount; i++ )
+ for ( unsigned i = 0; i < pmi->iMatchCount; i++ )
{
- if ( pmi->MatchArray[ i ] == otn )
+ if ( pmi->MatchArray[i] == otn )
return 0;
}
// add the event to the appropriate list
pmi->MatchArray[ pmi->iMatchCount ] = otn;
-
pmi->iMatchCount++;
omd->have_match = true;
return 0;
if ( !omd->have_match )
return 0;
- int i;
- int j;
- int k;
- const OptTreeNode* otn;
unsigned tcnt = 0;
EventQueueConfig* eq = SnortConfig::get_conf()->event_queue_config;
- RuleTreeNode* rtn;
+ int (*compar)(const void *, const void *);
+ compar = ( eq->order == SNORT_EVENTQ_PRIORITY )
+ ? &sortOrderByPriority : sortOrderByContentLength;
- for ( i = 0; i < SnortConfig::get_conf()->num_rule_types; i++ )
+ for ( unsigned i = 0; i < SnortConfig::get_conf()->num_rule_types; i++ )
{
/* bail if were not dumping events in all the action groups,
* and we've already got some events */
if (!SnortConfig::process_all_events() && (tcnt > 0))
return 1;
- if (omd->matchInfo[i].iMatchCount)
+ if ( omd->matchInfo[i].iMatchCount )
{
/*
* We must always sort so if we que 8 and log 3 and they are
* part of the natural ordering....Jan '06..
*/
/* Sort the rules in this action group */
- if (eq->order == SNORT_EVENTQ_PRIORITY)
- {
- qsort(omd->matchInfo[i].MatchArray, omd->matchInfo[i].iMatchCount,
- sizeof(void*), sortOrderByPriority);
- }
- else if (eq->order == SNORT_EVENTQ_CONTENT_LEN)
- {
- qsort(omd->matchInfo[i].MatchArray, omd->matchInfo[i].iMatchCount,
- sizeof(void*), sortOrderByContentLength);
- }
- else
- {
- FatalError("fpdetect: Order function for event queue is invalid.\n");
- }
+ qsort(omd->matchInfo[i].MatchArray, omd->matchInfo[i].iMatchCount,
+ sizeof(void*), compar);
/* Process each event in the action (alert,drop,log,...) groups */
- for (j=0; j < omd->matchInfo[i].iMatchCount; j++)
+ for (unsigned j = 0; j < omd->matchInfo[i].iMatchCount; j++)
{
- otn = omd->matchInfo[i].MatchArray[j];
- rtn = getRtnFromOtn(otn);
+ const OptTreeNode* otn = omd->matchInfo[i].MatchArray[j];
+ RuleTreeNode* rtn = getRtnFromOtn(otn);
- if (otn && rtn && Actions::is_pass(rtn->action))
+ if ( otn && rtn && Actions::is_pass(rtn->action) )
{
/* Already acted on rules, so just don't act on anymore */
if ( tcnt > 0 )
}
// Loop here so we don't log the same event multiple times.
- for (k = 0; k < j; k++)
+ for (unsigned k = 0; k < j; k++)
{
- if (omd->matchInfo[i].MatchArray[k] == otn)
+ if ( omd->matchInfo[i].MatchArray[k] == otn )
{
otn = nullptr;
break;
pc.alert_limit++;
/* Only count it if we're going to log it */
- if (tcnt <= eq->log_events)
+ if ( tcnt <= eq->log_events )
{
if ( p->flow )
fpAddSessionAlert(p, otn);
}
- if (tcnt >= eq->max_events)
+ if ( tcnt >= eq->max_events )
{
pc.queue_limit++;
return 1;
}
/* only log/count one pass */
- if ( otn && rtn && Actions::is_pass(rtn->action))
+ if ( otn && rtn && Actions::is_pass(rtn->action) )
{
p->packet_flags |= PKT_PASS_RULE;
return 1;
{
public:
MpseStash(unsigned limit)
- {
- enable = false;
- max = limit;
- }
+ : max(limit)
+ { }
void init()
{
{ enable = true; }
private:
- bool enable;
- unsigned count;
+ bool enable = false;
+ unsigned count = 0;
unsigned max;
std::vector<Node> queue;
struct MatchInfo
{
const OptTreeNode* MatchArray[MAX_EVENT_MATCH];
- int iMatchCount;
- int iMatchIndex;
- int iMatchMaxLen;
+ unsigned iMatchCount;
+ unsigned iMatchIndex;
+ unsigned iMatchMaxLen;
};
/*
PORT_RULE_MAP* prmNewMap()
{
- PORT_RULE_MAP* p = (PORT_RULE_MAP*)snort_calloc(sizeof(PORT_RULE_MAP));
- return p;
+ return (PORT_RULE_MAP*)snort_calloc(sizeof(PORT_RULE_MAP));
}
/*
{
ListHead* RuleList; /* The rule list associated with this node */
snort::Actions::Type mode; /* the rule mode */
- int evalIndex; /* eval index for this rule set */
+ unsigned evalIndex; /* eval index for this rule set */
char* name; /* name of this rule list */
RuleListNode* next; /* the next RuleListNode */
};
static GHash* alloc_srvmap()
{
// nodes are lists,free them in ghash_delete
- GHash* p = ghash_new(1000, 0, 0, (void (*)(void*))sflist_free);
- return p;
+ return new GHash(1000, 0, 0, (void (*)(void*))sflist_free);
}
static void free_srvmap(GHash* table)
{
if ( table )
- ghash_delete(table);
+ delete table;
}
srmm_table_t* ServiceMapNew()
static GHash* alloc_spgmm()
{
// 1000 rows, ascii key
- GHash* p = ghash_new(1000, 0, 0, delete_pg);
- return p;
+ return new GHash(1000, 0, 0, delete_pg);
}
static void free_spgmm(GHash* table)
if ( !table )
return;
- ghash_delete(table);
+ delete table;
}
srmm_table_t* ServicePortGroupMapNew()
*/
static void ServiceMapAddOtnRaw(GHash* table, const char* servicename, OptTreeNode* otn)
{
- SF_LIST* list = (SF_LIST*)ghash_find(table, servicename);
+ SF_LIST* list = (SF_LIST*)table->find(servicename);
if ( !list )
{
list = sflist_new();
- ghash_add(table, servicename, list);
+ table->insert(servicename, list);
}
sflist_add_tail(list, otn);
* each service map maintains a list of otn's for each service it maps to a
* service name.
*/
-static int ServiceMapAddOtn(
+static void ServiceMapAddOtn(
srmm_table_t* srmm, SnortProtocolId, const char* servicename, OptTreeNode* otn)
{
assert(servicename and otn);
if ( !OtnFlowFromServer(otn) )
ServiceMapAddOtnRaw(srmm->to_srv, servicename, otn);
-
- return 0;
}
void fpPrintServicePortGroupSummary(SnortConfig* sc)
LogMessage("| Service-PortGroup Table Summary \n");
LogMessage("---------------------------------\n");
- if ( unsigned n = sc->spgmmTable->to_srv->count )
+ if ( unsigned n = sc->spgmmTable->to_srv->get_count() )
LogMessage("| server : %d services\n", n);
- if ( unsigned n = sc->spgmmTable->to_cli->count )
+ if ( unsigned n = sc->spgmmTable->to_cli->get_count() )
LogMessage("| client : %d services\n", n);
LogMessage("---------------------------------\n");
* Scan the master otn lists and load the Service maps
* for service based rule grouping.
*/
-int fpCreateServiceMaps(SnortConfig* sc)
+void fpCreateServiceMaps(SnortConfig* sc)
{
- RuleTreeNode* rtn;
- GHashNode* hashNode;
- OptTreeNode* otn = nullptr;
- unsigned int svc_idx;
-
- for (hashNode = ghash_findfirst(sc->otn_map);
- hashNode;
- hashNode = ghash_findnext(sc->otn_map))
+ for (GHashNode* hashNode = sc->otn_map->find_first();
+ hashNode;
+ hashNode = sc->otn_map->find_next())
{
- otn = (OptTreeNode*)hashNode->data;
- for ( PolicyId policyId = 0;
- policyId < otn->proto_node_num;
- policyId++ )
+ OptTreeNode* otn = (OptTreeNode*)hashNode->data;
+ for (PolicyId policyId = 0;
+ policyId < otn->proto_node_num;
+ policyId++ )
{
- rtn = getRtnFromOtn(otn, policyId);
-
+ RuleTreeNode* rtn = getRtnFromOtn(otn, policyId);
if ( rtn )
{
// skip builtin rules
if ( !rtn->enabled() )
continue;
- for (svc_idx = 0; svc_idx < otn->sigInfo.num_services; svc_idx++)
+ for (unsigned svc_idx = 0; svc_idx < otn->sigInfo.num_services; svc_idx++)
{
const char* svc = otn->sigInfo.services[svc_idx].service;
-
- if ( ServiceMapAddOtn(sc->srmmTable, rtn->snort_protocol_id, svc, otn) )
- return -1;
+ ServiceMapAddOtn(sc->srmmTable, rtn->snort_protocol_id, svc, otn);
}
}
}
}
-
- return 0;
}
//-------------------------------------------------------------------------
namespace snort
{
struct SnortConfig;
-struct GHash;
+class GHash;
}
struct PortGroup;
void ServicePortGroupMapFree(srmm_table_t*);
void fpPrintServicePortGroupSummary(snort::SnortConfig*);
-int fpCreateServiceMaps(snort::SnortConfig*);
+void fpCreateServiceMaps(snort::SnortConfig*);
// Service/Protocol Ordinal To PortGroup table
typedef std::vector<PortGroup*> PortGroupVector;
key.gid = otn->sigInfo.gid;
key.sid = otn->sigInfo.sid;
- ghash_remove(otn_map, &key);
+ otn_map->remove(&key);
}
void OtnFree(void* data)
GHash* OtnLookupNew()
{
- return ghash_new(10000, sizeof(OtnKey), 0, OtnFree);
+ return new GHash(10000, sizeof(OtnKey), 0, OtnFree);
}
void OtnLookupAdd(GHash* otn_map, OptTreeNode* otn)
key.gid = otn->sigInfo.gid;
key.sid = otn->sigInfo.sid;
- int status = ghash_add(otn_map, &key, otn);
-
+ int status = otn_map->insert(&key, otn);
if ( status == GHASH_OK )
return;
key.gid = gid;
key.sid = sid;
- OptTreeNode* otn = (OptTreeNode*)ghash_find(otn_map, &key);
+ OptTreeNode* otn = (OptTreeNode*)otn_map->find(&key);
return otn;
}
void OtnLookupFree(GHash* otn_map)
{
if ( otn_map )
- ghash_delete(otn_map);
+ delete otn_map;
}
namespace snort
{
-struct GHash;
+class GHash;
struct SnortConfig;
}
static inline void SwapTag(TagNode*);
/**Calculated memory needed per node insertion into respective cache. Its includes
- * memory needed for allocating TagNode, XHashNode, and key size.
+ * memory needed for allocating TagNode, HashNode and key size.
*
* @param hash - pointer to XHash that should point to either ssn_tag_cache_ptr
* or host_tag_cache_ptr.
*
* @returns number of bytes needed
*/
-static inline unsigned int memory_per_node(
- XHash* hash
- )
+static inline unsigned int memory_per_node(XHash* hash)
{
- if (hash == ssn_tag_cache_ptr)
- {
- return sizeof(tTagFlowKey)+sizeof(XHashNode)+sizeof(TagNode);
- }
- else if (hash == host_tag_cache_ptr)
- {
- return sizeof(SfIp)+sizeof(XHashNode)+sizeof(TagNode);
- }
+ if ( hash == ssn_tag_cache_ptr )
+ return sizeof(tTagFlowKey) + sizeof(HashNode) + sizeof(TagNode);
+ else if ( hash == host_tag_cache_ptr )
+ return sizeof(SfIp) + sizeof(HashNode) + sizeof(TagNode);
return 0;
}
{
unsigned int hashTableSize = TAG_MEMCAP/sizeof(TagNode);
- ssn_tag_cache_ptr = xhash_new(
- hashTableSize, /* number of hash buckets */
- sizeof(tTagFlowKey), /* size of the key we're going to use */
- 0, /* size of the storage node */
- 0, /* disable memcap*/
- 0, /* use auto node recovery */
- nullptr, /* anr free function */
- TagFreeSessionNodeFunc, /* user free function */
- 0); /* recycle node flag */
-
- host_tag_cache_ptr = xhash_new(
- hashTableSize, /* number of hash buckets */
- sizeof(SfIp), /* size of the key we're going to use */
- 0, /* size of the storage node */
- 0, /* disable memcap*/
- 0, /* use auto node recovery */
- nullptr, /* anr free function */
- TagFreeHostNodeFunc, /* user free function */
- 0); /* recycle node flag */
+ ssn_tag_cache_ptr = new XHash(hashTableSize, sizeof(tTagFlowKey), 0, 0,
+ false, nullptr, TagFreeSessionNodeFunc, false);
+
+ host_tag_cache_ptr = new XHash(hashTableSize, sizeof(SfIp), 0, 0, false,
+ nullptr, TagFreeHostNodeFunc, false);
}
void CleanupTag()
{
- if (ssn_tag_cache_ptr)
- {
- xhash_delete(ssn_tag_cache_ptr);
- }
-
- if (host_tag_cache_ptr)
- {
- xhash_delete(host_tag_cache_ptr);
- }
+ delete ssn_tag_cache_ptr;
+ delete host_tag_cache_ptr;
}
static void TagSession(Packet* p, TagData* tag, uint32_t time, uint16_t event_id, void* log_list)
}
/* check for duplicates */
- returned = (TagNode*)xhash_find(tag_cache_ptr, idx);
+ returned = (TagNode*)tag_cache_ptr->get_user_data(idx);
if (returned == nullptr)
{
SwapTag(idx);
- returned = (TagNode*)xhash_find(tag_cache_ptr, idx);
+ returned = (TagNode*)tag_cache_ptr->get_user_data(idx);
SwapTag(idx);
}
SwapTag(idx);
}
- if (xhash_add(tag_cache_ptr, idx, idx) != XHASH_OK)
+ if (tag_cache_ptr->insert(idx, idx) != HASH_OK)
{
TagFree(tag_cache_ptr, idx);
return;
char create_event = 1;
/* check for active tags */
- if (!xhash_count(host_tag_cache_ptr) && !xhash_count(ssn_tag_cache_ptr))
+ if (!host_tag_cache_ptr->get_node_count() && !ssn_tag_cache_ptr->get_node_count())
{
return 0;
}
idx.key.dp = p->ptrs.dp;
/* check for session tags... */
- returned = (TagNode*)xhash_find(ssn_tag_cache_ptr, &idx);
+ returned = (TagNode*)ssn_tag_cache_ptr->get_user_data(&idx);
if (returned == nullptr)
{
idx.key.dp = p->ptrs.sp;
idx.key.sp = p->ptrs.dp;
- returned = (TagNode*)xhash_find(ssn_tag_cache_ptr, &idx);
+ returned = (TagNode*)ssn_tag_cache_ptr->get_user_data(&idx);
if (returned == nullptr)
{
- returned = (TagNode*)xhash_find(host_tag_cache_ptr, &idx);
+ returned = (TagNode*)host_tag_cache_ptr->get_user_data(&idx);
if (returned == nullptr)
{
*/
idx.key.sip = *p->ptrs.ip_api.get_src();
- returned = (TagNode*)xhash_find(host_tag_cache_ptr, &idx);
+ returned = (TagNode*)host_tag_cache_ptr->get_user_data(&idx);
}
if (returned != nullptr)
if ( !returned->metric )
{
- if (xhash_remove(taglist, returned) != XHASH_OK)
+ if (taglist->release_node(returned) != HASH_OK)
{
LogMessage("WARNING: failed to remove tagNode from hash.\n");
}
if (mustdie == 0)
{
- if (xhash_count(ssn_tag_cache_ptr) != 0)
- {
+ if (ssn_tag_cache_ptr->get_node_count() != 0)
pruned = PruneTime(ssn_tag_cache_ptr, thetime);
- }
- if (xhash_count(host_tag_cache_ptr) != 0)
- {
+ if (host_tag_cache_ptr->get_node_count() != 0)
pruned += PruneTime(host_tag_cache_ptr, thetime);
- }
}
else
{
while (pruned < mustdie &&
- (xhash_count(ssn_tag_cache_ptr) > 0 || xhash_count(host_tag_cache_ptr) > 0))
+ (ssn_tag_cache_ptr->get_node_count() > 0 || host_tag_cache_ptr->get_node_count() > 0))
{
TagNode* lru_node;
- if ((lru_node = (TagNode*)xhash_lru(ssn_tag_cache_ptr)) != nullptr)
+ if ((lru_node = (TagNode*)ssn_tag_cache_ptr->get_lru_user_data()) != nullptr)
{
- if (xhash_remove(ssn_tag_cache_ptr, lru_node) != XHASH_OK)
+ if (ssn_tag_cache_ptr->release_node(lru_node) != HASH_OK)
{
LogMessage("WARNING: failed to remove tagNode from hash.\n");
}
pruned++;
}
- if ((lru_node = (TagNode*)xhash_lru(host_tag_cache_ptr)) != nullptr)
+ if ((lru_node = (TagNode*)host_tag_cache_ptr->get_lru_user_data()) != nullptr)
{
- if (xhash_remove(host_tag_cache_ptr, lru_node) != XHASH_OK)
+ if (host_tag_cache_ptr->release_node(lru_node) != HASH_OK)
{
LogMessage("WARNING: failed to remove tagNode from hash.\n");
}
int pruned = 0;
TagNode* lru_node = nullptr;
- while ((lru_node = (TagNode*)xhash_lru(tree)) != nullptr)
+ while ((lru_node = (TagNode*)tree->get_lru_user_data()) != nullptr)
{
if ((lru_node->last_access + TAG_PRUNE_QUANTUM) < thetime)
{
- if (xhash_remove(tree, lru_node) != XHASH_OK)
+ if (tree->release_node(lru_node) != HASH_OK)
{
LogMessage("WARNING: failed to remove tagNode from hash.\n");
}
// ptr to list of RTNs (head part); indexed by policyId
RuleTreeNode** proto_nodes = nullptr;
-
OtnState* state = nullptr;
-
int chain_node_number = 0;
- int evalIndex = 0; /* where this rule sits in the evaluation sets */
-
+ unsigned evalIndex = 0; /* where this rule sits in the evaluation sets */
unsigned ruleIndex = 0; // unique index
-
uint32_t num_detection_opts = 0;
uint32_t plugins = 0;
-
- // Added for integrity checks during rule parsing.
- SnortProtocolId snort_protocol_id = 0;
-
+ SnortProtocolId snort_protocol_id = 0; // Added for integrity checks during rule parsing.
unsigned short proto_node_num = 0;
uint16_t longestPatternLen = 0;
-
IpsPolicy::Enable enable;
Flag flags = 0;
FileCache::FileCache(int64_t max_files_cached)
{
max_files = max_files_cached;
- fileHash = xhash_new(max_files, sizeof(FileHashKey), sizeof(FileNode),
- 0, 1, file_cache_anr_free_func, file_cache_free_func, 1);
- if (!fileHash)
- FatalError("Failed to create the expected channel hash table.\n");
- xhash_set_max_nodes(fileHash, max_files);
+ fileHash = new XHash(max_files, sizeof(FileHashKey), sizeof(FileNode),
+ 0, true, file_cache_anr_free_func, file_cache_free_func, true);
+ fileHash->set_max_nodes(max_files);
}
FileCache::~FileCache()
{
- if (fileHash)
- {
- xhash_delete(fileHash);
- }
+ delete fileHash;
}
void FileCache::set_block_timeout(int64_t timeout)
}
else
max_files = max;
- xhash_set_max_nodes(fileHash, max_files);
+ fileHash->set_max_nodes(max_files);
}
FileContext* FileCache::add(const FileHashKey& hashKey, int64_t timeout)
std::lock_guard<std::mutex> lock(cache_mutex);
- if (xhash_add(fileHash, (void*)&hashKey, &new_node) != XHASH_OK)
+ if (fileHash->insert((void*)&hashKey, &new_node) != HASH_OK)
{
/* Uh, shouldn't get here...
* There is already a node or couldn't alloc space
{
std::lock_guard<std::mutex> lock(cache_mutex);
- if (!xhash_count(fileHash))
+ if (!fileHash->get_node_count())
{
return nullptr;
}
- XHashNode* hash_node = xhash_find_node(fileHash, &hashKey);
+ HashNode* hash_node = fileHash->find_node(&hashKey);
if (!hash_node)
return nullptr;
FileNode* node = (FileNode*)hash_node->data;
if (!node)
{
- xhash_free_node(fileHash, hash_node);
+ fileHash->release_node(hash_node);
return nullptr;
}
if (timercmp(&node->cache_expire_time, &now, <))
{
- xhash_free_node(fileHash, hash_node);
+ fileHash->release_node(hash_node);
return nullptr;
}
namespace snort
{
-struct XHash;
-struct XHashNode;
+class XHash;
}
class FileCache
void FileIdentifier::init_merge_hash()
{
- identifier_merge_hash = ghash_new(1000, sizeof(MergeNode), 0, nullptr);
- assert(identifier_merge_hash);
+ identifier_merge_hash = new GHash(1000, sizeof(MergeNode), 0, nullptr);
}
FileIdentifier::~FileIdentifier()
{
/*Release memory used for identifiers*/
for (auto mem_block:id_memory_blocks)
- {
snort_free(mem_block);
- }
if (identifier_merge_hash != nullptr)
- {
- ghash_delete(identifier_merge_hash);
- }
+ delete identifier_merge_hash;
}
void* FileIdentifier::calloc_mem(size_t size)
/*This function examines whether to update the trie based on shared state*/
-bool FileIdentifier::update_next(IdentifierNode* start,IdentifierNode** next_ptr,
+bool FileIdentifier::update_next(IdentifierNode* start, IdentifierNode** next_ptr,
IdentifierNode* append)
{
IdentifierNode* next = (*next_ptr);
set_node_state_shared(append);
return false;
}
- else if ((result = (IdentifierNode*)ghash_find(identifier_merge_hash, &merge_node)))
+ else if ((result = (IdentifierNode*)identifier_merge_hash->find(&merge_node)))
{
/*the same pointer has been processed, reuse it*/
*next_ptr = result;
set_node_state_shared(next);
next = node;
- ghash_add(identifier_merge_hash, &merge_node, next);
+ identifier_merge_hash->insert(&merge_node, next);
}
else if (next->state == ID_NODE_SHARED)
{
merge_node.append_node = append;
next = clone_node(current_next);
set_node_state_shared(next);
- ghash_add(identifier_merge_hash, &merge_node, next);
+ identifier_merge_hash->insert(&merge_node, next);
}
*next_ptr = next;
return;
if ( !detection_filter_hash )
- {
detection_filter_hash = sfthd_local_new(df_config->memcap);
-
- if ( !detection_filter_hash )
- FatalError("can't allocate detection filter cache\n");
- }
}
void detection_filter_term()
if ( !detection_filter_hash )
return;
- xhash_delete(detection_filter_hash);
+ delete detection_filter_hash;
detection_filter_hash = nullptr;
}
for (i = 0; i < SFRF_MAX_GENID; i++)
{
- if (config->genHash[i] != nullptr)
- ghash_delete(config->genHash[i]);
+ if ( config->genHash[i] )
+ delete config->genHash[i];
}
snort_free(config);
nrows = nbytes / (SFRF_BYTES);
/* Create global hash table for all of the IP Nodes */
- rf_hash = xhash_new(
- nrows, /* try one node per row - for speed */
- sizeof(tSFRFTrackingNodeKey), /* keys size */
- sizeof(tSFRFTrackingNode), /* data size */
- nbytes, /* memcap **/
- 1, /* ANR flag - true ?- Automatic Node Recovery=ANR */
- nullptr, /* ANR callback - none */
- nullptr, /* user freemem callback - none */
- 1); /* Recycle nodes ?*/
+ rf_hash = new XHash(nrows, sizeof(tSFRFTrackingNodeKey),
+ sizeof(tSFRFTrackingNode), nbytes, true, nullptr, nullptr, true);
}
void SFRF_Delete()
if ( !rf_hash )
return;
- xhash_delete(rf_hash);
+ delete rf_hash;
rf_hash = nullptr;
}
void SFRF_Flush()
{
if ( rf_hash )
- xhash_make_empty(rf_hash);
+ rf_hash->clear();
}
static void SFRF_ConfigNodeFree(void* item)
}
/* Create the hash table for this gid */
- genHash = ghash_new(nrows, sizeof(tSFRFGenHashKey), 0, SFRF_SidNodeFree);
- if ( !genHash )
- return -2;
-
+ genHash = new GHash(nrows, sizeof(tSFRFGenHashKey), false, SFRF_SidNodeFree);
rf_config->genHash[cfgNode->gid] = genHash;
}
key.policyId = policy_id;
/* Check if sid is already in the table - if not allocate and add it */
- pSidNode = (tSFRFSidNode*)ghash_find(genHash, (void*)&key);
+ pSidNode = (tSFRFSidNode*)genHash->find((void*)&key);
if ( !pSidNode )
{
/* Create the pSidNode hash node data */
}
/* Add the pSidNode to the hash table */
- if ( ghash_add(genHash, (void*)&key, pSidNode) )
+ if ( genHash->insert((void*)&key, pSidNode) )
{
sflist_free(pSidNode->configNodeList);
snort_free(pSidNode);
key.sid = sid;
key.policyId = policy_id;
- pSidNode = (tSFRFSidNode*)ghash_find(genHash, (void*)&key);
+ pSidNode = (tSFRFSidNode*)genHash->find((void*)&key);
if ( !pSidNode )
{
#ifdef SFRF_DEBUG
unsigned int gid;
GHashNode* sidHashNode;
- for ( gid=0; gid < SFRF_MAX_GENID; gid++ )
+ for ( gid = 0; gid < SFRF_MAX_GENID; gid++ )
{
GHash* genHash = config->genHash [ gid ];
printf("...GEN_ID = %u\n",gid);
- for ( sidHashNode = ghash_findfirst(genHash);
- sidHashNode != nullptr;
- sidHashNode = ghash_findnext(genHash) )
+ for (sidHashNode = genHash->find_first();
+ sidHashNode != nullptr;
+ sidHashNode = genHash->find_next() )
{
/* Check for any Permanent sid objects for this gid */
pSidnode = (tSFRFSidNode*)sidHashNode->data;
each object has it's own unique thd_id */
SF_LNODE* cursor;
- for ( cfgNode = (tSFRFConfigNode*)sflist_first(pSidnode->configNodeList, &cursor);
- cfgNode != nullptr;
- cfgNode = (tSFRFConfigNode*)sflist_next(&cursor) )
+ for (cfgNode = (tSFRFConfigNode*)sflist_first(pSidnode->configNodeList, &cursor);
+ cfgNode != nullptr;
+ cfgNode = (tSFRFConfigNode*)sflist_next(&cursor) )
{
printf(".........SFRF_ID =%d\n",cfgNode->tid);
printf(".........tracking =%d\n",cfgNode->tracking);
/*
* Check for any Permanent sid objects for this gid or add this one ...
*/
- XHashNode* hnode = xhash_get_node(rf_hash, (void*)&key);
+ HashNode* hnode = rf_hash->get_node((void*)&key);
if ( !hnode )
{
// xhash_get_node fails to insert only if rf_hash is full.
namespace snort
{
+class GHash;
struct SfIp;
struct SnortConfig;
}
/* Array of hash, indexed by gid. Each array element is a hash, which
* is keyed on sid/policyId and data is a tSFRFSidNode node.
*/
- struct snort::GHash* genHash [SFRF_MAX_GENID];
+ snort::GHash* genHash [SFRF_MAX_GENID];
unsigned memcap;
unsigned noRevertCount;
/* Calc max ip nodes for this memory */
if ( nbytes < size )
- {
nbytes = size;
- }
- nrows = nbytes / (size);
-
- return xhash_new(
- nrows, /* try one node per row - for speed */
- key, /* keys size */
- data, /* data size */
- nbytes, /* memcap **/
- 1, /* ANR flag - true ?- Automatic Node Recovery=ANR */
- nullptr, /* ANR callback - none */
- nullptr, /* user freemem callback - none */
- 1); /* Recycle nodes ?*/
+ nrows = nbytes / size;
+
+ return new XHash(nrows, key, data, nbytes, true, nullptr, nullptr, true);
}
/*!
#ifdef THD_DEBUG
printf("Could not allocate the sfxhash table\n");
#endif
- xhash_delete(thd->ip_nodes);
+ delete thd->ip_nodes;
snort_free(thd);
return nullptr;
}
for (i = 0; i < THD_MAX_GENID; i++)
{
- if (thd_objs->sfthd_array[i])
- ghash_delete(thd_objs->sfthd_array[i]);
+ if ( thd_objs->sfthd_array[i] )
+ delete thd_objs->sfthd_array[i];
}
for (policyId = 0; policyId < thd_objs->numPoliciesAllocated; policyId++)
{
- if (thd_objs->sfthd_garray[policyId] == nullptr)
+ if ( !thd_objs->sfthd_garray[policyId] )
continue;
- if (thd_objs->sfthd_garray[policyId][0] != nullptr)
+ if ( thd_objs->sfthd_garray[policyId][0] )
{
sfthd_node_free(thd_objs->sfthd_garray[policyId][0]);
/* Free any individuals */
for (i = 0; i < THD_MAX_GENID; i++)
{
- if (thd_objs->sfthd_garray[policyId][i] !=
- thd_objs->sfthd_garray[policyId][0])
+ if ( thd_objs->sfthd_garray[policyId][i] !=
+ thd_objs->sfthd_garray[policyId][0] )
{
sfthd_node_free(thd_objs->sfthd_garray[policyId][i]);
}
/* Anything other GID will be allocated individually */
for (i = 1; i < THD_MAX_GENID; i++)
{
- if (thd_objs->sfthd_garray[policyId][i])
- {
+ if ( thd_objs->sfthd_garray[policyId][i] )
sfthd_node_free(thd_objs->sfthd_garray[policyId][i]);
- }
}
}
snort_free(thd_objs->sfthd_garray[policyId]);
}
- if (thd_objs->sfthd_garray != nullptr)
+ if ( thd_objs->sfthd_garray )
snort_free(thd_objs->sfthd_garray);
snort_free(thd_objs);
if (thd == nullptr)
return;
- if (thd->ip_nodes != nullptr)
- xhash_delete(thd->ip_nodes);
+ if ( thd->ip_nodes )
+ delete thd->ip_nodes;
- if (thd->ip_gnodes != nullptr)
- xhash_delete(thd->ip_gnodes);
+ if ( thd->ip_gnodes )
+ delete thd->ip_gnodes;
snort_free(thd);
}
}
/* Create the hash table for this gen_id */
- sfthd_hash = ghash_new(nrows, sizeof(tThdItemKey), 0, sfthd_item_free);
- if ( !sfthd_hash )
- {
- return -2;
- }
-
+ sfthd_hash = new GHash(nrows, sizeof(tThdItemKey), false, sfthd_item_free);
thd_objs->sfthd_array[config->gen_id] = sfthd_hash;
}
else
key.policyId = policy_id;
/* Check if sig_id is already in the table - if not allocate and add it */
- sfthd_item = (THD_ITEM*)ghash_find(sfthd_hash, (void*)&key);
+ sfthd_item = (THD_ITEM*)sfthd_hash->find((void*)&key);
if ( !sfthd_item )
{
/* Create the sfthd_item hash node data */
}
/* Add the sfthd_item to the hash table */
- if ( ghash_add(sfthd_hash, (void*)&key, sfthd_item) )
+ if ( sfthd_hash->insert((void*)&key, sfthd_item) )
{
sflist_free(sfthd_item->sfthd_node_list);
snort_free(sfthd_item);
/*
* Check for any Permanent sig_id objects for this gen_id or add this one ...
*/
- int status = xhash_add(local_hash, (void*)&key, &data);
- if (status == XHASH_INTABLE)
+ int status = local_hash->insert((void*)&key, &data);
+ if (status == HASH_INTABLE)
{
/* Already in the table */
- sfthd_ip_node = (THD_IP_NODE*)local_hash->cnode->data;
+ sfthd_ip_node = (THD_IP_NODE*)local_hash->get_cnode()->data;
/* Increment the event count */
sfthd_ip_node->count++;
}
- else if (status == XHASH_NOMEM)
+ else if (status == HASH_NOMEM)
{
event_filter_stats.xhash_nomem_peg_local++;
return 1;
}
- else if (status != XHASH_OK)
+ else if (status != HASH_OK)
{
/* hash error */
return 1; /* check the next threshold object */
data.tstart = data.tlast = curtime; /* Event time */
/* Check for any Permanent sig_id objects for this gen_id or add this one ... */
- int status = xhash_add(global_hash, (void*)&key, &data);
- if (status == XHASH_INTABLE)
+ int status = global_hash->insert((void*)&key, &data);
+ if (status == HASH_INTABLE)
{
/* Already in the table */
- sfthd_ip_node = (THD_IP_NODE*)global_hash->cnode->data;
+ sfthd_ip_node = (THD_IP_NODE*)global_hash->get_cnode()->data;
/* Increment the event count */
sfthd_ip_node->count++;
}
- else if (status == XHASH_NOMEM)
+ else if (status == HASH_NOMEM)
{
event_filter_stats.xhash_nomem_peg_global++;
return 1;
}
- else if (status != XHASH_OK)
+ else if (status != HASH_OK)
{
/* hash error */
return 1; /* check the next threshold object */
/*
* Check for any Permanent sig_id objects for this gen_id
*/
- sfthd_item = (THD_ITEM*)ghash_find(sfthd_hash, (void*)&key);
+ sfthd_item = (THD_ITEM*)sfthd_hash->find((void*)&key);
if (sfthd_item == nullptr)
{
#ifdef THD_DEBUG
printf("...GEN_ID = %u\n",gen_id);
- for (item_hash_node = ghash_findfirst(sfthd_hash);
- item_hash_node != 0;
- item_hash_node = ghash_findnext(sfthd_hash) )
+ for (item_hash_node = sfthd_hash->ghash_findfirst();
+ item_hash_node != 0;
+ item_hash_node = sfthd_hash->ghash_findnext() )
{
/* Check for any Permanent sig_id objects for this gen_id */
sfthd_item = (THD_ITEM*)item_hash_node->data;
namespace snort
{
-struct GHash;
-struct XHash;
+class GHash;
+class XHash;
struct SnortConfig;
}
p->rule = nullptr;
}
}
- xhash_delete(dThd);
+
+ delete dThd;
}
static int SetupCheck(int i)
{
// -size forces use of abs(size) ie w/o bumping up
hash_table = new ZHash(-MAX_HASH, sizeof(FlowKey));
- hash_table->set_keyops(FlowKey::hash, FlowKey::compare);
+ hash_table->set_key_opcodes(FlowKey::hash, FlowKey::is_equal);
nodes = new ExpectNode[max];
for (unsigned i = 0; i < max; ++i)
FlowCache::FlowCache(const FlowCacheConfig& cfg) : config(cfg)
{
hash_table = new ZHash(config.max_flows, sizeof(FlowKey));
- hash_table->set_keyops(FlowKey::hash, FlowKey::compare);
+ hash_table->set_key_opcodes(FlowKey::hash, FlowKey::is_equal);
uni_flows = new FlowUniList;
uni_ip_flows = new FlowUniList;
if ( (mode == ALLOWED_FLOWS_ONLY and (flow->was_blocked() || flow->is_suspended()))
or (mode == OFFLOADED_FLOWS_TOO and flow->was_blocked()) )
{
- if (!hash_table->touch())
+ if ( !hash_table->touch() )
break;
continue;
return c;
}
-int FlowKey::compare(const void* s1, const void* s2, size_t)
+bool FlowKey::is_equal(const void* s1, const void* s2, size_t)
{
const uint64_t* a,* b;
a = (const uint64_t*)s1;
b = (const uint64_t*)s2;
if (*a - *b)
- return 1; /* Compares IPv4 lo/hi
+ return false; /* Compares IPv4 lo/hi
Compares IPv6 low[0,1] */
a++;
b++;
if (*a - *b)
- return 1; /* Compares port lo/hi, vlan, protocol, version
+ return false; /* Compares port lo/hi, vlan, protocol, version
Compares IPv6 low[2,3] */
a++;
b++;
if (*a - *b)
- return 1; /* Compares IPv6 hi[0,1] */
+ return false; /* Compares IPv6 hi[0,1] */
a++;
b++;
if (*a - *b)
- return 1; /* Compares IPv6 hi[2,3] */
+ return false; /* Compares IPv6 hi[2,3] */
a++;
b++;
if (*a - *b)
- return 1; /* Compares MPLS label, port lo/hi */
+ return false; /* Compares MPLS label, port lo/hi */
a++;
b++;
if (*a - *b)
- return 1; /* Compares vlan,AddressSpace ID,ip_proto,type,version,8 bit pad */
+ return false; /* Compares vlan,AddressSpace ID,ip_proto,type,version,8 bit pad */
- return 0;
+ return true;
}
// If this data structure changes size, compare must be updated!
static uint32_t hash(HashFnc*, const unsigned char* d, int);
- static int compare(const void* s1, const void* s2, size_t);
+ static bool is_equal(const void* s1, const void* s2, size_t);
private:
bool init4(
// Validate that the imported flow matches up with the given flow key.
if (flow)
{
- if (FlowKey::compare(&key, flow->key, 0) == 0)
+ if (FlowKey::is_equal(&key, flow->key, 0))
{
if (flow->flow_state == Flow::FlowState::BLOCK)
{
void LogMessage(const char*,...) { }
}
-int FlowKey::compare(const void*, const void*, size_t) { return 0; }
+bool FlowKey::is_equal(const void*, const void*, size_t) { return false; }
int SFDAQInstance::ioctl(DAQ_IoctlCmd, void*, size_t) { return DAQ_SUCCESS; }
set (HASH_INCLUDES
hashes.h
+ hash_defs.h
ghash.h
xhash.h
hashfcn.h
* sha2: open source implementation by Aaron Gifford.
-* sfghash: Generic hash table
+* ghash: Generic hash table
-* sfxhash: Hash table with supports memcap and automatic memory recovery
+* xhash: Hash table with supports memcap and automatic memory recovery
when out of memory.
* zhash: zero runtime allocations/preallocated hash table.
#include "utils/util.h"
-#include "hashfcn.h"
#include "primetable.h"
namespace snort
{
-/*
-*
-* Create a new hash table
-*
-* nrows : number of rows in hash table, primes are best.
-* > 0 => we use the nearest prime internally
-* < 0 => we use the magnitude as nrows.
-* keysize : > 0 => bytes in each key, keys are binary bytes,
-* all keys are the same size.
-* ==0 => keys are strings and are null terminated,
-* allowing random key lengths.
-* userkeys : > 0 => indicates user owns the key data
-* and we should not allocate or free space for it,
-* nor should we attempt to free the user key. We just
-* save the pointer to the key.
-* ==0 => we should copy the keys and manage them internally
-* userfree : routine to free users data, null if we should not
-* free user data in ghash_delete(). The routine
-* should be of the form 'void userfree(void * userdata)',
-* 'free' works for simple allocations.
-*/
-GHash* ghash_new(int nrows, int keysize, int userkeys, gHashFree userfree)
-{
- if ( nrows > 0 ) /* make sure we have a prime number */
- {
- nrows = nearest_prime(nrows);
- }
- else /* use the magnitude or nrows as is */
- {
- nrows = -nrows;
- }
-
- GHash* h = (GHash*)snort_calloc(sizeof(GHash));
- h->hashfcn = hashfcn_new(nrows);
- h->table = (GHashNode**)snort_calloc(nrows, sizeof(GHashNode*));
+GHash::GHash(int nrows_, unsigned keysize, bool userkey, gHashFree userfree)
+ : keysize(keysize), userkey(userkey), userfree(userfree)
+{
+ if ( nrows_ > 0 )
+ nrows = nearest_prime(nrows_);
+ else
+ nrows = -nrows_;
+ hashfcn = hashfcn_new(nrows);
+ table = (GHashNode**)snort_calloc(nrows, sizeof(GHashNode*));
for ( int i = 0; i < nrows; i++ )
- {
- h->table[i] = nullptr;
- }
-
- h->userkey = userkeys;
- h->keysize = keysize;
- h->nrows = nrows;
- h->count = 0;
- h->userfree = userfree;
-
- h->crow = 0; // findfirst/next current row
- h->cnode = nullptr; // findfirst/next current node ptr
+ table[i] = nullptr;
- return h;
+ count = 0;
+ crow = 0;
+ cnode = nullptr;
}
-/*
-* Delete the hash Table
-*
-* free key's, free node's, and free the users data, if they
-* supply a free function
-*/
-void ghash_delete(GHash* h)
+GHash::~GHash()
{
- if ( !h )
- return;
+ hashfcn_free(hashfcn);
- hashfcn_free(h->hashfcn);
-
- if ( h->table )
- {
- for (int i=0; i<h->nrows; i++)
+ for (int i = 0; i < nrows; i++)
+ for ( GHashNode* node = table[i]; node; )
{
- for ( GHashNode* node=h->table[i]; node; )
- {
- GHashNode* onode = node;
- node = node->next;
+ GHashNode* onode = node;
+ node = node->next;
- if ( !h->userkey && onode->key )
- snort_free(const_cast<void*>(onode->key));
+ if ( !userkey && onode->key )
+ snort_free(const_cast<void*>(onode->key));
- if ( h->userfree && onode->data )
- h->userfree(onode->data); /* free users data, with users function */
+ if ( userfree && onode->data )
+ userfree(onode->data);
- snort_free(onode);
- }
+ snort_free(onode);
}
- snort_free(h->table);
- h->table = nullptr;
- }
- snort_free(h);
+ snort_free(table);
}
-/*
-* Add a key + data pair
-* ---------------------
-*
-* key + data should both be non-zero, although data can be zero
-*
-* t - hash table
-* key - users key data (should be unique in this table)
-* may be ascii strings or fixed size binary keys
-* data - users data pointer
-*
-* returns SF_HASH_NOMEM: alloc error
-* SF_HASH_INTABLE : key already in table (t->cnode points to the node)
-* SF_OK: added a node for this key + data pair
-*
-* Notes:
-* If the key node already exists, then t->cnode points to it on return,
-* this allows you to do something with the node - like add the data to a
-* linked list of data items held by the node, or track a counter, or whatever.
-*
-*/
-int ghash_add(GHash* t, const void* const key, void* const data)
+// set key length, hashkey, and index parameters required to find/add/remove a node
+// the parameters set are valid until for the life of the initial method called
+void GHash::set_node_parameters(const void* const key)
{
- unsigned hashkey;
- int klen;
- int index;
- GHashNode* hnode;
-
- if (t == nullptr || key == nullptr)
- return GHASH_ERR;
-
- /*
- * Get proper Key Size
- */
- if ( t->keysize > 0 )
- {
- klen = t->keysize;
- }
- else
- {
- /* need the null byte for strcmp() in ghash_find() */
- klen = strlen( (const char*)key) + 1;
- }
-
- hashkey = t->hashfcn->hash_fcn(t->hashfcn, (const unsigned char*)key, klen);
+ klen = ( keysize > 0 ) ? keysize : strlen((const char*)key) + 1;
+ hashkey = hashfcn->hash_fcn(hashfcn, (const unsigned char*)key, klen);
+ index = hashkey % nrows;
+}
- index = hashkey % t->nrows;
+GHashNode* GHash::find_node(const void* const key)
+{
+ assert(key);
- /*
- * Uniqueness:
- * Check 1st to see if the key is already in the table
- * Just bail if it is.
- */
- for ( hnode=t->table[index]; hnode; hnode=hnode->next )
+ set_node_parameters(key);
+ for ( GHashNode* hnode = table[index]; hnode; hnode = hnode->next )
{
- if ( t->keysize > 0 )
+ if ( keysize == 0 )
{
- if ( !t->hashfcn->keycmp_fcn(hnode->key,key,klen) )
- {
- t->cnode = hnode; /* save pointer to the node */
- return GHASH_INTABLE; /* found it */
- }
+ if ( !strcmp((const char*)hnode->key, (const char*)key) )
+ return hnode;
}
else
{
- if ( !strcmp((const char*)hnode->key,(const char*)key) )
- {
- t->cnode = hnode; /* save pointer to the node */
- return GHASH_INTABLE; /* found it */
- }
+ if ( hashfcn->keycmp_fcn(hnode->key, key, keysize) )
+ return hnode;
}
}
- /*
- * Create new node
- */
- hnode = (GHashNode*)snort_calloc(sizeof(GHashNode));
+ return nullptr;
+}
+
+int GHash::insert(const void* const key, void* const data)
+{
+ assert(key && data);
+
+ if ( GHashNode* hnode = find_node(key) )
+ {
+ cnode = hnode;
+ return GHASH_INTABLE;
+ }
- /* Add the Key */
- if ( t->userkey )
+ GHashNode* hnode = (GHashNode*)snort_calloc(sizeof(GHashNode));
+ if ( userkey )
{
- /* Use the Users key */
hnode->key = key;
}
else
{
- /* Create new key */
hnode->key = snort_alloc(klen);
-
- /* Copy key */
- memcpy(const_cast<void*>(hnode->key),key,klen);
+ memcpy(const_cast<void*>(hnode->key), key, klen);
}
- /* Add The Node */
- if ( t->table[index] ) /* add the node to the existing list */
- {
- hnode->prev = nullptr; // insert node as head node
- hnode->next=t->table[index];
- hnode->data=data;
- t->table[index]->prev = hnode;
- t->table[index] = hnode;
- }
- else /* 1st node in this list */
+ if ( table[index] )
{
- hnode->prev=nullptr;
- hnode->next=nullptr;
- hnode->data=data;
- t->table[index] = hnode;
- }
-
- t->count++;
-
- return GHASH_OK;
-}
-
-/*
-* Find a Node based on the key, return users data.
-*/
-static GHashNode* ghash_find_node(GHash* t, const void* const key)
-{
- unsigned hashkey;
- int index, klen;
- GHashNode* hnode;
-
- assert(t);
-
- if ( t->keysize )
- {
- klen = t->keysize;
+ hnode->prev = nullptr;
+ hnode->next = table[index];
+ hnode->data = data;
+ table[index]->prev = hnode;
+ table[index] = hnode;
}
else
{
- klen = strlen( (const char*)key) + 1;
+ hnode->prev = nullptr;
+ hnode->next = nullptr;
+ hnode->data = data;
+ table[index] = hnode;
}
- hashkey = t->hashfcn->hash_fcn(t->hashfcn, (const unsigned char*)key, klen);
-
- index = hashkey % t->nrows;
+ count++;
- for ( hnode=t->table[index]; hnode; hnode=hnode->next )
- {
- if ( t->keysize == 0 )
- {
- if ( !strcmp((const char*)hnode->key,(const char*)key) )
- {
- return hnode;
- }
- }
- else
- {
- if ( !t->hashfcn->keycmp_fcn(hnode->key,key,t->keysize) )
- {
- return hnode;
- }
- }
- }
-
- return nullptr;
+ return GHASH_OK;
}
-/*
-* Find a Node based on the key, return users data.
-*/
-void* ghash_find(GHash* t, const void* const key)
+void* GHash::find(const void* const key)
{
- GHashNode* hnode;
-
- assert(t);
-
- hnode = ghash_find_node(t, key);
+ assert(key);
+ GHashNode* hnode = find_node(key);
if ( hnode )
return hnode->data;
return nullptr;
}
-/*
-* Unlink and free the node
-*/
-static int ghash_free_node(GHash* t, unsigned index, GHashNode* hnode)
+int GHash::free_node(unsigned index, GHashNode* hnode)
{
- assert(t);
+ assert(hnode);
- if ( !t->userkey && hnode->key )
+ if ( !userkey && hnode->key )
snort_free(const_cast<void*>(hnode->key));
hnode->key = nullptr;
- if ( t->userfree)
- t->userfree(hnode->data); /* free users data, with users function */
+ if ( userfree)
+ userfree(hnode->data);
- if ( hnode->prev ) // not the 1st node
+ if ( hnode->prev )
{
hnode->prev->next = hnode->next;
if ( hnode->next )
hnode->next->prev = hnode->prev;
}
- else if ( t->table[index] ) // 1st node
+ else if ( table[index] )
{
- t->table[index] = t->table[index]->next;
- if ( t->table[index] )
- t->table[index]->prev = nullptr;
+ table[index] = table[index]->next;
+ if ( table[index] )
+ table[index]->prev = nullptr;
}
snort_free(hnode);
-
- t->count--;
+ count--;
return GHASH_OK;
}
-/*
-* Remove a Key/Data Pair from the table - find it, unlink it, and free the memory for it.
-*
-* returns : 0 - OK
-* -1 - node not found
-*/
-int ghash_remove(GHash* t, const void* const key)
+int GHash::remove(const void* const key)
{
- GHashNode* hnode;
- int klen;
- unsigned hashkey, index;
-
- assert(t);
+ assert(key);
- if ( t->keysize > 0 )
- {
- klen = t->keysize;
- }
+ if ( GHashNode* hnode = find_node(key) )
+ return free_node(index, hnode);
else
- {
- klen = strlen((const char*)key) + 1;
- }
-
- hashkey = t->hashfcn->hash_fcn(t->hashfcn, (const unsigned char*)key, klen);
-
- index = hashkey % t->nrows;
-
- for ( hnode=t->table[index]; hnode; hnode=hnode->next )
- {
- if ( t->keysize > 0 )
- {
- if ( !t->hashfcn->keycmp_fcn(hnode->key,key,klen) )
- {
- return ghash_free_node(t, index, hnode);
- }
- }
- else
- {
- if ( !strcmp((const char*)hnode->key,(const char*)key) )
- {
- return ghash_free_node(t, index, hnode);
- }
- }
- }
-
- return GHASH_ERR;
+ return GHASH_NOT_FOUND;
}
-/* Internal use only */
-static void ghash_next(GHash* t)
+void GHash::next()
{
- assert(t and t->cnode);
+ assert(cnode);
- /* Next node in current node list */
- t->cnode = t->cnode->next;
- if ( t->cnode )
- {
+ cnode = cnode->next;
+ if ( cnode )
return;
- }
- /* Next row
- Get 1st node in next non-empty row/node list */
- for ( t->crow++; t->crow < t->nrows; t->crow++ )
+ for ( crow++; crow < nrows; crow++ )
{
- t->cnode = t->table[ t->crow ];
- if ( t->cnode )
- {
+ cnode = table[crow];
+ if ( cnode )
return;
- }
}
}
-/*
-* Get First Hash Table Node
-*/
-GHashNode* ghash_findfirst(GHash* t)
+GHashNode* GHash::find_first()
{
- GHashNode* n;
-
- assert(t);
- /* Start with 1st row */
- for ( t->crow=0; t->crow < t->nrows; t->crow++ )
+ for ( crow = 0; crow < nrows; crow++ )
{
- /* Get 1st Non-Null node in row list */
- t->cnode = t->table[ t->crow ];
-
- if ( t->cnode )
+ cnode = table[crow];
+ if ( cnode )
{
- n = t->cnode;
-
- ghash_next(t); // load t->cnode with the next entry
-
+ GHashNode* n = cnode;
+ next();
return n;
}
}
return nullptr;
}
-/*
-* Get Next Hash Table Node
-*/
-GHashNode* ghash_findnext(GHash* t)
+GHashNode* GHash::find_next()
{
- GHashNode* n;
-
- assert(t);
-
- n = t->cnode;
-
- if ( !n ) /* Done, no more entries */
- {
- return nullptr;
- }
-
- /*
- Preload next node into current node
- */
- ghash_next(t);
+ GHashNode* n = cnode;
+ if ( n )
+ next();
return n;
}
-/**
- * Make hashfcn use a separate set of opcodes for the backend.
- *
- * @param h hashfcn ptr
- * @param hash_fcn user specified hash function
- * @param keycmp_fcn user specified key comparison function
- */
-int ghash_set_keyops(GHash* h,
- unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n))
+void GHash::set_key_opcodes(hash_func hash_fcn, keycmp_func keycmp_fcn)
{
- assert(h && hash_fcn && keycmp_fcn);
-
- return hashfcn_set_keyops(h->hashfcn, hash_fcn, keycmp_fcn);
+ hashfcn_set_keyops(hashfcn, hash_fcn, keycmp_fcn);
}
+
}
#include "main/snort_types.h"
-struct HashFnc;
+#include "hashfcn.h"
namespace snort
{
-
-#define GHASH_NOMEM (-2)
-#define GHASH_ERR (-1)
+#define GHASH_NOT_FOUND (-1)
#define GHASH_OK 0
#define GHASH_INTABLE 1
-// Flags for ghash_new: userkeys
-#define GH_COPYKEYS 0
-#define GH_USERKEYS 1
-
struct GHashNode
{
- struct GHashNode* next, * prev;
-
+ struct GHashNode* next;
+ struct GHashNode* prev;
const void* key; /* Copy of, or Pointer to, the Users key */
void* data; /* The users data, this is never copied! */
};
typedef void (* gHashFree)(void*);
-struct GHash
+class SO_PUBLIC GHash
{
- HashFnc* hashfcn;
- int keysize; /* bytes in key, if < 0 -> keys are strings */
- int userkey; /* user owns the key */
-
- GHashNode** table; /* array of node ptr's */
- int nrows; /* # rows int the hash table use a prime number 211, 9871 */
-
- unsigned count; /* total # nodes in table */
-
+public:
+ GHash(int nrows, unsigned keysize, bool userkey, gHashFree);
+ ~GHash();
+
+ int insert(const void* const key, void* const data);
+ int remove(const void* const key);
+ void* find(const void* const key);
+ GHashNode* find_first();
+ GHashNode* find_next();
+ void set_key_opcodes(hash_func, keycmp_func);
+
+ unsigned get_count() const
+ { return count; }
+
+private:
+ void set_node_parameters(const void* const key);
+ GHashNode* find_node(const void* const key);
+ int free_node(unsigned index, GHashNode*);
+ void next();
+
+ unsigned keysize; // bytes in key, if < 0 -> keys are strings
+ bool userkey; // user owns the key */
gHashFree userfree;
-
- int crow; /* findfirst/next row in table */
- GHashNode* cnode; /* findfirst/next node ptr */
+ int nrows; // # rows int the hash table use a prime number 211, 9871
+ HashFnc* hashfcn;
+ GHashNode** table; // array of node ptr's
+ unsigned count; // total # nodes in table
+ int crow; // findfirst/next row in table
+ GHashNode* cnode; // findfirst/next node ptr
+
+ // node parameters for search/add/remove
+ unsigned klen = 0;
+ unsigned hashkey = 0;
+ int index = 0;
};
-SO_PUBLIC GHash* ghash_new(int nrows, int keysize, int userkeys, gHashFree);
-SO_PUBLIC void ghash_delete(GHash*);
-SO_PUBLIC int ghash_add(GHash*, const void* const key, void* const data);
-SO_PUBLIC int ghash_remove(GHash*, const void* const key);
-SO_PUBLIC void* ghash_find(GHash*, const void* const key);
-SO_PUBLIC GHashNode* ghash_findfirst(GHash*);
-SO_PUBLIC GHashNode* ghash_findnext(GHash*);
-SO_PUBLIC int ghash_set_keyops(GHash*,
-unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
-int (* keycmp_fcn)(const void* s1, const void* s2, size_t n));
+
}
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2020 Cisco and/or its affiliates. All rights reserved.
+//
+// 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.
+//--------------------------------------------------------------------------
+// hash_defs.h author davis mcpherson davmcphe@cisco.com>
+
+#ifndef HASH_DEFS_H
+#define HASH_DEFS_H
+
+#include "main/snort_types.h"
+#include "utils/sfmemcap.h"
+
+#include "hashfcn.h"
+
+namespace snort
+{
+#define HASH_NOMEM (-2)
+#define HASH_ERR (-1)
+#define HASH_OK 0
+#define HASH_INTABLE 1
+#define HASH_PENDING 2
+
+struct HashNode
+{
+ struct HashNode* gnext; // global node list - used for aging nodes
+ struct HashNode* gprev;
+ struct HashNode* next; // row node list
+ struct HashNode* prev;
+ int rindex; // row index of table this node belongs to.
+ void* key; // Pointer to the key.
+ void* data; // Pointer to the users data, this is not copied !
+};
+
+typedef int (* Hash_FREE_FCN)(void* key, void* data);
+}
+#endif
/*
hashfcn.c
- Each hash table must allocate it's own GHash struct, this is because
- ghash_new uses the number of rows in the hash table to modulo the random
- values.
+ Each hash table allocates it's own GHash struct, using the number of
+ rows in the hash table to modulo the random values.
Updates:
#include "hashfcn.h"
+#include <cassert>
+
#include "main/snort_config.h"
#include "utils/util.h"
using namespace snort;
+static bool hashfcn_key_compare(const void* k1, const void* k2, size_t len)
+{
+ if ( memcmp(k1, k2, len ) == 0 )
+ return true;
+ else
+ return false;
+}
+
HashFnc* hashfcn_new(int m)
{
HashFnc* p;
- static int one=1;
+ static int one = 1;
if ( one ) /* one time init */
{
}
else
{
- p->seed = nearest_prime( (rand()%m)+3191);
- p->scale = nearest_prime( (rand()%m)+709);
+ p->seed = nearest_prime( (rand() % m) + 3191);
+ p->scale = nearest_prime( (rand() % m) + 709);
p->hardener = ((unsigned) rand() * rand()) + 133824503;
}
- p->hash_fcn = &hashfcn_hash;
- p->keycmp_fcn = &memcmp;
+ p->hash_fcn = &hashfcn_hash;
+ p->keycmp_fcn = &hashfcn_key_compare;
return p;
}
* @param hash_fcn user specified hash function
* @param keycmp_fcn user specified key comparison function
*/
-int hashfcn_set_keyops(HashFnc* h,
- unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n))
+void hashfcn_set_keyops(HashFnc* h, hash_func hash_fcn, keycmp_func keycmp_fcn)
{
- if (h && hash_fcn && keycmp_fcn)
- {
- h->hash_fcn = hash_fcn;
- h->keycmp_fcn = keycmp_fcn;
+ assert(h && hash_fcn && keycmp_fcn);
- return 0;
- }
-
- return -1;
+ h->hash_fcn = hash_fcn;
+ h->keycmp_fcn = keycmp_fcn;
}
namespace snort
{
-void mix_str(
- uint32_t& a, uint32_t& b, uint32_t& c,
- const char* s, unsigned n)
+void mix_str(uint32_t& a, uint32_t& b, uint32_t& c, const char* s, unsigned n)
{
unsigned i, j;
k=4;
for (unsigned l=0; l<k; l++)
- {
tmp |= (unsigned char) s[i + l] << l*8;
- }
switch (j)
{
}
if (j != 0)
- {
mix(a,b,c);
- }
}
uint32_t str_to_hash(const uint8_t *str, size_t length)
const char* s, unsigned n = 0);
SO_PUBLIC uint32_t str_to_hash(const uint8_t *str, size_t length);
+
+static inline int hash_nearest_power_of_2(int nrows)
+{
+ nrows -= 1;
+ for (unsigned i = 1; i < sizeof(nrows) * 8; i <<= 1)
+ nrows = nrows | (nrows >> i);
+ nrows += 1;
+
+ return nrows;
+}
+
}
+struct HashFnc;
+
+typedef uint32_t (* hash_func)(HashFnc*, const unsigned char* d, int n);
+typedef bool (* keycmp_func)(const void* s1, const void* s2, size_t n);
+
struct HashFnc
{
unsigned seed;
unsigned scale;
unsigned hardener;
- // FIXIT-H use types for these callbacks
- unsigned (* hash_fcn)(HashFnc*, const unsigned char* d, int n);
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n);
+ hash_func hash_fcn;
+ keycmp_func keycmp_fcn;
};
HashFnc* hashfcn_new(int nrows);
void hashfcn_free(HashFnc*);
-
unsigned hashfcn_hash(HashFnc*, const unsigned char* d, int n);
-
-int hashfcn_set_keyops(
- HashFnc*,
- // FIXIT-H use types for these callbacks
- unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n));
+void hashfcn_set_keyops(HashFnc*, hash_func, keycmp_func);
#endif
int num=100;
// Create a Hash Table
- GHash* t = ghash_new(1000, 0, GH_COPYKEYS, nullptr);
+ GHash* t = new GHash(1000, 0, false, nullptr);
// Add Nodes to the Hash Table
for (i=0; i<num; i++)
{
snprintf(str, sizeof(str), "KeyWord%d",i+1);
str[sizeof(str) - 1] = '\0';
- ghash_add(t, str, (void *)(str + (i+1)));
+ t->insert(str, (void *)(str + (i+1)));
}
// find those nodes
snprintf(str, sizeof(str), "KeyWord%d",i+1);
str[sizeof(str) - 1] = '\0';
- char* p = (char*)ghash_find(t, str);
+ char* p = (char*)t->find(str);
CHECK(p != nullptr);
CHECK(p == (void *)(str + (i+1)));
}
- for (GHashNode* n = ghash_findfirst(t); n; n = ghash_findnext(t) )
+ for (GHashNode* n = t->find_first(); n; n = t->find_next() )
{
- i = ghash_remove(t,n->key);
+ i = t->remove(n->key);
CHECK(i==0);
}
- ghash_delete(t);
+ delete t;
}
// test to generate collisions and increase test code coverage
int num=100;
// Create a Hash Table with smaller entries
- GHash* t = ghash_new(-10, 0, GH_COPYKEYS, nullptr);
+ GHash* t = new GHash(-10, 0, false, nullptr);
CHECK(t != nullptr);
{
snprintf(str, sizeof(str), "KeyWord%d",i+1);
str[sizeof(str) - 1] = '\0';
- ghash_add(t, str, (void *)(str + (i+1)));
+ t->insert(str, (void *)(str + (i+1)));
}
// try to add an existed entry
snprintf(str, sizeof(str), "KeyWord%d",1);
str[sizeof(str) - 1] = '\0';
- i = ghash_add(t, str, (void *)(str + (1)));
+ i = t->insert(str, (void *)(str + (1)));
CHECK(i == GHASH_INTABLE);
// find those nodes
snprintf(str, sizeof(str), "KeyWord%d",i+1);
str[sizeof(str) - 1] = '\0';
- char* p = (char*)ghash_find(t, str);
+ char* p = (char*)t->find(str);
CHECK(p != nullptr);
CHECK(p == (void *)(str + (i+1)));
}
// remove one node
- GHashNode* n = ghash_findfirst(t);
+ GHashNode* n = t->find_first();
if (n)
{
- n = ghash_findnext(t);
- i = ghash_remove(t,n->key);
+ n = t->find_next();
+ i = t->remove(n->key);
CHECK(i==0);
}
// remove rest of nodes
- for ( n = ghash_findfirst(t); n; n = ghash_findnext(t) )
+ for ( n = t->find_first(); n; n = t->find_next() )
{
- i = ghash_remove(t,n->key);
+ i = t->remove(n->key);
CHECK(i==0);
}
- ghash_delete(t);
+ delete t;
}
TEST(ghash, userfree_test)
int i;
// Create a small Hash Table with user free
- GHash* t = ghash_new(-5, 0, GH_COPYKEYS, myfree);
+ GHash* t = new GHash(-5, 0, false, myfree);
// add 5 nodes
for (i=0; i<5; i++)
{
char* p = (char*)snort_alloc(32);
p[0] = (char)(i+1);
p[1] = '\0';
- ghash_add(t, str, (void *)p);
+ t->insert(str, (void *)p);
}
// find those nodes
snprintf(str, sizeof(str), "KeyWord%d",i+1);
str[sizeof(str) - 1] = '\0';
- char *p = (char*)ghash_find(t, str);
+ char *p = (char*)t->find(str);
CHECK(p != nullptr);
CHECK(p[0] == (i+1));
str[sizeof(str) - 1] = '\0';
// it should not be found
- CHECK(ghash_find(t, str) == nullptr);
-
+ CHECK(t->find(str) == nullptr);
+
// try to remove a node that is not in the table
- CHECK(ghash_remove(t, str) == GHASH_ERR);
+ CHECK(t->remove( str) == GHASH_NOT_FOUND);
- for ( GHashNode* n = ghash_findfirst(t); n; n = ghash_findnext(t) )
+ for ( GHashNode* n = t->find_first(); n; n = t->find_next() )
{
// user free should be called here, no memory leak should be detected
- i = ghash_remove(t,n->key);
+ i = t->remove(n->key);
CHECK(i==0);
}
- ghash_delete(t);
-}
-
-TEST(ghash, nullptr_test)
-{
- CHECK(GHASH_ERR == ghash_add(nullptr, nullptr, nullptr));
- ghash_delete(nullptr);
+ delete t;
}
int main(int argc, char** argv)
// Test create a hash table, add nodes, find and delete.
TEST(xhash, create_xhash_test)
{
- XHash* test_table = xhash_new(4, sizeof(struct xhash_test_key),
- 0, 0, 0, nullptr, nullptr, 0);
- CHECK(test_table->keysize == sizeof(struct xhash_test_key));
- xhash_delete(test_table);
-}
+ XHash* test_table = new XHash(4, sizeof(struct xhash_test_key),
+ 0, 0, false, nullptr, nullptr, false);
+ CHECK(test_table->get_keysize() == sizeof(struct xhash_test_key));
-// Test verifies if free_anr_lru_function() throws error on invalid table
-TEST(xhash, free_anr_lru_invalid_test)
-{
- int ret = xhash_free_anr_lru(nullptr);
- CHECK(ret == XHASH_ERR);
+ void* data = test_table->get_mru_user_data();
+ CHECK(data == nullptr);
+
+ for (unsigned i = 1; i <= 4; i++)
+ {
+ xhash_test_key xtk;
+ xtk.key = 10 * i;
+ int ret = test_table->insert(&xtk, nullptr);
+ CHECK(ret == HASH_OK);
+ }
+
+ xhash_test_key xtk;
+ xtk.key = 10;
+ HashNode* xnode = test_table->find_node(&xtk);
+ CHECK(xnode != nullptr);
+ int ret = test_table->release_node(xnode);
+ CHECK(ret == HASH_OK);
+
+ delete test_table;
}
// Create a free node in xhash and verifies if xhash_free_anr_lru() deletes it
TEST(xhash, free_anr_lru_delete_free_node_test)
{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 1, 1040, 0, nullptr, nullptr, 1);
+ XHash* test_table = new XHash(3, sizeof(struct xhash_test_key),
+ 1, 1040, false, nullptr, nullptr, true);
xhash_test_key xtk;
xtk.key = 10;
- int ret = xhash_add(test_table, &xtk, nullptr);
- CHECK(ret == XHASH_OK);
+ int ret = test_table->insert(&xtk, nullptr);
+ CHECK(ret == HASH_OK);
- XHashNode *xnode = xhash_get_node(test_table, &xtk);
+ HashNode* xnode = test_table->get_node(&xtk);
CHECK(xnode != nullptr);
- ret = xhash_free_node(test_table, xnode);
- CHECK(ret == XHASH_OK);
+ ret = test_table->release_node(xnode);
+ CHECK(ret == HASH_OK);
- ret = xhash_free_anr_lru(test_table);
- CHECK(ret == XHASH_OK);
+ ret = test_table->delete_anr_or_lru_node();
+ CHECK(ret == HASH_OK);
- XHashNode* xhnode = xhash_find_node(test_table, &xtk);
+ HashNode* xhnode = test_table->find_node(&xtk);
CHECK(xhnode == nullptr);
- xhash_delete(test_table);
+
+ delete test_table;
}
// No free node is available, verifies if xhash_free_anr_lru() deletes the last node
TEST(xhash, free_anr_lru_delete_tail_node_test)
{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 1, 1040, 0, nullptr, nullptr, 1);
+ XHash* test_table = new XHash(3, sizeof(struct xhash_test_key),
+ 1, 1040, false, nullptr, nullptr, true);
xhash_test_key xtk;
- int ret = xhash_add(test_table, &xtk, nullptr);
- CHECK(ret == XHASH_OK);
+ int ret = test_table->insert(&xtk, nullptr);
+ CHECK(ret == HASH_OK);
- XHashNode* orig_gtail = test_table->gtail;
- ret = xhash_free_anr_lru(test_table);
- CHECK(ret == XHASH_OK);
- CHECK(orig_gtail != test_table->gtail);
+ ret = test_table->delete_anr_or_lru_node();
+ CHECK(ret == HASH_OK);
- xhash_delete(test_table);
+ HashNode* xhnode = test_table->find_node(&xtk);
+ CHECK(xhnode == nullptr);
+
+ delete test_table;
}
// No free node is available [recycle is not enabled], verifies if last node is deleted
TEST(xhash, free_anr_lru_usr_free_delete_tail_node_test)
{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 1, 1040, 0, nullptr, nullptr, 0);
- xhash_test_key xtk;
- int ret = xhash_add(test_table, &xtk, nullptr);
- CHECK(ret == XHASH_OK);
-
- XHashNode* orig_gtail = test_table->gtail;
- ret = xhash_free_anr_lru(test_table);
- CHECK(ret == XHASH_OK);
- CHECK(orig_gtail != test_table->gtail);
- xhash_delete(test_table);
-}
-
-// if new memcap is same as old memcap, do nothing
-TEST(xhash, change_memcap_same_memcap_test)
-{
- XHash* test_table = xhash_new(5, sizeof(struct xhash_test_key),
- 0, 80, 0, nullptr, nullptr, 1);
- unsigned max_work = 0;
- int ret = xhash_change_memcap(test_table, 80, &max_work);
- CHECK(ret == XHASH_OK);
- CHECK(test_table->mc.memcap == 80);
- xhash_delete(test_table);
-}
-
-// if new memcap is more than old memcap, only change the memcap
-TEST(xhash, change_memcap_more_memcap_test)
-{
- XHash* test_table = xhash_new(5, sizeof(struct xhash_test_key),
- 0, 80, 0, nullptr, nullptr, 1);
-
- unsigned max_work = 0;
- int ret = xhash_change_memcap(test_table, 100, &max_work);
- CHECK(ret == XHASH_OK);
- CHECK(test_table->mc.memcap == 100);
- xhash_delete(test_table);
-}
-
-// IF new memcap is is less than overhead bytes, throw an error
-TEST(xhash, change_memcap_less_than_overhead_memcap_test)
-{
- XHash* test_table = xhash_new(5, sizeof(struct xhash_test_key),
- 0, 80, 0, nullptr, nullptr, 1);
-
- unsigned max_work = 0;
- int ret = xhash_change_memcap(test_table, test_table->overhead_bytes-1, &max_work);
- CHECK(ret == XHASH_ERR);
- CHECK(test_table->mc.memcap == 80);
- xhash_delete(test_table);
-}
-
-//if new memcap is less than used memcap, do the pruning
-TEST(xhash, xhash_change_memcap_less_than_used_test)
-{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 1, 1040, 0, nullptr, nullptr, 1);
- xhash_test_key xtk[2];
- int ret = xhash_add(test_table, &xtk[0], nullptr);
- CHECK(ret == XHASH_OK);
-
- xtk[1].key = 100;
- ret = xhash_add(test_table, &xtk[1], nullptr);
- CHECK(ret == XHASH_OK);
-
- unsigned max_work = 0;
- unsigned new_memcap = test_table->mc.memused-1;
- ret = xhash_change_memcap(test_table, new_memcap, &max_work);
- CHECK(ret == XHASH_OK);
- CHECK(test_table->mc.memcap == new_memcap);
- xhash_delete(test_table);
-}
-
-// new memcap is less than old memcap and cannot prune
-TEST(xhash, xhash_change_memcap_nofree_nodes_test)
-{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 1, 1040, 0, nullptr, nullptr, 0);
+ XHash* test_table = new XHash(3, sizeof(struct xhash_test_key),
+ 1, 1040, false, nullptr, nullptr, false);
xhash_test_key xtk;
+ int ret = test_table->insert(&xtk, nullptr);
+ CHECK(ret == HASH_OK);
- int ret = xhash_add(test_table, &xtk, nullptr);
- CHECK(ret == XHASH_OK);
- unsigned new_memcap = test_table->mc.memused-1;
-
-
- unsigned max_work = 0;
- test_table->gtail = nullptr;
- ret = xhash_change_memcap(test_table, new_memcap, &max_work);
- CHECK(ret == XHASH_NOMEM);
- xhash_delete(test_table);
-}
-
-// new memcap is less than old memcap and max_work is than needed
-TEST(xhash, xhash_change_memcap_less_max_work_test)
-{
- XHash* test_table = xhash_new(3, sizeof(struct xhash_test_key),
- 142, 1040, 0, nullptr, nullptr, 0);
- xhash_test_key xtk;
-
- int ret = xhash_add(test_table, &xtk, nullptr);
- CHECK(ret == XHASH_OK);
- unsigned new_memcap = test_table->mc.memused-1;
-
- xhash_test_key xtk1;
- xtk1.key = 100;
- ret = xhash_add(test_table, &xtk1, nullptr);
- CHECK(ret == XHASH_OK);
-
- unsigned max_work = 1;
- ret = xhash_change_memcap(test_table, new_memcap, &max_work);
- CHECK(ret == XHASH_PENDING);
- CHECK(max_work == 0);
- xhash_delete(test_table);
+ ret = test_table->delete_anr_or_lru_node();
+ CHECK(ret == HASH_OK);
+ delete test_table;
}
int main(int argc, char** argv)
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//--------------------------------------------------------------------------
-
-/* sfxhash.c
+/* xhash.cc
*
* A Customized hash table library for storing and accessing key + data pairs.
*
*
* Per Node Memory Usage:
* ----------------------
- * XHashNode bytes
+ * HashNode bytes
* KEYSIZE bytes
* [DATASIZE bytes] if datasize > 0 during call to xhash_new.
*
#include <cassert>
#include "utils/util.h"
-#include "hashfcn.h"
using namespace snort;
-/*
- * Implements XHash as specialized hash container
- */
-
-/*
-* Private Malloc - abstract the memory system
-*/
-static inline void* s_alloc(XHash* t, int n)
-{
- return sfmemcap_alloc(&t->mc, n);
-}
-
-static inline void s_free(XHash* t, void* p)
-{
- sfmemcap_free(&t->mc, p);
-}
-
-static int xhash_nearest_powerof2(int nrows)
-{
- nrows -= 1;
- for (unsigned i=1; i<sizeof(nrows) * 8; i <<= 1)
- nrows = nrows | (nrows >> i);
- nrows += 1;
-
- return nrows;
-}
-
namespace snort
{
-/*
- * Create a new hash table
- *
- * By default, this will "splay" nodes to the top of a free list.
- *
- * nrows number of rows in hash table
- * keysize key size in bytes, same for all keys
- * datasize datasize in bytes, zero indicates user manages data
- * maxmem maximum memory to use in bytes
- * anr_flag Automatic Node Recovery boolean flag
- * anrfree users Automatic Node Recovery memory release function
- * usrfree users standard memory release function
- *
- * return XHash*
- * retval 0 out of memory
- * retval !0 Valid XHash pointer
- */
-/*
- Notes:
- if nrows < 0 don't cal the nearest powerof2.
- datasize must be the same for all entries, unless datasize is zero.
- maxmem of 0 indicates no memory limits.
-
-*/
-XHash* xhash_new(int nrows, int keysize, int datasize, unsigned long maxmem,
- int anr_flag,
- XHash_FREE_FCN anrfree,
- XHash_FREE_FCN usrfree,
- int recycle_flag)
-{
- if ( nrows > 0 ) /* make sure we have a prime number */
- {
- /* If nrows is not a power of two, need to find the
- * next highest power of two */
- nrows = xhash_nearest_powerof2(nrows);
- }
- else /* use the magnitude of nrows as is */
- {
- nrows = -nrows;
- }
-
- /* Allocate the table structure from general memory */
- XHash* h = (XHash*)snort_calloc(sizeof(XHash));
-
- /* this has a default hashing function */
- h->hashfcn = hashfcn_new(nrows);
- sfmemcap_init(&h->mc, maxmem);
-
- /* Allocate the array of node ptrs */
- h->table = (XHashNode**)s_alloc(h, sizeof(XHashNode*) * nrows);
- if ( !h->table )
- {
- snort_free(h->hashfcn);
- snort_free(h);
- return nullptr;
- }
-
- for ( int i = 0; i < nrows; i++ )
- h->table[i] = nullptr;
-
- h->anrfree = anrfree;
- h->usrfree = usrfree;
- h->keysize = keysize;
-
- h->pad = 0;
- h->datasize = datasize;
- h->nrows = nrows;
- h->max_nodes = 0;
- h->crow = 0;
- h->cnode = nullptr;
- h->count = 0;
- h->ghead = nullptr;
- h->gtail = nullptr;
- h->anr_count= 0;
- h->anr_tries= 0;
- h->anr_flag = anr_flag;
- h->splay = 1;
- h->recycle_nodes = recycle_flag;
-
- h->find_success = 0;
- h->find_fail = 0;
-
- /* save off how much we've already allocated from our memcap */
- h->overhead_bytes = h->mc.memused;
- h->overhead_blocks = h->mc.nblocks;
-
- return h;
-}
-
-/*
- * Set the maximum nodes used in this hash table.
- * Specifying 0 is unlimited (or otherwise limited by memcap).
- *
- * h XHash table pointer
- * max_nodes maximum nodes to allow.
- *
- */
-void xhash_set_max_nodes(XHash* h, int max_nodes)
-{
- if (h)
- {
- h->max_nodes = max_nodes;
- }
-}
-
-/*!
- * Free all nodes in the free list
- *
- * Removes and frees all of the nodes in the free list
- * No need to call the user free, since that should've been
- * done when those nodes were put back in the free list.
- *
- * h XHash table pointer
- */
-static void xhash_delete_free_list(XHash* t)
+XHash::XHash(int nrows_, int keysize_, int datasize_, unsigned long maxmem,
+ bool anr_enabled, Hash_FREE_FCN anr_free, Hash_FREE_FCN usr_free,
+ bool recycle_nodes)
+ : keysize(keysize_), datasize(datasize_), recycle_nodes(recycle_nodes),
+ anr_enabled(anr_enabled), anr_free(anr_free), usr_free(usr_free)
{
- if (t == nullptr || t->fhead == nullptr)
- return;
-
- XHashNode* cur = t->fhead;
- while (cur != nullptr)
- {
- XHashNode* next = cur->gnext;
- s_free(t, (void*)cur);
- cur = next;
- }
-
- t->fhead = nullptr;
- t->ftail = nullptr;
-}
-
-/*!
- * Try to change the memcap
- * Behavior is undefined when t->usrfree is set
- *
- * t SFXHASH table pointer
- * new_memcap the new desired memcap
- * max_work the maximum amount of work for the function to do (0 = do all available work)
- *
- * returns
- * XHASH_OK when memcap is successfully decreased
- * XHASH_PENDING when more work needs to be done
- * XHASH_NOMEM when there isn't enough memory in the hash table
- * XHASH_ERR when an error has occurred
- */
-int xhash_change_memcap(XHash *t, unsigned long new_memcap, unsigned *max_work)
-{
- if (t == nullptr or new_memcap < t->overhead_bytes)
- return XHASH_ERR;
-
- if (new_memcap == t->mc.memcap)
- return XHASH_OK;
-
- if (new_memcap > t->mc.memcap)
- {
- t->mc.memcap = new_memcap;
- return XHASH_OK;
- }
-
- unsigned work = 0;
- while (new_memcap < t->mc.memused
- and (work < *max_work or *max_work == 0)
- and (xhash_free_anr_lru(t) == XHASH_OK))
- work++;
+ // adjust rows to be power of 2
+ if ( nrows_ > 0 )
+ nrows = hash_nearest_power_of_2(nrows_);
+ else
+ nrows = -nrows_; // if negative use as is
- if (*max_work != 0 and (work == *max_work and new_memcap < t->mc.memused))
- {
- *max_work -= work;
- return XHASH_PENDING;
- }
+ table = (HashNode**)snort_calloc(sizeof(HashNode*) * nrows);
+ hashfcn = hashfcn_new(nrows);
+ sfmemcap_init(&mc, maxmem);
- //we ran out of nodes to free and there still isn't enough memory
- //or (we have undefined behavior: t->usrfree is set and xhash_free_anr_lru is returning XHASH_ERR)
- if (new_memcap < t->mc.memused)
- return XHASH_NOMEM;
+ for ( unsigned i = 0; i < nrows; i++ )
+ table[i] = nullptr;
- t->mc.memcap = new_memcap;
- return XHASH_OK;
+ mem_allocated_per_entry = sizeof(HashNode) + keysize + datasize + sizeof(long);
}
-/*!
- * Delete the hash Table
- *
- * free keys, free nodes, and free the users data.
- *
- * h XHash table pointer
- *
- */
-void xhash_delete(XHash* h)
+XHash::~XHash()
{
- if ( !h )
- return;
-
- if ( h->hashfcn )
- hashfcn_free(h->hashfcn);
+ if ( hashfcn )
+ hashfcn_free(hashfcn);
- if ( h->table )
+ for (unsigned i = 0; i < nrows; i++)
{
- for (unsigned i = 0; i < h->nrows; i++)
+ for ( HashNode* node = table[i]; node; )
{
- for ( XHashNode* node = h->table[i]; node; )
- {
- XHashNode* onode = node;
- node = node->next;
+ HashNode* onode = node;
+ node = node->next;
- /* Notify user that we are about to free this node function */
- if ( h->usrfree )
- h->usrfree(onode->key, onode->data);
+ if ( usr_free )
+ usr_free(onode->key, onode->data);
- s_free(h, onode);
- }
+ sfmemcap_free(&mc, onode);
}
- s_free(h, h->table);
- h->table = nullptr;
}
-
- xhash_delete_free_list(h);
-
- snort_free(h); /* free the table from general memory */
+ snort_free(table);
+ purge_free_list();
}
-/*!
- * Empty out the hash table
- *
- * h XHash table pointer
- *
- * return -1 on error
- */
-int xhash_make_empty(XHash* h)
+void XHash::clear()
{
- XHashNode* tmp = nullptr;
-
- if (h == nullptr)
- return -1;
-
- for (unsigned i = 0; i < h->nrows; i++)
+ for (unsigned i = 0; i < nrows; i++)
{
- for (XHashNode* n = h->table[i]; n != nullptr; n = tmp)
+ HashNode* n = table[i];
+ while ( n )
{
- tmp = n->next;
- if (xhash_free_node(h, n) != XHASH_OK)
- {
- return -1;
- }
+ HashNode* tmp;
+ tmp = n;
+ n = n->next;
+ release_node(tmp);
}
}
- h->max_nodes = 0;
- h->crow = 0;
- h->cnode = nullptr;
- h->count = 0;
- h->ghead = nullptr;
- h->gtail = nullptr;
- h->anr_count = 0;
- h->anr_tries = 0;
- h->find_success = 0;
- h->find_fail = 0;
-
- return 0;
+ max_nodes = 0;
+ crow = 0;
+ cnode = nullptr;
+ count = 0;
+ ghead = nullptr;
+ gtail = nullptr;
+ anr_count = 0;
+ anr_tries = 0;
+ find_success = 0;
+ find_fail = 0;
}
-/** Save the freed node for later use (recylcing).
- * Free List - uses the NODE gnext/gprev fields
- */
-static void xhash_save_free_node(XHash* t, XHashNode* hnode)
+void XHash::save_free_node(HashNode* hnode)
{
- /* Add A Node to the Free Node List */
- if ( t->fhead ) /* add the node to head of the the existing list */
+ if ( fhead )
{
hnode->gprev = nullptr;
- hnode->gnext = t->fhead;
- t->fhead->gprev = hnode;
- t->fhead = hnode;
- /* tail is not affected */
+ hnode->gnext = fhead;
+ fhead->gprev = hnode;
+ fhead = hnode;
}
- else /* 1st node in this list */
+ else
{
hnode->gprev = nullptr;
hnode->gnext = nullptr;
- t->fhead = hnode;
- t->ftail = hnode;
+ fhead = hnode;
+ ftail = hnode;
}
}
-/**Get a previously freed node for reuse.
- */
-static XHashNode* xhash_get_free_node(XHash* t)
+HashNode* XHash::get_free_node()
{
- XHashNode* node = t->fhead;
+ HashNode* node = fhead;
- /* Remove A Node from the Free Node List - remove the head node */
- if ( t->fhead )
+ if ( fhead )
{
- t->fhead = t->fhead->gnext;
- if ( t->fhead )
- t->fhead->gprev = nullptr;
+ fhead = fhead->gnext;
+ if ( fhead )
+ fhead->gprev = nullptr;
- if ( t->ftail == node ) /* no more nodes - clear the tail */
- t->ftail = nullptr;
+ if ( ftail == node )
+ ftail = nullptr;
}
return node;
}
-static void xhash_glink_node(XHash* t, XHashNode* hnode)
+void XHash::purge_free_list()
{
- /* Add The Node */
- if ( t->ghead ) /* add the node to head of the the existing list */
+ HashNode* cur = fhead;
+ while ( cur )
{
- hnode->gprev = nullptr;
- hnode->gnext = t->ghead;
- t->ghead->gprev = hnode;
- t->ghead = hnode;
- /* tail is not affected */
+ HashNode* next = cur->gnext;
+ sfmemcap_free(&mc, (void*)cur);
+ cur = next;
}
- else /* 1st node in this list */
+
+ fhead = nullptr;
+ ftail = nullptr;
+}
+
+void XHash::glink_node(HashNode* hnode)
+{
+ if ( ghead )
+ {
+ hnode->gprev = nullptr;
+ hnode->gnext = ghead;
+ ghead->gprev = hnode;
+ ghead = hnode;
+ }
+ else
{
hnode->gprev = nullptr;
hnode->gnext = nullptr;
- t->ghead = hnode;
- t->gtail = hnode;
+ ghead = hnode;
+ gtail = hnode;
}
}
-static void xhash_gunlink_node(XHash* t, XHashNode* hnode)
+void XHash::gunlink_node(HashNode* hnode)
{
- if ( t->gnode == hnode ) /* if this was the global next node */
- {
- t->gnode = hnode->gnext;
- }
+ if ( gnode == hnode )
+ gnode = hnode->gnext;
- /* Remove the Head Node */
- if ( t->ghead == hnode ) /* add the node to head of the the existing list */
+ if ( ghead == hnode )
{
- t->ghead = t->ghead->gnext;
- if ( t->ghead )
- t->ghead->gprev = nullptr;
+ ghead = ghead->gnext;
+ if ( ghead )
+ ghead->gprev = nullptr;
}
if ( hnode->gprev )
if ( hnode->gnext )
hnode->gnext->gprev = hnode->gprev;
- if ( t->gtail == hnode )
- t->gtail = hnode->gprev;
+ if ( gtail == hnode )
+ gtail = hnode->gprev;
}
-/**Move node to the front of global list. Node movement is application specific.
- */
-void xhash_gmovetofront(XHash* t, XHashNode* hnode)
+void XHash::gmove_to_front(HashNode* hnode)
{
- if ( hnode != t->ghead )
+ if ( hnode != ghead )
{
- xhash_gunlink_node(t, hnode);
- xhash_glink_node(t, hnode);
+ gunlink_node(hnode);
+ glink_node(hnode);
}
}
-/*
- *
- */
-static void xhash_link_node(XHash* t, XHashNode* hnode)
+HashNode* XHash::gfind_next()
+{
+ HashNode* n = gnode;
+ if ( n )
+ gnode = n->gnext;
+ return n;
+}
+
+HashNode* XHash::gfind_first()
+{
+ if ( ghead )
+ gnode = ghead->gnext;
+ else
+ gnode = nullptr;
+ return ghead;
+}
+
+void* XHash::get_mru_user_data()
+{
+ if ( ghead )
+ return ghead->data;
+ else
+ return nullptr;
+}
+
+void* XHash::get_lru_user_data()
+{
+ if ( gtail )
+ return gtail->data;
+ else
+ return nullptr;
+}
+
+void XHash::link_node(HashNode* hnode)
{
- /* Add The Node to the Hash Table Row List */
- if ( t->table[hnode->rindex] ) /* add the node to the existing list */
+ if ( table[hnode->rindex] )
{
- hnode->prev = nullptr; // insert node as head node
- hnode->next=t->table[hnode->rindex];
- t->table[hnode->rindex]->prev = hnode;
- t->table[hnode->rindex] = hnode;
+ hnode->prev = nullptr;
+ hnode->next = table[hnode->rindex];
+ table[hnode->rindex]->prev = hnode;
+ table[hnode->rindex] = hnode;
}
- else /* 1st node in this list */
+ else
{
- hnode->prev=nullptr;
- hnode->next=nullptr;
- t->table[hnode->rindex] = hnode;
+ hnode->prev = nullptr;
+ hnode->next = nullptr;
+ table[hnode->rindex] = hnode;
}
}
-static void xhash_unlink_node(XHash* t, XHashNode* hnode)
+void XHash::unlink_node(HashNode* hnode)
{
- if ( hnode->prev ) // definitely not the 1st node in the list
+ if ( hnode->prev )
{
hnode->prev->next = hnode->next;
if ( hnode->next )
hnode->next->prev = hnode->prev;
}
- else if ( t->table[hnode->rindex] ) // must be the 1st node in the list
+ else if ( table[hnode->rindex] )
{
- t->table[hnode->rindex] = t->table[hnode->rindex]->next;
- if ( t->table[hnode->rindex] )
- t->table[hnode->rindex]->prev = nullptr;
+ table[hnode->rindex] = table[hnode->rindex]->next;
+ if ( table[hnode->rindex] )
+ table[hnode->rindex]->prev = nullptr;
}
}
-/*
- * move a node to the front of the row list at row = 'index'
- */
-static void movetofront(XHash* t, XHashNode* n)
+void XHash::move_to_front(HashNode* n)
{
- /* Modify Hash Node Row List */
- if ( t->table[n->rindex] != n ) // if not at front of list already...
+ if ( table[n->rindex] != n )
{
- /* Unlink the node */
- xhash_unlink_node(t, n);
-
- /* Link at front of list */
- xhash_link_node(t, n);
+ unlink_node(n);
+ link_node(n);
}
- /* Move node in the global hash node list to the front */
- if (n == t->gnode)
- t->gnode = n->gnext;
- xhash_gmovetofront(t, n);
+ if (n == gnode)
+ gnode = n->gnext;
+ gmove_to_front(n);
}
/*
* to the front of the list. The oldest node is just the tail node.
*
*/
-static XHashNode* xhash_newnode(XHash* t)
+HashNode* XHash::allocate_node()
{
- /* Recycle Old Nodes - if any */
- XHashNode* hnode = xhash_get_free_node(t);
-
- /* Allocate memory for a node */
+ // use previously allocated node if there is a free one...
+ HashNode* hnode = get_free_node();
if ( !hnode )
{
- if ((t->max_nodes == 0) || (t->count < t->max_nodes))
- {
- hnode = (XHashNode*)s_alloc(t, sizeof(XHashNode) + t->pad +
- t->keysize + t->datasize);
- }
- }
+ if ( (max_nodes == 0) || (count < max_nodes) )
+ hnode = (HashNode*)sfmemcap_alloc(&mc,
+ sizeof(HashNode) + keysize + datasize);
- /* If we still haven't found hnode, we're at our memory limit.
- *
- * Uses Automatic Node Recovery, to recycle the oldest node-based on access
- * (Unlink and reuse the tail node)
- */
- if ( !hnode && t->anr_flag && t->gtail )
- {
- /* Find the oldest node the users willing to let go. */
- for (hnode = t->gtail; hnode; hnode = hnode->gprev )
+ if ( !hnode && anr_enabled && gtail )
{
- if ( t->anrfree ) /* User has provided a permission+release callback function */
+ /* Find the oldest node the users willing to let go. */
+ for (hnode = gtail; hnode; hnode = hnode->gprev )
{
- t->anr_tries++; /* Count # ANR requests */
-
- /* Ask the user for permission to release this node, but let them say no! */
- if ( t->anrfree(hnode->key, hnode->data) )
+ if ( anr_free )
{
- /* NO, don't recycle this node, user's not ready to let it go. */
- continue;
+ anr_tries++;
+ if ( anr_free(hnode->key, hnode->data) )
+ continue; // don't recycle this one...
}
- /* YES, user said we can recycle this node */
+ gunlink_node(hnode);
+ unlink_node(hnode);
+ count--;
+ anr_count++;
+ break;
}
-
- xhash_gunlink_node(t, hnode); /* unlink from the global list */
- xhash_unlink_node(t, hnode); /* unlink from the row list */
- t->count--;
- t->anr_count++; /* count # of ANR operations */
- break;
}
}
- /* either we are returning a node or we're all full and the user
- * won't let us allocate anymore and we return nullptr */
return hnode;
}
-/*
- *
- * Find a Node based on the key, return the node and the index.
- * The index is valid even if the return value is nullptr, in which
- * case the index is the correct row in which the node should be
- * created.
- *
- */
-
-#define hashsize(n) ((uint32_t)1<<(n))
-#define hashmask(n) (hashsize(n)-1)
-
-static XHashNode* xhash_find_node_row(XHash* t, const void* key, int* rindex)
+HashNode* XHash::find_node_row(const void* key, int* rindex)
{
- unsigned hashkey = t->hashfcn->hash_fcn(t->hashfcn, (const unsigned char*)key, t->keysize);
+ unsigned hashkey = hashfcn->hash_fcn(hashfcn, (const unsigned char*)key, keysize);
-/* printf("hashkey: %u t->keysize: %d\n", hashkey, t->keysize);
- flowkey_fprint(stdout, key);
- printf("****\n"); */
-
-// index = hashkey % t->nrows;
- /* Modulus is slow. Switched to a table size that is a power of 2. */
- int index = hashkey & (t->nrows - 1);
+ // Modulus is slow. masking since table size is a power of 2.
+ int index = hashkey & (nrows - 1);
*rindex = index;
- for (XHashNode* hnode = t->table[index]; hnode; hnode = hnode->next )
+ for (HashNode* hnode = table[index]; hnode; hnode = hnode->next )
{
- if ( !t->hashfcn->keycmp_fcn(hnode->key, key, t->keysize) )
+ if ( hashfcn->keycmp_fcn(hnode->key, key, keysize) )
{
- if ( t->splay > 0 )
- movetofront(t, hnode);
+ if ( splay > 0 )
+ move_to_front(hnode);
- t->find_success++;
+ find_success++;
return hnode;
}
}
- t->find_fail++;
+ find_fail++;
return nullptr;
}
-/*!
- * Add a key + data pair to the hash table
- *
- * 2003-06-06:
- * - unique_tracker.c assumes that this splays
- * nodes to the top when they are added.
- *
- * This is done because of the successful find.
- *
- * t XHash table pointer
- * key users key pointer
- * data users data pointer
- *
- * return integer
- * retval XHASH_OK success
- * retval XHASH_INTABLE already in the table, t->cnode points to the node
- * retval XHASH_NOMEM not enough memory
- */
-static int xhash_add_ex(XHash* t, const void* key, void* data, void** data_ptr)
+int XHash::insert(const void* key, void* data)
{
+ assert(key);
+
int index = 0;
/* Enforce uniqueness: Check for the key in the table */
- XHashNode* hnode = xhash_find_node_row(t, key, &index);
+ HashNode* hnode = find_node_row(key, &index);
if ( hnode )
{
- t->cnode = hnode;
- if (data_ptr)
- *data_ptr = hnode->data;
- return XHASH_INTABLE; /* found it - return it. */
+ cnode = hnode;
+ return HASH_INTABLE;
}
- /*
- * Alloc new hash node - allocate key space and data space at the same time.
- */
- hnode = xhash_newnode(t);
+ hnode = allocate_node();
if ( !hnode )
- {
- return XHASH_NOMEM;
- }
-
- /* Set up the new key pointer */
- hnode->key = (char*)hnode + sizeof(XHashNode);
-
- /* Copy the key */
- memcpy(hnode->key,key,t->keysize);
+ return HASH_NOMEM;
- /* Save our table row index */
+ hnode->key = (char*)hnode + sizeof(HashNode);
+ memcpy(hnode->key, key, keysize);
hnode->rindex = index;
- /* Copy the users data - or if datasize is zero set ptr to users data */
- if ( t->datasize )
+ if ( datasize )
{
- /* Set up the new data pointer */
- hnode->data= (char*)hnode + sizeof(XHashNode) + t->pad + t->keysize;
-
- if (data)
- {
- memcpy(hnode->data,data,t->datasize);
- }
- if (data_ptr)
- *data_ptr = hnode->data;
+ hnode->data = (char*)hnode + sizeof(HashNode) + keysize;
+ if ( data )
+ memcpy(hnode->data, data, datasize);
}
else
- {
hnode->data = data;
- }
- /* Link the node into the table row list */
- xhash_link_node (t, hnode);
+ link_node (hnode);
+ glink_node(hnode);
+ count++;
- /* Link at the front of the global node list */
- xhash_glink_node(t, hnode);
-
- /* Track # active nodes */
- t->count++;
-
- return XHASH_OK;
+ return HASH_OK;
}
-int xhash_add(XHash* t, void* key, void* data)
+HashNode* XHash::get_node(const void* key)
{
- return xhash_add_ex(t, key, data, nullptr);
-}
+ assert(key);
-/*!
- * Add a key to the hash table, return the hash node
- *
- * 2003-06-06:
- * - unique_tracker.c assumes that this splays
- * nodes to the top when they are added.
- *
- * This is done because of the successful find.
- *
- * t XHash table pointer
- * key users key pointer
- *
- * return XHashNode*
- * retval nullptr failed to add node
- */
-XHashNode* xhash_get_node(XHash* t, const void* key)
-{
int index = 0;
- /* Enforce uniqueness: Check for the key in the table */
- XHashNode* hnode = xhash_find_node_row(t, key, &index);
+ // Enforce uniqueness: Check for the key in the table
+ HashNode* hnode = find_node_row( key, &index);
if ( hnode )
{
- t->cnode = hnode;
-
- return hnode; /* found it - return it. */
+ cnode = hnode;
+ return hnode;
}
- /*
- * Alloc new hash node - allocate key space and data space at the same time.
- */
- hnode = xhash_newnode(t);
+ hnode = allocate_node();
if ( !hnode )
- {
return nullptr;
- }
-
- /* Set up the new key pointer */
- hnode->key = (char*)hnode + sizeof(XHashNode);
- /* Copy the key */
- memcpy(hnode->key,key,t->keysize);
-
- /* Save our table row index */
+ hnode->key = (char*)hnode + sizeof(HashNode);
+ memcpy(hnode->key, key, keysize);
hnode->rindex = index;
- /* Copy the users data - or if datasize is zero set ptr to users data */
- if ( t->datasize )
- {
- /* Set up the new data pointer */
- hnode->data = (char*)hnode + sizeof(XHashNode) + t->pad + t->keysize;
- }
+ if ( datasize )
+ hnode->data = (char*)hnode + sizeof(HashNode) + keysize;
else
- {
hnode->data = nullptr;
- }
- /* Link the node into the table row list */
- xhash_link_node (t, hnode);
-
- /* Link at the front of the global node list */
- xhash_glink_node(t, hnode);
-
- /* Track # active nodes */
- t->count++;
+ link_node(hnode);
+ glink_node(hnode);
+ count++;
return hnode;
}
-/*!
- * Add a key to the hash table, return the hash node
- * If space is not available, it will remove a single
- * node (the LRU) and replace it with a new node.
- *
- * This function handles the scenario that we don't
- * have enough room to allocate a new node - if this is the
- * case, additional pruning should be done
- *
- * t XHash table pointer
- * key users key pointer
- * prune_performed bool pointer, 1 = successful prune, 0 = no/failed prune
- *
- * return XHashNode*
- * retval XhashNode* successfully allocated
- * retval nullptr failed to allocate
- */
-XHashNode* xhash_get_node_with_prune(XHash* t, const void* key, bool* prune_performed)
+HashNode* XHash::get_node_with_prune(const void* key, bool* prune_performed)
{
- size_t mem_after_alloc = t->mc.memused + xhash_required_mem(t);
- bool over_capacity = (t->mc.memcap < mem_after_alloc);
- XHashNode* hnode = nullptr;
+ assert(key);
+
+ size_t mem_after_alloc = mc.memused + mem_allocated_per_entry;
+ bool over_capacity = (mc.memcap < mem_after_alloc);
- if (over_capacity)
- *prune_performed = (xhash_free_anr_lru(t) == XHASH_OK);
+ if ( over_capacity )
+ *prune_performed = (delete_anr_or_lru_node() == HASH_OK);
- if (*prune_performed or !over_capacity)
- hnode = xhash_get_node(t, key);
+ HashNode* hnode = nullptr;
+ if ( *prune_performed or !over_capacity )
+ hnode = get_node(key);
return hnode;
}
-/*!
- * Find a Node based on the key
- *
- * t XHash table pointer
- * key users key pointer
- *
- * return XHashNode* valid pointer to the hash node
- * retval 0 node not found
- *
- */
-XHashNode* xhash_find_node(XHash* t, const void* key)
+HashNode* XHash::find_node(const void* key)
{
- int rindex = 0;
-
- return xhash_find_node_row(t, key, &rindex);
-}
+ assert(key);
-/*!
- * Find the users data based associated with the key
- *
- * t XHash table pointer
- * key users key pointer
- *
- * return void* valid pointer to the users data
- * retval 0 node not found
- *
- */
-void* xhash_find(XHash* t, void* key)
-{
int rindex = 0;
- XHashNode* hnode = xhash_find_node_row(t, key, &rindex);
- if ( hnode )
- return hnode->data;
-
- return nullptr;
+ return find_node_row(key, &rindex);
}
-/**
- * Get the HEAD of the in use list
- *
- * t table pointer
- *
- * return the head of the list or nullptr
- */
-XHashNode* xhash_ghead(XHash* t)
+void* XHash::get_user_data(void* key)
{
- if (t)
- {
- return t->ghead;
- }
+ assert(key);
- return nullptr;
-}
-
-/**
- * Walk the global list
- *
- * n current node
- *
- * return the next node in the list or nullptr when at the end
- */
-XHashNode* xhash_gfindnext(XHash* t)
-{
- XHashNode* n = t->gnode;
- if (n)
- t->gnode = n->gnext;
- return n;
-}
-
-/**
- * Get the HEAD of the in use list
- *
- * t table pointer
- *
- * return the head of the list or nullptr
- */
-XHashNode* xhash_gfindfirst(XHash* t)
-{
- if (t)
- {
- if (t->ghead)
- t->gnode = t->ghead->gnext;
- else
- t->gnode = nullptr;
- return t->ghead;
- }
- return nullptr;
-}
-
-/*!
- * Return the most recently used data from the global list
- *
- * t XHash table pointer
- *
- * return void* valid pointer to the users data
- * retval 0 node not found
- *
- */
-void* xhash_mru(XHash* t)
-{
- XHashNode* hnode = xhash_ghead(t);
- if ( hnode )
- return hnode->data;
-
- return nullptr;
-}
-
-/*!
- * Return the least recently used data from the global list
- *
- * t XHash table pointer
- *
- * return void* valid pointer to the users data
- * retval 0 node not found
- *
- */
-void* xhash_lru(XHash* t)
-{
- XHashNode* hnode = t->gtail;
+ int rindex = 0;
+ HashNode* hnode = find_node_row(key, &rindex);
if ( hnode )
return hnode->data;
return nullptr;
}
-/*
- * Unlink and free the node
- */
-int xhash_free_node(XHash* t, XHashNode* hnode)
+int XHash::release_node(HashNode* hnode)
{
- xhash_unlink_node(t, hnode); /* unlink from the hash table row list */
+ assert(hnode);
- xhash_gunlink_node(t, hnode); /* unlink from global-hash-node list */
+ unlink_node(hnode);
+ gunlink_node(hnode);
+ count--;
- t->count--;
+ if ( usr_free )
+ usr_free(hnode->key, hnode->data);
- if ( t->usrfree )
- {
- t->usrfree(hnode->key, hnode->data);
- }
-
- if ( t->recycle_nodes )
- {
- xhash_save_free_node(t, hnode);
- }
+ if ( recycle_nodes )
+ save_free_node(hnode);
else
- {
- s_free(t, hnode);
- }
+ sfmemcap_free(&mc, hnode);
- return XHASH_OK;
+ return HASH_OK;
}
-/*!
- * Remove a Key + Data Pair from the table.
- *
- * t XHash table pointer
- * key users key pointer
- *
- * return 0 success
- * retval !0 failed
- *
- */
-int xhash_remove(XHash* t, void* key)
+int XHash::release_node(void* key)
{
- unsigned hashkey = t->hashfcn->hash_fcn(t->hashfcn, (unsigned char*)key, t->keysize);
-
-// index = hashkey % t->nrows;
- /* Modulus is slow */
- unsigned index = hashkey & (t->nrows - 1);
-
- for ( XHashNode* hnode = t->table[index]; hnode; hnode = hnode->next )
- {
- if ( !t->hashfcn->keycmp_fcn(hnode->key, key, t->keysize) )
- {
- return xhash_free_node(t, hnode);
- }
- }
+ assert(key);
- return XHASH_ERR;
-}
-
-/*
- Internal use only
-*/
-static void xhash_next(XHash* t)
-{
- if ( !t->cnode )
- return;
+ unsigned hashkey = hashfcn->hash_fcn(hashfcn, (unsigned char*)key, keysize);
- /* Next node in current node list */
- t->cnode = t->cnode->next;
- if ( t->cnode )
+ unsigned index = hashkey & (nrows - 1);
+ for ( HashNode* hnode = table[index]; hnode; hnode = hnode->next )
{
- return;
+ if ( hashfcn->keycmp_fcn(hnode->key, key, keysize) )
+ return release_node(hnode);
}
- /* Next row
- Get 1st node in next non-empty row/node list */
- for ( t->crow++; t->crow < t->nrows; t->crow++ )
- {
- t->cnode = t->table[ t->crow ];
- if ( t->cnode )
- {
- return;
- }
- }
+ return HASH_ERR;
}
-static inline int xhash_delete_free_node(XHash *t)
+int XHash::delete_free_node()
{
- XHashNode* fn = xhash_get_free_node(t);
+ HashNode* fn = get_free_node();
if (fn)
{
- s_free(t, fn);
- return XHASH_OK;
+ sfmemcap_free(&mc, fn);
+ return HASH_OK;
}
- return XHASH_ERR;
+ return HASH_ERR;
}
-/*!
- * Unlink and free an ANR node or the oldest node, if ANR is empty
- * behavior is undefined if either t->anrfree or t->usrfree is set
- *
- * t XHash table pointer
- *
- * returns
- * XHASH_ERR if error occurs
- * XHASH_OK if node is freed
- */
-int xhash_free_anr_lru(XHash *t)
+int XHash::delete_anr_or_lru_node()
{
- if (t == nullptr)
- return XHASH_ERR;
-
- if (t->fhead)
+ if ( fhead )
{
- if (xhash_delete_free_node(t) == XHASH_OK)
- return XHASH_OK;
+ if (delete_free_node() == HASH_OK)
+ return HASH_OK;
}
- if (t->gtail)
+ if ( gtail )
{
- if (xhash_free_node(t, t->gtail) == XHASH_OK)
+ if ( release_node(gtail) == HASH_OK )
{
- if (t->fhead)
+ if ( fhead )
{
- if (xhash_delete_free_node(t) == XHASH_OK)
- return XHASH_OK;
- }
- else if (!t->recycle_nodes)
- {
- return XHASH_OK;
+ if ( delete_free_node() == HASH_OK )
+ return HASH_OK;
}
+ else if ( !recycle_nodes )
+ return HASH_OK;
}
}
- return XHASH_ERR;
+ return HASH_ERR;
}
-/*!
- * Unlink and free nodes if the xhash is exceeding the
- * specified memcap
- *
- * t XHash table pointer
- * num_freed set to the number of nodes freed
- * work_limit the max amount of work to do
- *
- * returns
- * XHASH_ERR if error occurs
- * XHASH_OK if node(s) freed and memused is within memcap
- * XHASH_PENDING if additional pending is required
- */
-int xhash_free_overallocations(XHash* t, unsigned work_limit, unsigned* num_freed)
+int XHash::free_over_allocations(unsigned work_limit, unsigned* num_freed)
{
- while (t->mc.memcap < t->mc.memused and work_limit--)
+ while (mc.memcap < mc.memused and work_limit--)
{
- if (xhash_free_anr_lru(t) != XHASH_OK)
- return XHASH_ERR;
+ if (delete_anr_or_lru_node() != HASH_OK)
+ return HASH_ERR;
++*num_freed;
}
- return (t->mc.memcap >= t->mc.memused) ? XHASH_OK : XHASH_PENDING;
+ return (mc.memcap >= mc.memused) ? HASH_OK : HASH_PENDING;
}
-/*!
- * Find and return the first hash table node
- *
- * t XHash table pointer
- *
- * return 0 failed
- * retval !0 valid XHashNode *
- *
- */
-XHashNode* xhash_findfirst(XHash* t)
+void XHash::update_cnode()
{
- if (!t)
- return nullptr;
+ if ( !cnode )
+ return;
+
+ cnode = cnode->next;
+ if ( cnode )
+ return;
+
+ for ( crow++; crow < nrows; crow++ )
+ {
+ cnode = table[crow];
+ if ( cnode )
+ return;
+ }
+}
- /* Start with 1st row */
- for ( t->crow = 0; t->crow < t->nrows; t->crow++ )
+HashNode* XHash::find_first_node()
+{
+ for ( crow = 0; crow < nrows; crow++ )
{
- /* Get 1st Non-Null node in row list */
- t->cnode = t->table[ t->crow ];
- if ( t->cnode )
+ cnode = table[crow];
+ if ( cnode )
{
- XHashNode* n = t->cnode;
- xhash_next(t); // load t->cnode with the next entry
+ HashNode* n = cnode;
+ update_cnode();
return n;
}
}
return nullptr;
}
-/*!
- * Find and return the next hash table node
- *
- * t XHash table pointer
- *
- * return 0 failed
- * retval !0 valid XHashNode *
- *
- */
-XHashNode* xhash_findnext(XHash* t)
+HashNode* XHash::find_next_node()
{
- XHashNode* n = t->cnode;
- if ( !n ) /* Done, no more entries */
- {
+ HashNode* n = cnode;
+ if ( !n )
return nullptr;
- }
- /*
- Preload next node into current node
- */
- xhash_next(t);
+ update_cnode();
return n;
}
-// Make hashfcn use a separate set of opcodes for the backend.
-
-void xhash_set_keyops(XHash* h, hash_func hash_fcn, keycmp_func keycmp_fcn)
+void XHash::set_key_opcodes(hash_func hash_fcn, keycmp_func keycmp_fcn)
{
- assert(h and hash_fcn and keycmp_fcn);
- hashfcn_set_keyops(h->hashfcn, hash_fcn, keycmp_fcn);
+ hashfcn_set_keyops(hashfcn, hash_fcn, keycmp_fcn);
}
+
} // namespace snort
#include "utils/sfmemcap.h"
#include "main/snort_types.h"
-struct HashFnc;
+#include "hash_defs.h"
+#include "hashfcn.h"
namespace snort
{
-#define XHASH_NOMEM (-2)
-#define XHASH_ERR (-1)
-#define XHASH_OK 0
-#define XHASH_INTABLE 1
-#define XHASH_PENDING 2
-
-struct XHashNode
-{
- struct XHashNode* gnext; // global node list - used for aging nodes
- struct XHashNode* gprev;
- struct XHashNode* next; // row node list
- struct XHashNode* prev;
-
- int rindex; // row index of table this node belongs to.
-
- void* key; // Pointer to the key.
- void* data; // Pointer to the users data, this is not copied !
-};
-
-typedef int (* XHash_FREE_FCN)(void* key, void* data);
-
-struct XHash
+class SO_PUBLIC XHash
{
- HashFnc* hashfcn; // hash function
- int keysize; // bytes in key, if <= 0 -> keys are strings
- int datasize; // bytes in key, if == 0 -> user data
- XHashNode** table; // array of node ptr's */
- unsigned nrows; // # rows int the hash table use a prime number 211, 9871
- unsigned count; // total # nodes in table
-
- unsigned crow; // findfirst/next row in table
- unsigned pad;
- XHashNode* cnode; // findfirst/next node ptr
- int splay; // whether to splay nodes with same hash bucket
-
- unsigned max_nodes; // maximum # of nodes within a hash
+public:
+ XHash(int nrows_, int keysize_, int datasize_, unsigned long memcap,
+ bool anr_enabled, Hash_FREE_FCN, Hash_FREE_FCN, bool recycle_nodes);
+ ~XHash();
+
+ int free_over_allocations(unsigned work_limit, unsigned* num_freed);
+ void clear();
+
+ int insert(const void* key, void* data);
+ HashNode* get_node(const void* key);
+ HashNode* get_node_with_prune(const void* key, bool* prune_performed);
+ int release_node(void* key);
+ int release_node(HashNode* node);
+ int delete_anr_or_lru_node();
+ HashNode* find_node(const void* key);
+ HashNode* find_first_node();
+ HashNode* find_next_node();
+ void* get_user_data(void* key);
+ void* get_mru_user_data();
+ void* get_lru_user_data();
+ void set_key_opcodes(hash_func, keycmp_func);
+
+ // Set the maximum nodes used in this hash table.
+ // Specifying 0 is unlimited (or otherwise limited by memcap).
+ void set_max_nodes(int max)
+ { max_nodes = max; }
+
+ unsigned get_node_count()
+ { return count; }
+
+ unsigned get_anr_count()
+ { return anr_count; }
+
+ unsigned get_total_finds()
+ { return find_success + find_fail; }
+
+ unsigned get_find_fails()
+ { return find_fail; }
+
+ unsigned get_find_successes()
+ { return find_success; }
+
+ void set_memcap(unsigned long new_memcap)
+ { mc.memcap = new_memcap; }
+
+ unsigned long get_memcap()
+ { return mc.memcap; }
+
+ unsigned long get_mem_used()
+ { return mc.memused; }
+
+ const HashNode* get_cnode () const
+ { return cnode; }
+
+ int get_keysize () const
+ { return keysize; }
+
+private:
+ void purge_free_list();
+ void save_free_node(HashNode* hnode);
+ HashNode* get_free_node();
+ void glink_node(HashNode* hnode);
+ void gunlink_node(HashNode* hnode);
+ void gmove_to_front(HashNode* hnode);
+ HashNode* gfind_first();
+ HashNode* gfind_next();
+ void link_node(HashNode* hnode);
+ void unlink_node(HashNode* hnode);
+ void move_to_front(HashNode* n);
+ HashNode* allocate_node();
+ HashNode* find_node_row(const void* key, int* rindex);
+ void update_cnode();
+ int delete_free_node();
+
+ HashFnc* hashfcn = nullptr; // hash function
+ int keysize = 0; // bytes in key, if <= 0 -> keys are strings - FIXIT-H does negative keysize work?
+ int datasize = 0; // bytes in key, if == 0 -> user data
+ unsigned mem_allocated_per_entry = 0;
+ HashNode** table = nullptr; // array of node ptr's */
+ unsigned nrows = 0; // # rows int the hash table use a prime number 211, 9871
+ unsigned count = 0; // total # nodes in table
+ unsigned crow = 0; // findfirst/next row in table
+ HashNode* cnode = nullptr; // find_[first|next] node ptr
+ int splay = 1; // whether to splay nodes with same hash bucket
+ unsigned max_nodes = 0; // maximum # of nodes within a hash
MEMCAP mc;
- unsigned overhead_bytes; // # of bytes that will be unavailable for nodes inside the
- // table
- unsigned overhead_blocks; // # of blocks consumed by the table
- unsigned find_fail;
- unsigned find_success;
-
- XHashNode* ghead, * gtail; // global - root of all nodes allocated in table
- XHashNode* fhead, * ftail; // list of free nodes, which are recycled
- XHashNode* gnode; // gfirst/gnext node ptr */
- int recycle_nodes; // recycle nodes. Nodes are not freed, but are used for
- // subsequent new nodes
-
- /* Automatic Node Recover (ANR): When number of nodes in hash is equal
- * to max_nodes, remove the least recently used nodes and use it for
- * the new node. anr_tries indicates # of ANR tries.*/
-
- unsigned anr_tries;
- unsigned anr_count; // # ANR ops performed
- int anr_flag; // 0=off, !0=on
-
- XHash_FREE_FCN anrfree;
- XHash_FREE_FCN usrfree;
+ unsigned find_fail = 0;
+ unsigned find_success = 0;
+
+ HashNode* ghead = nullptr; // global - root of all nodes allocated in table
+ HashNode* gtail = nullptr;
+ HashNode* gnode = nullptr; // gfirst/gnext node ptr */
+ HashNode* fhead = nullptr; // list of free nodes, which are recycled
+ HashNode* ftail = nullptr;
+ bool recycle_nodes = false; // recycle nodes...
+
+ // Automatic Node Recover (ANR): When number of nodes in hash is equal
+ // to max_nodes, remove the least recently used nodes and use it for
+ // the new node. anr_tries indicates # of ANR tries.*/
+ unsigned anr_tries = 0;
+ unsigned anr_count = 0; // # ANR ops performed
+ bool anr_enabled = false; // false = anr disable, true = anr enabled
+
+ Hash_FREE_FCN anr_free = nullptr;
+ Hash_FREE_FCN usr_free = nullptr;
};
-SO_PUBLIC XHash* xhash_new(int nrows, int keysize, int datasize, unsigned long memcap,
- int anr_flag,
- XHash_FREE_FCN anrfunc,
- XHash_FREE_FCN usrfunc,
- int recycle_flag);
-
-SO_PUBLIC void xhash_set_max_nodes(XHash* h, int max_nodes);
-SO_PUBLIC int xhash_change_memcap(XHash *t, unsigned long new_memcap, unsigned *max_work);
-SO_PUBLIC int xhash_free_overallocations(XHash* t, unsigned work_limit, unsigned* num_freed);
-SO_PUBLIC void xhash_delete(XHash* h);
-SO_PUBLIC int xhash_make_empty(XHash*);
-
-SO_PUBLIC int xhash_add(XHash* h, void* key, void* data);
-SO_PUBLIC XHashNode* xhash_get_node(XHash* t, const void* key);
-SO_PUBLIC XHashNode* xhash_get_node_with_prune(XHash* t, const void* key, bool* prune_performed);
-SO_PUBLIC int xhash_remove(XHash* h, void* key);
-
-// Get the # of Nodes in HASH the table
-inline unsigned xhash_count(XHash* t)
-{ return t->count; }
-
-// Get the # auto recovery
-inline unsigned xhash_anr_count(XHash* t)
-{ return t->anr_count; }
-
-// Get the # finds
-inline unsigned xhash_find_total(XHash* t)
-{ return t->find_success + t->find_fail; }
-
-// Get the # unsuccessful finds
-inline unsigned xhash_find_fail(XHash* t)
-{ return t->find_fail; }
-
-// Get the # successful finds
-inline unsigned xhash_find_success(XHash* t)
-{ return t->find_success; }
-
-// Get the # of overhead bytes
-inline unsigned xhash_overhead_bytes(XHash* t)
-{ return t->overhead_bytes; }
-
-// Get the # of overhead blocks
-inline unsigned xhash_overhead_blocks(XHash* t)
-{ return t->overhead_blocks; }
-
-// Get the amount of space required to allocate a new node in the xhash t.
-constexpr size_t xhash_required_mem(XHash *t)
-{ return sizeof(XHashNode) + t->pad + t->keysize + t->datasize + sizeof(long); }
-
-SO_PUBLIC int xhash_free_anr_lru(XHash* t);
-SO_PUBLIC void* xhash_mru(XHash* t);
-SO_PUBLIC void* xhash_lru(XHash* t);
-SO_PUBLIC void* xhash_find(XHash* h, void* key);
-SO_PUBLIC XHashNode* xhash_find_node(XHash* t, const void* key);
-
-SO_PUBLIC XHashNode* xhash_findfirst(XHash* h);
-SO_PUBLIC XHashNode* xhash_findnext(XHash* h);
-
-SO_PUBLIC XHashNode* xhash_ghead(XHash* h);
-SO_PUBLIC void xhash_gmovetofront(XHash* t, XHashNode* hnode);
-
-SO_PUBLIC int xhash_free_node(XHash* t, XHashNode* node);
-
-typedef uint32_t (* hash_func)(HashFnc*, const unsigned char* d, int n);
-
-
-// return 0 for ==, 1 for != ; FIXIT-L convert to bool
-typedef int (* keycmp_func)(const void* s1, const void* s2, size_t n);
-
-SO_PUBLIC void xhash_set_keyops(XHash* h, hash_func, keycmp_func);
-
-SO_PUBLIC XHashNode* xhash_gfindfirst(XHash* t);
-SO_PUBLIC XHashNode* xhash_gfindnext(XHash* t);
} // namespace snort
#endif
#include "zhash.h"
+#include <cassert>
#include <cstring>
-#include "hashfcn.h"
+#include "hash_defs.h"
+
+using namespace snort;
//-------------------------------------------------------------------------
// private stuff
//-------------------------------------------------------------------------
-struct ZHashNode
-{
- ZHashNode* gnext = nullptr; // global list
- ZHashNode* gprev = nullptr; // global list
-
- ZHashNode* next = nullptr; // row list
- ZHashNode* prev = nullptr; // row list
-
- int rindex = 0;
-
- void* key = nullptr;
- void* data = nullptr;
-};
-
-static inline ZHashNode* s_node_alloc(int keysize)
+static inline HashNode* s_node_alloc(int keysize)
{
- auto node = static_cast<ZHashNode*>(
- ::operator new(sizeof(ZHashNode) + keysize));
+ auto node = static_cast<HashNode*>(
+ ::operator new(sizeof(HashNode) + keysize));
*node = {};
return node;
}
-static inline void s_node_free(ZHashNode* node)
+static inline void s_node_free(HashNode* node)
{ ::operator delete(node); }
void ZHash::delete_free_list()
if ( !fhead )
return;
- ZHashNode* cur = fhead;
+ HashNode* cur = fhead;
while ( cur )
{
}
}
-void ZHash::save_free_node(ZHashNode* node)
+void ZHash::save_free_node(HashNode* node)
{
if ( fhead )
{
}
}
-ZHashNode* ZHash::get_free_node()
+HashNode* ZHash::get_free_node()
{
- ZHashNode* node = fhead;
+ HashNode* node = fhead;
if ( fhead )
{
return node;
}
-void ZHash::glink_node(ZHashNode* node)
+void ZHash::glink_node(HashNode* node)
{
if ( ghead )
{
}
}
-void ZHash::gunlink_node(ZHashNode* node)
+void ZHash::gunlink_node(HashNode* node)
{
if ( cursor == node )
cursor = node->gprev;
gtail = node->gprev;
}
-void ZHash::link_node(ZHashNode* node)
+void ZHash::link_node(HashNode* node)
{
if ( table[node->rindex] ) // UNINITUSE
{
}
}
-void ZHash::unlink_node(ZHashNode* node)
+void ZHash::unlink_node(HashNode* node)
{
if ( node->prev )
{
}
}
-void ZHash::move_to_front(ZHashNode* node)
+void ZHash::move_to_front(HashNode* node)
{
// move to front of row list
if ( table[node->rindex] != node )
}
}
-ZHashNode* ZHash::find_node_row(const void* key, int& row)
+HashNode* ZHash::find_node_row(const void* key, int& row)
{
unsigned hashkey = hashfcn->hash_fcn(
hashfcn, (const unsigned char*)key, keysize);
int index = hashkey & (nrows - 1);
row = index;
- for ( ZHashNode* node=table[index]; node; node=node->next ) // UNINITUSE
+ for ( HashNode* node = table[index]; node; node = node->next ) // UNINITUSE
{
- if ( !hashfcn->keycmp_fcn(node->key,key,keysize) )
+ if ( hashfcn->keycmp_fcn(node->key, key, keysize) )
{
move_to_front(node);
find_success++;
return nullptr;
}
-int ZHash::nearest_powerof2(int rows)
-{
- rows -= 1;
-
- for ( unsigned i=1; i<sizeof(rows) * 8; i <<= 1 )
- rows = rows | (rows >> i);
-
- rows += 1;
- return rows;
-}
-
//-------------------------------------------------------------------------
// public stuff
//-------------------------------------------------------------------------
ZHash::ZHash(int rows, int keysz)
+ : keysize(keysz)
{
+ // adjust rows to be power of 2
if ( rows > 0 )
- {
- // make sure we have a prime number
- // rows = nearest_prime(rows);
-
- /* If rows is not a power of two, need to find the
- * next highest power of two */
- rows = nearest_powerof2(rows);
- }
- else /* use the magnitude of rows as is */
- {
- rows = -rows;
- }
-
- /* this has a default hashing function */
- hashfcn = hashfcn_new(rows);
-
- /* Allocate the array of node ptrs */
- table = new ZHashNode*[rows]();
+ nrows = hash_nearest_power_of_2(rows);
+ else
+ nrows = -rows; // if negative use as is
- keysize = keysz;
- nrows = rows;
+ table = new HashNode*[nrows]();
+ hashfcn = hashfcn_new(nrows);
fhead = cursor = nullptr;
ghead = gtail = nullptr;
ZHash::~ZHash()
{
- if ( hashfcn )
- hashfcn_free(hashfcn);
+ hashfcn_free(hashfcn);
- if ( table )
+ for ( unsigned i = 0; i < nrows; ++i )
{
- for ( unsigned i = 0; i < nrows; ++i )
+ for ( HashNode* node = table[i]; node; )
{
- for ( ZHashNode* node = table[i]; node; )
- {
- ZHashNode* onode = node;
- node = node->next;
- s_node_free(onode);
- }
+ HashNode* onode = node;
+ node = node->next;
+ s_node_free(onode);
}
- delete[] table;
}
+
+ delete[] table;
delete_free_list();
}
{
auto node = s_node_alloc(keysize);
- node->key = (char*)node + sizeof(ZHashNode);
+ node->key = (char*)node + sizeof(HashNode);
node->data = p;
save_free_node(node);
void* ZHash::pop()
{
- ZHashNode* node = get_free_node();
+ HashNode* node = get_free_node();
if ( !node )
return nullptr;
void* ZHash::get(const void* key, bool *new_node)
{
int row;
- ZHashNode* node = find_node_row(key, row);
+ HashNode* node = find_node_row(key, row);
if ( node )
return node->data;
void* ZHash::find(const void* key)
{
int row;
- ZHashNode* node = find_node_row(key, row);
+ HashNode* node = find_node_row(key, row);
if ( node )
return node->data;
bool ZHash::touch()
{
- ZHashNode* node = cursor;
+ HashNode* node = cursor;
if ( !node )
return false;
return false;
}
-bool ZHash::move_to_free_list(ZHashNode* node)
+bool ZHash::move_to_free_list(HashNode* node)
{
if ( !node )
return false;
bool ZHash::release()
{
- ZHashNode* node = cursor;
+ HashNode* node = cursor;
cursor = nullptr;
return move_to_free_list(node);
}
bool ZHash::release(const void* key)
{
int row;
- ZHashNode* node = find_node_row(key, row);
+ HashNode* node = find_node_row(key, row);
return move_to_free_list(node);
}
{
void* pv = nullptr;
int row;
- ZHashNode* node = find_node_row(key, row);
+ HashNode* node = find_node_row(key, row);
if ( node )
{
unlink_node(node);
return pv;
}
-int ZHash::set_keyops(
- unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n))
+void ZHash::set_key_opcodes(hash_func hash_fcn, keycmp_func keycmp_fcn)
{
- if ( hash_fcn && keycmp_fcn )
- return hashfcn_set_keyops(hashfcn, hash_fcn, keycmp_fcn);
-
- return -1;
+ hashfcn_set_keyops(hashfcn, hash_fcn, keycmp_fcn);
}
#include <cstddef>
-struct HashFnc;
-struct ZHashNode;
+#include "hashfcn.h"
+
+namespace snort
+{
+struct HashNode;
+}
class ZHash
{
bool release(const void* key);
bool release();
void* remove(const void* key);
+ void set_key_opcodes(hash_func, keycmp_func);
- inline unsigned get_count() { return count; }
- int set_keyops(
- unsigned (* hash_fcn)(HashFnc* p, const unsigned char* d, int n),
- int (* keycmp_fcn)(const void* s1, const void* s2, size_t n));
+ inline unsigned get_count()
+ { return count; }
private:
- ZHashNode* get_free_node();
- ZHashNode* find_node_row(const void*, int&);
+ snort::HashNode* get_free_node();
+ snort::HashNode* find_node_row(const void*, int&);
- void glink_node(ZHashNode*);
- void gunlink_node(ZHashNode*);
+ void glink_node(snort::HashNode*);
+ void gunlink_node(snort::HashNode*);
- void link_node(ZHashNode*);
- void unlink_node(ZHashNode*);
+ void link_node(snort::HashNode*);
+ void unlink_node(snort::HashNode*);
void delete_free_list();
- void save_free_node(ZHashNode*);
+ void save_free_node(snort::HashNode*);
- bool move_to_free_list(ZHashNode*);
- void move_to_front(ZHashNode*);
- int nearest_powerof2(int nrows);
+ bool move_to_free_list(snort::HashNode*);
+ void move_to_front(snort::HashNode*);
private:
HashFnc* hashfcn;
unsigned find_fail;
unsigned find_success;
- ZHashNode** table;
- ZHashNode* ghead;
- ZHashNode* gtail;
- ZHashNode* fhead;
- ZHashNode* cursor;
+ snort::HashNode** table;
+ snort::HashNode* ghead;
+ snort::HashNode* gtail;
+ snort::HashNode* fhead;
+ snort::HashNode* cursor;
};
#endif
// FIXIT-M why is the hash lookup done at runtime for flowbits groups?
// a pointer to flowbis_grp should be in flowbits config data
// this *should* be safe but iff splay mode is disabled
- auto flowbits_grp = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash, group);
+ auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
if ( !flowbits_grp )
return 0;
if ( !group )
return 0;
- auto flowbits_grp = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash, group);
+ auto flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
if ( !flowbits_grp )
return 0;
return 0;
case FLOWBITS_ALL:
- flowbits_grp = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash, group);
+ flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
if ( flowbits_grp == nullptr )
return 0;
for ( i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
return 1;
case FLOWBITS_ANY:
- flowbits_grp = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash, group);
+ flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(group);
if ( flowbits_grp == nullptr )
return 0;
for ( i = 0; i <= (unsigned int)(flowbits_grp->max_id >>3); i++ )
void flowbits_ginit(SnortConfig* sc)
{
sc->flowbit_state = new FlowBitState;
- sc->flowbit_state->flowbits_hash = ghash_new(10000, 0, 0, FlowItemFree);
-
- if ( !sc->flowbit_state->flowbits_hash )
- FatalError("Could not create flowbits hash.\n");
+ sc->flowbit_state->flowbits_hash = new GHash(10000, 0, 0, FlowItemFree);
// this is used during parse time and runtime so do NOT
// enable splay mode (which is NOT useful here anyway)
- sc->flowbit_state->flowbits_grp_hash = ghash_new(10000, 0, 0, FlowBitsGrpFree);
-
- if ( !sc->flowbit_state->flowbits_grp_hash )
- FatalError("could not create flowbits group hash.\n");
-
+ sc->flowbit_state->flowbits_grp_hash = new GHash(10000, 0, 0, FlowBitsGrpFree);
sc->flowbit_state->flowbits_bit_queue = sfqueue_new();
-
- if ( !sc->flowbit_state->flowbits_bit_queue )
- FatalError("could not create flowbits bit queue.\n");
}
void flowbits_gterm(SnortConfig* sc)
return;
if ( flowbit_state->flowbits_hash )
- ghash_delete(flowbit_state->flowbits_hash);
+ delete flowbit_state->flowbits_hash;
if ( flowbit_state->flowbits_grp_hash )
- ghash_delete(flowbit_state->flowbits_grp_hash);
+ delete flowbit_state->flowbits_grp_hash;
if ( flowbit_state->flowbits_bit_queue )
sfqueue_free_all(flowbit_state->flowbits_bit_queue, nullptr);
s_name, ALLOWED_SPECIAL_CHARS);
}
- flowbits_item = (FLOWBITS_OBJECT*)ghash_find(flowbit_state->flowbits_hash, flowbitName);
+ flowbits_item = (FLOWBITS_OBJECT*)flowbit_state->flowbits_hash->find(flowbitName);
if (flowbits_item == nullptr)
{
}
}
- int hstatus = ghash_add(flowbit_state->flowbits_hash, flowbitName, flowbits_item);
-
+ int hstatus = flowbit_state->flowbits_hash->insert(flowbitName, flowbits_item);
if (hstatus != GHASH_OK)
ParseError("Could not add flowbits key (%s) to hash.",flowbitName);
}
s_name, ALLOWED_SPECIAL_CHARS);
}
- flowbits_grp = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash, groupName);
+ flowbits_grp = (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(groupName);
if ( !flowbits_grp )
{
// new group defined, add (bitop set later once we know size)
flowbits_grp = (FLOWBITS_GRP*)snort_calloc(sizeof(*flowbits_grp));
- int hstatus = ghash_add(flowbit_state->flowbits_grp_hash, groupName, flowbits_grp);
-
+ int hstatus = flowbit_state->flowbits_grp_hash->insert(groupName, flowbits_grp);
if (hstatus != GHASH_OK)
ParseAbort("Could not add flowbits group (%s) to hash.\n",groupName);
if ( !flowbit_state->flowbits_hash or !flowbit_state->flowbits_grp_hash )
return;
- for ( GHashNode* n = ghash_findfirst(flowbit_state->flowbits_grp_hash);
- n != nullptr;
- n= ghash_findnext(flowbit_state->flowbits_grp_hash) )
+ for (GHashNode* n = flowbit_state->flowbits_grp_hash->find_first();
+ n != nullptr;
+ n= flowbit_state->flowbits_grp_hash->find_next())
{
FLOWBITS_GRP* fbg = (FLOWBITS_GRP*)n->data;
fbg->GrpBitOp = new BitOp(flowbit_state->flowbits_count);
while ( !flowbit_state->op_list.empty() )
{
const FLOWBITS_OP* fbop = flowbit_state->op_list.front();
- FLOWBITS_GRP* fbg = (FLOWBITS_GRP*)ghash_find(flowbit_state->flowbits_grp_hash,
- fbop->group);
+ FLOWBITS_GRP* fbg =
+ (FLOWBITS_GRP*)flowbit_state->flowbits_grp_hash->find(fbop->group);
assert(fbg);
for ( int i = 0; i < fbop->num_ids; ++i )
if (flowbit_state->flowbits_hash == nullptr)
return;
- for (n = ghash_findfirst(flowbit_state->flowbits_hash);
- n != nullptr;
- n= ghash_findnext(flowbit_state->flowbits_hash))
+ for (n = flowbit_state->flowbits_hash->find_first();
+ n != nullptr;
+ n = flowbit_state->flowbits_hash->find_next())
{
FLOWBITS_OBJECT* fb = (FLOWBITS_OBJECT*)n->data;
if (fb->toggle != flowbit_state->flowbits_toggle)
{
sfqueue_add(flowbit_state->flowbits_bit_queue, (NODE_DATA)(uintptr_t)fb->id);
- ghash_remove(flowbit_state->flowbits_hash, n->key);
+ flowbit_state->flowbits_hash->remove(n->key);
continue;
}
if (errno != EEXIST)
{
FatalError("Problem creating directory %s: %s\n",
- log_path,get_error(errno));
+ log_path, get_error(errno));
}
}
if (p->ptrs.sp >= p->ptrs.dp)
SnortSnprintf(session_file, STD_BUF, "%s/SESSION:%d-%d", log_path, p->ptrs.sp, p->ptrs.dp);
-
-
else
SnortSnprintf(session_file, STD_BUF, "%s/SESSION:%d-%d", log_path, p->ptrs.dp, p->ptrs.sp);
if (sid == 0)
return nullptr;
- for (hashNode = ghash_findfirst(SnortConfig::get_conf()->otn_map);
+ for (hashNode = SnortConfig::get_conf()->otn_map->find_first();
hashNode;
- hashNode = ghash_findnext(SnortConfig::get_conf()->otn_map))
+ hashNode = SnortConfig::get_conf()->otn_map->find_next())
{
OptTreeNode* otn = (OptTreeNode*)hashNode->data;
RuleTreeNode* rtn = getRuntimeRtnFromOtn(otn);
namespace snort
{
-struct GHash;
+class GHash;
struct SnortConfig;
}
struct sfip_var_t;
typedef unsigned int PolicyId;
-typedef struct snort::GHash PortVarTable;
+typedef snort::GHash PortVarTable;
enum PolicyMode
{
fpDeleteFastPacketDetection(this);
OtnLookupFree(otn_map);
- if (rtn_hash_table)
- xhash_delete(rtn_hash_table);
+ delete rtn_hash_table;
if (eth_dst )
snort_free(eth_dst);
namespace snort
{
class ProtocolReference;
+class GHash;
+class XHash;
struct ProfilerConfig;
-struct GHash;
-struct XHash;
struct SnortConfig;
class ReloadResourceTuner
ProtocolReference* proto_ref = nullptr;
- int num_rule_types = 0;
+ unsigned num_rule_types = 0;
RuleListNode* rule_lists = nullptr;
int evalOrder[Actions::MAX + 1];
if ( !pi )
FatalError("unconfigured inspector: '%s'.\n", key);
-
else
pi->add_ref();
*/
void MimeSession::init()
{
- const MimeToken* tmp;
-
MimeDecode::init();
mime_hdr_search_mpse = new SearchTool;
-
- if (mime_hdr_search_mpse == nullptr)
- FatalError("Could not instantiate search engine.\n");
-
- for (tmp = &mime_hdrs[0]; tmp->name != nullptr; tmp++)
+ for (const MimeToken* tmp = &mime_hdrs[0]; tmp->name != nullptr; tmp++)
{
mime_hdr_search[tmp->search_id].name = tmp->name;
mime_hdr_search[tmp->search_id].name_len = tmp->name_len;
-
mime_hdr_search_mpse->add(tmp->name, tmp->name_len, tmp->search_id);
}
}
}
-void AppIdServiceState::dump_stats()
-{
- // FIXIT-L - do we need to keep ipv4 and ipv6 separate? CRC: No.
-#if 0
- LogMessage("Service State:\n");
- if (serviceStateCache4)
- {
- LogMessage(" IPv4 Count: %u\n", xhash_count(serviceStateCache4));
- LogMessage(" IPv4 Memory Limit: %lu\n", serviceStateCache4->mc.memcap);
- LogMessage(" IPv4 Memory Used: %lu\n", serviceStateCache4->mc.memused);
- }
- if (serviceStateCache6)
- {
- LogMessage(" IPv6 Count: %u\n", xhash_count(serviceStateCache6));
- LogMessage(" IPv6 Memory Limit: %lu\n", serviceStateCache6->mc.memcap);
- LogMessage(" IPv6 Memory Used: %lu\n", serviceStateCache6->mc.memused);
- }
-#endif
-}
-
bool AppIdServiceState::prune(size_t max_memory, size_t num_items)
{
if ( service_state_cache )
static ServiceDiscoveryState* get(const snort::SfIp*, IpProtocol, uint16_t port, bool decrypted, bool do_touch = false);
static void remove(const snort::SfIp*, IpProtocol, uint16_t port, bool decrypted);
static void check_reset(AppIdSession& asd, const snort::SfIp* ip, uint16_t port);
-
- static void dump_stats();
-
static bool prune(size_t max_memory = 0, size_t num_items = -1u);
};
*swapped = 1;
}
- value = (FlowStateValue*)xhash_find(ip_map, &key);
+ value = (FlowStateValue*)ip_map->get_user_data(&key);
if (!value)
{
- XHashNode* node = xhash_get_node_with_prune(ip_map, &key, &prune_required);
+ HashNode* node = ip_map->get_node_with_prune(&key, &prune_required);
if (!node)
- {
return nullptr;
- }
if (prune_required)
{
{
bool need_pruning = false;
- if (!ip_map)
+ if ( !ip_map )
{
- ip_map = xhash_new(DEFAULT_XHASH_NROWS, sizeof(FlowStateKey), sizeof(FlowStateValue),
- new_memcap, 1, nullptr, nullptr, 1);
+ ip_map = new XHash(DEFAULT_XHASH_NROWS, sizeof(FlowStateKey), sizeof(FlowStateValue),
+ new_memcap, true, nullptr, nullptr, true);
}
else
{
need_pruning = (new_memcap < memcap);
memcap = new_memcap;
- ip_map->mc.memcap = memcap;
+ ip_map->set_memcap(new_memcap);
}
return need_pruning;
formatter->finalize_fields();
memcap = perf->flowip_memcap;
-
- ip_map = xhash_new(DEFAULT_XHASH_NROWS, sizeof(FlowStateKey), sizeof(FlowStateValue),
- memcap, 1, nullptr, nullptr, 1);
-
- if (!ip_map)
- FatalError("Unable to allocate memory for FlowIP stats\n");
+ ip_map = new XHash(DEFAULT_XHASH_NROWS, sizeof(FlowStateKey), sizeof(FlowStateValue),
+ memcap, true, nullptr, nullptr, true);
}
FlowIPTracker::~FlowIPTracker()
{
- if ( ip_map )
- xhash_delete(ip_map);
+ delete ip_map;
}
void FlowIPTracker::reset()
{
- xhash_make_empty(ip_map);
+ ip_map->clear();
}
void FlowIPTracker::update(Packet* p)
void FlowIPTracker::process(bool)
{
- for (auto node = xhash_findfirst(ip_map); node; node = xhash_findnext(ip_map))
+ for (auto node = ip_map->find_first_node(); node; node = ip_map->find_next_node())
{
FlowStateKey* key = (FlowStateKey*)node->key;
FlowStateValue* cur_stats = (FlowStateValue*)node->data;
{ "seconds", Parameter::PT_INT, "1:max32", "60",
"report interval" },
- { "flow_ip_memcap", Parameter::PT_INT, "8200:maxSZ", "52428800",
+ { "flow_ip_memcap", Parameter::PT_INT, "236:maxSZ", "52428800",
"maximum memory in bytes for flow tracking" },
{ "max_file_size", Parameter::PT_INT, "4096:max53", "1073741824",
if (flow_ip_tracker)
{
unsigned num_freed = 0;
- int result = xhash_free_overallocations(flow_ip_tracker->get_ip_map(), work_limit, &num_freed);
+ int result = flow_ip_tracker->get_ip_map()->free_over_allocations(work_limit, &num_freed);
pmstats.total_frees += num_freed;
pmstats.reload_frees += num_freed;
- return (result == XHASH_OK);
+ return (result == HASH_OK);
}
else
return true;
{
if ( portscan_hash )
{
- xhash_delete(portscan_hash);
+ delete portscan_hash;
portscan_hash = nullptr;
}
}
{
if ( portscan_hash )
{
- bool need_pruning = (memcap < portscan_hash->mc.memused);
- portscan_hash->mc.memcap = memcap;
+ bool need_pruning = (memcap < portscan_hash->get_mem_used());
+ portscan_hash->set_memcap(memcap);
return need_pruning;
}
int rows = memcap / ps_node_size();
-
- portscan_hash = xhash_new(rows, sizeof(PS_HASH_KEY), sizeof(PS_TRACKER),
- memcap, 1, ps_tracker_free, nullptr, 1);
-
- if ( !portscan_hash )
- FatalError("Failed to initialize portscan hash table.\n");
+ portscan_hash = new XHash(rows, sizeof(PS_HASH_KEY), sizeof(PS_TRACKER),
+ memcap, true, ps_tracker_free, nullptr, true);
return false;
}
return true;
unsigned num_pruned = 0;
- int result = xhash_free_overallocations(portscan_hash, work_limit, &num_pruned);
+ int result = portscan_hash->free_over_allocations(work_limit, &num_pruned);
spstats.reload_prunes += num_pruned;
- return result != XHASH_PENDING;
+ return result != HASH_PENDING;
}
void ps_reset()
{
if ( portscan_hash )
- xhash_make_empty(portscan_hash);
+ portscan_hash->clear();
}
// Check scanner and scanned ips to see if we can filter them out.
*/
static PS_TRACKER* ps_tracker_get(PS_HASH_KEY* key)
{
- PS_TRACKER* ht = (PS_TRACKER*)xhash_find(portscan_hash, (void*)key);
+ PS_TRACKER* ht = (PS_TRACKER*)portscan_hash->get_user_data((void*)key);
if ( ht )
return ht;
- auto prev_count = portscan_hash->count;
- if ( xhash_add(portscan_hash, (void*)key, nullptr) != XHASH_OK )
+ auto prev_count = portscan_hash->get_node_count();
+ if ( portscan_hash->insert((void*)key, nullptr) != HASH_OK )
return nullptr;
++spstats.trackers;
- if ( prev_count == portscan_hash->count )
+ if ( prev_count == portscan_hash->get_node_count() )
++spstats.alloc_prunes;
- ht = (PS_TRACKER*)xhash_mru(portscan_hash);
+ ht = (PS_TRACKER*)portscan_hash->get_mru_user_data();
if ( ht )
memset(ht, 0x00, sizeof(PS_TRACKER));
static PortObject* _POParseVar(POParser* pop)
{
- PortObject* pox;
- char* name;
-
- name = POParserName(pop);
-
+ char* name = POParserName(pop);
if (!name)
{
pop->pos++;
return nullptr;
}
- pox = PortVarTableFind(pop->pvTable, name);
+ PortObject* pox = PortVarTableFind(pop->pvTable, name);
snort_free(name);
if (!pox)
}
pox = PortObjectDup(pox);
-
- if (!pox)
- {
- pop->errflag = POPERR_MALLOC_FAILED;
- return nullptr;
- }
-
return pox;
}
{
PortObject* po = PortObjectNew();
- if (!po)
- {
- pop->errflag = POPERR_MALLOC_FAILED;
- return nullptr;
- }
-
pop->token[0] = 0;
/* The string in pop should only be of the form <port> or <port>:<port> */
static PortObject* _POParseString(POParser* pop)
{
- PortObject* po;
PortObject* potmp = nullptr;
int local_neg = 0;
char c;
int list_count = 0;
- po = PortObjectNew();
-
- if (!po)
- {
- pop->errflag = POPERR_MALLOC_FAILED;
- return nullptr;
- }
-
+ PortObject* po = PortObjectNew();
while ( (c = POPGetChar2(pop)) != 0 )
{
if (c == '!')
PortObject* PortObjectParseString(PortVarTable* pvTable, POParser* pop,
const char* name, const char* s, int nameflag)
{
- PortObject* po, * potmp;
-
POParserInit(pop, s, pvTable);
-
- po = PortObjectNew();
- if ( !po )
- {
- pop->errflag = POPERR_MALLOC_FAILED;
- return nullptr;
- }
+ PortObject* po = PortObjectNew();
if ( nameflag ) /* parse a name */
{
// LogMessage("PortObjectParseString: po->name=%s\n",po->name);
- potmp = _POParseString(pop);
-
+ PortObject* potmp = _POParseString(pop);
if ( !potmp )
{
PortObjectFree(po);
PortObject* pox = PortTableFindInputPortObjectPorts(dstTable, rtn->dst_portobject);
if ( !pox )
{
- /* Create a permanent port object */
- pox = PortObjectDupPorts(rtn->dst_portobject);
- if ( !pox )
- {
- ParseError("could not dup a port object - out of memory.");
- return -1;
- }
-
/* Add the port object to the table, and add the rule to the port object */
+ pox = PortObjectDupPorts(rtn->dst_portobject);
PortTableAddObject(dstTable, pox);
}
if ( !pox )
{
pox = PortObjectDupPorts(rtn->dst_portobject);
- if ( !pox )
- {
- ParseError("could not dup a bidir-port object - out of memory.");
- return -1;
- }
-
PortTableAddObject(srcTable, pox);
}
{
prc->src++;
PortObject* pox = PortTableFindInputPortObjectPorts(srcTable, rtn->src_portobject);
-
if ( !pox )
{
pox = PortObjectDupPorts(rtn->src_portobject);
- if ( !pox )
- {
- ParseError("could not dup a port object - out of memory.");
- return -1;
- }
PortTableAddObject(srcTable, pox);
}
if ( !pox )
{
pox = PortObjectDupPorts(rtn->src_portobject);
- if ( !pox )
- {
- ParseError("could not dup a bidir-port object - out of memory.");
- return -1;
- }
-
PortTableAddObject(dstTable, pox);
}
PortObjectAddRule(pox, otn->ruleIndex);
if ( sc->rtn_hash_table )
{
RuleTreeNodeKey key { testNode, policyId };
- return (RuleTreeNode*)xhash_find(sc->rtn_hash_table, &key);
+ return (RuleTreeNode*)sc->rtn_hash_table->get_user_data(&key);
}
return nullptr;
if ( !sc->otn_map )
return;
- for ( GHashNode* hashNode = ghash_findfirst(sc->otn_map);
- hashNode;
- hashNode = ghash_findnext(sc->otn_map) )
+ for (GHashNode* hashNode = sc->otn_map->find_first();
+ hashNode;
+ hashNode = sc->otn_map->find_next())
{
OptTreeNode* otn = (OptTreeNode*)hashNode->data;
/* Init sid-gid -> otn map */
sc->otn_map = OtnLookupNew();
- if (sc->otn_map == nullptr)
- ParseAbort("otn_map ghash_new failed.");
}
-static RuleListNode* addNodeToOrderedList(RuleListNode* ordered_list,
- RuleListNode* node, int evalIndex)
+static RuleListNode* addNodeToOrderedList
+ (RuleListNode* ordered_list, RuleListNode* node, unsigned evalIndex)
{
- RuleListNode* prev;
-
- prev = ordered_list;
+ RuleListNode* prev = ordered_list;
/* set the eval order for this rule set */
node->evalIndex = evalIndex;
ListHead* CreateRuleType(SnortConfig* sc, const char* name, Actions::Type mode)
{
RuleListNode* node;
- int evalIndex = 0;
+ unsigned evalIndex = 0;
if (sc == nullptr)
return nullptr;
{
assert(sc and sc->rtn_hash_table);
RuleTreeNodeKey key { rtn, policyId };
- xhash_remove(sc->rtn_hash_table, &key);
+ sc->rtn_hash_table->release_node(&key);
}
}
return rtn;
return c;
}
-static int rtn_compare_func(const void* k1, const void* k2, size_t)
+static bool rtn_compare_func(const void* k1, const void* k2, size_t)
{
const RuleTreeNodeKey* rtnk1 = (const RuleTreeNodeKey*)k1;
const RuleTreeNodeKey* rtnk2 = (const RuleTreeNodeKey*)k2;
if (!rtnk1 || !rtnk2)
- return 1;
+ return false;
if (rtnk1->policyId != rtnk2->policyId)
- return 1;
+ return false;
if (same_headers(rtnk1->rtn, rtnk2->rtn))
- return 0;
+ return true;
- return 1;
+ return false;
}
int addRtnToOtn(SnortConfig* sc, OptTreeNode* otn, RuleTreeNode* rtn, PolicyId policyId)
if (!sc->rtn_hash_table)
{
- sc->rtn_hash_table = xhash_new(
- 10000, sizeof(RuleTreeNodeKey), 0, 0, 0, nullptr, nullptr, 1);
-
- if (sc->rtn_hash_table == nullptr)
- FatalError("Failed to create rule tree node hash table\n");
-
- xhash_set_keyops(sc->rtn_hash_table, rtn_hash_func, rtn_compare_func);
+ sc->rtn_hash_table = new XHash(
+ 10000, sizeof(RuleTreeNodeKey), 0, 0, false, nullptr, nullptr, true);
+ sc->rtn_hash_table->set_key_opcodes(rtn_hash_func, rtn_compare_func);
}
RuleTreeNodeKey key;
memset(&key, 0, sizeof(key));
key.rtn = rtn;
key.policyId = policyId;
- xhash_add(sc->rtn_hash_table, &key, rtn);
+ sc->rtn_hash_table->insert(&key, rtn);
return 0;
}
}
po = PortObjectNew();
- if ( !po )
- {
- ParseAbort("PortVarTable missing an 'any' variable.");
- }
PortObjectSetName(po, name);
PortObjectAddPortAny(po);
}
switch (var_type)
{
case VAR_TYPE__DEFAULT:
- if (PortVarTableFind(portVarTable, name)
- || sfvt_lookup_var(ip_vartable, name)
- )
+ if ( PortVarTableFind(portVarTable, name)
+ || sfvt_lookup_var(ip_vartable, name) )
{
ParseError("can not redefine variable name %s to be of type "
"'var'. Use a different name.", name);
break;
case VAR_TYPE__PORTVAR:
- if (var_table != nullptr)
+ if ( var_table )
{
do
{
- if (strcasecmp(p->name, name) == 0)
+ if ( strcasecmp(p->name, name) == 0 )
{
ParseError("can not redefine variable name %s to be of "
"type 'portvar'. Use a different name.", name);
while (p != var_table);
}
- if (sfvt_lookup_var(ip_vartable, name))
+ if ( sfvt_lookup_var(ip_vartable, name) )
{
ParseError("can not redefine variable name %s to be of type "
"'portvar'. Use a different name.", name);
break;
case VAR_TYPE__IPVAR:
- if (var_table != nullptr)
+ if ( var_table )
{
do
{
- if (strcasecmp(p->name, name) == 0)
+ if ( strcasecmp(p->name, name) == 0 )
{
ParseError("can not redefine variable name %s to be of "
"type 'ipvar'. Use a different name.", name);
while (p != var_table);
}
- if (PortVarTableFind(portVarTable, name))
+ if ( PortVarTableFind(portVarTable, name) )
{
ParseError("can not redefine variable name %s to be of type "
"'ipvar'. Use a different name.", name);
}
+ break;
default:
/* Invalid function usage */
*/
PortObjectItem* PortObjectItemDup(PortObjectItem* poi)
{
- PortObjectItem* poinew;
-
- if ( !poi )
- return nullptr;
-
- poinew = PortObjectItemNew();
- if ( !poinew )
- return nullptr;
-
- memcpy(poinew,poi,sizeof(PortObjectItem));
-
+ PortObjectItem* poinew = PortObjectItemNew();
+ memcpy(poinew,poi, sizeof(PortObjectItem));
return poinew;
}
*errflag = 0;
/* Make sure this is not a duplicate */
- for (p=(PortObjectItem*)sflist_first(po->item_list,&pos);
+ for (p = (PortObjectItem*)sflist_first(po->item_list,&pos);
p != nullptr;
- p=(PortObjectItem*)sflist_next(&pos) )
+ p = (PortObjectItem*)sflist_next(&pos))
{
if ((p->lport == poi->lport) && (p->hport == poi->hport))
ParseWarning(WARN_RULES, "duplicate ports in list");
int PortObjectAddRange(PortObject* po, int lport, int hport)
{
PortObjectItem* poi = PortObjectItemNew();
-
- if ( !poi )
- return -1;
-
poi->lport = (unsigned short)lport;
poi->hport = (unsigned short)hport;
SF_LNODE* lpos = nullptr;
PortObject* ponew = PortObjectNew();
- if ( !ponew )
- return nullptr;
-
/* Dup the Name */
if ( po->name )
ponew->name = snort_strdup(po->name);
/* Dup the Item List */
if ( po->item_list )
{
- for (PortObjectItem* poi =(PortObjectItem*)sflist_first(po->item_list,&lpos);
+ for (PortObjectItem* poi = (PortObjectItem*)sflist_first(po->item_list, &lpos);
poi != nullptr;
- poi =(PortObjectItem*)sflist_next(&lpos) )
+ poi = (PortObjectItem*)sflist_next(&lpos) )
{
PortObjectItem* poinew = PortObjectItemDup(poi);
-
- if (!poinew)
- {
- PortObjectFree(ponew);
- return nullptr;
- }
-
PortObjectAddItem(ponew, poinew, nullptr);
}
}
/* Dup the input rule list */
if ( po->rule_list )
{
- for (int* prid = (int*)sflist_first(po->rule_list,&lpos);
+ for (int* prid = (int*)sflist_first(po->rule_list, &lpos);
prid != nullptr;
prid = (int*)sflist_next(&lpos) )
{
int* prule = (int*)snort_calloc(sizeof(int));
*prule = *prid;
- sflist_add_tail(ponew->rule_list,prule);
+ sflist_add_tail(ponew->rule_list, prule);
}
}
SF_LNODE* lpos = nullptr;
PortObject* ponew = PortObjectNew();
- if ( !ponew )
- return nullptr;
-
/* Dup the Name */
if ( po->name )
ponew->name = snort_strdup(po->name);
/* Dup the Item List */
if ( po->item_list )
{
- for (PortObjectItem* poi =(PortObjectItem*)sflist_first(po->item_list,&lpos);
+ for (PortObjectItem* poi = (PortObjectItem*)sflist_first(po->item_list, &lpos);
poi != nullptr;
- poi =(PortObjectItem*)sflist_next(&lpos) )
+ poi = (PortObjectItem*)sflist_next(&lpos))
{
PortObjectItem* poinew = PortObjectItemDup(poi);
-
- if (!poinew)
- {
- PortObjectFree(ponew);
- return nullptr;
- }
PortObjectAddItem(ponew, poinew, nullptr);
}
}
{
SF_LNODE* cursor;
- for ( PortObjectItem* poib = (PortObjectItem*)sflist_first(pob->item_list, &cursor);
- poib!= nullptr;
- poib = (PortObjectItem*)sflist_next(&cursor) )
+ for (PortObjectItem* poib = (PortObjectItem*)sflist_first(pob->item_list, &cursor);
+ poib!= nullptr;
+ poib = (PortObjectItem*)sflist_next(&cursor) )
{
PortObjectItem* poia = PortObjectItemNew();
SnortSnprintfAppend(print_buf, bufsize, " PortObject ");
if ( po->name )
- {
SnortSnprintfAppend(print_buf, bufsize, "%s ", po->name);
- }
SnortSnprintfAppend(print_buf, bufsize,
" Id:%d Ports:%u Rules:%u\n {\n",
- po->id, po->item_list->count,po->rule_list->count);
+ po->id, po->item_list->count, po->rule_list->count);
SnortSnprintfAppend(print_buf, bufsize, " Ports [\n ");
}
else
{
- for (poi=(PortObjectItem*)sflist_first(po->item_list,&pos);
+ for (poi = (PortObjectItem*)sflist_first(po->item_list,&pos);
poi != nullptr;
- poi=(PortObjectItem*)sflist_next(&pos) )
+ poi = (PortObjectItem*)sflist_next(&pos) )
{
PortObjectItemPrint(poi, print_buf, bufsize);
}
}
SnortSnprintfAppend(print_buf, bufsize, " Rules [ \n ");
- for (i=0; i<po->rule_list->count; i++)
+ for (i = 0; i < po->rule_list->count; i++)
{
if ( print_index_map )
- {
print_index_map(rlist[i], print_buf, bufsize);
- }
else
- {
SnortSnprintfAppend(print_buf, bufsize, " %d",rlist[i]);
- }
+
k++;
if ( k == 25 )
{
static int* RuleHashToSortedArray(GHash* rh)
{
- if ( !rh or !rh->count )
+ if ( !rh or !rh->get_count() )
return nullptr;
- int* ra = (int*)snort_calloc(rh->count, sizeof(int));
+ int* ra = (int*)snort_calloc(rh->get_count(), sizeof(int));
int k = 0;
- for ( GHashNode* node = ghash_findfirst(rh);
- node != nullptr && k < (int)rh->count;
- node = ghash_findnext(rh) )
+ for (GHashNode* node = rh->find_first();
+ node != nullptr && k < (int)rh->get_count();
+ node = rh->find_next() )
{
if ( int* prid = (int*)node->data )
ra[k++] = *prid;
}
- qsort(ra,rh->count,sizeof(int),integer_compare);
+ qsort(ra, rh->get_count(), sizeof(int), integer_compare);
return ra;
}
+static bool port_object_key_compare_func(const void* k1, const void* k2, size_t len)
+{
+ if ( memcmp(k1, k2, len ) )
+ return false;
+ else
+ return true;
+}
+
//-------------------------------------------------------------------------
// PortObject2 - public
//-------------------------------------------------------------------------
PortObject2* PortObject2New(int nrules)
{
PortObject2* po = (PortObject2*)snort_calloc(sizeof(PortObject2));
- po->item_list =(SF_LIST*)sflist_new();
-
- if ( !po->item_list )
- {
- snort_free(po);
- return nullptr;
- }
-
- po->rule_hash =(GHash*)ghash_new(nrules,sizeof(int), 0,
- snort_free /* frees data - should be rule id ptrs == (int*) */);
- if ( !po->rule_hash )
- {
- sflist_free_all(po->item_list, snort_free);
- snort_free(po);
- return nullptr;
- }
+ po->item_list = sflist_new();
+ po->rule_hash = new GHash(nrules, sizeof(int), 0, snort_free);
/* Use hash function defined above for hashing the key as an int. */
- ghash_set_keyops(po->rule_hash, po_rule_hash_func, memcmp);
+ po->rule_hash->set_key_opcodes(po_rule_hash_func, port_object_key_compare_func);
return po;
}
sflist_free_all(po->item_list, snort_free);
if ( po->rule_hash)
- ghash_delete(po->rule_hash);
+ delete po->rule_hash;
if (po->port_list)
delete po->port_list;
sflist_free_all(po->item_list, snort_free);
po->item_list = nullptr;
- ghash_delete(po->rule_hash);
+ delete po->rule_hash;
po->rule_hash = nullptr;
}
/*
* Dup the PortObjects Item List, Name, and RuleList->RuleHash
*/
-PortObject2* PortObject2Dup(PortObject* po)
+PortObject2* PortObject2Dup(PortObject& po)
{
- PortObject2* ponew = nullptr;
- PortObjectItem* poi = nullptr;
- PortObjectItem* poinew = nullptr;
- SF_LNODE* lpos = nullptr;
- int* prid = nullptr;
- int* prule = nullptr;
+ assert( po.rule_list );
- if ( !po )
- return nullptr;
+ PortObject2* ponew = PortObject2New(po.rule_list->count + PO_EXTRA_RULE_CNT);
- if ( !po->rule_list )
- return nullptr;
-
- ponew = PortObject2New(po->rule_list->count + PO_EXTRA_RULE_CNT);
- if ( !ponew )
- return nullptr;
-
- /* Dup the Name */
- if ( po->name )
- ponew->name = snort_strdup(po->name);
+ if ( po.name )
+ ponew->name = snort_strdup(po.name);
else
ponew->name = snort_strdup("dup");
/* Dup the Item List */
- if ( po->item_list )
+ if ( po.item_list )
{
- for (poi =(PortObjectItem*)sflist_first(po->item_list,&lpos);
- poi != nullptr;
- poi =(PortObjectItem*)sflist_next(&lpos) )
- {
- poinew = PortObjectItemDup(poi);
-
- if (!poinew)
- {
- PortObject2Free(ponew);
- return nullptr;
- }
+ PortObjectItem* poi = nullptr;
+ SF_LNODE* lpos = nullptr;
+ for (poi = (PortObjectItem*)sflist_first(po.item_list, &lpos);
+ poi != nullptr;
+ poi = (PortObjectItem*)sflist_next(&lpos) )
+ {
+ PortObjectItem* poinew = PortObjectItemDup(poi);
PortObjectAddItem( (PortObject*)ponew, poinew, nullptr);
}
}
/* Dup the input rule list */
- if ( po->rule_list )
+ if ( po.rule_list )
{
- for (prid = (int*)sflist_first(po->rule_list,&lpos);
- prid != nullptr;
- prid = (int*)sflist_next(&lpos) )
+ SF_LNODE* lpos = nullptr;
+
+ for (int* prid = (int*)sflist_first(po.rule_list, &lpos);
+ prid != nullptr;
+ prid = (int*)sflist_next(&lpos) )
{
- prule = (int*)snort_calloc(sizeof(int));
+ int* prule = (int*)snort_calloc(sizeof(int));
*prule = *prid;
- if ( ghash_add(ponew->rule_hash, prule, prule) != GHASH_OK )
- {
+ if ( ponew->rule_hash->insert(prule, prule) != GHASH_OK )
snort_free(prule);
- }
}
}
{
SF_LNODE* lpos;
- for ( int* prid = (int*)sflist_first(pob->rule_list,&lpos);
- prid!= nullptr;
- prid = (int*)sflist_next(&lpos) )
+ for (int* prid = (int*)sflist_first(pob->rule_list, &lpos);
+ prid!= nullptr;
+ prid = (int*)sflist_next(&lpos) )
{
int* prid2 = (int*)snort_calloc(sizeof(int));
*prid2 = *prid;
- if ( ghash_add(poa->rule_hash,prid2,prid2) != GHASH_OK )
+ if ( poa->rule_hash->insert(prid2, prid2) != GHASH_OK )
snort_free(prid2);
}
return poa;
/* Dup and append rule list numbers from pob to poa */
PortObject2* PortObject2AppendPortObject2(PortObject2* poa, PortObject2* pob)
{
- for (GHashNode* node = ghash_findfirst(pob->rule_hash);
- node!= nullptr;
- node = ghash_findnext(pob->rule_hash) )
+ for (GHashNode* node = pob->rule_hash->find_first();
+ node!= nullptr;
+ node = pob->rule_hash->find_next() )
{
int* prid = (int*)node->data;
int* prid2 = (int*)snort_calloc(sizeof(int));
*prid2 = *prid;
- if ( ghash_add(poa->rule_hash,prid2,prid2) != GHASH_OK )
+ if ( poa->rule_hash->insert(prid2, prid2) != GHASH_OK )
snort_free(prid2);
}
return poa;
void PortObject2PrintPorts(PortObject2* po)
{
- PortObjectItem* poi = nullptr;
SF_LNODE* pos = nullptr;
int bufsize = sizeof(po_print_buf);
po_print_buf[0] = '\0';
-
SnortSnprintfAppend(po_print_buf, bufsize, " PortObject ");
if ( po->name )
- {
SnortSnprintfAppend(po_print_buf, bufsize, "%s ", po->name);
- }
SnortSnprintfAppend(po_print_buf, bufsize,
" Id:%d Ports:%u Rules:%u\n {\n Ports [",
- po->id, po->item_list->count, po->rule_hash->count);
+ po->id, po->item_list->count, po->rule_hash->get_count());
if ( PortObjectHasAny( (PortObject*)po) )
{
}
else
{
- for (poi=(PortObjectItem*)sflist_first(po->item_list,&pos);
- poi != nullptr;
- poi=(PortObjectItem*)sflist_next(&pos) )
+ for (PortObjectItem* poi = (PortObjectItem*)sflist_first(po->item_list, &pos);
+ poi != nullptr;
+ poi = (PortObjectItem*)sflist_next(&pos) )
{
PortObjectItemPrint(poi, po_print_buf, bufsize);
}
SnortSnprintfAppend(po_print_buf, bufsize, "%s ",po->name);
SnortSnprintfAppend(po_print_buf, bufsize, " Id:%d Ports:%u Rules:%u PortUsageCnt=%d\n {\n",
- po->id, po->item_list->count, po->rule_hash->count, po->port_cnt);
+ po->id, po->item_list->count, po->rule_hash->get_count(), po->port_cnt);
SnortSnprintfAppend(po_print_buf, bufsize, " Ports [\n ");
return;
SnortSnprintfAppend(po_print_buf, bufsize, " Rules [ \n ");
- for (i=0; i<po->rule_hash->count; i++)
+ for (i = 0; i < po->rule_hash->get_count(); i++)
{
if ( print_index_map )
{
PortObject2* PortObject2New(int nrules /*guess at this */);
void PortObject2Free(PortObject2*);
void PortObject2Finalize(PortObject2*);
-PortObject2* PortObject2Dup(PortObject*);
+PortObject2* PortObject2Dup(PortObject&);
typedef void (*PortObjectIterator)(int port, void*);
void PortObject2Iterate(PortObject2*, PortObjectIterator, void*);
static plx_t* plx_new(void* pv_array[], int n)
{
- if (!pv_array || n < 0)
- return nullptr;
+ assert( pv_array && n > 0);
plx_t* p = (plx_t*)snort_calloc(sizeof(plx_t));
p->p = (void**)snort_calloc(n, sizeof(void*));
-1, and +1 are not strictly needed, they could both return
a non zero value for the purposes of hashing and searching.
*/
-static int plx_keycmp(const void* a, const void* b, size_t)
+static bool plx_keycmp(const void* a, const void* b, size_t)
{
const plx_t* pla = *(plx_t* const*)a;
const plx_t* plb = *(plx_t* const*)b;
if ( pla->n < plb->n )
- return -1;
+ return false;
if ( pla->n > plb->n )
- return 1;
+ return false;
for ( int i = 0; i < pla->n; i++ )
{
- if ( int cmp = p_keycmp(&pla->p[i], &plb->p[i]) )
- return cmp;
+ if ( p_keycmp(&pla->p[i], &plb->p[i]) )
+ return false;
}
- return 0; /* they are equal */
+ return true; /* they are equal */
}
//-------------------------------------------------------------------------
return values memcmp style
*/
-static int PortObject_keycmp(const void* a, const void* b, size_t)
+static bool PortObject_keycmp(const void* a, const void* b, size_t)
{
- return !PortObjectEqual(*(PortObject* const*)a, *(PortObject* const*)b);
+ return PortObjectEqual(*(PortObject* const*)a, *(PortObject* const*)b);
}
/*
SF_LNODE* pos;
/* hash up each item */
- for ( PortObjectItem* poi = (PortObjectItem*)sflist_first(po->item_list, &pos);
- poi != nullptr;
- poi = (PortObjectItem*)sflist_next(&pos) )
+ for (PortObjectItem* poi = (PortObjectItem*)sflist_first(po->item_list, &pos);
+ poi != nullptr;
+ poi = (PortObjectItem*)sflist_next(&pos) )
{
if ( poi->any() )
continue;
* lookup.
*/
static PortObject2* _merge_N_pol(
- GHash* mhash, GHash* mhashx,
- SF_LIST* plx_list, void** pol,
- int pol_cnt, plx_t* plx)
+ GHash* mhash, GHash* mhashx, SF_LIST* plx_list,
+ void** pol, int pol_cnt, plx_t* plx)
{
- PortObject2* ponew;
- PortObject2* pox;
- plx_t* plx_tmp;
- int stat;
-
- /*
- * Check for the merged port object in the plx table
- */
- ponew = (PortObject2*)ghash_find(mhashx, &plx);
-
+ // Check for the merged port object in the plx table
+ PortObject2* ponew = (PortObject2*)mhashx->find(&plx);
if ( ponew )
- {
return ponew;
- }
-
- /*
- * Merge the port objects together - ports and rules
- */
- /* Dup the 1st port objects rules and ports */
- ponew = PortObject2Dup( (PortObject*)pol[0]);
- if ( !ponew )
- {
- FatalError("Could not Dup2\n");
- }
+ // Merge the port objects together - ports and rules
+ // Dup the 1st port objects rules and ports
+ ponew = PortObject2Dup(*((PortObject*)pol[0]));
- /* Merge in all the other port object rules and ports */
+ // Merge in all the other port object rules and ports
if ( pol_cnt > 1 )
{
for ( int i = 1; i < pol_cnt; i++ )
- {
PortObjectAppendEx2(ponew, (PortObject*)pol[i]);
- }
- PortObjectNormalize( (PortObject*)ponew);
- }
-
- // PortObjectPrint2(ponew);
-
- /*
- * Add the Merged PortObject2 to the PortObject2 hash table
- * keyed by ports.
- */
- stat =ghash_add(mhash, &ponew, ponew);
- if ( stat != GHASH_OK )
- {
- /* This is possible since PLX hash on a different key */
- if ( stat == GHASH_INTABLE )
- {
- pox = (PortObject2*)ghash_find(mhash, &ponew);
- if ( pox )
- {
- PortObject2AppendPortObject2(pox, ponew);
- PortObject2Free(ponew);
- ponew = pox;
- }
- else
- {
- FatalError("mhash add/find error n=%d\n", pol_cnt);
- }
- }
- else
- {
- FatalError("Could not add ponew to hash table- error\n");
- }
- }
-
- /*
- * Create a plx node and add it to plx table
- * as the key with the merged port object as the data
- */
- plx_tmp = plx_new(pol, pol_cnt);
- if (!plx_tmp)
- {
- FatalError("plx_new: memory alloc error\n");
+ PortObjectNormalize((PortObject*)ponew);
}
- sflist_add_head(plx_list, (void*)plx_tmp);
- /*
- * Add the plx node to the PLX hash table
- */
- stat = ghash_add(mhashx, &plx_tmp, ponew);
- if ( stat != GHASH_OK )
+ // Add the Merged PortObject2 to the PortObject2 hash table keyed by ports.
+ int stat = mhash->insert(&ponew, ponew);
+ // This is possible since PLX hash on a different key
+ if ( stat == GHASH_INTABLE )
{
- if ( stat == GHASH_INTABLE )
- {
- FatalError("Could not add merged plx to PLX HASH table-INTABLE\n");
- }
- else
- {
- FatalError("Could not add merged plx to PLX HASH table\n");
- }
+ PortObject2* pox = (PortObject2*)mhash->find(&ponew);
+ assert( pox );
+ PortObject2AppendPortObject2(pox, ponew);
+ PortObject2Free(ponew);
+ ponew = pox;
}
+ // Create a plx node and add it to plx table as the key with the
+ // merged port object as the data
+ plx_t* plx_tmp = plx_new(pol, pol_cnt);
+ sflist_add_head(plx_list, (void*)plx_tmp);
- /*
- * Validate hash table entry
- */
- if ( ghash_find(mhashx, &plx_tmp) != ponew )
- {
- FatalError("Find after add failed on PLX HASH table key\n");
- }
+ // Add the plx node to the PLX hash table
+ stat = mhashx->insert(&plx_tmp, ponew);
+ if ( stat == GHASH_INTABLE )
+ FatalError("Could not add merged plx to PLX HASH table-INTABLE\n");
return ponew;
}
* Merge Large PortObjects
*/
if ( nlarge )
- {
- ponew = _merge_N_pol(mhash, mhashx, plx_list, polarge, nlarge, &plx_large);
- }
+ ponew = _merge_N_pol(mhash, mhashx, plx_list, polarge, nlarge, &plx_large);
/*
* Merge Small PortObjects
*/
if ( nsmall )
- {
posnew = _merge_N_pol(mhash, mhashx, plx_list, posmall, nsmall, &plx_small);
- }
/*
* Merge Large and Small (rule groups) PortObject2's together
* append small port object rule sets to the large port objects,
}
-static int PortTableCompileMergePortObjects(PortTable* p)
+static void PortTableCompileMergePortObjects(PortTable* p)
{
std::unique_ptr<PortObject*[]> upA(new PortObject*[SFPO_MAX_LPORTS]);
PortObject** pol = upA.get();
// Create a Merged Port Object Table - hash by ports, no user keys, don't free data
- GHash* mhash = ghash_new(PO_HASH_TBL_ROWS, sizeof(PortObject*), 0, nullptr);
-
- /* Setup hashing function and key comparison function */
- hashfcn_set_keyops(mhash->hashfcn, PortObject_hash, PortObject_keycmp);
+ GHash* mhash = new GHash(PO_HASH_TBL_ROWS, sizeof(PortObject*), 0, nullptr);
+ mhash->set_key_opcodes(PortObject_hash, PortObject_keycmp);
p->pt_mpo_hash = mhash;
// Create a Merged Port Object Table - hash by pointers, no user keys, don't free data
- GHash* mhashx = ghash_new(PO_HASH_TBL_ROWS, sizeof(plx_t*), 0, nullptr);
-
- /* Setup hashing function and key comparison function */
- hashfcn_set_keyops(mhashx->hashfcn, plx_hash, plx_keycmp);
+ GHash* mhashx = new GHash(PO_HASH_TBL_ROWS, sizeof(plx_t*), 0, nullptr);
+ mhashx->set_key_opcodes(plx_hash, plx_keycmp);
p->pt_mpxo_hash = mhashx;
-
SF_LIST* plx_list = sflist_new();
-
SF_LIST** optimized_pl = create_port_lists(p);
- /*
- * For each port, merge rules from all port objects that touch the port
- * into an optimal object, that may be shared with other ports.
- */
+ // For each port, merge rules from all port objects that touch the port
+ // into an optimal object, that may be shared with other ports.
int id = PO_INIT_ID;
for ( int i = 0; i < SFPO_MAX_PORTS; i++ )
SF_LNODE* lpos;
for (po = (PortObject*)sflist_first(optimized_pl[i], &lpos);
- po;
- po = (PortObject*)sflist_next(&lpos) )
+ po;
+ po = (PortObject*)sflist_next(&lpos) )
{
if (pol_cnt < SFPO_MAX_LPORTS )
- {
pol[ pol_cnt++ ] = po;
- }
}
p->pt_port_object[i] = nullptr;
if ( !pol_cnt )
- {
- //port not contained in any PortObject
- continue;
- }
+ continue; //port not contained in any PortObject
/* merge the rules into an optimal port object */
p->pt_port_object[i] =
PortTableCompileMergePortObjectList2(
mhash, mhashx, plx_list, pol, pol_cnt, p->pt_lrc);
-
- if ( !p->pt_port_object[i] )
- {
- FatalError(" Could not merge PorObjectList on port %d\n", i);
- }
-
- /* give the new compiled port object an id of its own */
- p->pt_port_object[i]->id = id++;
-
+ assert( p->pt_port_object[i] );
+ p->pt_port_object[i]->id = id++; // set the port object id
}
delete_port_lists(optimized_pl);
*/
/* 1st- Setup bitmasks for collecting ports */
- for (GHashNode* node=ghash_findfirst(mhashx);
- node;
- node=ghash_findnext(mhashx) )
+ for (GHashNode* node = mhashx->find_first();
+ node;
+ node = mhashx->find_next())
{
PortObject2* poa = (PortObject2*)node->data;
if ( !poa )
continue;
- if (!poa->port_list)
- {
+ if ( !poa->port_list )
poa->port_list = new PortBitSet;
-
- if ( !poa->port_list)
- FatalError("Memory error in PortTableCompile\n");
- }
}
/* Count how many ports each final port-object is used on */
for ( int i = 0; i < SFPO_MAX_PORTS; i++ )
{
- PortObject2* poa;
- poa = p->pt_port_object[i];
- if (poa)
+ PortObject2* poa = p->pt_port_object[i];
+ if ( poa )
{
poa->port_cnt++;
if ( poa->port_list )
poa->port_list->set(i);
-
else
FatalError("NULL po->port_list in po on port %d\n", i);
}
}
/* Process Port map and print final port-object usage stats */
- for (GHashNode* node=ghash_findfirst(mhashx);
- node;
- node=ghash_findnext(mhashx) )
+ for (GHashNode* node = mhashx->find_first();
+ node;
+ node = mhashx->find_next())
{
PortObject2* po = (PortObject2*)node->data;
-
- if ( !po )
- FatalError("MergePortOBject-NormalizePorts -NULL po\n");
-
- if ( !po->port_cnt ) /* port object is not used ignore it */
- continue;
-
- if ( !po->port_list )
- {
- //FatalError("MergePortOBject-NormalizePorts -NULL po->port_list\n");
+ assert( po );
+ if ( !po->port_cnt || !po->port_list ) /* port object is not used ignore it */
continue;
- }
PortBitSet parray;
-
/* Convert the port_list bits to a char array */
for ( int i = 0; i < SFPO_MAX_PORTS; i++ )
parray[ i ] = po->port_list->test(i);
/* Build a PortObjectItem list from the char array */
SF_LIST* plist = PortObjectItemListFromBits(parray, SFPO_MAX_PORTS);
-
- if ( !plist )
- {
- FatalError("MergePortObjects: No PortObjectItems in portobject\n");
- }
-
- /* free the original list */
- sflist_free_all(po->item_list, snort_free);
-
- /* set the new list - this is a list of port items for this port object */
- po->item_list = plist;
-
+ sflist_free_all(po->item_list, snort_free); // free the original list
+ po->item_list = plist; // set the new port object list of port items
}
sflist_free_all(plx_list, plx_free);
- return 0;
}
#ifdef DEBUG
pid = (int*)sflist_next(&rpos) )
{
/* find it in po2 */
- int* id = (int*)ghash_find(po2->rule_hash, pid);
+ int* id = (int*)po2->rule_hash->find(pid);
/* make sure it's in po2 */
if ( !id )
char* parray = upA.get();
memset(parray, 0, SFPO_MAX_PORTS);
- for ( GHashNode* node=ghash_findfirst(p->pt_mpo_hash);
- node;
- node=ghash_findnext(p->pt_mpo_hash) )
+ for (GHashNode* node = p->pt_mpo_hash->find_first();
+ node;
+ node = p->pt_mpo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
if ( PortObjectHasPort( (PortObject*)po, i) )
{
if ( parray[i] )
- {
return false;
- }
+
parray[i] = 1;
}
}
{
PortTable* p = (PortTable*)snort_calloc(sizeof(PortTable));
p->pt_polist = sflist_new();
-
- if (!p->pt_polist )
- {
- snort_free(p);
- return nullptr;
- }
-
p->pt_lrc = PTBL_LRC_DEFAULT; /* 10 rules, user should really control these */
p->pt_optimize = 1; /* if disabled, only one merged rule group is used */
{
sflist_free_all(p->pt_polist, PortObjectFree);
}
+
if (p->pt_mpo_hash)
{
- for ( GHashNode* node = ghash_findfirst(p->pt_mpo_hash);
- node;
- node = ghash_findnext(p->pt_mpo_hash) )
+ for (GHashNode* node = p->pt_mpo_hash->find_first();
+ node;
+ node = p->pt_mpo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
PortObject2Free(po);
}
- ghash_delete(p->pt_mpo_hash);
+ delete p->pt_mpo_hash;
}
+
if (p->pt_mpxo_hash)
- {
- ghash_delete(p->pt_mpxo_hash);
- }
+ delete p->pt_mpxo_hash;
snort_free(p);
}
// FIXIT-P we should be able to free pt_mpo_hash early too
void PortTableFinalize(PortTable* p)
{
- ghash_delete(p->pt_mpxo_hash);
+ delete p->pt_mpxo_hash;
p->pt_mpxo_hash = nullptr;
}
po = (PortObject*)sflist_next(&lpos) )
{
if ( PortObjectEqual(po, pox) )
- {
return po;
- }
}
return nullptr;
}
*/
int PortTableCompile(PortTable* p)
{
- /*
- * If not using an optimized Table use the rule_index_map in parser.c
- */
+ // If not using an optimized Table use the rule_index_map in parser.c
if ( !p->pt_optimize )
return 0;
- if ( PortTableCompileMergePortObjects(p) )
- {
- FatalError("Could not create PortArryayLists\n");
- }
-
+ PortTableCompileMergePortObjects(p);
#ifdef DEBUG
assert(PortTableConsistencyCheck(p));
int PortTablePrintCompiledEx(PortTable* p, rim_print_f print_index_map)
{
LogMessage(" *** PortTableCompiled [ %d compiled port groups ] \n\n",
- p->pt_mpo_hash->count);
+ p->pt_mpo_hash->get_count());
- for ( GHashNode* node = ghash_findfirst(p->pt_mpo_hash);
- node!= nullptr;
- node = ghash_findnext(p->pt_mpo_hash) )
+ for (GHashNode* node = p->pt_mpo_hash->find_first();
+ node != nullptr;
+ node = p->pt_mpo_hash->find_next())
{
PortObject2* po = (PortObject2*)node->data;
PortObject2PrintEx(po, print_index_map);
{
/* normalized user PortObjects and rule ids */
LogMessage(">>>PortTable - Compiled Port Groups\n");
- LogMessage(" [ %d port groups ] \n\n", p->pt_mpo_hash->count);
+ LogMessage(" [ %d port groups ] \n\n", p->pt_mpo_hash->get_count());
- for ( GHashNode* ponode = ghash_findfirst(p->pt_mpo_hash);
- ponode!= nullptr;
- ponode = ghash_findnext(p->pt_mpo_hash) )
+ for (GHashNode* ponode = p->pt_mpo_hash->find_first();
+ ponode != nullptr;
+ ponode = p->pt_mpo_hash->find_next())
{
PortObject2* po = (PortObject2*)ponode->data;
PortObject2Print(po);
SF_LIST* plist = sflist_new();
int nports = parray.count();
- if ( !plist )
- return nullptr;
-
for (int i = 0; i < n && nports > 0; i++)
{
if ( parray[i] == 0 )
lport = hport = i;
nports--;
- for (i++; i<n; i++)
+ for (i++; i < n; i++)
{
if ( parray[i] )
{
}
PortObjectItem* poi = PortObjectItemNew();
-
- if ( !poi )
- {
- sflist_free_all(plist, snort_free);
- return nullptr;
- }
-
- poi->lport =(unsigned short)lport;
- poi->hport =(unsigned short)hport;
+ poi->lport = (unsigned short)lport;
+ poi->hport = (unsigned short)hport;
sflist_add_tail(plist, poi);
}
*/
PortVarTable* PortVarTableCreate()
{
- PortObject* po;
- GHash* h;
-
/*
* This is used during parsing of config,
* so 1000 entries is ok, worst that happens is somewhat slower
* config/rule processing.
*/
- h = ghash_new(1000,0,0,PortObjectFree);
- if ( !h )
- return nullptr;
-
- /* Create default port objects */
- po = PortObjectNew();
- if ( !po )
- return nullptr;
-
- /* Default has an ANY port */
- PortObjectAddPortAny(po);
-
- /* Add ANY to the table */
- PortVarTableAdd(h, po);
+ GHash* h = new GHash(1000, 0, 0, PortObjectFree);
+ PortObject* po = PortObjectNew(); // Create default port objects
+ PortObjectAddPortAny(po); // Default has an ANY port
+ PortVarTableAdd(h, po); // Add ANY to the table
return h;
}
int PortVarTableFree(PortVarTable* pvt)
{
if ( pvt )
- {
- ghash_delete(pvt);
- }
+ delete pvt;
+
return 0;
}
*/
int PortVarTableAdd(PortVarTable* h, PortObject* po)
{
- int stat;
- stat = ghash_add(h,po->name,po);
+ int stat = h->insert(po->name, po);
if ( stat == GHASH_INTABLE )
return 1;
+
if ( stat == GHASH_OK )
return 0;
+
return -1;
}
if (!h || !name)
return nullptr;
- return (PortObject*)ghash_find(h,name);
+ return (PortObject*)h->find(name);
}
any = PortObjectNew();
nfp = PortObjectNew();
- if ( !src or !dst or !any or !nfp )
- ParseAbort("can't allocate port structs");
-
// someday these could be read from snort.conf, something like...
// 'config portlist: large-rule-count <val>'
src->pt_lrc = DEFAULT_LARGE_RULE_GROUP;
PortProto::~PortProto()
{
- if (src)
- PortTableFree(src);
-
- if (dst)
- PortTableFree(dst);
-
- if (any)
- PortObjectFree(any);
-
- if (nfp)
- PortObjectFree(nfp);
+ PortTableFree(src);
+ PortTableFree(dst);
+ PortObjectFree(any);
+ PortObjectFree(nfp);
}
RulePortTables* PortTablesNew()
{
RulePortTables* rpt = new RulePortTables;
- if ( !(rpt->svc_any = PortObjectNew()) )
- ParseAbort("udp any-any PortObjectNew() failed");
-
+ rpt->svc_any = PortObjectNew();
PortObjectAddPortAny(rpt->svc_any);
return rpt;
std::vector<View> entries;
- for ( auto* h = ghash_findfirst(otn_map); h; h = ghash_findnext(otn_map) )
+ for ( auto* h = otn_map->find_first(); h; h = otn_map->find_next() )
{
auto* otn = static_cast<OptTreeNode*>(h->data);
assert(otn);
assert(SnortConfig::get_conf());
auto* otn_map = SnortConfig::get_conf()->otn_map;
- for ( auto* h = ghash_findfirst(otn_map); h; h = ghash_findnext(otn_map) )
+ for ( auto* h = otn_map->find_first(); h; h = otn_map->find_next() )
{
auto* otn = static_cast<OptTreeNode*>(h->data);
assert(otn);
#include "sip_config.h"
+#include <cassert>
+
#include "log/messages.h"
#include "main/snort_debug.h"
#include "utils/util.h"
config->methodsConfig = SIP_METHOD_DEFAULT;
for (i = 0; i < 6; i++)
{
- if (SIP_AddMethodToList(StandardMethods[i].name,
- StandardMethods[i].methodFlag, &config->methods) == nullptr)
- {
- FatalError("Failed to add SIP default method: %s.\n", StandardMethods[i].name);
- }
+ SIP_AddMethodToList(StandardMethods[i].name,
+ StandardMethods[i].methodFlag, &config->methods);
}
}
if (METHOD_NOT_FOUND != i_method )
{
*methodsConfig |= 1 << (StandardMethods[i_method].methodFlag - 1);
- if (SIP_AddMethodToList(cur_tokenp,
- StandardMethods[i_method].methodFlag, pmethods) == nullptr)
- {
- ParseError("Failed to add SIP method: %s.", cur_tokenp);
- }
+ SIP_AddMethodToList(cur_tokenp, StandardMethods[i_method].methodFlag, pmethods);
}
else
{
static SIPMethodNode* SIP_AddMethodToList(
const char* methodName, SIPMethodsFlag methodConf, SIPMethodlist* p_methodList)
{
- if ( !methodName )
- return nullptr;
+ assert (methodName );
int methodLen = strlen(methodName);
SIPMethodNode* method = *p_methodList;
udpStats.released++;
}
-static int ProcessUdp(
- Flow* lwssn, Packet* p, StreamUdpConfig*, XHashNode*)
+static int ProcessUdp(Flow* lwssn, Packet* p, StreamUdpConfig*)
{
assert(lwssn->pkt_type == PktType::UDP);
UdpHAManager::process_deletion(*flow);
}
- ProcessUdp(flow, p, pc, nullptr);
+ ProcessUdp(flow, p, pc);
flow->markup_packet_flags(p);
flow->set_expire(p, flow->default_session_timeout);
*
* Simple list, queue, and dictionary implementations
* ( most of these implementations are list based - not performance monsters,
-* and they all use snort_alloc via s_alloc/s_free )
+* and they all use snort_alloc/snort_free )
*
* 11/05/2005 - man - Added sflist_firstx() and sflist_nextx() with user
* provided SF_NODE inputs for tracking the list position. This allows
#include "util.h"
-// private alloc
-static void* s_alloc(size_t n)
-{
- return snort_calloc(n);
-}
-
-/*
-* private free
-*/
-static void s_free(void* p)
-{
- if ( p )
- snort_free(p);
-}
-
namespace snort
{
SF_LIST* sflist_new()
{
- SF_LIST* s;
- s = (SF_LIST*)s_alloc(sizeof(SF_LIST) );
+ SF_LIST* s = (SF_LIST*)snort_calloc(sizeof(SF_LIST));
sflist_init(s);
return s;
}
void sflist_init(SF_LIST* s)
{
- s->count=0;
+ s->count = 0;
s->head = s->tail = nullptr;
}
void sflist_add_before(SF_LIST* s, SF_LNODE* lnode, NODE_DATA ndata)
{
- SF_LNODE* q;
-
if ( lnode )
{
/* Add to head of list */
sflist_add_head (s, ndata);
else
{
- q = (SF_LNODE*)s_alloc (sizeof (SF_LNODE) );
+ SF_LNODE* q = (SF_LNODE*)snort_calloc(sizeof (SF_LNODE));
q->ndata = (NODE_DATA)ndata;
q->next = lnode;
q->prev = lnode->prev;
lnode->prev->next = q;
- lnode->prev = q;
+ lnode->prev = q;
s->count++;
}
}
SF_LNODE* q;
if (!s->head)
{
- q = s->tail = s->head = (SF_LNODE*)s_alloc (sizeof (SF_LNODE));
+ q = s->tail = s->head = (SF_LNODE*)snort_calloc(sizeof (SF_LNODE));
q->ndata = (NODE_DATA)ndata;
q->next = nullptr;
q->prev = nullptr;
}
else
{
- q = (SF_LNODE*)s_alloc (sizeof (SF_LNODE));
+ q = (SF_LNODE*)snort_calloc(sizeof (SF_LNODE));
q->ndata = ndata;
q->next = s->head;
q->prev = nullptr;
SF_LNODE* q;
if (!s->head)
{
- q = s->tail = s->head = (SF_LNODE*)s_alloc (sizeof (SF_LNODE));
+ q = s->tail = s->head = (SF_LNODE*)snort_calloc(sizeof (SF_LNODE));
q->ndata = (NODE_DATA)ndata;
q->next = nullptr;
q->prev = nullptr;
}
else
{
- q = (SF_LNODE*)s_alloc (sizeof (SF_LNODE));
+ q = (SF_LNODE*)snort_calloc(sizeof (SF_LNODE));
q->ndata = ndata;
q->next = nullptr;
q->prev = s->tail;
else
s->head->prev = nullptr;
- s_free(q);
+ snort_free(q);
}
return (NODE_DATA)ndata;
}
else
s->tail->next = nullptr;
- s_free (q);
+ snort_free(q);
}
return (NODE_DATA)ndata;
}
else
s->head->prev = nullptr;
- s_free(n);
+ snort_free(n);
return;
}
else if ( n == s->tail )
else
s->tail->next = nullptr;
- s_free(n);
+ snort_free(n);
return;
}
n->next->prev = n->prev;
n->prev->next = n->next;
s->count--;
- s_free(n);
+ snort_free(n);
return;
}
}
{
sflist_remove_head(s);
}
- s_free(s);
+ snort_free(s);
}
void sflist_free_all(SF_LIST* s, void (* nfree)(void*) )
if ( p && nfree )
nfree(p);
}
- s_free(s);
+ snort_free(s);
}
void sflist_static_free_all(SF_LIST* s, void (* nfree)(void*) )
void sfqueue_add(SF_QUEUE* s, NODE_DATA ndata)
{
- sflist_add_tail (s, ndata);
+ sflist_add_tail(s, ndata);
}
{
sflist_free_all(s, nfree);
}
-
-