]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2389 in SNORT/snort3 from ~MASHASAN/snort3:rna_proto to master
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 11 Aug 2020 17:53:22 +0000 (17:53 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 11 Aug 2020 17:53:22 +0000 (17:53 +0000)
Squashed commit of the following:

commit e0f9fad3d3ba658ee4af9e1eae02cfc4f791f97a
Author: Masud Hasan <mashasan@cisco.com>
Date:   Fri Aug 7 19:19:03 2020 -0400

    rna: Discover network and transport protocols

13 files changed:
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/network_inspectors/rna/dev_notes.txt
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_mac_cache.cc
src/network_inspectors/rna/rna_mac_cache.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
src/network_inspectors/rna/test/rna_module_mock.h

index 0e1f354276eab5b0da78a04317feed65fc0ec627..fce17fc8370423e148a0f41c608ad26b15c4b598 100644 (file)
@@ -36,24 +36,48 @@ const uint8_t snort::zero_mac[MAC_SIZE] = {0, 0, 0, 0, 0, 0};
 
 void HostTracker::update_last_seen()
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
     last_seen = (uint32_t) packet_time();
 }
 
 void HostTracker::update_last_event(uint32_t time)
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
     last_event = time ? time : last_seen;
 }
 
+bool HostTracker::add_network_proto(const uint16_t type)
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+
+    for ( const auto& proto : network_protos )
+        if ( proto == type )
+            return false;
+
+    network_protos.emplace_back(type);
+    return true;
+}
+
+bool HostTracker::add_xport_proto(const uint8_t type)
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+
+    for ( const auto& proto : xport_protos )
+        if ( proto == type )
+            return false;
+
+    xport_protos.emplace_back(type);
+    return true;
+}
+
 bool HostTracker::add_mac(const uint8_t* mac, uint8_t ttl, uint8_t primary)
 {
     if ( !mac or !memcmp(mac, zero_mac, MAC_SIZE) )
         return false;
 
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
-    for ( auto& hm : macs )
+    for ( const auto& hm : macs )
         if ( !memcmp(mac, hm.mac, MAC_SIZE) )
             return false;
 
@@ -66,7 +90,7 @@ const HostMac* HostTracker::get_hostmac(const uint8_t* mac)
     if ( !mac or !memcmp(mac, zero_mac, MAC_SIZE) )
         return nullptr;
 
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     for ( const auto& hm : macs )
         if ( !memcmp(mac, hm.mac, MAC_SIZE) )
@@ -80,7 +104,7 @@ bool HostTracker::update_mac_ttl(const uint8_t* mac, uint8_t new_ttl)
     if ( !mac or !memcmp(mac, zero_mac, MAC_SIZE) )
         return false;
 
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     for ( auto& hm : macs )
         if ( !memcmp(mac, hm.mac, MAC_SIZE) )
@@ -104,7 +128,7 @@ bool HostTracker::make_primary(const uint8_t* mac)
 
     HostMac* hm = nullptr;
 
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     for ( auto& hm_iter : macs )
         if ( !memcmp(mac, hm_iter.mac, MAC_SIZE) )
@@ -127,7 +151,7 @@ bool HostTracker::make_primary(const uint8_t* mac)
 
 HostMac* HostTracker::get_max_ttl_hostmac()
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     HostMac* max_ttl_hm = nullptr;
     uint8_t max_ttl = 0;
@@ -173,7 +197,7 @@ void HostTracker::get_vlan_details(uint8_t& cfi, uint8_t& priority, uint16_t& vi
 
 void HostTracker::copy_data(uint8_t& p_hops, uint32_t& p_last_seen, list<HostMac>*& p_macs)
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     p_hops = hops;
     p_last_seen = last_seen;
@@ -184,7 +208,7 @@ void HostTracker::copy_data(uint8_t& p_hops, uint32_t& p_last_seen, list<HostMac
 bool HostTracker::add_service(Port port, IpProtocol proto, AppId appid, bool inferred_appid, bool* added)
 {
     host_tracker_stats.service_adds++;
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     for ( auto& s : services )
     {
@@ -211,7 +235,7 @@ bool HostTracker::add_service(Port port, IpProtocol proto, AppId appid, bool inf
 AppId HostTracker::get_appid(Port port, IpProtocol proto, bool inferred_only, bool allow_port_wildcard)
 {
     host_tracker_stats.service_finds++;
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     for ( const auto& s : services )
     {
@@ -225,7 +249,7 @@ AppId HostTracker::get_appid(Port port, IpProtocol proto, bool inferred_only, bo
 
 void HostTracker::remove_inferred_services()
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
     for ( auto s = services.begin(); s != services.end(); )
     {
         if (s->inferred_appid)
@@ -254,7 +278,7 @@ static inline string to_mac_string(const uint8_t* mac)
 
 void HostTracker::stringify(string& str)
 {
-    std::lock_guard<std::mutex> lck(host_tracker_lock);
+    lock_guard<mutex> lck(host_tracker_lock);
 
     str += "\n    hops: " + to_string(hops) + ", time: " + to_time_string(last_seen);
 
@@ -284,5 +308,21 @@ void HostTracker::stringify(string& str)
                     str += ", inferred";
             }
         }
-   }
+    }
+
+    auto total = network_protos.size();
+    if ( total )
+    {
+        str += "\nnetwork proto: ";
+        while ( total-- )
+            str += to_string(network_protos[total]) + (total? ", " : "");
+    }
+
+    total = xport_protos.size();
+    if ( total )
+    {
+        str += "\ntransport proto: ";
+        while ( total-- )
+            str += to_string(xport_protos[total]) + (total? ", " : "");
+    }
 }
index 9f42611b6d90424c987be9df05cccdecf2de9e1c..8947833cbe144da6ee5d94f11a5faddf17b3ba30 100644 (file)
@@ -136,6 +136,9 @@ public:
     // The caller owns and deletes the copied list of mac addresses
     void copy_data(uint8_t& p_hops, uint32_t& p_last_seen, std::list<HostMac>*& p_macs);
 
+    bool add_network_proto(const uint16_t type);
+    bool add_xport_proto(const uint8_t type);
+
     // Appid may not be identified always. Inferred means dynamic/runtime
     // appid detected from one flow to another flow such as BitTorrent.
     bool add_service(Port port, IpProtocol proto,
@@ -153,7 +156,9 @@ private:
     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<HostMac, HostMacAllocator> macs;
+    std::vector<uint16_t, HostCacheAllocIp<uint16_t>> network_protos;
+    std::vector<uint8_t, HostCacheAllocIp<uint8_t>> xport_protos;
     std::vector<HostApplication, HostAppAllocator> services;
     bool vlan_tag_present = false;
     vlan::VlanTagHdr vlan_tag;
index d90c9aaa52ab1cef7987e31a619a43acd8d1a18e..9530ac4939219c69e55598d38f957ad8c2466151 100644 (file)
@@ -54,11 +54,10 @@ to log the discovered hosts into a file, one can
 RNA Uses HostCacheMac, derived from LruCacheSharedMemcap, to track MAC addresses. The implementation
 of the MAC cache is as follows:
 
-   HostCacheMac (LruCacheSharedMemcap<uint8_t*, LruMac, HashMac>)
+   HostCacheMac (LruCacheSharedMemcap<uint8_t*, HostTrackerMac, HashMac>)
       |- - - - Key = uint8_t[6] (mac address)
-      |- - - - Data = LruMac
-      |                 | - - - - Valuetype = HostMacIp (derived from snort::HostMac)
-      |                 | - - - - Data = std::vector<ValueType, MacAllocator<ValueType>>
+      |- - - - Value = HostTrackerMac
+      |                 | - - - - Dynamic memory growth is tracked by HostCacheAllocMac allocator
       |
       |- - - - Hash = HashMac
       |                 |
index 01e3b568643ecc3c162df73f02f82734085cc031..8c5e6272e9ab5fda55a851b222529ea99fcd71b8 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "rna_logger.h"
 
+#include <cassert>
+
 #include "managers/event_manager.h"
 #include "protocols/packet.h"
 #include "rna_logger_common.h"
@@ -42,24 +44,20 @@ using namespace snort;
 
 bool RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
     const struct in6_addr* src_ip, const uint8_t* src_mac, uint32_t event_time,
-    void* cond_var, const HostMac* hm)
+    void* cond_var, const HostMac* hm, const uint16_t proto)
 {
     if ( !enabled )
         return false;
 
-    RnaLoggerEvent rle(type, subtype, ht, src_mac);
+    assert(ht);
+    RnaLoggerEvent rle(type, subtype, ht, src_mac, hm, proto);
     if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
         rle.ip = src_ip;
 
-    if (ht)
-    {
+    if ( event_time )
         (*ht)->update_last_event(event_time);
-        if (type == RNA_EVENT_CHANGE && subtype == CHANGE_HOST_UPDATE)
-            rle.cond_var = cond_var;
-    }
-
-    if (hm)
-        rle.hm = hm;
+    if ( subtype == CHANGE_HOST_UPDATE and type == RNA_EVENT_CHANGE )
+        rle.cond_var = cond_var;
 
     EventManager::call_loggers(nullptr, const_cast<Packet*>(p), "RNA", &rle);
     return true;
@@ -70,11 +68,12 @@ TEST_CASE("RNA logger", "[rna_logger]")
 {
     SECTION("Checking enabled flag")
     {
+        RnaTracker ht;
         RnaLogger logger1(false);
-        CHECK(logger1.log(0, 0, 0, 0, 0, 0) == false);
+        CHECK(logger1.log(0, 0, 0, &ht, 0, 0) == false);
 
         RnaLogger logger2(true);
-        CHECK(logger2.log(0, 0, 0, 0, 0, 0) == true);
+        CHECK(logger2.log(0, 0, 0, &ht, 0, 0) == true);
     }
 }
 #endif
index 7bfc487c329518234eb56a31655ea5a3920f8440..c9d87da4fa08b677c68b9c28b14d497b91665a7d 100644 (file)
@@ -35,7 +35,8 @@ using RnaTracker = std::shared_ptr<snort::HostTracker>;
 struct RnaLoggerEvent : public Event
 {
     RnaLoggerEvent(uint16_t p_type, uint16_t p_subtype, const RnaTracker* p_ht,
-        const uint8_t* p_mac) : type(p_type), subtype(p_subtype), ht(p_ht), mac(p_mac) { }
+        const uint8_t* p_mac, const snort::HostMac* p_hm, const uint16_t p_proto)
+        : type(p_type), subtype(p_subtype), ht(p_ht), mac(p_mac), hm(p_hm), proto(p_proto) { }
     uint16_t type;
     uint16_t subtype;
     const RnaTracker* ht;
@@ -43,6 +44,7 @@ struct RnaLoggerEvent : public Event
     const struct in6_addr* ip = nullptr;
     void* cond_var = nullptr;
     const snort::HostMac* hm;
+    const uint16_t proto;
 };
 
 class RnaLogger
@@ -51,7 +53,8 @@ public:
     RnaLogger(const bool enable) : enabled(enable) { }
     bool log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
        const struct in6_addr* src_ip, const uint8_t* src_mac,
-       uint32_t event_time = 0, void* cond_var = nullptr, const snort::HostMac* hm = nullptr);
+       uint32_t event_time = 0, void* cond_var = nullptr,
+       const snort::HostMac* hm = nullptr, const uint16_t proto = 0);
 
 private:
     const bool enabled;
index ec06c93f46eeab0a8938fca8154b0da86dd7ce8f..69d3ec11f25f35779a2b5e9ba713e820a1d24d94 100644 (file)
@@ -23,6 +23,8 @@
 // Common definitions between rna logger and pnd modules
 #define RNA_EVENT_NEW       1000
     #define NEW_HOST            1
+    #define NEW_NET_PROTOCOL    3
+    #define NEW_XPORT_PROTOCOL  4
 
 #define RNA_EVENT_CHANGE    1001
     #define CHANGE_HOPS                 5
index db7cdd1ca00f755f23e7999d8df9516bc73d7221..06fe2dee32c66b22194c30505f08e57113c88a2d 100644 (file)
 #endif
 #include "rna_mac_cache.h"
 
-#include <cassert>
-#include <vector>
-
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
 #endif
 
+using namespace snort;
+using namespace std;
+
 HostCacheMac host_cache_mac(MAC_CACHE_INITIAL_SIZE);
 
-void HostMacIp::update_vlan(uint16_t vth_pri_cfi_vlan, uint16_t vth_proto)
+bool HostTrackerMac::add_network_proto(const uint16_t type)
+{
+    lock_guard<mutex> lck(host_tracker_mac_lock);
+
+    for ( const auto& proto : network_protos )
+        if ( proto == type )
+            return false;
+
+    network_protos.emplace_back(type);
+    return true;
+}
+
+void HostTrackerMac::update_last_seen(uint32_t p_last_seen)
+{
+    lock_guard<mutex> lck(host_tracker_mac_lock);
+    last_seen = p_last_seen;
+}
+
+void HostTrackerMac::update_vlan(uint16_t vth_pri_cfi_vlan, uint16_t vth_proto)
 {
+    lock_guard<mutex> lck(host_tracker_mac_lock);
+
     vlan_tag_present = true;
     vlan_tag.vth_pri_cfi_vlan = vth_pri_cfi_vlan;
     vlan_tag.vth_proto = vth_proto;
 }
 
-bool HostMacIp::has_vlan()
+bool HostTrackerMac::has_vlan()
 {
+    lock_guard<mutex> lck(host_tracker_mac_lock);
     return vlan_tag_present;
 }
 
-uint16_t HostMacIp::get_vlan()
+uint16_t HostTrackerMac::get_vlan()
 {
+    lock_guard<mutex> lck(host_tracker_mac_lock);
     return vlan_tag.vth_pri_cfi_vlan;
 }
 
-void HostMacIp::get_vlan_details(uint8_t& cfi, uint8_t& priority, uint16_t& vid)
+void HostTrackerMac::get_vlan_details(uint8_t& cfi, uint8_t& priority, uint16_t& vid)
 {
+    lock_guard<mutex> lck(host_tracker_mac_lock);
+
     cfi = vlan_tag.cfi();
     priority = vlan_tag.priority();
     vid = vlan_tag.vid();
 }
 
+void HostTrackerMac::stringify(string& str)
+{
+    lock_guard<mutex> lck(host_tracker_mac_lock);
+
+    auto total = network_protos.size();
+    if ( total )
+    {
+        str += "\n Network proto: ";
+        while ( total-- )
+            str += to_string(network_protos[total]) + (total? ", " : "");
+    }
+}
+
 #ifdef UNIT_TEST
 TEST_CASE("RNA Mac Cache", "[rna_mac_cache]")
 {
@@ -72,37 +109,41 @@ TEST_CASE("RNA Mac Cache", "[rna_mac_cache]")
         MacKey c(c_mac);
         MacKey test(test_mac);
 
-        HostMacIp hm_b(b_mac, 1, 0);
+        bool new_host_mac = false;
 
-        bool new_host = false;
-        bool new_host_test = false;
+        auto a_ptr = host_cache_mac.find_else_create(a, &new_host_mac);
+        CHECK(new_host_mac == true);
+        CHECK(a_ptr != nullptr);
 
-        auto a_ptr = host_cache_mac.find_else_create(a, &new_host);
-        assert(new_host);
-        assert(a_ptr);
+        new_host_mac = false;
+        auto b_ptr = host_cache_mac.find_else_create(b, &new_host_mac);
+        CHECK(new_host_mac == true);
+        CHECK(b_ptr != nullptr);
 
-        auto b_ptr = host_cache_mac.find_else_create(b, &new_host);
-        assert(new_host);
-        b_ptr->insert(&hm_b);
-
-        auto c_ptr = host_cache_mac.find_else_create(c, &new_host);
-        assert(new_host);
-        assert(c_ptr);
+        new_host_mac = false;
+        auto c_ptr = host_cache_mac.find_else_create(c, &new_host_mac);
+        CHECK(new_host_mac == true);
+        CHECK(c_ptr != nullptr);
 
         // Try to add one of the previous macs again
-        auto test_ptr = host_cache_mac.find_else_create(test, &new_host_test);
-        assert(test_ptr);
-        assert(!new_host_test);
-
-        // Verify that test_ptr contains the host_mac we're looking for
-        assert(!memcmp(test_ptr->data.front().mac, b_mac, MAC_SIZE));
+        new_host_mac = false;
+        auto test_ptr = host_cache_mac.find_else_create(test, &new_host_mac);
+        CHECK(new_host_mac == false);
+        CHECK(test_ptr != nullptr);
+
+        // Verify macs in cache in LRU order, where test mac (i.e., b) is the most recent
+        const auto&& lru_data = host_cache_mac.get_all_data();
+        CHECK(lru_data.size() == 3);
+        CHECK(lru_data[2].first == a);
+        CHECK(lru_data[1].first == c);
+        CHECK(lru_data[0].first == b);
     }
 
     SECTION("HostCacheMac: MAC Hashing")
     {
         uint8_t a_mac[6] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6};
-        uint64_t hash = snort::hash_mac(a_mac);
-        assert(hash == 0xA1A2A3A4A5A6);
+        uint64_t hash = hash_mac(a_mac);
+        CHECK(hash == 0xA1A2A3A4A5A6);
     }
 }
 #endif
index f916ea5e577e943205b9e5a03700fd87276f9233..9988d98e15e36ffc698a3117ca814ed9850ef4e6 100644 (file)
 // Non-standard, required to include template definition across compiler translation units
 #include "host_tracker/host_cache_allocator.cc"
 #include "host_tracker/host_cache_allocator.h"
-#include "host_tracker/host_cache.h"
-#include "host_tracker/host_tracker.h"
-#include "sfip/sf_ip.h"
-
-using snort::SfIp;
 
 #define MAC_CACHE_INITIAL_SIZE 1024 * 1024 // Default to 1 MB
 
-class HostMacIp : public snort::HostMac
+template <class T>
+class HostCacheAllocMac : public HostCacheAlloc<T>
 {
 public:
-    HostMacIp (const uint8_t* p_mac, uint8_t p_primary, uint32_t p_last_seen)
-        : snort::HostMac(0, p_mac, p_primary, p_last_seen), src_ip(nullptr), dst_ip(nullptr)
-    { }
+    template <class U>
+    struct rebind
+    {
+        typedef HostCacheAllocMac<U> other;
+    };
 
-    HostMacIp (const uint8_t* p_mac, uint8_t p_primary, uint32_t p_last_seen,
-        SfIp* src, SfIp* dst) : snort::HostMac(0, p_mac, p_primary, p_last_seen),
-        src_ip(src), dst_ip(dst)
-    { }
+    using HostCacheAlloc<T>::lru;
 
-    SfIp* src_ip;
-    SfIp* dst_ip;
+    HostCacheAllocMac();
+};
 
-    snort::HostType host_type;
+class HostTrackerMac
+{
+public:
+    HostTrackerMac()
+    { last_seen = (uint32_t) snort::packet_time(); }
 
+    bool add_network_proto(const uint16_t type);
+    void update_last_seen(uint32_t p_last_seen);
     void update_vlan(uint16_t vth_pri_cfi_vlan, uint16_t vth_proto);
     bool has_vlan();
     uint16_t get_vlan();
     void get_vlan_details(uint8_t& cfi, uint8_t& priority, uint16_t& vid);
 
+    // This should be updated whenever HostTrackerMac data members are changed
+    void stringify(std::string& str);
+
+    snort::HostType host_type = snort::HostType::HOST_TYPE_HOST;
+
 private:
+    std::mutex host_tracker_mac_lock;
+    uint32_t last_seen;
     bool vlan_tag_present = false;
     snort::vlan::VlanTagHdr vlan_tag;
+    std::vector<uint16_t, HostCacheAllocMac<uint16_t>> network_protos;
 };
 
 class MacKey
@@ -80,36 +89,7 @@ struct HashMac
     { return snort::hash_mac(mk.mac_addr); }
 };
 
