// main commands
//-------------------------------------------------------------------------
-void snort::main_broadcast_command(AnalyzerCommand* ac)
+static AnalyzerCommand* get_command(AnalyzerCommand* ac, bool from_shell)
+{
+#ifndef SHELL
+ UNUSED(from_shell);
+#else
+ if ( from_shell )
+ return ( new ACShellCmd(current_fd, ac) );
+ else
+#endif
+ return ac;
+}
+
+void snort::main_broadcast_command(AnalyzerCommand* ac, bool from_shell)
{
unsigned dispatched = 0;
+
+ ac = get_command(ac, from_shell);
for (unsigned idx = 0; idx < max_pigs; ++idx)
{
orphan_commands.push(ac);
}
-static AnalyzerCommand* get_command(AnalyzerCommand* ac, bool from_shell)
-{
-#ifndef SHELL
- UNUSED(from_shell);
-#else
- if ( from_shell )
- return ( new ACShellCmd(current_fd, ac) );
- else
-#endif
- return ac;
-}
-
int main_dump_stats(lua_State* L)
{
bool from_shell = ( L != nullptr );
current_request->respond("== dumping stats\n", from_shell);
- main_broadcast_command(get_command(new ACGetStats(), from_shell));
+ main_broadcast_command(new ACGetStats(), from_shell);
return 0;
}
{
bool from_shell = ( L != nullptr );
current_request->respond("== rotating stats\n", from_shell);
- main_broadcast_command(get_command(new ACRotate(), from_shell));
+ main_broadcast_command(new ACRotate(), from_shell);
return 0;
}
bool from_shell = ( L != nullptr );
current_request->respond(".. swapping configuration\n", from_shell);
- main_broadcast_command(get_command(new ACSwap(new Swapper(old, sc, old_tc, tc)), from_shell));
+ main_broadcast_command(new ACSwap(new Swapper(old, sc, old_tc, tc)), from_shell);
return 0;
}
bool from_shell = ( L != nullptr );
current_request->respond(".. swapping policy\n", from_shell);
- main_broadcast_command(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
+ main_broadcast_command(new ACSwap(new Swapper(old, sc)), from_shell);
return 0;
}
{
bool from_shell = ( L != nullptr );
current_request->respond(".. reloading daq module\n", from_shell);
- main_broadcast_command(get_command(new ACDAQSwap(), from_shell));
+ main_broadcast_command(new ACDAQSwap(), from_shell);
proc_stats.daq_reloads++;
return 0;
bool from_shell = ( L != nullptr );
current_request->respond(".. swapping hosts table\n", from_shell);
- main_broadcast_command(get_command(new ACSwap(new Swapper(old, tc)), from_shell));
+ main_broadcast_command(new ACSwap(new Swapper(old, tc)), from_shell);
return 0;
}
bool from_shell = ( L != nullptr );
current_request->respond(".. deleted inspector\n", from_shell);
- main_broadcast_command(get_command(new ACSwap(new Swapper(old, sc)), from_shell));
+ main_broadcast_command(new ACSwap(new Swapper(old, sc)), from_shell);
return 0;
}
{
bool from_shell = ( L != nullptr );
current_request->respond("== pausing\n", from_shell);
- main_broadcast_command(get_command(new ACPause(), from_shell));
+ main_broadcast_command(new ACPause(), from_shell);
paused = true;
return 0;
}
{
bool from_shell = ( L != nullptr );
current_request->respond("== resuming\n", from_shell);
- main_broadcast_command(get_command(new ACResume(), from_shell));
+ main_broadcast_command(new ACResume(), from_shell);
paused = false;
return 0;
}
{
bool from_shell = ( L != nullptr );
current_request->respond("== stopping\n", from_shell);
- main_broadcast_command(get_command(new ACStop(), from_shell));
+ main_broadcast_command(new ACStop(), from_shell);
exit_requested = true;
return 0;
}
namespace snort
{
-SO_PUBLIC void main_broadcast_command(AnalyzerCommand* ac); // From main.cc
+SO_PUBLIC void main_broadcast_command(AnalyzerCommand* ac, bool from_shell = false); // From main.cc
}
#endif
int fd;
char read_buf[1024];
size_t bytes_read;
- const char* queued_response;
+ const char* queued_response = nullptr;
};
#endif
constraints.sport = sport;
constraints.dport = dport;
- main_broadcast_command(new AcAppIdDebug(&constraints));
+ main_broadcast_command(new AcAppIdDebug(&constraints), true);
return 0;
}
static int disable_debug(lua_State*)
{
- main_broadcast_command(new AcAppIdDebug(nullptr));
+ main_broadcast_command(new AcAppIdDebug(nullptr), true);
return 0;
}
#include <lua.hpp>
+#include "main/analyzer_command.h"
#include "profiler/profiler.h"
#include "packet_capture.h"
static int enable(lua_State*);
static int disable(lua_State*);
-const PegInfo cap_names[] =
-{
- { CountType::SUM, "processed", "packets processed against filter" },
- { CountType::SUM, "captured", "packets matching dumped after matching filter" },
- { CountType::END, nullptr, nullptr }
-};
-
static const Parameter s_capture[] =
{
{ "enable", Parameter::PT_BOOL, nullptr, "false",
{ 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::END, nullptr, nullptr }
+};
+
THREAD_LOCAL CaptureStats cap_count_stats;
THREAD_LOCAL ProfileStats cap_prof_stats;
+//-------------------------------------------------------------------------
+// class stuff
+//-------------------------------------------------------------------------
+class PacketCaptureDebug : public AnalyzerCommand
+{
+public:
+ PacketCaptureDebug(const char* f);
+ void execute(Analyzer&) override;
+ const char* stringify() override { return "PACKET_CAPTURE_DEBUG"; }
+private:
+ bool enable = false;
+ std::string filter;
+};
+
+// -----------------------------------------------------------------------------
+// static functions
+// -----------------------------------------------------------------------------
static int enable(lua_State* L)
{
- packet_capture_enable(lua_tostring(L, 1));
+ main_broadcast_command(new PacketCaptureDebug(lua_tostring(L, 1)), true);
return 0;
}
static int disable(lua_State*)
{
- packet_capture_disable();
+ main_broadcast_command(new PacketCaptureDebug(nullptr), true);
return 0;
}
+// -----------------------------------------------------------------------------
+// non-static functions
+// -----------------------------------------------------------------------------
+
+PacketCaptureDebug::PacketCaptureDebug(const char* f)
+{
+ if (f)
+ {
+ filter = f;
+ enable = true;
+ }
+}
+
+void PacketCaptureDebug::execute(Analyzer&)
+{
+ if (enable)
+ packet_capture_enable(filter);
+ else
+ packet_capture_disable();
+}
+
CaptureModule::CaptureModule() :
Module(CAPTURE_NAME, CAPTURE_HELP, s_capture)
{ config.enabled = false; }
#define FILE_NAME "packet_capture.pcap"
#define SNAP_LEN 65535
+// -----------------------------------------------------------------------------
+// static variables
+// -----------------------------------------------------------------------------
+
static CaptureConfig config;
static THREAD_LOCAL pcap_t* pcap = nullptr;
static THREAD_LOCAL pcap_dumper_t* dumper = nullptr;
static THREAD_LOCAL struct bpf_program bpf;
+// -----------------------------------------------------------------------------
+// static functions
+// -----------------------------------------------------------------------------
+
static inline bool capture_initialized()
{ return dumper != nullptr; }
-void packet_capture_enable(const string& f)
+static void _capture_term()
+{
+ if ( dumper )
+ {
+ pcap_dump_close(dumper);
+ dumper = nullptr;
+ }
+ if ( pcap )
+ {
+ free(pcap);
+ pcap = nullptr;
+ }
+ pcap_freecode(&bpf);
+}
+
+static bool bpf_compile_and_validate()
+{
+ // FIXIT-M This BPF compilation is not threadsafe and should be handled by the main thread
+ // and this call should use DLT from DAQ rather then hard coding DLT_EN10MB
+ if ( pcap_compile_nopcap(SNAP_LEN, DLT_EN10MB, &bpf,
+ config.filter.c_str(), 1, 0) >= 0 )
+ {
+ if (bpf_validate(bpf.bf_insns, bpf.bf_len))
+ return true;
+ else
+ WarningMessage("Unable to validate BPF filter\n");
+ }
+ else
+ WarningMessage("Unable to compile BPF filter\n");
+ return false;
+}
+
+static bool open_pcap_dumper()
+{
+ string fname;
+ get_instance_file(fname, FILE_NAME);
+
+ pcap = pcap_open_dead(DLT_EN10MB, SNAP_LEN);
+ dumper = pcap ? pcap_dump_open(pcap, fname.c_str()) : nullptr;
+
+ if (dumper)
+ return true;
+ else
+ WarningMessage("Could not initialize dump file\n");
+
+ return false;
+}
+
+// for unit test
+static void _packet_capture_enable(const string& f)
{
if ( !config.enabled )
{
config.filter = f;
config.enabled = true;
}
- else
- WarningMessage("Conflicting packet capture already in progress.\n");
}
-void packet_capture_disable()
+// for unit test
+static void _packet_capture_disable()
{
config.enabled = false;
LogMessage("Packet capture disabled\n");
}
+// -----------------------------------------------------------------------------
+// non-static functions
+// -----------------------------------------------------------------------------
+
+void packet_capture_enable(const string& f)
+{
+
+ _packet_capture_enable(f);
+
+ if ( !capture_initialized() )
+ {
+ if (bpf_compile_and_validate())
+ {
+ if (open_pcap_dumper())
+ {
+ LogMessage("Packet capture enabled\n");
+ return;
+ }
+ }
+ else
+ {
+ WarningMessage("Failed to enable Packet capture\n");
+ packet_capture_disable();
+ }
+ }
+}
+
+void packet_capture_disable()
+{
+ _packet_capture_disable();
+ if ( capture_initialized() )
+ _capture_term();
+}
+
//-------------------------------------------------------------------------
// class stuff
//-------------------------------------------------------------------------
public:
PacketCapture(CaptureModule*);
+ // non-static functions
void eval(Packet*) override;
void tterm() override { capture_term(); }
protected:
virtual bool capture_init();
virtual void capture_term();
- virtual pcap_dumper_t* open_dump(pcap_t*, const char*);
virtual void write_packet(Packet* p);
};
PacketCapture::PacketCapture(CaptureModule* m)
{ m->get_config(config); }
+void PacketCapture::capture_term() { _capture_term(); }
+
+bool PacketCapture::capture_init()
+{
+ if (bpf_compile_and_validate())
+ {
+ if (open_pcap_dumper())
+ {
+ LogMessage("Packet capture enabled\n");
+ return true;
+ }
+ }
+ packet_capture_disable();
+ return false;
+}
+
void PacketCapture::eval(Packet* p)
{
if ( config.enabled )
{
if ( !capture_initialized() )
- if ( !capture_init() )
+ if ( !capture_init() )
return;
if ( !bpf.bf_insns || bpf_filter(bpf.bf_insns, p->pkt,
capture_term();
}
-bool PacketCapture::capture_init()
-{
- if ( pcap_compile_nopcap(SNAP_LEN, DLT_EN10MB, &bpf,
- config.filter.c_str(), 1, 0) >= 0 )
- {
- if ( bpf_validate(bpf.bf_insns, bpf.bf_len) )
- {
- string fname;
- get_instance_file(fname, FILE_NAME);
-
- pcap = pcap_open_dead(DLT_EN10MB, SNAP_LEN);
- dumper = open_dump(pcap, fname.c_str());
-
- if ( dumper )
- return true;
- else
- WarningMessage("Could not initialize dump file\n");
- }
- else
- WarningMessage("Unable to validate BPF filter\n");
- }
- else
- WarningMessage("Unable to compile BPF filter\n");
-
- packet_capture_disable();
- capture_term();
- return false;
-}
-
-pcap_dumper_t* PacketCapture::open_dump(pcap_t* pcap, const char* fname)
-{ return pcap_dump_open(pcap, fname); }
-
-void PacketCapture::capture_term()
-{
- if ( dumper )
- {
- pcap_dump_close(dumper);
- dumper = nullptr;
- }
- if ( pcap )
- {
- free(pcap);
- pcap = nullptr;
- }
- pcap_freecode(&bpf);
-}
-
void PacketCapture::write_packet(Packet* p)
{
//DAQ_PktHdr_t is compatible with pcap_pkthdr
nullptr
};
+// --------------------------------------------------------------------------
+// unit tests
+// --------------------------------------------------------------------------
+
#ifdef UNIT_TEST
static Packet* init_null_packet()
{
MockPacketCapture(CaptureModule* m) : PacketCapture(m) {}
protected:
- pcap_dumper_t* open_dump(pcap_t*, const char*) override
- { return (pcap_dumper_t*)1; }
-
void write_packet(Packet* p) override
{
pcap.push_back(p);
write_packet_called = true;
}
+ bool capture_init() override
+ {
+ if (bpf_compile_and_validate())
+ {
+ dumper = (pcap_dumper_t*)1;
+ return true;
+ }
+ _packet_capture_disable();
+ capture_term();
+ return false;
+ }
+
void capture_term() override
{
dumper = nullptr;
CHECK ( !cap.write_packet_called );
cap.write_packet_called = false;
- packet_capture_enable("");
+ _packet_capture_enable("");
cap.eval(null_packet);
CHECK ( cap.write_packet_called );
cap.write_packet_called = false;
- packet_capture_disable();
+ _packet_capture_disable();
cap.eval(null_packet);
CHECK ( !cap.write_packet_called );
}
pc_dtor(real_cap);
MockPacketCapture cap(mod);
- packet_capture_enable("");
+ _packet_capture_enable("");
CHECK ( (capture_initialized() == false) );
cap.eval(null_packet);
CHECK ( (capture_initialized() == true) );
- packet_capture_disable();
+ _packet_capture_disable();
CHECK ( (capture_initialized() == true) );
cap.eval(null_packet);
CaptureModule mod;
MockPacketCapture cap(&mod);
- packet_capture_enable("");
+ _packet_capture_enable("");
cap.eval(&p);
REQUIRE ( cap.pcap.size() );
CHECK ( cap.pcap[0] == &p );
- packet_capture_disable();
+ _packet_capture_disable();
cap.eval(null_packet);
}
CaptureModule mod;
MockPacketCapture cap(&mod);
- packet_capture_enable("this is garbage");
+ _packet_capture_enable("this is garbage");
cap.eval(null_packet);
CHECK ( (capture_initialized() == false) );
- packet_capture_enable(
+ _packet_capture_enable(
"port 0 "
"port 1 "
"port 2 "
cap_count_stats.checked = 0;
cap_count_stats.matched = 0;
- packet_capture_enable("ip host 10.82.240.82");
- packet_capture_enable(""); //Test double-enable guard
+ _packet_capture_enable("ip host 10.82.240.82");
+ _packet_capture_enable(""); //Test double-enable guard
cap.write_packet_called = false;
cap.eval(&p_match);
CHECK ( cap.pcap[0] == &p_match );
CHECK ( cap.pcap[1] == &p_match );
- packet_capture_disable();
+ _packet_capture_disable();
cap.eval(null_packet);
}
#endif
constraints.sport = sport;
constraints.dport = dport;
- main_broadcast_command(new PacketTracerDebug(&constraints));
+ main_broadcast_command(new PacketTracerDebug(&constraints), true);
return 0;
}
static int disable(lua_State*)
{
- main_broadcast_command(new PacketTracerDebug(nullptr));
+ main_broadcast_command(new PacketTracerDebug(nullptr), true);
return 0;
}
PacketTracerModule::PacketTracerModule() :
Module(PACKET_TRACER_NAME, PACKET_TRACER_HELP, s_params)
-{
-}
-
+{}
bool PacketTracerModule::set(const char *, Value &v, SnortConfig*)
{