From: Oleg Torubara -X (otorubar - SOFTSERVE INC at Cisco) Date: Tue, 12 Mar 2024 05:50:06 +0000 (+0000) Subject: Pull request #4224: packet_capture: add packet capturing per tenant X-Git-Tag: 3.1.82.0~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=123f206fbb53c479bac78a6becd9db3c6daf2a9c;p=thirdparty%2Fsnort3.git Pull request #4224: packet_capture: add packet capturing per tenant Merge in SNORT/snort3 from ~OTORUBAR/snort3:packet_capture_per_tenant to master Squashed commit of the following: commit 3c0d68b1ab21d305c9d46016fe30e8c40fa1d9e8 Author: otorubar Date: Fri Feb 23 09:05:08 2024 -0800 packet_capture: add packet capturing per tenant --- diff --git a/src/network_inspectors/appid/appid_debug.cc b/src/network_inspectors/appid/appid_debug.cc index 8f8c6b58b..f862ccf51 100644 --- a/src/network_inspectors/appid/appid_debug.cc +++ b/src/network_inspectors/appid/appid_debug.cc @@ -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(info.protocol), - IntVectorToStr(info.tenants).c_str()); + int_vector_to_str(info.tenants).c_str()); enabled = true; } diff --git a/src/network_inspectors/appid/appid_module.cc b/src/network_inspectors/appid/appid_module.cc index 52672370e..3d5da3ffc 100644 --- a/src/network_inspectors/appid/appid_module.cc +++ b/src/network_inspectors/appid/appid_module.cc @@ -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); diff --git a/src/network_inspectors/appid/test/appid_debug_test.cc b/src/network_inspectors/appid/test/appid_debug_test.cc index d2a66e051..4542ffb13 100644 --- a/src/network_inspectors/appid/test/appid_debug_test.cc +++ b/src/network_inspectors/appid/test/appid_debug_test.cc @@ -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&, char) { return ""; } } -std::string IntVectorToStr(const std::vector& elems, char delim) { return ""; } THREAD_LOCAL const snort::Trace* appid_trace; diff --git a/src/network_inspectors/packet_capture/capture_module.cc b/src/network_inspectors/packet_capture/capture_module.cc index a450e58af..06a0634a5 100644 --- a/src/network_inspectors/packet_capture/capture_module.cc +++ b/src/network_inspectors/packet_capture/capture_module.cc @@ -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; } diff --git a/src/network_inspectors/packet_capture/capture_module.h b/src/network_inspectors/packet_capture/capture_module.h index 9b1c3b218..431824b75 100644 --- a/src/network_inspectors/packet_capture/capture_module.h +++ b/src/network_inspectors/packet_capture/capture_module.h @@ -31,6 +31,7 @@ struct CaptureConfig bool enabled; int16_t group; std::string filter; + std::vector tenants; }; struct CaptureStats diff --git a/src/network_inspectors/packet_capture/packet_capture.cc b/src/network_inspectors/packet_capture/packet_capture.cc index b317a62a2..b6290f2dd 100644 --- a/src/network_inspectors/packet_capture/packet_capture.cc +++ b/src/network_inspectors/packet_capture/packet_capture.cc @@ -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(); diff --git a/src/network_inspectors/packet_capture/packet_capture.h b/src/network_inspectors/packet_capture/packet_capture.h index f69f6c403..2ccca1033 100644 --- a/src/network_inspectors/packet_capture/packet_capture.h +++ b/src/network_inspectors/packet_capture/packet_capture.h @@ -22,7 +22,7 @@ #include -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 diff --git a/src/network_inspectors/packet_tracer/packet_tracer.cc b/src/network_inspectors/packet_tracer/packet_tracer.cc index 330820331..c064ef790 100644 --- a/src/network_inspectors/packet_tracer/packet_tracer.cc +++ b/src/network_inspectors/packet_tracer/packet_tracer.cc @@ -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(constraints.ip_proto), IntVectorToStr(constraints.tenants).c_str()); + static_cast(constraints.ip_proto), int_vector_to_str(constraints.tenants).c_str()); shell_enabled = true; diff --git a/src/network_inspectors/packet_tracer/packet_tracer_module.cc b/src/network_inspectors/packet_tracer/packet_tracer_module.cc index df9f43d30..d4a74ab64 100644 --- a/src/network_inspectors/packet_tracer/packet_tracer_module.cc +++ b/src/network_inspectors/packet_tracer/packet_tracer_module.cc @@ -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; } diff --git a/src/trace/trace_parser.cc b/src/trace/trace_parser.cc index 8822a4bc4..c4831129d 100644 --- a/src/trace/trace_parser.cc +++ b/src/trace/trace_parser.cc @@ -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 diff --git a/src/utils/util.cc b/src/utils/util.cc index afcf75dc0..868b4ffcc 100644 --- a/src/utils/util.cc +++ b/src/utils/util.cc @@ -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& 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& 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& 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& 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 diff --git a/src/utils/util.h b/src/utils/util.h index e42ed1eca..6625a21f6 100644 --- a/src/utils/util.h +++ b/src/utils/util.h @@ -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& elems); -std::string IntVectorToStr(const std::vector& 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& elems); +SO_PUBLIC std::string int_vector_to_str(const std::vector& elems, char delim = ','); } #endif