-template <class T>
-class HostCacheAllocMac : public HostCacheAlloc<T>
-{
-public:
-    template <class U>
-    struct rebind
-    {
-        typedef HostCacheAllocMac<U> other;
-    };
-
-    using HostCacheAlloc<T>::lru;
-
-    HostCacheAllocMac();
-};
-
-class LruMac
-{
-public:
-    typedef HostMacIp ValueType;
-    std::vector<ValueType, HostCacheAllocMac<ValueType>> data;
-
-    bool isempty()
-    { return data.size() == 0; }
-
-    void insert(HostMacIp *hmi)
-    { data.emplace_back(*hmi); }
-
-};
-
-typedef LruCacheSharedMemcap<MacKey, LruMac, HashMac> HostCacheMac;
+typedef LruCacheSharedMemcap<MacKey, HostTrackerMac, HashMac> HostCacheMac;
 extern HostCacheMac host_cache_mac;
 
 template <class T>
index 462ca62ac942c6547c013ecfcbd7761e4cd1690b..a33e7a1733c5aff3ed6099f1c359c24cebb45366 100644 (file)
@@ -46,6 +46,7 @@
 #endif
 
 using namespace snort;
+using namespace std;
 
 //-------------------------------------------------------------------------
 // rna commands, params, and pegs
