]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Pull request #4224: packet_capture: add packet capturing per tenant
authorOleg Torubara -X (otorubar - SOFTSERVE INC at Cisco) <otorubar@cisco.com>
Tue, 12 Mar 2024 05:50:06 +0000 (05:50 +0000)
committerSteve Chew (stechew) <stechew@cisco.com>
Tue, 12 Mar 2024 05:50:06 +0000 (05:50 +0000)
Merge in SNORT/snort3 from ~OTORUBAR/snort3:packet_capture_per_tenant to master

Squashed commit of the following:

commit 3c0d68b1ab21d305c9d46016fe30e8c40fa1d9e8
Author: otorubar <otorubar@cisco.com>
Date:   Fri Feb 23 09:05:08 2024 -0800

    packet_capture: add packet capturing per tenant

12 files changed:
src/network_inspectors/appid/appid_debug.cc
src/network_inspectors/appid/appid_module.cc
src/network_inspectors/appid/test/appid_debug_test.cc
src/network_inspectors/packet_capture/capture_module.cc
src/network_inspectors/packet_capture/capture_module.h
src/network_inspectors/packet_capture/packet_capture.cc
src/network_inspectors/packet_capture/packet_capture.h
src/network_inspectors/packet_tracer/packet_tracer.cc
src/network_inspectors/packet_tracer/packet_tracer_module.cc
src/trace/trace_parser.cc
src/utils/util.cc
src/utils/util.h

index 8f8c6b58b6a5b56c28b7b134b1d4246ae3736089..f862ccf517020c9f22c7cc669b71773c177eaaec 100644 (file)
@@ -223,7 +223,7 @@ void AppIdDebug::set_constraints(const char *desc,
 
         appid_log(nullptr, TRACE_INFO_LEVEL, "Debugging %s with %s-%hu and %s-%hu %hhu and tenants:%s\n", desc,
             sipstr, info.sport, dipstr, info.dport, static_cast<uint8_t>(info.protocol),
-            IntVectorToStr(info.tenants).c_str());
+            int_vector_to_str(info.tenants).c_str());
 
         enabled = true;
     }
index 52672370ee15af1129803860561fb733c6414ac0..3d5da3ffc7c917e7b2c76b151f6364a95f2b2efb 100644 (file)
@@ -315,7 +315,7 @@ static int enable_debug(lua_State* L)
     constraints.dport = dport;
 
     if (tenantsstr)
-        StrToIntVector(tenantsstr, ',', constraints.tenants);
+        str_to_int_vector(tenantsstr, ',', constraints.tenants);
 
     AppIdDebugLogEvent event(&constraints, "AppIdDbg");
     DataBus::publish(AppIdInspector::get_pub_id(), AppIdEventIds::DEBUG_LOG, event);
index d2a66e05166109c1aa30db70aa61b81a5db03a61..4542ffb139c3b06fd78dbd469bfb6d2a47e6f291 100644 (file)
@@ -54,9 +54,9 @@ void LogMessage(const char*, va_list&) { }
 void TraceApi::filter(snort::Packet const&) { }
 void trace_vprintf(const char*, unsigned char, const char*, const Packet*, const char*, va_list) { }
 uint8_t TraceApi::get_constraints_generation() { return 0; }
+std::string int_vector_to_str(const std::vector<uint32_t>&, char) { return ""; }
 }
 
-std::string IntVectorToStr(const std::vector<uint32_t>& elems, char delim) { return ""; }
 
 THREAD_LOCAL const snort::Trace* appid_trace;
 
index a450e58af26f8a1549e2158710f77ca2c10780df..06a0634a55155ea21333b4fa0a7291961163dde3 100644 (file)
@@ -29,6 +29,7 @@
 #include "control/control.h"
 #include "main/analyzer_command.h"
 #include "profiler/profiler.h"
+#include "utils/util.h"
 
 #include "packet_capture.h"
 
