]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1342 in SNORT/snort3 from stream_cleanup to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Wed, 12 Sep 2018 19:12:16 +0000 (15:12 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Wed, 12 Sep 2018 19:12:16 +0000 (15:12 -0400)
Squashed commit of the following:

commit e2e541448233efbeb6e41530b8e4f99edad5af9a
Author: Carter Waxman <cwaxman@cisco.com>
Date:   Mon Aug 13 12:33:04 2018 -0400

    DetectionEngine: added post-onload callbacks

src/detection/detection_engine.cc
src/detection/ips_context.cc
src/detection/ips_context.h
src/detection/regex_offload.cc
src/flow/flow.cc
src/stream/tcp/segment_overlap_editor.h
src/stream/tcp/tcp_reassembler.cc
src/stream/tcp/tcp_reassembler.h
src/stream/tcp/tcp_reassemblers.h

index 79481ec1c2e4e024acd395d65475448d9a8258d5..10606d65d6f209baafb9ed6e41c5590b9e6c3f0f 100644 (file)
@@ -82,6 +82,7 @@ DetectionEngine::~DetectionEngine()
     {
         finish_packet(context->packet);
         sw->complete();
+        context->post_detection();
     }
 }
 
@@ -307,6 +308,7 @@ void DetectionEngine::onload()
 
     InspectorManager::clear(p);
     sw->complete();
+    c->post_detection();
 }
 
 bool DetectionEngine::offload(Packet* p)
index ac07d74e98e01dfe78831d8af5ddc33483d4456c..75c3f6fb192290f4a7d39ada7734d52b096f34f2 100644 (file)
@@ -125,6 +125,14 @@ void IpsContext::snapshot_flow(Flow* f)
     flow.proto_id = f->ssn_state.snort_protocol_id;
 }
 
+void IpsContext::post_detection()
+{
+    for ( auto callback : post_callbacks )
+        callback(this);
+
+    post_callbacks.clear();
+}
+
 //--------------------------------------------------------------------------
 // unit tests
 //--------------------------------------------------------------------------
@@ -191,5 +199,25 @@ TEST_CASE("IpsContext basic", "[IpsContext]")
     }
     CHECK(TestData::count == num_data);
 }
+
+IpsContext* post_val;
+void test_post(IpsContext* c)
+{ post_val = c; }
+
+TEST_CASE("IpsContext post detection", "[IpsContext]")
+{
+    post_val = nullptr;
+    IpsContext c;
+    c.register_post_callback(test_post);
+
+    CHECK( post_val == nullptr);
+    c.post_detection();
+    CHECK( post_val == &c);
+
+    // callbacks should be cleared
+    post_val = nullptr;
+    c.post_detection();
+    CHECK( post_val == nullptr );
+}
 #endif
 
index 86031c0995d406cfdddf69dd73fc0f38384c9760..519c6401aa7a3b7bebfef33d54924e08ac519a01 100644 (file)
@@ -67,6 +67,8 @@ protected:
 class SO_PUBLIC IpsContext
 {
 public:
+    using Callback = void(*)(IpsContext*);
+
     IpsContext(unsigned size = 0);  // defaults to max id
     ~IpsContext();
 
@@ -94,6 +96,14 @@ public:
     enum ActiveRules
     { NONE, NON_CONTENT, CONTENT };
 
+    void register_post_callback(Callback callback)
+    { post_callbacks.push_back(callback); }
+
+    void clear_callbacks()
+    { post_callbacks.clear(); }
+
+    void post_detection();
+
 public:
     Packet* packet;
     Packet* encode_packet;
@@ -120,6 +130,8 @@ public:
 private:
     FlowSnapshot flow;
     std::vector<IpsContextData*> data;
+    std::vector<Callback> post_callbacks;
+
     unsigned slot;
 };
 }
index 57986b52b2eaf86c9388f838b62a2d96f732aebb..9e34e056d228b990ebe8f13064407643746861f0 100644 (file)
@@ -146,7 +146,9 @@ void RegexOffload::put(unsigned id, snort::Packet* p)
 bool RegexOffload::get(unsigned& id)
 {
     assert(!busy.empty());
-    RegexRequest* req = busy.front();  // FIXIT-H onload any order
+
+    // FIXIT-H onload flows in any order
+    RegexRequest* req = busy.front();
 
     if ( req->offload )
         return false;
index 5e8344c5cbd5f06f1b9e66b5cc68c12e93700dc7..ab524bc7ff542bf476cc891fddf4983f6efde029 100644 (file)
@@ -170,6 +170,8 @@ void Flow::reset(bool do_cleanup)
     constexpr size_t offset = offsetof(Flow, flow_data);
     // FIXIT-L need a struct to zero here to make future proof
     memset((uint8_t*)this+offset, 0, sizeof(Flow)-offset);
+
+    de.get_context()->clear_callbacks();
 }
 
 void Flow::restart(bool dump_flow_data)
