p->context->conf = SnortConfig::get_conf();
- // Build the searches list in the packet context
- fp_partial(p);
-
- if (p->context->searches.items.size() > 0)
- {
- trace_logf(detection, TRACE_DETECTION_ENGINE, "%" PRIu64 " de::offload %" PRIu64
- " (r=%d)\n", p->context->packet_number, p->context->context_num,
- offloader->count());
+ trace_logf(detection, TRACE_DETECTION_ENGINE, "%" PRIu64 " de::offload %" PRIu64
+ " (r=%d)\n", p->context->packet_number, p->context->context_num,
+ offloader->count());
- sw->suspend();
- p->set_offloaded();
+ sw->suspend();
+ p->set_offloaded();
- offloader->put(p);
- pc.offloads++;
+ offloader->put(p);
+ pc.offloads++;
- return true;
- }
- else
- {
- bool depends_on_suspended = p->flow ? p->flow->context_chain.front() :
- sw->non_flow_chain.front();
-
- if (!depends_on_suspended)
- {
- fp_complete(p);
- return false;
- }
- else
- {
- sw->suspend();
- pc.offload_suspends++;
- return true;
- }
- }
+#ifdef REG_TEST
+ onload();
+ return false;
+#else
+ return true;
+#endif
}
bool DetectionEngine::offload(Packet* p)
{
ContextSwitcher* sw = Analyzer::get_switcher();
+ fp_partial(p);
- bool depends_on_suspended =
- p->flow ? p->flow->context_chain.front() : sw->non_flow_chain.front();
-
- bool should_offload = p->dsize >= SnortConfig::get_conf()->offload_limit;
-
- if ( should_offload )
+ if ( p->dsize >= SnortConfig::get_conf()->offload_limit and
+ p->context->searches.items.size() > 0 )
{
if ( offloader->available() )
return do_offload(p);
pc.offload_busy++;
}
- if ( depends_on_suspended )
+ if ( p->flow ? p->flow->context_chain.front() : sw->non_flow_chain.front() )
{
- fp_partial(p);
p->context->searches.search_sync();
sw->suspend();
pc.offload_suspends++;
}
assert(p->flow ? !p->flow->is_suspended() : true);
- fp_full(p);
+ fp_complete(p, true);
return false;
}
void DetectionEngine::resume_ready_suspends(IpsContextChain& chain)
{
while ( chain.front() and !chain.front()->packet->is_offloaded() )
+ {
+#ifdef REG_TEST
+ complete(chain.front()->packet);
+#else
resume(chain.front()->packet);
+#endif
+ }
}
-void DetectionEngine::resume(Packet* p)
+void DetectionEngine::complete(Packet* p)
{
trace_logf(detection, TRACE_DETECTION_ENGINE, "%" PRIu64 " de::resume %" PRIu64 " (r=%d)\n",
p->context->packet_number, p->context->context_num, offloader->count());
sw->resume(p->context);
fp_complete(p);
+}
+
+void DetectionEngine::resume(Packet* p)
+{
+ complete(p);
+
finish_inspect_with_latency(p); // FIXIT-L should latency be evaluated here?
finish_inspect(p, true);
finish_packet(p);
static struct SF_EVENTQ* get_event_queue();
static bool do_offload(snort::Packet*);
static void offload_thread(IpsContext*);
+ static void complete(snort::Packet*);
static void resume(snort::Packet*);
static void resume_ready_suspends(IpsContextChain&);
{
const MpseApi* search_api = nullptr;
const MpseApi* offload_search_api = nullptr;
- PatternMatchVector pmv;
OptFpList* next = nullptr;
- bool only_literal;
bool exclude;
// skip builtin rules, continue for text and so rules
search_api = fp->get_search_api();
assert(search_api);
- only_literal = !MpseManager::is_regex_capable(search_api);
-
- pmv = get_fp_content(otn, next, srvc, only_literal, exclude);
+ bool only_literal = !MpseManager::is_regex_capable(search_api);
+ PatternMatchVector pmv = get_fp_content(otn, next, srvc, only_literal, exclude);
if ( !pmv.empty() )
{
pmv.pop_back();
if ( !main_pmd->is_relative() && !main_pmd->is_negated() && main_pmd->fp_only >= 0 &&
- // FIXIT-L no_case consideration is mpse specific, delegate
- !main_pmd->offset && !main_pmd->depth && main_pmd->is_no_case() )
+ // FIXIT-L no_case consideration is mpse specific, delegate
+ !main_pmd->offset && !main_pmd->depth && main_pmd->is_no_case() )
{
if ( !next || !next->ips_opt || !next->ips_opt->is_relative() )
main_pmd->fp_only |= (1 << Mpse::MPSE_TYPE_NORMAL);
{
if (!pg->mpsegrp[main_pmd->pm_type]->create_normal_mpse(sc, &agent))
{
- ParseError("Failed to create normal pattern matcher for %d", main_pmd->pm_type);
+ ParseError("Failed to create normal pattern matcher for %d",
+ main_pmd->pm_type);
return -1;
}
pmv_ol.pop_back();
if ( !ol_pmd->is_relative() && !ol_pmd->is_negated() && ol_pmd->fp_only >= 0 &&
- // FIXIT-L no_case consideration is mpse specific, delegate
- !ol_pmd->offset && !ol_pmd->depth && ol_pmd->is_no_case() )
+ // FIXIT-L no_case consideration is mpse specific, delegate
+ !ol_pmd->offset && !ol_pmd->depth && ol_pmd->is_no_case() )
{
if ( !next_ol || !next_ol->ips_opt || !next_ol->ips_opt->is_relative() )
ol_pmd->fp_only |= (1 << Mpse::MPSE_TYPE_OFFLOAD);
if (!pg->mpsegrp[main_pmd->pm_type]->create_offload_mpse(sc, &agent_offload))
{
ParseError("Failed to create offload pattern matcher for %d",
- main_pmd->pm_type);
+ main_pmd->pm_type);
return -1;
}
// Now add patterns
if (fpFinishPortGroupRule(sc, pg->mpsegrp[main_pmd->pm_type]->normal_mpse,
- otn, main_pmd, fp, Mpse::MPSE_TYPE_NORMAL, true) == 0)
+ otn, main_pmd, fp, Mpse::MPSE_TYPE_NORMAL, true) == 0)
{
if (main_pmd->pattern_size > otn->longestPatternLen)
otn->longestPatternLen = main_pmd->pattern_size;
// Add Alternative patterns
for (auto p : pmv)
fpAddAlternatePatterns(sc, pg->mpsegrp[main_pmd->pm_type]->normal_mpse,
- otn, p, fp, Mpse::MPSE_TYPE_NORMAL);
+ otn, p, fp, Mpse::MPSE_TYPE_NORMAL);
}
}
// Now add patterns
if (fpFinishPortGroupRule(sc, pg->mpsegrp[main_pmd->pm_type]->offload_mpse,
- otn, ol_pmd, fp, Mpse::MPSE_TYPE_OFFLOAD, true) == 0)
+ otn, ol_pmd, fp, Mpse::MPSE_TYPE_OFFLOAD, true) == 0)
{
if (ol_pmd->pattern_size > otn->longestPatternLen)
otn->longestPatternLen = ol_pmd->pattern_size;
// Add Alternative patterns
for (auto p : pmv_ol)
fpAddAlternatePatterns(sc, pg->mpsegrp[main_pmd->pm_type]->offload_mpse,
- otn, p, fp, Mpse::MPSE_TYPE_OFFLOAD);
+ otn, p, fp, Mpse::MPSE_TYPE_OFFLOAD);
}
}
- if (add_rule)
+ if ( add_rule )
{
- if (add_nfp_rule)
- pg->add_nfp_rule(otn);
- else
+ if ( !add_nfp_rule )
pg->add_rule();
+ else
+ {
+ pg->add_nfp_rule(otn);
+ print_nfp_info(s_group, otn);
+ }
}
-
return 0;
}
}
if ( otn->warned_fp() )
return;
- ParseWarning(WARN_RULES, "%s rule %u:%u:%u has no fast pattern",
- group, otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev);
+ const char* type = otn->longestPatternLen ? "negated" : "no";
+
+ ParseWarning(WARN_RULES, "%s rule %u:%u:%u has %s fast pattern",
+ group, otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev, type);
otn->set_warned_fp();
}
THREAD_LOCAL ProfileStats ruleOTNEvalPerfStats;
THREAD_LOCAL ProfileStats ruleNFPEvalPerfStats;
+static void fp_immediate(Packet*);
+
// Initialize the OtnxMatchData structure. We do this for
// every packet so this only sets the necessary counters to
// zero which saves us time.
assert(so->get_normal_mpse()->get_pattern_count() > 0);
cnt++;
- //FIXIT-P Batch outer UDP payload searches for teredo set and the outer header
- //during any signature evaluation
+ // FIXIT-P Batch outer UDP payload searches for teredo set and the outer header
+ // during any signature evaluation
if ( omd->p->ptrs.udph && (omd->p->proto_bits & (PROTO_BIT__TEREDO | PROTO_BIT__GTP)) )
{
int start_state = 0;
return 0;
}
-// This function does a set-wise match on content, and walks an otn list
-// for non-content. The otn list search will eventually be redone for
-// for performance purposes.
-
-static inline int fpEvalHeaderSW(PortGroup* port_group, Packet* p,
- int check_ports, char ip_rule, int type, OtnxMatchData* omd, FPTask task)
+static inline void eval_fp(
+ PortGroup* port_group, Packet* p, OtnxMatchData* omd, char ip_rule,
+ int check_ports, int type)
{
- if ( !p->is_detection_enabled(p->packet_flags & PKT_FROM_CLIENT) )
- return 0;
-
const uint8_t* tmp_payload = nullptr;
- int8_t curr_ip_layer = 0;
- bool repeat = false;
uint16_t tmp_dsize = 0;
- FastPatternConfig* fp = SnortConfig::get_conf()->fast_pattern_config;
- print_pkt_info(p);
+ if ( !ip_rule )
+ p->packet_flags &= ~PKT_IP_RULE;
- if ( task & FPTask::FP )
+ else
{
- if (ip_rule)
- {
- tmp_payload = p->data;
- tmp_dsize = p->dsize;
+ int8_t curr_ip_layer = 0;
- if (layer::set_outer_ip_api(p, p->ptrs.ip_api, curr_ip_layer))
- {
- p->data = p->ptrs.ip_api.ip_data();
- p->dsize = p->ptrs.ip_api.pay_len();
- p->packet_flags |= PKT_IP_RULE;
- repeat = true;
- }
- }
- else
+ tmp_payload = p->data; // FIXIT-H restore even with offload
+ tmp_dsize = p->dsize;
+
+ if (layer::set_outer_ip_api(p, p->ptrs.ip_api, curr_ip_layer))
{
- p->packet_flags &= ~PKT_IP_RULE;
+ p->data = p->ptrs.ip_api.ip_data();
+ p->dsize = p->ptrs.ip_api.pay_len();
+ p->packet_flags |= PKT_IP_RULE;
}
+ }
+
+ if ( DetectionEngine::content_enabled(p) )
+ {
+ FastPatternConfig* fp = SnortConfig::get_conf()->fast_pattern_config;
- if ( DetectionEngine::content_enabled(p) )
+ if ( fp->get_stream_insert() || !(p->packet_flags & PKT_STREAM_INSERT) )
+ if ( fp_search(port_group, p, check_ports, type, omd) )
+ return;
+ }
+ if ( ip_rule )
+ {
+ p->data = tmp_payload;
+ p->dsize = tmp_dsize;
+ }
+}
+
+static inline void eval_nfp(
+ PortGroup* port_group, Packet* p, OtnxMatchData* omd, char ip_rule)
+{
+ bool repeat = false;
+ int8_t curr_ip_layer = 0;
+
+ const uint8_t* tmp_payload = nullptr;
+ uint16_t tmp_dsize = 0;
+
+ FastPatternConfig* fp = SnortConfig::get_conf()->fast_pattern_config;
+
+ if (ip_rule)
+ {
+ tmp_payload = p->data;
+ tmp_dsize = p->dsize;
+
+ if (layer::set_outer_ip_api(p, p->ptrs.ip_api, curr_ip_layer))
{
- if ( fp->get_stream_insert() || !(p->packet_flags & PKT_STREAM_INSERT) )
- if ( fp_search(port_group, p, check_ports, type, omd) )
- return 0;
+ p->data = p->ptrs.ip_api.ip_data();
+ p->dsize = p->ptrs.ip_api.pay_len();
+ p->packet_flags |= PKT_IP_RULE;
+ repeat = true;
}
}
-
- if ( task & FPTask::NON_FP )
+ do
{
- do
+ if (port_group->nfp_rule_count)
{
- if (port_group->nfp_rule_count)
- {
- // walk and test the nfp OTNs
- if ( fp->get_debug_print_nc_rules() )
- LogMessage("NC-testing %u rules\n", port_group->nfp_rule_count);
+ // walk and test the nfp OTNs
+ if ( fp->get_debug_print_nc_rules() )
+ LogMessage("NC-testing %u rules\n", port_group->nfp_rule_count);
- detection_option_eval_data_t eval_data;
+ detection_option_eval_data_t eval_data;
- eval_data.pomd = omd;
- eval_data.p = p;
- eval_data.pmd = nullptr;
- eval_data.flowbit_failed = 0;
- eval_data.flowbit_noalert = 0;
+ eval_data.pomd = omd;
+ eval_data.p = p;
+ eval_data.pmd = nullptr;
+ eval_data.flowbit_failed = 0;
+ eval_data.flowbit_noalert = 0;
- int rval = 0;
- {
- DeepProfile rule_profile(rulePerfStats);
- DeepProfile rule_nfp_eval_profile(ruleNFPEvalPerfStats);
- trace_log(detection, TRACE_RULE_EVAL, "Testing non-content rules\n");
- rval = detection_option_tree_evaluate(
- (detection_option_tree_root_t*)port_group->nfp_tree, &eval_data);
- }
+ int rval = 0;
+ {
+ DeepProfile rule_profile(rulePerfStats);
+ DeepProfile rule_nfp_eval_profile(ruleNFPEvalPerfStats);
+ trace_log(detection, TRACE_RULE_EVAL, "Testing non-content rules\n");
+ rval = detection_option_tree_evaluate(
+ (detection_option_tree_root_t*)port_group->nfp_tree, &eval_data);
+ }
- if (rval)
- pmqs.qualified_events++;
- else
- pmqs.non_qualified_events++;
+ if (rval)
+ pmqs.qualified_events++;
+ else
+ pmqs.non_qualified_events++;
- pc.hard_evals++;
- }
+ pc.hard_evals++;
+ }
- // FIXIT-L need to eval all IP layers, etc.
- // FIXIT-L why run only nfp rules?
- if (ip_rule)
+ // FIXIT-L should really be logging any events based on curr_ip_layer
+ if (ip_rule)
+ {
+ /* Evaluate again with the next IP layer */
+ if (layer::set_outer_ip_api(p, p->ptrs.ip_api, curr_ip_layer))
{
- /* Evaluate again with the next IP layer */
- if (layer::set_outer_ip_api(p, p->ptrs.ip_api, curr_ip_layer))
- {
- p->data = p->ptrs.ip_api.ip_data();
- p->dsize = p->ptrs.ip_api.pay_len();
- p->packet_flags |= PKT_IP_RULE_2ND | PKT_IP_RULE;
- }
- else
- {
- /* Set the data & dsize back to original values. */
- p->data = tmp_payload;
- p->dsize = tmp_dsize;
- p->packet_flags &= ~(PKT_IP_RULE| PKT_IP_RULE_2ND);
- repeat = false;
- }
+ p->data = p->ptrs.ip_api.ip_data();
+ p->dsize = p->ptrs.ip_api.pay_len();
+ p->packet_flags |= PKT_IP_RULE_2ND | PKT_IP_RULE;
+ }
+ else
+ {
+ /* Set the data & dsize back to original values. */
+ p->data = tmp_payload;
+ p->dsize = tmp_dsize;
+ p->packet_flags &= ~(PKT_IP_RULE| PKT_IP_RULE_2ND);
+ repeat = false;
}
}
- while (repeat);
}
+ while (repeat);
+}
+
+// This function does a set-wise match on content, and walks an otn list
+// for non-content. The otn list search will eventually be redone for
+// for performance purposes.
+
+static inline int fpEvalHeaderSW(PortGroup* port_group, Packet* p,
+ int check_ports, char ip_rule, int type, OtnxMatchData* omd, FPTask task)
+{
+ if ( !p->is_detection_enabled(p->packet_flags & PKT_FROM_CLIENT) )
+ return 0;
+
+ print_pkt_info(p);
+
+ if ( task & FPTask::FP )
+ eval_fp(port_group, p, omd, ip_rule, check_ports, type);
+
+ if ( task & FPTask::NON_FP )
+ eval_nfp(port_group, p, omd, ip_rule);
return 0;
}
fpEvalHeaderUdp(p, omd, task);
+ // FIXIT-P Batch outer UDP payload searches for teredo set and the outer header
+ // during any signature evaluation
+ fp_immediate(p);
+
p->ptrs.sp = tmp_sp;
p->ptrs.dp = tmp_dp;
p->ptrs.udph = tmp_udph;
}
}
-void fp_full(Packet* p)
+void fp_partial(Packet* p)
{
IpsContext* c = p->context;
MpseStash* stash = c->stash;
stash->enable_process();
stash->init();
+ stash->disable_process();
init_match_info(c->otnx);
-
c->searches.mf = rule_tree_queue;
c->searches.context = c;
- fpEvalPacket(p, FPTask::BOTH);
-
- if ( c->searches.search_sync() )
- stash->process(rule_tree_match, c);
-
- fpFinalSelectEvent(c->otnx, p);
+ assert(!c->searches.items.size());
+ fpEvalPacket(p, FPTask::FP);
}
-void fp_partial(Packet* p)
+void fp_complete(Packet* p, bool search)
{
IpsContext* c = p->context;
MpseStash* stash = c->stash;
stash->enable_process();
- stash->init();
- stash->disable_process();
- init_match_info(c->otnx);
- c->searches.mf = rule_tree_queue;
- c->searches.context = c;
- fpEvalPacket(p, FPTask::FP);
+
+ if ( search )
+ c->searches.search_sync();
+
+ stash->process(rule_tree_match, c);
+ fpEvalPacket(p, FPTask::NON_FP);
+ fpFinalSelectEvent(c->otnx, p);
+ c->searches.items.clear();
}
-void fp_complete(Packet* p)
+void fp_full(Packet* p)
+{
+ fp_partial(p);
+ fp_complete(p, true);
+}
+
+static void fp_immediate(Packet* p)
{
IpsContext* c = p->context;
MpseStash* stash = c->stash;
stash->enable_process();
+ c->searches.search_sync();
stash->process(rule_tree_match, c);
- fpEvalPacket(p, FPTask::NON_FP);
- fpFinalSelectEvent(c->otnx, p);
+ c->searches.items.clear();
}
void fp_full(snort::Packet*);
void fp_partial(snort::Packet*);
-void fp_complete(snort::Packet*);
+void fp_complete(snort::Packet*, bool search = false);
#endif
#include "latency/packet_latency.h"
#include "latency/rule_latency.h"
#include "main/snort_config.h"
+#include "main/thread.h"
+#include "main/thread_config.h"
#include "managers/module_manager.h"
#include "utils/stats.h"
std::mutex mutex;
std::condition_variable cond;
+#ifdef REG_TEST
+ // used to make main thread wait for results to get predictable behavior
+ std::mutex sync_mutex;
+ std::condition_variable sync_cond;
+#endif
+
std::atomic<bool> offload { false };
bool go = true;
ThreadRegexOffload::ThreadRegexOffload(unsigned max) : RegexOffload(max)
{
+ unsigned i = ThreadConfig::get_instance_max();
+
for ( auto* req : idle )
- req->thread = new std::thread(worker, req, snort::SnortConfig::get_conf());
+ req->thread = new std::thread(worker, req, snort::SnortConfig::get_conf(), i++);
}
ThreadRegexOffload::~ThreadRegexOffload()
busy.emplace_back(req);
p->context->regex_req_it = std::prev(busy.end());
- std::unique_lock<std::mutex> lock(req->mutex);
- req->packet = p;
+ {
+ std::unique_lock<std::mutex> lock(req->mutex);
+ req->packet = p;
+
+ req->offload = true;
+ req->cond.notify_one();
+ }
- req->offload = true;
- req->cond.notify_one();
+#ifdef REG_TEST
+ {
+ std::unique_lock<std::mutex> sync_lock(req->sync_mutex);
+ while ( req->offload and req->sync_cond.wait_for(sync_lock, std::chrono::seconds(1))
+ == std::cv_status::timeout );
+ }
+#endif
}
bool ThreadRegexOffload::get(snort::Packet*& p)
return false;
}
-void ThreadRegexOffload::worker(RegexRequest* req, snort::SnortConfig* initial_config)
+void ThreadRegexOffload::worker(
+ RegexRequest* req, snort::SnortConfig* initial_config, unsigned id)
{
+ set_instance_id(id);
snort::SnortConfig::set_conf(initial_config);
while ( true )
std::unique_lock<std::mutex> lock(req->mutex);
req->cond.wait_for(lock, std::chrono::seconds(1));
- // setting conf is somewhat expensive, checking the conf is not
- // this occurs here to take advantage if idling
- if ( req->packet and req->packet->context->conf != snort::SnortConfig::get_conf() )
- snort::SnortConfig::set_conf(req->packet->context->conf);
-
if ( !req->go )
break;
assert(req->packet->is_offloaded());
assert(req->packet->context->searches.items.size() > 0);
+ snort::SnortConfig::set_conf(req->packet->context->conf);
snort::IpsContext* c = req->packet->context;
snort::Mpse::MpseRespType resp_ret;
c->searches.offload_search();
+
do
{
resp_ret = c->searches.receive_offload_responses();
c->searches.items.clear();
req->offload = false;
+
+#ifdef REG_TEST
+ {
+ std::unique_lock<std::mutex> lock(req->sync_mutex);
+ req->sync_cond.notify_one();
+ }
+#endif
}
snort::ModuleManager::accumulate_offload("search_engine");
snort::ModuleManager::accumulate_offload("detection");
bool get(snort::Packet*&) override;
private:
- static void worker(RegexRequest*, snort::SnortConfig*);
+ static void worker(RegexRequest*, snort::SnortConfig*, unsigned id);
};
#endif
for ( auto& so : item.second.so )
{
start_state = 0;
- switch (mpse_type)
- {
- case MPSE_TYPE_NORMAL:
- item.second.matches += so->get_normal_mpse()->search(item.first.buf,
- item.first.len, batch.mf, batch.context, &start_state);
- break;
- case MPSE_TYPE_OFFLOAD:
- item.second.matches += so->get_offload_mpse()->search(item.first.buf,
- item.first.len, batch.mf, batch.context, &start_state);
- break;
- }
+
+ Mpse* mpse = (mpse_type == MPSE_TYPE_OFFLOAD) ?
+ so->get_offload_mpse() : so->get_normal_mpse();
+
+ item.second.matches += mpse->search(
+ item.first.buf, item.first.len, batch.mf, batch.context, &start_state);
}
item.second.done = true;
}
Mpse::MpseRespType Mpse::poll_responses(MpseBatch*& batch, MpseType mpse_type)
{
+ FastPatternConfig* fp = SnortConfig::get_conf()->fast_pattern_config;
+ assert(fp);
+
const MpseApi* search_api = nullptr;
- if ( SnortConfig::get_conf()->fast_pattern_config )
+ switch (mpse_type)
{
- switch (mpse_type)
- {
- case MPSE_TYPE_NORMAL:
- search_api = SnortConfig::get_conf()->fast_pattern_config->get_search_api();
- break;
- case MPSE_TYPE_OFFLOAD:
- search_api = SnortConfig::get_conf()->fast_pattern_config->get_offload_search_api();
- if (!search_api)
- search_api = SnortConfig::get_conf()->fast_pattern_config->get_search_api();
- break;
- }
+ case MPSE_TYPE_NORMAL:
+ search_api = fp->get_search_api();
+ break;
+
+ case MPSE_TYPE_OFFLOAD:
+ search_api = fp->get_offload_search_api();
+
+ if (!search_api)
+ search_api = fp->get_search_api();
+ break;
}
if (search_api)
if ( pos > c.size() )
return NO_MATCH;
- hs_scratch_t *ss =
- (hs_scratch_t *) SnortConfig::get_conf()->state[get_instance_id()][scratch_index];
+ hs_scratch_t* ss =
+ (hs_scratch_t*)SnortConfig::get_conf()->state[get_instance_id()][scratch_index];
s_to = 0;
void Analyzer::init_unprivileged()
{
// using dummy values until further integration
+#ifdef REG_TEST
const unsigned max_contexts = 20;
+#else
+ const unsigned max_contexts = 1024;
+#endif
switcher = new ContextSwitcher;
switcher->push(new IpsContext);
SnortConfig* sc = SnortConfig::get_conf();
-
CodecManager::thread_init(sc);
// this depends on instantiated daq capabilities
InitTag();
EventTrace_Init();
detection_filter_init(sc->detection_filter_config);
- DetectionEngine::thread_init();
EventManager::open_outputs();
IpsManager::setup_options();
if (SnortConfig::pcap_show())
show_source();
+ // init here to pin separately from packet threads
+ DetectionEngine::thread_init();
+
// Perform all packet thread initialization actions that need to be taken with escalated
// privileges prior to starting the DAQ module.
SnortConfig::get_conf()->thread_config->implement_thread_affinity(STHREAD_TYPE_PACKET,
public:
DetectionModule() :
Module("detection", detection_help, detection_params, false, &TRACE_NAME(detection)) {}
+
bool set(const char*, Value&, SnortConfig*) override;
+ bool end(const char*, int, SnortConfig*) override;
const PegInfo* get_pegs() const override
{ return pc_names; }
{ return GLOBAL; }
};
+bool DetectionModule::end(const char*, int, SnortConfig* sc)
+{
+ if ( sc->offload_threads and ThreadConfig::get_instance_max() != 1 )
+ ParseError("You can not enable experimental offload with more than one packet thread.");
+
+ return true;
+}
+
bool DetectionModule::set(const char* fqn, Value& v, SnortConfig* sc)
{
if ( v.is("asn1") )
ActionManager::new_config(this);
InspectorManager::new_config(this);
- num_slots = ThreadConfig::get_instance_max();
- state = new std::vector<void*>[num_slots];
+ num_slots = 0;
+ state = nullptr;
profiler = new ProfilerConfig;
latency = new LatencyConfig();
FreeReferences(references);
// Only call scratch cleanup if we actually called scratch setup
- if ( state[0].size() > 0 )
+ if ( state and state[0].size() > 0 )
{
for ( unsigned i = scratch_handlers.size(); i > 0; i-- )
{
// FIXIT-M should cmd_line use the same var list / table?
var_list = nullptr;
- delete[] state;
- num_slots = ThreadConfig::get_instance_max();
+ assert(!state);
+ num_slots = offload_threads + ThreadConfig::get_instance_max();
state = new std::vector<void*>[num_slots];
}
{ "-y", Parameter::PT_IMPLIED, nullptr, nullptr,
"include year in timestamp in the alert and log files" },
- { "-z", Parameter::PT_INT, "0:max32", "1",
+ // do not provide parameter default as it will cause the value to change
+ // after allocations in SnortConfig if snort = { } is set in Lua
+ { "-z", Parameter::PT_INT, "0:max32", nullptr,
"<count> maximum number of packet threads (same as --max-packet-threads); "
"0 gets the number of CPU cores reported by the system; default is 1" },
{ "--markup", Parameter::PT_IMPLIED, nullptr, nullptr,
"output help in asciidoc compatible format" },
- { "--max-packet-threads", Parameter::PT_INT, "0:max32", "1",
+ { "--max-packet-threads", Parameter::PT_INT, "0:max32", nullptr,
"<count> configure maximum number of packet threads (same as -z)" },
{ "--mem-check", Parameter::PT_IMPLIED, nullptr, nullptr,
bool begin(const char*, int, SnortConfig*) override;
bool set(const char*, Value&, SnortConfig*) override;
+ bool end(const char*, int, SnortConfig*) override;
const PegInfo* get_pegs() const override
{ return proc_names; }
return true;
}
+bool SnortModule::end(const char*, int, SnortConfig* sc)
+{
+ if ( sc->offload_threads and ThreadConfig::get_instance_max() != 1 )
+ ParseError("You can not enable experimental offload with more than one packet thread.");
+
+ return true;
+}
+
//-------------------------------------------------------------------------
// singleton
//-------------------------------------------------------------------------
const char* get_instance_file(std::string& file, const char* name)
{
bool sep = false;
- file = !snort::SnortConfig::get_conf()->log_dir.empty() ? snort::SnortConfig::get_conf()->log_dir : "./";
+ file = !snort::SnortConfig::get_conf()->log_dir.empty() ?
+ snort::SnortConfig::get_conf()->log_dir : "./";
if ( file.back() != '/' )
file += '/';
if ( (ThreadConfig::get_instance_max() > 1) || snort::SnortConfig::get_conf()->id_zero )
{
char id[8];
- snprintf(id, sizeof(id), "%u", get_instance_id() + snort::SnortConfig::get_conf()->id_offset);
+ snprintf(id, sizeof(id), "%u",
+ get_instance_id() + snort::SnortConfig::get_conf()->id_offset);
file += id;
sep = true;
}
{
const MpseApi* api = ::get_api(name);
- if ( api )
+ if ( api and api->init )
api->init();
return api;
void MpseManager::print_mpse_summary(const MpseApi* api)
{
assert(api);
+ if ( api->print )
api->print();
}
match_cb = mf;
match_ctx = pv;
- hs_scratch_t *ss = (hs_scratch_t *) SnortConfig::get_conf()->state[get_instance_id()][scratch_index];
+ hs_scratch_t* ss =
+ (hs_scratch_t*)SnortConfig::get_conf()->state[get_instance_id()][scratch_index];
// scratch is null for the degenerate case w/o patterns
assert(!hs_db or ss);
tcpStats.rebuilt_packets++;
tcpStats.rebuilt_bytes += flushed_bytes;
+#ifdef DEEP_PROFILING
NoProfile exclude(s5TcpFlushPerfStats);
+#else
+ NoProfile exclude(s5TcpPerfStats);
+#endif
if ( !Analyzer::get_local_analyzer()->inspect_rebuilt(pdu) )
last_pdu = pdu;
trs.flush_count++;
show_rebuilt_packet(trs, pdu);
- NoProfile profile_exclude(s5TcpFlushPerfStats);
+
+#ifdef DEEP_PROFILING
+ NoProfile exclude(s5TcpFlushPerfStats);
+#else
+ NoProfile exclude(s5TcpPerfStats);
+#endif
+
Analyzer::get_local_analyzer()->inspect_rebuilt(pdu);
if ( trs.tracker->splitter )
****************************************************************************/
int DisplayBanner()
{
- const char* info = getenv("HOSTTYPE");
-
- if ( !info )
- info="from 2.9.11"; // last sync with head
-
const char* ljv = LUAJIT_VERSION;
while ( *ljv && !isdigit(*ljv) )
++ljv;
LogMessage("\n");
LogMessage(" ,,_ -*> Snort++ <*-\n");
- LogMessage(" o\" )~ Version %s (Build %s) %s\n",
- VERSION, BUILD, info);
+ LogMessage(" o\" )~ Version %s (Build %s)\n", VERSION, BUILD);
LogMessage(" '''' By Martin Roesch & The Snort Team\n");
LogMessage(" http://snort.org/contact#team\n");
LogMessage(" Copyright (C) 2014-2019 Cisco and/or its affiliates."