@@ -89,14 +90,14 @@ static int reload_fingerprint(lua_State*)
     return 0;
 }
 
-std::string format_dump_mac(uint8_t mac[MAC_SIZE])
+static inline string format_dump_mac(const uint8_t mac[MAC_SIZE])
 {
-    std::stringstream ss;
-    ss << std::hex;
+    stringstream ss;
+    ss << hex;
 
     for(int i=0; i < MAC_SIZE; i++)
     {
-        ss << std::setfill('0') << std::setw(2) << static_cast<int>(mac[i]);
+        ss << setfill('0') << setw(2) << static_cast<int>(mac[i]);
         if (i != MAC_SIZE - 1)
             ss << ":";
     }
@@ -179,9 +180,9 @@ bool RnaModule::begin(const char* fqn, int, SnortConfig*)
 bool RnaModule::set(const char*, Value& v, SnortConfig*)
 {
     if (v.is("rna_conf_path"))
-        mod_conf->rna_conf_path = std::string(v.get_string());
+        mod_conf->rna_conf_path = string(v.get_string());
     else if (v.is("fingerprint_dir"))
-        mod_conf->fingerprint_dir = std::string(v.get_string());
+        mod_conf->fingerprint_dir = string(v.get_string());
     else if (v.is("enable_logger"))
         mod_conf->enable_logger = v.get_bool();
     else if (v.is("log_when_idle"))
@@ -250,27 +251,23 @@ bool RnaModule::log_mac_cache(const char* outfile)
         return 0;
     }
 
-    std::ofstream out_stream(outfile);
+    ofstream out_stream(outfile);
     if ( !out_stream )
     {
         snort::LogMessage("Error opening %s for dumping MAC cache", outfile);
     }
 
-    std::string str;
+    string str;
     const auto&& lru_data = host_cache_mac.get_all_data();
     out_stream << "Current mac cache size: " << host_cache_mac.mem_size() << " bytes, "
-        << lru_data.size() << " trackers" << std::endl << std::endl;
+        << lru_data.size() << " trackers" << endl << endl;
     for ( const auto& elem : lru_data )
     {
         str = "MAC: ";
-
-        if (elem.second->data.size() > 0)
-            str += format_dump_mac(elem.second->data.front().mac);
-        else
-            str += "No MacHostTracker found for entry ";
-
-        str += "\n Key: " +  std::to_string(hash_mac(elem.second->data.front().mac));
-        out_stream << str << std::endl << std::endl;
+        str += format_dump_mac(elem.first.mac_addr);
+        str += "\n Key: " +  to_string(hash_mac(elem.first.mac_addr));
+        elem.second->stringify(str);
+        out_stream << str << endl << endl;
     }
     out_stream.close();
 
index ece385d07e67d0914148a9bc21df0b7feb4872c1..f25c50affd30ea72f4d3b0228c620870c58bcfcf 100644 (file)
@@ -29,8 +29,6 @@
 #define RNA_NAME "rna"
 #define RNA_HELP "Real-time network awareness and OS fingerprinting (experimental)"
 
-std::string format_dump_mac(uint8_t mac[6]);
-
 struct RnaStats
 {
     PegCount icmp_bidirectional;
index fe217a47cc1bf78a298ddbc1dc91d2e959c2c50e..946c2cef8cf1712042a5efa83923d8e4b5f9a37b 100644 (file)
@@ -42,7 +42,8 @@
 #endif
 
 using namespace snort;
-using namespace bpdu;
+using namespace snort::bpdu;
+using namespace std;
 
 static inline bool is_eligible_packet(const Packet* p)
 {
@@ -154,6 +155,8 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
     bool new_host = false;
     bool new_mac = false;
     const auto& src_ip = p->ptrs.ip_api.get_src();
+    const auto& src_ip_ptr = (const struct in6_addr*) src_ip->get_ip6_ptr();
+
     auto ht = host_cache.find_else_create(*src_ip, &new_host);
 
     if ( !new_host )
@@ -164,38 +167,45 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
     new_mac = 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);
-    }
+        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, src_ip_ptr, src_mac);
 
     if ( new_mac and !new_host )
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_ADD, p, &ht,
-            (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac,
-            0, nullptr, ht->get_hostmac(src_mac));
+            src_ip_ptr, src_mac, 0, nullptr, ht->get_hostmac(src_mac));
 
     if ( ht->update_mac_ttl(src_mac, ttl) )
     {
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_INFO, p, &ht,
-            (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac,
-            0, nullptr, ht->get_hostmac(src_mac));
+            src_ip_ptr, src_mac, 0, nullptr, ht->get_hostmac(src_mac));
 
         HostMac* hm = ht->get_max_ttl_hostmac();
         if (hm and hm->primary and ht->get_hops())
         {
             ht->update_hops(0);
-            logger.log(RNA_EVENT_CHANGE, CHANGE_HOPS, p, &ht,
-                (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac);
+            logger.log(RNA_EVENT_CHANGE, CHANGE_HOPS, p, &ht, src_ip_ptr, src_mac);
         }
     }
 
