]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #3466: rna: allow rna to fire an event when a new netflow connection...
authorMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 28 Jun 2022 16:55:31 +0000 (16:55 +0000)
committerMasud Hasan (mashasan) <mashasan@cisco.com>
Tue, 28 Jun 2022 16:55:31 +0000 (16:55 +0000)
Merge in SNORT/snort3 from ~MMATIRKO/snort3:netflow_conn_events to master

Squashed commit of the following:

commit d5a2c8c4a6217cc3dba89a8b25efae1d72e729f5
Author: Michael Matirko <mmatirko@cisco.com>
Date:   Tue Jun 7 13:37:12 2022 -0400

    rna: allow rna to fire an event when a new netflow connection is detected

16 files changed:
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_pnd.cc
src/network_inspectors/rna/rna_pnd.h
src/pub_sub/CMakeLists.txt
src/pub_sub/netflow_event.h
src/pub_sub/rna_events.h [new file with mode: 0644]
src/service_inspectors/netflow/CMakeLists.txt
src/service_inspectors/netflow/netflow.cc
src/service_inspectors/netflow/netflow_cache.cc
src/service_inspectors/netflow/netflow_cache.h
src/service_inspectors/netflow/netflow_headers.h
src/service_inspectors/netflow/netflow_module.cc
src/service_inspectors/netflow/netflow_module.h
src/service_inspectors/netflow/netflow_record.h [new file with mode: 0644]

index cc7768ea15bf25a2fc0b1c48a0d801036448ecb9..e01ad149cc87c434c530a1d8bf2d28885376063b 100644 (file)
@@ -134,7 +134,7 @@ void RnaCPEOSInfoEventHandler::handle(DataEvent& event, Flow*)
     pnd.analyze_cpe_os_info(event);
 }
 
-void RnaNetflowEventHandler::handle(DataEvent& event, Flow*)
+void RnaNetFlowEventHandler::handle(DataEvent& event, Flow*)
 {
     Profile profile(rna_perf_stats);
     ++rna_stats.netflow_record;
index b0ce76d50109722ea1dddeed57dce81b200d9095..32a82e4f80c4a181e41247f90feea3796f82ac6c 100644 (file)
@@ -162,10 +162,10 @@ private:
     RnaPnd& pnd;
 };
 
-class RnaNetflowEventHandler : public snort::DataHandler
+class RnaNetFlowEventHandler : public snort::DataHandler
 {
 public:
-    RnaNetflowEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
+    RnaNetFlowEventHandler(RnaPnd& nd) : DataHandler(RNA_NAME), pnd(nd) { }
     void handle(snort::DataEvent&, snort::Flow*) override;
 private:
     RnaPnd& pnd;
index ac15390b7846b4973fb130dc402841067f14f103..68ff5689e78d29e181a6b8fabc53a6db6d3d1233 100644 (file)
@@ -107,7 +107,7 @@ bool RnaInspector::configure(SnortConfig*)
     DataBus::subscribe_network( STREAM_TCP_MIDSTREAM_EVENT, new RnaTcpMidstreamEventHandler(*pnd) );
 
     DataBus::subscribe_network( CPE_OS_INFO_EVENT, new RnaCPEOSInfoEventHandler(*pnd) );
-    DataBus::subscribe_network( NETFLOW_EVENT, new RnaNetflowEventHandler(*pnd) );
+    DataBus::subscribe_network( NETFLOW_EVENT, new RnaNetFlowEventHandler(*pnd) );
 
     if (rna_conf && rna_conf->log_when_idle)
         DataBus::subscribe_network( THREAD_IDLE_EVENT, new RnaIdleEventHandler(*pnd) );
index c17eb935ff63394981a2fc2af394cd9b6d7e7c04..c9e0ff2ff36b65a28ac63ab5e5ca35080c34bf20 100644 (file)
@@ -35,6 +35,7 @@
 #include "protocols/icmp4.h"
 #include "protocols/icmp6.h"
 #include "protocols/protocol_ids.h"
+#include "pub_sub/rna_events.h"
 
 #include "rna_app_discovery.h"
 #include "rna_cpe_os.h"
@@ -182,10 +183,9 @@ bool RnaPnd::analyze_netflow(snort::DataEvent& event)
     if ( !p )
         return false;
 
-    NetflowEvent* nfe = static_cast<NetflowEvent*>(&event);
+    NetFlowEvent* nfe = static_cast<NetFlowEvent*>(&event);
 
-    if (nfe->get_create_host())
-        analyze_netflow_host(nfe);
+    analyze_netflow_host(nfe);
 
     if (nfe->get_create_service())
         analyze_netflow_service(nfe);
@@ -193,7 +193,7 @@ bool RnaPnd::analyze_netflow(snort::DataEvent& event)
     return true;
 }
 
-void RnaPnd::analyze_netflow_host(NetflowEvent* nfe)
+void RnaPnd::analyze_netflow_host(NetFlowEvent* nfe)
 {
     const Packet* p = nfe->get_packet();
     if ( !p )
@@ -211,7 +211,20 @@ void RnaPnd::analyze_netflow_host(NetflowEvent* nfe)
     const uint8_t src_mac[6] = {0};
 
     if ( new_host )
-        logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, src_ip_ptr, src_mac);
+    {
+        if (!nfe->get_create_host() and !nfe->get_create_service())
+        {
+            uint32_t service = nfe->get_service_id();
+            RNAEvent new_flow_event(p, nfe->get_record(), service);
+            DataBus::publish(RNA_NEW_NETFLOW_HOST, new_flow_event);
+            return;
+        }
+
+        if ( nfe->get_create_host() )
+            logger.log(RNA_EVENT_NEW, NEW_HOST, p, &ht, src_ip_ptr, src_mac);
+        else
+            return;
+    }
 
     uint16_t ptype = rna_get_eth(p);
     if ( ptype > to_utype(ProtocolId::ETHERTYPE_MINIMUM) )
