]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2420 in SNORT/snort3 from ~MASHASAN/snort3:rna_app_service to...
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Fri, 28 Aug 2020 01:20:50 +0000 (01:20 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Fri, 28 Aug 2020 01:20:50 +0000 (01:20 +0000)
Squashed commit of the following:

commit ad66c9f37f7beb0a3cbf0a18834a1b8994dd7d54
Author: Masud Hasan <mashasan@cisco.com>
Date:   Fri Aug 14 21:45:23 2020 -0400

    rna: Support service discovery from appid event changes

commit 9aa8d405eda1fe08496ea613d3049c5eb75da235
Author: Shravan Rangaraju <shrarang@cisco.com>
Date:   Fri Aug 14 06:22:01 2020 -0400

    appid: Generate events for service info changes

35 files changed:
src/host_tracker/host_tracker.cc
src/host_tracker/host_tracker.h
src/host_tracker/test/host_cache_allocator_test.cc
src/main/test/distill_verdict_test.cc
src/network_inspectors/appid/appid_app_descriptor.h
src/network_inspectors/appid/appid_http_session.cc
src/network_inspectors/appid/appid_session.cc
src/network_inspectors/appid/appid_session.h
src/network_inspectors/appid/appid_session_api.cc
src/network_inspectors/appid/appid_session_api.h
src/network_inspectors/appid/appid_types.h
src/network_inspectors/appid/detector_plugins/detector_pop3.cc
src/network_inspectors/appid/detector_plugins/http_url_patterns.cc
src/network_inspectors/appid/detector_plugins/http_url_patterns.h
src/network_inspectors/appid/service_plugins/service_detector.cc
src/network_inspectors/appid/service_plugins/service_detector.h
src/network_inspectors/appid/service_plugins/service_rpc.cc
src/network_inspectors/appid/test/appid_api_test.cc
src/network_inspectors/appid/test/appid_discovery_test.cc
src/network_inspectors/appid/test/appid_mock_session.h
src/network_inspectors/rna/CMakeLists.txt
src/network_inspectors/rna/rna_app_discovery.cc [new file with mode: 0644]
src/network_inspectors/rna/rna_app_discovery.h [new file with mode: 0644]
src/network_inspectors/rna/rna_event_handler.cc
src/network_inspectors/rna/rna_event_handler.h
src/network_inspectors/rna/rna_inspector.cc
src/network_inspectors/rna/rna_logger.cc
src/network_inspectors/rna/rna_logger.h
src/network_inspectors/rna/rna_logger_common.h
src/network_inspectors/rna/rna_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/pub_sub/appid_events.h

index 8f9463cbc26ac2174c824efc9a9c819e1a248f9d..aa7ab58cf53cedc414467086f64d2f0b14450451 100644 (file)
@@ -23,7 +23,6 @@
 #endif
 
 #include "host_tracker.h"
-#include "host_cache_allocator.cc"
 
 #include "utils/util.h"
 
@@ -99,6 +98,21 @@ const HostMac* HostTracker::get_hostmac(const uint8_t* mac)
     return nullptr;
 }
 
+const uint8_t* HostTracker::get_last_seen_mac()
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+    const HostMac* max_hm = nullptr;
+
+    for ( const auto& hm : macs )
+        if ( !max_hm or max_hm->last_seen < hm.last_seen)
+            max_hm = &hm;
+
+    if ( max_hm )
+        return max_hm->mac;
+
+    return zero_mac;
+}
+
 bool HostTracker::update_mac_ttl(const uint8_t* mac, uint8_t new_ttl)
 {
     if ( !mac or !memcmp(mac, zero_mac, MAC_SIZE) )
@@ -205,7 +219,8 @@ void HostTracker::copy_data(uint8_t& p_hops, uint32_t& p_last_seen, list<HostMac
         p_macs = new list<HostMac>(macs.begin(), macs.end());
 }
 
-bool HostTracker::add_service(Port port, IpProtocol proto, AppId appid, bool inferred_appid, bool* added)
+bool HostTracker::add_service(Port port, IpProtocol proto, AppId appid, bool inferred_appid,
+    bool* added)
 {
     host_tracker_stats.service_adds++;
     lock_guard<mutex> lck(host_tracker_lock);
@@ -225,21 +240,23 @@ bool HostTracker::add_service(Port port, IpProtocol proto, AppId appid, bool inf
         }
     }
 
-    services.emplace_back( HostApplication{port, proto, appid, inferred_appid} );
+    services.emplace_back(port, proto, appid, inferred_appid);
     if (added)
         *added = true;
 
     return true;
 }
 
-AppId HostTracker::get_appid(Port port, IpProtocol proto, bool inferred_only, bool allow_port_wildcard)
+AppId HostTracker::get_appid(Port port, IpProtocol proto, bool inferred_only,
+    bool allow_port_wildcard)
 {
     host_tracker_stats.service_finds++;
     lock_guard<mutex> lck(host_tracker_lock);
 
     for ( const auto& s : services )
     {
-        bool matched = (s.port == port and s.proto == proto and (!inferred_only or s.inferred_appid == inferred_only));
+        bool matched = (s.port == port and s.proto == proto and
+            (!inferred_only or s.inferred_appid == inferred_only));
         if ( matched or ( allow_port_wildcard and s.inferred_appid ) )
             return s.appid;
     }
@@ -247,6 +264,92 @@ AppId HostTracker::get_appid(Port port, IpProtocol proto, bool inferred_only, bo
     return APP_ID_NONE;
 }
 
+size_t HostTracker::get_service_count()
+{
+    lock_guard<mutex> lck(host_tracker_lock);
+    return services.size();
+}
+
+HostApplication HostTracker::get_service(Port port, IpProtocol proto, uint32_t lseen,
+    bool& is_new, AppId appid)
+{
+    host_tracker_stats.service_finds++;
+    lock_guard<mutex> lck(host_tracker_lock);
+
+    for ( auto& s : services )
+    {
+        if ( s.port == port and s.proto == proto )
+        {
+            if ( s.appid != appid and appid != APP_ID_NONE )
+            {
+                s.appid = appid;
+                is_new = true;
+            }
+            else if ( s.last_seen == 0 )
+                is_new = true;
+            s.last_seen = lseen;
+            ++s.hits;
+            return s;
+        }
+    }
+
+    is_new = true;
+    host_tracker_stats.service_adds++;
+    services.emplace_back(port, proto, appid, false, 1, lseen);
+    return services.back();
+}
+
+void HostTracker::update_service(const HostApplication& ha)
+{
+    host_tracker_stats.service_finds++;
+    lock_guard<mutex> lck(host_tracker_lock);
+
+    for ( auto& s : services )
+    {
+        if ( s.port == ha.port and s.proto == ha.proto )
+        {
+            s.hits = ha.hits;
+            s.last_seen = ha.last_seen;
+            if ( ha.appid > APP_ID_NONE )
+                s.appid = ha.appid;
+            return;
+        }
+    }
+}
+
+bool HostTracker::update_service_info(HostApplication& ha, const char* vendor, const char* version)
+{
+    host_tracker_stats.service_finds++;
+    lock_guard<mutex> lck(host_tracker_lock);
+
+    for ( auto& s : services )
+    {
+        if ( s.port == ha.port and s.proto == ha.proto )
+        {
+            bool changed = false;
+            if ( vendor and strncmp(s.vendor, vendor, INFO_SIZE) )
+            {
+                strncpy(s.vendor, vendor, INFO_SIZE);
+                s.vendor[INFO_SIZE-1] = '\0';
+                changed = true;
+            }
+            if ( version and strncmp(s.version, version, INFO_SIZE) )
+            {
+                strncpy(s.version, version, INFO_SIZE);
+                s.version[INFO_SIZE-1] = '\0';
+                changed = true;
+            }
+            if ( !changed )
+                return false;
+
+            ha.appid = s.appid; // copy these info for the caller
+            ha.hits = s.hits;
+            return true;
+        }
+    }
+    return false;
+}
+
 void HostTracker::remove_inferred_services()
 {
     lock_guard<mutex> lck(host_tracker_lock);
@@ -314,6 +417,10 @@ void HostTracker::stringify(string& str)
                 if ( s.inferred_appid )
                     str += ", inferred";
             }
+            if ( s.vendor[0] != '\0' )
+                str += ", vendor: " + string(s.vendor);
+            if ( s.version[0] != '\0' )
+                str += ", version: " + string(s.version);
         }
     }
 
