AC_HELP_STRING([--enable-perf-profiling],[enable module and rule performance profiling]),
enable_perf_profiling="$enableval", enable_perf_profiling="no")
+AM_CONDITIONAL(PERF_PROFILING, test "x$enable_perf_profiling" = "xyes")
+
if test "x$enable_perf_profiling" = "xyes"; then
CPPFLAGS="$CPPFLAGS -DPERF_PROFILING"
AC_DEFINE(PERF_PROFILING, [1], [enable perf profiling])
void ReactAction::exec(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(reactPerfStats);
+ PERF_PROFILE(reactPerfStats);
if ( Active::is_reset_candidate(p) )
send(p);
-
- MODULE_PROFILE_END(reactPerfStats);
}
void ReactAction::send(Packet* p)
void RejectAction::exec(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(rejPerfStats);
-
+ PERF_PROFILE(rejPerfStats);
send(p);
-
- MODULE_PROFILE_END(rejPerfStats);
}
void RejectAction::send(Packet* p)
void snort_inspect(Packet* p)
{
- PROFILE_VARS;
-
#ifdef PPM_MGR
uint64_t pktcnt=0;
PPM_END_PKT_TIMER();
}
#endif
- MODULE_PROFILE_START(eventqPerfStats);
+
+ PERF_PROFILE(eventqPerfStats);
SnortEventqLog(p);
SnortEventqReset();
- MODULE_PROFILE_END(eventqPerfStats);
}
void snort_log(Packet* p)
case PktType::PDU:
case PktType::FILE:
{
- PROFILE_VARS;
-
# ifdef PPM_MGR
/*
* Packet Performance Monitoring
** This is where we short circuit so
** that we can do IP checks.
*/
- MODULE_PROFILE_START(detectPerfStats);
- int detected = fpEvalPacket(p);
- MODULE_PROFILE_END(detectPerfStats);
-
- return detected;
+ PERF_PROFILE(detectPerfStats);
+ return fpEvalPacket(p);
}
default:
#define HASH_RULE_OPTIONS 16384
#define HASH_RULE_TREE 8192
+// FIXIT-L find a better place for this
+static inline bool operator==(const struct timeval& a, const struct timeval& b)
+{ return a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec; }
+
uint32_t detection_option_hash_func(SFHASHFCN*, unsigned char* k, int)
{
detection_option_key_t* key = (detection_option_key_t*)k;
detection_option_tree_node_t* node, detection_option_eval_data_t* eval_data,
Cursor& orig_cursor)
{
- int i, result = 0;
+ // need node->state to do perf profiling
+ if ( !node )
+ return 0;
+
+ dot_node_state_t* state = node->state + get_instance_id();
+ auto& node_stats = *state;
+ NODE_PERF_PROFILE(node_stats);
+
+ int result = 0;
int rval = DETECTION_OPTION_NO_MATCH;
char tmp_noalert_flag = 0;
Cursor cursor = orig_cursor;
uint32_t tmp_byte_extract_vars[NUM_BYTE_EXTRACT_VARS];
uint64_t cur_eval_pkt_count =
(rule_eval_pkt_count + (PacketManager::get_rebuilt_packet_count()));
- NODE_PROFILE_VARS;
// FIXIT-P these are initialized only to silence -O2 warnings
// they are set before use below
PatternMatchData* content_data = nullptr;
PcreData* pcre_data = nullptr;
- if (!node || !eval_data || !eval_data->p || !eval_data->pomd)
+ if ( !eval_data || !eval_data->p || !eval_data->pomd )
return 0;
- dot_node_state_t* state = node->state + get_instance_id();
+ auto p = eval_data->p;
+ auto pomd = eval_data->pomd;
- /* see if evaluated it before ... */
- if (node->is_relative == 0)
+ // see if evaluated it before ...
+ if ( !node->is_relative )
{
- /* Only matters if not relative... */
- if ((state->last_check.ts.tv_usec == eval_data->p->pkth->ts.tv_usec) &&
- (state->last_check.ts.tv_sec == eval_data->p->pkth->ts.tv_sec) &&
- (state->last_check.packet_number == cur_eval_pkt_count) &&
- (state->last_check.rebuild_flag == (eval_data->p->packet_flags &
- PKT_REBUILT_STREAM)) &&
- (!(eval_data->p->packet_flags & PKT_ALLOW_MULTIPLE_DETECT)))
+ auto last_check = state->last_check;
+
+ if ( last_check.ts == p->pkth->ts &&
+ last_check.packet_number == cur_eval_pkt_count &&
+ last_check.rebuild_flag == (p->packet_flags & PKT_REBUILT_STREAM) &&
+ !(p->packet_flags & PKT_ALLOW_MULTIPLE_DETECT) )
{
- /* eval'd this rule option before on this packet,
- * use the cached result. */
- if ((state->last_check.flowbit_failed == 0) &&
- !(eval_data->p->packet_flags & PKT_IP_RULE_2ND) &&
- !(eval_data->p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP )))
+ if ( !last_check.flowbit_failed &&
+ !(p->packet_flags & PKT_IP_RULE_2ND) &&
+ !(p->packet_flags & (PROTO_BIT__TEREDO|PROTO_BIT__GTP)) )
{
- return state->last_check.result;
+ return last_check.result;
}
}
}
- NODE_PROFILE_START(node);
-
- state->last_check.ts.tv_sec = eval_data->p->pkth->ts.tv_sec;
- state->last_check.ts.tv_usec = eval_data->p->pkth->ts.tv_usec;
+ state->last_check.ts = eval_data->p->pkth->ts;
state->last_check.packet_number = cur_eval_pkt_count;
- state->last_check.rebuild_flag = (eval_data->p->packet_flags & PKT_REBUILT_STREAM);
state->last_check.flowbit_failed = 0;
+ state->last_check.rebuild_flag = p->packet_flags & PKT_REBUILT_STREAM;
- /* Save some stuff off for repeated pattern tests */
+ // Save some stuff off for repeated pattern tests
if ( node->option_type == RULE_OPTION_TYPE_CONTENT )
- {
content_data = content_get_data(node->option_data);
- }
+
else if (node->option_type == RULE_OPTION_TYPE_PCRE)
- {
pcre_data = pcre_get_data(node->option_data);
- }
- /* No, haven't evaluated this one before... Check it. */
+ // No, haven't evaluated this one before... Check it.
do
{
- switch (node->option_type)
+ switch ( node->option_type )
{
case RULE_OPTION_TYPE_LEAF_NODE:
- /* Add the match for this otn to the queue. */
+ // Add the match for this otn to the queue.
{
OptTreeNode* otn = (OptTreeNode*)node->option_data;
PatternMatchData* pmd = (PatternMatchData*)eval_data->pmd;
int pattern_size = 0;
- int check_ports = 1;
- int eval_rtn_result;
- unsigned int svc_idx;
- int16_t app_proto = eval_data->p->get_application_protocol();
-
- if (pmd)
+ if ( pmd )
pattern_size = pmd->pattern_size;
- if ( app_proto and ((OTNX_MATCH_DATA*)(eval_data->pomd))->check_ports != 2 )
+ int16_t app_proto = p->get_application_protocol();
+ int check_ports = 1;
+
+ if ( app_proto and ((OTNX_MATCH_DATA*)(pomd))->check_ports != 2 )
{
- for (svc_idx = 0; svc_idx < otn->sigInfo.num_services; svc_idx++)
+ auto sig_info = otn->sigInfo;
+
+ for ( unsigned svc_idx = 0; svc_idx < sig_info.num_services; ++svc_idx )
{
- if ( app_proto == otn->sigInfo.services[svc_idx].service_ordinal )
+ if ( app_proto == sig_info.services[svc_idx].service_ordinal )
{
check_ports = 0;
- break; /* out of for */
+ break; // out of for
}
}
- if (otn->sigInfo.num_services && check_ports)
+ if (sig_info.num_services && check_ports)
{
- /* none of the services match */
+ // none of the services match
DebugFormat(DEBUG_DETECT,
"[**] SID %d not matched because of service mismatch (%d!=%d [**]\n",
- otn->sigInfo.id, app_proto, otn->sigInfo.services[0].service_ordinal);
- break; /* out of case */
+ sig_info.id, app_proto, sig_info.services[0].service_ordinal);
+
+ break; // out of case
}
}
+
+ int eval_rtn_result = 0;
+
// Don't include RTN time
- NODE_PROFILE_TMPEND(node);
- eval_rtn_result = fpEvalRTN(getRuntimeRtnFromOtn(otn), eval_data->p, check_ports);
- NODE_PROFILE_TMPSTART(node);
+ PERF_PAUSE_BLOCK(node_stats)
+ {
+ eval_rtn_result = fpEvalRTN(getRuntimeRtnFromOtn(otn), p,
+ check_ports);
+ }
- if (eval_rtn_result)
+ if ( eval_rtn_result )
{
- if ( !otn->detection_filter ||
- !detection_filter_test(
- otn->detection_filter,
- eval_data->p->ptrs.ip_api.get_src(), eval_data->p->ptrs.ip_api.get_dst(),
- eval_data->p->pkth->ts.tv_sec) )
+ bool f_result = true;
+
+ if ( otn->detection_filter )
+ f_result = detection_filter_test(otn->detection_filter,
+ p->ptrs.ip_api.get_src(), p->ptrs.ip_api.get_dst(),
+ p->pkth->ts.tv_sec);
+
+ if ( f_result )
{
#ifdef PERF_PROFILING
if (PROFILING_RULES)
otn->state[get_instance_id()].matches++;
#endif
- if (!eval_data->flowbit_noalert)
- {
- fpAddMatch((OTNX_MATCH_DATA*)eval_data->pomd, pattern_size, otn);
- }
+ if ( !eval_data->flowbit_noalert )
+ fpAddMatch((OTNX_MATCH_DATA*)pomd, pattern_size, otn);
+
result = rval = DETECTION_OPTION_MATCH;
}
}
+
+ break;
}
- break;
+
case RULE_OPTION_TYPE_CONTENT:
- if (node->evaluate)
+ if ( node->evaluate )
{
- /* This will be set in the fast pattern matcher if we found
- * a content and the rule option specifies not that
- * content. Essentially we've already evaluated this rule
- * option via the content option processing since only not
- * contents that are not relative in any way will have this
- * flag set */
- if (content_data->last_check)
+ // This will be set in the fast pattern matcher if we found
+ // a content and the rule option specifies not that
+ // content. Essentially we've already evaluated this rule
+ // option via the content option processing since only not
+ // contents that are not relative in any way will have this
+ // flag set
+ if ( content_data->last_check )
{
- PmdLastCheck* last_check =
- content_data->last_check + get_instance_id();
-
- if ((last_check->ts.tv_sec == eval_data->p->pkth->ts.tv_sec) &&
- (last_check->ts.tv_usec == eval_data->p->pkth->ts.tv_usec) &&
- (last_check->packet_number == cur_eval_pkt_count) &&
- (last_check->rebuild_flag == (eval_data->p->packet_flags &
- PKT_REBUILT_STREAM)))
+ auto last_check = content_data->last_check + get_instance_id();
+
+ if ( last_check->ts == p->pkth->ts &&
+ last_check->packet_number == cur_eval_pkt_count &&
+ last_check->rebuild_flag == (p->packet_flags & PKT_REBUILT_STREAM) )
{
rval = DETECTION_OPTION_NO_MATCH;
break;
}
}
- rval = node->evaluate(node->option_data, cursor, eval_data->p);
+
+ rval = node->evaluate(node->option_data, cursor, p);
}
+
break;
+
case RULE_OPTION_TYPE_PCRE:
- if (node->evaluate)
- {
- rval = node->evaluate(node->option_data, cursor, eval_data->p);
- }
+ if ( node->evaluate )
+ rval = node->evaluate(node->option_data, cursor, p);
+
break;
+
case RULE_OPTION_TYPE_FLOWBIT:
- if (node->evaluate)
+ if ( node->evaluate )
{
- flowbits_setoperation = FlowBits_SetOperation(node->option_data);
- if (!flowbits_setoperation)
- {
- rval = node->evaluate(node->option_data, cursor, eval_data->p);
- }
- else
- {
- /* set to match so we don't bail early. */
+ flowbits_setoperation =
+ FlowBits_SetOperation(node->option_data);
+
+ if ( flowbits_setoperation )
+ // set to match so we don't bail early
rval = DETECTION_OPTION_MATCH;
- }
+
+ else
+ rval = node->evaluate(node->option_data, cursor, eval_data->p);
}
+
break;
+
default:
- if (node->evaluate)
- rval = node->evaluate(node->option_data, cursor, eval_data->p);
+ if ( node->evaluate )
+ rval = node->evaluate(node->option_data, cursor, p);
+
break;
+
}
- if (rval == DETECTION_OPTION_NO_MATCH)
+ if ( rval == DETECTION_OPTION_NO_MATCH )
{
state->last_check.result = result;
- NODE_PROFILE_END_NOMATCH(node);
return result;
}
- else if (rval == DETECTION_OPTION_FAILED_BIT)
+
+ else if ( rval == DETECTION_OPTION_FAILED_BIT )
{
eval_data->flowbit_failed = 1;
- /* clear the timestamp so failed flowbit gets eval'd again */
+ // clear the timestamp so failed flowbit gets eval'd again
state->last_check.flowbit_failed = 1;
state->last_check.result = result;
- NODE_PROFILE_END_NOMATCH(node);
return 0;
}
- else if (rval == DETECTION_OPTION_NO_ALERT)
+
+ else if ( rval == DETECTION_OPTION_NO_ALERT )
{
- /* Cache the current flowbit_noalert flag, and set it
- * so nodes below this don't alert. */
+ // Cache the current flowbit_noalert flag, and set it
+ // so nodes below this don't alert.
tmp_noalert_flag = eval_data->flowbit_noalert;
eval_data->flowbit_noalert = 1;
}
- /* Back up byte_extract vars so they don't get overwritten between rules */
- for (i = 0; i < NUM_BYTE_EXTRACT_VARS; i++)
- {
+ // Back up byte_extract vars so they don't get overwritten between rules
+ for ( int i = 0; i < NUM_BYTE_EXTRACT_VARS; ++i )
GetByteExtractValue(&(tmp_byte_extract_vars[i]), (int8_t)i);
- }
#ifdef PPM_MGR
if ( PPM_PKTS_ENABLED() )
PPM_PACKET_TEST();
if ( PPM_PACKET_ABORT_FLAG() )
{
- /* bail if we exceeded time */
- if (result == DETECTION_OPTION_NO_MATCH)
- {
- NODE_PROFILE_END_NOMATCH(node);
- }
- else
- {
- NODE_PROFILE_END_MATCH(node);
- }
+ // bail if we exceeded time
+
+ if ( result != DETECTION_OPTION_NO_MATCH )
+ NODE_PERF_PROFILE_STOP_MATCH(node_stats);
+
state->last_check.result = result;
return result;
}
}
#endif
- /* Don't include children's time in this node */
- NODE_PROFILE_TMPEND(node);
- /* Passed, check the children. */
- if (node->num_children)
+ PERF_PAUSE_BLOCK(node_stats)
{
- for (i=0; i<node->num_children; i++)
+ // Passed, check the children.
+ if ( node->num_children )
{
- int j = 0;
- detection_option_tree_node_t* child_node = node->children[i];
- dot_node_state_t* child_state = child_node->state + get_instance_id();
-
- for (j = 0; j < NUM_BYTE_EXTRACT_VARS; j++)
+ for ( int i = 0; i < node->num_children; ++i )
{
- SetByteExtractValue(tmp_byte_extract_vars[j], (int8_t)j);
- }
+ detection_option_tree_node_t* child_node =
+ node->children[i];
- if (loop_count > 0)
- {
- if (child_state->result == DETECTION_OPTION_NO_MATCH)
+ dot_node_state_t* child_state =
+ child_node->state + get_instance_id();
+
+ for ( int j = 0; j < NUM_BYTE_EXTRACT_VARS; ++j )
+ SetByteExtractValue(tmp_byte_extract_vars[j], (int8_t)j);
+
+ if ( loop_count > 0 )
{
- if (((child_node->option_type == RULE_OPTION_TYPE_CONTENT)
- || (child_node->option_type == RULE_OPTION_TYPE_PCRE))
- && !child_node->is_relative)
+ if ( child_state->result == DETECTION_OPTION_NO_MATCH )
{
- /* If it's a non-relative content or pcre, no reason
- * to check again. Only increment result once.
- * Should hit this condition on first loop iteration. */
- if (loop_count == 1)
- result++;
- continue;
- }
- else if ((child_node->option_type == RULE_OPTION_TYPE_CONTENT)
- && child_node->is_relative)
- {
- /* Check for an unbounded relative search. If this
- * failed before, it's going to fail again so don't
- * go down this path again */
- if ( is_unbounded(child_node->option_data) )
+ if ( (child_node->option_type == RULE_OPTION_TYPE_CONTENT ||
+ child_node->option_type == RULE_OPTION_TYPE_PCRE) &&
+ !child_node->is_relative )
{
- /* Only increment result once. Should hit this
- * condition on first loop iteration. */
- if (loop_count == 1)
- result++;
+ // If it's a non-relative content or pcre, no reason
+ // to check again. Only increment result once.
+ // Should hit this condition on first loop iteration.
+ if ( loop_count == 1 )
+ ++result;
+
continue;
}
+
+ else if ( child_node->option_type == RULE_OPTION_TYPE_CONTENT &&
+ child_node->is_relative )
+ {
+ // Check for an unbounded relative search. If this
+ // failed before, it's going to fail again so don't
+ // go down this path again
+ if ( is_unbounded(child_node->option_data) )
+ {
+ // Only increment result once. Should hit this
+ // condition on first loop iteration
+ if (loop_count == 1)
+ ++result;
+
+ continue;
+ }
+ }
}
+
+ else if ( child_node->option_type == RULE_OPTION_TYPE_LEAF_NODE )
+ // Leaf node matched, don't eval again
+ continue;
+
+ else if ( child_state->result == child_node->num_children )
+ // This branch of the tree matched or has options that
+ // don't need to be evaluated again, so don't need to
+ // evaluate this option again
+ continue;
}
- else if (child_node->option_type == RULE_OPTION_TYPE_LEAF_NODE)
- {
- /* Leaf node matched, don't eval again */
- continue;
- }
- else if (child_state->result == child_node->num_children)
- {
- /* This branch of the tree matched or has options that
- * don't need to be evaluated again, so don't need to
- * evaluate this option again */
- continue;
- }
- }
- child_state->result = detection_option_node_evaluate(
- node->children[i], eval_data, cursor);
+ child_state->result = detection_option_node_evaluate(
+ node->children[i], eval_data, cursor);
- if (child_node->option_type == RULE_OPTION_TYPE_LEAF_NODE)
- {
- /* Leaf node won't have any children but will return success
- * or failure */
- result += child_state->result;
- }
- else if (child_state->result == child_node->num_children)
- {
- /* Indicate that the child's tree branches are done */
- result++;
- }
+ if ( child_node->option_type == RULE_OPTION_TYPE_LEAF_NODE )
+ // Leaf node won't have any children but will return success
+ // or failure
+ result += child_state->result;
+
+ else if (child_state->result == child_node->num_children)
+ // Indicate that the child's tree branches are done
+ ++result;
#ifdef PPM_MGR
- if ( PPM_PKTS_ENABLED() )
- {
- PPM_GET_TIME();
- PPM_PACKET_TEST();
- if ( PPM_PACKET_ABORT_FLAG() )
+ if ( PPM_PKTS_ENABLED() )
{
- /* bail if we exceeded time */
- state->last_check.result = result;
- return result;
+ PPM_GET_TIME();
+ PPM_PACKET_TEST();
+ if ( PPM_PACKET_ABORT_FLAG() )
+ {
+ // bail if we exceeded time
+ state->last_check.result = result;
+ return result;
+ }
}
- }
#endif
- }
-
- /* If all children branches matched, we don't need to reeval any of
- * the children so don't need to reeval this content/pcre rule
- * option at a new offset.
- * Else, reset the DOE ptr to last eval for offset/depth,
- * distance/within adjustments for this same content/pcre
- * rule option */
- if (result == node->num_children)
- continue_loop = 0;
+ }
- /* Don't need to reset since it's only checked after we've gone
- * through the loop at least once and the result will have
- * been set again already */
- //for (i = 0; i < node->num_children; i++)
- // node->children[i]->result;
+ // If all children branches matched, we don't need to reeval any of
+ // the children so don't need to reeval this content/pcre rule
+ // option at a new offset.
+ // Else, reset the DOE ptr to last eval for offset/depth,
+ // distance/within adjustments for this same content/pcre
+ // rule option
+ if ( result == node->num_children )
+ continue_loop = 0;
+
+ // Don't need to reset since it's only checked after we've gone
+ // through the loop at least once and the result will have
+ // been set again already
+ //for (i = 0; i < node->num_children; i++)
+ // node->children[i]->result;
+ }
}
- NODE_PROFILE_TMPSTART(node);
-
- if (rval == DETECTION_OPTION_NO_ALERT)
+ if ( rval == DETECTION_OPTION_NO_ALERT )
{
- /* Reset the flowbit_noalert flag in eval data */
+ // Reset the flowbit_noalert flag in eval data
eval_data->flowbit_noalert = tmp_noalert_flag;
}
- if (continue_loop && (rval == DETECTION_OPTION_MATCH) && (node->relative_children))
+ if ( continue_loop &&
+ rval == DETECTION_OPTION_MATCH &&
+ node->relative_children )
{
if ( node->option_type == RULE_OPTION_TYPE_CONTENT )
- {
continue_loop = content_next(content_data);
- }
+
else if (node->option_type == RULE_OPTION_TYPE_PCRE)
- {
continue_loop = pcre_next(pcre_data);
- }
+
else
- {
continue_loop = 0;
- }
}
+
else
- {
continue_loop = 0;
- }
#ifdef PERF_PROFILING
- /* We're essentially checking this node again and it potentially
- * might match again */
- if (continue_loop && PROFILING_RULES)
+ // We're essentially checking this node again and it potentially
+ // might match again
+ if ( continue_loop && PROFILING_RULES )
state->checks++;
#endif
loop_count++;
}
- while (continue_loop);
- if (flowbits_setoperation && (result == DETECTION_OPTION_MATCH))
+ // FIXIT-H What's the point of this?
+ // either it infinite loops, or effective no-op
+ while ( continue_loop );
+
+ if ( flowbits_setoperation && result == DETECTION_OPTION_MATCH )
{
- /* Do any setting/clearing/resetting/toggling of flowbits here
- * given that other rule options matched. */
- rval = node->evaluate(node->option_data, cursor, eval_data->p);
- if (rval != DETECTION_OPTION_MATCH)
- {
+ // Do any setting/clearing/resetting/toggling of flowbits here
+ // given that other rule options matched
+ rval = node->evaluate(node->option_data, cursor, p);
+ if ( rval != DETECTION_OPTION_MATCH )
result = rval;
- }
}
- if (eval_data->flowbit_failed)
+ if ( eval_data->flowbit_failed )
{
- /* something deeper in the tree failed a flowbit test, we may need to
- * reeval this node. */
+ // something deeper in the tree failed a flowbit test, we may need to
+ // reeval this node
state->last_check.flowbit_failed = 1;
}
+
state->last_check.result = result;
- if (result == DETECTION_OPTION_NO_MATCH)
- {
- NODE_PROFILE_END_NOMATCH(node);
- }
- else
- {
- NODE_PROFILE_END_MATCH(node);
- }
+ if ( result != DETECTION_OPTION_NO_MATCH )
+ NODE_PERF_PROFILE_STOP_MATCH(node_stats);
return result;
}
uint64_t ppm_disable_cnt;
uint64_t ppm_enable_cnt;
#endif
+
+#ifdef PERF_PROFILING
+ void update(uint64_t elapsed, bool match)
+ {
+ ticks += elapsed;
+
+ if ( match )
+ ticks_match += elapsed;
+ else
+ ticks_no_match += elapsed;
+
+ ++checks;
+ }
+#endif
};
struct detection_option_tree_node_t
fpLogOther(p, rtn, otn, rtn->type);
return 1;
}
- OTN_PROFILE_ALERT(otn);
+
+#ifdef PERF_PROFILING
+ otn->state[get_instance_id()].alerts++;
+#endif
event_id++;
action_execute((RuleType)action, p, otn, event_id);
*/
int fpEvalRTN(RuleTreeNode* rtn, Packet* p, int check_ports)
{
- PROFILE_VARS;
-
- MODULE_PROFILE_START(ruleRTNEvalPerfStats);
+ PERF_PROFILE(ruleRTNEvalPerfStats);
if ( !rtn )
- {
- MODULE_PROFILE_END(ruleRTNEvalPerfStats);
return 0;
- }
- /* FIXIT: maybe add a port test here ... */
+ // FIXIT: maybe add a port test here ...
DebugFormat(DEBUG_DETECT, "[*] Rule Head %p\n", rtn);
" => Header check failed, checking next node\n");
DebugMessage(DEBUG_DETECT,
" => returned from next node check\n");
- MODULE_PROFILE_END(ruleRTNEvalPerfStats);
return 0;
}
** Return that there is a rule match and log the event outside
** of this routine.
*/
- MODULE_PROFILE_END(ruleRTNEvalPerfStats);
return 1;
}
detection_option_tree_root_t* root,
detection_option_eval_data_t* eval_data)
{
- int i, rval = 0;
- PROFILE_VARS;
+ PERF_PROFILE(ruleOTNEvalPerfStats);
if (!root)
return 0;
- MODULE_PROFILE_START(ruleOTNEvalPerfStats); /* Not really OTN, but close */
#ifdef PPM_MGR
/* Start Rule Timer */
Cursor c(eval_data->p);
- for ( i = 0; i< root->num_children; i++)
+ int rval = 0;
+ for ( int i = 0; i< root->num_children; i++)
{
/* Increment number of events generated from that child */
rval += detection_option_node_evaluate(root->children[i], eval_data, c);
}
#endif
- MODULE_PROFILE_END(ruleOTNEvalPerfStats);
return rval;
}
detection_option_tree_root_t* root = (detection_option_tree_root_t*)tree;
detection_option_eval_data_t eval_data;
NCListNode* ncl;
- int rval=0;
- PROFILE_VARS;
eval_data.pomd = pomd;
eval_data.p = pomd->p;
eval_data.flowbit_failed = 0;
eval_data.flowbit_noalert = 0;
- MODULE_PROFILE_START(rulePerfStats);
-
- /* NOTE: The otn will be the first one in the match state. If there are
- * multiple rules associated with a match state, mucking with the otn
- * may muck with an unintended rule */
-
- /* Set flag for not contents so they aren't evaluated */
- for (ncl = (NCListNode*)neg_list; ncl != nullptr; ncl = ncl->next)
+ PERF_PROFILE_BLOCK(rulePerfStats)
{
- PMX* neg_pmx = (PMX*)ncl->pmx;
- PatternMatchData* neg_pmd = (PatternMatchData*)neg_pmx->PatternMatchData;
+ /* NOTE: The otn will be the first one in the match state. If there are
+ * multiple rules associated with a match state, mucking with the otn
+ * may muck with an unintended rule */
- assert(neg_pmd->last_check);
+ /* Set flag for not contents so they aren't evaluated */
+ for (ncl = (NCListNode*)neg_list; ncl != nullptr; ncl = ncl->next)
+ {
+ PMX* neg_pmx = (PMX*)ncl->pmx;
+ PatternMatchData* neg_pmd = (PatternMatchData*)neg_pmx->PatternMatchData;
- PmdLastCheck* last_check =
- neg_pmd->last_check + get_instance_id();
+ assert(neg_pmd->last_check);
- last_check->ts.tv_sec = eval_data.p->pkth->ts.tv_sec;
- last_check->ts.tv_usec = eval_data.p->pkth->ts.tv_usec;
- last_check->packet_number = (rule_eval_pkt_count
- + (PacketManager::get_rebuilt_packet_count()));
- last_check->rebuild_flag = (eval_data.p->packet_flags & PKT_REBUILT_STREAM);
- }
+ PmdLastCheck* last_check =
+ neg_pmd->last_check + get_instance_id();
- rval = detection_option_tree_evaluate(root, &eval_data);
+ last_check->ts.tv_sec = eval_data.p->pkth->ts.tv_sec;
+ last_check->ts.tv_usec = eval_data.p->pkth->ts.tv_usec;
+ last_check->packet_number = (rule_eval_pkt_count
+ + (PacketManager::get_rebuilt_packet_count()));
+ last_check->rebuild_flag = (eval_data.p->packet_flags & PKT_REBUILT_STREAM);
+ }
- if (rval)
- {
- // We have a qualified event from this tree
- pomd->pg->event_count++;
- UpdateQEvents(&sfEvent);
- }
- else
- {
- // This means that the event is non-qualified.
- pomd->pg->match_count++;
- UpdateNQEvents(&sfEvent);
+ if ( detection_option_tree_evaluate(root, &eval_data) )
+ {
+ // We have a qualified event from this tree
+ pomd->pg->event_count++;
+ UpdateQEvents(&sfEvent);
+ }
+ else
+ {
+ // This means that the event is non-qualified.
+ pomd->pg->match_count++;
+ UpdateNQEvents(&sfEvent);
+ }
}
- MODULE_PROFILE_END(rulePerfStats);
-
if (eval_data.flowbit_failed)
return -1;
bool repeat = false;
uint16_t tmp_dsize;
FastPatternConfig* fp = snort_conf->fast_pattern_config;
- PROFILE_VARS;
if (ip_rule)
{
LogMessage("NC-testing %u rules\n", port_group->nfp_rule_count);
detection_option_eval_data_t eval_data;
- int rval;
eval_data.pomd = omd;
eval_data.p = p;
eval_data.flowbit_failed = 0;
eval_data.flowbit_noalert = 0;
- MODULE_PROFILE_START(ncrulePerfStats);
- rval = detection_option_tree_evaluate(
- (detection_option_tree_root_t*)port_group->nfp_tree, &eval_data);
- MODULE_PROFILE_END(ncrulePerfStats);
+ int rval = 0;
+
+ PERF_PROFILE_BLOCK(ncrulePerfStats)
+ {
+ rval = detection_option_tree_evaluate(
+ (detection_option_tree_root_t*)port_group->nfp_tree,
+ &eval_data);
+ }
if (rval)
{
const unsigned char* T, int n, MpseMatch match,
void* data, int* current_state)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(mpsePerfStats);
+ PERF_PROFILE(mpsePerfStats);
int ret = _search(T, n, match, data, current_state);
if ( inc_global_counter )
s_bcnt += n;
- MODULE_PROFILE_END(mpsePerfStats);
return ret;
}
int TcpAckOption::eval(Cursor&, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(tcpAckPerfStats);
-
- int rval;
+ PERF_PROFILE(tcpAckPerfStats);
if ( p->ptrs.tcph && config.eval(p->ptrs.tcph->th_ack) )
- rval = DETECTION_OPTION_MATCH;
-
- else
- rval = DETECTION_OPTION_NO_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(tcpAckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int Asn1Option::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(asn1PerfStats);
- /*
- ** Failed if there is no data to decode.
- */
+ // Failed if there is no data to decode.
if (!p->data)
return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(asn1PerfStats);
if ( Asn1DoDetect(c.buffer(), c.size(), &config, c.start()) )
- {
- MODULE_PROFILE_END(asn1PerfStats);
return DETECTION_OPTION_MATCH;
- }
- MODULE_PROFILE_END(asn1PerfStats);
return DETECTION_OPTION_NO_MATCH;
}
int Base64DecodeOption::eval(Cursor& c, Packet*)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- const uint8_t* start_ptr;
- unsigned size;
- uint8_t base64_buf[DECODE_BLEN];
- uint32_t base64_size =0;
+ PERF_PROFILE(base64PerfStats);
+
- PROFILE_VARS;
- MODULE_PROFILE_START(base64PerfStats);
base64_decode_size = 0;
+
Base64DecodeData* idx = (Base64DecodeData*)&config;
+ const uint8_t* start_ptr = nullptr;
+ unsigned size = 0;
if (idx->flags & BASE64DECODE_RELATIVE_FLAG)
{
}
if ( idx->offset >= size )
- {
- MODULE_PROFILE_END(base64PerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
+
start_ptr += idx->offset;
size -= idx->offset;
+ uint8_t base64_buf[DECODE_BLEN];
+ uint32_t base64_size = 0;
+
if (sf_unfold_header(start_ptr, size, base64_buf, sizeof(base64_buf), &base64_size, 0, 0) != 0)
- {
- MODULE_PROFILE_END(base64PerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
if (idx->bytes_to_decode && (base64_size > idx->bytes_to_decode))
{
if (sf_base64decode(base64_buf, base64_size, (uint8_t*)base64_decode_buf,
sizeof(base64_decode_buf), &base64_decode_size) != 0)
- {
- MODULE_PROFILE_END(base64PerfStats);
- return rval;
- }
-
- MODULE_PROFILE_END(base64PerfStats);
+ return DETECTION_OPTION_NO_MATCH;
return DETECTION_OPTION_MATCH;
}
int Base64DataOption::eval(Cursor& c, Packet*)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(base64PerfStats);
+ PERF_PROFILE(base64PerfStats);
if ( !base64_decode_size )
- {
- MODULE_PROFILE_END(base64PerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
c.set(s_data_name, base64_decode_buf, base64_decode_size);
- rval = DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(base64PerfStats);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
//-------------------------------------------------------------------------
int LenOption::eval(Cursor& c, Packet*)
{
- int rval = DETECTION_OPTION_NO_MATCH;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(lenCheckPerfStats);
+ PERF_PROFILE(lenCheckPerfStats);
if ( config.eval(c.length()) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(lenCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int ByteExtractOption::eval(Cursor& c, Packet* p)
{
- ByteExtractData* data = &config;
- int ret, bytes_read;
- uint32_t* value;
+ PERF_PROFILE(byteExtractPerfStats);
- PROFILE_VARS;
- MODULE_PROFILE_START(byteExtractPerfStats);
+ ByteExtractData* data = &config;
if (data == NULL || p == NULL)
- {
- MODULE_PROFILE_END(byteExtractPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
const uint8_t* start = c.buffer();
int dsize = c.size();
ptr += data->offset;
const uint8_t* end = start + dsize;
- value = &(extracted_values[data->var_number]);
+ uint32_t* value = &(extracted_values[data->var_number]);
- /* check bounds */
+ // check bounds
if (ptr < start || ptr >= end)
- {
- MODULE_PROFILE_END(byteExtractPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- /* do the extraction */
+ // do the extraction
+ int ret = 0;
+ int bytes_read = 0;
+
if (data->data_string_convert_flag == 0)
{
ret = byte_extract(data->endianess, data->bytes_to_grab, ptr, start, end, value);
if (ret < 0)
- {
- MODULE_PROFILE_END(byteExtractPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
+
bytes_read = data->bytes_to_grab;
}
else
{
ret = string_extract(data->bytes_to_grab, data->base, ptr, start, end, value);
if (ret < 0)
- {
- MODULE_PROFILE_END(byteExtractPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
+
bytes_read = ret;
}
c.add_pos(bytes_read);
/* this rule option always "matches" if the read is performed correctly */
- MODULE_PROFILE_END(byteExtractPerfStats);
return DETECTION_OPTION_MATCH;
}
int ByteJumpOption::eval(Cursor& c, Packet*)
{
+ PERF_PROFILE(byteJumpPerfStats);
+
ByteJumpData* bjd = (ByteJumpData*)&config;
- int rval = DETECTION_OPTION_NO_MATCH;
- uint32_t jump = 0;
- uint32_t payload_bytes_grabbed = 0;
- int32_t offset;
- PROFILE_VARS;
- MODULE_PROFILE_START(byteJumpPerfStats);
+ int32_t offset = 0;
- /* Get values from byte_extract variables, if present. */
+ // Get values from byte_extract variables, if present.
if (bjd->offset_var >= 0 && bjd->offset_var < NUM_BYTE_EXTRACT_VARS)
{
uint32_t extract_offset;
const uint8_t* const base_ptr = offset +
((bjd->relative_flag) ? c.start() : start_ptr);
- /* Both of the extraction functions contain checks to ensure the data
- * is inbounds and will return no match if it isn't */
+ uint32_t jump = 0;
+ uint32_t payload_bytes_grabbed = 0;
+
+ // Both of the extraction functions contain checks to ensure the data
+ // is inbounds and will return no match if it isn't
if ( !bjd->data_string_convert_flag )
{
if ( byte_extract(
bjd->endianess, bjd->bytes_to_grab,
base_ptr, start_ptr, end_ptr, &jump) )
- {
- MODULE_PROFILE_END(byteJumpPerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
payload_bytes_grabbed = bjd->bytes_to_grab;
}
base_ptr, start_ptr, end_ptr, &jump);
if (tmp < 0)
- {
- MODULE_PROFILE_END(byteJumpPerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
+
payload_bytes_grabbed = tmp;
}
// Negative offsets that put us outside the buffer should have been caught
jump += bjd->post_offset;
if ( !c.set_pos(jump) )
- {
- MODULE_PROFILE_END(byteJumpPerfStats);
- return rval;
- }
- else
- {
- rval = DETECTION_OPTION_MATCH;
- }
+ return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_END(byteJumpPerfStats);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
//-------------------------------------------------------------------------
{
uint32_t bytes_to_compare;
uint32_t cmp_value;
+ // FIXIT-L should be an enum
uint32_t opcode;
int32_t offset;
uint8_t not_flag;
int8_t offset_var;
} ByteTestData;
+// -----------------------------------------------------------------------------
+// static functions
+// -----------------------------------------------------------------------------
+
+static inline bool byte_test_check(uint32_t op, uint32_t val, uint32_t cmp, bool not_flag)
+{
+ bool success = false;
+
+ switch ( op )
+ {
+ case CHECK_LT:
+ success = (val < cmp);
+ break;
+
+ case CHECK_EQ:
+ success = (val == cmp);
+ break;
+
+ case CHECK_GT:
+ success = (val > cmp);
+ break;
+
+ case CHECK_AND:
+ success = ((val & cmp) > 0);
+ break;
+
+ case CHECK_XOR:
+ success = ((val ^ cmp) > 0);
+ break;
+
+ case CHECK_GTE:
+ success = (val >= cmp);
+ break;
+
+ case CHECK_LTE:
+ success = (val <= cmp);
+ break;
+
+ case CHECK_ALL:
+ success = ((val & cmp) == cmp);
+ break;
+
+ case CHECK_GT0:
+ success = ((val & cmp) != 0);
+ break;
+
+ case CHECK_NONE:
+ success = ((val & cmp) == 0);
+ break;
+ }
+
+ if ( not_flag )
+ {
+ DebugMessage(DEBUG_PATTERN_MATCH,
+ "checking for not success...flag\n");
+
+ success = !success;
+ }
+
+ return success;
+}
+
+
class ByteTestOption : public IpsOption
{
public:
int ByteTestOption::eval(Cursor& c, Packet*)
{
- ByteTestData* btd = (ByteTestData*)&config;
- int rval = DETECTION_OPTION_NO_MATCH;
- uint32_t value = 0;
- int success = 0;
- const uint8_t* start_ptr;
- int payload_bytes_grabbed;
- int offset;
- uint32_t cmp_value;
+ PERF_PROFILE(byteTestPerfStats);
- PROFILE_VARS;
- MODULE_PROFILE_START(byteTestPerfStats);
+ ByteTestData* btd = (ByteTestData*)&config;
+ uint32_t cmp_value = 0;
- /* Get values from byte_extract variables, if present. */
+ // Get values from byte_extract variables, if present.
if (btd->cmp_value_var >= 0 && btd->cmp_value_var < NUM_BYTE_EXTRACT_VARS)
{
uint32_t val;
GetByteExtractValue(&val, btd->cmp_value_var);
cmp_value = val;
}
+
else
cmp_value = btd->cmp_value;
+ int offset = 0;
+
if (btd->offset_var >= 0 && btd->offset_var < NUM_BYTE_EXTRACT_VARS)
{
uint32_t val;
GetByteExtractValue(&val, btd->offset_var);
offset = (int32_t)val;
}
- else
- offset = btd->offset;
- if ( btd->relative_flag )
- start_ptr = c.start();
else
- start_ptr = c.buffer();
+ offset = btd->offset;
+ const uint8_t* start_ptr = btd->relative_flag ? c.start() : c.buffer();
start_ptr += offset;
- /* both of these functions below perform their own bounds checking within
- * byte_extract.c
- */
+ uint32_t value = 0;
+ int payload_bytes_grabbed = 0;
if (!btd->data_string_convert_flag)
{
if ( byte_extract(
btd->endianess, btd->bytes_to_compare,
start_ptr, c.buffer(), c.endo(), &value))
- {
- MODULE_PROFILE_END(byteTestPerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
#ifdef DEBUG
payload_bytes_grabbed = (int)btd->bytes_to_compare;
#endif
DebugMessage(DEBUG_PATTERN_MATCH,
"String Extraction Failed\n");
- MODULE_PROFILE_END(byteTestPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
}
"Grabbed %d bytes at offset %d, value = 0x%08X(%u)\n",
payload_bytes_grabbed, btd->offset, value, value);
- switch (btd->opcode)
- {
- case CHECK_LT:
- success = (value < cmp_value);
- break;
-
- case CHECK_EQ:
- success = (value == cmp_value);
- break;
-
- case CHECK_GT:
- success = (value > cmp_value);
- break;
-
- case CHECK_AND:
- success = ((value & cmp_value) > 0);
- break;
-
- case CHECK_XOR:
- success = ((value ^ cmp_value) > 0);
- break;
-
- case CHECK_GTE:
- success = (value >= cmp_value);
- break;
-
- case CHECK_LTE:
- success = (value <= cmp_value);
- break;
-
- case CHECK_ALL:
- success = ((value & cmp_value) == cmp_value);
- break;
-
- case CHECK_GT0:
- success = ((value & cmp_value) != 0);
- break;
-
- case CHECK_NONE:
- success = ((value & cmp_value) == 0);
- break;
- }
-
- if (btd->not_flag)
- {
- DebugMessage(DEBUG_PATTERN_MATCH,
- "checking for not success...flag\n");
- if (!success)
- {
- rval = DETECTION_OPTION_MATCH;
- }
- }
- else if (success)
- {
- rval = DETECTION_OPTION_MATCH;
- }
+ if ( byte_test_check(btd->opcode, value, cmp_value, btd->not_flag) )
+ return DETECTION_OPTION_MATCH;
- /* if the test isn't successful, this function *must* return 0 */
- MODULE_PROFILE_END(byteTestPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
static int CheckANDPatternMatch(PatternMatchData* idx, Cursor& c)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- int found = 0;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(contentPerfStats);
+ PERF_PROFILE(contentPerfStats);
DebugMessage(DEBUG_PATTERN_MATCH, "CheckPatternANDMatch: ");
- found = uniSearchReal(idx, c);
+ int found = uniSearchReal(idx, c);
if ( found == -1 )
{
if ( found )
{
- rval = DETECTION_OPTION_MATCH;
DebugMessage(DEBUG_PATTERN_MATCH, "Pattern match found\n");
+ return DETECTION_OPTION_MATCH;
}
+
else
{
DebugMessage(DEBUG_PATTERN_MATCH, "Pattern match failed\n");
+ return DETECTION_OPTION_NO_MATCH;
}
-
- MODULE_PROFILE_END(contentPerfStats);
- return rval;
}
PatternMatchData* content_get_data(void* pv)
// Test the packet's payload size against the rule payload size value
int DsizeOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(dsizePerfStats);
+ PERF_PROFILE(dsizePerfStats);
/* fake packet dsizes are always wrong
(unless they are PDUs) */
- if (
- (p->packet_flags & PKT_REBUILT_STREAM) &&
- !(p->packet_flags & PKT_PDU_HEAD) )
- {
- MODULE_PROFILE_END(dsizePerfStats);
- return rval;
- }
+ if ((p->packet_flags & PKT_REBUILT_STREAM) && !p->is_pdu_start())
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->dsize) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(dsizePerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int FileDataOption::eval(Cursor& c, Packet*)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- uint8_t* data;
- uint16_t len;
+ PERF_PROFILE(fileDataPerfStats);
- PROFILE_VARS;
- MODULE_PROFILE_START(fileDataPerfStats);
+ uint8_t* data = g_file_data.data;
+ uint16_t len = g_file_data.len;
- data = g_file_data.data;
- len = g_file_data.len;
-
- if ( (data == NULL)|| (len == 0) )
- {
- MODULE_PROFILE_END(fileDataPerfStats);
- return rval;
- }
+ if ( !data || !len )
+ return DETECTION_OPTION_NO_MATCH;
c.set(s_name, data, len);
- rval = DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(fileDataPerfStats);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
//-------------------------------------------------------------------------
int TcpFlagOption::eval(Cursor&, Packet* p)
{
- TcpFlagCheckData* flagptr = &config;
- int rval = DETECTION_OPTION_NO_MATCH;
- u_char tcp_flags;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(tcpFlagsPerfStats);
+ PERF_PROFILE(tcpFlagsPerfStats);
+ // if error appeared when tcp header was processed,
+ // test fails automagically.
if (!p->ptrs.tcph)
- {
- /* if error appeared when tcp header was processed,
- * test fails automagically */
- MODULE_PROFILE_END(tcpFlagsPerfStats);
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
/* the flags we really want to check are all the ones
*/
- tcp_flags = p->ptrs.tcph->th_flags & (0xFF ^ flagptr->tcp_mask);
+ TcpFlagCheckData* flagptr = &config;
+ u_char tcp_flags = p->ptrs.tcph->th_flags & (0xFF ^ flagptr->tcp_mask);
DebugMessage(DEBUG_IPS_OPTION, " <!!> CheckTcpFlags: ");
if (flagptr->tcp_flags == tcp_flags) /* only these set */
{
DebugMessage(DEBUG_IPS_OPTION,"Got TCP [default] flag match!\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
if ((flagptr->tcp_flags & tcp_flags) == flagptr->tcp_flags)
{
DebugMessage(DEBUG_IPS_OPTION, "Got TCP [ALL] flag match!\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
if ((flagptr->tcp_flags & tcp_flags) == 0) /* none set */
{
DebugMessage(DEBUG_IPS_OPTION,"Got TCP [NOT] flag match!\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
if ((flagptr->tcp_flags & tcp_flags) != 0) /* something set */
{
DebugMessage(DEBUG_IPS_OPTION,"Got TCP [ANY] flag match!\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
break;
}
- MODULE_PROFILE_END(tcpFlagsPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int FlowCheckOption::eval(Cursor&, Packet* p)
{
- FlowCheckData* fcd = &config;
- PROFILE_VARS;
+ PERF_PROFILE(flowCheckPerfStats);
- MODULE_PROFILE_START(flowCheckPerfStats);
+ FlowCheckData* fcd = &config;
- /* Check established/unestablished first */
+ // Check established/unestablished first
{
if ((fcd->established == 1) && !(p->packet_flags & PKT_STREAM_EST))
{
- /*
- ** This option requires an established connection and it isn't
- ** in that state yet, so no match.
- */
- MODULE_PROFILE_END(flowCheckPerfStats);
+ // This option requires an established connection and it isn't
+ // in that state yet, so no match.
return DETECTION_OPTION_NO_MATCH;
}
else if ((fcd->unestablished == 1) && (p->packet_flags & PKT_STREAM_EST))
{
- /*
- ** We're looking for an unestablished stream, and this is
- ** established, so don't continue processing.
- */
- MODULE_PROFILE_END(flowCheckPerfStats);
+ // We're looking for an unestablished stream, and this is
+ // established, so don't continue processing.
return DETECTION_OPTION_NO_MATCH;
}
}
- /* Now check from client */
+ // Now check from client
if (fcd->from_client)
{
{
- if (!(p->packet_flags & PKT_FROM_CLIENT) &&
- (p->packet_flags & PKT_FROM_SERVER))
+ if (!p->from_client() && p->from_server())
{
- /* No match on from_client */
- MODULE_PROFILE_END(flowCheckPerfStats);
+ // No match on from_client
return DETECTION_OPTION_NO_MATCH;
}
}
}
- /* And from server */
+ // And from server
if (fcd->from_server)
{
{
- if (!(p->packet_flags & PKT_FROM_SERVER) &&
- (p->packet_flags & PKT_FROM_CLIENT))
+ if (!p->from_server() && p->from_client())
{
- /* No match on from_server */
- MODULE_PROFILE_END(flowCheckPerfStats);
+ // No match on from_server
return DETECTION_OPTION_NO_MATCH;
}
}
}
- /* ...ignore_reassembled */
+ // ...ignore_reassembled
if (fcd->ignore_reassembled & IGNORE_STREAM)
{
if (p->packet_flags & PKT_REBUILT_STREAM)
{
- MODULE_PROFILE_END(flowCheckPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
}
{
if (p->packet_flags & PKT_REBUILT_FRAG)
{
- MODULE_PROFILE_END(flowCheckPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
}
- /* ...only_reassembled */
+ // ...only_reassembled
if (fcd->only_reassembled & ONLY_STREAM)
{
if ( !(p->packet_flags & PKT_REBUILT_STREAM) && !p->is_full_pdu() )
{
- MODULE_PROFILE_END(flowCheckPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
}
{
if (!(p->packet_flags & PKT_REBUILT_FRAG))
{
- MODULE_PROFILE_END(flowCheckPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
}
- MODULE_PROFILE_END(flowCheckPerfStats);
return DETECTION_OPTION_MATCH;
}
int FlowBitsOption::eval(Cursor&, Packet* p)
{
- FLOWBITS_OP* flowbits = config;
- int rval = DETECTION_OPTION_NO_MATCH;
+ PERF_PROFILE(flowBitsPerfStats);
- PROFILE_VARS;
+ FLOWBITS_OP* flowbits = config;
if (!flowbits)
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(flowBitsPerfStats);
- rval = check_flowbits(flowbits->type, (uint8_t)flowbits->eval,
+ return check_flowbits(flowbits->type, (uint8_t)flowbits->eval,
flowbits->ids, flowbits->num_ids, flowbits->group, p);
-
- MODULE_PROFILE_END(flowBitsPerfStats);
- return rval;
}
//-------------------------------------------------------------------------
int FragBitsOption::eval(Cursor&, Packet* p)
{
+ PERF_PROFILE(fragBitsPerfStats);
+
FragBitsData* fb = &config;
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
- if(!p->ptrs.ip_api.is_ip())
- {
- return rval;
- }
+ if ( !p->has_ip() )
+ return DETECTION_OPTION_NO_MATCH;
+
const uint16_t frag_offset = p->ptrs.ip_api.off_w_flags();
- MODULE_PROFILE_START(fragBitsPerfStats);
+
DebugMessage(DEBUG_IPS_OPTION, " <!!> CheckFragBits: ");
DebugFormat(DEBUG_IPS_OPTION, "[rule: 0x%X:%d pkt: 0x%X] ",
if (fb->frag_bits == (frag_offset & bitmask))
{
DebugMessage(DEBUG_IPS_OPTION,"Got Normal bits match\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
DebugMessage(DEBUG_IPS_OPTION,"Normal test failed\n");
}
+
break;
case FB_NOT:
if ((fb->frag_bits & (frag_offset & bitmask)) == 0)
{
DebugMessage(DEBUG_IPS_OPTION,"Got NOT bits match\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
if ((fb->frag_bits & (frag_offset & bitmask)) == fb->frag_bits)
{
DebugMessage(DEBUG_IPS_OPTION,"Got ALL bits match\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
if ((fb->frag_bits & (frag_offset & bitmask)) != 0)
{
DebugMessage(DEBUG_IPS_OPTION,"Got ANY bits match\n");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
else
{
DebugMessage(DEBUG_IPS_OPTION,"ANY test failed\n");
}
break;
+
default:
break;
}
/* if the test isn't successful, this function *must* return 0 */
- MODULE_PROFILE_END(fragBitsPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int FragOffsetOption::eval(Cursor&, Packet* p)
{
- int p_offset = p->ptrs.ip_api.off();
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(fragOffsetPerfStats);
if (!p->has_ip())
- {
- return rval;
- }
+ return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(fragOffsetPerfStats);
- if ( config.eval(p_offset) )
- rval = DETECTION_OPTION_MATCH;
+ if ( !config.eval(p->ptrs.ip_api.off()) )
+ return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_END(fragOffsetPerfStats);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
//-------------------------------------------------------------------------
int HashOption::eval(Cursor& c, Packet*)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(hash_ps[idx]);
+ auto& hash_option_stats = hash_ps[idx];
+ PERF_PROFILE(hash_option_stats);
- int rval = DETECTION_OPTION_NO_MATCH;
int found = match(c);
if ( found == -1 )
which is not what we want. */
found = 0;
}
+
else
- {
found ^= config->negated;
- }
if ( found )
- {
- rval = DETECTION_OPTION_MATCH;
- }
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(hash_ps[idx]);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int HttpIpsOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(http_ps[idx]);
+ auto& http_option_stats = http_ps[idx];
+ PERF_PROFILE(http_option_stats);
- int rval;
InspectionBuffer hb;
if ( !p->flow || !p->flow->gadget )
- rval = DETECTION_OPTION_NO_MATCH;
+ return DETECTION_OPTION_NO_MATCH;
// FIXIT-P cache id at parse time for runtime use
else if ( !p->flow->gadget->get_buf(key, p, hb) )
- rval = DETECTION_OPTION_NO_MATCH;
+ return DETECTION_OPTION_NO_MATCH;
- else
- {
- c.set(key, hb.data, hb.len);
- rval = DETECTION_OPTION_MATCH;
- }
+ c.set(key, hb.data, hb.len);
- MODULE_PROFILE_END(http_ps[idx]);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
//-------------------------------------------------------------------------
int HttpHeaderOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(httpHeaderPerfStats);
+ PERF_PROFILE(httpHeaderPerfStats);
- int rval;
InspectionBuffer hb;
if ( !p->flow || !p->flow->gadget )
- rval = DETECTION_OPTION_NO_MATCH;
+ return DETECTION_OPTION_NO_MATCH;
// FIXIT-P cache id at parse time for runtime use
- else if ( !p->flow->gadget->get_buf(s_name, p, hb) )
- rval = DETECTION_OPTION_NO_MATCH;
+ if ( !p->flow->gadget->get_buf(s_name, p, hb) )
+ return DETECTION_OPTION_NO_MATCH;
- else if ( !name.size() )
+ if ( !name.size() )
{
c.set(s_name, hb.data, hb.len);
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
- else if ( find(name, hb, c) )
- rval = DETECTION_OPTION_MATCH;
- else
- rval = DETECTION_OPTION_NO_MATCH;
+ if ( find(name, hb, c) )
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(httpHeaderPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int IcmpIdOption::eval(Cursor&, Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(icmpIdPerfStats);
if (!p->ptrs.icmph)
return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(icmpIdPerfStats);
if ( (p->ptrs.icmph->type == ICMP_ECHO ||
p->ptrs.icmph->type == ICMP_ECHOREPLY) ||
(uint16_t)p->ptrs.icmph->type == icmp::Icmp6Types::REPLY_6) )
{
if ( config.eval(p->ptrs.icmph->s_icmp_id) )
- {
- MODULE_PROFILE_END(icmpIdPerfStats);
return DETECTION_OPTION_MATCH;
- }
}
- MODULE_PROFILE_END(icmpIdPerfStats);
+
return DETECTION_OPTION_NO_MATCH;
}
int IcmpSeqOption::eval(Cursor&, Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(icmpSeqPerfStats);
if (!p->ptrs.icmph)
return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(icmpSeqPerfStats);
-
if ( (p->ptrs.icmph->type == ICMP_ECHO ||
p->ptrs.icmph->type == ICMP_ECHOREPLY) ||
((uint16_t)p->ptrs.icmph->type == icmp::Icmp6Types::ECHO_6 ||
{
if ( config.eval(p->ptrs.icmph->s_icmp_seq) )
{
- MODULE_PROFILE_END(icmpSeqPerfStats);
return DETECTION_OPTION_MATCH;
}
}
- MODULE_PROFILE_END(icmpSeqPerfStats);
+
return DETECTION_OPTION_NO_MATCH;
}
int IcodeOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(icmpCodePerfStats);
- /* return 0 if we don't have an icmp header */
+ // return 0 if we don't have an icmp header
if (!p->ptrs.icmph)
- return rval;
-
- MODULE_PROFILE_START(icmpCodePerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.icmph->code) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(icmpCodePerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int IpIdOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(ipIdPerfStats);
if (!p->has_ip())
- return rval;
-
- MODULE_PROFILE_START(ipIdPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.ip_api.id()) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(ipIdPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int IpProtoOption::eval(Cursor&, Packet* p)
{
+ PERF_PROFILE(ipProtoPerfStats);
+
IpProtoData* ipd = &config;
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
if (!p->has_ip())
{
DebugMessage(DEBUG_IPS_OPTION,"Not IP\n");
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
- MODULE_PROFILE_START(ipProtoPerfStats);
-
const uint8_t ip_proto = p->get_ip_proto_next();
switch (ipd->comparison_flag)
{
case IP_PROTO__EQUAL:
if (ip_proto == ipd->protocol)
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
+
break;
case IP_PROTO__NOT_EQUAL:
if (ip_proto != ipd->protocol)
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
+
break;
case IP_PROTO__GREATER_THAN:
if (ip_proto > ipd->protocol)
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
+
break;
case IP_PROTO__LESS_THAN:
if (ip_proto < ipd->protocol)
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
+
break;
default:
}
/* if the test isn't successful, this function *must* return 0 */
- MODULE_PROFILE_END(ipProtoPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int IpOptOption::eval(Cursor&, Packet* p)
{
+ PERF_PROFILE(ipOptionPerfStats);
+
IpOptionData* ipOptionData = &config;
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
DebugMessage(DEBUG_IPS_OPTION, "CheckIpOptions:");
- if (!p->ptrs.ip_api.is_ip4())
- return rval; /* if error occured while ip header
- * was processed, return 0 automatically. */
- MODULE_PROFILE_START(ipOptionPerfStats);
+ if ( !p->is_ip4() )
+ // if error occured while ip header
+ // was processed, return 0 automatically.
+ return DETECTION_OPTION_NO_MATCH;
const ip::IP4Hdr* const ip4h = p->ptrs.ip_api.get_ip4h();
const uint8_t option_len = ip4h->get_opt_len();
if ((ipOptionData->any_flag == 1) && (option_len > 0))
{
DebugMessage(DEBUG_IPS_OPTION, "Matched any ip options!\n");
- rval = DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(ipOptionPerfStats);
- return rval;
+ return DETECTION_OPTION_MATCH;
}
ip::IpOptionIterator iter(ip4h, p);
static_cast<int>(opt.code));
if (ipOptionData->ip_option == opt.code)
- {
- rval = DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(ipOptionPerfStats);
- return rval;
- }
+ return DETECTION_OPTION_MATCH;
+
}
- /* if the test isn't successful, return 0 */
- MODULE_PROFILE_END(ipOptionPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int IsDataAtOption::eval(Cursor& c, Packet*)
{
+ PERF_PROFILE(isDataAtPerfStats);
+
IsDataAtData* isdata = &config;
- int rval = DETECTION_OPTION_NO_MATCH;
- const uint8_t* start_ptr;
- int offset;
- PROFILE_VARS;
- MODULE_PROFILE_START(isDataAtPerfStats);
+ int offset;
- /* Get values from byte_extract variables, if present. */
+ // Get values from byte_extract variables, if present.
if (isdata->offset_var >= 0 && isdata->offset_var < NUM_BYTE_EXTRACT_VARS)
{
uint32_t value;
else
offset = isdata->offset;
+ const uint8_t* start_ptr;
if ( isdata->flags & ISDATAAT_RELATIVE_FLAG )
{
start_ptr = c.start();
}
start_ptr += offset;
+ int rval = DETECTION_OPTION_NO_MATCH;
if (inBounds(c.buffer(), c.endo(), start_ptr))
{
DebugMessage(DEBUG_PATTERN_MATCH,
rval = !rval;
}
- /* otherwise dump */
- MODULE_PROFILE_END(isDataAtPerfStats);
+ // otherwise dump
return rval;
}
int IcmpTypeOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(icmpTypePerfStats);
- /* return 0 if we don't have an icmp header */
+ // return 0 if we don't have an icmp header
if (!p->ptrs.icmph)
- return rval;
-
- MODULE_PROFILE_START(icmpTypePerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.icmph->type) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(icmpTypePerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int LuaJitOption::eval(Cursor& c, Packet*)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(luaIpsPerfStats);
+ PERF_PROFILE(luaIpsPerfStats);
cursor = &c;
{
const char* err = lua_tostring(L, -1);
ErrorMessage("%s\n", err);
- MODULE_PROFILE_END(luaIpsPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
- bool result = lua_toboolean(L, -1);
+ if ( lua_toboolean(L, -1) )
+ return DETECTION_OPTION_MATCH;
- int ret = result ? DETECTION_OPTION_MATCH : DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_END(luaIpsPerfStats);
-
- return ret;
+ return DETECTION_OPTION_NO_MATCH;
}
}
int PcreOption::eval(Cursor& c, Packet*)
{
- PcreData* pcre_data = config;
- int found_offset = -1; /* where is the ending location of the pattern */
- bool matched = false;
+ PERF_PROFILE(pcrePerfStats);
- PROFILE_VARS;
- MODULE_PROFILE_START(pcrePerfStats);
+ PcreData* pcre_data = config;
// short circuit this for testing pcre performance impact
if (SnortConfig::no_pcre())
- {
- MODULE_PROFILE_END(pcrePerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
unsigned pos = c.get_delta();
if ( pos > c.size() )
return 0;
- matched = pcre_search(pcre_data, c.buffer(), c.size(), pos, &found_offset);
+ int found_offset = -1; // where is the ending location of the pattern
+ bool matched = pcre_search(pcre_data, c.buffer(), c.size(), pos,
+ &found_offset);
if (matched)
{
c.set_pos(found_offset);
c.set_delta(found_offset);
}
- MODULE_PROFILE_END(pcrePerfStats);
+
return DETECTION_OPTION_MATCH;
}
- MODULE_PROFILE_END(pcrePerfStats);
return DETECTION_OPTION_NO_MATCH;
}
int PktDataOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(pktDataPerfStats);
+ PERF_PROFILE(pktDataPerfStats);
c.reset(p);
-
- MODULE_PROFILE_END(pktDataPerfStats);
return DETECTION_OPTION_MATCH;
}
int RawDataOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(rawDataPerfStats);
+ PERF_PROFILE(rawDataPerfStats);
c.set(s_name, p->data, p->dsize);
-
- MODULE_PROFILE_END(rawDataPerfStats);
return DETECTION_OPTION_MATCH;
}
int ReplaceOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(replacePerfStats);
+ PERF_PROFILE(replacePerfStats);
if ( p->is_cooked() )
return false;
store(c.get_pos() - repl.size());
- MODULE_PROFILE_END(replacePerfStats);
return DETECTION_OPTION_MATCH;
}
void ReplaceOption::action(Packet*)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(replacePerfStats);
+ PERF_PROFILE(replacePerfStats);
if ( pending() )
Replace_QueueChange(repl, (unsigned)pos());
-
- MODULE_PROFILE_END(replacePerfStats);
}
//-------------------------------------------------------------------------
int RpcOption::eval(Cursor&, Packet* p)
{
+ PERF_PROFILE(rpcCheckPerfStats);
+
RpcCheckData* ds_ptr = &config;
- unsigned char* c=(unsigned char*)p->data;
- u_long rpcvers, prog, vers, proc;
- enum msg_type direction;
- int rval = DETECTION_OPTION_NO_MATCH;
-#ifdef DEBUG_MSGS
- int i;
-#endif
- PROFILE_VARS;
if (!(p->is_tcp() || p->is_udp()))
- return 0; /* if error occured while ip header
- * was processed, return 0 automagically. */
+ return DETECTION_OPTION_NO_MATCH;
- MODULE_PROFILE_START(rpcCheckPerfStats);
+ auto c = p->data;
if ( p->is_tcp() )
{
if (p->dsize<28)
{
DebugMessage(DEBUG_IPS_OPTION, "RPC packet too small");
- MODULE_PROFILE_END(rpcCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
}
else
if (p->dsize<24)
{
DebugMessage(DEBUG_IPS_OPTION, "RPC packet too small");
- MODULE_PROFILE_END(rpcCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
}
#ifdef DEBUG_MSGS
DebugMessage(DEBUG_IPS_OPTION,"<---xid---> <---dir---> <---rpc--->"
" <---prog--> <---vers--> <---proc-->\n");
- for (i=0; i<24; i++)
+ for (int i = 0; i < 24; i++)
{
DebugFormat(DEBUG_IPS_OPTION, "%02X ",c[i]);
}
+
DebugMessage(DEBUG_IPS_OPTION,"\n");
#endif
(void)IXDR_GET_LONG (c);
/* Read direction : CALL or REPLY */
- direction = IXDR_GET_ENUM (c, enum msg_type);
+ enum msg_type direction = IXDR_GET_ENUM (c, enum msg_type);
/* We only look at calls */
if (direction != CALL)
{
DebugMessage(DEBUG_IPS_OPTION, "RPC packet not a call");
- MODULE_PROFILE_END(rpcCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
/* Read the RPC message version */
- rpcvers = IXDR_GET_LONG (c);
+ u_long rpcvers = IXDR_GET_LONG (c);
/* Fail if it is not right */
if (rpcvers != RPC_MSG_VERSION)
{
DebugMessage(DEBUG_IPS_OPTION,"RPC msg version invalid");
- MODULE_PROFILE_END(rpcCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
/* Read the program number, version, and procedure */
- prog = IXDR_GET_LONG (c);
- vers = IXDR_GET_LONG (c);
- proc = IXDR_GET_LONG (c);
+ u_long prog = IXDR_GET_LONG (c);
+ u_long vers = IXDR_GET_LONG (c);
+ u_long proc = IXDR_GET_LONG (c);
DebugFormat(DEBUG_IPS_OPTION,"RPC decoded to: %lu %lu %lu\n",
prog,vers,proc);
{
DebugMessage(DEBUG_IPS_OPTION,"RPC proc matches");
DebugMessage(DEBUG_IPS_OPTION, "Yippee! Found one!");
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
}
}
}
}
/* if the test isn't successful, return 0 */
- MODULE_PROFILE_END(rpcCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int TcpSeqOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(tcpSeqPerfStats);
if (!p->ptrs.tcph)
- return rval;
-
- MODULE_PROFILE_START(tcpSeqPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.tcph->th_seq) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(tcpSeqPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int SessionOption::eval(Cursor&, Packet* p)
{
+ PERF_PROFILE(sessionPerfStats);
+
SessionData* session_data = &config;
- FILE* session; /* session file ptr */
- PROFILE_VARS;
- MODULE_PROFILE_START(sessionPerfStats);
+ if ( !p || !p->dsize || !p->data )
+ return DETECTION_OPTION_MATCH;
- /* if there's data in this packet */
- if (p != NULL)
- {
- if ((p->dsize != 0 && p->data != NULL) || (!(p->ptrs.decode_flags & DECODE_FRAG)))
- {
- session = OpenSessionFile(p);
+ if ( p->is_fragment() )
+ return DETECTION_OPTION_MATCH;
- if (session == NULL)
- {
- MODULE_PROFILE_END(sessionPerfStats);
- return DETECTION_OPTION_MATCH;
- }
+ // FIXIT-M should wrap file open/close in a class to ensure cleanup
+ {
+ FILE* session = OpenSessionFile(p);
+ if ( !session )
+ return DETECTION_OPTION_MATCH;
- DumpSessionData(session, p, session_data);
+ DumpSessionData(session, p, session_data);
- fclose(session);
- }
+ fclose(session);
}
- MODULE_PROFILE_END(sessionPerfStats);
return DETECTION_OPTION_MATCH;
}
int SoOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(soPerfStats);
-
- int ret = func(data, c, p);
-
- MODULE_PROFILE_END(soPerfStats);
- return ret;
+ PERF_PROFILE(soPerfStats);
+ return func(data, c, p);
}
//-------------------------------------------------------------------------
int IpTosOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(ipTosPerfStats);
if(!p->ptrs.ip_api.is_ip())
- return rval;
-
- MODULE_PROFILE_START(ipTosPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.ip_api.tos()) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(ipTosPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int TtlOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(ttlCheckPerfStats);
if(!p->ptrs.ip_api.is_ip())
- return rval;
-
- MODULE_PROFILE_START(ttlCheckPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.ip_api.ttl()) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(ttlCheckPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int TcpWinOption::eval(Cursor&, Packet* p)
{
- int rval = DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
+ PERF_PROFILE(tcpWinPerfStats);
if (!p->ptrs.tcph)
- return rval;
-
- MODULE_PROFILE_START(tcpWinPerfStats);
+ return DETECTION_OPTION_NO_MATCH;
if ( config.eval(p->ptrs.tcph->th_win) )
- rval = DETECTION_OPTION_MATCH;
+ return DETECTION_OPTION_MATCH;
- MODULE_PROFILE_END(tcpWinPerfStats);
- return rval;
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
void LuaJitLogger::alert(Packet* p, const char*, Event* e)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(luaLogPerfStats);
+ PERF_PROFILE(luaLogPerfStats);
packet = p;
event = e;
lua_State* L = states[get_instance_id()];
- {
- Lua::ManageStack ms(L, 1);
-
- lua_getglobal(L, "alert");
+ Lua::ManageStack ms(L, 1);
- if ( lua_pcall(L, 0, 1, 0) )
- {
- const char* err = lua_tostring(L, -1);
- ErrorMessage("%s\n", err);
- MODULE_PROFILE_END(luaLogPerfStats);
- }
+ lua_getglobal(L, "alert");
+ if ( lua_pcall(L, 0, 1, 0) )
+ {
+ const char* err = lua_tostring(L, -1);
+ ErrorMessage("%s\n", err);
}
-
- MODULE_PROFILE_END(luaLogPerfStats);
}
//-------------------------------------------------------------------------
static void register_profiles()
{
#ifdef PERF_PROFILING
- RegisterProfile("detect", nullptr, get_profile);
- RegisterProfile("mpse", "detect", get_profile);
- RegisterProfile("rule eval", "detect", get_profile);
- RegisterProfile("rtn eval", "rule eval", get_profile);
- RegisterProfile("rule tree eval", "rule eval", get_profile);
- RegisterProfile("decode", nullptr, get_profile);
- RegisterProfile("eventq", nullptr, get_profile);
- RegisterProfile("total", nullptr, get_profile);
- RegisterProfile("daq meta", nullptr, get_profile);
+ PerfProfilerManager::register_module("detect", nullptr, get_profile);
+ PerfProfilerManager::register_module("mpse", "detect", get_profile);
+ PerfProfilerManager::register_module("rule eval", "detect", get_profile);
+ PerfProfilerManager::register_module("rtn eval", "rule eval", get_profile);
+ PerfProfilerManager::register_module("rule tree eval", "rule eval", get_profile);
+ PerfProfilerManager::register_module("decode", nullptr, get_profile);
+ PerfProfilerManager::register_module("eventq", nullptr, get_profile);
+ PerfProfilerManager::register_module("total", nullptr, get_profile);
+ PerfProfilerManager::register_module("daq meta", nullptr, get_profile);
#endif
}
periodic_release();
#ifdef PERF_PROFILING
- CleanupProfileStatsNodeList();
+ PerfProfilerManager::term();
#endif
/* free allocated memory */
DAQ_Delete();
#ifdef PERF_PROFILING
- ReleaseProfileStats();
+ PerfProfilerManager::consolidate_stats();
#endif
otnx_match_data_term();
DAQ_Verdict Snort::packet_callback(
void*, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
{
- int inject = 0;
- PROFILE_VARS;
+ PERF_PROFILE(totalPerfStats);
- MODULE_PROFILE_START(totalPerfStats);
pc.total_from_daq++;
rule_eval_pkt_count++;
packet_time_update(&pkthdr->ts);
if ( snort_conf->pkt_skip && pc.total_from_daq <= snort_conf->pkt_skip )
- {
- MODULE_PROFILE_END(totalPerfStats);
return DAQ_VERDICT_PASS;
- }
- MODULE_PROFILE_START(eventqPerfStats);
- SnortEventqReset();
- MODULE_PROFILE_END(eventqPerfStats);
+ PERF_PROFILE_BLOCK(eventqPerfStats)
+ {
+ SnortEventqReset();
+ }
sfthreshold_reset();
ActionManager::reset_queue();
DAQ_Verdict verdict = process_packet(s_packet, pkthdr, pkt);
ActionManager::execute(s_packet);
+
+ int inject = 0;
verdict = update_verdict(verdict, inject);
UpdateWireStats(&sfBase, pkthdr->caplen, Active::packet_was_dropped(), inject);
else if ( break_time() )
DAQ_BreakLoop(0);
- MODULE_PROFILE_END(totalPerfStats);
return verdict;
}
s_modules.push_back(mh);
#ifdef PERF_PROFILING
- RegisterProfile(m);
+ PerfProfilerManager::register_module(m);
#endif
}
void ArpSpoof::eval(Packet* p)
{
- IPMacEntry* ipme;
- PROFILE_VARS;
- const arp::EtherARP* ah;
- const eth::EtherHdr* eh;
+ PERF_PROFILE(arpPerfStats);
// preconditions - what we registered for
assert(p->type() == PktType::ARP);
assert(p->proto_bits & PROTO_BIT__ETH);
- ah = layer::get_arp_layer(p);
- eh = layer::get_eth_layer(p);
+ const arp::EtherARP* ah = layer::get_arp_layer(p);
+ const eth::EtherHdr* eh = layer::get_eth_layer(p);
/* is the ARP protocol type IP and the ARP hardware type Ethernet? */
if ((ntohs(ah->ea_hdr.ar_hrd) != 0x0001) ||
(ntohs(ah->ea_hdr.ar_pro) != ETHERNET_TYPE_IP))
return;
- MODULE_PROFILE_START(arpPerfStats);
++asstats.total_packets;
switch (ntohs(ah->ea_hdr.ar_op))
}
break;
}
- MODULE_PROFILE_END(arpPerfStats);
/* return if the overwrite list hasn't been initialized */
if (!config->check_overwrite)
return;
- if ((ipme = LookupIPMacEntryByIP(config->ipmel,
- ah->arp_spa32)) == NULL)
- {
- DebugMessage(DEBUG_INSPECTOR,
- "MODNAME: LookupIPMacEntryByIp returned NULL\n");
- return;
- }
- else
+ IPMacEntry* ipme = LookupIPMacEntryByIP(config->ipmel, ah->arp_spa32);
+ if ( ipme )
{
DebugFormat(DEBUG_INSPECTOR,
"MODNAME: LookupIPMacEntryByIP returned %p\n", ipme);
- /* If the Ethernet source address or the ARP source hardware address
- * in p doesn't match the MAC address in ipme, then generate an alert
- */
- if ((memcmp((uint8_t*)eh->ether_src,
- (uint8_t*)ipme->mac_addr, 6)) ||
- (memcmp((uint8_t*)ah->arp_sha,
- (uint8_t*)ipme->mac_addr, 6)))
+ auto cmp_ether_src = memcmp(eh->ether_src, ipme->mac_addr, 6);
+ auto cmp_arp_sha = memcmp(ah->arp_sha, ipme->mac_addr, 6);
+
+ // If the Ethernet source address or the ARP source hardware address
+ // in p doesn't match the MAC address in ipme, then generate an alert
+ if ( cmp_ether_src || cmp_arp_sha )
{
- SnortEventqAdd(GID_ARP_SPOOF,
- ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK);
+ SnortEventqAdd(GID_ARP_SPOOF, ARPSPOOF_ARP_CACHE_OVERWRITE_ATTACK);
DebugMessage(DEBUG_INSPECTOR,
"MODNAME: Attempted ARP cache overwrite attack\n");
-
- return;
}
}
+
+ else
+ DebugMessage(DEBUG_INSPECTOR,
+ "MODNAME: LookupIPMacEntryByIp returned NULL\n");
}
//-------------------------------------------------------------------------
void Normalizer::eval(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(norm_perf_stats);
+ PERF_PROFILE(norm_perf_stats);
if ( !p->is_rebuilt() && !Active::packet_was_dropped() )
Norm_Packet(&config, p);
-
- MODULE_PROFILE_END(norm_perf_stats);
}
//-------------------------------------------------------------------------
void PerfMonitor::eval(Packet* p)
{
+ PERF_PROFILE(perfmonStats);
+
static THREAD_LOCAL bool first = true;
- PROFILE_VARS;
- MODULE_PROFILE_START(perfmonStats);
+
if (first)
{
sfPerformanceStats(&config, p);
++pmstats.total_packets;
-
- MODULE_PROFILE_END(perfmonStats);
}
//-------------------------------------------------------------------------
void PortScan::eval(Packet* p)
{
- PS_PKT ps_pkt;
- PROFILE_VARS;
+ PERF_PROFILE(psPerfStats);
assert(p->ptrs.ip_api.is_ip());
if ( p->packet_flags & PKT_REBUILT_STREAM )
return;
- MODULE_PROFILE_START(psPerfStats);
++spstats.total_packets;
+ PS_PKT ps_pkt;
memset(&ps_pkt, 0x00, sizeof(PS_PKT)); // FIXIT-P don't zap unless necessary
ps_pkt.pkt = (void*)p;
{
PortscanAlert(&ps_pkt, &ps_pkt.scanned->proto, ps_pkt.proto);
}
-
- MODULE_PROFILE_END(psPerfStats);
}
//-------------------------------------------------------------------------
void PacketManager::decode(
Packet* p, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt, bool cooked)
{
- PROFILE_VARS;
+ PERF_PROFILE(decodePerfStats);
+
DecodeData unsure_encap_ptrs;
uint8_t mapped_prot = CodecManager::grinder;
p->ptrs.reset();
layer::set_packet_pointer(p);
- MODULE_PROFILE_START(decodePerfStats);
s_stats[total_processed]++;
// loop until the protocol id is no longer valid
if ( !p->proto_bits )
p->proto_bits = PROTO_BIT__OTHER;
-
- MODULE_PROFILE_END(decodePerfStats);
}
//-------------------------------------------------------------------------
* CRC 1
*
*/
-static int BoGetDirection(Packet* p, char* pkt_data)
+static int BoGetDirection(Packet* p, const char* pkt_data)
{
uint32_t len = 0;
uint32_t id = 0;
void BackOrifice::eval(Packet* p)
{
- uint16_t cyphertext_referent;
- uint16_t cyphertext_suffix;
- uint16_t key;
- const char* magic_cookie = "*!*QWTY?";
- char* pkt_data;
- const char* magic_data;
- char* end;
- char plaintext;
- int i;
- int bo_direction = 0;
- PROFILE_VARS;
+ PERF_PROFILE(boPerfStats);
+
+ const char* const magic_cookie = "*!*QWTY?";
// preconditions - what we registered for
assert(p->is_udp());
- /* make sure it's at least 19 bytes long */
+ // make sure it's at least 19 bytes long
if (p->dsize < BO_MIN_SIZE)
- {
return;
- }
- MODULE_PROFILE_START(boPerfStats);
++bostats.total_packets;
- /*
- * take the first two characters of the packet and generate the
- * first reference that gives us a reference key
- */
- cyphertext_referent = (uint16_t)(p->data[0] << 8) & 0xFF00;
+ // take the first two characters of the packet and generate the
+ // first reference that gives us a reference key
+ uint16_t cyphertext_referent = (uint16_t)(p->data[0] << 8) & 0xFF00;
cyphertext_referent |= (uint16_t)(p->data[1]) & 0x00FF;
- /*
- * generate the second referent from the last two characters
- * of the cyphertext
- */
- cyphertext_suffix = (uint16_t)(p->data[6] << 8) & 0xFF00;
+ // generate the second referent from the last two characters
+ // of the cyphertext
+ uint16_t cyphertext_suffix = (uint16_t)(p->data[6] << 8) & 0xFF00;
cyphertext_suffix |= (uint16_t)(p->data[7]) & 0x00FF;
- for (i=0; i<3; i++)
+ for ( int i = 0; i < 3; ++i )
{
- /* get the key from the cyphertext */
- key = lookup1[cyphertext_referent][i];
-
- /*
- * if the lookup from the proposed key matches the cyphertext reference
- * then we've probably go the right key and can proceed to full
- * decryption using the key
- *
- * moral of the story: don't use a lame keyspace
- */
- if (lookup2[key] == cyphertext_suffix)
+ // get the key from the cyphertext
+ uint16_t key = lookup1[cyphertext_referent][i];
+
+ // if the lookup from the proposed key matches the cyphertext reference
+ // then we've probably go the right key and can proceed to full
+ // decryption using the key
+ // moral of the story: don't use a lame keyspace
+ if ( lookup2[key] == cyphertext_suffix )
{
+ auto pkt_data = reinterpret_cast<const char*>(p->data);
+ auto end = pkt_data + BO_MAGIC_SIZE;
+ const char* magic_data = magic_cookie;
+
holdrand = key;
- pkt_data = (char*)p->data;
- end = (char*)p->data + BO_MAGIC_SIZE;
- magic_data = magic_cookie;
- while (pkt_data<end)
+ while ( pkt_data < end )
{
- plaintext = (char)(*pkt_data ^ BoRand());
+ char plaintext = *pkt_data ^ BoRand();
- if (*magic_data != plaintext)
+ if ( *magic_data != plaintext )
{
DebugFormat(DEBUG_INSPECTOR,
"Failed check one on 0x%X : 0x%X\n",
*magic_data, plaintext);
- MODULE_PROFILE_END(boPerfStats);
+
return;
}
- magic_data++;
- pkt_data++;
+ ++magic_data;
+ ++pkt_data;
}
- /* if we fall thru there's a detect */
+ // if we fall thru there's a detect
DebugMessage(DEBUG_INSPECTOR,
"Detected Back Orifice Data!\n");
DebugFormat(DEBUG_INSPECTOR, "hash value: %d\n", key);
- bo_direction = BoGetDirection(p, pkt_data);
+ int bo_direction = BoGetDirection(p, pkt_data);
if ( bo_direction == BO_FROM_CLIENT )
{
SnortEventqAdd(GID_BO, BO_CLIENT_TRAFFIC_DETECT);
DebugMessage(DEBUG_INSPECTOR, "Client packet\n");
}
+
else if ( bo_direction == BO_FROM_SERVER )
{
SnortEventqAdd(GID_BO, BO_SERVER_TRAFFIC_DETECT);
DebugMessage(DEBUG_INSPECTOR, "Server packet\n");
}
+
else
- {
SnortEventqAdd(GID_BO, BO_TRAFFIC_DETECT);
- }
}
}
-
- MODULE_PROFILE_END(boPerfStats);
}
//-------------------------------------------------------------------------
static void snort_dns(Packet* p)
{
- DNSData* dnsSessionData = NULL;
- uint8_t direction = 0;
- PROFILE_VARS;
+ PERF_PROFILE(dnsPerfStats);
- /* For TCP, do a few extra checks... */
+ // For TCP, do a few extra checks...
if ( p->has_tcp_data() )
{
- /* If session picked up mid-stream, do not process further.
- * Would be almost impossible to tell where we are in the
- * data stream. */
+ // If session picked up mid-stream, do not process further.
+ // Would be almost impossible to tell where we are in the
+ // data stream.
if ( p->flow->get_session_flags() & SSNFLAG_MIDSTREAM )
{
return;
return;
}
- /* If we're waiting on stream reassembly, don't process this packet. */
+ // If we're waiting on stream reassembly, don't process this packet.
if ( p->packet_flags & PKT_STREAM_INSERT )
{
return;
}
}
- /* Get the direction of the packet. */
- direction = ( (p->packet_flags & PKT_FROM_SERVER ) ?
+ // Get the direction of the packet.
+ uint8_t direction = ( (p->packet_flags & PKT_FROM_SERVER ) ?
DNS_DIR_FROM_SERVER : DNS_DIR_FROM_CLIENT );
- MODULE_PROFILE_START(dnsPerfStats);
- /* Attempt to get a previously allocated DNS block. */
- dnsSessionData = get_dns_session_data(p);
+ // Attempt to get a previously allocated DNS block.
+ DNSData* dnsSessionData = get_dns_session_data(p);
if (dnsSessionData == NULL)
{
- /* Check the stream session. If it does not currently
- * have our DNS data-block attached, create one.
- */
+ // Check the stream session. If it does not currently
+ // have our DNS data-block attached, create one.
dnsSessionData = SetNewDNSData(p);
if ( !dnsSessionData )
- {
- /* Could not get/create the session data for this packet. */
- MODULE_PROFILE_END(dnsPerfStats);
+ // Could not get/create the session data for this packet.
return;
- }
}
if (dnsSessionData->flags & DNS_FLAG_NOT_DNS)
- {
- MODULE_PROFILE_END(dnsPerfStats);
return;
- }
if (direction == DNS_DIR_FROM_SERVER)
{
ParseDNSResponseMessage(p, dnsSessionData);
}
-
- MODULE_PROFILE_END(dnsPerfStats);
}
//-------------------------------------------------------------------------
*/
void do_detection(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(ftppDetectPerfStats);
- /*
- * If we get here we either had a client or server request/response.
- * We do the detection here, because we're starting a new paradigm
- * about protocol decoders.
- *
- * Protocol decoders are now their own detection engine, since we are
- * going to be moving protocol field detection from the generic
- * detection engine into the protocol module. This idea scales much
- * better than having all these Packet struct field checks in the
- * main detection engine for each protocol field.
- */
- MODULE_PROFILE_START(ftppDetectPerfStats);
+ // If we get here we either had a client or server request/response.
+ // We do the detection here, because we're starting a new paradigm
+ // about protocol decoders.
+ //
+ // Protocol decoders are now their own detection engine, since we are
+ // going to be moving protocol field detection from the generic
+ // detection engine into the protocol module. This idea scales much
+ // better than having all these Packet struct field checks in the
+ // main detection engine for each protocol field.
get_data_bus().publish(PACKET_EVENT, p);
DisableInspection(p);
- MODULE_PROFILE_END(ftppDetectPerfStats);
#ifdef PERF_PROFILING
ftppDetectCalled = 1;
#endif
static int SnortFTP(
FTP_SESSION* FTPsession, Packet* p, int iInspectMode)
{
- int iRet;
- PROFILE_VARS;
+ PERF_PROFILE(ftpPerfStats);
- if (!FTPsession ||
- FTPsession->server_conf == NULL ||
- FTPsession->client_conf == NULL)
- {
+ if ( !FTPsession || !FTPsession->server_conf || !FTPsession->client_conf )
return FTPP_INVALID_SESSION;
- }
- if (!FTPsession->server_conf->check_encrypted_data &&
- ((FTPsession->encr_state == AUTH_TLS_ENCRYPTED) ||
- (FTPsession->encr_state == AUTH_SSL_ENCRYPTED) ||
- (FTPsession->encr_state == AUTH_UNKNOWN_ENCRYPTED)) )
+ if ( !FTPsession->server_conf->check_encrypted_data )
{
- return FTPP_SUCCESS;
- }
+ if ( FTPsession->encr_state == AUTH_TLS_ENCRYPTED ||
+ FTPsession->encr_state == AUTH_SSL_ENCRYPTED ||
+ FTPsession->encr_state == AUTH_UNKNOWN_ENCRYPTED )
- MODULE_PROFILE_START(ftpPerfStats);
+ return FTPP_SUCCESS;
+ }
if (iInspectMode == FTPP_SI_SERVER_MODE)
{
{
DebugMessage(DEBUG_FTPTELNET,
"Client packet will be reassembled\n");
- MODULE_PROFILE_END(ftpPerfStats);
return FTPP_SUCCESS;
}
else
}
}
- iRet = initialize_ftp(FTPsession, p, iInspectMode);
- if (iRet)
- {
- MODULE_PROFILE_END(ftpPerfStats);
- return iRet;
- }
+ int ret = initialize_ftp(FTPsession, p, iInspectMode);
+ if ( ret )
+ return ret;
- iRet = check_ftp(FTPsession, p, iInspectMode);
- if (iRet == FTPP_SUCCESS)
+ ret = check_ftp(FTPsession, p, iInspectMode);
+ if ( ret == FTPP_SUCCESS )
{
- /* Ideally, snort_detect(), called from do_detection, will look at
- * the cmd & param buffers, or the rsp & msg buffers. Current
- * architecture does not support this...
- * So, we call do_detection() here. Otherwise, we'd call it
- * from inside check_ftp -- each time we process a pipelined
- * FTP command.
- */
+ // Ideally, snort_detect(), called from do_detection, will look at
+ // the cmd & param buffers, or the rsp & msg buffers. Current
+ // architecture does not support this...
+ // So, we call do_detection() here. Otherwise, we'd call it
+ // from inside check_ftp -- each time we process a pipelined
+ // FTP command.
do_detection(p);
}
- MODULE_PROFILE_END(ftpPerfStats);
#ifdef PERF_PROFILING
ft_update_perf(ftpPerfStats);
#endif
- return iRet;
+ return ret;
}
static int snort_ftp(Packet* p)
void FtpData::eval(Packet* p)
{
+ PERF_PROFILE(ftpdataPerfStats);
+
// precondition - what we registered for
assert(p->has_tcp_data());
if ( FileService::get_max_file_depth() < 0 )
return;
- PROFILE_VARS;
- MODULE_PROFILE_START(ftpdataPerfStats);
-
SnortFTPData(p);
++fdstats.total_packets;
-
- MODULE_PROFILE_END(ftpdataPerfStats);
}
//-------------------------------------------------------------------------
static int SnortTelnet(TELNET_PROTO_CONF* telnet_config, TELNET_SESSION* Telnetsession,
Packet* p, int iInspectMode)
{
- int iRet;
- PROFILE_VARS;
+ PERF_PROFILE(telnetPerfStats);
- if (!Telnetsession)
- {
+ if ( !Telnetsession )
return FTPP_NONFATAL_ERR;
- }
- if (Telnetsession->encr_state && !Telnetsession->telnet_conf->check_encrypted_data)
- {
+ if ( Telnetsession->encr_state &&
+ !Telnetsession->telnet_conf->check_encrypted_data )
return FTPP_SUCCESS;
- }
- MODULE_PROFILE_START(telnetPerfStats);
-
- if (!telnet_config->normalize)
+ if ( telnet_config->normalize )
{
- do_detection(p);
- }
- else
- {
- iRet = normalize_telnet(
- Telnetsession, p, iInspectMode, FTPP_APPLY_TNC_ERASE_CMDS);
+ int ret = normalize_telnet(Telnetsession, p, iInspectMode,
+ FTPP_APPLY_TNC_ERASE_CMDS);
- if ((iRet == FTPP_SUCCESS) || (iRet == FTPP_NORMALIZED))
- {
+ if ( ret == FTPP_SUCCESS || ret == FTPP_NORMALIZED )
do_detection(p);
- }
}
- MODULE_PROFILE_END(telnetPerfStats);
+
+ else
+ do_detection(p);
+
#ifdef PERF_PROFILING
ft_update_perf(telnetPerfStats);
#endif
int iCallDetect = 1;
HttpSessionData* hsd = NULL;
- PROFILE_VARS;
-
hi_stats.total++;
/*
return 0;
}
// see comments on call to snort_detect() below
- MODULE_PROFILE_START(hiDetectPerfStats);
- get_data_bus().publish(PACKET_EVENT, p);
+ PERF_PROFILE_BLOCK(hiDetectPerfStats)
+ {
+ get_data_bus().publish(PACKET_EVENT, p);
#ifdef PERF_PROFILING
- hiDetectCalled = 1;
+ hiDetectCalled = 1;
#endif
- MODULE_PROFILE_END(hiDetectPerfStats);
+ }
+
return 0;
}
** better than having all these Packet struct field checks in the
** main detection engine for each protocol field.
*/
- MODULE_PROFILE_START(hiDetectPerfStats);
- snort_detect(p);
+ PERF_PROFILE_BLOCK(hiDetectPerfStats)
+ {
+ snort_detect(p);
#ifdef PERF_PROFILING
- hiDetectCalled = 1;
+ hiDetectCalled = 1;
#endif
- MODULE_PROFILE_END(hiDetectPerfStats);
+ }
/*
** We set the global detection flag here so that if request pipelines
void HttpInspect::eval(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(hiPerfStats);
// preconditions - what we registered for
assert(p->has_tcp_data());
- MODULE_PROFILE_START(hiPerfStats);
hi_clear_events();
HttpInspectMain(config, p);
* spent in snort_detect().
* Subtract the ticks from this if iCallDetect == 0
*/
- MODULE_PROFILE_END(hiPerfStats);
#ifdef PERF_PROFILING
if (hiDetectCalled)
{
void Imap::eval(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(imapPerfStats);
+
// precondition - what we registered for
assert(p->has_tcp_data());
assert(p->flow);
++imapstats.total_packets;
- MODULE_PROFILE_START(imapPerfStats);
-
snort_imap(config, p);
-
- MODULE_PROFILE_END(imapPerfStats);
}
//-------------------------------------------------------------------------
void Pop::eval(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(popPerfStats);
+
// precondition - what we registered for
assert(p->has_tcp_data());
assert(p->flow);
++popstats.total_packets;
- MODULE_PROFILE_START(popPerfStats);
-
snort_pop(config, p);
-
- MODULE_PROFILE_END(popPerfStats);
}
//-------------------------------------------------------------------------
*/
void RpcDecode::eval(Packet* p)
{
- RpcSsnData* rsdata = NULL;
- PROFILE_VARS;
+ PERF_PROFILE(rpcdecodePerfStats);
// preconditions - what we registered for
assert(p->has_tcp_data());
- /* If we're stateful that means stream has been configured.
- * In this case we don't look at server packets.
- * There is the case were stream configuration requires a 3 way handshake.
- * If no 3 way, then the packet flags won't be set, so don't look at it
- * since we won't be able to determeine who's the client and who's the server. */
- if ( !(p->packet_flags & PKT_FROM_CLIENT) )
- {
+ // If we're stateful that means stream has been configured.
+ // In this case we don't look at server packets.
+ // There is the case were stream configuration requires a 3 way handshake.
+ // If no 3 way, then the packet flags won't be set, so don't look at it
+ // since we won't be able to determeine who's the client and who's the
+ // server.
+ if ( !p->from_client() )
return;
- }
- if ( p->flow != NULL )
+ RpcSsnData* rsdata = nullptr;
+
+ if ( p->flow )
{
RpcFlowData* fd = (RpcFlowData*)p->flow->get_application_data(
RpcFlowData::flow_id);
- rsdata = fd ? &fd->session : NULL;
+ if ( fd )
+ rsdata = &fd->session;
}
- MODULE_PROFILE_START(rpcdecodePerfStats);
++rdstats.total_packets;
- if ((rsdata == NULL) && (p->flow != NULL))
- {
- if (!stream.is_midstream(p->flow))
- rsdata = RpcSsnDataNew(p);
- }
+ if ( !rsdata && p->flow && !stream.is_midstream(p->flow) )
+ rsdata = RpcSsnDataNew(p);
if ( RpcSsnIsActive(rsdata) and (p->packet_flags & PKT_REBUILT_STREAM) )
{
RpcStatus ret = RpcStatefulInspection(&config, rsdata, p);
if (ret == RPC_STATUS__SUCCESS)
- {
- MODULE_PROFILE_END(rpcdecodePerfStats);
return;
- }
- /* Something went wrong - deactivate session tracking
- * and decode normally */
+ // Something went wrong - deactivate session tracking
+ // and decode normally
if (ret == RPC_STATUS__ERROR)
RpcSsnSetInactive(rsdata, p);
}
DebugMessage(DEBUG_RPC,"Stateless inspection\n");
RpcPreprocEvent(&config, rsdata, ConvertRPC(&config, rsdata, p));
-
- MODULE_PROFILE_END(rpcdecodePerfStats);
}
bool RpcDecode::get_buf(InspectionBuffer::Type ibt, Packet*, InspectionBuffer& b)
int SipIpsOption::eval(Cursor& c, Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(sip_ps[idx]);
+ auto& sip_stats = sip_ps[idx];
+ PERF_PROFILE(sip_stats);
- int rval;
SIPData* sd;
SIP_Roptions* ropts;
const uint8_t* data = NULL;
unsigned len = 0;
if ((!p->is_tcp() && !p->is_udp()) || !p->flow || !p->dsize)
- {
- MODULE_PROFILE_END(sip_ps[idx]);
return DETECTION_OPTION_NO_MATCH;
- }
// FIXIT-P cache id at parse time for runtime use
sd = get_sip_session_data(p->flow);
if (!sd)
- {
- MODULE_PROFILE_END(sip_ps[idx]);
return DETECTION_OPTION_NO_MATCH;
- }
ropts = &sd->ropts;
if (data != NULL)
{
c.set(key, data, len);
- rval = DETECTION_OPTION_MATCH;
- }
- else
- {
- rval = DETECTION_OPTION_NO_MATCH;
+ return DETECTION_OPTION_MATCH;
}
- MODULE_PROFILE_END(sip_ps[idx]);
- return rval;
+ else
+ return DETECTION_OPTION_NO_MATCH;
}
//-------------------------------------------------------------------------
int SipMethodOption::eval(Cursor&, Packet* p)
{
- SIPData* sd;
- SIP_Roptions* ropts;
- uint32_t methodFlag;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(sipMethodRuleOptionPerfStats);
+ PERF_PROFILE(sipMethodRuleOptionPerfStats);
if ((!p->is_tcp() && !p->is_udp()) || !p->flow || !p->dsize)
- {
- MODULE_PROFILE_END(sipMethodRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- sd = get_sip_session_data(p->flow);
+ SIPData* sd = get_sip_session_data(p->flow);
if (!sd)
- {
- MODULE_PROFILE_END(sipMethodRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- ropts = &sd->ropts;
+ SIP_Roptions* ropts = &sd->ropts;
// Not response
- methodFlag = 1 << (ropts->methodFlag - 1);
+ uint32_t methodFlag = 1 << (ropts->methodFlag - 1);
if (IsRequest(ropts) && ((smod.flags & methodFlag) ^ smod.mask))
- {
- MODULE_PROFILE_END(sipMethodRuleOptionPerfStats);
return DETECTION_OPTION_MATCH;
- }
- MODULE_PROFILE_END(sipMethodRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
int SipStatCodeOption::eval(Cursor&, Packet* p)
{
- SIPData* sd;
- SIP_Roptions* ropts;
- uint16_t short_code;
- int i_code;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(sipStatCodeRuleOptionPerfStats);
+ PERF_PROFILE(sipStatCodeRuleOptionPerfStats);
if ((!p->is_tcp() && !p->is_udp()) || !p->flow || !p->dsize)
- {
- MODULE_PROFILE_END(sipStatCodeRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- sd = get_sip_session_data(p->flow);
+ SIPData* sd = get_sip_session_data(p->flow);
if (!sd)
- {
- MODULE_PROFILE_END(sipStatCodeRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- ropts = &sd->ropts;
+ SIP_Roptions* ropts = &sd->ropts;
if (0 == ropts->status_code)
- {
- MODULE_PROFILE_END(sipStatCodeRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- /*Match the stat code*/
- short_code = ropts->status_code / 100;
- for (i_code = 0; i_code < SIP_NUM_STAT_CODE_MAX; i_code++)
+ // Match the stat code
+ uint16_t short_code = ropts->status_code / 100;
+ for ( int i = 0; i < SIP_NUM_STAT_CODE_MAX; i++ )
{
- if ((ssod.stat_codes[i_code] == short_code)||
- (ssod.stat_codes[i_code] == ropts->status_code))
- {
- MODULE_PROFILE_END(sipStatCodeRuleOptionPerfStats);
+ auto stat_code = ssod.stat_codes[i];
+ if ( stat_code == short_code || stat_code == ropts->status_code )
return DETECTION_OPTION_MATCH;
- }
}
- MODULE_PROFILE_END(sipStatCodeRuleOptionPerfStats);
-
return DETECTION_OPTION_NO_MATCH;
}
*/
static void snort_sip(SIP_PROTO_CONF* config, Packet* p)
{
- SIPData* sessp = NULL;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(sipPerfStats);
+ PERF_PROFILE(sipPerfStats);
/* Attempt to get a previously allocated SIP block. */
- sessp = get_sip_session_data(p->flow);
+ SIPData* sessp = get_sip_session_data(p->flow);
if (sessp == NULL)
{
sessp = SetNewSIPData(p, config);
if ( !sessp )
- {
- /* Could not get/create the session data for this packet. */
- MODULE_PROFILE_END(sipPerfStats);
+ // Could not get/create the session data for this packet.
return;
- }
}
/* Don't process if we've missed packets */
if (sessp->state_flags & SIP_FLG_MISSED_PACKETS)
- {
- MODULE_PROFILE_END(sipPerfStats);
return;
- }
SIP_Process(p,sessp, config);
-
- MODULE_PROFILE_END(sipPerfStats);
}
//-------------------------------------------------------------------------
void Smtp::eval(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(smtpPerfStats);
+
// precondition - what we registered for
assert(p->has_tcp_data());
assert(p->flow);
++smtpstats.total_packets;
- MODULE_PROFILE_START(smtpPerfStats);
-
snort_smtp(config, p);
-
- MODULE_PROFILE_END(smtpPerfStats);
}
bool Smtp::get_buf(
*/
static void snort_ssh(SSH_PROTO_CONF* config, Packet* p)
{
- SSHData* sessp = NULL;
- uint8_t direction;
- unsigned int offset = 0;
- uint32_t search_dir_ver, search_dir_keyinit;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(sshPerfStats);
+ PERF_PROFILE(sshPerfStats);
- /* Attempt to get a previously allocated SSH block. */
- sessp = get_session_data(p->flow);
+ // Attempt to get a previously allocated SSH block.
+ SSHData* sessp = get_session_data(p->flow);
if (sessp == NULL)
{
sessp = SetNewSSHData(p);
if ( !sessp )
- {
- /* Could not get/create the session data for this packet. */
- MODULE_PROFILE_END(sshPerfStats);
+ // Could not get/create the session data for this packet.
return;
- }
}
-
- /* Don't process if we've missed packets */
+ // Don't process if we've missed packets
if (sessp->state_flags & SSH_FLG_MISSED_PACKETS)
- {
- MODULE_PROFILE_END(sshPerfStats);
return;
- }
- /* Make sure this preprocessor should run.
- check if we're waiting on stream reassembly */
+ // Make sure this preprocessor should run.
+ // check if we're waiting on stream reassembly
if ( p->packet_flags & PKT_STREAM_INSERT )
- {
- MODULE_PROFILE_END(sshPerfStats);
return;
- }
- /* If we picked up mid-stream or missed any packets (midstream pick up
- * * means we've already missed packets) set missed packets flag and make
- * * sure we don't do any more reassembly on this session */
+ // If we picked up mid-stream or missed any packets (midstream pick up
+ // means we've already missed packets) set missed packets flag and make
+ // sure we don't do any more reassembly on this session
if ((p->flow->get_session_flags() & SSNFLAG_MIDSTREAM)
|| stream.missed_packets(p->flow, SSN_DIR_BOTH))
{
- /* Order only matters if the packets are not encrypted */
+ // Order only matters if the packets are not encrypted
if ( !(sessp->state_flags & SSH_FLG_SESS_ENCRYPTED ))
{
sessp->state_flags |= SSH_FLG_MISSED_PACKETS;
-
- MODULE_PROFILE_END(sshPerfStats);
return;
}
}
- /* Get the direction of the packet. */
+ uint8_t direction;
+ uint32_t search_dir_ver;
+ uint32_t search_dir_keyinit;
+
+ // Get the direction of the packet.
if ( p->packet_flags & PKT_FROM_SERVER )
{
direction = SSH_DIR_FROM_SERVER;
search_dir_ver = SSH_FLG_CLIENT_IDSTRING_SEEN;
search_dir_keyinit = SSH_FLG_CLIENT_SKEY_SEEN | SSH_FLG_CLIENT_KEXINIT_SEEN;
}
+
+ unsigned int offset = 0;
+
if ( !(sessp->state_flags & SSH_FLG_SESS_ENCRYPTED ))
{
- /* If server and client have not performed the protocol
- * version exchange yet, must look for version strings.
- */
+ // If server and client have not performed the protocol
+ // version exchange yet, must look for version strings.
if ( !(sessp->state_flags & search_dir_ver) )
{
offset = ProcessSSHProtocolVersionExchange(config, sessp, p, direction);
if (!offset)
- {
- /*Error processing protovers exchange msg */
- MODULE_PROFILE_END(sshPerfStats);
+ // Error processing protovers exchange msg
return;
- }
- /* found protocol version. Stream reassembly might have appended an ssh packet,
- * such as the key exchange init. Thus call ProcessSSHKeyInitExchange() too.
- */
+
+ // found protocol version.
+ // Stream reassembly might have appended an ssh packet,
+ // such as the key exchange init.
+ // Thus call ProcessSSHKeyInitExchange() too.
}
- /* Expecting to see the key init exchange at this point
- * (in SSH2) or the actual key exchange if SSH1
- */
+ // Expecting to see the key init exchange at this point
+ // (in SSH2) or the actual key exchange if SSH1
if ( !(sessp->state_flags & search_dir_keyinit) )
{
offset = ProcessSSHKeyInitExchange(sessp, p, direction, offset);
if (!offset)
{
if ( !(sessp->state_flags & SSH_FLG_SESS_ENCRYPTED ))
- {
- MODULE_PROFILE_END(sshPerfStats);
return;
- }
}
}
- /* If SSH2, need to process the actual key exchange msgs.
- * The actual key exchange type was negotiated in the
- * key exchange init msgs. SSH1 won't arrive here.
- */
+ // If SSH2, need to process the actual key exchange msgs.
+ // The actual key exchange type was negotiated in the
+ // key exchange init msgs. SSH1 won't arrive here.
offset = ProcessSSHKeyExchange(sessp, p, direction, offset);
if (!offset)
- {
- MODULE_PROFILE_END(sshPerfStats);
return;
- }
}
+
if ( (sessp->state_flags & SSH_FLG_SESS_ENCRYPTED ))
{
- /* Traffic on this session is currently encrypted.
- * Two of the major SSH exploits, SSH1 CRC-32 and
- * the Challenge-Response Overflow attack occur within
- * the encrypted portion of the SSH session. Therefore,
- * the only way to detect these attacks is by examining
- * amounts of data exchanged for anomalies.
- */
+ // Traffic on this session is currently encrypted.
+ // Two of the major SSH exploits, SSH1 CRC-32 and
+ // the Challenge-Response Overflow attack occur within
+ // the encrypted portion of the SSH session. Therefore,
+ // the only way to detect these attacks is by examining
+ // amounts of data exchanged for anomalies.
sessp->num_enc_pkts++;
if ( sessp->num_enc_pkts <= config->MaxEncryptedPackets )
if ( direction == SSH_DIR_FROM_CLIENT )
{
if (!offset)
- {
sessp->num_client_bytes += p->dsize;
- }
+
else
- {
sessp->num_client_bytes += (p->dsize - offset);
- }
if ( sessp->num_client_bytes >= config->MaxClientBytes )
{
- /* Probable exploit in progress.*/
+ // Probable exploit in progress.
if (sessp->version == SSH_VERSION_1)
- {
- {
- SnortEventqAdd(GID_SSH, SSH_EVENT_CRC32);
+ SnortEventqAdd(GID_SSH, SSH_EVENT_CRC32);
- stream.stop_inspection(p->flow, p, SSN_DIR_BOTH, -1, 0);
- }
- }
else
- {
- {
- SnortEventqAdd(GID_SSH, SSH_EVENT_RESPOVERFLOW);
+ SnortEventqAdd(GID_SSH, SSH_EVENT_RESPOVERFLOW);
- stream.stop_inspection(p->flow, p, SSN_DIR_BOTH, -1, 0);
- }
- }
+ stream.stop_inspection(p->flow, p, SSN_DIR_BOTH, -1, 0);
}
}
+
else
{
- /*
- * Have seen a server response, so
- * this appears to be a valid exchange.
- * Reset suspicious byte count to zero.
- */
+ // Have seen a server response, so this appears to be a valid
+ // exchange. Reset suspicious byte count to zero
sessp->num_client_bytes = 0;
}
}
+
else
{
- /* Have already examined more than the limit
- * of encrypted packets. Both the Gobbles and
- * the CRC32 attacks occur during authentication
- * and therefore cannot be used late in an
- * encrypted session. For performance purposes,
- * stop examining this session.
- */
+ // Have already examined more than the limit
+ // of encrypted packets. Both the Gobbles and
+ // the CRC32 attacks occur during authentication
+ // and therefore cannot be used late in an
+ // encrypted session. For performance purposes,
+ // stop examining this session.
stream.stop_inspection(p->flow, p, SSN_DIR_BOTH, -1, 0);
}
}
- MODULE_PROFILE_END(sshPerfStats);
}
/* Checks if the string 'str' is 'max' bytes long or longer.
int SslStateOption::eval(Cursor&, Packet* pkt)
{
- SSLData* sd;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(sslStateRuleOptionPerfStats);
+ PERF_PROFILE(sslStateRuleOptionPerfStats);
if ( !(pkt->packet_flags & PKT_REBUILT_STREAM) && !pkt->is_full_pdu() )
- {
- MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
if (!pkt->flow)
- {
- MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- sd = get_ssl_session_data(pkt->flow);
+ SSLData* sd = get_ssl_session_data(pkt->flow);
if (!sd)
- {
- MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
if ((ssod.flags & sd->ssn_flags) ^ ssod.mask)
- {
- MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
return DETECTION_OPTION_MATCH;
- }
-
- MODULE_PROFILE_END(sslStateRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
int SslVersionOption::eval(Cursor&, Packet* pkt)
{
- SSLData* sd;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(sslVersionRuleOptionPerfStats);
+ PERF_PROFILE(sslVersionRuleOptionPerfStats);
if ( !(pkt->packet_flags & PKT_REBUILT_STREAM) && !pkt->is_full_pdu() )
- {
- MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
if (!pkt->flow)
- {
- MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
- sd = get_ssl_session_data(pkt->flow);
+ SSLData* sd = get_ssl_session_data(pkt->flow);
if (!sd)
- {
- MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
- }
if ((svod.flags & sd->ssn_flags) ^ svod.mask)
- {
- MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
return DETECTION_OPTION_MATCH;
- }
-
- MODULE_PROFILE_END(sslVersionRuleOptionPerfStats);
return DETECTION_OPTION_NO_MATCH;
}
*/
static void snort_ssl(SSL_PROTO_CONF* config, Packet* p)
{
- SSLData* sd = NULL;
- uint8_t dir;
- uint8_t index;
- uint32_t new_flags;
- uint8_t heartbleed_type = 0;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(sslPerfStats);
+ PERF_PROFILE(sslPerfStats);
/* Attempt to get a previously allocated SSL block. */
- sd = get_ssl_session_data(p->flow);
+ SSLData* sd = get_ssl_session_data(p->flow);
if (sd == NULL)
{
sd = SetNewSSLData(p);
if ( !sd )
- {
- /* Could not get/create the session data for this packet. */
- MODULE_PROFILE_END(sslPerfStats);
+ // Could not get/create the session data for this packet.
return;
- }
}
+
SSL_CLEAR_TEMPORARY_FLAGS(sd->ssn_flags);
- dir = (p->packet_flags & PKT_FROM_SERVER) ? 1 : 0;
- index = (p->packet_flags & PKT_REBUILT_STREAM) ? 2 : 0;
- new_flags = SSL_decode(p->data, (int)p->dsize, p->packet_flags, sd->ssn_flags,
+ uint8_t dir = (p->packet_flags & PKT_FROM_SERVER) ? 1 : 0;
+ uint8_t index = (p->packet_flags & PKT_REBUILT_STREAM) ? 2 : 0;
+
+ uint8_t heartbleed_type = 0;
+ uint32_t new_flags = SSL_decode(p->data, (int)p->dsize, p->packet_flags, sd->ssn_flags,
&heartbleed_type, &(sd->partial_rec_len[dir+index]), config->max_heartbeat_len);
if (heartbleed_type & SSL_HEARTBLEED_REQUEST)
sd->ssn_flags |= new_flags;
- MODULE_PROFILE_END(sslPerfStats);
return;
}
/* Application data is updated inside of SSLPP_process_other */
- MODULE_PROFILE_END(sslPerfStats);
return;
}
sd->ssn_flags |= new_flags;
-
- MODULE_PROFILE_END(sslPerfStats);
}
//-------------------------------------------------------------------------
void StreamBase::eval(Packet* p)
{
- PROFILE_VARS;
+ PERF_PROFILE(s5PerfStats);
if ( !is_eligible(p) )
return;
- MODULE_PROFILE_START(s5PerfStats);
-
switch ( p->type() )
{
case PktType::IP:
default:
break;
}
-
- MODULE_PROFILE_END(s5PerfStats);
}
#if 0
int FileSession::process(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(file_ssn_stats);
+ PERF_PROFILE(file_ssn_stats);
p->flow->ssn_state.application_protocol = SNORT_PROTO_USER;
StreamFileConfig* c = get_file_cfg(p->flow->ssn_server);
file_flows->file_process((uint8_t*)p->data, p->dsize, position(p), c->upload);
set_file_data((uint8_t*)p->data, p->dsize);
- MODULE_PROFILE_END(file_ssn_stats);
return 0;
}
*/
static void FragRebuild(FragTracker* ft, Packet* p)
{
+ PERF_PROFILE(fragRebuildPerfStats);
+
static THREAD_LOCAL uint8_t encap_frag_cnt = 0;
uint8_t* rebuild_ptr = NULL; /* ptr to the start of the reassembly buffer */
const uint8_t* rebuild_end; /* ptr to the end of the reassembly buffer */
Fragment* frag; /* frag pointer for managing fragments */
int ret = 0;
Packet* dpkt;
- PROFILE_VARS;
// XXX NOT YET IMPLEMENTED - debugging
- MODULE_PROFILE_START(fragRebuildPerfStats);
-
if (!defrag_pkts[encap_frag_cnt])
defrag_pkts[encap_frag_cnt] = PacketManager::encode_new();
sfBase.iFragFlushes++;
/* Rebuild is complete */
- MODULE_PROFILE_END(fragRebuildPerfStats);
/*
* process the packet through the detection engine
{
FragEngine* fe = &engine;
int insert_return = 0; /* return value from the insert function */
- PROFILE_VARS;
// preconditions - what we registered for
assert(p->has_ip() && !(p->ptrs.decode_flags & DECODE_ERR_CKSUM_IP));
ip_stats.total++;
UpdateIPFragStats(&sfBase, p->pkth->caplen);
- MODULE_PROFILE_START(fragPerfStats);
+ PERF_PROFILE(fragPerfStats);
pkttime = (struct timeval*)&p->pkth->ts;
if (!ft->engine )
{
new_tracker(p, ft);
- MODULE_PROFILE_END(fragPerfStats);
return;
}
else if (expire(p, ft, fe) == FRAG_TRACKER_TIMEOUT)
LogMessage("WARNING: Insert into Fraglist failed, "
"(offset: %u).\n", frag_offset);
#endif
- MODULE_PROFILE_END(fragPerfStats);
return;
case FRAG_INSERT_TTL:
}
#endif
ip_stats.discards++;
- MODULE_PROFILE_END(fragPerfStats);
return;
case FRAG_INSERT_ATTACK:
case FRAG_INSERT_ANOMALY:
ip_stats.discards++;
- MODULE_PROFILE_END(fragPerfStats);
return;
case FRAG_INSERT_TIMEOUT:
#ifdef DEBUG
LogMessage("WARNING: Insert into Fraglist failed due to timeout, "
"(offset: %u).\n", frag_offset);
#endif
- MODULE_PROFILE_END(fragPerfStats);
return;
case FRAG_INSERT_OVERLAP_LIMIT:
#ifdef DEBUG
(frag_offset << 3), p->dsize);
#endif
ip_stats.discards++;
- MODULE_PROFILE_END(fragPerfStats);
return;
default:
break;
release_tracker(ft);
}
}
-
- MODULE_PROFILE_END(fragPerfStats);
}
/**
Fragment* dump_me = NULL; /* frag ptr for complete overlaps to dump */
const uint8_t* fragStart;
int16_t fragLength;
- PROFILE_VARS;
const uint16_t net_frag_offset = p->ptrs.ip_api.off();
sfBase.iFragInserts++;
- MODULE_PROFILE_START(fragInsertPerfStats);
+ PERF_PROFILE(fragInsertPerfStats);
if (p->is_ip6() && (net_frag_offset == 0))
{
EventAnomOversize(fe);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
ft->calculated_size = frag_end;
EventAnomZeroFrag(fe);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
ft->frag_flags |= FRAG_BAD;
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
ft->frag_flags |= FRAG_BAD;
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ATTACK;
}
}
EventAnomZeroFrag(fe);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
{
/* Some warning here,
* no, its done in add_frag_node */
- MODULE_PROFILE_END(fragInsertPerfStats);
return ret;
}
left->size -= (int16_t)overlap;
EventAnomBadsizeSm(fe);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
}
"Overly large fragment %d 0x%x 0x%x %d\n",
fragLength, p->ptrs.ip_api.dgram_len(), p->ptrs.ip_api.off(),
net_frag_offset);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_FAILED;
}
ft->frag_flags |= FRAG_BAD;
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ATTACK;
}
}
ip_stats.discards++;
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_ANOMALY;
}
{
/* Some warning here,
* no, its done in add_frag_node */
- MODULE_PROFILE_END(fragInsertPerfStats);
return ret;
}
EventExcessiveOverlap(fe);
- MODULE_PROFILE_END(fragInsertPerfStats);
return FRAG_INSERT_OVERLAP_LIMIT;
}
DebugMessage(DEBUG_FRAG,
"insert(): returning normally\n");
- MODULE_PROFILE_END(fragInsertPerfStats);
return ret;
}
#ifdef ENABLE_EXPECTED_IP
if ( flow_con->expected_session(flow, p))
- {
- MODULE_PROFILE_END(ip_perf_stats);
return false;
- }
#endif
return true;
}
int IpSession::process(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(ip_perf_stats);
+ PERF_PROFILE(ip_perf_stats);
if ( stream.expired_session(flow, p) )
{
#ifdef ENABLE_EXPECTED_IP
if ( flow_con->expected_session(flow, p))
- {
- MODULE_PROFILE_END(ip_perf_stats);
return 0;
- }
#endif
}
if ( stream.blocked_session(flow, p) || stream.ignored_session(flow, p) )
- {
- MODULE_PROFILE_END(ip_perf_stats);
return 0;
- }
if ( p->ptrs.decode_flags & DECODE_FRAG )
{
UpdateSession(p, flow);
- MODULE_PROFILE_END(ip_perf_stats);
return 0;
}
if (!pkt->flow || !pkt->ptrs.tcph)
return 0;
- PROFILE_VARS;
- MODULE_PROFILE_START(streamReassembleRuleOptionPerfStats);
-
- Flow* lwssn = (Flow*)pkt->flow;
- TcpSession* tcpssn = (TcpSession*)lwssn->session;
-
- if ( !srod.enable ) /* Turn it off */
+ PERF_PROFILE_BLOCK(streamReassembleRuleOptionPerfStats)
{
- if ( srod.direction & SSN_DIR_FROM_SERVER )
- {
- tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
- stream.set_splitter(lwssn, true);
- }
+ Flow* lwssn = (Flow*)pkt->flow;
+ TcpSession* tcpssn = (TcpSession*)lwssn->session;
- if ( srod.direction & SSN_DIR_FROM_CLIENT )
+ if ( !srod.enable ) /* Turn it off */
{
- tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
- stream.set_splitter(lwssn, false);
+ if ( srod.direction & SSN_DIR_FROM_SERVER )
+ {
+ tcpssn->server.flush_policy = STREAM_FLPOLICY_IGNORE;
+ stream.set_splitter(lwssn, true);
+ }
+
+ if ( srod.direction & SSN_DIR_FROM_CLIENT )
+ {
+ tcpssn->client.flush_policy = STREAM_FLPOLICY_IGNORE;
+ stream.set_splitter(lwssn, false);
+ }
}
- }
- else
- {
- // FIXIT-M PAF need to instantiate service splitter?
- // FIXIT-M PAF need to check for ips / on-data
- if ( srod.direction & SSN_DIR_FROM_SERVER )
+ else
{
- tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
- stream.set_splitter(lwssn, true, new AtomSplitter(true));
+ // FIXIT-M PAF need to instantiate service splitter?
+ // FIXIT-M PAF need to check for ips / on-data
+ if ( srod.direction & SSN_DIR_FROM_SERVER )
+ {
+ tcpssn->server.flush_policy = STREAM_FLPOLICY_ON_ACK;
+ stream.set_splitter(lwssn, true, new AtomSplitter(true));
+ }
+
+ if ( srod.direction & SSN_DIR_FROM_CLIENT )
+ {
+ tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
+ stream.set_splitter(lwssn, false, new AtomSplitter(false));
+ }
}
- if ( srod.direction & SSN_DIR_FROM_CLIENT )
+ if (srod.fastpath)
{
- tcpssn->client.flush_policy = STREAM_FLPOLICY_ON_ACK;
- stream.set_splitter(lwssn, false, new AtomSplitter(false));
- }
- }
+ /* Turn off inspection */
+ lwssn->ssn_state.ignore_direction |= srod.direction;
+ DisableInspection(pkt);
- if (srod.fastpath)
- {
- /* Turn off inspection */
- lwssn->ssn_state.ignore_direction |= srod.direction;
- DisableInspection(pkt);
-
- /* TBD: Set TF_FORCE_FLUSH ? */
+ /* TBD: Set TF_FORCE_FLUSH ? */
+ }
}
- MODULE_PROFILE_END(streamReassembleRuleOptionPerfStats);
if (srod.alert)
return DETECTION_OPTION_MATCH;
int SizeOption::eval(Cursor&, Packet* pkt)
{
+ PERF_PROFILE(streamSizePerfStats);
+
if (!pkt->flow || !pkt->ptrs.tcph)
return DETECTION_OPTION_NO_MATCH;
- PROFILE_VARS;
- MODULE_PROFILE_START(streamSizePerfStats);
-
Flow* lwssn = (Flow*)pkt->flow;
TcpSession* tcpssn = (TcpSession*)lwssn->session;
default:
break;
}
- MODULE_PROFILE_END(streamSizePerfStats);
+
return result;
}
static int FlushStream(Packet* p, TcpTracker *st, uint32_t toSeq,
uint8_t *flushbuf, const uint8_t *flushbuf_end)
{
+ PERF_PROFILE(s5TcpBuildPacketPerfStats);
+
uint16_t bytes_flushed = 0;
DEBUG_WRAP(uint32_t bytes_queued = st->seg_bytes_logical; );
uint32_t segs = 0;
uint32_t flags = PKT_PDU_HEAD;
- PROFILE_VARS;
- assert(st->seglist_next); MODULE_PROFILE_START(s5TcpBuildPacketPerfStats);
+ assert(st->seglist_next);
uint32_t total = toSeq - st->seglist_next->seq;
DebugFormat(DEBUG_STREAM_STATE, "flushed %d bytes / %d segs on stream, %d still queued\n",
bytes_flushed, segs, bytes_queued);
- MODULE_PROFILE_END(s5TcpBuildPacketPerfStats);
return bytes_flushed;
}
static inline int _flush_to_seq(TcpSession *tcpssn, TcpTracker *st,
uint32_t bytes, Packet *p, uint32_t pkt_flags)
{
+ PERF_PROFILE(s5TcpFlushPerfStats);
+
uint32_t stop_seq;
uint32_t footprint;
uint32_t bytes_processed = 0;
int32_t flushed_bytes;
EncodeFlags enc_flags = 0;
- PROFILE_VARS;
-
- MODULE_PROFILE_START(s5TcpFlushPerfStats);
#ifdef HAVE_DAQ_ADDRESS_SPACE_ID
DAQ_PktHdr_t pkth;
{
DebugFormat(DEBUG_STREAM_STATE, "Negative footprint, bailing %d (0x%X - 0x%X)\n",
footprint, stop_seq, st->seglist_base_seq);
- MODULE_PROFILE_END(s5TcpFlushPerfStats);
return bytes_processed;
}
tcpStats.rebuilt_packets++;
UpdateStreamReassStats(&sfBase, flushed_bytes);
- MODULE_PROFILE_TMPEND(s5TcpFlushPerfStats);
+ PERF_PAUSE_BLOCK(s5TcpFlushPerfStats)
+ PERF_PROFILE_BLOCK(s5TcpProcessRebuiltPerfStats)
{
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpProcessRebuiltPerfStats);
-
Snort::detect_rebuilt_packet(s5_pkt);
-
- MODULE_PROFILE_END(s5TcpProcessRebuiltPerfStats);
- } MODULE_PROFILE_TMPSTART(s5TcpFlushPerfStats);
+ }
}
st->seglist_base_seq += flushed_bytes;
} while (st->seglist_next and DataToFlush(st));
/* tell them how many bytes we processed */
- MODULE_PROFILE_END(s5TcpFlushPerfStats);
return bytes_processed;
}
// because we don't wait until it is acknowledged
static inline uint32_t flush_pdu_ips(TcpSession* ssn, TcpTracker* trk, uint32_t* flags)
{
- uint32_t total = 0, avail;
- TcpSegment* seg;
- PROFILE_VARS;
+ PERF_PROFILE(s5TcpPAFPerfStats);
- MODULE_PROFILE_START(s5TcpPAFPerfStats);
- avail = get_q_sequenced(trk);
- seg = trk->seglist_next;
+ TcpSegment* seg = trk->seglist_next;
- // * must stop if gap (checked in paf_check)
+ uint32_t total = 0;
+ uint32_t avail = get_q_sequenced(trk);
+
+ // must stop if gap (checked in paf_check)
while (seg && *flags && (total < avail))
{
int32_t flush_pt;
if (flush_pt >= 0)
{
- MODULE_PROFILE_END(s5TcpPAFPerfStats);
-
// see flush_pdu_ackd()
if (!trk->splitter->is_paf() && avail > (unsigned) flush_pt)
{
seg = seg->next;
}
- MODULE_PROFILE_END(s5TcpPAFPerfStats);
return -1;
}
static inline uint32_t flush_pdu_ackd(TcpSession* ssn, TcpTracker* trk,
uint32_t* flags)
{
- uint32_t total = 0;
+ PERF_PROFILE(s5TcpPAFPerfStats);
+
TcpSegment* seg;
- PROFILE_VARS;
+ if ( SEQ_LT(trk->seglist_base_seq, trk->r_win_base) )
+ seg = trk->seglist;
+ else
+ seg = nullptr;
- MODULE_PROFILE_START(s5TcpPAFPerfStats);
- seg = SEQ_LT(trk->seglist_base_seq, trk->r_win_base) ? trk->seglist : NULL;
+ uint32_t total = 0;
// * must stop if not acked
// * must use adjusted size of seg if not fully acked
if (flush_pt >= 0)
{
- MODULE_PROFILE_END(s5TcpPAFPerfStats);
-
// for non-paf splitters, flush_pt > 0 means we reached
// the minimum required, but we flush what is available
// instead of creating more, but smaller, packets
seg = seg->next;
}
- MODULE_PROFILE_END(s5TcpPAFPerfStats);
return -1;
}
+
int CheckFlushPolicyOnData(TcpSession *tcpssn, TcpTracker *talker, TcpTracker *listener, Packet *p)
{
uint32_t flushed = 0;
const uint8_t* rdata = tdb->pkt->data;
uint16_t rsize = tdb->pkt->dsize;
uint32_t rseq = tdb->seq;
- PROFILE_VARS;
DEBUG_WRAP(
TcpSegment *lastptr = NULL;
uint32_t base_seq = st->seglist_base_seq;
DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
DebugMessage(DEBUG_STREAM_STATE, "!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+\n");
- MODULE_PROFILE_START(s5TcpInsertPerfStats);
+ PERF_PROFILE(s5TcpInsertPerfStats);
// NORM fast tracks are in sequence - no norms
if (st->seglist_tail && SegmentFastTrack(st->seglist_tail, tdb))
// BLOCK add to existing block and/or allocate new block
ret = AddStreamNode(st, tdb, len, slide /* 0 */, trunc /* 0 */, seq, left /* tail */);
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return ret;
}
/* flag an anomaly */
EventBadSegment();
inc_tcp_discards();
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return STREAM_INSERT_ANOMALY;
}
break;
/* flag an anomaly */
EventBadSegment();
inc_tcp_discards();
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return STREAM_INSERT_ANOMALY;
}
}
if (ret != STREAM_INSERT_OK)
{
/* No warning, its done in StreamSeglistAddNode */
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return ret;
}
left->size -= (int16_t) overlap;
/* flag an anomaly */
EventBadSegment();
inc_tcp_discards();
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return STREAM_INSERT_ANOMALY;
}
}
"(seq: %X seq_end: %X overlap: %lu\n", seq, seq_end, overlap);
EventBadSegment();
inc_tcp_discards();
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return STREAM_INSERT_ANOMALY;
}
slide = seq - tdb->seq;
ret = AddStreamNode(st, tdb, len, slide, trunc, seq, left);
if (ret != STREAM_INSERT_OK)
- {
- /* no warning, already done above */
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
+ // no warning, already done above
return ret;
- }
/* Set seq to end of right since overlap was greater than
* or equal to right->size and inserted seq has been
seq, seq_end, overlap);
EventBadSegment();
inc_tcp_discards();
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return STREAM_INSERT_ANOMALY;
}
break;
DebugMessage(DEBUG_STREAM_STATE, "StreamQueue returning normally\n");
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return ret;
}
static void NewQueue(TcpTracker *st, TcpDataBlock *tdb)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ PERF_PROFILE(s5TcpInsertPerfStats);
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpInsertPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
DebugMessage(DEBUG_STREAM_STATE, "In NewQueue\n");
if (overlap >= tdb->pkt->dsize)
{
DebugMessage(DEBUG_STREAM_STATE, "full overlap on ack'd data, dropping segment\n");
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
return;
}
}
DebugFormat(DEBUG_STREAM_STATE, "Attached new queue to seglist, %d bytes queued, base_seq 0x%X\n",
tdb->pkt->dsize-overlap, st->seglist_base_seq);
-
- MODULE_PROFILE_END(s5TcpInsertPerfStats);
}
static int ProcessTcpData(TcpTracker *listener, TcpSession *tcpssn,
TcpDataBlock *tdb, StreamTcpConfig *config)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
-
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpDataPerfStats);
+ PERF_PROFILE(s5TcpDataPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
uint32_t seq = tdb->seq;
if( tcph->is_syn() )
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, data on SYN, not MAC Policy!\n");
listener->normalizer->trim_syn_payload( tdb );
- MODULE_PROFILE_END(s5TcpDataPerfStats);
return STREAM_UNALIGNED;
}
}
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
listener->normalizer->trim_win_payload( tdb );
- MODULE_PROFILE_END(s5TcpDataPerfStats);
return STREAM_UNALIGNED;
}
ProcessTcpStream(listener, tcpssn, tdb, config);
/* set flags to session flags */
- MODULE_PROFILE_END(s5TcpDataPerfStats);
return STREAM_ALIGNED;
}
}
{
DebugMessage(DEBUG_STREAM_STATE, "Bailing, we're out of the window!\n");
listener->normalizer->trim_win_payload( tdb );
- MODULE_PROFILE_END(s5TcpDataPerfStats);
return STREAM_UNALIGNED;
}
}
}
- MODULE_PROFILE_END(s5TcpDataPerfStats);
return STREAM_UNALIGNED;
}
static void NewTcpSessionOnSyn(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ PERF_PROFILE(s5TcpNewSessPerfStats);
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
TcpSession* tss;
/******************************************************************
tcpStats.sessions_on_syn++;
NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
- MODULE_PROFILE_END(s5TcpNewSessPerfStats);
}
static void NewTcpSessionOnSynAck(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ PERF_PROFILE(s5TcpNewSessPerfStats);
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
TcpSession* tss;
tss = (TcpSession*) flow->session;
tcpStats.sessions_on_syn_ack++;
NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
- MODULE_PROFILE_END(s5TcpNewSessPerfStats);
}
static void NewTcpSessionOn3Way(Flow* flow, TcpDataBlock* tdb,
StreamTcpConfig* dstPolicy)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ PERF_PROFILE(s5TcpNewSessPerfStats);
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
TcpSession* tss;
/******************************************************************
tcpStats.sessions_on_3way++;
NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
- MODULE_PROFILE_END(s5TcpNewSessPerfStats);
}
static void NewTcpSessionOnData(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* dstPolicy)
{
- const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
+ PERF_PROFILE(s5TcpNewSessPerfStats);
- PROFILE_VARS; MODULE_PROFILE_START(s5TcpNewSessPerfStats);
+ const tcp::TCPHdr* tcph = tdb->pkt->ptrs.tcph;
TcpSession* tss;
tss = (TcpSession*) flow->session;
tcpStats.sessions_on_data++;
NewTcpSession(tdb->pkt, flow, dstPolicy, tss);
- MODULE_PROFILE_END(s5TcpNewSessPerfStats);
}
static int ProcessTcp(Flow* flow, TcpDataBlock* tdb, StreamTcpConfig* config)
{
+ PERF_PROFILE(s5TcpStatePerfStats);
+
int retcode = ACTION_NOTHING;
int eventcode = 0;
int got_ts = 0;
TcpTracker* talker = NULL;
TcpTracker* listener = NULL;
DEBUG_WRAP( const char* t = NULL; const char* l = NULL; );
- PROFILE_VARS;
if (flow->protocol != PktType::TCP)
{
tcpssn = ( TcpSession* ) flow->session;
- MODULE_PROFILE_START(s5TcpStatePerfStats);
-
if (!tcpssn->tcp_init)
{
// FIXIT-L expected flow should be checked by flow_con before we
StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_ESTABLISHED);
}
else if (!tdb->pkt->dsize)
- {
- /* Do nothing. */
- MODULE_PROFILE_END(s5TcpStatePerfStats);
+ // Do nothing.
return retcode;
- }
}
else
{
/* Got SYN/RST. We're done. */
listener->normalizer->trim_syn_payload( tdb );
listener->normalizer->trim_rst_payload( tdb );
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_RST;
}
else if (tcph->is_syn_only())
if (!tcpssn->tcp_init)
{
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode;
}
inc_tcp_discards();
listener->normalizer->trim_win_payload( tdb );
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
}
StreamUpdatePerfBaseState(&sfBase, flow, TCP_STATE_CLOSING);
/* Leave listener open, data may be in transit */
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_RST;
}
/* Reset not valid. */
eventcode |= EVENT_BAD_RST;
listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode;
}
listener->s_mgr.state = TCP_STATE_SYN_SENT;
DebugMessage(DEBUG_STREAM_STATE, "Accepted SYN ACK\n");
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode;
}
leave listener open, data may be in transit */
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_RST;
}
/* Reset not valid. */
eventcode |= EVENT_BAD_RST;
listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ts_action;
}
else
inc_tcp_discards();
listener->normalizer->trim_win_payload( tdb );
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ts_action;
}
}
inc_tcp_discards();
// this packet was normalized elsewhere
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ts_action;
}
/* got a bad SYN on the session, alert! */
eventcode |= EVENT_SYN_ON_EST;
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | action;
}
}
inc_tcp_discards();
listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
else if ((tdb->pkt->packet_flags & PKT_FROM_CLIENT) && (tdb->win <= SLAM_MAX)
if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
{
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
}
if (listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK))
{
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
}
eventcode |= EVENT_BAD_ACK;
LogTcpEvents(eventcode);
listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
break;
eventcode |= EVENT_BAD_FIN;
LogTcpEvents(eventcode);
listener->normalizer->packet_dropper(tdb, NORM_TCP_BLOCK);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_BAD_PKT;
}
}
LogTcpEvents(eventcode);
TcpSessionCleanup(flow, 0, tdb->pkt);
flow->session_state |= STREAM_STATE_CLOSED;
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode | ACTION_LWSSN_CLOSED;
}
else if( listener->s_mgr.state == TCP_STATE_CLOSED
}
LogTcpEvents(eventcode);
- MODULE_PROFILE_END(s5TcpStatePerfStats);
return retcode;
}
*/
int TcpSession::process(Packet* p)
{
+ PERF_PROFILE(s5TcpPerfStats);
+
TcpDataBlock tdb;
int status;
- PROFILE_VARS;
DEBUG_WRAP(
char flagbuf[9];
ntohl(p->ptrs.tcph->th_seq), ntohl(p->ptrs.tcph->th_ack), p->dsize);
);
- MODULE_PROFILE_START(s5TcpPerfStats);
-
if (stream.blocked_session(flow, p)
|| (flow->session_state & STREAM_STATE_IGNORE))
- {
- MODULE_PROFILE_END(s5TcpPerfStats);
return ACTION_NOTHING;
- }
+
SetupTcpDataBlock(&tdb, p);
StreamTcpConfig* config = get_tcp_cfg(flow->ssn_server);
event_mask |= EVENT_NO_3WHS;
}
- MODULE_PROFILE_END(s5TcpPerfStats);
#ifdef REG_TEST
S5TraceTCP(p, flow, &tdb, 1);
#endif
midstream_pickup_allowed: if (!p->ptrs.tcph->is_syn_ack()
&& !p->dsize && !(StreamPacketHasWscale(p) & TF_WSCALE))
{
- MODULE_PROFILE_END(s5TcpPerfStats);
#ifdef REG_TEST
S5TraceTCP(p, flow, &tdb, 1);
#endif
p->packet_flags & PKT_FROM_SERVER ? "server" : "client");
}
- MODULE_PROFILE_END(s5TcpPerfStats);
S5TraceTCP(p, flow, &tdb, 0);
return 0;
}
int UdpSession::process(Packet* p)
{
+ PERF_PROFILE(udp_perf_stats);
+
StreamUdpConfig* pc = get_udp_cfg(flow->ssn_server);
- SFXHASH_NODE* hash_node = NULL;
-
- PROFILE_VARS;
- MODULE_PROFILE_START(udp_perf_stats);
- /*
- * Check if the session is expired.
- * Should be done before we do something with the packet...
- */
+ // Check if the session is expired.
+ // Should be done before we do something with the packet...
if ( stream.expired_session(flow, p) )
{
UdpSessionCleanup(flow);
udpStats.created++;
udpStats.timeouts++;
}
- ProcessUdp(flow, p, pc, hash_node);
+
+ ProcessUdp(flow, p, pc, nullptr);
flow->markup_packet_flags(p);
flow->set_expire(p, pc->session_timeout);
- MODULE_PROFILE_END(udp_perf_stats);
return 0;
}
#ifdef ENABLE_EXPECTED_USER
if ( flow_con->expected_session(flow, p))
- {
- MODULE_PROFILE_END(user_perf_stats);
return false;
- }
#endif
return true;
}
int UserSession::process(Packet* p)
{
- PROFILE_VARS;
- MODULE_PROFILE_START(user_perf_stats);
+ PERF_PROFILE(user_perf_stats);
if ( stream.expired_session(flow, p) )
{
#ifdef ENABLE_EXPECTED_USER
if ( flow_con->expected_session(flow, p))
- {
- MODULE_PROFILE_END(user_perf_stats);
return 0;
- }
#endif
}
flow->set_direction(p);
if ( stream.blocked_session(flow, p) || stream.ignored_session(flow, p) )
- {
- MODULE_PROFILE_END(user_perf_stats);
return 0;
- }
update(p, flow);
if ( p->ptrs.decode_flags & DECODE_EOF )
end(p, flow);
- MODULE_PROFILE_END(user_perf_stats);
return 0;
}
+if ( ENABLE_PERFPROFILING )
+ set ( PERFPROFILING_SOURCES profiler.cc )
+endif ( ENABLE_PERFPROFILING )
+
set (TIME_INCLUDES
cpuclock.h
profiler.h
ppm.h
ppm_module.cc
ppm_module.h
- profiler.cc
+ ${PERFPROFILING_SOURCES}
periodic.cc
periodic.h
timersub.h
ppm.cc \
ppm_module.cc \
ppm_module.h \
-profiler.cc \
periodic.cc \
periodic.h \
timersub.h
+if PERF_PROFILING
+libtime_a_SOURCES += profiler.cc
+endif
#include <unistd.h>
#include <mutex>
-using namespace std;
+#include "time/cpuclock.h"
#include "detection/fp_detect.h"
#include "detection/treenodes.h"
#include "detection/rules.h"
#include "framework/module.h"
#include "hash/sfghash.h"
-// FIXIT-M: Instead of using preprocessor directives, use the build system
-// to control compilation of this module
-#ifdef PERF_PROFILING
+#ifdef UNIT_TEST
+#include "test/catch.hpp"
+#endif
+
+using namespace std;
+
+#define TOTAL "total"
+// -----------------------------------------------------------------------------
+// types
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// static variables
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// static functions
+// -----------------------------------------------------------------------------
+
+// FIXIT-L legacy stuff (to be cleaned up)
typedef struct _ProfileStatsNode
{
ProfileStats stats;
static ProfileStatsNode* get_node(const char*);
-#define TOTAL "total"
static ProfileStatsNode* get_root(ProfileStatsNode* idx)
{
if (num != 0)
{
indent += 2;
- LogMessage("%*d%*s%*d" FMTu64("*") FMTu64("*") FMTu64("*") "%*.2f%*.2f%*.2f\n",
+ LogMessage("%*d%*s%*d" FMTu64("*") FMTu64("*") "%*.2f%*.2f%*.2f\n",
indent, num,
28 - indent, idx->node->name, 6, idx->node->layer,
11, idx->node->stats.checks,
- 11, idx->node->stats.exits,
20, (uint64_t)(idx->node->stats.ticks/ticks_per_microsec),
11, idx->ticks_per_check/ticks_per_microsec,
14, idx->pct_of_parent,
/* The totals */
indent += strlen(idx->node->name);
- LogMessage("%*s%*s%*d" FMTu64("*") FMTu64("*") FMTu64("*") "%*.2f%*.2f%*.2f\n",
+ LogMessage("%*s%*s%*d" FMTu64("*") FMTu64("*") "%*.2f%*.2f%*.2f\n",
indent, idx->node->name,
28 - indent, idx->node->name, 6, idx->node->layer,
11, idx->node->stats.checks,
- 11, idx->node->stats.exits,
20, (uint64_t)(idx->node->stats.ticks/ticks_per_microsec),
11, idx->ticks_per_check/ticks_per_microsec,
14, idx->pct_of_parent,
assert(ps);
node->stats.ticks += ps->ticks;
- node->stats.ticks_start += ps->ticks_start;
node->stats.checks += ps->checks;
- node->stats.exits += ps->exits;
node = node->next;
}
else
LogMessage("Module Profile Statistics (all)\n");
- LogMessage("%*s%*s%*s%*s%*s%*s%*s%*s%*s\n",
+ LogMessage("%*s%*s%*s%*s%*s%*s%*s%*s\n",
4, "Num",
24, "Module",
6, "Layer",
11, "Checks",
- 11, "Exits",
20, "Microsecs",
11, "Avg/Check",
14, "Pct of Caller",
13, "Pct of Total");
- LogMessage("%*s%*s%*s%*s%*s%*s%*s%*s%*s\n",
+ LogMessage("%*s%*s%*s%*s%*s%*s%*s%*s\n",
4, "===",
24, "======",
6, "=====",
11, "======",
- 11, "=====",
20, "=========",
11, "=========",
14, "=============",
for (idx = gProfileStatsNodeList; idx != NULL; idx = idx->next)
{
idx->stats.ticks = 0;
- idx->stats.ticks_start = 0;
idx->stats.checks = 0;
- idx->stats.exits = 0;
}
}
CleanupProfileStatsNodeList();
}
-#endif
+// -----------------------------------------------------------------------------
+// non-static implementation
+// -----------------------------------------------------------------------------
+
+void NodePerfProfiler::update(bool match)
+{ stats.update(get_delta(), match); }
+
+// -----------------------------------------------------------------------------
+// public API
+// -----------------------------------------------------------------------------
+
+void PerfProfilerManager::register_module(Module* m)
+{ RegisterProfile(m); }
+
+void PerfProfilerManager::register_module(const char* name, const char* pname, Module* m)
+{ RegisterProfile(name, pname, nullptr, m); }
+
+void PerfProfilerManager::register_module(const char* name, const char* pname,
+ get_profile_func getter)
+{ RegisterProfile(name, pname, getter, nullptr); }
+
+// thread local
+void PerfProfilerManager::consolidate_stats()
+{ ReleaseProfileStats(); }
+
+void PerfProfilerManager::show_module_stats()
+{ ShowPreprocProfiles(); }
+
+void PerfProfilerManager::reset_module_stats()
+{ }
+
+void PerfProfilerManager::show_rule_stats()
+{ ShowRuleProfiles(); }
+
+void PerfProfilerManager::reset_rule_stats()
+{ }
+
+void PerfProfilerManager::show_all_stats()
+{
+ if ( SnortConfig::get_profile_modules() )
+ show_module_stats();
+
+ if ( SnortConfig::get_profile_rules() )
+ show_rule_stats();
+}
+
+void PerfProfilerManager::reset_all_stats()
+{ }
+
+void PerfProfilerManager::init()
+{ }
+
+void PerfProfilerManager::term()
+{ CleanupProfileStatsNodeList(); }
+
+// -----------------------------------------------------------------------------
+// unit tests
+// -----------------------------------------------------------------------------
+
+#ifdef UNIT_TEST
+
+struct ProfilePauseObserver
+{
+ void start()
+ {
+ start_called = true;
+ if ( pause_called )
+ pause_called_before_start = true;
+ }
+
+ void pause()
+ { pause_called = true; }
+
+ bool pause_called = false;
+ bool start_called = false;
+ bool pause_called_before_start = false;
+};
+
+TEST_CASE( "stopwatch", "[profiler]" )
+{
+ Stopwatch sw;
+
+ REQUIRE_FALSE( sw.alive() );
+ REQUIRE( sw.get() == 0 );
+
+ SECTION( "start" )
+ {
+ sw.start();
+
+ SECTION( "sets clock to alive" )
+ {
+ CHECK( sw.alive() );
+ }
+ SECTION( "running elapsed time should be non-zero" )
+ {
+ CHECK( sw.get() > 0 );
+ }
+
+ SECTION( "start on running clock has no effect" )
+ {
+ auto val = sw.get();
+ sw.start();
+ CHECK( sw.alive() );
+ CHECK( sw.get() > val );
+ }
+ }
+
+ SECTION( "stop" )
+ {
+ sw.start();
+ sw.stop();
+
+ SECTION( "sets clock to be dead" )
+ {
+ CHECK_FALSE( sw.alive() );
+ }
+
+ SECTION( "ticks should not increase after death" )
+ {
+ auto val = sw.get();
+ CHECK( val == sw.get() );
+ }
+
+ SECTION( "stop on stopped clock has no effect" )
+ {
+ auto val = sw.get();
+ sw.stop();
+ CHECK_FALSE( sw.alive() );
+ CHECK( val == sw.get() );
+ }
+ }
+
+ SECTION( "reset" )
+ {
+ sw.start();
+
+ SECTION( "reset on running clock" )
+ {
+ sw.reset();
+ CHECK_FALSE( sw.alive() );
+ CHECK( sw.get() == 0 );
+ }
+
+ SECTION( "reset on stopped clock" )
+ {
+ sw.stop();
+ sw.reset();
+ CHECK_FALSE( sw.alive() );
+ CHECK( sw.get() == 0 );
+ }
+ }
+
+ SECTION( "cancel" )
+ {
+ sw.start();
+ SECTION( "cancel on running clock that has no lap time" )
+ {
+ sw.cancel();
+ CHECK_FALSE( sw.alive() );
+ CHECK( sw.get() == 0 );
+ }
+
+ SECTION( "cancel on stopped clock that has lap time" )
+ {
+ sw.stop();
+ auto val = sw.get();
+ sw.cancel();
+
+ CHECK_FALSE( sw.alive() );
+ CHECK( val == sw.get() );
+ }
+ }
+}
+
+TEST_CASE( "perf profiler base", "[profiler]" )
+{
+ SECTION( "profiler is started on instantiation" )
+ {
+ PerfProfilerBase prof;
+ CHECK( prof.get_delta() > 0 );
+ }
+
+ SECTION( "profiler evaluates to true" )
+ {
+ PerfProfilerBase prof;
+ CHECK( prof );
+ }
+}
+
+TEST_CASE( "perf profiler", "[profiler]" )
+{
+ ProfileStats stats = { 0, 0 };
+
+ REQUIRE( stats.ticks == 0 );
+ REQUIRE( stats.checks == 0 );
+
+ SECTION( "going out of scope causes profiler to update stats" )
+ {
+ {
+ PerfProfiler prof(stats);
+ }
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+
+ SECTION( "stopping profiler is only done once" )
+ {
+ PerfProfiler prof(stats);
+ prof.stop();
+ ProfileStats saved = stats;
+ prof.stop();
+
+ CHECK( saved.ticks == stats.ticks );
+ CHECK( saved.checks == stats.checks );
+ }
+
+ SECTION( "profiler can be stopped while paused" )
+ {
+ PerfProfiler prof(stats);
+ prof.pause();
+ prof.stop();
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+
+ SECTION( "profiler can be pause and restarted" )
+ {
+ PerfProfiler prof(stats);
+ prof.pause();
+ prof.start();
+
+ CHECK( stats.ticks == 0 );
+ CHECK( stats.checks == 0 );
+
+ prof.stop();
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+
+ SECTION( "profiler correctly handles exceptions" )
+ {
+ try
+ {
+ PerfProfiler prof(stats);
+ throw int(1);
+ }
+
+ catch( int& )
+ { }
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+}
+
+TEST_CASE( "node perf profiler", "[profiler]" )
+{
+ dot_node_state_t stats;
+
+ stats.ticks = 0;
+ stats.ticks_match = 0;
+ stats.ticks_no_match = 0;
+ stats.checks = 0;
+
+ SECTION( "going out of scope causes profiler to update stats" )
+ {
+ {
+ NodePerfProfiler prof(stats);
+ }
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+
+ SECTION( "evaluates to NO MATCH by default" )
+ {
+ CHECK( stats.ticks_no_match > 0 );
+ }
+ }
+
+ SECTION( "stopping profiler is only done once" )
+ {
+ NodePerfProfiler prof(stats);
+ prof.stop(false);
+ dot_node_state_t saved = stats;
+ prof.stop(true);
+
+ CHECK( saved.ticks == stats.ticks );
+ CHECK( saved.checks == stats.checks );
+
+ SECTION( "only one of match or no match is updated" )
+ {
+ CHECK( stats.ticks_no_match > 0 );
+ CHECK( stats.ticks_match == 0 );
+ }
+ }
+
+ SECTION( "profiler can be stopped while paused" )
+ {
+ NodePerfProfiler prof(stats);
+ prof.pause();
+ prof.stop(false);
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+
+ SECTION( "profiler can be pause and restarted" )
+ {
+ NodePerfProfiler prof(stats);
+ prof.pause();
+ prof.start();
+
+ CHECK( stats.ticks == 0 );
+ CHECK( stats.checks == 0 );
+
+ prof.stop(false);
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+
+ SECTION( "profiler uses MATCH when stop(true) is called" )
+ {
+ NodePerfProfiler prof(stats);
+ prof.stop(true);
+
+ CHECK( stats.ticks_match > 0 );
+
+ SECTION( "and doesn't update NO MATCH" )
+ {
+ CHECK( stats.ticks_no_match == 0 );
+ }
+ }
+
+ SECTION( "profiler correctly handles exceptions" )
+ {
+ try
+ {
+ NodePerfProfiler prof(stats);
+ throw int(1);
+ }
+
+ catch( int& )
+ { }
+
+ CHECK( stats.ticks > 0 );
+ CHECK( stats.checks == 1 );
+ }
+}
+
+TEST_CASE( "perf profiler pause", "[profiler]" )
+{
+ ProfilePauseObserver observer;
+
+ {
+ ProfilerPause<decltype(observer)> pause(observer);
+ }
+
+ CHECK( observer.pause_called );
+ CHECK( observer.start_called );
+ CHECK( observer.pause_called_before_start );
+}
+
+#endif
struct ProfileStats
{
uint64_t ticks;
- uint64_t ticks_start;
uint64_t checks;
- uint64_t exits;
+
+ void update(uint64_t elapsed)
+ { ++checks; ticks += elapsed; }
};
-#ifdef PERF_PROFILING
#include "main/thread.h"
#include "time/cpuclock.h"
-// Sort preferences for rule profiling
-#define PROFILE_SORT_CHECKS 1
-#define PROFILE_SORT_AVG_TICKS 2
-#define PROFILE_SORT_TOTAL_TICKS 3
-#define PROFILE_SORT_MATCHES 4
-#define PROFILE_SORT_NOMATCHES 5
-#define PROFILE_SORT_AVG_TICKS_PER_MATCH 6
-#define PROFILE_SORT_AVG_TICKS_PER_NOMATCH 7
-
-// MACROS that handle profiling of rules and preprocessors
-#define PROFILE_VARS_NAMED(name) uint64_t name ## _ticks_start, name ## _ticks_end
-#define PROFILE_VARS PROFILE_VARS_NAMED(snort)
+// FIXIT-L should go in its own module
+class Stopwatch
+{
+public:
+ Stopwatch() :
+ elapsed { 0 }, running { false } { }
-#define PROFILE_START_NAMED(name) \
- get_clockticks(name ## _ticks_start)
+ void start()
+ {
+ if ( running )
+ return;
-#define PROFILE_END_NAMED(name) \
- get_clockticks(name ## _ticks_end)
+ get_clockticks(ticks_start);
+ running = true;
+ }
-#define NODE_PROFILE_END \
- PROFILE_END_NAMED(node); \
- node_ticks_delta = node_ticks_end - node_ticks_start
+ void stop()
+ {
+ if ( !running )
+ return;
-#ifndef PROFILING_RULES
-#define PROFILING_RULES SnortConfig::get_profile_rules()
-#endif
+ elapsed += get_delta();
+ running = false;
+ }
-#define NODE_PROFILE_VARS \
- uint64_t node_ticks_start = 0, node_ticks_end, node_ticks_delta, node_deltas = 0
+ uint64_t get() const
+ {
+ if ( running )
+ return elapsed + get_delta();
-#define NODE_PROFILE_START(node) \
- if (PROFILING_RULES) { \
- unsigned id = get_instance_id(); \
- node->state[id].checks++; \
- PROFILE_START_NAMED(node); \
+ return elapsed;
}
-#define NODE_PROFILE_END_MATCH(node) \
- if (PROFILING_RULES) { \
- NODE_PROFILE_END; \
- unsigned id = get_instance_id(); \
- node->state[id].ticks += node_ticks_delta + node_deltas; \
- node->state[id].ticks_match += node_ticks_delta + node_deltas; \
- }
+ bool alive() const
+ { return running; }
+
+ void reset()
+ { running = false; elapsed = 0; }
-#define NODE_PROFILE_END_NOMATCH(node) \
- if (PROFILING_RULES) { \
- NODE_PROFILE_END; \
- unsigned id = get_instance_id(); \
- node->state[id].ticks += node_ticks_delta + node_deltas; \
- node->state[id].ticks_no_match += node_ticks_delta + node_deltas; \
+ void cancel()
+ { running = false; }
+
+private:
+ uint64_t get_delta() const
+ {
+ uint64_t ticks_stop;
+ get_clockticks(ticks_stop);
+ return ticks_stop - ticks_start;
}
-#define NODE_PROFILE_TMPSTART(node) \
- if (PROFILING_RULES) { \
- PROFILE_START_NAMED(node); \
+ uint64_t elapsed;
+ bool running;
+ uint64_t ticks_start;
+};
+
+class PerfProfilerBase
+{
+public:
+ PerfProfilerBase()
+ { start(); }
+
+ void start()
+ { sw.start(); }
+
+ void pause()
+ { sw.stop(); }
+
+ // for macro block
+ operator bool() const
+ { return true; }
+
+ uint64_t get_delta() const
+ { return sw.get(); }
+
+private:
+ Stopwatch sw;
+};
+
+class PerfProfiler : public PerfProfilerBase
+{
+public:
+ PerfProfiler(ProfileStats& ps) :
+ PerfProfilerBase(), stats(ps), closed { false } { }
+
+ ~PerfProfiler()
+ { stop(); }
+
+ // Once a profiler is stopped, it cannot be restarted
+ void stop()
+ {
+ if ( closed )
+ return;
+
+ stats.update(get_delta());
+ closed = true;
}
-#define NODE_PROFILE_TMPEND(node) \
- if (PROFILING_RULES) { \
- NODE_PROFILE_END; \
- node_deltas += node_ticks_delta; \
+private:
+ ProfileStats& stats;
+ bool closed;
+};
+
+struct dot_node_state_t;
+
+class NodePerfProfiler : public PerfProfilerBase
+{
+public:
+ NodePerfProfiler(dot_node_state_t& dns) :
+ PerfProfilerBase(), stats(dns), closed { false } { }
+
+ // If no stop is explicitly specified, assume no match
+ ~NodePerfProfiler()
+ { stop(false); }
+
+ void stop(bool match)
+ {
+ if ( closed )
+ return;
+
+ update(match);
+ closed = true;
}
-#define OTN_PROFILE_ALERT(otn) otn->state[get_instance_id()].alerts++;
+private:
+ void update(bool);
+ dot_node_state_t& stats;
+ bool closed;
+};
+
+template<typename Profiler>
+struct ProfilerPause
+{
+ ProfilerPause(Profiler& prof) :
+ profiler(prof)
+ { profiler.pause(); }
+
+ ~ProfilerPause()
+ { profiler.start(); }
+
+ // for macro block
+ operator bool() const
+ { return true; }
+
+ Profiler& profiler;
+};
+
+#ifdef PERF_PROFILING
#ifndef PROFILING_MODULES
#define PROFILING_MODULES SnortConfig::get_profile_modules()
#endif
-#define MODULE_PROFILE_START_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- ppstat.checks++; \
- PROFILE_START_NAMED(name); \
- ppstat.ticks_start = name ## _ticks_start; \
- }
-#define MODULE_PROFILE_START(ppstat) MODULE_PROFILE_START_NAMED(snort, ppstat)
+#ifndef PROFILING_RULES
+#define PROFILING_RULES SnortConfig::get_profile_rules()
+#endif
-#define MODULE_PROFILE_REENTER_START_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- PROFILE_START_NAMED(name); \
- ppstat.ticks_start = name ## _ticks_start; \
- }
-#define MODULE_PROFILE_REENTER_START(ppstat) MODULE_PROFILE_REENTER_START_NAMED(snort, ppstat)
+#define PERF_PROFILER_NAME(stats) \
+ stats ## _perf_profiler
-#define MODULE_PROFILE_TMPSTART_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- PROFILE_START_NAMED(name); \
- ppstat.ticks_start = name ## _ticks_start; \
- }
-#define MODULE_PROFILE_TMPSTART(ppstat) MODULE_PROFILE_TMPSTART_NAMED(snort, ppstat)
+#define PERF_PAUSE_NAME(stats) \
+ stats ## _perf_pause
-#define MODULE_PROFILE_END_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- PROFILE_END_NAMED(name); \
- ppstat.exits++; \
- ppstat.ticks += name ## _ticks_end - ppstat.ticks_start; \
- }
-#define MODULE_PROFILE_END(ppstat) MODULE_PROFILE_END_NAMED(snort, ppstat)
+#define PERF_PROFILE(stats) \
+ PerfProfiler PERF_PROFILER_NAME(stats) { stats }
-#define MODULE_PROFILE_REENTER_END_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- PROFILE_END_NAMED(name); \
- ppstat.ticks += name ## _ticks_end - ppstat.ticks_start; \
- }
-#define MODULE_PROFILE_REENTER_END(ppstat) MODULE_PROFILE_REENTER_END_NAMED(snort, ppstat)
+#define PERF_PROFILE_BLOCK(stats) \
+ if ( PERF_PROFILE(stats) )
-#define MODULE_PROFILE_TMPEND_NAMED(name, ppstat) \
- if (PROFILING_MODULES) { \
- PROFILE_END_NAMED(name); \
- ppstat.ticks += name ## _ticks_end - ppstat.ticks_start; \
- }
-#define MODULE_PROFILE_TMPEND(ppstat) MODULE_PROFILE_TMPEND_NAMED(snort, ppstat)
+#define NODE_PERF_PROFILE(stats) \
+ NodePerfProfiler PERF_PROFILER_NAME(stats) { stats }
+
+#define NODE_PERF_PROFILE_BLOCK(stats) \
+ if ( NODE_PERF_PROFILE(stats) )
+
+#define NODE_PERF_PROFILE_STOP_MATCH(stats) \
+ PERF_PROFILER_NAME(stats) .stop(true)
+
+#define NODE_PERF_PROFILE_STOP_NO_MATCH(stats) \
+ PERF_PROFILER_NAME(stats) .stop(false)
+
+#define PERF_PAUSE_BLOCK(stats) \
+ if ( ProfilerPause<decltype(PERF_PROFILER_NAME(stats))> \
+ PERF_PAUSE_NAME(stats) { PERF_PROFILER_NAME(stats) } )
+// thread local access method
+using get_profile_func = ProfileStats* (*)(const char*);
+
+class PerfProfilerManager
+{
+public:
+ static void register_module(Module*);
+ static void register_module(const char*, const char*, Module*);
+ static void register_module(const char*, const char*, get_profile_func);
+
+ // thread local
+ static void consolidate_stats();
+
+ static void show_module_stats();
+ static void reset_module_stats();
+
+ static void show_rule_stats();
+ static void reset_rule_stats();
+
+ static void show_all_stats();
+ static void reset_all_stats();
+
+ static void init();
+ static void term();
+};
+
+// Sort preferences for rule profiling
+#define PROFILE_SORT_CHECKS 1
+#define PROFILE_SORT_AVG_TICKS 2
+#define PROFILE_SORT_TOTAL_TICKS 3
+#define PROFILE_SORT_MATCHES 4
+#define PROFILE_SORT_NOMATCHES 5
+#define PROFILE_SORT_AVG_TICKS_PER_MATCH 6
+#define PROFILE_SORT_AVG_TICKS_PER_NOMATCH 7
+
// -----------------------------------------------------------------------------
// Profiling API
// -----------------------------------------------------------------------------
int sort;
};
-void ShowRuleProfiles(void);
-void ResetRuleProfiling(void);
-
-// thread local access method
-using get_profile_func = ProfileStats* (*)(const char*);
-
-void RegisterProfile(
- const char* keyword, const char* parent,
- get_profile_func, class Module* owner = nullptr);
-
-void RegisterProfile(class Module*);
-
-void ShowPreprocProfiles(void);
-void ResetPreprocProfiling(void);
-void ReleaseProfileStats(void);
-void CleanupProfileStatsNodeList(void);
-
extern THREAD_LOCAL ProfileStats totalPerfStats;
extern THREAD_LOCAL ProfileStats metaPerfStats;
-#else
-#define PROFILE_VARS
-#define PROFILE_VARS_NAMED(name)
-#define NODE_PROFILE_VARS
-#define NODE_PROFILE_START(node)
-#define NODE_PROFILE_END_MATCH(node)
-#define NODE_PROFILE_END_NOMATCH(node)
-#define NODE_PROFILE_TMPSTART(node)
-#define NODE_PROFILE_TMPEND(node)
-#define OTN_PROFILE_ALERT(otn)
-#define MODULE_PROFILE_START(ppstat)
-#define MODULE_PROFILE_START_NAMED(name, ppstat)
-#define MODULE_PROFILE_REENTER_START(ppstat)
-#define MODULE_PROFILE_REENTER_START_NAMED(name, ppstat)
-#define MODULE_PROFILE_TMPSTART(ppstat)
-#define MODULE_PROFILE_TMPSTART_NAMED(name, ppstat)
-#define MODULE_PROFILE_END(ppstat)
-#define MODULE_PROFILE_END_NAMED(name, ppstat)
-#define MODULE_PROFILE_REENTER_END(ppstat)
-#define MODULE_PROFILE_REENTER_END_NAMED(name, ppstat)
-#define MODULE_PROFILE_TMPEND(ppstat)
-#define MODULE_PROFILE_TMPEND_NAMED(name, ppstat)
-#endif // PERF_PROFILING
-
-static inline void ShowAllProfiles()
-{
-#ifdef PERF_PROFILING
- ShowPreprocProfiles();
- ShowRuleProfiles();
-#endif
-}
-static inline void ResetAllProfiles()
-{
-#ifdef PERF_PROFILING
- ResetPreprocProfiling();
- ResetRuleProfiling();
-#endif
-}
+#else
+#define PERF_PROFILER_NAME(stats)
+#define PERF_PAUSE_NAME(stats)
+#define PERF_PROFILE(stats)
+#define PERF_PROFILE_BLOCK(stats)
+#define NODE_PERF_PROFILE(stats)
+#define NODE_PERF_PROFILE_BLOCK(stats)
+#define NODE_PERF_PROFILE_STOP_MATCH(stats)
+#define NODE_PERF_PROFILE_STOP_NO_MATCH(stats)
+#define PERF_PAUSE_BLOCK(stats)
+#endif // PERF_PROFILING
#endif
snort_conf->logging_flags &= ~LOGGING_FLAG__QUIET;
- ShowAllProfiles();
+ PerfProfilerManager::show_all_stats();
snort_conf->logging_flags |= save_quiet_flag;
}