From: Masud Hasan (mashasan) Date: Tue, 11 Aug 2020 17:53:22 +0000 (+0000) Subject: Merge pull request #2389 in SNORT/snort3 from ~MASHASAN/snort3:rna_proto to master X-Git-Tag: 3.0.2-5~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3722d4bd85a7777dce74350cdf834cf31f8c2cc;p=thirdparty%2Fsnort3.git Merge pull request #2389 in SNORT/snort3 from ~MASHASAN/snort3:rna_proto to master Squashed commit of the following: commit e0f9fad3d3ba658ee4af9e1eae02cfc4f791f97a Author: Masud Hasan Date: Fri Aug 7 19:19:03 2020 -0400 rna: Discover network and transport protocols --- diff --git a/src/host_tracker/host_tracker.cc b/src/host_tracker/host_tracker.cc index 0e1f35427..fce17fc83 100644 --- a/src/host_tracker/host_tracker.cc +++ b/src/host_tracker/host_tracker.cc @@ -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 lck(host_tracker_lock); + lock_guard lck(host_tracker_lock); last_seen = (uint32_t) packet_time(); } void HostTracker::update_last_event(uint32_t time) { - std::lock_guard lck(host_tracker_lock); + lock_guard lck(host_tracker_lock); last_event = time ? time : last_seen; } +bool HostTracker::add_network_proto(const uint16_t type) +{ + lock_guard 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 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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*& p_macs) { - std::lock_guard lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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 lck(host_tracker_lock); + lock_guard 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? ", " : ""); + } } diff --git a/src/host_tracker/host_tracker.h b/src/host_tracker/host_tracker.h index 9f42611b6..8947833cb 100644 --- a/src/host_tracker/host_tracker.h +++ b/src/host_tracker/host_tracker.h @@ -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*& 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 macs; + std::vector macs; + std::vector> network_protos; + std::vector> xport_protos; std::vector services; bool vlan_tag_present = false; vlan::VlanTagHdr vlan_tag; diff --git a/src/network_inspectors/rna/dev_notes.txt b/src/network_inspectors/rna/dev_notes.txt index d90c9aaa5..9530ac493 100644 --- a/src/network_inspectors/rna/dev_notes.txt +++ b/src/network_inspectors/rna/dev_notes.txt @@ -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) + HostCacheMac (LruCacheSharedMemcap) |- - - - Key = uint8_t[6] (mac address) - |- - - - Data = LruMac - | | - - - - Valuetype = HostMacIp (derived from snort::HostMac) - | | - - - - Data = std::vector> + |- - - - Value = HostTrackerMac + | | - - - - Dynamic memory growth is tracked by HostCacheAllocMac allocator | |- - - - Hash = HashMac | | diff --git a/src/network_inspectors/rna/rna_logger.cc b/src/network_inspectors/rna/rna_logger.cc index 01e3b5686..8c5e6272e 100644 --- a/src/network_inspectors/rna/rna_logger.cc +++ b/src/network_inspectors/rna/rna_logger.cc @@ -25,6 +25,8 @@ #include "rna_logger.h" +#include + #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(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 diff --git a/src/network_inspectors/rna/rna_logger.h b/src/network_inspectors/rna/rna_logger.h index 7bfc487c3..c9d87da4f 100644 --- a/src/network_inspectors/rna/rna_logger.h +++ b/src/network_inspectors/rna/rna_logger.h @@ -35,7 +35,8 @@ using RnaTracker = std::shared_ptr; 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; diff --git a/src/network_inspectors/rna/rna_logger_common.h b/src/network_inspectors/rna/rna_logger_common.h index ec06c93f4..69d3ec11f 100644 --- a/src/network_inspectors/rna/rna_logger_common.h +++ b/src/network_inspectors/rna/rna_logger_common.h @@ -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 diff --git a/src/network_inspectors/rna/rna_mac_cache.cc b/src/network_inspectors/rna/rna_mac_cache.cc index db7cdd1ca..06fe2dee3 100644 --- a/src/network_inspectors/rna/rna_mac_cache.cc +++ b/src/network_inspectors/rna/rna_mac_cache.cc @@ -23,39 +23,76 @@ #endif #include "rna_mac_cache.h" -#include -#include - #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 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 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 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 lck(host_tracker_mac_lock); return vlan_tag_present; } -uint16_t HostMacIp::get_vlan() +uint16_t HostTrackerMac::get_vlan() { + lock_guard 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 lck(host_tracker_mac_lock); + cfi = vlan_tag.cfi(); priority = vlan_tag.priority(); vid = vlan_tag.vid(); } +void HostTrackerMac::stringify(string& str) +{ + lock_guard 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 diff --git a/src/network_inspectors/rna/rna_mac_cache.h b/src/network_inspectors/rna/rna_mac_cache.h index f916ea5e5..9988d98e1 100644 --- a/src/network_inspectors/rna/rna_mac_cache.h +++ b/src/network_inspectors/rna/rna_mac_cache.h @@ -25,39 +25,48 @@ // 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 HostCacheAllocMac : public HostCacheAlloc { 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 + struct rebind + { + typedef HostCacheAllocMac 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::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> network_protos; }; class MacKey @@ -80,36 +89,7 @@ struct HashMac { return snort::hash_mac(mk.mac_addr); } }; -template -class HostCacheAllocMac : public HostCacheAlloc -{ -public: - template - struct rebind - { - typedef HostCacheAllocMac other; - }; - - using HostCacheAlloc::lru; - - HostCacheAllocMac(); -}; - -class LruMac -{ -public: - typedef HostMacIp ValueType; - std::vector> data; - - bool isempty() - { return data.size() == 0; } - - void insert(HostMacIp *hmi) - { data.emplace_back(*hmi); } - -}; - -typedef LruCacheSharedMemcap HostCacheMac; +typedef LruCacheSharedMemcap HostCacheMac; extern HostCacheMac host_cache_mac; template diff --git a/src/network_inspectors/rna/rna_module.cc b/src/network_inspectors/rna/rna_module.cc index 462ca62ac..a33e7a173 100644 --- a/src/network_inspectors/rna/rna_module.cc +++ b/src/network_inspectors/rna/rna_module.cc @@ -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(mac[i]); + ss << setfill('0') << setw(2) << static_cast(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(); diff --git a/src/network_inspectors/rna/rna_module.h b/src/network_inspectors/rna/rna_module.h index ece385d07..f25c50aff 100644 --- a/src/network_inspectors/rna/rna_module.h +++ b/src/network_inspectors/rna/rna_module.h @@ -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; diff --git a/src/network_inspectors/rna/rna_pnd.cc b/src/network_inspectors/rna/rna_pnd.cc index fe217a47c..946c2cef8 100644 --- a/src/network_inspectors/rna/rna_pnd.cc +++ b/src/network_inspectors/rna/rna_pnd.cc @@ -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*) ×tamp); + 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*) ×tamp); + 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(ht); + RnaTracker rt = shared_ptr(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(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(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 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 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; diff --git a/src/network_inspectors/rna/rna_pnd.h b/src/network_inspectors/rna/rna_pnd.h index 47833ad43..cf86b6b37 100644 --- a/src/network_inspectors/rna/rna_pnd.h +++ b/src/network_inspectors/rna/rna_pnd.h @@ -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::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); diff --git a/src/network_inspectors/rna/test/rna_module_mock.h b/src/network_inspectors/rna/test/rna_module_mock.h index d7baad34e..3043dc255 100644 --- a/src/network_inspectors/rna/test/rna_module_mock.h +++ b/src/network_inspectors/rna/test/rna_module_mock.h @@ -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