index a0b25d7d1074c7014c2064aaef970f8f0f49dcf0..89b802c87e7202aae83ef7fec3088d212a813646 100644 (file)
@@ -76,6 +76,7 @@ struct TcpReassemblerState
 {
     SegmentOverlapState sos;
     TcpStreamTracker* tracker;
+    snort::Packet* last_pdu = nullptr;
     uint32_t flush_count;   // number of flushed queued segments
     uint32_t xtradata_mask; // extra data available to log
     bool server_side;
index 64cc1c5988f872b88252f36967f215023e193d3f..a79d4f80f796e3f8e66e1e413f921778330c98f4 100644 (file)
 
 using namespace snort;
 
+static THREAD_LOCAL Packet* last_pdu = nullptr;
+
+void purge_alerts_callback_ackd(IpsContext* c)
+{
+    TcpSession* session = (TcpSession*)c->packet->flow->session;
+
+    if ( c->packet->is_from_server() )
+        session->client.reassembler.purge_alerts();
+    else
+        session->server.reassembler.purge_alerts();
+}
+
+void purge_alerts_callback_ips(IpsContext* c)
+{
+    TcpSession* session = (TcpSession*)c->packet->flow->session;
+
+    if ( c->packet->is_from_server() )
+        session->server.reassembler.purge_alerts();
+    else
+        session->client.reassembler.purge_alerts();
+}
+
 void TcpReassembler::trace_segments(TcpReassemblerState& trs)
 {
     TcpSegmentNode* tsn = trs.sos.seglist.head;
@@ -224,16 +246,17 @@ int TcpReassembler::dup_reassembly_segment(
     return STREAM_INSERT_OK;
 }
 
-int TcpReassembler::purge_alerts(TcpReassemblerState& trs, Flow* flow)
+void TcpReassembler::purge_alerts(TcpReassemblerState& trs)
 {
+    Flow* flow = trs.sos.session->flow;
+
     for (int i = 0; i < trs.tracker->alert_count; i++)
     {
         StreamAlertInfo* ai = trs.tracker->alerts + i;
         Stream::log_extra_data(flow, trs.xtradata_mask, ai->event_id, ai->event_second);
     }
     trs.tracker->alert_count = 0;
-
-    return 0;
+    last_pdu = nullptr;
 }
 
 int TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq)
@@ -266,7 +289,17 @@ int TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq)
     if ( SEQ_LT(trs.tracker->rcv_nxt, flush_seq) )
         trs.tracker->rcv_nxt = flush_seq;
 
-    purge_alerts(trs, trs.sos.session->flow);
+    if ( last_pdu )
+    {
+        if ( trs.tracker->normalizer.is_tcp_ips_enabled() )
+            last_pdu->context->register_post_callback(purge_alerts_callback_ips);
+        else
+            last_pdu->context->register_post_callback(purge_alerts_callback_ackd);
+
+        last_pdu = nullptr;
+    }
+    else
+        purge_alerts(trs);
 
     if ( trs.sos.seglist.head == nullptr )
         trs.sos.seglist.tail = nullptr;
@@ -561,6 +594,9 @@ int TcpReassembler::_flush_to_seq(
 
             NoProfile exclude(s5TcpFlushPerfStats);
             Snort::inspect(pdu);
+
+            if ( pdu->flow->is_offloaded() )
+                last_pdu = pdu;
         }
         else
         {
index b66e8d78f17a589949313e0758d45ed1981f8f5c..68283de92a20e9ab22e3196583cc9e06d080b4f9 100644 (file)
@@ -42,6 +42,7 @@ public:
     virtual int flush_on_data_policy(TcpReassemblerState&, snort::Packet*);
     virtual int flush_on_ack_policy(TcpReassemblerState&, snort::Packet*);
     virtual void trace_segments(TcpReassemblerState&);
+    virtual void purge_alerts(TcpReassemblerState&);
 
 protected:
     TcpReassembler() = default;
@@ -61,7 +62,6 @@ protected:
     void queue_reassembly_segment(TcpReassemblerState&, TcpSegmentNode* prev, TcpSegmentNode*);
     void init_overlap_editor(TcpReassemblerState&, TcpSegmentDescriptor&);
     bool is_segment_fasttrack(TcpReassemblerState&, TcpSegmentNode* tail, TcpSegmentDescriptor&);
-    int purge_alerts(TcpReassemblerState&, snort::Flow*);
     void show_rebuilt_packet(TcpReassemblerState&, snort::Packet*);
     uint32_t get_flush_data_len(
         TcpReassemblerState&, TcpSegmentNode*, uint32_t to_seq, unsigned max);
index affa5ba981f6e0348b04ce152661f4a5b24158c3..895cb8c331ad1f761c5e73e3c45a03e1fcd98299 100644 (file)
@@ -43,6 +43,9 @@ public:
     int queue_packet_for_reassembly(TcpSegmentDescriptor& tsd)
     { return reassembler->queue_packet_for_reassembly(trs, tsd); }
 
+    void purge_alerts()
+    { reassembler->purge_alerts(trs); }
+
     void purge_segment_list()
     { reassembler->purge_segment_list(trs); }