From: Michael Altizer (mialtize) Date: Wed, 20 Jun 2018 13:49:18 +0000 (-0400) Subject: Merge pull request #1257 in SNORT/snort3 from passive_binder to master X-Git-Tag: 3.0.0-246~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=597cb676461304b87d9a61417bcaa68535a81cce;p=thirdparty%2Fsnort3.git Merge pull request #1257 in SNORT/snort3 from passive_binder to master Squashed commit of the following: commit 3b7b3e7d59a842b64e7d338be21225f0d89d2594 Author: Michael Altizer Date: Tue Jun 5 19:56:37 2018 -0400 binder: Refactor binder as a passive, event-driven inspector --- diff --git a/src/flow/flow_control.cc b/src/flow/flow_control.cc index 42753d8df..c07887d64 100644 --- a/src/flow/flow_control.cc +++ b/src/flow/flow_control.cc @@ -416,13 +416,11 @@ unsigned FlowControl::process(Flow* flow, Packet* p) else { init_roles(p, flow); - Inspector* b = InspectorManager::get_binder(); + DataBus::publish(FLOW_STATE_SETUP_EVENT, p); - if ( b ) - b->eval(p); - - if ( !b || (flow->flow_state == Flow::FlowState::INSPECT && - (!flow->ssn_client || !flow->session->setup(p))) ) + if ( flow->flow_state == Flow::FlowState::SETUP || + (flow->flow_state == Flow::FlowState::INSPECT && + (!flow->ssn_client || !flow->session->setup(p))) ) flow->set_state(Flow::FlowState::ALLOW); ++news; diff --git a/src/framework/data_bus.h b/src/framework/data_bus.h index 127f733b9..c37a36640 100644 --- a/src/framework/data_bus.h +++ b/src/framework/data_bus.h @@ -59,6 +59,13 @@ protected: DataEvent() = default; }; +class BareDataEvent final : public DataEvent +{ +public: + BareDataEvent() = default; + ~BareDataEvent() override = default; +}; + class DataHandler { public: @@ -123,15 +130,24 @@ private: }; } -// common data events +// +// Common core functionality data events +// + #define PACKET_EVENT "detection.packet" #define DAQ_META_EVENT "daq.metapacket" #define FLOW_STATE_EVENT "flow.state_change" #define THREAD_IDLE_EVENT "thread.idle" #define THREAD_ROTATE_EVENT "thread.rotate" -// An event that indicates that the service on a flow has been updated. -#define FLOW_SERVICE_CHANGE_EVENT "flow_service_change_event" +// A flow changed its service +#define FLOW_SERVICE_CHANGE_EVENT "flow.service_change_event" + +// A flow has entered the setup state +#define FLOW_STATE_SETUP_EVENT "flow.state_setup" + +// A new standby flow was generated by stream high availability +#define STREAM_HA_NEW_FLOW_EVENT "stream.ha.new_flow" #endif diff --git a/src/framework/inspector.h b/src/framework/inspector.h index 75aa7800f..ed4509a0b 100644 --- a/src/framework/inspector.h +++ b/src/framework/inspector.h @@ -91,7 +91,6 @@ public: virtual void clear(Packet*) { } virtual void meta(int, const uint8_t*) { } - virtual int exec(int, void*) { return 0; } // framework support unsigned get_ref(unsigned i) { return ref_count[i]; } @@ -172,7 +171,6 @@ public: enum InspectorType { IT_PASSIVE, // config only, or data consumer (eg file_log, binder, ftp_client) - IT_BINDER, // maps config to traffic IT_WIZARD, // guesses service inspector IT_PACKET, // processes raw packets only (eg normalize, capture) IT_STREAM, // flow tracking and reassembly (eg ip, tcp, udp) diff --git a/src/managers/inspector_manager.cc b/src/managers/inspector_manager.cc index c6b9e6600..1f2242625 100644 --- a/src/managers/inspector_manager.cc +++ b/src/managers/inspector_manager.cc @@ -27,7 +27,6 @@ #include #include "binder/bind_module.h" -#include "binder/binder.h" #include "detection/detect.h" #include "detection/detection_engine.h" #include "flow/flow.h" @@ -248,6 +247,9 @@ void FrameworkPolicy::vectorize() { case IT_PASSIVE : passive.add(p); + // FIXIT-L Ugly special case for noticing a binder + if ( !strcmp(p->pp_class.api.base.name, bind_id) ) + binder = p->handler; break; case IT_PACKET: @@ -267,10 +269,6 @@ void FrameworkPolicy::vectorize() service.add(p); break; - case IT_BINDER: - binder = p->handler; - break; - case IT_WIZARD: wizard = p->handler; break; @@ -415,7 +413,7 @@ static PHInstance* get_instance( FrameworkPolicy* fp, const char* keyword, bool dflt_only = false) { std::vector::iterator it; - return get_instance(fp, keyword, dflt_only, it)? *it : nullptr; + return get_instance(fp, keyword, dflt_only, it) ? *it : nullptr; } static PHInstance* get_new( @@ -502,14 +500,14 @@ void InspectorManager::dispatch_meta(FrameworkPolicy* fp, int type, const uint8_ p->handler->meta(type, data); } -Inspector* InspectorManager::get_binder() +Binder* InspectorManager::get_binder() { InspectionPolicy* pi = snort::get_inspection_policy(); if ( !pi || !pi->framework_policy ) return nullptr; - return pi->framework_policy->binder; + return (Binder*) pi->framework_policy->binder; } // FIXIT-P cache get_inspector() returns or provide indexed lookup @@ -555,7 +553,7 @@ bool InspectorManager::delete_inspector(SnortConfig* sc, const char* iname) fp->ilist.erase(old_it); ok = true; std::vector::iterator bind_it; - if ( get_instance(fp, "binder", false, bind_it) ) + if ( get_instance(fp, bind_id, false, bind_it) ) { (*bind_it)->handler->remove_inspector_binding(sc, iname); } @@ -740,7 +738,7 @@ Inspector* InspectorManager::instantiate( #endif // create default binding for wizard and configured services -static void instantiate_binder(SnortConfig* sc, FrameworkPolicy* fp) +static void instantiate_default_binder(SnortConfig* sc, FrameworkPolicy* fp) { BinderModule* m = (BinderModule*)ModuleManager::get_module(bind_id); bool tcp = false, udp = false, pdu = false; @@ -798,7 +796,7 @@ static bool configure(SnortConfig* sc, FrameworkPolicy* fp, bool cloned) if ( new_ins or reenabled_ins ) { std::vector::iterator old_binder; - if ( get_instance(fp, "binder", false, old_binder) ) + if ( get_instance(fp, bind_id, false, old_binder) ) { if ( new_ins and fp->default_binder ) { @@ -823,7 +821,7 @@ static bool configure(SnortConfig* sc, FrameworkPolicy* fp, bool cloned) // can't bind wizard but this exposes other issues that must // be fixed first. if ( fp->session.num and !fp->binder /*and fp->wizard*/ ) - instantiate_binder(sc, fp); + instantiate_default_binder(sc, fp); return ok; } @@ -918,10 +916,8 @@ static inline void execute( void InspectorManager::bumble(Packet* p) { Flow* flow = p->flow; - Inspector* ins = get_binder(); - if ( ins ) - ins->exec(BinderSpace::ExecOperation::HANDLE_GADGET, flow); + DataBus::publish(FLOW_SERVICE_CHANGE_EVENT, p); flow->clear_clouseau(); diff --git a/src/managers/inspector_manager.h b/src/managers/inspector_manager.h index d6b57c016..6fe1fb26a 100644 --- a/src/managers/inspector_manager.h +++ b/src/managers/inspector_manager.h @@ -25,10 +25,7 @@ #include "framework/inspector.h" -#ifdef PIGLET -#include "framework/inspector.h" -#endif - +class Binder; struct FrameworkPolicy; struct InspectionPolicy; @@ -64,7 +61,7 @@ public: static InspectorType get_type(const char* key); SO_PUBLIC static Inspector* get_inspector(const char* key, bool dflt_only = false); - SO_PUBLIC static Inspector* get_binder(); + SO_PUBLIC static Binder* get_binder(); SO_PUBLIC static Inspector* acquire(const char* key, bool dflt_only = false); SO_PUBLIC static void release(Inspector*); diff --git a/src/network_inspectors/binder/CMakeLists.txt b/src/network_inspectors/binder/CMakeLists.txt index 3b5a833e6..2bb28f3ed 100644 --- a/src/network_inspectors/binder/CMakeLists.txt +++ b/src/network_inspectors/binder/CMakeLists.txt @@ -1,7 +1,6 @@ set(FILE_LIST binder.cc - binder.h binding.h bind_module.cc bind_module.h diff --git a/src/network_inspectors/binder/binder.cc b/src/network_inspectors/binder/binder.cc index 8a679300d..8d0b603e3 100644 --- a/src/network_inspectors/binder/binder.cc +++ b/src/network_inspectors/binder/binder.cc @@ -21,8 +21,6 @@ #include "config.h" #endif -#include "binder.h" - #include "flow/flow.h" #include "flow/flow_key.h" #include "framework/data_bus.h" @@ -577,12 +575,15 @@ public: bool configure(SnortConfig*) override; - void eval(Packet*) override; - int exec(int, void*) override; + void eval(Packet*) override { } void add(Binding* b) { bindings.push_back(b); } + void handle_flow_setup(Packet*); + void handle_flow_service_change(Flow*); + void handle_new_standby_flow(Flow*); + private: void apply(const Stuff&, Flow*); @@ -590,24 +591,48 @@ private: void get_bindings(Flow*, Stuff&, Packet* = nullptr); // may be null when dealing with HA flows void apply(Flow*, Stuff&); Inspector* find_gadget(Flow*); - int exec_handle_gadget(void*); - int exec_eval_standby_flow(void*); private: vector bindings; }; +class FlowStateSetupHandler : public DataHandler +{ +public: + FlowStateSetupHandler() = default; + + void handle(DataEvent& event, Flow* flow) override + { + Binder* binder = InspectorManager::get_binder(); + if (binder && flow) + binder->handle_flow_setup(const_cast(event.get_packet())); + } +}; + // When a flow's service changes, re-evaluate service to inspector mapping. class FlowServiceChangeHandler : public DataHandler { public: - FlowServiceChangeHandler() { } + FlowServiceChangeHandler() = default; + + void handle(DataEvent&, Flow* flow) override + { + Binder* binder = InspectorManager::get_binder(); + if (binder && flow) + binder->handle_flow_service_change(flow); + } +}; + +class StreamHANewFlowHandler : public DataHandler +{ +public: + StreamHANewFlowHandler() = default; void handle(DataEvent&, Flow* flow) override { - Binder* binder = (Binder*)InspectorManager::get_binder(); - if(binder and flow) - binder->exec(BinderSpace::ExecOperation::HANDLE_GADGET, flow); + Binder* binder = InspectorManager::get_binder(); + if (binder && flow) + binder->handle_new_standby_flow(flow); } }; @@ -644,7 +669,9 @@ bool Binder::configure(SnortConfig* sc) set_binding(sc, pb); } - DataBus::subscribe(FLOW_SERVICE_CHANGE_EVENT, new FlowServiceChangeHandler); + DataBus::subscribe(FLOW_STATE_SETUP_EVENT, new FlowStateSetupHandler()); + DataBus::subscribe(FLOW_SERVICE_CHANGE_EVENT, new FlowServiceChangeHandler()); + DataBus::subscribe(STREAM_HA_NEW_FLOW_EVENT, new StreamHANewFlowHandler()); return true; } @@ -669,7 +696,7 @@ void Binder::remove_inspector_binding(SnortConfig*, const char* name) } } -void Binder::eval(Packet* p) +void Binder::handle_flow_setup(Packet* p) { Profile profile(bindPerfStats); Stuff stuff; @@ -682,11 +709,12 @@ void Binder::eval(Packet* p) ++bstats.packets; } -int Binder::exec_handle_gadget( void* pv ) +void Binder::handle_flow_service_change( Flow* flow ) { - assert(pv); + Profile profile(bindPerfStats); + + assert(flow); - Flow* flow = (Flow*)pv; Inspector* ins = find_gadget(flow); if ( ins ) @@ -700,7 +728,7 @@ int Binder::exec_handle_gadget( void* pv ) flow->ssn_state.snort_protocol_id = SnortConfig::get_conf()->proto_ref->find(flow->service); if ( !flow->is_stream() ) - return 0; + return; if ( ins ) { @@ -712,36 +740,17 @@ int Binder::exec_handle_gadget( void* pv ) Stream::set_splitter(flow, true, new AtomSplitter(true)); Stream::set_splitter(flow, false, new AtomSplitter(false)); } - - return 0; } -// similar to eval(), but working on a Flow in HA Standby mode -int Binder::exec_eval_standby_flow( void* pv ) +void Binder::handle_new_standby_flow( Flow* flow ) { - Flow* flow = (Flow*)pv; + Profile profile(bindPerfStats); Stuff stuff; get_bindings(flow, stuff); apply(flow, stuff); ++bstats.verdicts[stuff.action]; - return 0; -} - -int Binder::exec(int operation, void* pv) -{ - Profile profile(bindPerfStats); - - switch( operation ) - { - case BinderSpace::ExecOperation::HANDLE_GADGET: - return exec_handle_gadget( pv ); - case BinderSpace::ExecOperation::EVAL_STANDBY_FLOW: - return exec_eval_standby_flow( pv ); - default: - return (-1); - } } //------------------------------------------------------------------------- @@ -825,7 +834,7 @@ void Binder::get_bindings(Flow* flow, Stuff& stuff, Packet* p) } } - Binder* sub = (Binder*)InspectorManager::get_binder(); + Binder* sub = InspectorManager::get_binder(); // If policy selection produced a new binder to use, use that instead. if ( sub && sub != this ) @@ -909,7 +918,7 @@ static const InspectApi bind_api = mod_ctor, mod_dtor }, - IT_BINDER, + IT_PASSIVE, PROTO_BIT__ANY_TYPE, nullptr, // buffers nullptr, // service diff --git a/src/network_inspectors/binder/binder.h b/src/network_inspectors/binder/binder.h deleted file mode 100644 index 1a01ccfe6..000000000 --- a/src/network_inspectors/binder/binder.h +++ /dev/null @@ -1,30 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (C) 2016-2018 Cisco and/or its affiliates. All rights reserved. -// -// This program is free software; you can redistribute it and/or modify it -// under the terms of the GNU General Public License Version 2 as published -// by the Free Software Foundation. You may not use, modify or distribute -// this program under any other version of the GNU General Public License. -// -// This program is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with this program; if not, write to the Free Software Foundation, Inc., -// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -//-------------------------------------------------------------------------- - -// binder.h author Ed Borgoyn - -#ifndef BINDER_H -#define BINDER_H - -namespace BinderSpace -{ - enum ExecOperation : int { HANDLE_GADGET, EVAL_STANDBY_FLOW }; -} - -#endif - diff --git a/src/stream/base/stream_ha.cc b/src/stream/base/stream_ha.cc index f5f69c19b..641125e45 100644 --- a/src/stream/base/stream_ha.cc +++ b/src/stream/base/stream_ha.cc @@ -25,7 +25,6 @@ #include -#include "binder/binder.h" #include "flow/flow_key.h" #include "managers/inspector_manager.h" #include "stream/stream.h" @@ -107,9 +106,10 @@ bool StreamHAClient::consume(Flow*& flow, FlowKey* key, HAMessage* msg) // A nullptr indicates that the protocol has no handler if ( (flow = protocol_create_session(key)) == nullptr ) return false; - Inspector* b = InspectorManager::get_binder(); - if ( b != nullptr ) - b->exec(BinderSpace::ExecOperation::EVAL_STANDBY_FLOW,(void*)flow); + + BareDataEvent event; + DataBus::publish(STREAM_HA_NEW_FLOW_EVENT, event, flow); + flow->ha_state->clear(FlowHAState::NEW); int family = (hac->flags & SessionHAContent::FLAG_IP6) ? AF_INET6 : AF_INET; if ( hac->flags & SessionHAContent::FLAG_LOW )