}
// Add key/data pair to front of list.
- list.push_front(std::make_pair(key, data));
+ list.emplace_front(std::make_pair(key, data));
// Add list iterator for the new entry to map.
map[key] = list.begin();
#include "target_based/snort_protocols.h"
using namespace snort;
+using namespace std;
#define LRU_CACHE_INITIAL_SIZE 65535
LruCacheShared<HostIpKey, std::shared_ptr<HostTracker>, HashHostIpKey>
host_cache(LRU_CACHE_INITIAL_SIZE);
+namespace snort
+{
+
void host_cache_add_host_tracker(HostTracker* ht)
{
std::shared_ptr<HostTracker> sptr(ht);
host_cache.insert((const uint8_t*) ht->get_ip_addr().get_ip6_ptr(), sptr);
}
-namespace snort
-{
-bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, const char* service)
+bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, SnortProtocolId id)
{
HostIpKey ipkey((const uint8_t*) ipaddr.get_ip6_ptr());
- SnortProtocolId proto_id = SnortConfig::get_conf()->proto_ref->find(service);
- HostApplicationEntry app_entry(ipproto, port, proto_id);
std::shared_ptr<HostTracker> ht;
if (!host_cache.find(ipkey, ht))
{
// This host hasn't been seen. Add it.
- ht = std::make_shared<HostTracker>();
+ ht = std::make_shared<HostTracker>(ipaddr);
if (ht == nullptr)
{
host_cache.insert(ipkey, ht);
}
+ HostApplicationEntry app_entry(ipproto, port, id);
return ht->add_service(app_entry);
}
+bool host_cache_add_service(const SfIp& ipaddr, Protocol ipproto, Port port, const char* service)
+{
+ return host_cache_add_service(ipaddr, ipproto, port,
+ SnortConfig::get_conf()->proto_ref->find(service));
+}
+
bool host_cache_add_app_mapping(const SfIp& ipaddr, Port port, Protocol proto, AppId appId)
{
HostIpKey ipkey((const uint8_t*) ipaddr.get_ip6_ptr());
extern LruCacheShared<HostIpKey, std::shared_ptr<HostTracker>, HashHostIpKey> host_cache;
-void host_cache_add_host_tracker(HostTracker*);
-
namespace snort
{
+void host_cache_add_host_tracker(HostTracker*);
+
// Insert a new service into host cache if it doesn't already exist.
-SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, const char* service);
+SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, SnortProtocolId);
+SO_PUBLIC bool host_cache_add_service(const SfIp&, Protocol, Port, const char*);
+
bool host_cache_add_app_mapping(const SfIp&, Port, Protocol, AppId);
AppId host_cache_find_app_mapping(const SfIp* , Port, Protocol );
}
std::lock_guard<std::mutex> lck(host_tracker_lock);
AppMapping app_map = {port, proto, appid};
- app_mappings.push_back(app_map);
+ app_mappings.emplace_back(app_map);
}
AppId HostTracker::find_app_mapping(Port port, Protocol proto)
}
AppMapping app_map = {port, proto, appid};
- app_mappings.push_back(app_map);
+ app_mappings.emplace_back(app_map);
return true;
}
if (iter != services.end())
return false; // Already exists.
- services.push_front(app_entry);
+ services.emplace_front(app_entry);
return true;
}
if (iter != services.end())
services.erase(iter);
- services.push_front(app_entry);
+ services.emplace_front(app_entry);
}
bool HostTracker::find_service(Protocol ipproto, Port port, HostApplicationEntry& app_entry)
rna_inspector.h
rna_module.cc
rna_module.h
+ rna_pnd.cc
+ rna_pnd.h
)
#if (STATIC_INSPECTORS)
using namespace snort;
-void RnaIcmpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaIcmpEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
++rna_stats.icmp;
+ pnd.analyze_flow_icmp(event.get_packet());
}
-void RnaIpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaIpEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
++rna_stats.ip;
+ pnd.analyze_flow_ip(event.get_packet());
}
-void RnaUdpEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpSynEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
- ++rna_stats.udp;
+ ++rna_stats.tcp_syn;
+ pnd.analyze_flow_tcp(event.get_packet(), false);
}
-void RnaTcpSynEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpSynAckEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
- ++rna_stats.tcp_syn;
+ ++rna_stats.tcp_syn_ack;
+ pnd.analyze_flow_tcp(event.get_packet(), false);
}
-void RnaTcpSynAckEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaTcpMidstreamEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
- ++rna_stats.tcp_syn_ack;
+ ++rna_stats.tcp_midstream;
+ pnd.analyze_flow_tcp(event.get_packet(), true);
}
-void RnaTcpMidstreamEventHandler::handle(snort::DataEvent&, snort::Flow*)
+void RnaUdpEventHandler::handle(DataEvent& event, Flow*)
{
Profile profile(rna_perf_stats);
-
- ++rna_stats.tcp_midstream;
+ ++rna_stats.udp;
+ pnd.analyze_flow_udp(event.get_packet());
}
#include "framework/data_bus.h"
#include "rna_module.h"
+#include "rna_pnd.h"
class RnaIcmpEventHandler : public snort::DataHandler
{
public:
- RnaIcmpEventHandler() : DataHandler(RNA_NAME) { }
+ RnaIcmpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
class RnaIpEventHandler : public snort::DataHandler
{
public:
- RnaIpEventHandler() : DataHandler(RNA_NAME) { }
+ RnaIpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
-class RnaUdpEventHandler : public snort::DataHandler
+class RnaTcpSynEventHandler : public snort::DataHandler
{
public:
- RnaUdpEventHandler() : DataHandler(RNA_NAME) { }
+ RnaTcpSynEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
-class RnaTcpSynEventHandler : public snort::DataHandler
+class RnaTcpSynAckEventHandler : public snort::DataHandler
{
public:
- RnaTcpSynEventHandler() : DataHandler(RNA_NAME) { }
+ RnaTcpSynAckEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
-class RnaTcpSynAckEventHandler : public snort::DataHandler
+class RnaTcpMidstreamEventHandler : public snort::DataHandler
{
public:
- RnaTcpSynAckEventHandler() : DataHandler(RNA_NAME) { }
+ RnaTcpMidstreamEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
-class RnaTcpMidstreamEventHandler : public snort::DataHandler
+class RnaUdpEventHandler : public snort::DataHandler
{
public:
- RnaTcpMidstreamEventHandler() : DataHandler(RNA_NAME) { }
+ RnaUdpEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+ RnaPnd& pnd;
};
#endif
bool RnaInspector::configure(SnortConfig*)
{
- DataBus::subscribe( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpEventHandler() );
- DataBus::subscribe( STREAM_IP_NEW_FLOW_EVENT, new RnaIpEventHandler() );
- DataBus::subscribe( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpEventHandler() );
- DataBus::subscribe( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler() );
- DataBus::subscribe( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler() );
- DataBus::subscribe( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler() );
+ DataBus::subscribe( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpEventHandler(pnd) );
+ DataBus::subscribe( STREAM_IP_NEW_FLOW_EVENT, new RnaIpEventHandler(pnd) );
+ DataBus::subscribe( STREAM_UDP_NEW_FLOW_EVENT, new RnaUdpEventHandler(pnd) );
+ DataBus::subscribe( STREAM_TCP_SYN_EVENT, new RnaTcpSynEventHandler(pnd) );
+ DataBus::subscribe( STREAM_TCP_SYN_ACK_EVENT, new RnaTcpSynAckEventHandler(pnd) );
+ DataBus::subscribe( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler(pnd) );
return true;
}
void RnaInspector::eval(Packet* p)
{
Profile profile(rna_perf_stats);
+ ++rna_stats.other_packets;
- // Handling untracked sessions, e.g., non-IP packets
assert( !p->flow );
assert( !(BIT((unsigned)p->type()) & PROTO_BIT__ANY_SSN) );
- ++rna_stats.other_packets;
-
-#ifdef NDEBUG
+ // Handling untracked sessions, e.g., non-IP packets
+ // pnd.analyze_flow_non_ip(p);
UNUSED(p);
-#endif
}
void RnaInspector::show(SnortConfig*)
#include "framework/inspector.h"
#include "rna_module.h"
+#include "rna_pnd.h"
namespace snort
{
bool load_rna_conf();
const RnaModuleConfig* mod_conf = nullptr;
RnaConfig* rna_conf = nullptr;
+ RnaPnd pnd;
};
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2003-2013 Sourcefire, Inc.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+// rna_pnd.cc authors: Martin Roesch <roesch@sourcefire.com>
+// Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_pnd.h"
+
+#include "host_tracker/host_cache.h"
+
+using namespace snort;
+
+static const uint8_t zeromac[6] = {0, 0, 0, 0, 0, 0};
+
+static inline bool is_eligible_packet(const snort::Packet* p)
+{
+ if ( p->has_ip() or
+ memcmp(snort::layer::get_eth_layer(p)->ether_src, zeromac, sizeof(zeromac)) )
+ return true;
+ return false;
+}
+
+static inline bool is_eligible_ip(const snort::Packet* p)
+{
+ // If payload needs to be inspected ever, allow rebuilt packet when is_proxied
+ if ( !is_eligible_packet(p) or p->is_rebuilt() or !p->flow )
+ return false;
+ return true;
+}
+
+static inline bool is_eligible_tcp(const snort::Packet* p)
+{
+ if ( !is_eligible_ip(p) or p->ptrs.tcph->is_rst() )
+ return false;
+ return true;
+}
+
+static inline bool is_eligible_udp(const snort::Packet* p)
+{
+ if ( !is_eligible_ip(p) )
+ return false;
+ if ( p->is_from_client() )
+ {
+ const snort::SfIp* src = p->ptrs.ip_api.get_src();
+ const snort::SfIp* dst = p->ptrs.ip_api.get_dst();
+ if ( !src->is_set() and IN6_IS_ADDR_MULTICAST(dst->get_ip6_ptr()) and
+ p->ptrs.sp == 68 and p->ptrs.dp == 67 )
+ return false; // skip BOOTP
+ }
+ return true;
+}
+
+void RnaPnd::analyze_flow_icmp(const Packet* p)
+{
+ if ( is_eligible_ip(p) )
+ discover_network_icmp(p);
+}
+
+void RnaPnd::analyze_flow_ip(const Packet* p)
+{
+ if ( is_eligible_ip(p) )
+ discover_network_ip(p);
+}
+
+void RnaPnd::analyze_flow_non_ip(const Packet* p)
+{
+ if ( is_eligible_packet(p) )
+ discover_network_non_ip(p);
+}
+
+void RnaPnd::analyze_flow_tcp(const Packet* p, bool is_midstream)
+{
+ // If and when flow stores rna state, process the flow data here before global cache access
+ if ( is_eligible_tcp(p) )
+ discover_network_tcp(p);
+
+ UNUSED(is_midstream);
+}
+
+void RnaPnd::analyze_flow_udp(const Packet* p)
+{
+ if ( is_eligible_udp(p) )
+ discover_network_udp(p);
+}
+
+void RnaPnd::discover_network_icmp(const Packet* p)
+{
+ if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+ p->flow->client_port, SNORT_PROTO_ICMP) )
+ return;
+ // process rna discovery for icmp
+}
+
+void RnaPnd::discover_network_ip(const Packet* p)
+{
+ if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+ p->flow->client_port, SNORT_PROTO_IP) )
+ return;
+ // process rna discovery for ip
+}
+
+void RnaPnd::discover_network_non_ip(const Packet* p)
+{
+ // process rna discovery for non-ip in mac cache
+ UNUSED(p);
+}
+
+void RnaPnd::discover_network_tcp(const Packet* p)
+{
+ // Track from initiator direction, if not already seen
+ if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+ p->flow->client_port, SNORT_PROTO_TCP) )
+ return;
+
+ // Add mac address to ht list, ttl, last_seen, etc.
+ // Generate new host events
+}
+
+void RnaPnd::discover_network_udp(const Packet* p)
+{
+ if ( !host_cache_add_service(p->flow->client_ip, (uint8_t)p->get_ip_proto_next(),
+ p->flow->client_port, SNORT_PROTO_UDP) )
+ return;
+ // process rna discovery for udp
+}
+
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2014-2019 Cisco and/or its affiliates. All rights reserved.
+// Copyright (C) 2003-2013 Sourcefire, Inc.
+//
+// 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.
+//--------------------------------------------------------------------------
+
+#ifndef RNA_PND_H
+#define RNA_PND_H
+
+#include "protocols/eth.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+
+namespace snort
+{
+struct Packet;
+}
+
+class RnaPnd
+{
+public:
+ void analyze_flow_icmp(const snort::Packet* p);
+ void analyze_flow_ip(const snort::Packet* p);
+ void analyze_flow_non_ip(const snort::Packet* p);
+ void analyze_flow_tcp(const snort::Packet* p, bool is_midstream);
+ void analyze_flow_udp(const snort::Packet* p);
+
+private:
+ // General rna utilities not associated with flow
+ void discover_network_icmp(const snort::Packet* p);
+ void discover_network_ip(const snort::Packet* p);
+ void discover_network_non_ip(const snort::Packet* p);
+ void discover_network_tcp(const snort::Packet* p);
+ void discover_network_udp(const snort::Packet* p);
+};
+
+#endif