+    uint16_t ptype = rna_get_eth(p);
+    if ( ptype > to_utype(ProtocolId::ETHERTYPE_MINIMUM) )
+    {
+        if ( ht->add_network_proto(ptype) )
+            logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, src_ip_ptr, src_mac,
+                0, nullptr, nullptr, ptype);
+    }
+
+    ptype = to_utype(p->get_ip_proto_next());
+    if ( ht->add_xport_proto(ptype) )
+        logger.log(RNA_EVENT_NEW, NEW_XPORT_PROTOCOL, p, &ht, src_ip_ptr, src_mac,
+            0, nullptr, nullptr, ptype);
+
     if ( !new_host )
     {
         generate_change_host_update(&ht, p, src_ip, src_mac, packet_time());
     }
 }
 
-inline void RnaPnd::update_vlan(const Packet* p, HostMacIp& hm)
+inline void RnaPnd::update_vlan(const Packet* p, HostTrackerMac& hm)
 {
     if (!(p->proto_bits & PROTO_BIT__VLAN))
         return;
@@ -207,7 +217,7 @@ inline void RnaPnd::update_vlan(const Packet* p, HostMacIp& hm)
 }
 
 void RnaPnd::generate_change_vlan_update(RnaTracker *rt, const Packet* p,
-    const uint8_t* src_mac, HostMacIp& hm, bool isnew)
+    const uint8_t* src_mac, HostTrackerMac& hm, bool isnew)
 {
     if (!(p->proto_bits & PROTO_BIT__VLAN))
         return;
@@ -219,14 +229,12 @@ void RnaPnd::generate_change_vlan_update(RnaTracker *rt, const Packet* p,
 
     if (isnew or !hm.has_vlan() or hm.get_vlan() != vh->vth_pri_cfi_vlan)
     {
-        time_t timestamp = packet_time() - update_timeout;
-
         if (!isnew)
             update_vlan(p, hm);
 
         rt->get()->update_vlan(vh->vth_pri_cfi_vlan, vh->vth_proto);
         logger.log(RNA_EVENT_CHANGE, CHANGE_VLAN_TAG, p, rt, nullptr,
-            src_mac, rt->get()->get_last_seen(), (void*) &timestamp);
+            src_mac, rt->get()->get_last_seen());
     }
 }
 