index bc45d0a0e06a8c75325f2c0f7a9c66b98ffbcb26..b5a1a79d7bf9ac2f944582a401abe1f377f538fb 100644 (file)
@@ -50,6 +50,7 @@ extern THREAD_LOCAL struct HostTrackerStats host_tracker_stats;
 
 namespace snort
 {
+#define INFO_SIZE 32
 #define MAC_SIZE 6
 extern const uint8_t zero_mac[MAC_SIZE];
 
@@ -67,10 +68,18 @@ struct HostMac
 
 struct HostApplication
 {
+    HostApplication() = default;
+    HostApplication(Port pt, IpProtocol pr, AppId ap, bool in, uint32_t ht = 0, uint32_t ls = 0) :
+        port(pt), proto(pr), appid(ap), inferred_appid(in), hits(ht), last_seen(ls) { }
+
     Port port;
     IpProtocol proto;
     AppId appid;
     bool inferred_appid;
+    uint32_t hits;
+    uint32_t last_seen;
+    char vendor[INFO_SIZE] = { 0 };
+    char version[INFO_SIZE] = { 0 };
 };
 
 enum HostType
@@ -153,6 +162,8 @@ public:
     // Returns the matching host_mac
     const HostMac* get_hostmac(const uint8_t* mac);
 
+    const uint8_t* get_last_seen_mac();
+
     void update_vlan(uint16_t vth_pri_cfi_vlan, uint16_t vth_proto);
     bool has_vlan();
     uint16_t get_vlan();
@@ -169,8 +180,14 @@ public:
     bool add_service(Port port, IpProtocol proto,
         AppId appid = APP_ID_NONE, bool inferred_appid = false, bool* added = nullptr);
 
-    AppId get_appid(Port port, IpProtocol proto, bool inferred_only = false, bool allow_port_wildcard = false);
+    AppId get_appid(Port port, IpProtocol proto, bool inferred_only = false,
+        bool allow_port_wildcard = false);
 
+    size_t get_service_count();
+    HostApplication get_service(Port port, IpProtocol proto, uint32_t lseen, bool& is_new,
+        AppId appid = APP_ID_NONE);
+    void update_service(const HostApplication& ha);
+    bool update_service_info(HostApplication& ha, const char* vendor, const char* version);
     void remove_inferred_services();
 
     bool add_tcp_fingerprint(uint32_t fpid);
@@ -183,7 +200,7 @@ 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::vector<HostMac, HostMacAllocator> macs;
+    std::list<HostMac, HostMacAllocator> macs; // list guarantees iterator validity on insertion
     std::vector<uint16_t, HostCacheAllocIp<uint16_t>> network_protos;
     std::vector<uint8_t, HostCacheAllocIp<uint8_t>> xport_protos;
     std::vector<HostApplication, HostAppAllocator> services;
index 2c56f4159c1d032e7c9cb361e5ec27d190f377f2..49bf94aee575e01f9b4738ffb10b9dc57ed9d9d4 100644 (file)
@@ -66,10 +66,6 @@ public:
 typedef LruCacheSharedMemcap<string, Item, hash<string>> CacheType;
 CacheType cache(100);
 
-// Unorthodox, but necessary because we need the implementation of
-// HostCacheAlloc in this file, which we inherit.
-#include "host_tracker/host_cache_allocator.cc"
-
 // Implement the allocator constructor AFTER we have a cache object
 // to point to and the implementation of our base HostCacheAlloc:
 template <class T>
index e2aeccc0b36f5382ec260f2eb83056cd16b7e23d..29c5f449289c73d818cbf4e9ee3f4b6acdab251a 100644 (file)
@@ -40,7 +40,7 @@ int SFDAQInstance::finalize_message(DAQ_Msg_h, DAQ_Verdict verdict)
     return -1;
 }
 void DeferredTrust::finalize(Active&) { }
-void DeferredTrust::set_deferred_trust(unsigned module_id, bool on)
+void DeferredTrust::set_deferred_trust(unsigned, bool on)
 {
     deferred_trust = on ? TRUST_DEFER_ON : TRUST_DEFER_OFF;
 }
index 516e241c91f51e038a65d0a17c63c96adb48fbbb..648a9f13bfe276ecc8b16fc4fc04e8735991bad6 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "protocols/packet.h"
 #include "pub_sub/appid_events.h"
+#include "utils/util.h"
 
 #include "appid_types.h"
 #include "application_ids.h"
@@ -49,7 +50,6 @@ public:
     virtual void reset()
     {
         my_id = APP_ID_NONE;
-        my_vendor.clear();
         my_version.clear();
     }
 
@@ -70,17 +70,6 @@ public:
 
     virtual void set_id(const snort::Packet& p, AppIdSession& asd, AppidSessionDirection dir, AppId app_id, AppidChangeBits& change_bits);
 
-    const char* get_vendor() const
-    {
-        return my_vendor.empty() ? nullptr : my_vendor.c_str();
-    }
-
-    void set_vendor(const char* vendor)
-    {
-        if ( vendor )
-            my_vendor = vendor;
-    }
-
     const char* get_version() const
     {
         return my_version.empty() ? nullptr : my_version.c_str();
@@ -97,21 +86,47 @@ public:
 
 private:
     AppId my_id = APP_ID_NONE;
-    std::string my_vendor;
     std::string my_version;
 };
 
+struct AppIdServiceSubtype
+{
+    AppIdServiceSubtype* next = nullptr;
+    std::string service;
+    std::string vendor;
+    std::string version;
+};
+
 class ServiceAppDescriptor : public ApplicationDescriptor
 {
 public:
     ServiceAppDescriptor() = default;
+    ~ServiceAppDescriptor() override
+    {
+        AppIdServiceSubtype* tmp_subtype = subtype;
+        while (tmp_subtype)
+        {
+            subtype = tmp_subtype->next;
+            delete tmp_subtype;
+            tmp_subtype = subtype;
+        }
+    }
 
     void set_id(AppId app_id, OdpContext& odp_ctxt);
 
     void reset() override
     {
         ApplicationDescriptor::reset();
+        my_vendor.clear();
         port_service_id = APP_ID_NONE;
+
+        AppIdServiceSubtype* tmp_subtype = subtype;
+        while (tmp_subtype)
+        {
+            subtype = tmp_subtype->next;
+            delete tmp_subtype;
+            tmp_subtype = subtype;
+        }
     }
 
     void update_stats(AppId id) override;
@@ -128,10 +143,41 @@ public:
         return deferred;
     }
 
+    const char* get_vendor() const
+    {
+        return my_vendor.empty() ? nullptr : my_vendor.c_str();
+    }
+
+    void set_vendor(const char* vendor, AppidChangeBits& change_bits)
+    {
+        if ( vendor )
+        {
+            my_vendor = vendor;
+            change_bits.set(APPID_SERVICE_VENDOR_BIT);
+        }
+    }
+
+    void add_subtype(AppIdServiceSubtype& more_subtype, AppidChangeBits& change_bits)
+    {
+        AppIdServiceSubtype** tmp_subtype;
+
+        for (tmp_subtype = &subtype; *tmp_subtype; tmp_subtype = &(*tmp_subtype)->next)
+            ;
+        *tmp_subtype = &more_subtype;
+        change_bits.set(APPID_SERVICE_SUBTYPE_BIT);
+    }
+
+    const AppIdServiceSubtype* get_subtype() const
+    {
+        return subtype;
+    }
+
 private:
     AppId port_service_id = APP_ID_NONE;
     bool deferred = false;
     using ApplicationDescriptor::set_id;
+    std::string my_vendor;
+    AppIdServiceSubtype* subtype = nullptr;
 };
 
 class ClientAppDescriptor : public ApplicationDescriptor
