]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1733 in SNORT/snort3 from ~SMINUT/snort3:rna_update_timeout to...
authorMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 10 Sep 2019 16:31:19 +0000 (12:31 -0400)
committerMike Stepanek (mstepane) <mstepane@cisco.com>
Tue, 10 Sep 2019 16:31:19 +0000 (12:31 -0400)
Squashed commit of the following:

commit e082dd186ee53898cb90b31d7b426cd277afd2f1
Author: Silviu Minut <sminut@cisco.com>
Date:   Thu Sep 5 12:41:00 2019 -0400

    rna: generate an RNA_EVENT_CHANGE when a host is seen after the last log event and the current time is past the update timeout.

    rna: lock when returning last_seen and last_event in host tracker and add peg counts for RnaIdleEventHandler.

    rna: pass cond_var to the rna log functions, as per snort 2.

    rna: make generation of a CHANGE_HOST_UPDATE event from idle, configurable.

    rna: change RnaLoggerEvent::cond_var from time_t to void* because SfUnified2LoggerRNA::rna_serialize() already takes a void* as cond_var.

    rna: pass host tracker IP address rather than NULL when calling generate_change_host_update from idle.

    rna: supress unused variable message in RnaIdleEventHandle::handle().

    rna: address reviewers' comments.

13 files changed:
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/rna/rna_config.h
src/network_inspectors/rna/rna_event_handler.cc
src/network_inspectors/rna/rna_event_handler.h
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_logger.cc
src/network_inspectors/rna/rna_logger.h
src/network_inspectors/rna/rna_logger_common.h
src/network_inspectors/rna/rna_module.cc
src/network_inspectors/rna/rna_module.h
src/network_inspectors/rna/rna_pnd.cc
src/network_inspectors/rna/rna_pnd.h

index 28f5c8fb7e304a39e26ce85c345b02362a796f76..6a3bc8a092d6726c494801c5b685c7562a04ab27 100644 (file)
@@ -40,6 +40,12 @@ void HostTracker::update_last_seen()
     last_seen = (uint32_t) packet_time();
 }
 
+void HostTracker::update_last_event(uint32_t time)
+{
+    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    last_event = time ? time : last_seen;
+}
+
 bool HostTracker::add_mac(const u_int8_t* mac, u_int8_t ttl, u_int8_t primary)
 {
     if ( !mac or !memcmp(mac, zero_mac, MAC_SIZE) )
index ac2bce1ce3f3c074ac7111f0a3a7fecf965d55f5..ff46f9adc1de36397b49df65848c36b4a34fefa5 100644 (file)
@@ -78,9 +78,24 @@ class SO_PUBLIC HostTracker
 {
 public:
     HostTracker() : hops(-1)
-    { last_seen = (uint32_t) packet_time(); }
+    {
+        last_seen = (uint32_t) packet_time();
+        last_event = -1;
+    }
 
     void update_last_seen();
+    uint32_t get_last_seen() const
+    {
+        std::lock_guard<std::mutex> lck(host_tracker_lock);
+        return last_seen;
+    }
+
+    void update_last_event(uint32_t time = 0);
+    uint32_t get_last_event() const
+    {
+        std::lock_guard<std::mutex> lck(host_tracker_lock);
+        return last_event;
+    }
 
     // Returns true if a new mac entry is added, false otherwise
     bool add_mac(const u_int8_t* mac, u_int8_t ttl, u_int8_t primary);
@@ -99,9 +114,10 @@ public:
     void stringify(std::string& str);
 
 private:
-    std::mutex host_tracker_lock; // ensure that updates to a shared object are safe
+    mutable std::mutex host_tracker_lock; // ensure that updates to a shared object are safe
     uint8_t hops;                 // hops from the snort inspector, e.g., zero for ARP
     uint32_t last_seen;           // the last time this host was seen
+    uint32_t last_event;          // the last time an event was generated
     std::list<HostMac, HostMacAllocator> macs;
     std::vector<HostApplication, HostAppAllocator> services;
 
index 791b4f5b35aba76d493d6246b2e6e22e0a77ef90..c8a6723321d474ea23b9b2541010d7cb38e87f92 100644 (file)
@@ -28,6 +28,7 @@ struct RnaModuleConfig
     std::string fingerprint_dir;
     std::string custom_fingerprint_dir;
     bool enable_logger;
+    bool log_when_idle;
 };
 
 // Give default values so that RNA can work even if rna_conf_path is not provided
@@ -39,7 +40,7 @@ struct RnaConfig
     uint16_t max_host_services = 100;
     uint16_t max_host_service_info = 16;
     bool enable_banner_grab = 0;
+    bool log_when_idle = 0;
 };
 
 #endif
