// FIXIT-M refactor the way this is used so all methods are members called against this pointer
THREAD_LOCAL PacketTracer* snort::s_pkt_trace = nullptr;
+THREAD_LOCAL Stopwatch<SnortClock>* snort::pt_timer = nullptr;
+
// so modules can register regardless of when packet trace is activated
static THREAD_LOCAL struct{ unsigned val = 0; } global_mutes;
if ( s_pkt_trace == nullptr )
s_pkt_trace = new T();
+ if ( pt_timer == nullptr )
+ pt_timer = new Stopwatch<SnortClock>;
+
s_pkt_trace->mutes.resize(global_mutes.val, false);
s_pkt_trace->open_file();
s_pkt_trace->user_enabled = config_status;
delete s_pkt_trace;
s_pkt_trace = nullptr;
}
+
+ if (pt_timer)
+ {
+ delete pt_timer;
+ pt_timer = nullptr;
+ }
}
void PacketTracer::dump(char* output_buff, unsigned int len)
memcpy(output_buff, s_pkt_trace->buffer,
(len < s_pkt_trace->buff_len + 1 ? len : s_pkt_trace->buff_len + 1));
- s_pkt_trace->reset();
+ s_pkt_trace->reset(false);
}
void PacketTracer::dump(Packet* p)
if (is_paused())
return;
- if (s_pkt_trace->daq_activated)
- s_pkt_trace->dump_to_daq(p);
-
if ((s_pkt_trace->buff_len > 0)
and (s_pkt_trace->user_enabled or s_pkt_trace->shell_enabled))
{
LogMessage(s_pkt_trace->log_fh, "%s\n", s_pkt_trace->buffer);
}
- s_pkt_trace->reset();
+ s_pkt_trace->reset(false);
+}
+
+void PacketTracer::daq_dump(Packet *p)
+{
+ if (is_paused())
+ return;
+
+ if (s_pkt_trace->daq_activated)
+ s_pkt_trace->dump_to_daq(p);
+
+ s_pkt_trace->reset(true);
+}
+
+void PacketTracer::daq_log(const char* format, ...)
+{
+ if (is_paused())
+ return;
+
+ va_list ap;
+ va_start(ap, format);
+ s_pkt_trace->log_va(format, ap, true);
+ va_end(ap);
}
void PacketTracer::log(const char* format, ...)
va_list ap;
va_start(ap, format);
- s_pkt_trace->log_va(format, ap);
+ s_pkt_trace->log_va(format, ap, false);
va_end(ap);
}
va_list ap;
va_start(ap, format);
- s_pkt_trace->log_va(format, ap);
+ s_pkt_trace->log_va(format, ap, false);
va_end(ap);
s_pkt_trace->mutes[mute] = true;
else
s_pkt_trace->daq_activated = false;
- if (s_pkt_trace->daq_activated or s_pkt_trace->user_enabled or s_pkt_trace->shell_enabled)
+ if (s_pkt_trace->user_enabled or s_pkt_trace->shell_enabled)
{
if (!p.ptrs.ip_api.is_ip())
{
s_pkt_trace->active = false;
}
+void PacketTracer::pt_timer_start()
+{
+ pt_timer->reset();
+ pt_timer->start();
+}
+
// -----------------------------------------------------------------------------
// non-static functions
// -----------------------------------------------------------------------------
}
}
-void PacketTracer::log_va(const char* format, va_list ap)
+void PacketTracer::populate_buf(const char* format, va_list ap, char* buffer, uint32_t& buff_len)
+{
+ const int buff_space = max_buff_size - buff_len;
+ const int len = vsnprintf(buffer + buff_len, buff_space, format, ap);
+
+ if (len >= 0 and len < buff_space)
+ buff_len += len;
+ else
+ buff_len = max_buff_size - 1;
+}
+
+void PacketTracer::log_va(const char* format, va_list ap, bool daq_log)
{
// FIXIT-L Need to find way to add 'PktTracerDbg' string as part of format string.
std::string dbg_str;
- if (shell_enabled) // only add debug string during shell execution
+ if (shell_enabled and !daq_log) // only add debug string during shell execution
{
dbg_str = "PktTracerDbg ";
if (strcmp(format, "\n") != 0)
format = dbg_str.c_str();
}
- const int buff_space = max_buff_size - buff_len;
- const int len = vsnprintf(buffer + buff_len, buff_space, format, ap);
-
- if (len >= 0 and len < buff_space)
- buff_len += len;
+ if (daq_log)
+ s_pkt_trace->populate_buf(format, ap, daq_buffer, daq_buff_len);
else
- buff_len = max_buff_size - 1;
+ s_pkt_trace->populate_buf(format, ap, buffer, buff_len);
}
void PacketTracer::add_ip_header_info(const Packet& p)
void PacketTracer::dump_to_daq(Packet* p)
{
assert(p);
- p->daq_instance->set_packet_trace_data(p->daq_msg, (uint8_t *)buffer, buff_len + 1);
+ p->daq_instance->set_packet_trace_data(p->daq_msg, (uint8_t *)daq_buffer, daq_buff_len + 1);
}
-void PacketTracer::reset()
+void PacketTracer::reset(bool daq_log)
{
- buff_len = 0;
- buffer[0] = '\0';
+ if ( daq_log )
+ {
+ daq_buff_len = 0;
+ daq_buffer[0] = '\0';
+ }
+ else
+ {
+ buff_len = 0;
+ buffer[0] = '\0';
- for ( unsigned i = 0; i < mutes.size(); i++ )
- mutes[i] = false;
+ for ( unsigned i = 0; i < mutes.size(); i++ )
+ mutes[i] = false;
+ }
}
+
// --------------------------------------------------------------------------
// unit tests
// --------------------------------------------------------------------------
static unsigned int get_buff_len()
{ return ((TestPacketTracer*)s_pkt_trace)->buff_len; }
+ static char* get_daq_buff()
+ { return ((TestPacketTracer*)s_pkt_trace)->daq_buffer; }
+
+ static unsigned int get_daq_buff_len()
+ { return ((TestPacketTracer*)s_pkt_trace)->daq_buff_len; }
+
static void set_user_enable(bool status)
{ ((TestPacketTracer*)s_pkt_trace)->user_enabled = status; }
TestPacketTracer::thread_term();
}
+TEST_CASE("basic daq log", "[PacketTracer]")
+{
+ char test_str[] = "1234567890";
+ // instantiate a packet tracer
+ TestPacketTracer::thread_init();
+ TestPacketTracer::pt_timer_start();
+ TestPacketTracer::set_daq_enable(true);
+ TestPacketTracer::daq_log("%s", test_str);
+ CHECK(!(strcmp(TestPacketTracer::get_daq_buff(), test_str)));
+ CHECK((TestPacketTracer::get_daq_buff_len() == 10));
+ TestPacketTracer::daq_log("%s", "ABCDEFG");
+ CHECK((strcmp(TestPacketTracer::get_daq_buff(), "1234567890ABCDEFG") == 0));
+ CHECK((TestPacketTracer::get_daq_buff_len() == strlen(TestPacketTracer::get_daq_buff())));
+
+ // log empty string won't change existed buffer
+ unsigned int curr_len = TestPacketTracer::get_daq_buff_len();
+ char empty_str[] = "";
+ TestPacketTracer::daq_log("%s", empty_str);
+ CHECK((TestPacketTracer::get_daq_buff_len() == curr_len));
+
+ TestPacketTracer::thread_term();
+}
+
TEST_CASE("corner cases", "[PacketTracer]")
{
char test_str[] = "1234567890", empty_str[] = "";
TestPacketTracer::thread_init();
TestPacketTracer::set_user_enable(true);
+ TestPacketTracer::set_daq_enable(true);
// init length check
CHECK((TestPacketTracer::get_buff_len() == 0));
+ CHECK((TestPacketTracer::get_daq_buff_len() == 0));
// logging empty string to start with
TestPacketTracer::log("%s", empty_str);
CHECK((TestPacketTracer::get_buff_len() == 0));
+ TestPacketTracer::daq_log("%s", empty_str);
+ CHECK((TestPacketTracer::get_daq_buff_len() == 0));
// log messages larger than buffer size
for(int i=0; i<1024; i++)
+ {
TestPacketTracer::log("%s", test_str);
+ TestPacketTracer::daq_log("%s", test_str);
+ }
// when buffer limit is reached, buffer length will stopped at max_buff_size-1
CHECK((TestPacketTracer::get_buff_len() == (TestPacketTracer::max_buff_size-1)));
+ CHECK((TestPacketTracer::get_daq_buff_len() == (TestPacketTracer::max_buff_size-1)));
// continue logging will not change anything
TestPacketTracer::log("%s", test_str);
CHECK((TestPacketTracer::get_buff_len() == (TestPacketTracer::max_buff_size-1)));
+ TestPacketTracer::daq_log("%s", test_str);
+ CHECK((TestPacketTracer::get_daq_buff_len() == (TestPacketTracer::max_buff_size-1)));
TestPacketTracer::thread_term();
}
#include "protocols/ipv6.h"
#include "protocols/protocol_ids.h"
#include "sfip/sf_ip.h"
+#include "time/clock_defs.h"
+#include "time/stopwatch.h"
// %s %u -> %s %u %u AS=%u ID=%u GR=%hd-%hd
// IPv6 Port -> IPv6 Port Proto AS=ASNum ID=InstanceNum GR=SrcGroupNum-DstGroupNum
static void dump(char* output_buff, unsigned int len);
static void dump(Packet*);
+ static void daq_dump(Packet*);
static void configure(bool status, const std::string& file_name);
static void set_constraints(const PacketConstraints* constraints);
static SO_PUBLIC void unpause();
static SO_PUBLIC bool is_paused();
static SO_PUBLIC bool is_active();
+ static SO_PUBLIC bool is_daq_activated();
static SO_PUBLIC TracerMute get_mute();
static SO_PUBLIC void log(const char* format, ...) __attribute__((format (printf, 1, 2)));
static SO_PUBLIC void log(TracerMute, const char* format, ...) __attribute__((format (printf, 2, 3)));
+ static SO_PUBLIC void daq_log(const char* format, ...) __attribute__((format (printf, 1, 2)));
+ static SO_PUBLIC void pt_timer_start();
+
protected:
std::vector<bool> mutes;
char buffer[max_buff_size];
unsigned buff_len = 0;
+ char daq_buffer[max_buff_size];
+ unsigned daq_buff_len = 0;
unsigned pause_count = 0;
bool user_enabled = false;
template<typename T = PacketTracer> static void _thread_init();
// non-static functions
- void log_va(const char*, va_list);
+ void log_va(const char*, va_list, bool);
+ void populate_buf(const char*, va_list, char*, uint32_t&);
void add_ip_header_info(const snort::Packet&);
void add_eth_header_info(const snort::Packet&);
void add_packet_type_info(const snort::Packet&);
virtual void open_file();
virtual void dump_to_daq(Packet*);
- virtual void reset();
-
+ virtual void reset(bool);
};
SO_PUBLIC extern THREAD_LOCAL PacketTracer* s_pkt_trace;
+SO_PUBLIC extern THREAD_LOCAL Stopwatch<SnortClock>* pt_timer;
inline bool PacketTracer::is_active()
{ return s_pkt_trace ? s_pkt_trace->active : false; }
+inline bool PacketTracer::is_daq_activated()
+{ return s_pkt_trace ? s_pkt_trace->daq_activated : false; }
+
struct SO_PUBLIC PacketTracerSuspend
{
PacketTracerSuspend()