index 6495eafe35549e38413189504c354032f6195e58..d1933ef0c55f2ec78ac2f5ffd7208d169e985955 100644 (file)
@@ -528,33 +528,26 @@ int AppIdHttpSession::process_http_packet(AppidSessionDirection direction,
         {
             if ( asd.get_service_id() == APP_ID_NONE or asd.get_service_id() == APP_ID_HTTP  or
                 asd.get_service_id() == APP_ID_HTTP2)
+            {
+                char* vendorVersion = nullptr;
+                char* vendor = nullptr;
+                AppIdServiceSubtype* subtype = nullptr;
+
+                http_matchers.get_server_vendor_version(server->c_str(), server->size(),
+                    &vendorVersion, &vendor, &subtype);
+                if (vendor || vendorVersion)
                 {
-                    char* vendorVersion = nullptr;
-                    char* vendor = nullptr;
-                    AppIdServiceSubtype* subtype = nullptr;
-
-                    http_matchers.get_server_vendor_version(server->c_str(), server->size(),
-                        &vendorVersion, &vendor, &subtype);
-                    if (vendor || vendorVersion)
-                    {
-                        asd.set_service_vendor(vendor);
-                        asd.set_service_version(vendorVersion, change_bits);
-                        asd.scan_flags &= ~SCAN_HTTP_VENDOR_FLAG;
-
-                        snort_free(vendor);
-                        snort_free(vendorVersion);
-                    }
-
-                    if (subtype)
-                    {
-                        AppIdServiceSubtype** tmp_subtype;
-
-                        for (tmp_subtype = &asd.subtype; *tmp_subtype; tmp_subtype = &(*tmp_subtype)->next)
-                            ;
-
-                        *tmp_subtype = subtype;
-                    }
+                    asd.set_service_vendor(vendor, change_bits);
+                    asd.set_service_version(vendorVersion, change_bits);
+                    asd.scan_flags &= ~SCAN_HTTP_VENDOR_FLAG;
+
+                    snort_free(vendor);
+                    snort_free(vendorVersion);
                 }
+
+                if (subtype)
+                    asd.add_service_subtype(*subtype, change_bits);
+            }
         }
 
         if (is_webdav)
index 76adeea2e74f7a699bfdf101bbe356b929b94cf7..29c34a88cfc72fea6639631a6ca4f7e8dbaacf37 100644 (file)
@@ -627,17 +627,6 @@ void AppIdSession::delete_session_data(bool free_api)
     snort_free(netbios_name);
     snort_free(netbios_domain);
 
-    AppIdServiceSubtype* rna_ss = subtype;
-    while (rna_ss)
-    {
-        subtype = rna_ss->next;
-        snort_free(const_cast<char*>(rna_ss->service));
-        snort_free(const_cast<char*>(rna_ss->vendor));
-        snort_free(const_cast<char*>(rna_ss->version));
-        snort_free(rna_ss);
-        rna_ss = subtype;
-    }
-
     if (tsession)
         delete tsession;
 
index 98ab3ae1bb4b762175135c284d98d04f589b8616..794421249e197b7b545cbd78c783fc66fc9b02d3 100644 (file)
@@ -265,7 +265,6 @@ public:
     APPID_DISCOVERY_STATE service_disco_state = APPID_DISCO_STATE_NONE;
     SESSION_SERVICE_SEARCH_STATE service_search_state = SESSION_SERVICE_SEARCH_STATE::START;
     ServiceDetector* service_detector = nullptr;
-    AppIdServiceSubtype* subtype = nullptr;
     std::vector<ServiceDetector*> service_candidates;
 
     // Following field is used only for non-http sessions. For HTTP traffic,
@@ -478,9 +477,14 @@ public:
         api.service.set_version(version, change_bits);
     }
 
-    void set_service_vendor(const char* vendor)
+    void set_service_vendor(const char* vendor, AppidChangeBits& change_bits)
     {
-        api.service.set_vendor(vendor);
+        api.service.set_vendor(vendor, change_bits);
+    }
+
+    void add_service_subtype(AppIdServiceSubtype& subtype, AppidChangeBits& change_bits)
+    {
+        api.service.add_subtype(subtype, change_bits);
     }
 
     AppId get_client_id() const
index 420566bed0b5bdc51c443fe10de649e459cb0e44..4adcdf83b4340f25ddffbf857c5e53f262918e08 100644 (file)
@@ -48,6 +48,14 @@ AppId AppIdSessionApi::get_service_app_id() const
     return application_ids[APP_PROTOID_SERVICE];
 }
 
+void AppIdSessionApi::get_service_info(const char*& vendor, const char*& version,
+    const AppIdServiceSubtype*& subtype) const
+{
+    vendor = service.get_vendor();
+    version = service.get_version();
+    subtype = service.get_subtype();
+}
+
 AppId AppIdSessionApi::get_misc_app_id(uint32_t stream_index) const
 {
     if (get_service_app_id() == APP_ID_HTTP2)
index 4a061c451e49c2ff8403f5438bab2d061ca9eff8..bf4d5bb5e8699818808429e3c5f787134bcc014a 100644 (file)
@@ -105,12 +105,16 @@ class SO_PUBLIC AppIdSessionApi : public StashGenericObject
 {
 public:
     AppId get_service_app_id() const;
+    void get_service_info(const char*& vendor, const char*& version,
+        const AppIdServiceSubtype*& subtype) const;
     AppId get_misc_app_id(uint32_t stream_index = 0) const;
     AppId get_client_app_id(uint32_t stream_index = 0) const;
     AppId get_payload_app_id(uint32_t stream_index = 0) const;
     AppId get_referred_app_id(uint32_t stream_index = 0) const;
-    void get_app_id(AppId& service, AppId& client, AppId& payload, AppId& misc, AppId& referred, uint32_t stream_index = 0) const;
-    void get_app_id(AppId* service, AppId* client, AppId* payload, AppId* misc, AppId* referred, uint32_t stream_index = 0) const;
+    void get_app_id(AppId& service, AppId& client, AppId& payload, AppId& misc, AppId& referred,
+        uint32_t stream_index = 0) const;
+    void get_app_id(AppId* service, AppId* client, AppId* payload, AppId* misc, AppId* referred,
+        uint32_t stream_index = 0) const;
     bool is_appid_inspecting_session() const;
     bool is_appid_available() const;
     const char* get_client_version(uint32_t stream_index = 0) const;
@@ -121,8 +125,8 @@ public:
     const char* get_tls_host() const;
     bool is_http_inspection_done() const;
 
-    // For protocols such as HTTP2 which can have multiple streams within a single flow, get_first_stream_*
-    // methods return the appids in the first stream seen in a packet.
+    // For protocols such as HTTP2 which can have multiple streams within a single flow,
+    // get_first_stream_* methods return the appids in the first stream seen in a packet.
     void get_first_stream_app_ids(AppId& service, AppId& client, AppId& payload, AppId& misc) const;
     void get_first_stream_app_ids(AppId& service, AppId& client, AppId& payload) const;
 
index f1de4a6e530638d2627fe9962eb66d85eff74b71..0e3c1460f7d5cbcd6b5f3d5244338b89371a3503 100644 (file)
@@ -65,12 +65,4 @@ enum AppidSessionDirection
     APP_ID_APPID_SESSION_DIRECTION_MAX
 };
 
-struct AppIdServiceSubtype
-{
-    AppIdServiceSubtype* next;
-    const char* service;
-    const char* vendor;
-    const char* version;
-};
-
 #endif
index 10628baa08ea8fe64d235140885a3c1a6bb5772a..7dfbe3505df776eb9bdeed54de3a420201783f6f 100644 (file)
@@ -256,11 +256,7 @@ static void pop3_free_state(void* data)
         {
             AppIdServiceSubtype* sub = sd->subtype;
             sd->subtype = sub->next;
-            if (sub->service)
-                snort_free((void*)sub->service);
-            if (sub->version)
-                snort_free((void*)sub->version);
-            snort_free(sub);
+            delete sub;
         }
         ClientPOP3Data* cd = &dd->client;
         if (cd->username)
@@ -495,13 +491,11 @@ static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint1
                     ;
                 if (p == s || p >= line_end || !(*p))
                     goto ven_ver_done;
-                sub = (AppIdServiceSubtype*)snort_calloc(sizeof(AppIdServiceSubtype));
                 unsigned sub_len;
 
                 sub_len = p - s;
-                sub->service = (const char*)snort_calloc(sub_len+1);
-                memcpy(const_cast<char*>(sub->service), s, sub_len);
-                (const_cast<char*>(sub->service))[sub_len] = 0;
+                sub = new AppIdServiceSubtype();
+                sub->service.assign(reinterpret_cast<const char*>(s), sub_len);
                 sub->next = pd->subtype;
                 pd->subtype = sub;
                 if (line_end-p > (int)sizeof(subver_po)-1
@@ -513,9 +507,7 @@ static int pop3_server_validate(POP3DetectorData* dd, const uint8_t* data, uint1
                     if (p != s && p < line_end && *p)
                     {
                         sub_len = p - s;
-                        sub->version = (const char*)snort_calloc(sub_len+1);
-                        memcpy(const_cast<char*>(sub->version), s, sub_len);
-                        (const_cast<char*>(sub->version))[sub_len] = 0;
+                        sub->version.assign(reinterpret_cast<const char*>(s), sub_len);
                     }
                 }
             }
index d8939d25e141221f779731fd77335de6ab8aee0e..a2f9807eff131f74b430b1566ce4251bb82c1a1b 100644 (file)
@@ -1656,21 +1656,11 @@ void HttpPatternMatchers::get_server_vendor_version(const char* data, int len, c
                 {
                     if ( subname && subname_len > 0 && subver && *subname )
                     {
-                        AppIdServiceSubtype* sub =
-                            (AppIdServiceSubtype*)snort_calloc(
-                            sizeof(AppIdServiceSubtype));
-                        char* tmp = (char*)snort_calloc(subname_len + 1);
-                        memcpy(tmp, subname, subname_len);
-                        tmp[subname_len] = 0;
-                        sub->service = tmp;
+                        AppIdServiceSubtype* sub = new AppIdServiceSubtype();
+                        sub->service.assign(subname, subname_len);
                         int subver_len = p - subver;
                         if (subver_len > 0 && *subver)
-                        {
-                            tmp = (char*)snort_calloc(subver_len + 1);
-                            memcpy(tmp, subver, subver_len);
-                            tmp[subver_len] = 0;
-                            sub->version = tmp;
-                        }
+                            sub->version.assign(subver, subver_len);
                         sub->next = *subtype;
                         *subtype = sub;
                     }
@@ -1690,21 +1680,12 @@ void HttpPatternMatchers::get_server_vendor_version(const char* data, int len, c
 
         if ( subname && subname_len > 0 && subver && *subname )
         {
-            AppIdServiceSubtype* sub =
-                (AppIdServiceSubtype*)snort_calloc(sizeof(AppIdServiceSubtype));
-            char* tmp = (char*)snort_calloc(subname_len + 1);
-            memcpy(tmp, subname, subname_len);
-            tmp[subname_len] = 0;
-            sub->service = tmp;
+            AppIdServiceSubtype* sub = new AppIdServiceSubtype();
+            sub->service.assign(subname, subname_len);
 
             int subver_len = p - subver;
             if ( subver_len > 0 && *subver )
-            {
-                tmp = (char*)snort_calloc(subver_len + 1);
-                memcpy(tmp, subver, subver_len);
-                tmp[subver_len] = 0;
-                sub->version = tmp;
-            }
+                sub->version.assign(subver, subver_len);
             sub->next = *subtype;
             *subtype = sub;
         }
index 7fea1d40cdcf658e75e090982897c0ec66c6f1b7..7eb6ecbe97533a509bfeffcf001b2f11c333477b 100644 (file)
@@ -40,6 +40,7 @@ struct Packet;
 }
 class AppIdHttpSession;
 class AppIdContext;
+struct AppIdServiceSubtype;
 class OdpContext;
 
 enum httpPatternType
index 0b5ec30daea373f46c1a1b802eff0dc46a60b1dd..c6b5024bfbe1bec54b640b201dbbeb107426b2ed 100644 (file)
@@ -80,15 +80,18 @@ int ServiceDetector::service_inprocess(AppIdSession& asd, const Packet* pkt, App
     return APPID_SUCCESS;
 }
 
-int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir, AppId appId,
-    const char* vendor, const char* version, AppidChangeBits& change_bits)
+int ServiceDetector::update_service_data(AppIdSession& asd, const Packet* pkt,
+    AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
+    AppidChangeBits& change_bits, AppIdServiceSubtype* subtype)
 {
     uint16_t port = 0;
     const SfIp* ip = nullptr;
 
     asd.service_detector = this;
-    asd.set_service_vendor(vendor);
+    asd.set_service_vendor(vendor, change_bits);
     asd.set_service_version(version, change_bits);
+    if (subtype)
+        asd.add_service_subtype(*subtype, change_bits);
     asd.set_service_detected();
     asd.set_service_id(appId, asd.get_odp_ctxt());
 
@@ -136,34 +139,23 @@ int ServiceDetector::add_service_consume_subtype(AppIdSession& asd, const Packet
     AppidSessionDirection dir, AppId appId, const char* vendor, const char* version,
     AppIdServiceSubtype* subtype, AppidChangeBits& change_bits)
 {
-    asd.subtype = subtype;
-    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits);
+    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits, subtype);
 }
 
 int ServiceDetector::add_service(AppidChangeBits& change_bits, AppIdSession& asd,
     const Packet* pkt, AppidSessionDirection dir, AppId appId, const char* vendor,
-    const char* version, const AppIdServiceSubtype* subtype)
+    const char* version, AppIdServiceSubtype* subtype)
 {
     AppIdServiceSubtype* new_subtype = nullptr;
 
     for (; subtype; subtype = subtype->next)
     {
-        AppIdServiceSubtype* tmp_subtype = (AppIdServiceSubtype*)snort_calloc(
-            sizeof(AppIdServiceSubtype));
-        if (subtype->service)
-            tmp_subtype->service = snort_strdup(subtype->service);
-
-        if (subtype->vendor)
-            tmp_subtype->vendor = snort_strdup(subtype->vendor);
-
-        if (subtype->version)
-            tmp_subtype->version = snort_strdup(subtype->version);
+        AppIdServiceSubtype* tmp_subtype = new AppIdServiceSubtype(*subtype);
 
         tmp_subtype->next = new_subtype;
         new_subtype = tmp_subtype;
     }
-    asd.subtype = new_subtype;
-    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits);
+    return update_service_data(asd, pkt, dir, appId, vendor, version, change_bits, new_subtype);
 }
 
 int ServiceDetector::incompatible_data(AppIdSession& asd, const Packet* pkt, AppidSessionDirection dir)