-
index 012a37947bf2125c08d009d4826dfadb8830b511..75724cccd59fcd7df47cb75c5cdb53fc5e94d498 100644 (file)
@@ -88,3 +88,11 @@ void RnaUdpNewFlowEventHandler::handle(DataEvent& event, Flow*)
     ++rna_stats.udp_new;
     pnd.analyze_flow_udp(event.get_packet());
 }
+
+void RnaIdleEventHandler::handle(DataEvent& event, Flow*)
+{
+    UNUSED(event);
+    Profile profile(rna_perf_stats);
+    ++rna_stats.change_host_update;
+    pnd.generate_change_host_update();
+}
index cc6adbb29f8afa20e236d21577ca93047e1705db..1d809aed50d578ce17921861d14d35c8958718ba 100644 (file)
@@ -108,4 +108,13 @@ private:
     RnaPnd& pnd;
 };
 
+class RnaIdleEventHandler : public snort::DataHandler
+{
+public:
+    RnaIdleEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
+};
+
 #endif
index bbfc697805740b8ccf07aecd79eb5ac9b90b9014..4315f7a9718ae0be4187c1d49eede1c2774e8d97 100644 (file)
@@ -53,10 +53,11 @@ RnaInspector::RnaInspector(RnaModule* mod)
 {
     mod_conf = mod->get_config();
     load_rna_conf();
+    time_t update_timeout = rna_conf ? rna_conf->update_timeout : 0;
     if ( mod_conf )
-        pnd = new RnaPnd(mod_conf->enable_logger, mod_conf->rna_conf_path);
+        pnd = new RnaPnd(mod_conf->enable_logger, mod_conf->rna_conf_path, update_timeout);
     else
-        pnd = new RnaPnd(false, "");
+        pnd = new RnaPnd(false, "", update_timeout);
 }
 
 RnaInspector::~RnaInspector()
@@ -80,6 +81,8 @@ bool RnaInspector::configure(SnortConfig*)
     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) );
+    if (rna_conf && rna_conf->log_when_idle)
+        DataBus::subscribe( THREAD_IDLE_EVENT, new RnaIdleEventHandler(*pnd) );
 
     return true;
 }
index ccc0cd7c2412f7e0fd173e8ab43c386707373778..bd1708ddb92e989a3a459031441b87692bbb9be0 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "managers/event_manager.h"
 #include "protocols/packet.h"
+#include "rna_logger_common.h"
 
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
@@ -34,8 +35,9 @@
 
 using namespace snort;
 
-bool RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const RnaTracker* ht,
-    const struct in6_addr* src_ip, const u_int8_t* src_mac)
+bool RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+    const struct in6_addr* src_ip, const u_int8_t* src_mac, uint32_t event_time,
+    void* cond_var)
 {
     if ( !enabled )
         return false;
@@ -46,6 +48,13 @@ bool RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const RnaT
     else
         rle.ip = nullptr;
 
+    if (ht)
+    {
+        (*ht)->update_last_event(event_time);
+        if (type == RNA_EVENT_CHANGE && subtype == CHANGE_HOST_UPDATE)
+            rle.cond_var = cond_var;
+    }
+
     EventManager::call_loggers(nullptr, const_cast<Packet*>(p), "RNA", &rle);
     return true;
 }
index 24091e2bf3c456e2eb41a7074b60c624291b1c85..0b72de6af09723a488448cf1101f57da7cf0da5d 100644 (file)
@@ -40,14 +40,16 @@ struct RnaLoggerEvent : public Event
     const RnaTracker* ht;
     const u_int8_t* mac;
     const struct in6_addr* ip;
+    void* cond_var = nullptr;
 };
 
 class RnaLogger
 {
 public:
     RnaLogger(const bool enable) : enabled(enable) { }
-    bool log(uint16_t type, uint16_t subtype, const snort::Packet* p, const RnaTracker* ht,
-        const struct in6_addr* src_ip, const u_int8_t* src_mac);
+    bool log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+       const struct in6_addr* src_ip, const u_int8_t* src_mac,
+       uint32_t event_time = 0, void* cond_var = nullptr);
 
 private:
     const bool enabled;
index bcdf273d21c48f7a89dc5b31d481d644fb421007..1f256c1a7d42b6988f6017c62b7980269ca8feee 100644 (file)
@@ -24,4 +24,7 @@
 #define RNA_EVENT_NEW       1000
     #define NEW_HOST            1
 
+#define RNA_EVENT_CHANGE    1001
+    #define CHANGE_HOST_UPDATE         15
+
 #endif
index 708dd6de41cac2aaa17d560df7e11eb567fd8d74..d954d76cb23833a172bf559ca940b9bab0bb4e76 100644 (file)
@@ -56,6 +56,9 @@ static const Parameter rna_params[] =
     { "enable_logger", Parameter::PT_BOOL, nullptr, "true",
       "enable or disable writing discovery events into logger" },
 
