]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #3067 in SNORT/snort3 from ~DERAMADA/snort3:netflow_unique_templat...
authorSteve Chew (stechew) <stechew@cisco.com>
Mon, 20 Sep 2021 20:30:30 +0000 (20:30 +0000)
committerSteve Chew (stechew) <stechew@cisco.com>
Mon, 20 Sep 2021 20:30:30 +0000 (20:30 +0000)
Squashed commit of the following:

commit d936e929feacc641f05d7da7965a460c75a55e58
Author: Deepak Ramadass <deramada@cisco.com>
Date:   Fri Sep 17 10:45:56 2021 -0400

    fix cppucheck

commit 2d612e6f89852f66e6ccdfba40c79105364f2b41
Author: Deepak Ramadass <deramada@cisco.com>
Date:   Fri Sep 17 10:02:41 2021 -0400

    netflow: use device ip and template id to ensure that the template cache keys are unique

src/service_inspectors/netflow/netflow.cc
src/service_inspectors/netflow/netflow_module.h

index 75025ee60b449569159c00d902ee9bbc08a8e0c9..d9865ba57e649e83be893e4aca0fed2d2a618887 100644 (file)
@@ -65,7 +65,7 @@ static THREAD_LOCAL NetflowCache* netflow_cache = nullptr;
 static NetflowCache* dump_cache = nullptr;
 
 // Netflow version 9 Template fields cache.
-typedef std::unordered_map<uint16_t, std::vector<Netflow9TemplateField>> TemplateFieldCache;
+typedef std::unordered_map<std::pair<uint16_t, snort::SfIp>, std::vector<Netflow9TemplateField>, TemplateIpHash> TemplateFieldCache;
 static THREAD_LOCAL TemplateFieldCache* template_cache = nullptr;
 
 // -----------------------------------------------------------------------------
@@ -358,6 +358,7 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
     header.unix_secs -= header.sys_uptime;
 
     const int zone = p->pkth->ingress_index;
+    const snort::SfIp device_ip = *p->ptrs.ip_api.get_src();
 
     data += sizeof(Netflow9Hdr);
 
@@ -384,11 +385,13 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
         // field id
         f_id = ntohs(flowset->field_id);
 
+        auto ti_key = std::make_pair(f_id, device_ip);
+
         // It's a data flowset
-        if ( f_id > 255 && template_cache->count(f_id) > 0 )
+        if ( f_id > 255 && template_cache->count(ti_key) > 0 )
         {
             std::vector<Netflow9TemplateField> tf;
-            tf = template_cache->at(f_id);
+            tf = template_cache->at(ti_key);
 
             while( data < flowset_end && records )
             {
@@ -482,15 +485,17 @@ static bool decode_netflow_v9(const unsigned char* data, uint16_t size,
 
                 if ( field_count > 0 )
                 {
+                    auto t_key = std::make_pair(t_id, device_ip);
+
                     // remove if there any entry exists for this template
-                    auto is_erased = template_cache->erase(t_id);
+                    auto is_erased = template_cache->erase(t_key);
 
                     // count only unique templates
                     if ( is_erased == 1 )
                         --netflow_stats.v9_templates;
 
                     // add template to cache
-                    template_cache->emplace(t_id, tf);
+                    template_cache->emplace(t_key, tf);
 
                     // update the total templates count
                     ++netflow_stats.v9_templates;
index 0a7bc975c773bbde2a651004f43b590fd470c0ea..f886e2d04033a46a53198e3af970d9d1cd16f540 100644 (file)
@@ -50,6 +50,19 @@ struct NetflowHash
     }
 };
 
+// Generate hash of template id and device ip
+struct TemplateIpHash
+{
+    size_t operator()(const std::pair<uint16_t, snort::SfIp> &ti) const
+    {
+        const uint64_t* ip64 = (const uint64_t*) ti.second.get_ip6_ptr();
+
+        return std::hash<uint64_t>() (ip64[0]) ^
+               std::hash<uint64_t>() (ip64[1]) ^
+               std::hash<uint64_t>() ((uint64_t)ti.first);
+    }
+};
+
 struct NetflowRule
 {
     NetflowRule() { reset(); }