output - configure the output method for trace messages
modules - trace configuration for specific modules
constraints - filter traces by the packet constraints
- log_ntuple - on/off packet n-tuple info logging
+ ntuple - on/off packet n-tuple info logging
+ timestamp - on/off message timestamps logging
The following lines, added in snort.lua, will enable trace messages for
detection and codec modules. The messages will be printed to syslog if
the packet filtering constraints match. Messages will be in extended format,
-including n-tuple packet info at the beginning of each trace message.
+including timestamp and n-tuple packet info at the beginning of each trace message.
trace =
{
src_port = 100,
dst_port = 200
},
- log_ntuple = true
+ ntuple = true,
+ timestamp = true
}
The trace module supports config reloading. Also, it's possible to set or clear
options and/or packet filter constraints directly during Snort run and
without reloading the entire config.
-Control channel also allow adjusting trace output format by setting log_ntuple switcher.
+Control channel also allow adjusting trace output format by setting ntuple
+and timestamp switchers.
After entering the Snort shell, there are two commands available for
the trace module:
trace.set({ modules = { all = N } }) - enable traces for all modules with verbosity level N
- trace.set({ log_ntuple = true/false }) - on/off packet n-tuple info logging
+ trace.set({ ntuple = true/false }) - on/off packet n-tuple info logging
+
+ trace.set({ timestamp = true/false }) - on/off timestamp logging
trace.clear() - clear modules traces and constraints
P – packet thread
O – other thread
-Setting the option - *log_ntuple* allows you to change the trace message format,
+Setting the option - *ntuple* allows you to change the trace message format,
expanding it with information about the processed packet.
It will be added at the beginning, right after the thread type and instance ID,
Those info can be displayed only for IP packets.
Port defaults to zero if a packet doesn't have it.
+The *timestamp* option extends output format
+by logging the message time in the next format:
+
+ MM/DD-hh:mm:ss.SSSSSS
+
+Where:
+
+ M – month
+ D – day
+ h – hours
+ m – minutes
+ s – seconds
+ S – milliseconds
+
==== Example - Debugging rules using detection trace
The detection engine is responsible for rule evaluation. Turning on the
output - create a concrete logger factory based on the output value (stdout/syslog).
constraints - set packet constraints to use for trace filtering.
modules - set modules trace level verbosity.
- log_ntuple - on/off packet n-tuple info logging.
+ ntuple - on/off packet n-tuple info logging.
+ timestamp - on/off message time stamps.
This is a built-in module (from coreinit.lua)
for setting/clearing trace configuration from the shell. Commands parameters are encapsulated in
the TraceSwapParams class.
Available commands:
- 1) trace.set({ modules = {}, constraints = {}, log_ntuple = true/false })
- -- set new modules traces, constraints and log_ntuple option;
+ 1) trace.set({ modules = {}, constraints = {}, ntuple = true/false, timestamp = true/false })
+ -- set new modules traces, constraints, ntuple and timestamp options;
2) trace.clear() -- clear modules traces and constraints.
* TraceSwapParams
g_packet_constraints = new_cs;
}
-static inline void set_ntuple(bool log_ntuple)
+static inline void set_logger_options(const TraceConfig* trace_config)
{
if ( g_trace_logger )
- g_trace_logger->set_ntuple(log_ntuple);
+ {
+ g_trace_logger->set_ntuple(trace_config->ntuple);
+ g_trace_logger->set_timestamp(trace_config->timestamp);
+ }
}
void TraceApi::thread_init(const TraceConfig* trace_config)
if ( trace_config->logger_factory )
g_trace_logger = trace_config->logger_factory->instantiate();
- set_ntuple(trace_config->log_ntuple);
+ set_logger_options(trace_config);
update_constraints(trace_config->constraints);
trace_config->setup_module_trace();
}
void TraceApi::thread_reinit(const TraceConfig* trace_config)
{
- set_ntuple(trace_config->log_ntuple);
+ set_logger_options(trace_config);
update_constraints(trace_config->constraints);
trace_config->setup_module_trace();
}
: TraceConfig()
{
traces = other.traces;
- log_ntuple = other.log_ntuple;
+ ntuple = other.ntuple;
+ timestamp = other.timestamp;
if ( other.constraints )
constraints = new PacketConstraints(*other.constraints);
}
public:
snort::TraceLoggerFactory* logger_factory = nullptr;
snort::PacketConstraints* constraints = nullptr;
- bool log_ntuple = false;
+
+ bool ntuple = false;
+ bool timestamp = false;
bool initialized = false;
+
private:
Traces traces;
};
uint8_t log_level, const char* trace_option, const Packet* p) = 0;
void set_ntuple(bool flag)
- { log_ntuple = flag; }
+ { ntuple = flag; }
+
+ void set_timestamp(bool flag)
+ { timestamp = flag; }
protected:
- bool log_ntuple = false;
+ bool ntuple = false;
+ bool timestamp = false;
};
class TraceLoggerFactory
#include "main/thread.h"
#include "protocols/packet.h"
+#include "utils/util.h"
using namespace snort;
// Loggers
//-----------------------------------------------
-static std::string get_ntuple(bool log_ntuple, const Packet* p)
+static std::string get_ntuple(bool ntuple, const Packet* p)
{
- if ( !log_ntuple or !p or !p->has_ip() )
+ if ( !ntuple or !p or !p->has_ip() )
return "";
SfIpString src_addr;
return ss.str();
}
+static std::string get_timestamp(bool timestamp)
+{
+ if ( !timestamp )
+ return "";
+
+ char ts[TIMEBUF_SIZE];
+ ts_print(nullptr, ts);
+
+ return std::string(ts) + ":";
+}
+
// Stdout
class StdoutTraceLogger : public TraceLogger
void StdoutTraceLogger::log(const char* log_msg, const char* name,
uint8_t log_level, const char* trace_option, const Packet* p)
{
- fprintf(file, "%c%u:%s%s:%s:%d: %s", thread_type, instance_id,
- get_ntuple(log_ntuple, p).c_str(), name, trace_option, log_level, log_msg);
+ fprintf(file, "%s%c%u:%s%s:%s:%d: %s", get_timestamp(timestamp).c_str(),
+ thread_type, instance_id, get_ntuple(ntuple, p).c_str(),
+ name, trace_option, log_level, log_msg);
}
// Syslog
void SyslogTraceLogger::log(const char* log_msg, const char* name,
uint8_t log_level, const char* trace_option, const Packet* p)
{
- syslog(priority, "%s%s:%s:%d: %s", get_ntuple(log_ntuple, p).c_str(),
+ syslog(priority, "%s%s:%s:%d: %s", get_ntuple(ntuple, p).c_str(),
name, trace_option, log_level, log_msg);
}
{ "output", Parameter::PT_ENUM, "stdout | syslog", nullptr,
"output method for trace log messages" },
- { "log_ntuple", Parameter::PT_BOOL, nullptr, "false",
- "use extended trace output with n-tuple packet info" },
+ { "ntuple", Parameter::PT_BOOL, nullptr, "false",
+ "print packet n-tuple info with trace messages" },
+
+ { "timestamp", Parameter::PT_BOOL, nullptr, "false",
+ "print message timestamps with trace messages" },
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
}
return true;
}
- else if ( v.is("log_ntuple") )
+ else if ( v.is("ntuple") )
+ {
+ trace_parser->get_trace_config().ntuple = v.get_bool();
+ return true;
+ }
+ else if ( v.is("timestamp") )
{
- trace_parser->get_trace_config().log_ntuple = v.get_bool();
+ trace_parser->get_trace_config().timestamp = v.get_bool();
return true;
}
else if ( strstr(fqn, "trace.modules.") == fqn )
void TraceSwapParams::set_params(const Parameter* params)
{
- const Parameter* ntuple_params = Parameter::find(params, "log_ntuple");
+ const Parameter* ntuple_params = Parameter::find(params, "ntuple");
+ const Parameter* timestamp_params = Parameter::find(params, "timestamp");
const Parameter* modules_params = Parameter::find(params, "modules");
const Parameter* constraints_params = Parameter::find(params, "constraints");
assert(ntuple_params);
+ assert(timestamp_params);
assert(modules_params);
assert(constraints_params);
*ntuple_params,
+ *timestamp_params,
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
static const Command commands[] =
{
- { "set", set, trace_params, "set modules traces, constraints and log_ntuple option" },
+ { "set", set, trace_params,
+ "set modules traces, constraints, ntuple and timestamp options" },
{ "clear", clear, nullptr, "clear modules traces and constraints" },
const Parameter* TraceSwapParams::get_params()
{ return s_params; }
+struct LogParams
+{
+ bool set_traces;
+ bool set_constraints;
+ bool set_ntuple;
+ bool set_timestamp;
+
+ bool is_set() const
+ { return set_traces or set_constraints or set_ntuple or set_timestamp; }
+
+ void print_msg() const
+ {
+ if ( set_traces and set_constraints )
+ LogMessage("== set modules traces and constraints\n");
+ else if ( !is_set() )
+ LogMessage("== clear modules traces and constraints\n");
+ else if ( set_traces )
+ LogMessage("== set modules traces\n");
+ else if ( set_constraints )
+ LogMessage("== set constraints\n");
+
+ if ( set_ntuple )
+ LogMessage("== set ntuple option\n");
+
+ if ( set_timestamp )
+ LogMessage("== set timestamp option\n");
+ }
+};
+
class TraceSwap : public AnalyzerCommand
{
public:
- TraceSwap(TraceConfig* tc, bool set_traces = false, bool set_constraints = false,
- bool set_ntuple = false)
+ TraceSwap(TraceConfig* tc, const LogParams& lp)
: trace_config(tc),
- is_set_ntuple(set_ntuple),
- is_set_traces(set_traces),
- is_set_constraints(set_constraints)
+ log_params(lp)
{ assert(trace_config); }
~TraceSwap() override;
const char* stringify() override
{ return "TRACE_SWAP"; }
-private:
- void print_msg() const;
-
private:
TraceConfig* trace_config = nullptr;
- bool is_set_ntuple;
- bool is_set_traces;
- bool is_set_constraints;
+ LogParams log_params;
};
TraceSwap::~TraceSwap()
TraceApi::thread_reinit(trace_config);
SnortConfig::get_main_conf()->set_overlay_trace_config(trace_config);
- print_msg();
+ log_params.print_msg();
}
bool TraceSwap::execute(Analyzer&, void**)
// Update configuration for packet threads
TraceApi::thread_reinit(trace_config);
- print_msg();
+ log_params.print_msg();
return true;
}
-void TraceSwap::print_msg() const
-{
- if ( is_set_traces and is_set_constraints )
- LogMessage("== set modules traces and constraints\n");
- else if ( !is_set_traces and !is_set_constraints and !is_set_ntuple )
- LogMessage("== clear modules traces and constraints\n");
- else if ( is_set_traces )
- LogMessage("== set modules traces\n");
- else if ( is_set_constraints )
- LogMessage("== set constraints\n");
-
- if ( is_set_ntuple )
- LogMessage("== set log_ntuple option\n");
-}
-
static int set(lua_State* L)
{
const SnortConfig* sc = SnortConfig::get_conf();
TraceConfig* trace_config = new TraceConfig(sc->overlay_trace_config
? *sc->overlay_trace_config : *sc->trace_config);
- TraceParser trace_parser(*trace_config);
-
- const Parameter* params_tree = TraceSwapParams::get_params();
- bool parse_err = false;
- bool set_traces = false;
- bool set_constraints = false;
- bool set_ntuple = false;
-
// Passed Lua entry check
if ( lua_gettop(L) != 1 or !lua_istable(L, 1) )
{
return 0;
}
+ TraceParser trace_parser(*trace_config);
+ const Parameter* params_tree = TraceSwapParams::get_params();
+ LogParams log_params{};
+ bool parse_err = false;
+
// Outer table traversal
lua_pushnil(L);
while ( lua_next(L, 1) )
const char* root_element_key = luaL_checkstring(L, -2);
const Parameter* root_parameter = Parameter::find(params_tree, root_element_key);
- // extended output switcher
+ // log n-tuple
if ( !strcmp(root_element_key, params_tree[2].name) )
{
if ( lua_isboolean(L, -1) and root_parameter )
{
- set_ntuple = true;
- trace_parser.get_trace_config().log_ntuple = bool(lua_toboolean(L, -1));
+ log_params.set_ntuple = true;
+ trace_parser.get_trace_config().ntuple = bool(lua_toboolean(L, -1));
+ }
+ else
+ {
+ LogMessage("== invalid value for option: %s\n", root_element_key);
+ parse_err = true;
+ }
+
+ lua_pop(L, 1);
+ continue;
+ }
+
+ // log time stamp
+ if ( !strcmp(root_element_key, params_tree[3].name) )
+ {
+ if ( lua_isboolean(L, -1) and root_parameter )
+ {
+ log_params.set_timestamp = true;
+ trace_parser.get_trace_config().timestamp = bool(lua_toboolean(L, -1));
}
else
{
- LogMessage("== invalid value is provided: %s\n", root_element_key);
+ LogMessage("== invalid value for option: %s\n", root_element_key);
parse_err = true;
}
// "modules" table traversal
else if ( !strcmp(root_element_key, params_tree[0].name) )
{
- set_traces = true;
+ log_params.set_traces = true;
trace_parser.clear_traces();
const Parameter* modules_param = (const Parameter*)root_parameter->range;
// "constraints" table traversal
else if ( !strcmp(root_element_key, params_tree[1].name) )
{
- set_constraints = true;
+ log_params.set_constraints = true;
trace_parser.clear_constraints();
const Parameter* constraints_param = (const Parameter*)root_parameter->range;
if ( !parse_err )
{
- if ( !set_traces and !set_constraints and !set_ntuple )
+ if ( !log_params.is_set() )
{
trace_parser.clear_traces();
trace_parser.clear_constraints();
}
- if ( set_constraints )
+ if ( log_params.set_constraints )
trace_parser.finalize_constraints();
main_broadcast_command(new TraceSwap(
- &trace_parser.get_trace_config(), set_traces, set_constraints, set_ntuple),
- true);
+ &trace_parser.get_trace_config(), log_params), true);
}
else
delete trace_config;
{
// Create an empty overlay TraceConfig
// It will be set in a SnortConfig during TraceSwap execution and owned by it after
- main_broadcast_command(new TraceSwap(new TraceConfig), true);
+ main_broadcast_command(new TraceSwap(new TraceConfig, {}), true);
return 0;
}