#include "latency/packet_latency.h"
#include "latency/rule_latency.h"
#include "log/messages.h"
-#include "log/packet_tracer.h"
#include "main/modules.h"
#include "main/snort.h"
#include "main/snort_config.h"
#include "main/snort_debug.h"
#include "managers/action_manager.h"
+#include "packet_tracer/packet_tracer.h"
#include "parser/parser.h"
#include "profiler/profiler_defs.h"
#include "protocols/icmp4.h"
if ( EventTrace_IsEnabled() )
EventTrace_Log(p, otn, action);
- PacketTracer::log("Event: %u:%u:%u, Action %s\n",
- otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev,
- Actions::get_string((Actions::Type)action));
-
+ if ( PacketTracer::is_active() )
+ {
+ PacketTracer::log("Event: %u:%u:%u, Action %s\n",
+ otn->sigInfo.gid, otn->sigInfo.sid,
+ otn->sigInfo.rev, Actions::get_string((Actions::Type)action));
+ }
+
// rule option actions are queued here (eg replace)
otn_trigger_actions(otn, p);
log_text.h
messages.h
obfuscator.h
- packet_tracer.h
text_log.h
unified2.h
u2_packet.h
log_text.cc
messages.cc
obfuscator.cc
- packet_tracer.cc
text_log.cc
u2_packet.cc
)
#include "host_tracker/host_cache_module.h"
#include "latency/latency_module.h"
#include "log/messages.h"
-#include "log/packet_tracer.h"
#include "managers/module_manager.h"
#include "managers/plugin_manager.h"
#include "memory/memory_module.h"
#include "packet_io/sfdaq_module.h"
+#include "packet_tracer/packet_tracer_module.h"
#include "parser/config_file.h"
#include "parser/parse_conf.h"
#include "parser/parse_ip.h"
#endif
"output 20 bytes per lines instead of 16 when dumping buffers" },
- { "enable_packet_trace", Parameter::PT_BOOL, nullptr, "false",
- "enable summary output of state that determined packet verdict" },
-
- { "packet_trace_output", Parameter::PT_ENUM, "console | file", "console",
- "select where to send packet trace" },
-
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
Usage get_usage() const override
{ return GLOBAL; }
-
- enum PacketTraceOutput
- {
- PACKET_TRACE_CONSOLE,
- PACKET_TRACE_FILE
- };
};
bool OutputModule::set(const char*, Value& v, SnortConfig* sc)
else if ( v.is("dump_payload_verbose") )
v.update_mask(sc->output_flags, OUTPUT_FLAG__VERBOSE_DUMP);
- else if ( v.is("enable_packet_trace") )
- sc->enable_packet_trace = v.get_bool();
-
- else if ( v.is("packet_trace_output") )
- {
- switch ( v.get_long() )
- {
- case PACKET_TRACE_CONSOLE:
- PacketTracer::set_log_file("-");
- break;
-
- case PACKET_TRACE_FILE:
- PacketTracer::set_log_file("packet_trace.txt");
- break;
-
- default:
- return false;
- }
- }
-
else if ( v.is("quiet") )
v.update_mask(sc->logging_flags, LOGGING_FLAG__QUIET);
ModuleManager::add_module(new CodecModule);
ModuleManager::add_module(new DetectionModule);
ModuleManager::add_module(new MemoryModule);
+ ModuleManager::add_module(new PacketTracerModule);
ModuleManager::add_module(new PacketsModule);
ModuleManager::add_module(new ProcessModule);
ModuleManager::add_module(new ProfilerModule);
#include "latency/rule_latency.h"
#include "log/log.h"
#include "log/messages.h"
-#include "log/packet_tracer.h"
#include "loggers/loggers.h"
#include "main.h"
#include "main/shell.h"
#include "packet_io/active.h"
#include "packet_io/sfdaq.h"
#include "packet_io/trough.h"
+#include "packet_tracer/packet_tracer.h"
#include "parser/cmd_line.h"
#include "parser/parser.h"
#include "profiler/profiler.h"
HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
InspectorManager::thread_init(SnortConfig::get_conf());
PacketTracer::thread_init();
- if (SnortConfig::packet_trace_enabled())
- PacketTracer::enable_user();
-
+
// in case there are HA messages waiting, process them first
HighAvailabilityManager::process_receive();
PacketManager::thread_init();
PacketManager::decode(p, pkthdr, pkt, is_frag);
assert(p->pkth && p->pkt);
- PacketTracer::add_header_info(p);
+ PacketTracer::activate(*p);
if (is_frag)
{
DAQ_Verdict Snort::packet_callback(
void*, const DAQ_PktHdr_t* pkthdr, const uint8_t* pkt)
{
- if (pkthdr->flags & DAQ_PKT_FLAG_TRACE_ENABLED)
- PacketTracer::enable_daq();
- else
- PacketTracer::disable_daq();
-
set_default_policy();
Profile profile(totalPerfStats);
int inject = 0;
verdict = update_verdict(s_packet, verdict, inject);
- PacketTracer::log("NAP id %u, IPS id %u, Verdict %s\n",
- get_network_policy()->policy_id, get_ips_policy()->policy_id,
- SFDAQ::verdict_to_string(verdict));
+ if (PacketTracer::is_active())
+ {
+ PacketTracer::log("NAP id %u, IPS id %u, Verdict %s\n",
+ get_network_policy()->policy_id, get_ips_policy()->policy_id,
+ SFDAQ::verdict_to_string(verdict));
- PacketTracer::dump(pkthdr);
+ PacketTracer::dump(pkthdr);
+ }
HighAvailabilityManager::process_update(s_packet->flow, pkthdr);
uint16_t event_trace_max = 0;
long int tagged_packet_limit = 256;
- bool enable_packet_trace = false;
std::string log_dir;
!get_conf()->chroot_dir.empty();
}
- static bool packet_trace_enabled()
- {
- return get_conf()->enable_packet_trace;
- }
-
bool track_on_syn() const
{ return (run_flags & RUN_FLAG__TRACK_ON_SYN) != 0; }
add_subdirectory(binder)
add_subdirectory(normalize)
add_subdirectory(packet_capture)
+add_subdirectory(packet_tracer)
add_subdirectory(perf_monitor)
add_subdirectory(port_scan)
add_subdirectory(reputation)
$<TARGET_OBJECTS:appid>
$<TARGET_OBJECTS:binder>
$<TARGET_OBJECTS:normalize>
+ $<TARGET_OBJECTS:packet_tracer>
$<TARGET_OBJECTS:port_scan>
$<TARGET_OBJECTS:reputation>
${STATIC_INSPECTOR_OBJS}
#include "flow/flow.h"
#include "log/messages.h"
-#include "log/packet_tracer.h"
#include "managers/inspector_manager.h"
#include "managers/module_manager.h"
+#include "packet_tracer/packet_tracer.h"
#include "profiler/profiler.h"
#include "protocols/packet.h"
payload_app_name = appid_api.get_application_name(payload_id);
misc_name = appid_api.get_application_name(misc_id);
- PacketTracer::log(appid_mute,
- "AppID: service: %s(%d), client: %s(%d), payload: %s(%d), misc: %s(%d)\n",
- (service_app_name ? service_app_name : ""), service_id,
- (client_app_name ? client_app_name : ""), client_id,
- (payload_app_name ? payload_app_name : ""), payload_id,
- (misc_name ? misc_name : ""), misc_id);
+ if (PacketTracer::is_active())
+ {
+ PacketTracer::log(appid_mute,
+ "AppID: service: %s(%d), client: %s(%d), payload: %s(%d), misc: %s(%d)\n",
+ (service_app_name ? service_app_name : ""), service_id,
+ (client_app_name ? client_app_name : ""), client_id,
+ (payload_app_name ? payload_app_name : ""), payload_id,
+ (misc_name ? misc_name : ""), misc_id);
+ }
}
}
void AppIdInspector::eval(Packet* p)
{
Profile profile(appidPerfStats);
-
appid_stats.packets++;
+
if (p->flow)
{
AppIdDiscovery::do_application_discovery(p, *this);
// FIXIT-L tag verdict reason as appid for daq
- if (PacketTracer::active())
+ if (PacketTracer::is_active())
add_appid_to_packet_trace(*p->flow);
}
else
--- /dev/null
+set (PACKET_TRACER_INCLUDES
+ packet_tracer.h
+)
+
+add_library ( packet_tracer OBJECT
+ ${PACKET_TRACER_INCLUDES}
+ packet_tracer.cc
+ packet_tracer_module.h
+ packet_tracer_module.cc
+)
+
+install(FILES ${PACKET_TRACER_INCLUDES}
+ DESTINATION "${INCLUDE_INSTALL_PATH}/network_inspectors/packet_tracer"
+)
\ No newline at end of file
#include <cstdio>
#include <unordered_map>
+#include "log/log.h"
+#include "log/messages.h"
#include "packet_io/sfdaq.h"
#include "protocols/eth.h"
+#include "protocols/icmp4.h"
#include "protocols/ip.h"
#include "protocols/packet.h"
#include "protocols/tcp.h"
-
-#include "log.h"
-#include "messages.h"
+#include "utils/util.h"
#ifdef UNIT_TEST
#include "catch/snort_catch.h"
using namespace snort;
+// -----------------------------------------------------------------------------
+// static variables
+// -----------------------------------------------------------------------------
+
static const uint8_t VERDICT_REASON_NO_BLOCK = 2; /* Not blocking packet; all enum defined after this indicates blocking */
+
+// FIXIT-M currently non-threadsafe accesses being done in packet threads against this
static std::unordered_map<uint8_t, uint8_t> reasons = { {VERDICT_REASON_NO_BLOCK, PacketTracer::PRIORITY_UNSET} };
-
+
// FIXIT-M refactor the way this is used so all methods are members called against this pointer
-static THREAD_LOCAL PacketTracer* s_pkt_trace = nullptr;
+THREAD_LOCAL PacketTracer* snort::s_pkt_trace = nullptr;
// so modules can register regardless of when packet trace is activated
static THREAD_LOCAL struct{ unsigned val = 0; } global_mutes;
static std::string log_file = "-";
+static bool config_status = false;
-PacketTracer::PacketTracer()
-{ reason = VERDICT_REASON_NO_BLOCK; }
+// -----------------------------------------------------------------------------
+// static functions
+// -----------------------------------------------------------------------------
void PacketTracer::register_verdict_reason(uint8_t reason_code, uint8_t priority)
{
assert(reasons.find(reason_code) == reasons.end());
-
reasons[reason_code] = priority;
}
void PacketTracer::set_log_file(std::string file)
{ log_file = file; }
-void PacketTracer::open_file()
-{
- if ( log_file == "-" )
- log_fh = stdout;
- else
- {
- std::string path;
- const char* fname = get_instance_file(path, log_file.c_str());
- log_fh = fopen(fname, "a+");
-
- if ( log_fh == nullptr )
- {
- WarningMessage("Could not open %s for packet trace logging\n", log_file.c_str());
- log_fh = stdout;
- }
- }
-}
-
// template needed for unit tests
template<typename T> void PacketTracer::_thread_init()
{
s_pkt_trace->mutes.resize(global_mutes.val, false);
s_pkt_trace->open_file();
+ s_pkt_trace->user_enabled = config_status;
}
template void PacketTracer::_thread_init<PacketTracer>();
void PacketTracer::thread_init()
{ _thread_init(); }
-PacketTracer::~PacketTracer()
-{
- if ( log_fh && log_fh != stdout )
- {
- fclose(log_fh);
- log_fh = nullptr;
- }
-}
-
void PacketTracer::thread_term()
{
if ( s_pkt_trace )
}
}
-void PacketTracer::dump_to_daq(const DAQ_PktHdr_t* pkt_hdr)
-{
- SFDAQ::get_local_instance()->modify_flow_pkt_trace(pkt_hdr, s_pkt_trace->reason,
- (uint8_t *)s_pkt_trace->buffer, s_pkt_trace->buff_len + 1);
-}
-
-void PacketTracer::reset()
-{
- buff_len = 0;
- buffer[0] = '\0';
- reason = VERDICT_REASON_NO_BLOCK;
-
- for ( unsigned i = 0; i < mutes.size(); i++ )
- mutes[i] = false;
-}
-
void PacketTracer::dump(char* output_buff, unsigned int len)
{
- if (!active())
+ if (is_paused())
return;
if (output_buff)
void PacketTracer::dump(const DAQ_PktHdr_t* pkt_hdr)
{
- if (!active())
+ if (is_paused())
return;
- if (s_pkt_trace->daq_enabled)
+ if (s_pkt_trace->daq_activated)
s_pkt_trace->dump_to_daq(pkt_hdr);
- if (s_pkt_trace->user_enabled)
+ if (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();
void PacketTracer::set_reason(uint8_t reason)
{
- if ( !active() )
- return;
-
if ( reasons[reason] > reasons[s_pkt_trace->reason] )
s_pkt_trace->reason = reason;
}
-void PacketTracer::log(const char* format, va_list ap)
+void PacketTracer::log(const char* format, ...)
{
- if ( !active() )
+ if (is_paused())
return;
- const int buff_space = max_buff_size - s_pkt_trace->buff_len;
- const int len = vsnprintf(s_pkt_trace->buffer + s_pkt_trace->buff_len,
- buff_space, format, ap);
-
- if (len >= 0 and len < buff_space)
- s_pkt_trace->buff_len += len;
- else
- s_pkt_trace->buff_len = max_buff_size - 1;
-}
-
-void PacketTracer::log(const char* format, ...)
-{
va_list ap;
va_start(ap, format);
- log(format, ap);
+ s_pkt_trace->log(format, ap);
va_end(ap);
}
va_list ap;
va_start(ap, format);
- log(format, ap);
+ s_pkt_trace->log(format, ap);
va_end(ap);
s_pkt_trace->mutes[mute] = true;
}
-void PacketTracer::add_header_info(Packet* p)
+bool PacketTracer::is_paused()
+{
+ if ( s_pkt_trace and s_pkt_trace->pause_count )
+ return true;
+ return false;
+}
+
+void PacketTracer::set_constraints(const PTSessionConstraints* constraints)
{
- if (!active())
+ if (!s_pkt_trace)
return;
- if ( auto eh = layer::get_eth_layer(p) )
+ if (!constraints)
{
- // MAC layer
- log("%02X:%02X:%02X:%02X:%02X:%02X -> ", eh->ether_src[0],
- eh->ether_src[1], eh->ether_src[2], eh->ether_src[3],
- eh->ether_src[4], eh->ether_src[5]);
- log("%02X:%02X:%02X:%02X:%02X:%02X ", eh->ether_dst[0],
- eh->ether_dst[1], eh->ether_dst[2], eh->ether_dst[3],
- eh->ether_dst[4], eh->ether_dst[5]);
- // protocol and pkt size
- log("%04X\n", (uint16_t)eh->ethertype());
- }
-
- if (p->ptrs.ip_api.get_src() and p->ptrs.ip_api.get_dst())
- {
- char sipstr[INET6_ADDRSTRLEN], dipstr[INET6_ADDRSTRLEN];
-
- p->ptrs.ip_api.get_src()->ntop(sipstr, sizeof(sipstr));
- p->ptrs.ip_api.get_dst()->ntop(dipstr, sizeof(dipstr));
-
- log("%s:%hu -> %s:%hu proto %u\n",
- sipstr, p->ptrs.sp, dipstr, p->ptrs.dp, (unsigned)p->ptrs.ip_api.proto());
- log("Packet: %s", p->get_type());
- if (p->type() == PktType::TCP)
- {
- char tcpFlags[10];
- CreateTCPFlagString(p->ptrs.tcph, tcpFlags);
- log( " %s, seq %u, ack %u", tcpFlags,
- p->ptrs.tcph->seq(), p->ptrs.tcph->ack());
- }
- log("\n");
+ LogMessage("Debugging packet tracer disabled\n");
+ s_pkt_trace->shell_enabled = false;
}
+ else
+ s_pkt_trace->update_constraints(constraints);
}
-bool PacketTracer::active()
+void PacketTracer::configure(bool status, const std::string& file_name)
{
- if ( !s_pkt_trace )
- return false;
-
- if ( s_pkt_trace->pause_count )
- return false;
- return s_pkt_trace->user_enabled || s_pkt_trace->daq_enabled;
+ log_file = file_name;
+ config_status = status;
}
-void PacketTracer::enable_user()
-{ s_pkt_trace->user_enabled = true; }
-
-void PacketTracer::enable_daq()
-{ s_pkt_trace->daq_enabled = true; }
-
-void PacketTracer::disable_daq()
-{ s_pkt_trace->daq_enabled = false; }
-
void PacketTracer::pause()
{ s_pkt_trace->pause_count++; }
void PacketTracer::unpause()
{
assert(s_pkt_trace->pause_count);
-
s_pkt_trace->pause_count--;
}
return s_pkt_trace->mutes.size() - 1;
}
+void PacketTracer::activate(const Packet& p)
+{
+ if (!s_pkt_trace)
+ return;
+
+ if ( p.pkth->flags & DAQ_PKT_FLAG_TRACE_ENABLED )
+ s_pkt_trace->daq_activated = 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 (!p.ptrs.ip_api.is_ip())
+ {
+ s_pkt_trace->add_eth_header_info(p);
+ s_pkt_trace->add_packet_type_info(p);
+ }
+ else
+ {
+ if (s_pkt_trace->shell_enabled)
+ {
+ uint16_t sport = p.ptrs.sp;
+ uint16_t dport = p.ptrs.dp;
+
+ const SfIp *actual_sip = p.ptrs.ip_api.get_src();
+ const SfIp *actual_dip = p.ptrs.ip_api.get_dst();
+
+ const uint32_t *sip_ptr = actual_sip->get_ip6_ptr();
+ const uint32_t *dip_ptr = actual_dip->get_ip6_ptr();
+
+ IpProtocol proto = p.get_ip_proto_next();
+
+ if (!(s_pkt_trace->info.proto_match(proto) and
+ ((s_pkt_trace->info.port_match(sport, dport) and s_pkt_trace->info.ip_match(sip_ptr, dip_ptr)) or
+ (s_pkt_trace->info.port_match(dport, sport) and s_pkt_trace->info.ip_match(dip_ptr, sip_ptr)))))
+ {
+ s_pkt_trace->active = false;
+ return;
+ }
+ }
+ s_pkt_trace->active = true;
+ s_pkt_trace->add_ip_header_info(p);
+ }
+ }
+ else
+ s_pkt_trace->active = false;
+}
+
+// -----------------------------------------------------------------------------
+// non-static functions
+// -----------------------------------------------------------------------------
+
+// constructor
+PacketTracer::PacketTracer()
+{ reason = VERDICT_REASON_NO_BLOCK; }
+
+// destructor
+PacketTracer::~PacketTracer()
+{
+ if ( log_fh && log_fh != stdout )
+ {
+ fclose(log_fh);
+ log_fh = nullptr;
+ }
+}
+
+void PacketTracer::log(const char* format, va_list ap)
+{
+ // 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
+ {
+ dbg_str = "PktTracerDbg ";
+ if (strcmp(format, "\n") != 0)
+ dbg_str += get_debug_session();
+ dbg_str += format;
+ 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;
+ else
+ buff_len = max_buff_size - 1;
+}
+
+void PacketTracer::add_ip_header_info(const Packet& p)
+{
+ SfIpString sipstr;
+ SfIpString dipstr;
+
+ uint16_t sport = p.ptrs.sp;
+ uint16_t dport = p.ptrs.dp;
+
+ const SfIp* actual_sip = p.ptrs.ip_api.get_src();
+ const SfIp* actual_dip = p.ptrs.ip_api.get_dst();
+
+ IpProtocol proto = p.get_ip_proto_next();
+
+ actual_sip->ntop(sipstr, sizeof(sipstr));
+ actual_dip->ntop(dipstr, sizeof(dipstr));
+
+ if (shell_enabled)
+ {
+ PacketTracer::log("\n");
+ snprintf(debug_session, sizeof(debug_session), "%s %hu -> %s %hu %hhu AS=%hu ID=%u ",
+ sipstr, sport, dipstr, dport, static_cast<uint8_t>(proto),
+ p.pkth->address_space_id, get_instance_id());
+ }
+ else
+ {
+ add_eth_header_info(p);
+ PacketTracer::log("%s:%hu -> %s:%hu proto %u AS=%hu ID=%u\n",
+ sipstr, sport, dipstr, dport, static_cast<uint8_t>(proto),
+ p.pkth->address_space_id, get_instance_id());
+ }
+ add_packet_type_info(p);
+}
+
+void PacketTracer::add_packet_type_info(const Packet& p)
+{
+ bool is_v6 = p.ptrs.ip_api.is_ip6();
+ char timestamp[TIMEBUF_SIZE];
+ ts_print((const struct timeval*)&p.pkth->ts, timestamp);
+
+ switch (p.type())
+ {
+ case PktType::TCP:
+ {
+ char tcpFlags[10];
+ CreateTCPFlagString(p.ptrs.tcph, tcpFlags);
+
+ if (p.ptrs.tcph->th_flags & TH_ACK)
+ PacketTracer::log("Packet: TCP %s, %s, seq %u, ack %u\n", tcpFlags, timestamp,
+ p.ptrs.tcph->seq(), p.ptrs.tcph->ack());
+ else
+ PacketTracer::log("Packet: TCP %s, %s, seq %u\n", tcpFlags, timestamp, p.ptrs.tcph->seq());
+ break;
+ }
+
+ case PktType::ICMP:
+ {
+ const char* icmp_str = is_v6 ? "ICMPv6" : "ICMP";
+
+ PacketTracer::log("Packet: %s, %s, Type: %u Code: %u \n", icmp_str, timestamp,
+ p.ptrs.icmph->type, p.ptrs.icmph->code);
+ break;
+ }
+
+ default:
+ PacketTracer::log("Packet: %s, %s\n", p.get_type(), timestamp);
+ break;
+ }
+}
+
+void PacketTracer::add_eth_header_info(const Packet& p)
+{
+ auto eh = layer::get_eth_layer(&p);
+ if (!(shell_enabled) && eh )
+ {
+ // MAC layer
+ PacketTracer::log("%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X\n",
+ eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
+ eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
+ eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
+ eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
+ (uint16_t)eh->ethertype());
+ }
+}
+
+void PacketTracer::update_constraints(const PTSessionConstraints* constraints)
+{
+
+ char sipstr[INET6_ADDRSTRLEN];
+ char dipstr[INET6_ADDRSTRLEN];
+
+ info.set(*constraints);
+ info.sip.ntop(sipstr, sizeof(sipstr));
+ info.dip.ntop(dipstr, sizeof(dipstr));
+ LogMessage("Debugging packet tracer with %s-%hu and %s-%hu %hhu\n",
+ sipstr, info.sport, dipstr, info.dport, static_cast<uint8_t>(info.protocol));
+
+ shell_enabled = true;
+
+}
+
+void PacketTracer::open_file()
+{
+ if ( log_file == "-" )
+ log_fh = stdout;
+ else
+ {
+ std::string path;
+ const char* fname = get_instance_file(path, log_file.c_str());
+ log_fh = fopen(fname, "a+");
+
+ if ( log_fh == nullptr )
+ {
+ WarningMessage("Could not open %s for packet trace logging\n", log_file.c_str());
+ log_fh = stdout;
+ }
+ }
+}
+
+void PacketTracer::dump_to_daq(const DAQ_PktHdr_t* pkt_hdr)
+{
+ SFDAQ::get_local_instance()->modify_flow_pkt_trace(pkt_hdr, reason,
+ (uint8_t *)buffer, buff_len + 1);
+}
+
+void PacketTracer::reset()
+{
+ buff_len = 0;
+ buffer[0] = '\0';
+ reason = VERDICT_REASON_NO_BLOCK;
+
+ for ( unsigned i = 0; i < mutes.size(); i++ )
+ mutes[i] = false;
+}
+
+// --------------------------------------------------------------------------
+// unit tests
+// --------------------------------------------------------------------------
+
#ifdef UNIT_TEST
#include <fcntl.h>
#include <unistd.h>
static unsigned int get_buff_len()
{ return ((TestPacketTracer*)s_pkt_trace)->buff_len; }
+ static void set_user_enable(bool status)
+ { ((TestPacketTracer*)s_pkt_trace)->user_enabled = status; }
+
static bool is_user_enabled()
{ return ((TestPacketTracer*)s_pkt_trace)->user_enabled; }
+ static void set_daq_enable(bool status)
+ { ((TestPacketTracer*)s_pkt_trace)->daq_activated = status; }
+
static bool is_daq_enabled()
- { return ((TestPacketTracer*)s_pkt_trace)->daq_enabled; }
+ { return ((TestPacketTracer*)s_pkt_trace)->daq_activated; }
static bool is_paused()
{ return ((TestPacketTracer*)s_pkt_trace)->pause_count; }
char test_str[] = "1234567890";
// instantiate a packet tracer
TestPacketTracer::thread_init();
- TestPacketTracer::enable_user();
+ TestPacketTracer::set_user_enable(true);
// basic logging
TestPacketTracer::log("%s", test_str);
CHECK(!(strcmp(TestPacketTracer::get_buff(), test_str)));
{
char test_str[] = "1234567890", empty_str[] = "";
TestPacketTracer::thread_init();
- TestPacketTracer::enable_user();
+ TestPacketTracer::set_user_enable(true);
// init length check
CHECK((TestPacketTracer::get_buff_len() == 0));
// logging empty string to start with
char test_str[] = "ABCD", results[] = "ABCD3=400";
TestPacketTracer::thread_init();
- TestPacketTracer::enable_user();
+ TestPacketTracer::set_user_enable(true);
TestPacketTracer::log("%s%d=%d", test_str, 3, 400);
TestPacketTracer::dump(test_string, TestPacketTracer::max_buff_size);
CHECK(!strcmp(test_string, results));
{
TestPacketTracer::thread_init();
// packet tracer is disabled by default
- CHECK(!TestPacketTracer::active());
+ CHECK(!TestPacketTracer::is_active());
// enabled from user
- TestPacketTracer::enable_user();
- CHECK(TestPacketTracer::active());
+ TestPacketTracer::set_user_enable(true);
CHECK(TestPacketTracer::is_user_enabled());
CHECK(!TestPacketTracer::is_daq_enabled());
// enabled from DAQ
- TestPacketTracer::enable_daq();
- CHECK(TestPacketTracer::active());
+ TestPacketTracer::set_daq_enable(true);
CHECK(TestPacketTracer::is_daq_enabled());
// disable DAQ enable
- TestPacketTracer::disable_daq();
+ TestPacketTracer::set_daq_enable(false);
CHECK(!TestPacketTracer::is_daq_enabled());
// user configuration remain enabled
- CHECK(TestPacketTracer::active());
CHECK(TestPacketTracer::is_user_enabled());
TestPacketTracer::thread_term();
char test_str[] = "1234567890";
TestPacketTracer::thread_init();
- TestPacketTracer::enable_user();
+ TestPacketTracer::set_user_enable(true);
TestPacketTracer::pause();
TestPacketTracer::pause();
TestPacketTracer::pause();
TEST_CASE("reasons", "[PacketTracer]")
{
TestPacketTracer::thread_init();
- TestPacketTracer::enable_daq();
+ TestPacketTracer::set_daq_enable(true);
uint8_t low1 = 100, low2 = 101, high = 102;
TestPacketTracer::register_verdict_reason(low1, PacketTracer::PRIORITY_LOW);
TestPacketTracer::register_verdict_reason(low2, PacketTracer::PRIORITY_LOW);
TEST_CASE("verbosity", "[PacketTracer]")
{
TestPacketTracer::thread_init();
- TestPacketTracer::enable_user();
+ TestPacketTracer::set_user_enable(true);
PacketTracer::TracerMute mute_1 = TestPacketTracer::get_mute();
PacketTracer::TracerMute mute_2 = TestPacketTracer::get_mute();
#include <cstdarg>
#include <cstdio>
+#include <cstring>
#include <daq_common.h>
-#include <string>
#include <vector>
#include "main/snort_types.h"
+#include "main/thread.h"
+#include "protocols/ipv6.h"
+#include "protocols/protocol_ids.h"
+#include "sfip/sf_ip.h"
+
+// %s %u -> %s %u %u AS=%u ID=%u
+// IPv6 Port -> IPv6 Port Proto AS=ASNum ID=InstanceNum
+#define PT_DEBUG_SESSION_ID_SIZE ((39+1+5+1+2+1+39+1+5+1+3+1+2+1+10+1+2+1+10)+1)
+
+struct PTSessionConstraints
+{
+ snort::SfIp sip;
+ int sip_flag = 0;
+ snort::SfIp dip;
+ int dip_flag = 0;
+ uint16_t sport;
+ uint16_t dport;
+ IpProtocol protocol = IpProtocol::PROTO_NOT_SET;
+
+ bool proto_match(IpProtocol& proto)
+ {
+ return (protocol == IpProtocol::PROTO_NOT_SET or protocol == proto);
+ }
+ bool port_match(uint16_t p1, uint16_t p2)
+ {
+ return (!sport or sport == p1) and (!dport or dport == p2);
+ }
+ bool ip_match(const uint32_t* ip1, const uint32_t* ip2)
+ {
+ return
+ ((!sip_flag or !memcmp(sip.get_ip6_ptr(), ip1, sizeof(snort::ip::snort_in6_addr))) and
+ (!dip_flag or !memcmp(dip.get_ip6_ptr(), ip2, sizeof(snort::ip::snort_in6_addr))));
+ }
+
+ void set(const PTSessionConstraints& src);
+};
+
+inline void PTSessionConstraints::set(const PTSessionConstraints& src)
+{
+ if ((sip_flag = src.sip_flag))
+ sip.set(src.sip);
+ if ((dip_flag = src.dip_flag))
+ dip.set(src.dip);
+ sport = src.sport;
+ dport = src.dport;
+ protocol = src.protocol;
+}
namespace snort
{
struct Packet;
+
class PacketTracer
{
public:
virtual ~PacketTracer();
typedef uint8_t TracerMute;
-
static const int max_buff_size = 2048;
+ // static functions
static void set_log_file(std::string);
static void thread_init();
static void thread_term();
static void dump(char* output_buff, unsigned int len);
static void dump(const DAQ_PktHdr_t*);
- static void add_header_info(Packet* p);
-
- static void enable_user();
- static void enable_daq();
- static void disable_daq();
-
- static SO_PUBLIC bool active();
-
+ static void configure(bool status, const std::string& file_name);
+ static void set_constraints(const PTSessionConstraints* constraints);
+ static void activate(const snort::Packet&);
+
static SO_PUBLIC void pause();
static SO_PUBLIC void unpause();
-
+ static SO_PUBLIC bool is_paused();
+ static SO_PUBLIC bool is_active();
+
static SO_PUBLIC TracerMute get_mute();
static SO_PUBLIC void register_verdict_reason(uint8_t reason_code, uint8_t priority);
static SO_PUBLIC void log(TracerMute, const char* format, ...) __attribute__((format (printf, 2, 3)));
protected:
+
+
+ // non-static variable
FILE* log_fh = stdout;
std::vector<bool> mutes;
char buffer[max_buff_size];
unsigned pause_count = 0;
bool user_enabled = false;
- bool daq_enabled = false;
+ bool daq_activated = false;
+ bool shell_enabled = false;
+ bool active = false;
+
+ char debug_session[PT_DEBUG_SESSION_ID_SIZE];
+ PTSessionConstraints info;
+
+ // static functions
+ template<typename T = PacketTracer> static void _thread_init();
+
+ // non-static functions
+ void log(const char*, va_list);
+ void add_ip_header_info(const snort::Packet&);
+ void add_eth_header_info(const snort::Packet&);
+ void add_packet_type_info(const snort::Packet&);
+ void update_constraints(const PTSessionConstraints* constraints);
+ const char *get_debug_session() { return debug_session; }
virtual void open_file();
virtual void dump_to_daq(const DAQ_PktHdr_t*);
virtual void reset();
- static void log(const char*, va_list);
- template<typename T = PacketTracer> static void _thread_init();
};
-}
+SO_PUBLIC extern THREAD_LOCAL PacketTracer* s_pkt_trace;
+
+inline bool PacketTracer::is_active()
+{ return s_pkt_trace ? s_pkt_trace->active : false; }
+
+}
+
#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// packet_tracer_module.cc author Shashikant Lad <shaslad@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <lua.hpp>
+
+#include "packet_tracer_module.h"
+
+#include "main/snort_config.h"
+#include "profiler/profiler.h"
+#include "main/analyzer_command.h"
+#include "log/messages.h"
+#include "sfip/sf_ip.h"
+
+#include "packet_tracer.h"
+
+using namespace snort;
+
+static int enable(lua_State*);
+static int disable(lua_State*);
+
+static const Parameter s_params[] =
+{
+ {"enable", Parameter::PT_BOOL, nullptr, "false",
+ "enable summary output of state that determined packet verdict"},
+
+ {"output", Parameter::PT_ENUM, "console | file", "console",
+ "select where to send packet trace"},
+
+ {nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr}
+};
+
+static const Parameter enable_packet_tracer_params[] =
+{
+ {"proto", Parameter::PT_INT, nullptr, nullptr, "numerical IP protocol ID filter"},
+ {"src_ip", Parameter::PT_STRING, nullptr, nullptr, "source IP address filter"},
+ {"src_port", Parameter::PT_INT, nullptr, nullptr, "source port filter"},
+ {"dst_ip", Parameter::PT_STRING, nullptr, nullptr, "destination IP address filter"},
+ {"dst_port", Parameter::PT_INT, nullptr, nullptr, "destination port filter"},
+ {nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr}
+};
+
+static const Command packet_tracer_cmds[] =
+{
+ {"enable", enable, enable_packet_tracer_params, "enable packet tracer debugging"},
+ {"disable", disable, nullptr, "disable packet tracer"},
+ {nullptr, nullptr, nullptr, nullptr}
+};
+
+class PacketTracerDebug : public AnalyzerCommand
+{
+ public:
+ PacketTracerDebug(PTSessionConstraints *cs);
+ void execute(Analyzer &) override;
+ const char *stringify() override { return "PACKET_TRACER_DEBUG"; }
+
+ private:
+ PTSessionConstraints constraints = {};
+ bool enable = false;
+};
+
+PacketTracerDebug::PacketTracerDebug(PTSessionConstraints *cs)
+{
+ if (cs)
+ {
+ memcpy(&constraints, cs, sizeof(constraints));
+ enable = true;
+ }
+}
+
+void PacketTracerDebug::execute(Analyzer &)
+{
+ if (enable)
+ PacketTracer::set_constraints(&constraints);
+ else
+ PacketTracer::set_constraints(nullptr);
+}
+
+static int enable(lua_State* L)
+{
+ int proto = luaL_optint(L, 1, 0);
+ const char *sipstr = luaL_optstring(L, 2, nullptr);
+ int sport = luaL_optint(L, 3, 0);
+ const char *dipstr = luaL_optstring(L, 4, nullptr);
+ int dport = luaL_optint(L, 5, 0);
+
+ SfIp sip, dip;
+ if (sipstr)
+ {
+ if (sip.set(sipstr) != SFIP_SUCCESS)
+ LogMessage("Invalid source IP address provided: %s\n", sipstr);
+ }
+
+ if (dipstr)
+ {
+ if (dip.set(dipstr) != SFIP_SUCCESS)
+ LogMessage("Invalid destination IP address provided: %s\n", dipstr);
+ }
+
+ PTSessionConstraints constraints = {};
+
+ if (proto)
+ constraints.protocol = (IpProtocol)proto;
+
+ if (sip.is_set())
+ {
+ memcpy(&constraints.sip, sip.get_ip6_ptr(), sizeof(constraints.sip));
+ constraints.sip_flag = true;
+ }
+
+ if (dip.is_set())
+ {
+ memcpy(&constraints.dip, dip.get_ip6_ptr(), sizeof(constraints.dip));
+ constraints.dip_flag = true;
+ }
+
+ constraints.sport = sport;
+ constraints.dport = dport;
+
+ main_broadcast_command(new PacketTracerDebug(&constraints));
+ return 0;
+}
+
+static int disable(lua_State*)
+{
+ main_broadcast_command(new PacketTracerDebug(nullptr));
+ return 0;
+}
+
+PacketTracerModule::PacketTracerModule() :
+ Module(PACKET_TRACER_NAME, PACKET_TRACER_HELP, s_params)
+{
+}
+
+
+bool PacketTracerModule::set(const char *, Value &v, SnortConfig*)
+{
+ if ( v.is("enable") )
+ config->enabled = v.get_bool();
+
+ else if ( v.is("output") )
+ {
+ switch ( v.get_long() )
+ {
+ case PACKET_TRACE_CONSOLE:
+ config->file = "-";
+ break;
+
+ case PACKET_TRACE_FILE:
+ config->file = "packet_trace.txt";
+ break;
+
+ default:
+ return false;
+ }
+ }
+ else
+ return false;
+
+ return true;
+}
+
+const Command *PacketTracerModule::get_commands() const
+{
+ return packet_tracer_cmds;
+}
+
+bool PacketTracerModule::begin(const char*, int, SnortConfig*)
+{
+ assert(!config);
+ config = new PacketTracerConfig;
+ return true;
+}
+bool PacketTracerModule::end(const char*, int, SnortConfig*)
+{
+ if (config != nullptr)
+ {
+ PacketTracer::configure(config->enabled, config->file);
+ delete config;
+ config = nullptr;
+ }
+ return true;
+}
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2018-2018 Cisco and/or its affiliates. All rights reserved.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License Version 2 as published
+// by the Free Software Foundation. You may not use, modify or distribute
+// this program under any other version of the GNU General Public License.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//--------------------------------------------------------------------------
+
+// packet_tracer_module.h author Shashikant Lad <shaslad@cisco.com>
+
+#ifndef PACKET_TRACER_MODULE_H
+#define PACKET_TRACER_MODULE_H
+
+#include "framework/module.h"
+
+#define PACKET_TRACER_NAME "packet_tracer"
+#define PACKET_TRACER_HELP "generate debug trace messages for packets"
+
+struct PacketTracerConfig
+{
+ bool enabled;
+ std::string file;
+};
+
+class PacketTracerModule : public snort::Module
+{
+public:
+ PacketTracerModule();
+
+
+ enum PacketTraceOutput
+ {
+ PACKET_TRACE_CONSOLE,
+ PACKET_TRACE_FILE
+ };
+
+ const snort::Command* get_commands() const override;
+ bool begin(const char*, int, snort::SnortConfig*) override;
+ bool set(const char*, snort::Value&, snort::SnortConfig*) override;
+ bool end(const char*, int, snort::SnortConfig*) override;
+
+ Usage get_usage() const override
+ { return GLOBAL; }
+
+private:
+ PacketTracerConfig* config = nullptr;
+};
+
+#endif