#include "latency/packet_latency.h"
#include "latency/rule_latency.h"
#include "log/messages.h"
+#include "log/packet_tracer.h"
#include "main/snort.h"
#include "main/snort_config.h"
#include "main/snort_debug.h"
if ( EventTrace_IsEnabled() )
EventTrace_Log(p, otn, action);
+ PacketTracer::log("Event: %d:%d:%d, Action %s\n",
+ otn->sigInfo.gid, otn->sigInfo.sid, otn->sigInfo.rev,
+ get_action_string((RuleType)action));
+
// rule option actions are queued here (eg replace)
otn_trigger_actions(otn, p);
messages.cc
obfuscator.cc
obfuscator.h
+ packet_tracer.cc
+ packet_tracer.h
text_log.cc
)
messages.cc \
obfuscator.cc \
obfuscator.h \
+packet_tracer.cc \
+packet_tracer.h \
text_log.cc
if ENABLE_UNIT_TESTS
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 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.
+//--------------------------------------------------------------------------
+
+// pkt_tracer.cc author Steven Baigal <sbaigal@cisco.com>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "packet_tracer.h"
+
+#include <cstdarg>
+
+#include "log.h"
+#include "protocols/eth.h"
+#include "protocols/ip.h"
+#include "protocols/packet.h"
+#include "protocols/tcp.h"
+
+#ifdef UNIT_TEST
+#include "catch/catch.hpp"
+#endif
+
+static THREAD_LOCAL PacketTracer* s_pkt_trace = nullptr;
+
+void PacketTracer::thread_init()
+{
+ if (s_pkt_trace == nullptr)
+ {
+ s_pkt_trace = new PacketTracer();
+ }
+}
+
+void PacketTracer::thread_term()
+{
+ if (s_pkt_trace)
+ {
+ delete s_pkt_trace;
+ s_pkt_trace = nullptr;
+ }
+}
+
+void PacketTracer::dump(char* output_buff, unsigned int len)
+{
+ if (!s_pkt_trace)
+ return;
+ if (output_buff)
+ {
+ memcpy(output_buff, s_pkt_trace->buffer,
+ (len < s_pkt_trace->buff_len + 1 ? len : s_pkt_trace->buff_len + 1));
+ }
+ else
+ printf("%s\n", s_pkt_trace->buffer);
+
+ s_pkt_trace->buff_len = 0;
+ s_pkt_trace->buffer[0] = '\0';
+}
+
+void PacketTracer::log(const char* format, ...)
+{
+ if (!s_pkt_trace)
+ return;
+
+ va_list ap;
+
+ va_start(ap, format);
+ 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);
+ va_end(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::add_header_info(Packet* p)
+{
+ if (!s_pkt_trace)
+ return;
+
+ if ( auto eh = layer::get_eth_layer(p) )
+ {
+ // 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_src())
+ {
+ 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-%u - %s-%u %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");
+ }
+}
+
+#ifdef UNIT_TEST
+
+char* PacketTracer::get_buff()
+{
+ return this->buffer;
+}
+
+int PacketTracer::get_buff_len()
+{
+ return this->buff_len;
+}
+
+#define MAX_PKT_TRACE_BUFF_SIZE 2048
+
+TEST_CASE("basic log", "[PacketTracer]")
+{
+ char test_str[] = "1234567890";
+ // instantiate a packet tracer
+ PacketTracer::thread_init();
+
+ // basic logging
+ PacketTracer::log("%s", test_str);
+ CHECK((memcmp(s_pkt_trace->get_buff(), test_str, 10) == 0));
+ CHECK((s_pkt_trace->get_buff_len() == 10));
+ // continue log will add message to the buffer
+ PacketTracer::log("%s", "ABCDEFG");
+ CHECK((strcmp(s_pkt_trace->get_buff(), "1234567890ABCDEFG") == 0));
+ CHECK((s_pkt_trace->get_buff_len() == (int)strlen(s_pkt_trace->get_buff())));
+ // log empty string won't change existed buffer
+ int curr_len = s_pkt_trace->get_buff_len();
+ char empty_str[] = "";
+ PacketTracer::log("%s", empty_str);
+ CHECK((s_pkt_trace->get_buff_len() == curr_len));
+
+ PacketTracer::thread_term();
+}
+
+TEST_CASE("corner cases", "[PacketTracer]")
+{
+ char test_str[] = "1234567890", empty_str[] = "";
+ PacketTracer::thread_init();
+
+ // init length check
+ CHECK((s_pkt_trace->get_buff_len() == 0));
+ // logging empty string to start with
+ PacketTracer::log("%s", empty_str);
+ CHECK((s_pkt_trace->get_buff_len() == 0));
+
+ // log messages larger than buffer size
+ for(int i=0; i<1024; i++)
+ PacketTracer::log("%s", test_str);
+ // when buffer limit is reached, buffer length will stoppped at max_buff_size-1
+ CHECK((s_pkt_trace->get_buff_len() == (MAX_PKT_TRACE_BUFF_SIZE-1)));
+
+ // continue logging will not change anything
+ PacketTracer::log("%s", test_str);
+ CHECK((s_pkt_trace->get_buff_len() == (MAX_PKT_TRACE_BUFF_SIZE-1)));
+
+ PacketTracer::thread_term();
+}
+
+TEST_CASE("dump", "[PacketTracer]")
+{
+ char test_string[MAX_PKT_TRACE_BUFF_SIZE];
+ char test_str[] = "ABCD", results[] = "ABCD3=400";
+
+ PacketTracer::thread_init();
+
+ PacketTracer::log("%s%d=%d", test_str, 3, 400);
+ PacketTracer::dump(test_string, MAX_PKT_TRACE_BUFF_SIZE);
+ CHECK(!strcmp(test_string, results));
+ CHECK((s_pkt_trace->get_buff_len() == 0));
+
+ // dump again
+ PacketTracer::dump(test_string, MAX_PKT_TRACE_BUFF_SIZE);
+ CHECK(!strcmp(test_string, ""));
+ CHECK((s_pkt_trace->get_buff_len() == 0));
+
+ PacketTracer::thread_term();
+}
+#endif
--- /dev/null
+//--------------------------------------------------------------------------
+// Copyright (C) 2017-2017 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.h author Steven Baigal <sbaigal@cisco.com>
+
+#ifndef PACKET_TRACER_H
+#define PACKET_TRACER_H
+
+struct Packet;
+
+class PacketTracer
+{
+public:
+ static void thread_init();
+ static void thread_term();
+ static void log(const char* format, ...) __attribute__((format (printf, 1, 2)));
+ static void dump(char* output_buff=nullptr, unsigned int len=0);
+ static void add_header_info(Packet* p);
+#ifdef UNIT_TEST
+ char* get_buff();
+ int get_buff_len();
+#endif
+private:
+ static const int max_buff_size = 2048;
+ char buffer[max_buff_size];
+ unsigned int buff_len = 0;
+};
+
+#endif
#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"
#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" },
+
{ nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr }
};
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("log_ipv6_extra_data") )
// FIXIT-M move to output|logging_flags
sc->log_ipv6_extra = v.get_bool() ? 0 : 1;
#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 "managers/action_manager.h"
SideChannelManager::thread_init();
HighAvailabilityManager::thread_init(); // must be before InspectorManager::thread_init();
InspectorManager::thread_init(snort_conf);
+ if (SnortConfig::packet_trace_enabled())
+ PacketTracer::thread_init();
// in case there are HA messages waiting, process them first
HighAvailabilityManager::process_receive();
EventTrace_Term();
CleanupTag();
FileService::thread_term();
+ PacketTracer::thread_term();
Active::term();
delete s_switcher;
PacketManager::decode(p, pkthdr, pkt);
assert(p->pkth && p->pkt);
+ PacketTracer::add_header_info(p);
+
if (is_frag)
{
p->packet_flags |= (PKT_PSEUDO | PKT_REBUILT_FRAG);
int inject = 0;
verdict = update_verdict(verdict, inject);
+ PacketTracer::log("NAP id %d, IPS id %d, Verdict %s\n",
+ get_network_policy()->policy_id, get_ips_policy()->policy_id,
+ SFDAQ::verdict_to_string(verdict));
+
+ PacketTracer::dump();
+
// FIXIT-H move this to the appropriate struct
//perfBase->UpdateWireStats(pkthdr->caplen, Active::packet_was_dropped(), inject);
HighAvailabilityManager::process_update(s_packet->flow, pkthdr);
uint8_t log_ipv6_extra = 0;
uint16_t event_trace_max = 0;
long int tagged_packet_limit = 256;
+ bool enable_packet_trace = false;
std::string log_dir;
return snort_conf->user_id != -1 || snort_conf->group_id != -1 ||
!snort_conf->chroot_dir.empty();
}
+
+ static bool packet_trace_enabled()
+ {
+ return snort_conf->enable_packet_trace;
+ }
};
#endif
#include "detector_plugins/detector_sip.h"
#include "detector_plugins/detector_pattern.h"
#include "log/messages.h"
+#include "log/packet_tracer.h"
#include "main/snort_config.h"
#include "managers/inspector_manager.h"
#include "protocols/packet.h"
CRYPTO_cleanup_all_ex_data();
}
+static void add_appid_to_packet_trace(Flow* flow)
+{
+ AppIdSession* session = appid_api.get_appid_session(flow);
+ if (session)
+ {
+ AppId service_id, client_id, payload_id, misc_id;
+ const char *service_app_name, *client_app_name, *payload_app_name, *misc_name;
+ session->get_application_ids(service_id, client_id, payload_id, misc_id);
+ service_app_name = appid_api.get_application_name(service_id);
+ client_app_name = appid_api.get_application_name(client_id);
+ payload_app_name = appid_api.get_application_name(payload_id);
+ misc_name = appid_api.get_application_name(misc_id);
+
+ PacketTracer::log("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);
+ }
+}
+
AppIdInspector::AppIdInspector(const AppIdModuleConfig* pc)
{
assert(pc);
appid_stats.packets++;
if (p->flow)
+ {
AppIdDiscovery::do_application_discovery(p);
+ if (SnortConfig::packet_trace_enabled())
+ add_appid_to_packet_trace(p->flow);
+ }
else
appid_stats.ignored_packets++;
}
AppIdSession* asd = appid_api.get_appid_session(flow);
return asd->payload_app_id;
}
-
#include <list>
#include <vector>
-#include "application_ids.h"
-#include "appid_utils/sf_multi_mpse.h"
-#include "appid_utils/sf_mlmp.h"
#include "flow/flow.h"
#include "log/messages.h"
#include "search_engines/search_tool.h"
#include "utils/util.h"
+#include "application_ids.h"
+#include "appid_utils/sf_multi_mpse.h"
+#include "appid_utils/sf_mlmp.h"
+
struct Packet;
struct AppIdServiceSubtype;
class AppIdHttpSession;
daq_mod = nullptr;
}
+const char* SFDAQ::verdict_to_string(DAQ_Verdict verdict)
+{
+ return daq_verdict_string(verdict);
+}
+
bool SFDAQ::forwarding_packet(const DAQ_PktHdr_t* h)
{
// DAQ mode is inline and the packet will be forwarded?
static void unload();
static void print_types(std::ostream&);
+ static const char* verdict_to_string(DAQ_Verdict verdict);
static void init(const SnortConfig*);
static void term();