@@ -243,12 +251,10 @@ void RnaPnd::generate_change_vlan_update(RnaTracker *rt, const Packet* p,
 
     if (isnew or !rt->get()->has_vlan() or rt->get()->get_vlan() != vh->vth_pri_cfi_vlan)
     {
-        time_t timestamp = packet_time() - update_timeout;
-
         rt->get()->update_vlan(vh->vth_pri_cfi_vlan, vh->vth_proto);
         logger.log(RNA_EVENT_CHANGE, CHANGE_VLAN_TAG, p, rt,
             (const struct in6_addr*) src_ip->get_ip6_ptr(),
-            src_mac, rt->get()->get_last_seen(), (void*) &timestamp);
+            src_mac, rt->get()->get_last_seen());
     }
 }
 
@@ -278,7 +284,7 @@ void RnaPnd::generate_change_host_update()
         generate_change_host_update(&h.second, nullptr, &h.first, nullptr, sec);
 }
 
-void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht)
+void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht, bool discover_proto)
 {
     // In general, this is the default case for mac eventing.
     // Ex. if BPDU dsap, ssap checks fail, we fallback here to
@@ -291,24 +297,40 @@ void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht)
 
     if (new_host_mac)
     {
-        HostMacIp hm(mk.mac_addr, 0, p->pkth->ts.tv_sec);
-
-        update_vlan(p, hm);
-        hm_ptr->insert(&hm);
+        update_vlan(p, *hm_ptr);
 
         ht.get()->update_last_seen();
         ht.get()->add_mac(mk.mac_addr, 0, 0);
 
-        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht,
-            (const struct in6_addr*) nullptr, mk.mac_addr);
+        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, nullptr, mk.mac_addr);
 
