]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1219 in SNORT/snort3 from add_capture_support to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Thu, 10 May 2018 16:29:31 +0000 (12:29 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Thu, 10 May 2018 16:29:31 +0000 (12:29 -0400)
Squashed commit of the following:

commit a5e4304b0fa51fb13d40af0f802ee8059d529edd
Author: shaslad <shaslad@cisco.com>
Date:   Thu May 3 22:12:04 2018 -0400

    packet_capture: adding analyzer command to initialize dump file

src/main.cc
src/main/analyzer_command.h
src/main/request.h
src/network_inspectors/appid/appid_module.cc
src/network_inspectors/packet_capture/capture_module.cc
src/network_inspectors/packet_capture/packet_capture.cc
src/network_inspectors/packet_tracer/packet_tracer_module.cc

index 266d89513c24fb03d4cbd1911b59b93c76e21f00..aba39f06f8c61bda7f4b8a36b2b576d79f0e6287 100644 (file)
@@ -241,9 +241,23 @@ static Pig* get_lazy_pig(unsigned max)
 // 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)
     {
@@ -255,23 +269,11 @@ void snort::main_broadcast_command(AnalyzerCommand* ac)
         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;
 }
 
@@ -279,7 +281,7 @@ int main_rotate_stats(lua_State* L)
 {
     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;
 }
 
@@ -321,7 +323,7 @@ int main_reload_config(lua_State* L)
 
     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;
 }
@@ -362,7 +364,7 @@ int main_reload_policy(lua_State* L)
 
     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;
 }
@@ -371,7 +373,7 @@ int main_reload_daq(lua_State* L)
 {
     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;
@@ -409,7 +411,7 @@ int main_reload_hosts(lua_State* L)
 
     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;
 }
@@ -450,7 +452,7 @@ int main_delete_inspector(lua_State* L)
 
     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;
 }
@@ -472,7 +474,7 @@ int main_pause(lua_State* L)
 {
     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;
 }
@@ -481,7 +483,7 @@ int main_resume(lua_State* L)
 {
     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;
 }
@@ -505,7 +507,7 @@ int main_quit(lua_State* L)
 {
     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;
 }
index 72ad0d30139a74442aaf7396e4dabd773ae22c12..a069291b218c8865bddb44593356c7190fb72853 100644 (file)
@@ -113,7 +113,7 @@ public:
 
 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
index eb8fa9539a434474e4c38186cad35920c6dc8c85..61e048ba2a20d942198690f2ad0f09bdba91359e 100644 (file)
@@ -41,6 +41,6 @@ private:
     int fd;
     char read_buf[1024];
     size_t bytes_read;
-    const char* queued_response;
+    const char* queued_response = nullptr;
 };
 #endif
index c20d2a99c1e1e38551a3b5ac73e92366f020107c..4b65ac6472e12f6e3cdcf37b91925fadeb668219 100644 (file)
@@ -146,14 +146,14 @@ static int enable_debug(lua_State* L)
     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;
 }
 
index 8b2f8db7dcdeacbe40dfad74e6184474e19ffed9..660351c730692201cfde619fa7ff17dc9967762b 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <lua.hpp>
 
+#include "main/analyzer_command.h"
 #include "profiler/profiler.h"
 
 #include "packet_capture.h"
@@ -36,13 +37,6 @@ using namespace std;
 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",
@@ -61,21 +55,66 @@ static const Command cap_cmds[] =
     { 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; }
index 866f873a5e28745679c496c641e0460a3de313f6..3bfa8508525bdf94c46b32ffcb810493a93dcc7b 100644 (file)
@@ -42,32 +42,122 @@ using namespace std;
 #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
 //-------------------------------------------------------------------------
@@ -77,25 +167,41 @@ class PacketCapture : public Inspector
 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,
@@ -111,53 +217,6 @@ void PacketCapture::eval(Packet* p)
         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
@@ -219,6 +278,10 @@ const BaseApi* nin_packet_capture[] =
     nullptr
 };
 
+// --------------------------------------------------------------------------
+// unit tests
+// --------------------------------------------------------------------------
+
 #ifdef UNIT_TEST
 static Packet* init_null_packet()
 {
@@ -242,15 +305,24 @@ public:
     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;
@@ -271,12 +343,12 @@ TEST_CASE("toggle", "[PacketCapture]")
     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 );
 }
@@ -296,13 +368,13 @@ TEST_CASE("lazy init", "[PacketCapture]")
     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);
@@ -328,13 +400,13 @@ TEST_CASE("blank filter", "[PacketCapture]")
     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);
 }
 
@@ -345,11 +417,11 @@ TEST_CASE("bad filter", "[PacketCapture]")
     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 "
@@ -413,8 +485,8 @@ TEST_CASE("bpf filter", "[PacketCapture]")
     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);
@@ -436,7 +508,7 @@ TEST_CASE("bpf filter", "[PacketCapture]")
     CHECK ( cap.pcap[0] == &p_match );
     CHECK ( cap.pcap[1] == &p_match );
 
-    packet_capture_disable();
+    _packet_capture_disable();
     cap.eval(null_packet);
 }
 #endif
index 74bb97eda56c69469d6f20b418f6883441531b80..28db49bc21880e195a501bceda43d0305f54e1a9 100644 (file)
@@ -137,21 +137,19 @@ static int enable(lua_State* L)
     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*)
 {