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;
}
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);
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;
#include "control/control.h"
#include "main/analyzer_command.h"
#include "profiler/profiler.h"
+#include "utils/util.h"
#include "packet_capture.h"
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 }
};
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 }
};
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;
};
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
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;
}
// 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();
{
config.enabled = false;
config.group = -1;
+ config.tenants.clear();
}
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;
}
bool enabled;
int16_t group;
std::string filter;
+ std::vector<uint32_t> tenants;
};
struct CaptureStats
#include "framework/inspector.h"
#include "log/messages.h"
#include "protocols/packet.h"
+#include "utils/util.h"
#ifdef UNIT_TEST
#include "catch/snort_catch.h"
}
// 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);
}
}
{
config.enabled = false;
config.group = -1;
+ config.tenants.clear();
LogMessage("Packet capture disabled\n");
}
// 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() )
{
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)
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) )
{
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:
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();
#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
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;
if (tenantsstr)
{
- StrToIntVector(tenantsstr, ',', constraints.tenants);
+ str_to_int_vector(tenantsstr, ',', constraints.tenants);
constraints.set_bits |= PacketConstraints::SetBits::TENANT;
}
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
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()
{
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
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();
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