index 291f8d1c1c30b9f265809007aba16c58bfc80b3d..1a54561df9d675c415499229abc011f6b39313ff 100644 (file)
@@ -37,7 +37,7 @@ public:
 
     int add_service(AppidChangeBits&, AppIdSession&, const snort::Packet*,
         AppidSessionDirection, AppId, const char* vendor = nullptr,
-        const char* version = nullptr, const AppIdServiceSubtype* = nullptr);
+        const char* version = nullptr, AppIdServiceSubtype* = nullptr);
 
     int add_service_consume_subtype(AppIdSession&, const snort::Packet*,
         AppidSessionDirection dir, AppId, const char* vendor, const char* version,
@@ -57,8 +57,8 @@ public:
     }
 
 private:
-    int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection dir, AppId,
-        const char* vendor, const char* version, AppidChangeBits& change_bits);
+    int update_service_data(AppIdSession&, const snort::Packet*, AppidSessionDirection, AppId,
+        const char*, const char*, AppidChangeBits&, AppIdServiceSubtype*);
 };
 #endif
 
index 31cd6bc07eece861e8e297b509bf4d6fb001eb10..3e2acf78a0d21fc4c3765e00db5d0c51ecf4d679 100644 (file)
@@ -497,14 +497,12 @@ done:
         {
             if (pname && *pname)
             {
-                memset(&sub, 0, sizeof(sub));
                 sub.service = pname;
                 subtype = &sub;
             }
             else if (program)
             {
                 snprintf(subname, sizeof(subname), "(%u)", program);
-                memset(&sub, 0, sizeof(sub));
                 sub.service = subname;
                 subtype = &sub;
             }
@@ -844,14 +842,12 @@ inprocess:
         {
             if (pname && *pname)
             {
-                memset(&sub, 0, sizeof(sub));
                 sub.service = pname;
                 subtype = &sub;
             }
             else if (program)
             {
                 sprintf(subname, "(%u)", program);
-                memset(&sub, 0, sizeof(sub));
                 sub.service = subname;
                 subtype = &sub;
             }
index f2936b3a0a711d0037b2a1be7a272a21f6573781..7057aa74ff230a061db5b8bc0bdbc93d0f215679 100644 (file)
@@ -315,7 +315,7 @@ TEST(appid_api, ssl_app_group_id_lookup)
     CHECK_EQUAL(service, APPID_UT_ID);
     CHECK_EQUAL(client, APPID_UT_ID);
     CHECK_EQUAL(payload, APPID_UT_ID);
-    STRCMP_EQUAL("Published change_bits == 000000000000000", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000000000000", test_log);
 
     service = APP_ID_NONE;
     client = APP_ID_NONE;
@@ -328,7 +328,7 @@ TEST(appid_api, ssl_app_group_id_lookup)
     STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_first_alt_name(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
-    STRCMP_EQUAL("Published change_bits == 000000100011000", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000100011000", test_log);
 
     mock_session->tsession->set_tls_host("www.cisco.com", 13, change_bits);
     mock_session->tsession->set_tls_cname("www.cisco.com", 13, change_bits);
@@ -344,7 +344,7 @@ TEST(appid_api, ssl_app_group_id_lookup)
     STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_org_unit(), "Cisco");
-    STRCMP_EQUAL("Published change_bits == 000000100011000", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000100011000", test_log);
 
     string host = "";
     val = appid_api.ssl_app_group_id_lookup(flow, (const char*)(host.c_str()), nullptr,
@@ -355,7 +355,7 @@ TEST(appid_api, ssl_app_group_id_lookup)
     STRCMP_EQUAL(mock_session->tsession->get_tls_host(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_cname(), APPID_UT_TLS_HOST);
     STRCMP_EQUAL(mock_session->tsession->get_tls_org_unit(), "Google");
-    STRCMP_EQUAL("Published change_bits == 000000100000000", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000100000000", test_log);
     mock().checkExpectations();
 }
 
index 709a22c3c756ab887d1f19caaddfbcfc97229526..6ffa57f18e1a837178d5952360218950efe9cce1 100644 (file)
@@ -379,7 +379,7 @@ TEST(appid_discovery_tests, event_published_when_ignoring_flow)
 
     // Detect changes in service, client, payload, and misc appid
     mock().checkExpectations();
-    STRCMP_EQUAL("Published change_bits == 000000001111100", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000001111100", test_log);
 
     delete &asd->get_api();
     delete asd;
@@ -411,7 +411,7 @@ TEST(appid_discovery_tests, event_published_when_processing_flow)
 
     // Detect changes in service, client, payload, and misc appid
     mock().checkExpectations();
-    STRCMP_EQUAL("Published change_bits == 000000001111100", test_log);
+    STRCMP_EQUAL("Published change_bits == 00000000001111100", test_log);
     delete &asd->get_api();
     delete asd;
     delete flow;
@@ -506,10 +506,10 @@ TEST(appid_discovery_tests, change_bits_to_string)
     change_bits.set();
     change_bits_to_string(change_bits, str);
     STRCMP_EQUAL(str.c_str(), "created, reset, service, client, payload, misc, referred, host,"
-        " tls-host, url, user-agent, response, referrer, dns-host, version");
+        " tls-host, url, user-agent, response, referrer, dns-host, version, service-vendor, service-subtype");
 
     // Failure of this test is a reminder that enum is changed, hence translator needs update
-    CHECK_EQUAL(APPID_MAX_BIT, 15);
+    CHECK_EQUAL(APPID_MAX_BIT, 17);
 }
 
 int main(int argc, char** argv)
index 91c195438274686e8ea7c30115d8c732a9b33ccc..af0cb4b9dc77810b8f0e7799b3abac6acc552ef4 100644 (file)
@@ -88,9 +88,9 @@ AppIdSession::AppIdSession(IpProtocol proto, const SfIp* ip, uint16_t, AppIdInsp
     set_client_user(APPID_UT_ID, APPID_UT_USERNAME);
     set_client_version(APPID_UT_CLIENT_VERSION, change_bits);
 
-    set_service_vendor(APPID_UT_SERVICE_VENDOR);
+    set_service_vendor(APPID_UT_SERVICE_VENDOR, change_bits);
     set_service_version(APPID_UT_SERVICE_VERSION, change_bits);
-    subtype = &APPID_UT_SERVICE_SUBTYPE;
+    add_service_subtype(*(new AppIdServiceSubtype(APPID_UT_SERVICE_SUBTYPE)), change_bits);
 
     tsession = new TlsSession;
 
index 7408e79db111c56ae04649ce6f2a0ed5ea5c2cde..57d672cf7dd071c36c961a0e77cac742b1a7d107 100644 (file)
@@ -8,6 +8,8 @@ set (RNA_INCLUDES
 
 set ( RNA_SOURCES
     ${RNA_INCLUDES}
+    rna_app_discovery.cc
+    rna_app_discovery.h
     rna_event_handler.cc
     rna_event_handler.h
     rna_fingerprint.cc
diff --git a/src/network_inspectors/rna/rna_app_discovery.cc b/src/network_inspectors/rna/rna_app_discovery.cc
new file mode 100644 (file)
index 0000000..27949ec
--- /dev/null
@@ -0,0 +1,143 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// rna_app_discovery.cc authors: Masud Hasan <mashasan@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "rna_app_discovery.h"
+
+#include "detection/detection_engine.h"
+#include "network_inspectors/appid/appid_session_api.h"
+
+#include "rna_logger_common.h"
+
+using namespace snort;
+
+void RnaAppDiscovery::process(AppidEvent* appid_event, DiscoveryFilter& filter,
+    RnaConfig* conf, RnaLogger& logger)
+{
+    const Packet* p = DetectionEngine::get_current_packet();
+
+    // Published appid events may be on rebuilt packets
+    if ( !p->flow or !filter.is_host_monitored(p) )
+        return;
+
+    IpProtocol proto;
+    if ( p->flow->pkt_type == PktType::TCP )
+        proto = IpProtocol::TCP;
+    else if ( p->flow->pkt_type == PktType::UDP )
+        proto = IpProtocol::UDP;
+    else
+        return;
+
+    const auto& src_ip = p->ptrs.ip_api.get_src();
+    auto ht = host_cache.find(*src_ip);
+    if ( !ht )
+        return; // should not happen as rna would get new flow event before appid event
+
+    const uint8_t* src_mac;
+    if ( layer::get_eth_layer(p) )
+        src_mac = layer::get_eth_layer(p)->ether_src;
+    else
+        src_mac = ht->get_last_seen_mac();
+
+    ht->update_last_seen();
+    const auto& appid_change_bits = appid_event->get_change_bitset();
+    const auto& appid_session_api = appid_event->get_appid_session_api();
+
+    if ( appid_change_bits[APPID_SERVICE_BIT] or appid_change_bits[APPID_CLIENT_BIT] or
+        appid_change_bits[APPID_PAYLOAD_BIT] )
+    {
+        AppId service, client, payload;
+        appid_session_api.get_app_id(&service, &client, &payload, nullptr, nullptr);
+
+        if ( appid_change_bits[APPID_SERVICE_BIT] and service > APP_ID_NONE )
+            discover_service(p, proto, ht, (const struct in6_addr*) src_ip->get_ip6_ptr(),
+                src_mac, conf, logger, service);
+    }
+
+    if ( appid_change_bits[APPID_SERVICE_VENDOR_BIT] or appid_change_bits[APPID_VERSION_BIT] )
+    {
+        const char* vendor;
+        const char* version;
+        const AppIdServiceSubtype* subtype;
+        appid_session_api.get_service_info(vendor, version, subtype);
+        update_service_info(p, proto, vendor, version, ht, src_ip, src_mac, logger);
+    }
+}
+
+void RnaAppDiscovery::discover_service(const Packet* p, IpProtocol proto, RnaTracker& rt,
+    const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
+    RnaLogger& logger, AppId service)
+{
+    if ( conf and conf->max_host_services and conf->max_host_services <= rt->get_service_count() )
+        return;
+
+    bool is_new = false;
+
+    // Work on a local copy instead of reference as we release lock during event generations
+    auto ha = rt->get_service(p->flow->server_port, proto, (uint32_t) packet_time(), is_new);
+    if ( is_new )
+    {
+        if ( proto == IpProtocol::TCP )
+            logger.log(RNA_EVENT_NEW, NEW_TCP_SERVICE, p, &rt, src_ip, src_mac, &ha);
+        else
+            logger.log(RNA_EVENT_NEW, NEW_UDP_SERVICE, p, &rt, src_ip, src_mac, &ha);
+
+        ha.hits = 0; // hit count is reset after logs are written
+        ha.appid = service;
+        rt->update_service(ha);
+    }
+}
+
+void RnaAppDiscovery::update_service_info(const Packet* p, IpProtocol proto, const char* vendor,
+    const char* version, RnaTracker& rt, const SfIp* ip, const uint8_t* src_mac, RnaLogger& logger)
+{
+    if ( !vendor and !version )
+        return;
+
+    HostApplication ha(p->flow->server_port, proto, APP_ID_NONE, false);
+    if ( !rt->update_service_info(ha, vendor, version) )
+        return;
+
+    // Work on a local copy for eventing purpose
+    ha.last_seen = (uint32_t) packet_time();
+    if ( vendor )
+    {
+        strncpy(ha.vendor, vendor, INFO_SIZE);
+        ha.vendor[INFO_SIZE-1] = '\0';
+    }
+    if ( version )
+    {
+        strncpy(ha.version, version, INFO_SIZE);
+        ha.version[INFO_SIZE-1] = '\0';
+    }
+
+    if ( proto == IpProtocol::TCP )
+        logger.log(RNA_EVENT_CHANGE, CHANGE_TCP_SERVICE_INFO, p, &rt,
+            (const struct in6_addr*) ip->get_ip6_ptr(), src_mac, &ha);
+    else
+        logger.log(RNA_EVENT_CHANGE, CHANGE_UDP_SERVICE_INFO, p, &rt,
+            (const struct in6_addr*) ip->get_ip6_ptr(), src_mac, &ha);
+
+    ha.hits = 0;
+    rt->update_service(ha);
+}
diff --git a/src/network_inspectors/rna/rna_app_discovery.h b/src/network_inspectors/rna/rna_app_discovery.h
new file mode 100644 (file)
index 0000000..9acd143
--- /dev/null
@@ -0,0 +1,40 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation.  You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//--------------------------------------------------------------------------
+
+#ifndef RNA_APP_DISCOVERY_H
+#define RNA_APP_DISCOVERY_H
+
+#include "rna_pnd.h"
+
+class RnaAppDiscovery
+{
+public:
+    static void process(AppidEvent* appid_event, DiscoveryFilter& filter,
+        RnaConfig* conf, RnaLogger& logger);
+
+    static void discover_service(const snort::Packet* p, IpProtocol proto, RnaTracker& rt,
+        const struct in6_addr* src_ip, const uint8_t* src_mac, RnaConfig* conf,
+        RnaLogger& logger, AppId service = APP_ID_NONE);
+
+private:
+    static void update_service_info(const snort::Packet* p, IpProtocol proto, const char* vendor,
+        const char* version, RnaTracker& rt, const snort::SfIp* ip, const uint8_t* src_mac,
+        RnaLogger& logger);
+};
+
+#endif
index a0b4c993817502f23eaa62b865c7acd8f24543f8..72f8c93cbb7d9b9e8dcd44003234e0309a49ec29 100644 (file)
 
 using namespace snort;
 
+void RnaAppidEventHandler::handle(DataEvent& event, Flow*)
+{
+    Profile profile(rna_perf_stats);
+    ++rna_stats.appid_change;
+    pnd.analyze_appid_changes(event);
+}
+
 void RnaIcmpBidirectionalEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
index 653c8c844ab1196b26b4c026828afeb59a1951c9..980842bc28143be033430e5c8227c466461705ac 100644 (file)
 #include "rna_module.h"
 #include "rna_pnd.h"
 
+class RnaAppidEventHandler : public snort::DataHandler
+{
+public:
+    RnaAppidEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    void handle(snort::DataEvent&, snort::Flow*) override;
+private:
+    RnaPnd& pnd;
+};
+
 class RnaIcmpNewFlowEventHandler : public snort::DataHandler
 {
 public:
index bf4daca61f9c692d9ee976d6165316aa4cc534bf..e70fc14f1ed715f2366a1e5783313bc9126c55bf 100644 (file)
@@ -56,11 +56,10 @@ RnaInspector::RnaInspector(RnaModule* mod)
 {
     mod_conf = mod->get_config();
     load_rna_conf();
-    time_t update_timeout = rna_conf ? rna_conf->update_timeout : 0;
     if ( mod_conf )
-        pnd = new RnaPnd(mod_conf->enable_logger, mod_conf->rna_conf_path, update_timeout);
+        pnd = new RnaPnd(mod_conf->enable_logger, mod_conf->rna_conf_path, rna_conf);
     else
-        pnd = new RnaPnd(false, "", update_timeout);
+        pnd = new RnaPnd(false, "", rna_conf);
 }
 
 RnaInspector::~RnaInspector()
@@ -74,6 +73,8 @@ RnaInspector::~RnaInspector()
 
 bool RnaInspector::configure(SnortConfig* sc)
 {
+    DataBus::subscribe_global( APPID_EVENT_ANY_CHANGE, new RnaAppidEventHandler(*pnd), sc );
+
     DataBus::subscribe_global( STREAM_ICMP_NEW_FLOW_EVENT, new RnaIcmpNewFlowEventHandler(*pnd), sc );
     DataBus::subscribe_global( STREAM_ICMP_BIDIRECTIONAL_EVENT, new RnaIcmpBidirectionalEventHandler(*pnd), sc );
 
index 95a42120f83d2d6d451874c83e7f121d75e591dd..ceb0e2e140a7d5d581cbde2425dc6ac044d672fe 100644 (file)
 
 #include "managers/event_manager.h"
 #include "protocols/packet.h"
+
 #include "rna_fingerprint_tcp.h"
 #include "rna_logger_common.h"
+#include "rna_module.h"
 
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
 
 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, const uint16_t proto,
-    const TcpFingerprint* tfp)
+#ifdef DEBUG_MSGS
+static inline void rna_logger_message(const RnaLoggerEvent& rle)
+{
+    char macbuf[19];
+    snprintf(macbuf, 19, "%02X:%02X:%02X:%02X:%02X:%02X",
+        rle.mac[0], rle.mac[1], rle.mac[2], rle.mac[3], rle.mac[4], rle.mac[5]);
+    if ( rle.ip )
+    {
+        SfIp ip;
+        SfIpString ipbuf;
+        ip.set(rle.ip); // using this instead of packet's ip to support ARP
+        debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s, ip %s\n",
+            rle.type, rle.subtype, macbuf, ip.ntop(ipbuf));
+    }
+    else
+        debug_logf(rna_trace, nullptr, "RNA log: type %u, subtype %u, mac %s\n",
+            rle.type, rle.subtype, macbuf);
+}
+#endif
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+   const struct in6_addr* src_ip, const uint8_t* src_mac, const HostApplication* ha)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, 0, 0,
+        nullptr, ha, nullptr, nullptr);
+}
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+    const struct in6_addr* src_ip, const uint8_t* src_mac, const TcpFingerprint* tfp)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, 0, 0,
+        nullptr, nullptr, tfp, nullptr);
+}
+
+void 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)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
+        nullptr, nullptr, nullptr, nullptr);
+}
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+    const struct in6_addr* src_ip, const uint8_t* src_mac, const HostMac* hm, uint32_t event_time)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
+        hm, nullptr, nullptr, nullptr);
+}
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, RnaTracker* ht,
+    uint16_t proto, const uint8_t* src_mac, const struct in6_addr* src_ip, uint32_t event_time)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, event_time, proto,
+        nullptr, nullptr, nullptr, nullptr);
+}
+
+void RnaLogger::log(uint16_t type, uint16_t subtype, const Packet* p, const uint8_t* src_mac,
+    const struct in6_addr* src_ip, RnaTracker* ht, uint32_t event_time, void* cond_var)
+{
+    log(type, subtype, src_ip, src_mac, ht, p, event_time, 0,
+        nullptr, nullptr, nullptr, cond_var);
+}
+
+bool RnaLogger::log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip,
+    const uint8_t* src_mac, RnaTracker* ht, const Packet* p, uint32_t event_time,
+    uint16_t proto, const HostMac* hm, const HostApplication* ha, const TcpFingerprint* tfp,
+    void* cond_var)
 {
     if ( !enabled )
         return false;
 
     assert(ht);
-    RnaLoggerEvent rle(type, subtype, ht, src_mac, hm, proto, tfp);
+
+    RnaLoggerEvent rle(type, subtype, src_mac, ht, hm, proto, cond_var, ha, tfp);
     if ( src_ip and (!IN6_IS_ADDR_V4MAPPED(src_ip) or src_ip->s6_addr32[3]) )
         rle.ip = src_ip;
-
+    else
+        rle.ip = nullptr;
     if ( event_time )
         (*ht)->update_last_event(event_time);
-    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);
+
+#ifdef DEBUG_MSGS
+    rna_logger_message(rle);
+#endif
     return true;
 }
 
