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;
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) )
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) )
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) )
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;
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;
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 )
{
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 )
{
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)
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);
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? ", " : "");
+ }
}
// 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,
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;
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
| |
#include "rna_logger.h"
+#include <cassert>
+
#include "managers/event_manager.h"
#include "protocols/packet.h"
#include "rna_logger_common.h"
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;
{
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
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;
const struct in6_addr* ip = nullptr;
void* cond_var = nullptr;
const snort::HostMac* hm;
+ const uint16_t proto;
};
class RnaLogger
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;
// 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
#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]")
{
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
// 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
{ 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>
#endif
using namespace snort;
+using namespace std;
//-------------------------------------------------------------------------
// rna commands, params, and pegs
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 << ":";
}
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"))
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();
#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;
#endif
using namespace snort;
-using namespace bpdu;
+using namespace snort::bpdu;
+using namespace std;
static inline bool is_eligible_packet(const Packet* p)
{
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 )
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;
}
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;
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());
}
}
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());
}
}
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
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);
+ }
}
}
}
#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);
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;
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);
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);
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;
#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()
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);
void WarningMessage(const char*,...) {}
SnortConfig::SnortConfig(SnortConfig const*) {}
SnortConfig::~SnortConfig() {}
+time_t packet_time() { return 0; }
} // end of namespace snort
#endif