-        generate_change_vlan_update(&ht, p, mk.mac_addr, hm, true);
+        generate_change_vlan_update(&ht, p, mk.mac_addr, *hm_ptr, true);
     }
     else
     {
-        if (hm_ptr and !hm_ptr->isempty())
+        hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
+        generate_change_vlan_update(&ht, p, mk.mac_addr, *hm_ptr, false);
+    }
+
+    if (discover_proto)
+    {
+        uint16_t ntype = rna_get_eth(p);
+        if ( ntype > to_utype(ProtocolId::ETHERTYPE_MINIMUM) )
+        {
+            if ( hm_ptr->add_network_proto(ntype) )
+                logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, nullptr, mk.mac_addr,
+                    0, nullptr, nullptr, ntype);
+        }
+        else if ( ntype != to_utype(ProtocolId::ETHERTYPE_NOT_SET) )
         {
-            generate_change_vlan_update(&ht, p, mk.mac_addr, hm_ptr->data.front(), false);
+            const Layer& lyr = p->layers[p->num_layers-1];
+            if ( lyr.prot_id == ProtocolId::ETHERNET_LLC )
+            {
+                ntype = ((const RNA_LLC*) lyr.start)->s.proto;
+                if ( hm_ptr->add_network_proto(ntype) )
+                    logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, nullptr, mk.mac_addr,
+                        0, nullptr, nullptr, ntype);
+            }
         }
     }
 }
