void update_allocations(size_t);
void update_deallocations(size_t);
- Inspector* get_handler() {return handler;}
+ Inspector* get_handler() { return handler; }
// return fixed size (could be an approx avg)
// this must be fixed for life of flow data instance
char ignore_direction;
};
-enum DeferredWhitelist {
+enum DeferredWhitelist
+{
WHITELIST_DEFER_OFF = 0,
WHITELIST_DEFER_ON,
WHITELIST_DEFER_STARTED,
int set_ignore_direction(char ignore_direction)
{
- if (ssn_state.ignore_direction != ignore_direction)
- ssn_state.ignore_direction = ignore_direction;
-
+ ssn_state.ignore_direction = ignore_direction;
return ssn_state.ignore_direction;
}
{
gadget->rem_ref();
gadget = nullptr;
+ if (assistant_gadget != nullptr)
+ clear_assistant_gadget();
+ }
+
+ void set_assistant_gadget(Inspector* ins)
+ {
+ assistant_gadget = ins;
+ assistant_gadget->add_ref();
+ }
+
+ void clear_assistant_gadget()
+ {
+ assistant_gadget->rem_ref();
+ assistant_gadget = nullptr;
}
void set_data(Inspector* pd)
{ return context_chain.front(); }
void set_default_session_timeout(uint32_t dst, bool force)
- {
+ {
if (force || (default_session_timeout == 0))
- default_session_timeout = dst;
+ default_session_timeout = dst;
}
void set_hard_expiration()
FlowData* flow_data;
Inspector* clouseau; // service identifier
Inspector* gadget; // service handler
+ Inspector* assistant_gadget;
Inspector* data;
const char* service;
else
ssn_state.session_flags |= SSNFLAG_NO_DETECT_TO_SERVER;
}
-
}
#endif
#include "protocols/packet.h"
#include "protocols/tcp.h"
#include "protocols/udp.h"
+#include "pub_sub/assistant_gadget_event.h"
#include "stream/stream.h"
#include "stream/stream_splitter.h"
#include "target_based/sftarget_reader.h"
return false;
}
+inline bool Binding::check_service(const char* service) const
+{
+ if ( when.svc == service )
+ return true;
+
+ return false;
+}
+
// we want to correlate src_zone to src_nets and src_ports, and dst_zone to dst_nets and
// dst_ports. it doesn't matter if the packet is actually moving in the opposite direction as
// binder is only evaluated once per flow and we need to capture the correct binding from
if ( forward_match )
return Binding::DR_FORWARD;
-
+
if ( reverse_match )
return Binding::DR_REVERSE;
{ return traffic_val == DAQ_PKTHDR_UNKNOWN ? true : when_val.test(traffic_val); });
}
-bool Binding::check_all(const Flow* flow, Packet* p) const
+bool Binding::check_all(const Flow* flow, Packet* p, const char* service) const
{
Binding::DirResult dir = Binding::DR_ANY_MATCH;
if ( dir == Binding::DR_NO_MATCH )
return false;
- if ( !check_service(flow) )
+ if (service)
+ {
+ if (!check_service(service))
+ return false;
+ }
+ else if ( !check_service(flow) )
return false;
if ( !check_zone(p) )
return InspectorManager::get_inspector(s);
}
+static Inspector* get_gadget_by_id(const char* service)
+{
+ const SnortProtocolId id = SnortConfig::get_conf()->proto_ref->find(service);
+ const char* s = SnortConfig::get_conf()->proto_ref->get_name(id);
+ return InspectorManager::get_inspector(s);
+}
+
//-------------------------------------------------------------------------
// stuff stuff
//-------------------------------------------------------------------------
bool apply_action(Flow*);
void apply_session(Flow*, const HostAttributeEntry*);
void apply_service(Flow*, const HostAttributeEntry*);
+ void apply_assistant(Flow*, const char*);
};
bool Stuff::update(Binding* pb)
flow->set_clouseau(wizard);
}
+void Stuff::apply_assistant(Flow* flow, const char* service)
+{
+ if ( !gadget )
+ gadget = get_gadget_by_id(service);
+
+ if ( gadget )
+ flow->set_assistant_gadget(gadget);
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
void handle_flow_setup(Packet*);
void handle_flow_service_change(Flow*);
void handle_new_standby_flow(Flow*);
+ void handle_assistant_gadget(const char* service, Packet*);
private:
void set_binding(SnortConfig*, Binding*);
- void get_bindings(Flow*, Stuff&, Packet* = nullptr); // may be null when dealing with HA flows
+ void get_bindings(Flow*, Stuff&, Packet* = nullptr, const char* = nullptr); // may be null when dealing with HA flows
void apply(Flow*, Stuff&);
+ void apply_assistant(Flow*, Stuff&, const char*);
Inspector* find_gadget(Flow*);
private:
}
};
+class AssistantGadgetHandler : public DataHandler
+{
+public:
+ AssistantGadgetHandler() : DataHandler(BIND_NAME) { }
+
+ void handle(DataEvent& event, Flow*) override
+ {
+ Binder* binder = InspectorManager::get_binder();
+ AssistantGadgetEvent* assistant_event = (AssistantGadgetEvent*)&event;
+
+ if (binder)
+ binder->handle_assistant_gadget(assistant_event->get_service(),
+ assistant_event->get_packet());
+ }
+};
+
Binder::Binder(vector<Binding*>& v)
{
bindings = std::move(v);
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());
+ DataBus::subscribe(FLOW_ASSISTANT_GADGET_EVENT, new AssistantGadgetHandler());
return true;
}
++bstats.verdicts[stuff.action];
}
+void Binder::handle_assistant_gadget(const char* service, Packet* p)
+{
+ Profile profile(bindPerfStats);
+ Stuff stuff;
+ Flow* flow = p->flow;
+
+ get_bindings(flow, stuff, p, service);
+ apply_assistant(flow, stuff, service);
+}
+
//-------------------------------------------------------------------------
// implementation stuff
//-------------------------------------------------------------------------
// FIXIT-P this is a simple linear search until functionality is nailed
// down. performance should be the focus of the next iteration.
-void Binder::get_bindings(Flow* flow, Stuff& stuff, Packet* p)
+void Binder::get_bindings(Flow* flow, Stuff& stuff, Packet* p, const char* service)
{
unsigned sz = bindings.size();
(!pb->use.network_index or network_set) )
continue;
- if ( !pb->check_all(flow, p) )
+ if ( !pb->check_all(flow, p, service) )
continue;
if ( pb->use.inspection_index and !inspection_set )
{
set_inspection_policy(SnortConfig::get_conf(), pb->use.inspection_index - 1);
- flow->inspection_policy_id = pb->use.inspection_index - 1;
+ if (!service)
+ flow->inspection_policy_id = pb->use.inspection_index - 1;
inspection_set = true;
}
if ( pb->use.ips_index and !ips_set )
{
set_ips_policy(SnortConfig::get_conf(), pb->use.ips_index - 1);
- flow->ips_policy_id = pb->use.ips_index - 1;
+ if (!service)
+ flow->ips_policy_id = pb->use.ips_index - 1;
ips_set = true;
}
if ( pb->use.network_index and !network_set )
{
set_network_policy(SnortConfig::get_conf(), pb->use.network_index - 1);
- flow->network_policy_id = pb->use.network_index - 1;
+ if (!service)
+ flow->network_policy_id = pb->use.network_index - 1;
network_set = true;
}
}
if ( pb->use.ips_index or pb->use.inspection_index or pb->use.network_index )
continue;
- if ( !pb->check_all(flow, p) )
+ if ( !pb->check_all(flow, p, service) )
continue;
if ( stuff.update(pb) )
stuff.apply_service(flow, host);
}
+void Binder::apply_assistant(Flow* flow, Stuff& stuff, const char* service)
+{
+ stuff.apply_assistant(flow, service);
+}
+
//-------------------------------------------------------------------------
// api stuff
//-------------------------------------------------------------------------
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2019-2019 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.
+//--------------------------------------------------------------------------
+// assistant_gadget_events.h author Maya Dagon <mdagon@cisco.com>
+
+#ifndef ASSISTANT_GADGET_EVENTS_H
+#define ASSISTANT_GADGET_EVENTS_H
+
+#include "framework/data_bus.h"
+#include "target_based/snort_protocols.h"
+#include "utils/util.h"
+
+// A flow is setting up assistant inspector.
+// For example used by HTTP2 to set NHI as assistant inspector.
+
+#define FLOW_ASSISTANT_GADGET_EVENT "flow.assistant_gadget"
+
+namespace snort
+{
+struct Packet;
+}
+
+class AssistantGadgetEvent : public snort::DataEvent
+{
+public:
+ AssistantGadgetEvent(snort::Packet* packet, const char* _service)
+ : p(packet), service(_service)
+ { }
+
+ snort::Packet* get_packet() override
+ { return p; }
+
+ const char* get_service()
+ { return service.c_str(); }
+
+private:
+ snort::Packet* p;
+ std::string service;
+};
+
+#endif
+