@@ -71,11 +139,14 @@ TEST_CASE("RNA logger", "[rna_logger]")
     SECTION("Checking enabled flag")
     {
         RnaTracker ht;
+        uint8_t mac[6] = {0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6};
         RnaLogger logger1(false);
-        CHECK(logger1.log(0, 0, 0, &ht, 0, 0) == false);
+        CHECK(logger1.log(0, 0, nullptr, mac, &ht, nullptr, 0, 0,
+            nullptr, nullptr, nullptr, nullptr) == false);
 
         RnaLogger logger2(true);
-        CHECK(logger2.log(0, 0, 0, &ht, 0, 0) == true);
+        CHECK(logger2.log(0, 0, nullptr, mac, &ht, nullptr, 0, 0,
+            nullptr, nullptr, nullptr, nullptr) == true);
     }
 }
 #endif
index 99430afd6774126cb4571cfef5407dadf6afe981..381fc12ee04a2a58a9527673e2446b9b1b3b8f2e 100644 (file)
@@ -35,30 +35,60 @@ 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, const snort::HostMac* p_hm, const uint16_t p_proto,
-        const snort::TcpFingerprint* tcp_fp)
-        : type(p_type), subtype(p_subtype), ht(p_ht), mac(p_mac), hm(p_hm), proto(p_proto), tfp(tcp_fp) { }
+    RnaLoggerEvent (uint16_t t, uint16_t st, const uint8_t* mc, const RnaTracker* rt,
+        const snort::HostMac* hmp, uint16_t pr, void* cv, const snort::HostApplication* hap,
+        const snort::TcpFingerprint* tf) : type(t), subtype(st), mac(mc), ht(rt), hm(hmp),
+        proto(pr), cond_var(cv), ha(hap), tfp(tf) { }
+
     uint16_t type;
     uint16_t subtype;