@@ -319,64 +341,59 @@ void RnaPnd::discover_network_ethernet(const Packet* p)
     #define BPDU_ID 0x42
     #define SNAP_ID 0xAA
     int retval = 1;
-    HostTracker* ht = new HostTracker();
-    RnaTracker rt = std::shared_ptr<snort::HostTracker>(ht);
+    RnaTracker rt = shared_ptr<snort::HostTracker>(new HostTracker());
 
     if (!p->is_eth())
         return;
 
     if (layer::get_arp_layer(p))
-    {
         retval = discover_network_arp(p, &rt);
-    }
-
-    // If we have an inner LLC layer, grab it
-    Layer lyr = p->layers[p->num_layers-1];
-    if (p->layers[p->num_layers-1].prot_id == ProtocolId::ETHERNET_LLC)
+    else
     {
-        uint16_t etherType = rna_get_eth(p);
-
-        if (!etherType || etherType > static_cast<uint16_t>(ProtocolId::ETHERTYPE_MINIMUM))
+        // If we have an inner LLC layer, grab it
+        const Layer& lyr = p->layers[p->num_layers-1];
+        if (lyr.prot_id == ProtocolId::ETHERNET_LLC)
         {
-            generate_new_host_mac(p, rt);
-            return;
-        }
+            uint16_t etherType = rna_get_eth(p);
 
-        const RNA_LLC* llc = (const RNA_LLC*) lyr.start;
+            if (!etherType || etherType > static_cast<uint16_t>(ProtocolId::ETHERTYPE_MINIMUM))
+            {
+                generate_new_host_mac(p, rt);
+                return;
+            }
 
-        if (llc->s.s.DSAP != llc->s.s.SSAP)
-        {
-            generate_new_host_mac(p, rt);
-            return;
-        }
+            const RNA_LLC* llc = (const RNA_LLC*) lyr.start;
 
-        switch (llc->s.s.DSAP)
-        {
-            case BPDU_ID:
+            if (llc->s.s.DSAP != llc->s.s.SSAP)
             {
-                retval = discover_network_bpdu(p, ((const uint8_t*)llc + sizeof(RNA_LLC)), rt);
-                break;
+                generate_new_host_mac(p, rt);
+                return;
             }
 
-            default:
-                break;
+            switch (llc->s.s.DSAP)
+            {
+                case BPDU_ID:
+                {
+                    retval = discover_network_bpdu(p, ((const uint8_t*)llc + sizeof(RNA_LLC)), rt);
+                    break;
+                }
+
+                default:
+                    break;
+            }
         }
     }
 
     if (retval)