+    { "log_when_idle", Parameter::PT_BOOL, nullptr, "false",
+      "enable host update logging when snort is idle" },
+
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
@@ -71,6 +74,7 @@ static const PegInfo rna_pegs[] =
     { CountType::SUM, "tcp_syn_ack", "count of TCP SYN-ACK packets received" },
     { CountType::SUM, "tcp_midstream", "count of TCP midstream packets received" },
     { CountType::SUM, "other_packets", "count of packets received without session tracking" },
+    { CountType::SUM, "change_host_update", "count number of change host update events" },
     { CountType::END, nullptr, nullptr},
 };
 
@@ -107,6 +111,8 @@ bool RnaModule::set(const char*, Value& v, SnortConfig*)
         mod_conf->custom_fingerprint_dir = std::string(v.get_string());
     else if (v.is("enable_logger"))
         mod_conf->enable_logger = v.get_bool();
+    else if (v.is("log_when_idle"))
+        mod_conf->log_when_idle = v.get_bool();
     else
         return false;
 
index 15f4157ef927ed84db31aab430cd21647122a599..b835670b36c143f366b0fcf5222f8de3892f1421 100644 (file)
@@ -41,6 +41,7 @@ struct RnaStats
     PegCount tcp_syn_ack;
     PegCount tcp_midstream;
     PegCount other_packets;
+    PegCount change_host_update;
 };
 
 extern THREAD_LOCAL RnaStats rna_stats;
@@ -68,4 +69,3 @@ private:
 };
 
 #endif
-
index f4130bf8492c3ea4a9b36e74637647756a575358..ed818d6d5851359cfcd03d3b7dbd573b99edfb34 100644 (file)
@@ -153,8 +153,39 @@ void RnaPnd::discover_network(const Packet* p, u_int8_t ttl)
     ht->add_mac(src_mac, ttl, 0);
 
     if ( new_host )
+    {
         logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht,
             (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac);
+    }
+    else if ( update_timeout )
+        generate_change_host_update(&ht, p, src_ip, src_mac, packet_time());
+
+}
+
+void RnaPnd::generate_change_host_update(RnaTracker* ht, const snort::Packet* p,
+    const SfIp* src_ip, const uint8_t* src_mac, time_t sec)
+{
+    if ( !ht || !update_timeout)
+        return;
+
+    uint32_t last_seen = (*ht)->get_last_seen();
+    uint32_t last_event = (*ht)->get_last_event();
+    time_t timestamp = sec - update_timeout;
+    if ( last_seen > last_event && (time_t) last_event + update_timeout <= sec )
+        logger.log(RNA_EVENT_CHANGE, CHANGE_HOST_UPDATE, p, ht,
+        (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac, last_seen, (void*) &timestamp);
+    // FIXIT-M: deal with host service hits.
+}
+
+void RnaPnd::generate_change_host_update()
+{
+    if ( !update_timeout )
+        return;
+
+    auto hosts = host_cache.get_all_data();
+    auto sec = time(nullptr);
+    for ( auto & h : hosts )
+        generate_change_host_update(&h.second, nullptr, &h.first, nullptr, sec);
 }
 
 #ifdef UNIT_TEST
index e798554a3534c5c811e07c5de78dc67fb5485676..5abe5d6b1d90123049fe6ed5688d8bcfee43fea5 100644 (file)
@@ -23,6 +23,7 @@
 #include "helpers/discovery_filter.h"
 
 #include "rna_logger.h"
+#include "sfip/sf_ip.h"
 
 namespace snort
 {
@@ -37,8 +38,9 @@ enum class TcpPacketType
 class RnaPnd
 {
 public:
-    RnaPnd(const bool en, const std::string& conf)
-        : logger(RnaLogger(en)), filter(DiscoveryFilter(conf)) { }
+
+    RnaPnd(const bool en, const std::string& conf, time_t ut = 0)
+        : logger(RnaLogger(en)), filter(DiscoveryFilter(conf)), update_timeout(ut) { }
 
     void analyze_flow_icmp(const snort::Packet* p);
     void analyze_flow_ip(const snort::Packet* p);
@@ -46,6 +48,13 @@ public:
     void analyze_flow_tcp(const snort::Packet* p, TcpPacketType type);
     void analyze_flow_udp(const snort::Packet* p);
 
+    // generate change event for single host
+    void generate_change_host_update(RnaTracker* ht, const snort::Packet* p,
+        const snort::SfIp* src_ip, const uint8_t* src_mac, time_t sec);
+
+    // generate change event for all hosts in the ip cache
+    void generate_change_host_update();
+
 private:
     // General rna utilities not associated with flow
     void discover_network_icmp(const snort::Packet* p);
@@ -57,6 +66,7 @@ private:
 
     RnaLogger logger;
     DiscoveryFilter filter;
+    time_t update_timeout;
 };
 
 #endif