@@ -41,13 +42,16 @@ static int disable(lua_State*);
 static const Parameter s_capture[] =
 {
     { "enable", Parameter::PT_BOOL, nullptr, "false",
-      "initially enable packet dumping" },
+      "state of packet capturing" },
 
     { "filter", Parameter::PT_STRING, nullptr, nullptr,
-      "bpf filter to use for packet dump" },
+      "bpf filter to use for packet capturing" },
 
     { "group", Parameter::PT_INT, "-1:32767", "-1",
-      "group filter to use for the packet dump" },
+      "group filter to use for packet capturing" },
+
+    { "tenants", Parameter::PT_STRING, nullptr, nullptr,
+      "comma-separated tenants filter to use for packet capturing" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
@@ -55,25 +59,28 @@ static const Parameter s_capture[] =
 static const Parameter capture_params[] =
 {
     { "filter", Parameter::PT_STRING, nullptr, nullptr,
-      "bpf filter to use for packet dump" },
+      "bpf filter to use for packet capturing" },
 
     { "group", Parameter::PT_INT, "-1:32767", "-1",
-      "group filter to use for the packet dump" },
+      "group filter to use for packet capturing" },
+
+    { "tenants", Parameter::PT_STRING, nullptr, nullptr,
+      "comma-separated tenants filter to use for packet capturing" },
 
     { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
 };
 
 static const Command cap_cmds[] =
 {
-    { "enable", enable, capture_params, "dump raw packets"},
-    { "disable", disable, nullptr, "stop packet dump"},
+    { "enable", enable, capture_params, "capture raw packets"},
+    { "disable", disable, nullptr, "stop packet capturing"},
     { nullptr, nullptr, nullptr, nullptr }
 };
 
 static const PegInfo cap_names[] =
 {
     { CountType::SUM, "processed", "packets processed against filter" },
-    { CountType::SUM, "captured", "packets matching dumped after matching filter" },
+    { CountType::SUM, "captured", "packets captured after matching filter" },
     { CountType::END, nullptr, nullptr }
 };
 
@@ -86,13 +93,14 @@ THREAD_LOCAL ProfileStats cap_prof_stats;
 class PacketCaptureDebug : public AnalyzerCommand
 {
 public:
-    PacketCaptureDebug(const char* f, const int16_t g);
+    PacketCaptureDebug(const char* f, const int16_t g, const char* t);
     bool execute(Analyzer&, void**) override;
     const char* stringify() override { return "PACKET_CAPTURE_DEBUG"; }
 private:
     bool enable = false;
     std::string filter;
     int16_t group = -1;
+    std::string tenants;
 };
 
 // -----------------------------------------------------------------------------
@@ -100,14 +108,14 @@ private:
 // -----------------------------------------------------------------------------
 static int enable(lua_State* L)
 {
-    main_broadcast_command(new PacketCaptureDebug(lua_tostring(L, 1),
-        luaL_optint(L, 2, 0)), ControlConn::query_from_lua(L));
+    main_broadcast_command(new PacketCaptureDebug(luaL_optstring(L, 1, ""),
+        luaL_optint(L, 2, 0), luaL_optstring(L, 3, "")), ControlConn::query_from_lua(L));
     return 0;
 }
 
 static int disable(lua_State* L)
 {
-    main_broadcast_command(new PacketCaptureDebug(nullptr, -1), ControlConn::query_from_lua(L));
+    main_broadcast_command(new PacketCaptureDebug(nullptr, -1, nullptr), ControlConn::query_from_lua(L));
     return 0;
 }
 
@@ -115,20 +123,21 @@ static int disable(lua_State* L)
 // non-static functions
 // -----------------------------------------------------------------------------
 
-PacketCaptureDebug::PacketCaptureDebug(const char* f, const int16_t g)
+PacketCaptureDebug::PacketCaptureDebug(const char* f, const int16_t g, const char* t)
 {
     if (f)
     {
         filter = f;
         group = g;
         enable = true;
+        tenants = t == nullptr ? "" : t;
     }
 }
 
 bool PacketCaptureDebug::execute(Analyzer&, void**)
 {
     if (enable)
-        packet_capture_enable(filter, group);
+        packet_capture_enable(filter, group, tenants);
     else
         packet_capture_disable();
 
@@ -140,6 +149,7 @@ CaptureModule::CaptureModule() :
 {
     config.enabled = false;
     config.group = -1;
+    config.tenants.clear();
 }
 
 bool CaptureModule::set(const char*, Value& v, SnortConfig*)
@@ -153,6 +163,9 @@ bool CaptureModule::set(const char*, Value& v, SnortConfig*)
     else if ( v.is("group") )
         config.group = v.get_int16();
 
+    else if ( v.is("tenants") )
+        str_to_int_vector(v.get_string(), ',', config.tenants);
+
     return true;
 }
 
index 9b1c3b218de3a208340b363cc5cc2f8100a68813..431824b753caa6654ca876809fee952d03f21bc6 100644 (file)
@@ -31,6 +31,7 @@ struct CaptureConfig
     bool enabled;
     int16_t group;
     std::string filter;
+    std::vector<uint32_t> tenants;
 };
 
 struct CaptureStats
index b317a62a265da49107cdf0ac4fde4d24317973ad..b6290f2dd78d25043bb692f749b4f04210674c28 100644 (file)
@@ -29,6 +29,7 @@
 #include "framework/inspector.h"
 #include "log/messages.h"
 #include "protocols/packet.h"
+#include "utils/util.h"
 
 #ifdef UNIT_TEST
 #include "catch/snort_catch.h"
@@ -108,13 +109,14 @@ static bool open_pcap_dumper()
 }
 
 // for unit test