@@ -230,7 +243,7 @@ void RnaPnd::analyze_netflow_host(NetflowEvent* nfe)
         generate_change_host_update(&ht, p, &src_ip, src_mac, packet_time());
 }
 
-void RnaPnd::analyze_netflow_service(NetflowEvent* nfe)
+void RnaPnd::analyze_netflow_service(NetFlowEvent* nfe)
 {
 
     const Packet* p = nfe->get_packet();
index ed5aca794367bf737df8344f1465d512c9a6c2be..acb4ef6507b220c9ff17d236a26fd3ec5d60a84f 100644 (file)
@@ -133,8 +133,8 @@ public:
     void analyze_smb_fingerprint(snort::DataEvent&);
     bool analyze_cpe_os_info(snort::DataEvent&);
     bool analyze_netflow(snort::DataEvent&);
-    void analyze_netflow_host(snort::NetflowEvent*);
-    void analyze_netflow_service(snort::NetflowEvent*);
+    void analyze_netflow_host(snort::NetFlowEvent*);
+    void analyze_netflow_service(snort::NetFlowEvent*);
 
     // generate change event for all hosts in the ip cache
     void generate_change_host_update();
index d00049a668f9dc62af96ddc4dedcad6bbe459106..829d3187f4cf86100d4daed1a7ea68702a866b94 100644 (file)
@@ -14,6 +14,7 @@ set (PUB_SUB_INCLUDES
     http_request_body_event.h
     netflow_event.h
     opportunistic_tls_event.h
+    rna_events.h
     sip_events.h
     smb_events.h
     ssh_events.h
index f7ce3277a1a8d11c01d5ad27e44d1d21563c1fa6..82aa601582593400fa9b6dd91887055e0d72f626 100644 (file)
 #define NETFLOW_EVENT_H
 
 #include "framework/data_bus.h"
-#include "service_inspectors/netflow/netflow_headers.h"
+#include "service_inspectors/netflow/netflow_record.h"
 
 #define NETFLOW_EVENT "service_inspector.netflow"
 
 namespace snort
 {
 
-class NetflowEvent : public DataEvent
+class NetFlowEvent : public DataEvent
 {
 public:
-    NetflowEvent(const snort::Packet* p, const NetflowSessionRecord* rec,
+    NetFlowEvent(const snort::Packet* p, const NetFlowSessionRecord* rec,
         bool cre_host, bool cre_serv, uint32_t s_id)
         : pkt(p), record(rec), create_host(cre_host),
           create_service(cre_serv), serviceID(s_id) { }
@@ -39,7 +39,7 @@ public:
     const Packet* get_packet() override
     { return pkt; }
 
-    const NetflowSessionRecord* get_record()
+    const NetFlowSessionRecord* get_record()
     { return record; }
 
     bool get_create_host()
@@ -53,7 +53,7 @@ public:
 
 private:
     const Packet* pkt;
-    const NetflowSessionRecord* record;
+    const NetFlowSessionRecord* record;
     bool create_host;
     bool create_service;
     uint32_t serviceID = 0;
diff --git a/src/pub_sub/rna_events.h b/src/pub_sub/rna_events.h
new file mode 100644 (file)
index 0000000..986a44c
--- /dev/null
@@ -0,0 +1,54 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 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_events.h author Michael Matirko <mmatirko@cisco.com>
+
+#ifndef RNA_EVENTS_H
+#define RNA_EVENTS_H
+
+#include "framework/data_bus.h"
+#include "service_inspectors/netflow/netflow_record.h"
+
+#define RNA_NEW_NETFLOW_HOST "network_inspector.rna.new_netflow_host"
+
+namespace snort
+{
+
+class RNAEvent : public DataEvent
+{
+public:
+    RNAEvent(const snort::Packet* p, const NetFlowSessionRecord* rec, const uint32_t service)
+        : pkt(p), record(rec), service_id(service) { }
+
+    const Packet* get_packet() override
+    { return pkt; }
+
+    const NetFlowSessionRecord* get_record()
+    { return record; }
+
+    uint32_t get_service_id()
+    { return service_id; }
+
+private:
+    const Packet* pkt;
+    const NetFlowSessionRecord* record;
+    const uint32_t service_id;
+};
+
+}
+
+#endif
\ No newline at end of file
index a4e0531f3fc510dab489315975708303c864c7db..850a4a6d324e39eef34b6cba44efc008abec99b1 100644 (file)
@@ -1,9 +1,13 @@
 
-set ( FILE_LIST
+set ( NETFLOW_INCLUDES
     netflow_cache.h
     netflow_headers.h
-    netflow_module.cc
     netflow_module.h
+    netflow_record.h
+)
+set ( FILE_LIST
+    ${NETFLOW_INCLUDES}
+    netflow_module.cc
     netflow.cc
 )
 
@@ -13,4 +17,8 @@ if (STATIC_INSPECTORS)
 else (STATIC_INSPECTORS)
     add_dynamic_module(netflow inspectors ${FILE_LIST})
 
-endif (STATIC_INSPECTORS)
\ No newline at end of file
+endif (STATIC_INSPECTORS)
+
+install(FILES ${NETFLOW_INCLUDES}
+    DESTINATION "${INCLUDE_INSTALL_PATH}/service_inspectors/netflow"
+)
\ No newline at end of file
index 0c1c2d976ee2b9a2ea650bb4d7cb8421211e8f53..4ea6211857959bd72998b34c73270b89fabd7193 100644 (file)
 #include "utils/util.h"
 
 #include "netflow_cache.cc"
+#include "netflow_record.h"
 
 using namespace snort;
 
-THREAD_LOCAL NetflowStats netflow_stats;
+THREAD_LOCAL NetFlowStats netflow_stats;
 THREAD_LOCAL ProfileStats netflow_perf_stats;
 
 // Used to ensure we fully populate the record; can't rely on the actual values being zero
@@ -63,7 +64,7 @@ struct RecordStatus
 // -----------------------------------------------------------------------------
 
 // temporary cache required to dump the output
-typedef std::pair<snort::SfIp, NetflowSessionRecord> IpRecord;
+typedef std::pair<snort::SfIp, NetFlowSessionRecord> IpRecord;
 typedef std::vector<IpRecord> DumpCache;
 static DumpCache* dump_cache = nullptr;
 
@@ -80,7 +81,7 @@ static std::unordered_map<int, int>* tcp_srv_map = nullptr;
 // -----------------------------------------------------------------------------
 // static functions
 // -----------------------------------------------------------------------------
-static const NetflowRule* filter_record(const NetflowRules* rules, const int zone,
+static const NetFlowRule* filter_record(const NetFlowRules* rules, const int zone,
     const SfIp* src, const SfIp* dst)
 {
     const SfIp* addr[2] = {src, dst};
@@ -105,24 +106,53 @@ static const NetflowRule* filter_record(const NetflowRules* rules, const int zon
     return nullptr;
 }
 
-static void publish_service_event(const Packet* p, const NetflowRule* match, NetflowSessionRecord& record)
+static void publish_netflow_event(const Packet* p, const NetFlowRule* match, NetFlowSessionRecord& record)
 {
     uint32_t serviceID = 0;
 
+    std::unordered_map<int, int>* service_mappings = nullptr;
+
     if (record.proto == (int) ProtocolId::TCP and tcp_srv_map)
-        serviceID = (*tcp_srv_map)[record.responder_port];
+        service_mappings = tcp_srv_map;
     else if (record.proto == (int) ProtocolId::UDP and udp_srv_map)
-        serviceID = (*udp_srv_map)[record.responder_port];
+        service_mappings = udp_srv_map;
+
+    if (service_mappings)
+    {
+        uint32_t sid_responder;
+        uint32_t sid_initiator;
+
+        if (service_mappings->count(record.responder_port))
+            sid_responder = (*service_mappings)[record.responder_port];
+        else
+            sid_responder = 0;
+
+        if (service_mappings->count(record.initiator_port))
+            sid_initiator = (*service_mappings)[record.initiator_port];
+        else
+            sid_initiator = 0;
 
-    NetflowEvent event(p, &record, match->create_host, match->create_service, serviceID);
+        // Use only the known port. If both are known, take the lower numbered port.
+        if (sid_responder && !sid_initiator)
+            serviceID = sid_responder;
+        else if (sid_initiator && !sid_responder)
+            serviceID = sid_initiator;
+        else
+            serviceID = (record.initiator_port > record.responder_port) ? sid_responder : sid_initiator;
+    }
+
+    NetFlowEvent event(p, &record, match->create_host, match->create_service, serviceID);
     DataBus::publish(NETFLOW_EVENT, event);
 }
 
 static bool version_9_record_update(const unsigned char* data, uint32_t unix_secs,
-    uint16_t field_type, uint16_t field_length, NetflowSessionRecord &record,
-    RecordStatus& record_status)
+    uint32_t sys_uptime, uint16_t field_type, uint16_t field_length,
+    NetFlowSessionRecord &record, RecordStatus& record_status)
 {
 
+    uint32_t last_pkt_time = 0;
+    uint32_t first_pkt_time = 0;
+
     switch ( field_type )
     {
         case NETFLOW_PROTOCOL:
@@ -221,7 +251,14 @@ static bool version_9_record_update(const unsigned char* data, uint32_t unix_sec
             if( field_length != sizeof(record.last_pkt_second) )
                 return false;
 
-            record.last_pkt_second = unix_secs + ntohl(*(const time_t*)data)/1000;
+            last_pkt_time = ntohl(*(const time_t*)data)/1000;
+            // last_pkt_time (LAST_SWITCHED) is defined as the system uptime
+            // at which the flow was seen. If this is == to the current uptime
+            // something has gone wrong - use the NetFlow header unix time instead.
+            if (last_pkt_time >= sys_uptime)
+                record.last_pkt_second = unix_secs;
+            else
+                record.last_pkt_second = unix_secs + last_pkt_time;
 
             // invalid flow time value
             if( record.last_pkt_second > MAX_TIME )
@@ -235,7 +272,11 @@ static bool version_9_record_update(const unsigned char* data, uint32_t unix_sec
             if( field_length != sizeof(record.first_pkt_second) )
                 return false;
 
-            record.first_pkt_second = unix_secs + ntohl(*(const time_t*)data)/1000;
+            first_pkt_time = ntohl(*(const time_t*)data)/1000;
+            if (first_pkt_time >= sys_uptime)
+                record.first_pkt_second = unix_secs;
+            else
+                record.first_pkt_second = unix_secs + first_pkt_time;
 
             // invalid flow time value
             if( record.first_pkt_second > MAX_TIME )
@@ -359,21 +400,21 @@ static bool version_9_record_update(const unsigned char* data, uint32_t unix_sec
 }
 
 static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
-    const Packet* p, const NetflowRules* p_rules)
+    const Packet* p, const NetFlowRules* p_rules)
 {
-    Netflow9Hdr header;
-    const Netflow9Hdr *pheader;
-    const Netflow9FlowSet *flowset;
+    NetFlow9Hdr header;
+    const NetFlow9Hdr *pheader;
+    const NetFlow9FlowSet *flowset;
     const uint8_t *end;
     const uint8_t *flowset_end;
     uint16_t records;
 
-    if( size < sizeof(Netflow9Hdr) )
+    if( size < sizeof(NetFlow9Hdr) )
         return false;
 
     end = data + size;
 
-    pheader = (const Netflow9Hdr *)data;
+    pheader = (const NetFlow9Hdr *)data;
     header.flow_count = ntohs(pheader->flow_count);
 
     // invalid header flow count
@@ -391,7 +432,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
     const int zone = p->pkth->ingress_index;
     const snort::SfIp device_ip = *p->ptrs.ip_api.get_src();
 
-    data += sizeof(Netflow9Hdr);
+    data += sizeof(NetFlow9Hdr);
 
     while ( data < end )
     {
@@ -401,12 +442,12 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
         if ( data + sizeof(*flowset) > end )
             return false;
 
-        flowset = (const Netflow9FlowSet *)data;
+        flowset = (const NetFlow9FlowSet *)data;
 
         // length includes the flowset_id and length fields
         length = ntohs(flowset->field_length);
 
-        // invalid Netflow length
+        // invalid NetFlow length
         if( data + length > end )
             return false;
 
@@ -426,7 +467,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
             while( data < flowset_end && records )
             {
 
-                NetflowSessionRecord record = {};
+                NetFlowSessionRecord record = {};
                 RecordStatus record_status;
                 bool bad_field = false;
 
@@ -438,7 +479,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
 
                     if ( !bad_field )
                     {
-                        bool status = version_9_record_update(data, header.unix_secs,
+                        bool status = version_9_record_update(data, header.unix_secs, header.sys_uptime,
                             t_field->field_type, t_field->field_length, record, record_status);
 
                         if ( !status )
@@ -456,7 +497,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
                 }
 
                 // filter based on configuration
-                const NetflowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
+                const NetFlowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
                 if ( !match )
                 {
                     records--;
@@ -478,8 +519,8 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
                             record.nf_src_tos = record.nf_dst_tos;
                     }
 
-                    if (match->create_service)
-                        publish_service_event(p, match, record);
+                    record.netflow_initiator_ip.set(p->ptrs.ip_api.get_src()->get_ip6_ptr(), AF_INET6);
+                    publish_netflow_event(p, match, record);
 
                 }
 
@@ -495,12 +536,12 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
             // Step through the templates in this flowset and store them
             while ( data < flowset_end && records )
             {
-                const Netflow9Template* t_template;
+                const NetFlow9Template* t_template;
                 uint16_t field_count, t_id;
-                const Netflow9TemplateField* field;
-                std::vector<Netflow9TemplateField> tf;
+                const NetFlow9TemplateField* field;
+                std::vector<NetFlow9TemplateField> tf;
 
-                t_template = (const Netflow9Template *)data;
+                t_template = (const NetFlow9Template *)data;
                 field_count = ntohs(t_template->template_field_count);
 
                 if ( data + sizeof(*t_template) > flowset_end )
@@ -518,7 +559,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
                     if ( data + sizeof(*field) > flowset_end )
                         return false;
 
-                    field = (const Netflow9TemplateField *)data;
+                    field = (const NetFlow9TemplateField *)data;
                     tf.emplace_back(ntohs(field->field_type), ntohs(field->field_length));
                     data += sizeof(*field);
                 }
@@ -569,16 +610,16 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
 }
 
 static bool decode_netflow_v5(const unsigned char* data, uint16_t size,
-    const Packet* p, const NetflowRules* p_rules)
+    const Packet* p, const NetFlowRules* p_rules)
 {
-    Netflow5Hdr header;
-    const Netflow5Hdr *pheader;
-    const Netflow5RecordHdr *precord;
-    const Netflow5RecordHdr *end;
+    NetFlow5Hdr header;
+    const NetFlow5Hdr *pheader;
+    const NetFlow5RecordHdr *precord;
+    const NetFlow5RecordHdr *end;
 
-    end = (const Netflow5RecordHdr *)(data + size);
+    end = (const NetFlow5RecordHdr *)(data + size);
 
-    pheader = (const Netflow5Hdr *)data;
+    pheader = (const NetFlow5Hdr *)data;
     header.flow_count  = ntohs(pheader->flow_count);
 
     // invalid header flow count
@@ -587,8 +628,8 @@ static bool decode_netflow_v5(const unsigned char* data, uint16_t size,
 
     const int zone = p->pkth->ingress_index;
 
-    data += sizeof(Netflow5Hdr);
-    precord = (const Netflow5RecordHdr *)data;
+    data += sizeof(NetFlow5Hdr);
+    precord = (const NetFlow5RecordHdr *)data;
 
     // Invalid flow count
     if ( (precord + header.flow_count) > end )
@@ -612,7 +653,7 @@ static bool decode_netflow_v5(const unsigned char* data, uint16_t size,
         if ( first_packet > MAX_TIME or last_packet > MAX_TIME or first_packet > last_packet )
             return false;
 
-        NetflowSessionRecord record = {};
+        NetFlowSessionRecord record = {};
 
         // Invalid source IP address provided
         if ( record.initiator_ip.set(&precord->flow_src_addr, AF_INET) != SFIP_SUCCESS )
@@ -624,7 +665,7 @@ static bool decode_netflow_v5(const unsigned char* data, uint16_t size,
         if ( record.next_hop_ip.set(&precord->next_hop_addr, AF_INET) != SFIP_SUCCESS )
             return false;
 
-        const NetflowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
+        const NetFlowRule* match = filter_record(p_rules, zone, &record.initiator_ip, &record.responder_ip);
         if ( !match )
             continue;
 
@@ -650,13 +691,13 @@ static bool decode_netflow_v5(const unsigned char* data, uint16_t size,
         if ( netflow_cache->add(record.initiator_ip, record, false) )
             ++netflow_stats.unique_flows;
 
-        if (match->create_service)
-            publish_service_event(p, match, record);
+        record.netflow_initiator_ip.set(p->ptrs.ip_api.get_src()->get_ip6_ptr(), AF_INET6);
+        publish_netflow_event(p, match, record);
     }
     return true;
 }
 
-static bool validate_netflow(const Packet* p, const NetflowRules* p_rules)
+static bool validate_netflow(const Packet* p, const NetFlowRules* p_rules)
 {
     uint16_t size = p->dsize;
     const unsigned char* data = p->data;
@@ -664,7 +705,7 @@ static bool validate_netflow(const Packet* p, const NetflowRules* p_rules)
     bool retval = false;
 
     // invalid packet size
-    if( size < sizeof(Netflow5Hdr))
+    if( size < sizeof(NetFlow5Hdr))
         return false;
 
     version = ntohs(*((const uint16_t *)data));
@@ -694,11 +735,11 @@ static bool validate_netflow(const Packet* p, const NetflowRules* p_rules)
 // inspector stuff
 //-------------------------------------------------------------------------
 
-class NetflowInspector : public snort::Inspector
+class NetFlowInspector : public snort::Inspector
 {
 public:
-    NetflowInspector(const NetflowConfig*);
-    ~NetflowInspector() override;
+    NetFlowInspector(const NetFlowConfig*);
+    ~NetFlowInspector() override;
 
     void tinit() override;
     void tterm() override;
@@ -708,20 +749,20 @@ public:
     void install_reload_handler(snort::SnortConfig*) override;
 
 private:
-    const NetflowConfig *config;
+    const NetFlowConfig *config;
 
     bool log_netflow_cache();
     void stringify(std::ofstream&);
 };
 
-class NetflowReloadSwapper : public snort::ReloadSwapper
+class NetFlowReloadSwapper : public snort::ReloadSwapper
 {
 public:
-    explicit NetflowReloadSwapper(NetflowInspector& ins) : inspector(ins) { }
+    explicit NetFlowReloadSwapper(NetFlowInspector& ins) : inspector(ins) { }
     void tswap() override;
 
 private:
-    NetflowInspector& inspector;
+    NetFlowInspector& inspector;
 };
 
 static std::string to_string(const std::vector <snort::SfCidr>& networks)
@@ -770,7 +811,7 @@ static std::string to_string(const std::vector <int>& zones)
     return zs;
 }
 
-static void show_device(const NetflowRule& d, bool is_exclude)
+static void show_device(const NetFlowRule& d, bool is_exclude)
 {
     ConfigLogger::log_flag("exclude", is_exclude, true);
     ConfigLogger::log_flag("create_host", d.create_host, true);
@@ -779,7 +820,7 @@ static void show_device(const NetflowRule& d, bool is_exclude)
     ConfigLogger::log_value("zones", to_string(d.zones).c_str(), true);
 }
 
-void NetflowInspector::show(const SnortConfig*) const
+void NetFlowInspector::show(const SnortConfig*) const
 {
     ConfigLogger::log_value("flow_memcap", (uint64_t)config->flow_memcap);
     ConfigLogger::log_value("template_memcap", (uint64_t)config->template_memcap);
@@ -808,7 +849,7 @@ void NetflowInspector::show(const SnortConfig*) const
     }
 }
 
-void NetflowInspector::stringify(std::ofstream& file_stream)
+void NetFlowInspector::stringify(std::ofstream& file_stream)
 {
     std::sort(dump_cache->begin(), dump_cache->end(), IpCompare());
 
@@ -818,8 +859,8 @@ void NetflowInspector::stringify(std::ofstream& file_stream)
 
     for (auto& elem : *dump_cache)
     {
-        NetflowSessionRecord& record = elem.second;
-        str = "Netflow Record #";
+        NetFlowSessionRecord& record = elem.second;
+        str = "NetFlow Record #";
         str += std::to_string(++i);
         str += "\n";
 
@@ -859,7 +900,7 @@ void NetflowInspector::stringify(std::ofstream& file_stream)
     return;
 }
 
-bool NetflowInspector::log_netflow_cache()
+bool NetFlowInspector::log_netflow_cache()
 {
     const char* file_name = config->dump_file;
 
@@ -889,7 +930,7 @@ bool NetflowInspector::log_netflow_cache()
     return true;
 }
 
-NetflowInspector::NetflowInspector(const NetflowConfig* pc)
+NetFlowInspector::NetFlowInspector(const NetFlowConfig* pc)
 {
     config = pc;
 
@@ -900,7 +941,7 @@ NetflowInspector::NetflowInspector(const NetflowConfig* pc)
             dump_cache = new DumpCache;
     }
 
-    NetflowModule* mod = (NetflowModule*) ModuleManager::get_module(NETFLOW_NAME);
+    NetFlowModule* mod = (NetFlowModule*) ModuleManager::get_module(NETFLOW_NAME);
 
     if (mod)
     {
@@ -909,7 +950,7 @@ NetflowInspector::NetflowInspector(const NetflowConfig* pc)
     }
 }
 
-NetflowInspector::~NetflowInspector()
+NetFlowInspector::~NetFlowInspector()
 {
     // config and cache removal
     if ( config )
@@ -933,7 +974,7 @@ NetflowInspector::~NetflowInspector()
     }
 }
 
-void NetflowInspector::eval(Packet* p)
+void NetFlowInspector::eval(Packet* p)
 {
     if ( !p->is_udp() or !p->dsize or !p->data or !netflow_cache )
         return;
@@ -942,23 +983,23 @@ void NetflowInspector::eval(Packet* p)
 
     if ( d != config->device_rule_map.end() )
     {
-        const NetflowRules* p_rules = &(d->second);
+        const NetFlowRules* p_rules = &(d->second);
 
         if ( ! validate_netflow(p, p_rules) )
             ++netflow_stats.invalid_netflow_record;
     }
 }
 
-void NetflowInspector::tinit()
+void NetFlowInspector::tinit()
 {
     delete netflow_cache;
-    netflow_cache = new NetflowCache(config->flow_memcap, netflow_stats);
+    netflow_cache = new NetFlowCache(config->flow_memcap, netflow_stats);
 
     delete template_cache;
     template_cache = new TemplateFieldCache(config->template_memcap, netflow_stats);
 }
 
-void NetflowInspector::tterm()
+void NetFlowInspector::tterm()
 {
     if ( config->dump_file and dump_cache )
     {
@@ -970,12 +1011,12 @@ void NetflowInspector::tterm()
     delete template_cache;
 }
 
-void NetflowInspector::install_reload_handler(SnortConfig* sc)
+void NetFlowInspector::install_reload_handler(SnortConfig* sc)
 {
-    sc->register_reload_handler(new NetflowReloadSwapper(*this));
+    sc->register_reload_handler(new NetFlowReloadSwapper(*this));
 }
 
-void NetflowReloadSwapper::tswap()
+void NetFlowReloadSwapper::tswap()
 {
     inspector.tinit();
 }
@@ -985,15 +1026,15 @@ void NetflowReloadSwapper::tswap()
 //-------------------------------------------------------------------------
 
 static Module* netflow_mod_ctor()
-{ return new NetflowModule; }
+{ return new NetFlowModule; }
 
 static void netflow_mod_dtor(Module* m)
 { delete m; }
 
 static Inspector* netflow_ctor(Module* m)
 {
-    NetflowModule *mod = (NetflowModule*)m;
-    return new NetflowInspector(mod->get_data());
+    NetFlowModule *mod = (NetFlowModule*)m;
+    return new NetFlowInspector(mod->get_data());
 }
 
 static void netflow_dtor(Inspector* p)
index 3a21fc068fb591cc1599da0296bb50113e46c0bf..0252931f4443ee4066b6bac914786f48e7146c11 100644 (file)
 
 #include "netflow_cache.h"
 
-THREAD_LOCAL NetflowCache* netflow_cache = nullptr;
+THREAD_LOCAL NetFlowCache* netflow_cache = nullptr;
 
 template <class T>
-LruCacheAllocNetflow<T>::LruCacheAllocNetflow()
+LruCacheAllocNetFlow<T>::LruCacheAllocNetFlow()
 {
     lru = netflow_cache;
 }
index 02f3ebae6776da654ee27795e5bea92fe83febdb..83c3ca9ec70d9b46e51777ceb70ae319dbe928d0 100644 (file)
 
 #include "netflow_headers.h"
 #include "netflow_module.h"
+#include "netflow_record.h"
 
-// Trivial derived allocator, pointing to their own cache. LruCacheAllocNetflow has a
+// Trivial derived allocator, pointing to their own cache. LruCacheAllocNetFlow has a
 // CacheInterface* pointing to an lru cache. We can create different cache types by
 // instantiating the lru cache using different keys and derive here allocators with
 // CacheInterface* pointing to the appropriate lru cache object.
 template <class T>
-class LruCacheAllocNetflow : public CacheAlloc<T>
+class LruCacheAllocNetFlow : public CacheAlloc<T>
 {
 public:
     // This needs to be in every derived class:
     template <class U>
     struct rebind
     {
-        typedef LruCacheAllocNetflow<U> other;
+        typedef LruCacheAllocNetFlow<U> other;
     };
 
     using CacheAlloc<T>::lru;
-    LruCacheAllocNetflow();
+    LruCacheAllocNetFlow();
 };
 
 template<typename Key, typename Value, typename Hash>
-class LruCacheLocalNetflow : public LruCacheLocal<Key, Value, Hash>, public CacheInterface
+class LruCacheLocalNetFlow : public LruCacheLocal<Key, Value, Hash>, public CacheInterface
 {
 public:
     using LruLocal = LruCacheLocal<Key, Value, Hash>;
@@ -58,10 +59,10 @@ public:
     using LruLocal::max_size;
     using LruLocal::list;
 
-    LruCacheLocalNetflow(const size_t sz, struct LruCacheLocalStats& st) : LruLocal(sz, st) {}
+    LruCacheLocalNetFlow(const size_t sz, struct LruCacheLocalStats& st) : LruLocal(sz, st) {}
 
     template <class T>
-    friend class LruCacheAllocNetflow;
+    friend class LruCacheAllocNetFlow;
 
 private:
     // Only the allocator calls this
@@ -103,7 +104,7 @@ public:
     LruCacheLocalTemplate(const size_t sz, struct LruCacheLocalStats& st) : LruLocal(sz, st)
     {}
 
-    bool insert(const Key& key, std::vector<Netflow9TemplateField>& tf)
+    bool insert(const Key& key, std::vector<NetFlow9TemplateField>& tf)
     {
         bool is_new = false;
         Value& entry = LruLocal::find_else_create(key, &is_new);
@@ -134,14 +135,14 @@ private:
     }
 };
 
-// Used to track record for unique IP; we assume Netflow packets coming from
-// a given Netflow device will go to the same thread
-typedef LruCacheLocalNetflow<snort::SfIp, NetflowSessionRecord, NetflowHash> NetflowCache;
+// Used to track record for unique IP; we assume NetFlow packets coming from
+// a given NetFlow device will go to the same thread
+typedef LruCacheLocalNetFlow<snort::SfIp, NetFlowSessionRecord, NetFlowHash> NetFlowCache;
 
-// Used to track Netflow version 9 Template fields
+// Used to track NetFlow version 9 Template fields
 typedef std::pair<uint16_t, snort::SfIp> TemplateFieldKey;
-typedef LruCacheAllocTemplate<Netflow9TemplateField> TemplateAllocator;
-typedef std::vector<Netflow9TemplateField, TemplateAllocator> TemplateFieldValue;
+typedef LruCacheAllocTemplate<NetFlow9TemplateField> TemplateAllocator;
+typedef std::vector<NetFlow9TemplateField, TemplateAllocator> TemplateFieldValue;
 typedef LruCacheLocalTemplate<TemplateFieldKey, TemplateFieldValue, TemplateIpHash> TemplateFieldCache;
 
 #endif
index 6a18d343b5ea97197a6406e25d81bcd1e6a7b3b6..b9475d23b3b1d0e98a3403f454382fc897f8b321 100644 (file)
@@ -28,7 +28,7 @@
 #define NETFLOW_MAX_COUNT 256
 #define MAX_TIME 2145916799
 
-enum NetflowFieldTypes : uint16_t
+enum NetFlowFieldTypes : uint16_t
 {
     NETFLOW_IN_BYTES = 1,
     NETFLOW_IN_PKTS = 2,
@@ -55,36 +55,10 @@ enum NetflowFieldTypes : uint16_t
     NETFLOW_DST_TOS = 55,
 };
 
-struct NetflowSessionRecord
+struct NetFlow5Hdr
 {
-    snort::SfIp initiator_ip;
-    snort::SfIp responder_ip;
-    snort::SfIp next_hop_ip;
-    uint8_t proto;
-    uint16_t initiator_port;
-    uint16_t responder_port;
-    uint32_t first_pkt_second;
-    uint32_t last_pkt_second;
-    uint64_t initiator_pkts;
-    uint64_t responder_pkts;
-    uint64_t initiator_bytes;
-    uint64_t responder_bytes;
-    uint8_t tcp_flags;
-
-    uint32_t nf_src_as;
-    uint32_t nf_dst_as;
-    uint32_t nf_snmp_in;
-    uint32_t nf_snmp_out;
-    uint8_t nf_src_tos;
-    uint8_t nf_dst_tos;
-    uint8_t nf_src_mask;
-    uint8_t nf_dst_mask;
-};
-
-struct Netflow5Hdr
-{
-    uint16_t version;               // Netflow export format version number
-    uint16_t flow_count;            // Number of flows exported in this packet(1-30)
+    uint16_t version;               // NetFlow export format version number
+    uint16_t flow_count;            // Number of flows exported in this packet (1-30)
     uint32_t sys_uptime;            // Current time in milliseconds since the export device booted
     uint32_t unix_secs;             // Current count of seconds since 0000 UTC 1970
     uint32_t unix_nsecs;            // Residual nanoseconds since 0000 UTC 1970
@@ -94,7 +68,7 @@ struct Netflow5Hdr
     uint16_t sampling_interval;     // First two bits hold the sampling mode; remaining 14 bits hold value of sampling interval
 };
 
-struct Netflow5RecordHdr
+struct NetFlow5RecordHdr
 {
     uint32_t flow_src_addr;         // Source IP address
     uint32_t flow_dst_addr;         // Destination IP address
@@ -118,34 +92,34 @@ struct Netflow5RecordHdr
     uint16_t pad2;                  // Unused (zero) bytes
 };
 
-struct Netflow9Hdr
+struct NetFlow9Hdr
 {
-    uint16_t version;               // The version of netflow records exported in this packet;
+    uint16_t version;               // The version of netflow records exported in this packet
     uint16_t flow_count;            // Number of FlowSet records (both template and data) contained within this packet
     uint32_t sys_uptime;            // Time in milliseconds since this device was first booted
     uint32_t unix_secs;             // Seconds since 0000 Coordinated Universal Time (UTC) 1970
-    uint32_t sequence_num;          // Incremental sequence counter of all export packets sent by this export device;
+    uint32_t sequence_num;          // Incremental sequence counter of all export packets sent by this export device
     uint32_t source_id;             // A 32-bit value that identifies the Exporter Observation Domain
 };
 
-struct Netflow9FlowSet
+struct NetFlow9FlowSet
 {
     uint16_t field_id;
     uint16_t field_length;
 };
 
-struct Netflow9Template
+struct NetFlow9Template
 {
     uint16_t template_id;
     uint16_t template_field_count;
 };
 
-struct Netflow9TemplateField
+struct NetFlow9TemplateField
 {
     uint16_t field_type;
     uint16_t field_length;
 
-    Netflow9TemplateField(uint16_t type, uint16_t length)
+    NetFlow9TemplateField(uint16_t type, uint16_t length)
         : field_type(type)
         , field_length(length)
     {}
index e2bcc6d2f8a1b6f1a158933d5c51e41fef119513..a73583cfec75957cdac7c544100f248c951e7f6d 100644 (file)
@@ -101,28 +101,26 @@ static const PegInfo netflow_pegs[] =
 // netflow module
 //-------------------------------------------------------------------------
 
-NetflowModule::NetflowModule() : Module(NETFLOW_NAME, NETFLOW_HELP, netflow_params)
-{
-    conf = nullptr;
-}
+NetFlowModule::NetFlowModule() : Module(NETFLOW_NAME, NETFLOW_HELP, netflow_params)
+{ }
 
-NetflowModule::~NetflowModule()
+NetFlowModule::~NetFlowModule()
 {
     delete conf;
 }
 
-NetflowConfig* NetflowModule::get_data()
+NetFlowConfig* NetFlowModule::get_data()
 {
-    NetflowConfig* tmp = conf;
+    NetFlowConfig* tmp = conf;
     conf = nullptr;
     return tmp;
 }
 
-bool NetflowModule::begin(const char* fqn, int idx, SnortConfig*)
+bool NetFlowModule::begin(const char* fqn, int idx, SnortConfig*)
 {
     if ( !conf )
     {
-        conf = new NetflowConfig();
+        conf = new NetFlowConfig();
     }
 
     if ( idx && !strcmp(fqn, "netflow.rules") )
@@ -134,7 +132,7 @@ bool NetflowModule::begin(const char* fqn, int idx, SnortConfig*)
     return true;
 }
 
-bool NetflowModule::end(const char* fqn, int idx, SnortConfig*)
+bool NetFlowModule::end(const char* fqn, int idx, SnortConfig*)
 {
     if ( idx && !strcmp(fqn, "netflow.rules") )
     {
@@ -150,7 +148,7 @@ bool NetflowModule::end(const char* fqn, int idx, SnortConfig*)
 
     return true;
 }
-bool NetflowModule::set(const char*, Value& v, SnortConfig*)
+bool NetFlowModule::set(const char*, Value& v, SnortConfig*)
 {
     if ( v.is("flow_memcap") )
         conf->flow_memcap = v.get_size();
@@ -219,7 +217,7 @@ bool NetflowModule::set(const char*, Value& v, SnortConfig*)
     return true;
 }
 
-void NetflowModule::parse_service_id_file(const std::string& serv_id_file_path)
+void NetFlowModule::parse_service_id_file(const std::string& serv_id_file_path)
 {
     std::string serv_line;
     std::ifstream serv_id_file;
@@ -250,11 +248,11 @@ void NetflowModule::parse_service_id_file(const std::string& serv_id_file_path)
     }
 }
 
-PegCount* NetflowModule::get_counts() const
+PegCount* NetFlowModule::get_counts() const
 { return (PegCount*)&netflow_stats; }
 
-const PegInfo* NetflowModule::get_pegs() const
+const PegInfo* NetFlowModule::get_pegs() const
 { return netflow_pegs; }
 
-ProfileStats* NetflowModule::get_profile() const
+ProfileStats* NetFlowModule::get_profile() const
 { return &netflow_perf_stats; }
index e905ea118be458fad4b75736649a8d1d0b7e6fa2..2d90e3693a6b29deafd107a40282fff506a43f9f 100644 (file)
@@ -41,7 +41,7 @@ struct SnortConfig;
 #define NETFLOW_ANY_ZONE (-1)
 
 //  Used to create hash of key for indexing into cache.
-struct NetflowHash
+struct NetFlowHash
 {
     size_t operator()(const snort::SfIp& ip) const
     {
@@ -64,9 +64,9 @@ struct TemplateIpHash
     }
 };
 
-struct NetflowRule
+struct NetFlowRule
 {
-    NetflowRule() { reset(); }
+    NetFlowRule() { reset(); }
     void reset()
     {
         networks.clear();
@@ -108,24 +108,24 @@ struct NetflowRule
     bool create_service = false;
 };
 
-using NetflowRuleList = std::vector<NetflowRule>;
-struct NetflowRules
+using NetFlowRuleList = std::vector<NetFlowRule>;
+struct NetFlowRules
 {
-    NetflowRuleList exclude;
-    NetflowRuleList include;
+    NetFlowRuleList exclude;
+    NetFlowRuleList include;
 };
 
-struct NetflowConfig
+struct NetFlowConfig
 {
-    NetflowConfig() { }
+    NetFlowConfig() { }
     const char* dump_file = nullptr;
-    std::unordered_map <snort::SfIp, NetflowRules, NetflowHash> device_rule_map;
+    std::unordered_map <snort::SfIp, NetFlowRules, NetFlowHash> device_rule_map;
     uint32_t update_timeout = 0;
     size_t flow_memcap = 0;
     size_t template_memcap = 0;
 };
 
-struct NetflowStats : public LruCacheLocalStats
+struct NetFlowStats : public LruCacheLocalStats
 {
     PegCount invalid_netflow_record;
     PegCount packets;
@@ -138,14 +138,14 @@ struct NetflowStats : public LruCacheLocalStats
     PegCount version_9;
 };
 
-extern THREAD_LOCAL NetflowStats netflow_stats;
+extern THREAD_LOCAL NetFlowStats netflow_stats;
 extern THREAD_LOCAL snort::ProfileStats netflow_perf_stats;
 
-class NetflowModule : public snort::Module
+class NetFlowModule : public snort::Module
 {
 public:
-    NetflowModule();
-    ~NetflowModule() override;
+    NetFlowModule();
+    ~NetFlowModule() override;
 
     bool set(const char*, snort::Value&, snort::SnortConfig*) override;
     bool begin(const char*, int, snort::SnortConfig*) override;
@@ -154,7 +154,7 @@ public:
     const PegInfo* get_pegs() const override;
     PegCount* get_counts() const override;
     snort::ProfileStats* get_profile() const override;
-    NetflowConfig* get_data();
+    NetFlowConfig* get_data();
 
     void parse_service_id_file(const std::string& serv_id_file_path);
 
@@ -168,8 +168,8 @@ public:
     { return true; }
 
 private:
-    NetflowConfig* conf = nullptr;
-    NetflowRule rule_cfg = {};
+    NetFlowConfig* conf = nullptr;
+    NetFlowRule rule_cfg = {};
     snort::SfIp device_ip_cfg = {};
     bool is_exclude_rule = false;
 };
diff --git a/src/service_inspectors/netflow/netflow_record.h b/src/service_inspectors/netflow/netflow_record.h
new file mode 100644 (file)
index 0000000..bd3ec59
--- /dev/null
@@ -0,0 +1,53 @@
+//--------------------------------------------------------------------------
+// Copyright (C) 2022-2022 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.
+//--------------------------------------------------------------------------
+
+// netflow_record.h author Michael Matirko <mmatirkoe@cisco.com>
+
+#ifndef NETFLOW_RECORD_H
+#define NETFLOW_RECORD_H
+
+#include "sfip/sf_ip.h"
+
+struct NetFlowSessionRecord
+{
+    snort::SfIp initiator_ip;
+    snort::SfIp responder_ip;
+    snort::SfIp next_hop_ip;
+    snort::SfIp netflow_initiator_ip;
+    uint8_t proto;
+    uint16_t initiator_port;
+    uint16_t responder_port;
+    uint32_t first_pkt_second;
+    uint32_t last_pkt_second;
+    uint64_t initiator_pkts;
+    uint64_t responder_pkts;
+    uint64_t initiator_bytes;
+    uint64_t responder_bytes;
+    uint8_t tcp_flags;
+
+    uint32_t nf_src_as;
+    uint32_t nf_dst_as;
+    uint32_t nf_snmp_in;
+    uint32_t nf_snmp_out;
+    uint8_t nf_src_tos;
+    uint8_t nf_dst_tos;
+    uint8_t nf_src_mask;
+    uint8_t nf_dst_mask;
+};
+
+#endif