-    const RnaTracker* ht;
+    const struct in6_addr* ip;
     const uint8_t* mac;
-    const struct in6_addr* ip = nullptr;
-    void* cond_var = nullptr;
+    const RnaTracker* ht;
     const snort::HostMac* hm;
-    const uint16_t proto;
-    const snort::TcpFingerprint* tfp = nullptr;
+    uint16_t proto;
+    void* cond_var;
+    const snort::HostApplication* ha;
+    const snort::TcpFingerprint* tfp;
 };
 
 class RnaLogger
 {
 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, const uint16_t proto = 0,
-            const snort::TcpFingerprint* tfp = nullptr);
+
+    // for host application
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+        const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::HostApplication* ha);
+
+    // for tcp fingerprint
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+        const struct in6_addr* src_ip, const uint8_t* src_mac, const snort::TcpFingerprint* tfp);
+
+    // for event time
+    void 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);
+
+    // for mac event
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+        const struct in6_addr* src_ip, const uint8_t* src_mac,
+        const snort::HostMac* hm = nullptr, uint32_t event_time = 0);
+
+    // for protocol event
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, RnaTracker* ht,
+        uint16_t proto, const uint8_t* mac, const struct in6_addr* ip = nullptr,
+        uint32_t event_time = 0);
+
+    // for timeout update
+    void log(uint16_t type, uint16_t subtype, const snort::Packet* p, const uint8_t* src_mac,
+        const struct in6_addr* src_ip, RnaTracker* ht, uint32_t event_time, void* cond_var);
+
+    // for all
+    bool log(uint16_t type, uint16_t subtype, const struct in6_addr* src_ip,
+        const uint8_t* src_mac, RnaTracker* ht, const snort::Packet* p = nullptr,
+        uint32_t event_time = 0, uint16_t proto = 0, const snort::HostMac* hm = nullptr,
+        const snort::HostApplication* ha = nullptr, const snort::TcpFingerprint* tfp = nullptr,
+        void* cond_var = nullptr);
 
 private:
     const bool enabled;
