if ( p->alt_dsize == 0 )
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
return 0;
}
{
if ( !GetHttpBufferMask() && (p->alt_dsize == 0) )
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
return 0;
}
}
if ( !(session->server_conf->inspect_response) &&
IsLimitedDetect(p) && !p->alt_dsize )
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
return 0;
}
ClearHttpBuffers();
if ( IsLimitedDetect(p) &&
!GetHttpBufferMask() && (p->alt_dsize == 0) )
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
return 0;
}
}
*/
{
Profile exclude(hiPerfStats);
- DetectionEngine::detect(p);
+ DetectionEngine de;
+ de.detect(p);
}
/*
if ( iCallDetect == 0 )
{
// DetectionEngine::detect called at least once from above pkt processing loop.
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
}
return 0;
Trace TRACE_NAME(detection);
-THREAD_LOCAL DetectionEngine::ActiveRules active_rules = DetectionEngine::NONE;
-
static THREAD_LOCAL unsigned s_events = 0;
static THREAD_LOCAL Ring<unsigned>* offload_ids = nullptr;
DetectionEngine::~DetectionEngine()
{
- if ( context == get_context() )
- clear_packet();
+ clear_packet(context->packet);
+ ContextSwitcher* sw = Snort::get_switcher();
+
+ if ( context == sw->get_context() )
+ sw->complete();
}
+Packet* DetectionEngine::get_packet()
+{ return context->packet; }
+
IpsContext* DetectionEngine::get_context()
{ return Snort::get_switcher()->get_context(); }
Packet* DetectionEngine::get_current_packet()
{ return Snort::get_switcher()->get_context()->packet; }
-Packet* DetectionEngine::get_packet()
-{ return get_current_packet(); }
-
void DetectionEngine::set_encode_packet(Packet* p)
{ Snort::get_switcher()->get_context()->encode_packet = p; }
return p;
}
-void DetectionEngine::clear_packet()
+void DetectionEngine::clear_packet(Packet* p)
{
- ContextSwitcher* sw = Snort::get_switcher();
- IpsContext* c = sw->get_context();
-
- if ( c->offload )
- return;
-
- Packet* p = c->packet;
-
log_events(p);
- reset();
+ reset(p);
if ( p->endianness )
{
delete p->endianness;
p->endianness = nullptr;
}
-
- sw->complete();
}
uint8_t* DetectionEngine::get_buffer(unsigned& max)
IpsContextData* DetectionEngine::get_data(unsigned id)
{ return Snort::get_switcher()->get_context()->get_context_data(id); }
-DetectionEngine::ActiveRules DetectionEngine::get_detects()
-{ return active_rules; }
+void DetectionEngine::disable_all(Packet* p)
+{ p->context->active_rules = IpsContext::NONE; }
-void DetectionEngine::set_detects(ActiveRules ar)
-{ active_rules = ar; }
+bool DetectionEngine::all_disabled(Packet* p)
+{ return p->context->active_rules == IpsContext::NONE; }
-void DetectionEngine::disable_content()
+void DetectionEngine::disable_content(Packet* p)
{
- if ( active_rules == CONTENT )
- active_rules = NON_CONTENT;
+ if ( p->context->active_rules == IpsContext::CONTENT )
+ p->context->active_rules = IpsContext::NON_CONTENT;
}
-void DetectionEngine::disable_all()
-{ active_rules = NONE; }
+void DetectionEngine::enable_content(Packet* p)
+{ p->context->active_rules = IpsContext::CONTENT; }
+
+bool DetectionEngine::content_enabled(Packet* p)
+{ return p->context->active_rules == IpsContext::CONTENT; }
+
+IpsContext::ActiveRules DetectionEngine::get_detects(Packet* p)
+{ return p->context->active_rules; }
-bool DetectionEngine::offloaded(Flow* flow)
-{ return flow->test_session_flags(SSNFLAG_OFFLOAD); }
+void DetectionEngine::set_detects(Packet* p, IpsContext::ActiveRules ar)
+{ p->context->active_rules = ar; }
bool DetectionEngine::offloaded(Packet* p)
-{ return p->flow and offloaded(p->flow); }
+{ return p->flow and p->flow->is_offloaded(); }
void DetectionEngine::idle()
{
void DetectionEngine::onload(Flow* flow)
{
- while ( flow->test_session_flags(SSNFLAG_OFFLOAD) )
+ while ( flow->is_offloaded() )
{
const struct timespec blip = { 0, 1 };
trace_logf(detection, "%lu de::sleep\n", pc.total_from_daq);
pc.total_from_daq, *id, offload_ids->count());
Packet* p = c->packet;
- p->flow->clear_session_flags(SSNFLAG_OFFLOAD);
+ p->flow->clear_offloaded();
c->offload->join();
delete c->offload;
fp_onload(p);
InspectorManager::clear(p);
log_events(p);
- reset();
- clear_packet();
+ reset(p);
+ clear_packet(p);
+
+ sw->complete();
}
bool DetectionEngine::offload(Packet* p)
assert(p == p->context->packet);
onload(p->flow); // FIXIT-H ensures correct sequencing, suboptimal
- p->flow->set_session_flags(SSNFLAG_OFFLOAD|SSNFLAG_WAS_OFF);
+ p->flow->set_offloaded();
pc.offloads++;
+ assert(p->context == sw->get_context());
+
unsigned id = sw->suspend();
offload_ids->put(id);
}
else
{
- active_rules = CONTENT;
+ enable_content(p);
p->alt_dsize = 0; // FIXIT-H should be redundant
InspectorManager::execute(p);
Active::apply_delayed_action(p);
- if ( active_rules > NONE )
+ if ( !all_disabled(p) )
{
if ( detect(p) )
return;
Profile profile(eventqPerfStats);
log_events(p);
- reset();
+ reset(p);
Stream::check_flow_block_pending(p);
}
*/
int DetectionEngine::log_events(Packet* p)
{
- SF_EVENTQ* pq = get_event_queue();
+ SF_EVENTQ* pq = p->context->equeue;
sfeventq_action(pq, ::log_events, (void*)p);
return 0;
}
s_events = 0;
}
-void DetectionEngine::reset()
+void DetectionEngine::reset(Packet* p)
{
- SF_EVENTQ* pq = get_event_queue();
+ SF_EVENTQ* pq = p->context->equeue;
sfeventq_reset(pq);
reset_counts();
}
#include "actions/actions.h"
#include "detection/detection_util.h"
+#include "detection/ips_context.h"
#include "main/snort_types.h"
struct DataPointer;
static Packet* get_current_packet();
static Packet* set_packet();
- static void clear_packet();
- static bool offloaded(Flow*);
static bool offloaded(Packet*);
static bool offload(Packet*);
static void onload(Flow*);
- static void onload();
static void idle();
static void set_encode_packet(Packet*);
static int queue_event(const struct OptTreeNode*);
static int queue_event(unsigned gid, unsigned sid, RuleType = RULE_TYPE__NONE);
- static int log_events(struct Packet*);
+ static int log_events(Packet*);
- static void reset();
+ static void reset(Packet*);
static void reset_counts();
- enum ActiveRules
- { NONE, NON_CONTENT, CONTENT };
-
- static ActiveRules get_detects();
- static void set_detects(ActiveRules);
+ static void disable_all(Packet*);
+ static bool all_disabled(Packet*);
- static void disable_content();
- static void disable_all();
+ static void disable_content(Packet*);
+ static void enable_content(Packet*);
+ static bool content_enabled(Packet*);
- static void enable_content()
- { set_detects(CONTENT); }
+ static IpsContext::ActiveRules get_detects(Packet*);
+ static void set_detects(Packet*, IpsContext::ActiveRules);
- static bool content_enabled()
- { return get_detects() == CONTENT; }
+private:
+ static struct SF_EVENTQ* get_event_queue();
+ static void onload();
+ static void clear_packet(Packet*);
private:
IpsContext* context;
- static struct SF_EVENTQ* get_event_queue();
};
static inline void set_next_file_data(const uint8_t* p, unsigned n)
p->packet_flags &= ~PKT_IP_RULE;
}
- if ( DetectionEngine::content_enabled() )
+ 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 0;
}
+ if ( DetectionEngine::offloaded(p) )
+ return 0; // FIXIT-H can't eval nfp rules here - move to onload
+
do
{
// FIXIT-L restrict no-fast-pattern to non-data packets? (non-data includes
if (tmp_api.pay_len() > udp::UDP_HEADER_LEN)
p->dsize = tmp_api.pay_len() - udp::UDP_HEADER_LEN;
- auto save_detect = DetectionEngine::get_detects();
+ auto save_detect = DetectionEngine::get_detects(p);
if ( p->dsize )
- DetectionEngine::enable_content();
+ DetectionEngine::enable_content(p);
fpEvalHeaderUdp(p, omd);
p->data = tmp_data;
p->dsize = tmp_dsize;
- DetectionEngine::set_detects(save_detect);
+ DetectionEngine::set_detects(p, save_detect);
}
/*
offload = nullptr;
onload = false;
+ active_rules = CONTENT;
}
IpsContext::~IpsContext()
unsigned get_slot()
{ return slot; }
+ enum ActiveRules
+ { NONE, NON_CONTENT, CONTENT };
+
public:
Packet* packet;
Packet* encode_packet;
class MpseStash* stash;
struct OtnxMatchData* otnx;
+ struct SF_EVENTQ* equeue;
+
uint64_t pkt_count;
bool onload;
-
- struct SF_EVENTQ* equeue;
+ ActiveRules active_rules;
static const unsigned buf_size = Codec::PKT_MAX;
{
pkt_type = type;
bitop = nullptr;
+ flow_flags = 0;
if ( HighAvailabilityManager::active() )
{
#define SSNFLAG_CLIENT_SWAPPED 0x00400000
#define SSNFLAG_PROXIED 0x01000000
-#define SSNFLAG_OFFLOAD 0x02000000
-#define SSNFLAG_WAS_OFF 0x04000000 // FIXIT-L debug only
#define SSNFLAG_NONE 0x00000000 /* nothing, an MT bag of chips */
#define STREAM_STATE_NO_PICKUP 0x2000
#define STREAM_STATE_BLOCK_PENDING 0x4000
+#define FLOW_IS_OFFLOADED 0x01
+#define FLOW_WAS_OFFLOADED 0x02 // FIXIT-L debug only
+
// FIXIT-L move to appid class if/when the application ids array
// is moved
typedef int32_t AppId;
return disable_inspect;
}
+ bool is_offloaded() const
+ { return flow_flags & FLOW_IS_OFFLOADED; }
+
+ void set_offloaded()
+ { flow_flags |= (FLOW_IS_OFFLOADED|FLOW_WAS_OFFLOADED); }
+
+ void clear_offloaded()
+ { flow_flags &= ~FLOW_IS_OFFLOADED; }
+
public: // FIXIT-M privatize if possible
// fields are organized by initialization and size to minimize
// void space and allow for memset of tail end of struct
PktType pkt_type; // ^^
// these fields are always set; not zeroed
+ uint8_t flow_flags;
Flow* prev, * next;
Inspector* ssn_client;
Inspector* ssn_server;
break;
}
#endif
- if ( DetectionEngine::offloaded(flow) )
+ if ( flow->is_offloaded() )
break;
if ( flow->last_data_seen + config.pruning_timeout >= thetime )
assert(flow); // holds true because hash_table->get_count() > 0
if ( (save_me and flow == save_me) or flow->was_blocked() or
- DetectionEngine::offloaded(flow) )
+ flow->is_offloaded() )
{
// check for non-null save_me above to silence analyzer
// "called C++ object pointer is null" here
break;
if ( HighAvailabilityManager::in_standby(flow) or
- DetectionEngine::offloaded(flow) )
+ flow->is_offloaded() )
{
flow = static_cast<Flow*>(hash_table->next());
continue;
if ( news )
Stream::stop_inspection(flow, p, SSN_DIR_BOTH, -1, 0);
else
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
p->ptrs.decode_flags |= DECODE_PKT_TRUST;
break;
else
Active::block_again();
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
break;
case Flow::FlowState::RESET:
Active::reset_again();
Stream::blocked_flow(flow, p);
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
break;
}
(p->packet_flags & PKT_FROM_CLIENT) ? "sender" : "responder");
flow->ssn_state.ignore_direction = ignore;
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
}
return ignore;
Profile detect_profile(detectPerfStats);
Profile rebuilt_profile(rebuiltPacketPerfStats);
- auto save_detect = DetectionEngine::get_detects();
-
DetectionEngine de;
main_hook(p);
- clear_file_data();
- DetectionEngine::set_detects(save_detect);
+ if ( DetectionEngine::offloaded(p) )
+ return;
+
+ clear_file_data(); // FIXIT-H get rid of this
}
DAQ_Verdict Snort::process_packet(
int asn1_mem = 0;
uint32_t run_flags = 0;
- unsigned offload_limit = 99999;
+ unsigned offload_limit = 99999; // disabled
//------------------------------------------------------
// process stuff
return false;
else if ( !p->dsize )
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
else if ( flow->gadget && flow->gadget->likes(p) )
{
DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_BLACKLIST);
Active::drop_packet(p, true);
// disable all preproc analysis and detection for this packet
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
p->disable_inspect = true;
if (p->flow)
{
{
DetectionEngine::queue_event(GID_REPUTATION, REPUTATION_EVENT_WHITELIST);
p->packet_flags |= PKT_IGNORE;
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
p->disable_inspect = true;
if (p->flow)
{
void do_detection(Packet* p)
{
get_data_bus().publish(PACKET_EVENT, p);
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
}
}
static inline uint32_t SSLPP_process_alert(
- SSL_PROTO_CONF*, uint32_t ssn_flags, uint32_t new_flags, const Packet* packet)
+ SSL_PROTO_CONF*, uint32_t ssn_flags, uint32_t new_flags, Packet* packet)
{
DebugMessage(DEBUG_SSL, "Process Alert\n");
!(new_flags & SSL_HEARTBEAT_SEEN))
{
DebugMessage(DEBUG_SSL, "Disabling detect\n");
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(packet);
}
/* Need to negate the application flags from the opposing side. */
}
else if (!(new_flags & SSL_HEARTBEAT_SEEN))
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(packet);
}
}
}
else if (!(new_flags & SSL_HEARTBEAT_SEEN))
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(packet);
}
}
else
if (!(new_flags & SSL_HEARTBEAT_SEEN))
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
}
sd->ssn_flags |= new_flags;
if ((frag_offset != 0)) /* ||
((p->get_ip_proto_next() != IpProtocol::UDP) && (p->ptrs.decode_flags & DECODE_MF))) */
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
}
/*
//dont forward fragments to engine if some previous fragment was dropped
if ( ft->frag_flags & FRAG_DROP_FRAGMENTS )
{
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
Active::daq_drop_packet(p);
ip_stats.drops++;
}
{
// Need to reset some things here because the rebuilt packet
// will have reset the do_detect flag when it hits Inspect.
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
}
}
// FIXIT-L these 2 function names convey no meaning afaict... figure out
// why are they called and name appropriately...
- virtual void retransmit_process()
+ virtual void retransmit_process(Packet* p)
{
// Data has already been analyzed so don't bother looking at it again.
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
}
virtual void retransmit_handle(Packet* p)
/* FIXIT-M handle bytes/response parameters */
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
flow->set_state(Flow::FlowState::ALLOW);
}
"Blocking %s packet as session was blocked\n",
p->is_from_server() ? "server" : "client");
- DetectionEngine::disable_content();
+ DetectionEngine::disable_content(p);
Active::drop_packet(p);
active_response(p, flow);
return true;
"Stream Ignoring packet from %s. Session marked as ignore\n",
p->is_from_client() ? "sender" : "responder");
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
return true;
}
{
/* Turn off inspection */
lwssn->ssn_state.ignore_direction |= srod.direction;
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(pkt);
/* TBD: Set TF_FORCE_FLUSH ? */
}
if ( rsize == 0 )
{
// All data was retransmitted
- session->retransmit_process();
+ session->retransmit_process(tsd->get_pkt());
keep_segment = false;
}
if ( right->is_retransmit(rdata, rsize, rseq, right->orig_dsize, nullptr) )
{
// All data was retransmitted
- session->retransmit_process();
+ session->retransmit_process(tsd->get_pkt());
keep_segment = false;
}
else
int TcpReassembler::_flush_to_seq(uint32_t bytes, Packet* p, uint32_t pkt_flags)
{
Profile profile(s5TcpFlushPerfStats);
+
DetectionEngine::onload(session->flow);
s5_pkt = DetectionEngine::set_packet();
uint32_t footprint = stop_seq - seglist_base_seq;
if ( footprint == 0 )
- {
- DetectionEngine::clear_packet();
return bytes_processed;
- }
if ( footprint > s5_pkt->max_dsize )
/* this is as much as we can pack into a stream buffer */
footprint = s5_pkt->max_dsize;
+ DetectionEngine::onload(session->flow);
+ s5_pkt = DetectionEngine::set_packet();
+
+ DAQ_PktHdr_t pkth;
+ session->GetPacketHeaderFoo(&pkth, pkt_flags);
+
+ if ( !p )
+ {
+ // FIXIT-H we need to have user_policy_id in this case
+ // FIXIT-H this leads to format_tcp() copying from s5_pkt to s5_pkt
+ // (neither of these issues is created by passing null through to here)
+ p = s5_pkt;
+ }
+
+ PacketManager::format_tcp(enc_flags, p, s5_pkt, PSEUDO_PKT_TCP, &pkth, pkth.opaque);
+ prep_s5_pkt(session->flow, p, pkt_flags);
+
((DAQ_PktHdr_t*)s5_pkt->pkth)->ts = seglist.next->tv;
/* setup the pseudopacket payload */
int32_t TcpReassembler::flush_pdu_ackd(uint32_t* flags)
{
Profile profile(s5TcpPAFPerfStats);
+ DetectionEngine::onload(session->flow);
uint32_t total = 0;
TcpSegmentNode* tsn = SEQ_LT(seglist_base_seq, tracker->r_win_base) ? seglist.head : nullptr;
if (pkt_action_mask & ACTION_DISABLE_INSPECTION)
{
- DetectionEngine::disable_all();
+ DetectionEngine::disable_all(p);
DebugFormat(DEBUG_STREAM_STATE,
"Stream Ignoring packet from %s. Session marked as ignore\n",
#include "user_session.h"
+#include "detection/detection_engine.h"
+#include "detection/rules.h"
#include "main/snort.h"
#include "profiler/profiler_defs.h"
#include "protocols/packet.h"
void UserTracker::process(Packet* p)
{
+ DetectionEngine::onload(p->flow);
+
uint32_t flags = 0;
int flush_amt = scan(p, flags);