#include "filters/rate_filter.h"
#include "filters/sfrf.h"
#include "filters/sfthreshold.h"
+#include "hash/sfxhash.h"
#include "helpers/process.h"
#include "ips_options/ips_pcre.h"
#include "latency/latency_config.h"
fpDeleteFastPacketDetection(this);
+ if (rtn_hash_table)
+ sfxhash_delete(rtn_hash_table);
+
if (eth_dst )
snort_free(eth_dst);
SFXHASH* detection_option_hash_table = nullptr;
SFXHASH* detection_option_tree_hash_table = nullptr;
+ SFXHASH* rtn_hash_table = nullptr;
PolicyMap* policy_map = nullptr;
struct VarNode* var_list = nullptr;
#include "mstring.h"
+#include <cassert>
+
#include "utils/util.h"
static char* mSplitAddTok(const char*, const int, const char*, const char);
char** retstr;
const char* whitespace = " \t";
- if (num_toks == NULL)
- return NULL;
+ assert(num_toks);
+ assert(str);
*num_toks = 0;
+ size_t str_length = strlen(str);
- if ((str == NULL) || (strlen(str) == 0) ||
- ((sep_chars != NULL) && (strlen(sep_chars) == 0)))
- {
+ if (str_length == 0)
return NULL;
- }
if (sep_chars == NULL)
sep_chars = whitespace;
+ size_t sep_length = strlen(sep_chars);
+
/* Meta char cannot also be a separator char */
- for (i = 0; i < strlen(sep_chars); i++)
+ for (i = 0; i < sep_length; i++)
{
if (sep_chars[i] == meta_char)
return NULL;
}
/* Move past initial separator characters and whitespace */
- for (i = 0; i < strlen(str); i++)
+ for (i = 0; i < str_length; i++)
{
- for (j = 0; j < strlen(sep_chars); j++)
+ if (isspace((int)str[i]))
+ continue;
+
+ for (j = 0; j < sep_length; j++)
{
- if ((str[i] == sep_chars[j]) ||
- isspace((int)str[i]))
- {
+ if (str[i] == sep_chars[j])
break;
- }
}
/* Not a separator character or whitespace */
- if (j == strlen(sep_chars))
+ if (j == sep_length)
break;
}
- if (i == strlen(str))
+ if (i == str_length)
{
/* Nothing but separator characters or whitespace in string */
return NULL;
if ((cur_tok + 1) == (size_t)max_toks)
{
retstr = (char**)snort_calloc(sizeof(char*));
- retstr[cur_tok] = snort_strndup(&str[i], strlen(str) - i);
+ retstr[cur_tok] = snort_strndup(&str[i], str_length - i);
*num_toks = cur_tok + 1;
return retstr;
}
/* Mark the beginning of the next tok */
tok_start = i;
- for (; i < strlen(str); i++)
+ for (; i < str_length; i++)
{
if (!escaped)
{
}
/* See if the current character is a separator */
- for (j = 0; j < strlen(sep_chars); j++)
+ for (j = 0; j < sep_length; j++)
{
if (str[i] == sep_chars[j])
break;
}
/* It's a normal character */
- if (j == strlen(sep_chars))
+ if (j == sep_length)
continue;
/* Current character matched a separator character. Trim off
cur_tok++;
/* Move past any more separator characters or whitespace */
- for (; i < strlen(str); i++)
+ for (; i < str_length; i++)
{
- for (j = 0; j < strlen(sep_chars); j++)
+ if (isspace((int)str[i]))
+ continue;
+
+ for (j = 0; j < sep_length; j++)
{
- if ((str[i] == sep_chars[j]) ||
- isspace((int)str[i]))
- {
+ if (str[i] == sep_chars[j])
break;
- }
}
/* Not a separator character or whitespace */
- if (j == strlen(sep_chars))
+ if (j == sep_length)
break;
}
/* Nothing but separator characters or whitespace left in the string */
- if (i == strlen(str))
+ if (i == str_length)
{
*num_toks = cur_tok;
}
/* Trim whitespace at end of last tok */
- for (j = strlen(str); j > tok_start; j--)
+ for (j = str_length; j > tok_start; j--)
{
if (!isspace((int)str[j - 1]))
break;
char* tok;
int tok_len = 0;
int got_meta = 0;
+ size_t sep_length = strlen(sep_chars);
/* Get the length of the returned tok
* Could have a maximum token length and use a fixed sized array and
else
{
/* See if the current character is a separator */
- for (j = 0; j < strlen(sep_chars); j++)
+ for (j = 0; j < sep_length; j++)
{
if (str[i] == sep_chars[j])
break;
/* It's a non-separator character, so include
* the meta character in the return tok */
- if (j == strlen(sep_chars))
+ if (j == sep_length)
tok_len++;
got_meta = 0;
else
{
/* See if the current character is a separator */
- for (j = 0; j < strlen(sep_chars); j++)
+ for (j = 0; j < sep_length; j++)
{
if (str[i] == sep_chars[j])
break;
/* It's a non-separator character, so include
* the meta character in the return tok */
- if (j == strlen(sep_chars))
+ if (j == sep_length)
tok[k++] = meta_char;
got_meta = 0;
#include "detection/rtn_checks.h"
#include "detection/treenodes.h"
#include "framework/decode_data.h"
+#include "hash/sfxhash.h"
#include "log/messages.h"
#include "main/snort_config.h"
#include "main/snort_debug.h"
return 0;
}
-static bool same_headers(RuleTreeNode* rule, RuleTreeNode* rtn)
+bool same_headers(RuleTreeNode* rule, RuleTreeNode* rtn)
{
if ( !rule or !rtn )
return false;
static RuleTreeNode* findHeadNode(
SnortConfig* sc, RuleTreeNode* testNode, PolicyId policyId)
{
- SFGHASH_NODE* hashNode;
-
- for (hashNode = sfghash_findfirst(sc->otn_map);
- hashNode;
- hashNode = sfghash_findnext(sc->otn_map))
+ if ( sc->rtn_hash_table )
{
- OptTreeNode* otn = (OptTreeNode*)hashNode->data;
- RuleTreeNode* rtn = getRtnFromOtn(otn, policyId);
-
- if (same_headers(rtn, testNode))
- return rtn;
+ RuleTreeNodeKey key { testNode, policyId };
+ return (RuleTreeNode*)sfxhash_find(sc->rtn_hash_table, &key);
}
return nullptr;
{
// current OTN is newer version. Keep current and discard the new one.
// OTN is for new policy group, salvage RTN
- deleteRtnFromOtn(otn_new);
+ deleteRtnFromOtn(otn_new, sc);
ParseWarning(WARN_RULES, "%u:%u duplicates previous rule. Using revision %u.",
otn_cur->sigInfo.gid, otn_cur->sigInfo.sid, otn_cur->sigInfo.rev);
// otherwise ignore it
if ( !rtn_cur )
{
- addRtnToOtn(otn_cur, rtn_new);
+ addRtnToOtn(sc, otn_cur, rtn_new);
}
else
{
for ( unsigned i = 0; i < otn_cur->proto_node_num; ++i )
{
- RuleTreeNode* rtnTmp2 = deleteRtnFromOtn(otn_cur, i);
+ RuleTreeNode* rtnTmp2 = deleteRtnFromOtn(otn_cur, i, sc, (rtn_cur != rtn_new));
if ( rtnTmp2 and (i != get_ips_policy()->policy_id) )
{
- addRtnToOtn(otn_new, rtnTmp2, i);
+ addRtnToOtn(sc, otn_new, rtnTmp2, i);
}
}
* port var table is freed */
RuleTreeNode* new_rtn = ProcessHeadNode(sc, &rtn, rtn.listhead);
- addRtnToOtn(otn, new_rtn);
+ addRtnToOtn(sc, otn, new_rtn);
OptTreeNode* otn_dup =
OtnLookup(sc->otn_map, otn->sigInfo.gid, otn->sigInfo.sid);
#include "filters/detection_filter.h"
#include "filters/rate_filter.h"
#include "filters/sfthreshold.h"
+#include "hash/sfhashfcn.h"
+#include "hash/sfxhash.h"
#include "log/messages.h"
#include "main/shell.h"
#include "main/snort_config.h"
*
* @return pointer to deleted RTN, NULL otherwise.
*/
-RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn, PolicyId policyId)
+RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn, PolicyId policyId, SnortConfig* sc, bool remove)
{
- RuleTreeNode* rtn = NULL;
+ RuleTreeNode* rtn = nullptr;
if (otn->proto_nodes
&& (otn->proto_node_num >= (policyId+1)))
{
rtn = getRtnFromOtn(otn, policyId);
- otn->proto_nodes[policyId] = NULL;
+ otn->proto_nodes[policyId] = nullptr;
+
+ if ( remove && rtn )
+ {
+ RuleTreeNodeKey key{ rtn, policyId };
+ if ( sc && sc->rtn_hash_table )
+ sfxhash_remove(sc->rtn_hash_table, &key);
+ }
return rtn;
}
- return NULL;
+ return nullptr;
+}
+
+RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn, SnortConfig* sc)
+{
+ return deleteRtnFromOtn(otn, get_ips_policy()->policy_id, sc);
+}
+
+uint32_t rtn_hash_func(SFHASHFCN*, unsigned char *k, int)
+{
+ uint32_t a,b,c;
+ RuleTreeNodeKey* rtnk = (RuleTreeNodeKey*)k;
+ RuleTreeNode* rtn = rtnk->rtn;
+
+ a = rtn->type;
+ b = rtn->flags;
+ c = (uint32_t)(uintptr_t)rtn->listhead;
+
+ mix(a,b,c);
+
+ a += (uint32_t)(uintptr_t)rtn->src_portobject;
+ b += (uint32_t)(uintptr_t)rtn->dst_portobject;
+ c += (uint32_t)(uintptr_t)rtnk->policyId;
+
+ finalize(a,b,c);
+
+ return c;
}
-RuleTreeNode* deleteRtnFromOtn(OptTreeNode* otn)
+int rtn_compare_func(const void *k1, const void *k2, size_t)
{
- return deleteRtnFromOtn(otn, get_ips_policy()->policy_id);
+ RuleTreeNodeKey* rtnk1 = (RuleTreeNodeKey*)k1;
+ RuleTreeNodeKey* rtnk2 = (RuleTreeNodeKey*)k2;
+
+ if (!rtnk1 || !rtnk2)
+ return 1;
+
+ if (rtnk1->policyId != rtnk2->policyId)
+ return 1;
+
+ if (same_headers(rtnk1->rtn, rtnk2->rtn))
+ return 0;
+
+ return 1;
}
/**Add RTN to OTN for a particular OTN.
* @return 0 if successful,
* -ve otherwise
*/
-int addRtnToOtn(OptTreeNode* otn, RuleTreeNode* rtn, PolicyId policyId)
+int addRtnToOtn(SnortConfig* sc, OptTreeNode* otn, RuleTreeNode* rtn, PolicyId policyId)
{
if (otn->proto_node_num <= policyId)
{
otn->proto_nodes[policyId] = rtn;
+ // Optimized for parsing only, this check avoids adding run time rtn
+ if (!sc)
+ return 0;
+
+ if (!sc->rtn_hash_table)
+ {
+ sc->rtn_hash_table = sfxhash_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");
+
+ sfxhash_set_keyops(sc->rtn_hash_table, rtn_hash_func, rtn_compare_func);
+ }
+
+ RuleTreeNodeKey key;
+ memset(&key, 0, sizeof(key));
+ key.rtn = rtn;
+ key.policyId = policyId;
+ sfxhash_add(sc->rtn_hash_table, &key, rtn);
+
return 0; //success
}
-int addRtnToOtn(OptTreeNode* otn, RuleTreeNode* rtn)
+int addRtnToOtn(SnortConfig*sc, OptTreeNode* otn, RuleTreeNode* rtn)
{
- return addRtnToOtn(otn, rtn, get_ips_policy()->policy_id);
+ return addRtnToOtn(sc, otn, rtn, get_ips_policy()->policy_id);
}
void rule_index_map_print_index(int index, char* buf, int bufsize)
int ParseBool(const char* arg);
-int addRtnToOtn(struct OptTreeNode*, RuleTreeNode*);
-int addRtnToOtn(struct OptTreeNode*, RuleTreeNode*, PolicyId);
+int addRtnToOtn(SnortConfig*, struct OptTreeNode*, RuleTreeNode*);
+int addRtnToOtn(SnortConfig*, struct OptTreeNode*, RuleTreeNode*, PolicyId);
-RuleTreeNode* deleteRtnFromOtn(struct OptTreeNode*);
-RuleTreeNode* deleteRtnFromOtn(struct OptTreeNode*, PolicyId);
+bool same_headers(RuleTreeNode*, RuleTreeNode*);
+RuleTreeNode* deleteRtnFromOtn(OptTreeNode*, SnortConfig* sc = nullptr);
+RuleTreeNode* deleteRtnFromOtn(struct OptTreeNode*, PolicyId, SnortConfig* sc = nullptr, bool remove = true);
inline RuleTreeNode* getRtnFromOtn(const struct OptTreeNode* otn, PolicyId policyId)
{
void parser_get_rule_ids(int index, unsigned& gid, unsigned& sid);
void rule_index_map_print_index(int index, char* buf, int);
+struct RuleTreeNodeKey
+{
+ RuleTreeNode* rtn;
+ PolicyId policyId;
+};
+
#endif
// consistency check - part 1
// make sure each port is only in one composite port object
-static void PortTableConsistencyCheck(PortTable* p)
+static bool PortTableConsistencyCheck(PortTable* p)
{
std::unique_ptr<char[]> upA(new char[SFPO_MAX_PORTS]);
char* parray = upA.get();
if ( !po )
{
- FatalError("PortObject consistency Check failed, hash table problem\n");
+ DebugMessage(DEBUG_PORTLISTS, "PortObject consistency Check failed, hash table problem\n");
+ return false;
}
if ( !po->port_cnt ) /* port object is not used ignore it */
{
if ( parray[i] )
{
- FatalError("PortTableCompile: failed consistency check, "
- "multiple objects reference port %d\n", i);
+ DebugFormat(DEBUG_PORTLISTS, "PortTableCompile: failed consistency check, "
+ "multiple objects reference port %d\n", i);
+ return false;
}
parray[i] = 1;
}
}
}
- DebugMessage(DEBUG_PORTLISTS,
- "***\n***Port Table Compiler Consistency Check Phase-I Passed !\n");
+ return true;
}
// consistency check - part 2
* check that each port it reference has all of the rules
* referenced to that port in the composite object
*/
-static void PortTableConsistencyCheck2(PortTable* p)
+static bool PortTableConsistencyCheck2(PortTable* p)
{
SF_LNODE* pos;
PortObject2* lastpo = nullptr;
{
if ( _po2_include_po_rules(p->pt_port_object[i], ipo) )
{
- FatalError("InputPortObject<->CompositePortObject "
- "consistency Check II failed\n");
+ DebugMessage(DEBUG_PORTLISTS,
+ "InputPortObject<->CompositePortObject consistency Check II failed\n");
+ return false;
}
lastpo = p->pt_port_object[i];
}
}
}
- DebugMessage(DEBUG_PORTLISTS,
- "***\n***Port Table Compiler Consistency Check Phase-II Passed !!!"
- " - Good to go Houston\n****\n");
+ return true;
}
//-------------------------------------------------------------------------
DEBUG_WRAP(DebugMessage(DEBUG_PORTLISTS, "Done\n"); fflush(stdout); );
- PortTableConsistencyCheck(p);
- PortTableConsistencyCheck2(p);
+ assert(PortTableConsistencyCheck(p));
+ assert(PortTableConsistencyCheck2(p));
return 0;
}
return cnt;
}
-/*
- * Make a list of ports form the char array, each char is either
- * on or off.
- */
SF_LIST* PortObjectItemListFromBits(const PortBitSet& parray, int n)
{
SF_LIST* plist = sflist_new();
+ int nports = parray.count();
if ( !plist )
return 0;
- for (int i = 0; i < n; i++)
+ for (int i = 0; i < n && nports > 0; i++)
{
if ( parray[i] == 0 )
continue;
/* Either a port or the start of a range */
lport = hport = i;
+ nports--;
for (i++; i<n; i++)
{
if ( parray[i] )
{
hport = i;
+ nports--;
continue;
}
break;
// debug stuff
//-------------------------------------------------------------------------
-#ifdef DEBUG
+#ifdef DEBUG_MSGS
static const char* smb_com_strings[SMB_MAX_NUM_COMS] =
{
"Create Directory", // 0x00
{ DCE2_SMB_CHAIN_OPEN_CLOSE, DCE2_SMB_CHAIN_OPEN_CLOSE_STR },
{ DCE2_SMB_INVALID_SHARE, DCE2_SMB_INVALID_SHARE_STR },
- { DCE2_CO_BAD_MAJOR_VERSION, DCE2_CO_BAD_MAJOR_VERSION_STR },
- { DCE2_CO_BAD_MINOR_VERSION, DCE2_CO_BAD_MINOR_VERSION_STR },
- { DCE2_CO_BAD_PDU_TYPE, DCE2_CO_BAD_PDU_TYPE_STR },
- { DCE2_CO_FRAG_LEN_LT_HDR, DCE2_CO_FRAG_LEN_LT_HDR_STR },
- { DCE2_CO_NO_CTX_ITEMS_SPECFD, DCE2_CO_NO_CTX_ITEMS_SPECFD_STR },
- { DCE2_CO_NO_TFER_SYNTAX_SPECFD, DCE2_CO_NO_TFER_SYNTAX_SPECFD_STR },
- { DCE2_CO_FRAG_LT_MAX_XMIT_FRAG, DCE2_CO_FRAG_LT_MAX_XMIT_FRAG_STR },
- { DCE2_CO_FRAG_GT_MAX_XMIT_FRAG, DCE2_CO_FRAG_GT_MAX_XMIT_FRAG_STR },
- { DCE2_CO_ALTER_CHANGE_BYTE_ORDER, DCE2_CO_ALTER_CHANGE_BYTE_ORDER_STR },
- { DCE2_CO_FRAG_DIFF_CALL_ID, DCE2_CO_FRAG_DIFF_CALL_ID_STR },
- { DCE2_CO_FRAG_DIFF_OPNUM, DCE2_CO_FRAG_DIFF_OPNUM_STR },
- { DCE2_CO_FRAG_DIFF_CTX_ID, DCE2_CO_FRAG_DIFF_CTX_ID_STR },
-
{ DCE2_SMB_V1, DCE2_SMB_V1_STR },
{ DCE2_SMB_V2, DCE2_SMB_V2_STR },
{ DCE2_SMB_INVALID_BINDING, DCE2_SMB_INVALID_BINDING_STR },