-static void _packet_capture_enable(const string& f, const int16_t g = -1)
+static void _packet_capture_enable(const string& f, const int16_t g = -1, const string& t = "")
 {
     if ( !config.enabled )
     {
         config.filter = f;
         config.enabled = true;
         config.group = g;
+        str_to_int_vector(t, ',', config.tenants);
     }
 }
 
@@ -123,6 +125,7 @@ static void _packet_capture_disable()
 {
     config.enabled = false;
     config.group = -1;
+    config.tenants.clear();
     LogMessage("Packet capture disabled\n");
 }
 
@@ -130,10 +133,10 @@ static void _packet_capture_disable()
 // non-static functions
 // -----------------------------------------------------------------------------
 
-void packet_capture_enable(const string& f, const int16_t g)
+void packet_capture_enable(const string& f, const int16_t g, const string& t)
 {
 
-    _packet_capture_enable(f, g);
+    _packet_capture_enable(f, g, t);
 
     if ( !capture_initialized() )
     {
@@ -202,8 +205,11 @@ bool PacketCapture::capture_init()
 void PacketCapture::show(const SnortConfig*) const
 {
     ConfigLogger::log_flag("enable", config.enabled);
-    if ( config.enabled )
+    if (config.enabled) 
+    {
         ConfigLogger::log_value("filter", config.filter.c_str());
+        ConfigLogger::log_value("tenants", int_vector_to_str(config.tenants).c_str());
+    }
 }
 
 void PacketCapture::eval(Packet* p)
@@ -223,6 +229,17 @@ void PacketCapture::eval(Packet* p)
         if ( p->is_cooked() )
             return;
 
+        if (!config.tenants.empty())
+        {
+            if (!std::any_of(config.tenants.begin(), config.tenants.end(),[&p](uint32_t tenant_id){
+            return p->pkth->tenant_id == tenant_id;
+            }))
+            {
+                cap_count_stats.checked++;
+                return;
+            }
+        }
+
         if ( !bpf.bf_insns || bpf_filter(bpf.bf_insns, p->pkt,
                 p->pktlen, p->pkth->pktlen) )
         {
@@ -318,6 +335,21 @@ static Packet* init_null_packet()
     return &p;
 }
 
+static Packet* init_packet_with_tenant(uint32_t tenant_id)
+{
+    static Packet p(false);
+    static DAQ_PktHdr_t h;
+
+    h.tenant_id = tenant_id;
+
+    p.pkth = &h;
+    p.pkt = nullptr;
+    p.pktlen = 0;
+    h.pktlen = 0;
+
+    return &p;
+}
+
 class MockPacketCapture : public PacketCapture
 {
 public:
@@ -405,6 +437,38 @@ TEST_CASE("lazy init", "[PacketCapture]")
     mod_dtor(mod);
 }
 
+TEST_CASE("filter tenants", "[PacketCapture]")
+{
+    auto mod = (CaptureModule*)mod_ctor();
+    auto real_cap = (PacketCapture*)pc_ctor(mod);
+
+    CHECK ( (capture_initialized() == false) );
+
+    pc_dtor(real_cap);
+    MockPacketCapture cap(mod);
+
+    _packet_capture_enable("",-1,"11,13");
+    CHECK ( (capture_initialized() == false) );
+
+    auto packet_tenants_11 = init_packet_with_tenant(11);
+    cap.write_packet_called = false;
+    cap.eval(packet_tenants_11);
+    CHECK ( cap.write_packet_called );
+
+    auto packet_tenants_13 = init_packet_with_tenant(13);
+    cap.write_packet_called = false;
+    cap.eval(packet_tenants_13);
+    CHECK ( cap.write_packet_called );
+
+    auto packet_tenants_22 = init_packet_with_tenant(22);
+    cap.write_packet_called = false;
+    cap.eval(packet_tenants_22);
+    CHECK ( !cap.write_packet_called );
+
+    _packet_capture_disable();
+    mod_dtor(mod);
+}
+
 TEST_CASE("blank filter", "[PacketCapture]")
 {
     auto null_packet = init_null_packet();
index f69f6c4038964587514e1a99f59f88d4ea912cbc..2ccca10330a4a0bc9af5ed6b20b2331825451d1f 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <string>
 
-void packet_capture_enable(const std::string&, const int16_t g = -1);
+void packet_capture_enable(const std::string&, const int16_t g = -1, const std::string& t = "");
 void packet_capture_disable();
 
 #endif
index 3308203317d70478ed58d50848f2ef6949b389dc..c064ef790a44536fca7ed945bfb583d6e20bd824 100644 (file)
@@ -467,7 +467,7 @@ void PacketTracer::update_constraints(const PacketConstraints* cs)
 
     LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu and tenants:%s\n",
         sipstr, constraints.src_port, dipstr, constraints.dst_port,
-        static_cast<uint8_t>(constraints.ip_proto), IntVectorToStr(constraints.tenants).c_str());
+        static_cast<uint8_t>(constraints.ip_proto), int_vector_to_str(constraints.tenants).c_str());
 
     shell_enabled = true;
 
index df9f43d30bba723d141f23e0cef9230527524865..d4a74ab64dbef5b32bb698cc4680a05472cfd781 100644 (file)
@@ -131,7 +131,7 @@ static int enable(lua_State* L)
 
     if (tenantsstr)
     {
-        StrToIntVector(tenantsstr, ',', constraints.tenants);
+        str_to_int_vector(tenantsstr, ',', constraints.tenants);
         constraints.set_bits |= PacketConstraints::SetBits::TENANT;
     }
 
index 8822a4bc4a782e28c3679f98b67e6428e5db3ed1..c4831129da89e6729bf6cf5f7e63e65c60e03723 100644 (file)
@@ -127,7 +127,7 @@ bool TraceParser::set_constraints(const Value& val)
         if (!tenants_str)
             return false;
 
-        StrToIntVector(tenants_str, ',', parsed_constraints.tenants);
+        str_to_int_vector(tenants_str, ',', parsed_constraints.tenants);
         parsed_constraints.set_bits |= PacketConstraints::SetBits::TENANT;
     }
     else