index 99bce39f51e71e17b221dfe895920e524f2c9694..cd25272d7ec7ea329e40fdf1c7129136e5cb8d16 100644 (file)
 // Common definitions between rna logger and pnd modules
 #define RNA_EVENT_NEW       1000
     #define NEW_HOST            1
+    #define NEW_TCP_SERVICE     2
     #define NEW_NET_PROTOCOL    3
     #define NEW_XPORT_PROTOCOL  4
+    #define NEW_UDP_SERVICE     6
     #define NEW_OS              8
 
 #define RNA_EVENT_CHANGE    1001
     #define CHANGE_HOPS                 5
+    #define CHANGE_TCP_SERVICE_INFO     6
+    #define CHANGE_UDP_SERVICE_INFO    10
     #define CHANGE_MAC_INFO            13
     #define CHANGE_MAC_ADD             14
     #define CHANGE_HOST_UPDATE         15
index 436d6c0a4961e7810b5f73b00d27b85ce2fc6748..0007c1e7b2459f0d9441b4df108efb34e43804c8 100644 (file)
@@ -97,7 +97,7 @@ private:
     uint32_t last_seen = 0;
     uint32_t last_event = 0;
     bool vlan_tag_present = false;
-    snort::vlan::VlanTagHdr vlan_tag;
+    snort::vlan::VlanTagHdr vlan_tag = { };
     std::vector<uint16_t, HostCacheAllocMac<uint16_t>> network_protos;
 };
 
index 3806c262b266ba75c3c6b54c01d6d6df286c5b0f..9ca7f840c6c78588770d5aa2dfc06efcc9000ada 100644 (file)
@@ -49,6 +49,8 @@
 using namespace snort;
 using namespace std;
 
+THREAD_LOCAL const Trace* rna_trace = nullptr;
+
 //-------------------------------------------------------------------------
 // rna commands, params, and pegs
 //-------------------------------------------------------------------------
@@ -172,6 +174,7 @@ static const Parameter rna_params[] =
 
 static const PegInfo rna_pegs[] =
 {
+    { CountType::SUM, "appid_change", "count of appid change events received" },
     { CountType::SUM, "icmp_bidirectional", "count of bidirectional ICMP flows received" },
     { CountType::SUM, "icmp_new", "count of new ICMP flows received" },
     { CountType::SUM, "ip_bidirectional", "count of bidirectional IP received" },
@@ -321,6 +324,15 @@ const PegInfo* RnaModule::get_pegs() const
 ProfileStats* RnaModule::get_profile() const
 { return &rna_perf_stats; }
 
+void RnaModule::set_trace(const Trace* trace) const
+{ rna_trace = trace; }
+
+const TraceOption* RnaModule::get_trace_options() const
+{
+    static const TraceOption rna_trace_options(nullptr, 0, nullptr);
+    return &rna_trace_options;
+}
+
 bool RnaModule::log_mac_cache(const char* outfile)
 {
     if ( !outfile )
index 0124bd6a2d05bc621ed262664ea1b1a887058223..c22f420f69f599f6c2d5ec0f5f5fba18ade54ab1 100644 (file)
@@ -22,6 +22,7 @@
 #define RNA_MODULE_H
 
 #include "framework/module.h"
+#include "main/snort_debug.h"
 #include "profiler/profiler.h"
 
 #include "rna_config.h"
@@ -30,6 +31,7 @@
 
 struct RnaStats
 {
+    PegCount appid_change;
     PegCount icmp_bidirectional;
     PegCount icmp_new;
     PegCount ip_bidirectional;
@@ -45,6 +47,7 @@ struct RnaStats
 
 extern THREAD_LOCAL RnaStats rna_stats;
 extern THREAD_LOCAL snort::ProfileStats rna_perf_stats;
+extern THREAD_LOCAL const snort::Trace* rna_trace;
 
 class RnaModule : public snort::Module
 {
@@ -66,6 +69,9 @@ public:
     Usage get_usage() const override
     { return CONTEXT; }
 
+    void set_trace(const snort::Trace*) const override;
+    const snort::TraceOption* get_trace_options() const override;
+
 private:
     RnaModuleConfig* mod_conf = nullptr;
     const char* dump_file = nullptr;
index 1b55812c58d8a4333cbfea682c1ac93aa862a0b6..775cd90e8519c37b941c755b4e5cf497c6f57cac 100644 (file)
 #include "protocols/arp.h"
 #include "protocols/bpdu.h"
 #include "protocols/icmp4.h"
-#include "protocols/packet.h"
 #include "protocols/protocol_ids.h"
-#include "protocols/tcp.h"
 
+#include "rna_app_discovery.h"
 #include "rna_fingerprint_tcp.h"
 #include "rna_logger_common.h"
 
@@ -46,44 +45,9 @@ using namespace snort;
 using namespace snort::bpdu;
 using namespace std;
 
-static inline bool is_eligible_packet(const Packet* p)
+void RnaPnd::analyze_appid_changes(DataEvent& event)
 {
-    if ( p->has_ip() or
-        memcmp(layer::get_eth_layer(p)->ether_src, zero_mac, MAC_SIZE) )
-        return true;
-    return false;
-}
-
-static inline bool is_eligible_ip(const Packet* p)
-{
-    // If payload needs to be inspected ever, allow rebuilt packet when is_proxied
-    if ( !p->has_ip() or p->is_rebuilt() or !p->flow )
-        return false;
-    return true;
-}
-
-static inline bool is_eligible_tcp(const Packet* p)
-{
-    if ( !is_eligible_ip(p) or p->ptrs.tcph->is_rst() )
-        return false;
-    return true;
-}
-
-static inline bool is_eligible_udp(const Packet* p)
-{
-    if ( !is_eligible_ip(p) )
-        return false;
-    if ( p->is_from_client() )
-    {
-        const SfIp* src = p->ptrs.ip_api.get_src();
-        const SfIp* dst = p->ptrs.ip_api.get_dst();
-        // FIXIT-M this code checking the v6 address unconditionally is almost certainly wrong,
-        //          especially since it's looking for an IPv4-specific protocol
-        if ( !src->is_set() and ((const uint8_t *) dst->get_ip6_ptr())[0] == 0XFF and
-            p->ptrs.sp == 68 and p->ptrs.dp == 67 )
-            return false; // skip BOOTP
-    }
-    return true;
+    RnaAppDiscovery::process(static_cast<AppidEvent*>(&event), filter, conf, logger);
 }
 
 void RnaPnd::analyze_flow_icmp(const Packet* p)
@@ -182,12 +146,12 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
 
     if ( new_mac and !new_host )
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_ADD, p, &ht,
-            src_ip_ptr, src_mac, packet_time(), nullptr, ht->get_hostmac(src_mac));
+            src_ip_ptr, src_mac, ht->get_hostmac(src_mac), packet_time());
 
     if ( ht->update_mac_ttl(src_mac, ttl) )
     {
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_INFO, p, &ht,
-            src_ip_ptr, src_mac, packet_time(), nullptr, ht->get_hostmac(src_mac));
+            src_ip_ptr, src_mac, ht->get_hostmac(src_mac), packet_time());
 
         HostMac* hm = ht->get_max_ttl_hostmac();
         if (hm and hm->primary and ht->get_hops())
@@ -201,14 +165,21 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
     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,
-                packet_time(), nullptr, nullptr, ptype);
+            logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, ptype, src_mac, src_ip_ptr,
+                packet_time());
     }
 
     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,
-            packet_time(), nullptr, nullptr, ptype);
+        logger.log(RNA_EVENT_NEW, NEW_XPORT_PROTOCOL, p, &ht, ptype, src_mac, src_ip_ptr,
+            packet_time());
+
+    if ( p->flow->two_way_traffic() )
+    {
+        auto proto = p->get_ip_proto_next();
+        if ( proto == IpProtocol::TCP or proto == IpProtocol::UDP )
+            RnaAppDiscovery::discover_service(p, proto, ht, src_ip_ptr, src_mac, conf, logger);
+    }
 
     if ( !new_host )
     {
@@ -225,10 +196,7 @@ void RnaPnd::discover_network(const Packet* p, uint8_t ttl)
         const TcpFingerprint* tfp = processor->get(p, rna_flow);
 
         if (tfp && ht->add_tcp_fingerprint(tfp->fpid))
-        {
-            logger.log(RNA_EVENT_NEW, NEW_OS, p, &ht, src_ip_ptr,
-                src_mac, 0, nullptr, nullptr, ptype, tfp);
-        }
+            logger.log(RNA_EVENT_NEW, NEW_OS, p, &ht, src_ip_ptr, src_mac, tfp);
     }
 }
 