-        generate_new_host_mac(p, rt);
+        generate_new_host_mac(p, rt, true);
 
     return;
 }
 
 int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
 {
-    bool new_host_mac = false;
-    bool new_host = false;
-
     MacKey mk(layer::get_eth_layer(p)->ether_src);
     const auto& src_mac = mk.mac_addr;
-    HostMacIp hm(mk.mac_addr, 0, p->pkth->ts.tv_sec);
 
     const snort::arp::EtherARP *ah = layer::get_arp_layer(p);
 
@@ -399,12 +416,13 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
     if ( !(filter.is_host_monitored(p, nullptr, &spa) ))
         return 1;
 
+    bool new_host = false;
+    bool new_host_mac = false;
     auto ht = host_cache.find_else_create(spa, &new_host);
+    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
 
-    std::shared_ptr<LruMac> hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
-
-    if (new_host_mac)
-        hm_ptr->insert(&hm);
+    if (!new_host_mac)
+        hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
 
     *ht_ref = ht;
 
@@ -431,6 +449,11 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
 
     generate_change_vlan_update(&ht, p, src_mac, &spa, true);
 
+    auto ntype = to_utype(ProtocolId::ETHERTYPE_ARP);
+    if ( hm_ptr->add_network_proto(ntype) )
+        logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, nullptr, src_mac,
+            0, nullptr, nullptr, ntype);
+
     if ( ht->get_hops() )
     {
         ht->update_hops(0);
@@ -462,19 +485,15 @@ int RnaPnd::discover_network_bpdu(const Packet* p, const uint8_t* data,
 
 int RnaPnd::discover_switch(const Packet* p, RnaTracker ht_ref)
 {
-    bool new_host = false;
+    bool new_host_mac = false;
     MacKey mk(layer::get_eth_layer(p)->ether_src);
 
-    std::shared_ptr<LruMac> hm_ptr = host_cache_mac.find_else_create(mk, &new_host);
+    auto hm_ptr = host_cache_mac.find_else_create(mk, &new_host_mac);
 
-    if (new_host)
+    if (new_host_mac)
     {
-        HostMacIp hm(mk.mac_addr, 0, p->pkth->ts.tv_sec);
-
-        hm.host_type = HOST_TYPE_BRIDGE;
-
-        update_vlan(p, hm);
-        hm_ptr->insert(&hm);
+        hm_ptr->host_type = HOST_TYPE_BRIDGE;
+        update_vlan(p, *hm_ptr);
 
         ht_ref.get()->update_last_seen();
         ht_ref.get()->add_mac(mk.mac_addr, 0, 1);
@@ -482,11 +501,12 @@ int RnaPnd::discover_switch(const Packet* p, RnaTracker ht_ref)
         logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht_ref,
             (const struct in6_addr*) nullptr, mk.mac_addr);
 
-        generate_change_vlan_update(&ht_ref, p, mk.mac_addr, hm, true);
+        generate_change_vlan_update(&ht_ref, p, mk.mac_addr, *hm_ptr, true);
     }
     else
     {
-        generate_change_vlan_update(&ht_ref, p, mk.mac_addr, hm_ptr->data.front(), false);
+        hm_ptr->update_last_seen(p->pkth->ts.tv_sec);
+        generate_change_vlan_update(&ht_ref, p, mk.mac_addr, *hm_ptr, false);
     }
 
     return 0;
index 47833ad4363d45f76e93aadb51648ccc1019d200..cf86b6b37a5b60f32e8b296a75753708e1b389e6 100644 (file)
@@ -29,8 +29,8 @@
 #include "protocols/vlan.h"
 #include "sfip/sf_ip.h"
 
-#include "rna_mac_cache.h"
 #include "rna_logger.h"
+#include "rna_mac_cache.h"
 
 #define USHRT_MAX std::numeric_limits<unsigned short>::max()
 
@@ -88,23 +88,23 @@ public:
     void analyze_flow_tcp(const snort::Packet* p, TcpPacketType type);
     void analyze_flow_udp(const snort::Packet* p);
 
+    // generate change event for all hosts in the ip cache
+    void generate_change_host_update();
+
+private:
     // 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();
-
     // Change vlan event related utilities
-    inline void update_vlan(const snort::Packet* p, HostMacIp& hm);
+    inline void update_vlan(const snort::Packet* p, HostTrackerMac& hm);
     void generate_change_vlan_update(RnaTracker *rt, const snort::Packet* p,
-        const uint8_t* src_mac, HostMacIp& hm, bool isnew);
+        const uint8_t* src_mac, HostTrackerMac& hm, bool isnew);
     void generate_change_vlan_update(RnaTracker *rt, const snort::Packet* p,
-        const uint8_t* src_mac, const SfIp* src_ip, bool isnew);
+        const uint8_t* src_mac, const snort::SfIp* src_ip, bool isnew);
 
-    void generate_new_host_mac(const snort::Packet* p, RnaTracker ht);
+    void generate_new_host_mac(const snort::Packet* p, RnaTracker ht, bool discover_proto = false);
 
-private:
     // General rna utilities not associated with flow
     void discover_network_icmp(const snort::Packet* p);
     void discover_network_ip(const snort::Packet* p);
index d7baad34e29331915ffc089d63e7293976e75774..3043dc255607604696a7cd0df553c4cdd5582f53 100644 (file)
@@ -61,6 +61,7 @@ void LogMessage(const char*,...) {}
 void WarningMessage(const char*,...) {}
 SnortConfig::SnortConfig(SnortConfig const*) {}
 SnortConfig::~SnortConfig() {}
+time_t packet_time() { return 0; }
 } // end of namespace snort
 
 #endif