index afcf75dc0d850d7febf1eb55d0137bac2cfc13a0..868b4ffcc9cd002b3ba8ca1bb8cba429744f0b5d 100644 (file)
@@ -514,36 +514,6 @@ bool get_file_size(const std::string& path, size_t& size)
     return true;
 }
 
-void StrToIntVector(const std::string& s, char delim, std::vector<uint32_t>& elems)
-{
-    std::istringstream ss(s);
-    std::string item;
-    while (std::getline(ss, item, delim))
-    {
-        size_t pos;
-        uint32_t i = std::stoul(item, &pos);
-        elems.push_back(i);
-    }
-}
-
-std::string IntVectorToStr(const std::vector<uint32_t>& elems, char delim)
-{
-    std::string str = "none";
-    if (elems.size())
-    {
-        std::ostringstream oss;
-        for (size_t i = 0; i < elems.size(); ++i)
-        {
-            oss << elems[i];
-            if (i < elems.size() - 1)
-                oss << delim;
-        }
-        str = oss.str();
-    }
-
-    return str;
-}
-
 #if defined(NOCOREFILE)
 void SetNoCores()
 {
@@ -687,6 +657,36 @@ void uint8_to_printable_str(const uint8_t* buff, unsigned len, std::string& prin
     end_hex_state(hex_state, print_str);
 }
 
+void str_to_int_vector(const std::string& s, char delim, std::vector<uint32_t>& elems)
+{
+    std::istringstream ss(s);
+    std::string item;
+    while (std::getline(ss, item, delim))
+    {
+        size_t pos;
+        uint32_t i = std::stoul(item, &pos);
+        elems.push_back(i);
+    }
+}
+
+std::string int_vector_to_str(const std::vector<uint32_t>& elems, char delim)
+{
+    std::string str = "none";
+    if (elems.size())
+    {
+        std::ostringstream oss;
+        for (size_t i = 0; i < elems.size(); ++i)
+        {
+            oss << elems[i];
+            if (i < elems.size() - 1)
+                oss << delim;
+        }
+        str = oss.str();
+    }
+
+    return str;
+}
+
 }
 
 #ifdef UNIT_TEST
index e42ed1eca5de738c4623e3f2eec9544f8569d246..6625a21f6d059990fc57e2b6f994f84565e080fc 100644 (file)
@@ -75,8 +75,6 @@ bool EnterChroot(std::string& root_dir, std::string& log_dir);
 void InitProtoNames();
 unsigned int get_random_seed();
 bool get_file_size(const std::string&, size_t&);
-void StrToIntVector(const std::string& s, char delim, std::vector<uint32_t>& elems);
-std::string IntVectorToStr(const std::vector<uint32_t>& elems, char delim = ',');
 
 #if defined(NOCOREFILE)
 void SetNoCores();
@@ -132,6 +130,8 @@ SO_PUBLIC char* snort_strdup(const char*);
 SO_PUBLIC char* snort_strndup(const char*, size_t);
 SO_PUBLIC void ts_print(const struct timeval*, char*, bool yyyymmdd = false);
 void uint8_to_printable_str(const uint8_t* buff, unsigned len, std::string& print_str);
+SO_PUBLIC void str_to_int_vector(const std::string& s, char delim, std::vector<uint32_t>& elems);
+SO_PUBLIC std::string int_vector_to_str(const std::vector<uint32_t>& elems, char delim = ',');
 }
 
 #endif