@@ -260,8 +228,7 @@ void RnaPnd::generate_change_vlan_update(RnaTracker *rt, const Packet* p,
             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());
+        logger.log(RNA_EVENT_CHANGE, CHANGE_VLAN_TAG, p, rt, nullptr, src_mac, packet_time());
     }
 }
 
@@ -280,8 +247,7 @@ void RnaPnd::generate_change_vlan_update(RnaTracker *rt, const Packet* p,
     {
         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());
+            (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac, packet_time());
     }
 }
 
@@ -295,8 +261,8 @@ void RnaPnd::generate_change_host_update(RnaTracker* ht, const Packet* p,
     uint32_t last_event = (*ht)->get_last_event();
     time_t timestamp = sec - update_timeout;
     if ( last_seen > last_event && (time_t) last_event + update_timeout <= sec )
-        logger.log(RNA_EVENT_CHANGE, CHANGE_HOST_UPDATE, p, ht,
-        (const struct in6_addr*) src_ip->get_ip6_ptr(), src_mac, last_seen, (void*) &timestamp);
+        logger.log(RNA_EVENT_CHANGE, CHANGE_HOST_UPDATE, p, src_mac,
+            (const struct in6_addr*) src_ip->get_ip6_ptr(), ht, last_seen, (void*) &timestamp);
     // FIXIT-M: deal with host service hits.
 }
 
@@ -323,8 +289,8 @@ void RnaPnd::generate_change_host_update_eth(HostTrackerMac* mt, const Packet* p
 
     if ( last_seen > last_event && (time_t) last_event + update_timeout <= sec )
     {
-        logger.log(RNA_EVENT_CHANGE, CHANGE_HOST_UPDATE, p, &rt,
-            nullptr, src_mac, last_seen, (void*) &timestamp);
+        logger.log(RNA_EVENT_CHANGE, CHANGE_HOST_UPDATE, p, src_mac, nullptr,
+            &rt, last_seen, (void*) &timestamp);
 
         mt->update_last_event(sec);
     }
@@ -384,8 +350,7 @@ void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht, bool discover
         {
             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);
+                logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, ntype, mk.mac_addr);
                 hm_ptr->update_last_event(p->pkth->ts.tv_sec);
             }
         }
@@ -397,8 +362,7 @@ void RnaPnd::generate_new_host_mac(const Packet* p, RnaTracker ht, bool discover
                 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);
+                    logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, ntype, mk.mac_addr);
                     hm_ptr->update_last_event(p->pkth->ts.tv_sec);
                 }
             }
@@ -509,15 +473,13 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
     if ( ht->add_mac(src_mac, 0, 0) )
     {
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_ADD, p, ht_ref,
-            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac,
-            0, nullptr, ht->get_hostmac(src_mac));
+            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac, ht->get_hostmac(src_mac));
         hm_ptr->update_last_event(p->pkth->ts.tv_sec);
     }
     else if (ht->make_primary(src_mac))
     {
         logger.log(RNA_EVENT_CHANGE, CHANGE_MAC_INFO, p, ht_ref,
-            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac,
-            0, nullptr, ht->get_hostmac(src_mac));
+            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac, ht->get_hostmac(src_mac));
         hm_ptr->update_last_event(p->pkth->ts.tv_sec);
     }
 
@@ -526,8 +488,7 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
 
     if ( hm_ptr->add_network_proto(ntype) )
     {
-        logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, nullptr, src_mac,
-            0, nullptr, nullptr, ntype);
+        logger.log(RNA_EVENT_NEW, NEW_NET_PROTOCOL, p, &ht, ntype, src_mac);
         hm_ptr->update_last_event(p->pkth->ts.tv_sec);
     }
 
@@ -535,8 +496,7 @@ int RnaPnd::discover_network_arp(const Packet* p, RnaTracker* ht_ref)
     {
         ht->update_hops(0);
         logger.log(RNA_EVENT_CHANGE, CHANGE_HOPS, p, ht_ref,
-            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac, 0, nullptr,
-             ht->get_hostmac(src_mac));
+            (const struct in6_addr*) spa.get_ip6_ptr(), src_mac, ht->get_hostmac(src_mac));
         hm_ptr->update_last_event(p->pkth->ts.tv_sec);
     }
 
index ce9c6f04d883a27995a76324a7685ce15c9abeb6..6bd5c29cdeea37cb20d35abfb1042158eb358264 100644 (file)
 #include "host_tracker/host_tracker.h"
 #include "protocols/eth.h"
 #include "protocols/layer.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
 #include "protocols/vlan.h"
+#include "pub_sub/appid_events.h"
 #include "sfip/sf_ip.h"
 
+#include "rna_config.h"
 #include "rna_logger.h"
 #include "rna_mac_cache.h"
 
 #define USHRT_MAX std::numeric_limits<unsigned short>::max()
 
-namespace snort
-{
-struct Packet;
-}
-
 enum class TcpPacketType
 {
     SYN, SYN_ACK, MIDSTREAM
@@ -60,6 +59,46 @@ struct RNA_LLC
 };
 #pragma pack()
 
+static inline bool is_eligible_packet(const snort::Packet* p)
+{
+    if ( p->has_ip() or
+        memcmp(snort::layer::get_eth_layer(p)->ether_src, snort::zero_mac, MAC_SIZE) )
+        return true;
+    return false;
+}
+
+static inline bool is_eligible_ip(const snort::Packet* p)
+{
+    // If payload needs to be inspected ever, allow rebuilt packet when is_proxied
+    if ( !p->has_ip() or p->is_rebuilt() or !p->flow )
+        return false;
+    return true;
+}
+
+static inline bool is_eligible_tcp(const snort::Packet* p)
+{
+    if ( !is_eligible_ip(p) or p->ptrs.tcph->is_rst() )
+        return false;
+    return true;
+}
+
+static inline bool is_eligible_udp(const snort::Packet* p)
+{
+    if ( !is_eligible_ip(p) )
+        return false;
+    if ( p->is_from_client() )
+    {
+        const snort::SfIp* src = p->ptrs.ip_api.get_src();
+        const snort::SfIp* dst = p->ptrs.ip_api.get_dst();
+        // FIXIT-M this code checking the v6 address unconditionally is almost certainly wrong,
+        //          especially since it's looking for an IPv4-specific protocol
+        if ( !src->is_set() and ((const uint8_t *) dst->get_ip6_ptr())[0] == 0XFF and
+            p->ptrs.sp == 68 and p->ptrs.dp == 67 )
+            return false; // skip BOOTP
+    }
+    return true;
+}
+
 static inline unsigned short rna_get_eth(const snort::Packet* p)
 {
     const snort::vlan::VlanTagHdr* vh = nullptr;
@@ -79,9 +118,11 @@ class RnaPnd
 {
 public:
 
-    RnaPnd(const bool en, const std::string& conf, time_t ut = 0)
-        : logger(RnaLogger(en)), filter(DiscoveryFilter(conf)), update_timeout(ut) { }
+    RnaPnd(const bool en, const std::string& cp, RnaConfig* rc = nullptr) :
+        logger(RnaLogger(en)), filter(DiscoveryFilter(cp)), conf(rc)
+        { update_timeout = (rc ? rc->update_timeout : 0); }
 
+    void analyze_appid_changes(snort::DataEvent& event);
     void analyze_flow_icmp(const snort::Packet* p);
     void analyze_flow_ip(const snort::Packet* p);
     void analyze_flow_non_ip(const snort::Packet* p);
@@ -123,6 +164,7 @@ private:
 
     RnaLogger logger;
     DiscoveryFilter filter;
+    RnaConfig* conf;
     time_t update_timeout;
 };
 
index c4f4a704dffcd310bb9314dd9f8067b00771502b..d387654b836e4e4d4bf405d7d7893d7ddf70fc53 100644 (file)
@@ -60,6 +60,8 @@ enum AppidChangeBit
 
     // other
     APPID_VERSION_BIT,
+    APPID_SERVICE_VENDOR_BIT,
+    APPID_SERVICE_SUBTYPE_BIT,
 
     APPID_MAX_BIT
 };
@@ -100,6 +102,10 @@ inline void change_bits_to_string(AppidChangeBits& change_bits, std::string& str
         --n? str.append("dns-host, ") : str.append("dns-host");
     if (change_bits.test(APPID_VERSION_BIT))
         --n? str.append("version, ") : str.append("version");
+    if (change_bits.test(APPID_SERVICE_VENDOR_BIT))
+        --n? str.append("service-vendor, ") : str.append("service-vendor");
+    if (change_bits.test(APPID_SERVICE_SUBTYPE_BIT))
+        --n? str.append("service-subtype, ") : str.append("service-subtype");
     if (n != 0) // make sure all bits from AppidChangeBit enum get translated
         str.append("change_bits_to_string error!");
 }