#include "act_replace.h"
+#include "detection/detection_engine.h"
#include "framework/ips_action.h"
#include "framework/module.h"
#include "packet_io/active.h"
// queue foo
//--------------------------------------------------------------------------
-struct Replacement
-{
- std::string data;
- unsigned offset;
-};
-
-#define MAX_REPLACEMENTS 32
-static THREAD_LOCAL Replacement* rpl;
-static THREAD_LOCAL int num_rpl = 0;
-
void Replace_ResetQueue()
{
- num_rpl = 0;
+ DetectionEngine::clear_replacement();
}
void Replace_QueueChange(const std::string& s, unsigned off)
{
- Replacement* r;
-
- if ( num_rpl == MAX_REPLACEMENTS )
- return;
-
- r = rpl + num_rpl++;
-
- r->data = s;
- r->offset = off;
+ DetectionEngine::add_replacement(s, off);
}
-static inline void Replace_ApplyChange(Packet* p, Replacement* r)
+static inline void Replace_ApplyChange(Packet* p, std::string& data, unsigned offset)
{
- uint8_t* start = const_cast<uint8_t*>(p->data) + r->offset;
+ uint8_t* start = const_cast<uint8_t*>(p->data) + offset;
const uint8_t* end = p->data + p->dsize;
unsigned len;
- if ( (start + r->data.size()) >= end )
- len = p->dsize - r->offset;
+ if ( (start + data.size()) >= end )
+ len = p->dsize - offset;
else
- len = r->data.size();
+ len = data.size();
- memcpy(start, r->data.c_str(), len);
+ memcpy(start, data.c_str(), len);
}
static void Replace_ModifyPacket(Packet* p)
{
- if ( num_rpl == 0 )
- return;
+ std::string data;
+ unsigned offset;
+ bool modified = false;
- for ( int n = 0; n < num_rpl; n++ )
+ while ( DetectionEngine::get_replacement(data, offset) )
{
- Replace_ApplyChange(p, rpl+n);
+ modified = true;
+ Replace_ApplyChange(p, data, offset);
}
- p->packet_flags |= PKT_MODIFIED;
- num_rpl = 0;
+
+ if ( modified )
+ p->packet_flags |= PKT_MODIFIED;
+
+ DetectionEngine::clear_replacement();
}
//-------------------------------------------------------------------------
static void rep_dtor(IpsAction* p)
{ delete p; }
-static void rep_tinit()
-{ rpl = new Replacement[MAX_REPLACEMENTS]; }
-
-static void rep_tterm()
-{ delete[] rpl; }
-
static ActionApi rep_api
{
{
Actions::ALERT,
nullptr,
nullptr,
- rep_tinit,
- rep_tterm,
+ nullptr,
+ nullptr,
rep_ctor,
rep_dtor
};
#include "detection_engine.h"
+#include "actions/act_replace.h"
#include "events/sfeventq.h"
#include "filters/sfthreshold.h"
#include "framework/endianness.h"
IpsContextData* DetectionEngine::get_data(unsigned id)
{ return Snort::get_switcher()->get_context()->get_context_data(id); }
+void DetectionEngine::add_replacement(const std::string& s, unsigned off)
+{
+ Replacement r;
+
+ r.data = s;
+ r.offset = off;
+ Snort::get_switcher()->get_context()->rpl.push_back(r);
+}
+
+bool DetectionEngine::get_replacement(std::string& s, unsigned& off)
+{
+ if ( Snort::get_switcher()->get_context()->rpl.empty() )
+ return false;
+
+ auto rep = Snort::get_switcher()->get_context()->rpl.back();
+
+ s = rep.data;
+ off = rep.offset;
+
+ Snort::get_switcher()->get_context()->rpl.pop_back();
+ return true;
+}
+
+void DetectionEngine::clear_replacement()
+{
+ Snort::get_switcher()->get_context()->rpl.clear();
+}
+
void DetectionEngine::disable_all(Packet* p)
{ p->context->active_rules = IpsContext::NONE; }
#include "main/snort_types.h"
struct DataPointer;
+struct Replacement;
namespace snort
{
static void set_data(unsigned id, IpsContextData*);
static IpsContextData* get_data(unsigned id);
+ static void add_replacement(const std::string&, unsigned);
+ static bool get_replacement(std::string&, unsigned&);
+ static void clear_replacement();
+
static bool detect(Packet*, bool offload_ok = false);
static void inspect(Packet*);
namespace snort
{
struct SnortConfig;
+struct Replacement
+{
+ std::string data;
+ unsigned offset;
+};
class SO_PUBLIC IpsContextData
{
ActiveRules active_rules;
bool check_tags;
+ std::vector<Replacement> rpl;
+
static const unsigned buf_size = Codec::PKT_MAX;
private:
}
// process (wire-only) packet verdicts here
-static DAQ_Verdict update_verdict(DAQ_Verdict verdict, int& inject)
+static DAQ_Verdict update_verdict(Packet* p, DAQ_Verdict verdict, int& inject)
{
if ( Active::packet_was_dropped() and Active::can_block() )
{
if ( verdict == DAQ_VERDICT_PASS )
verdict = DAQ_VERDICT_BLOCK;
}
- else if ( s_packet->packet_flags & PKT_RESIZED )
+ else if ( p->packet_flags & PKT_RESIZED )
{
// we never increase, only trim, but daq doesn't support resizing wire packet
- PacketManager::encode_update(s_packet);
+ PacketManager::encode_update(p);
- if ( !SFDAQ::inject(s_packet->pkth, 0, s_packet->pkt, s_packet->pkth->pktlen) )
+ if ( !SFDAQ::inject(p->pkth, 0, p->pkt, p->pkth->pktlen) )
{
inject = 1;
verdict = DAQ_VERDICT_BLOCK;
}
}
- else if ( s_packet->packet_flags & PKT_MODIFIED )
+ else if ( p->packet_flags & PKT_MODIFIED )
{
// this packet was normalized and/or has replacements
- PacketManager::encode_update(s_packet);
+ PacketManager::encode_update(p);
verdict = DAQ_VERDICT_REPLACE;
}
- else if ( (s_packet->packet_flags & PKT_IGNORE) ||
- (s_packet->flow && s_packet->flow->get_ignore_direction( ) == SSN_DIR_BOTH) )
+ else if ( (p->packet_flags & PKT_IGNORE) ||
+ (p->flow && p->flow->get_ignore_direction( ) == SSN_DIR_BOTH) )
{
if ( !Active::get_tunnel_bypass() )
{
aux_counts.internal_whitelist++;
}
}
- else if ( s_packet->ptrs.decode_flags & DECODE_PKT_TRUST )
+ else if ( p->ptrs.decode_flags & DECODE_PKT_TRUST )
{
- if (s_packet->flow)
- s_packet->flow->set_ignore_direction(SSN_DIR_BOTH);
+ if (p->flow)
+ p->flow->set_ignore_direction(SSN_DIR_BOTH);
verdict = DAQ_VERDICT_WHITELIST;
}
else
ActionManager::execute(s_packet);
int inject = 0;
- verdict = update_verdict(verdict, inject);
+ verdict = update_verdict(s_packet, verdict, inject);
PacketTracer::log("NAP id %u, IPS id %u, Verdict %s\n",
get_network_policy()->policy_id, get_ips_policy()->policy_id,