]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #906 in SNORT/snort3 from daq_reload to master
authorMichael Altizer (mialtize) <mialtize@cisco.com>
Tue, 23 May 2017 19:22:48 +0000 (15:22 -0400)
committerMichael Altizer (mialtize) <mialtize@cisco.com>
Tue, 23 May 2017 19:22:48 +0000 (15:22 -0400)
Squashed commit of the following:

commit 19f347e73b9ab4f23a7017809f4c51150954a106
Author: Bhagya Tholpady <bbantwal@cisco.com>
Date:   Mon May 22 12:08:07 2017 -0400

    control_mgmt: add support for daq module reload

17 files changed:
extra/configure.ac
extra/src/daqs/CMakeLists.txt
extra/src/daqs/Makefile.am
extra/src/daqs/daq_regtest/CMakeLists.txt [new file with mode: 0644]
extra/src/daqs/daq_regtest/Makefile.am [new file with mode: 0644]
extra/src/daqs/daq_regtest/daq_regtest.c [new file with mode: 0644]
src/main.cc
src/main.h
src/main/analyzer.cc
src/main/analyzer.h
src/main/analyzer_command.cc
src/main/analyzer_command.h
src/main/snort_module.cc
src/packet_io/sfdaq.cc
src/packet_io/sfdaq.h
src/utils/stats.cc
src/utils/stats.h

index 0b825f662df20af5ff2252d5b7db1f95e91f9b2c..2ea26c8340115906c5afa8ff1cc1d9e51282dfdc 100644 (file)
@@ -44,6 +44,7 @@ src/codecs/cd_token_ring/Makefile \
 src/codecs/cd_wlan/Makefile \
 src/daqs/Makefile \
 src/daqs/daq_socket/Makefile \
+src/daqs/daq_regtest/Makefile \
 src/inspectors/Makefile \
 src/inspectors/data_log/Makefile \
 src/inspectors/dpx/Makefile \
index 560a9a5cec53f4c24c0136e1b7959b7258d453ce..27c1f50f7c81d2ed49fd76269ea70a1b7b47c40a 100644 (file)
@@ -1,2 +1,3 @@
 add_subdirectory ( daq_socket )
+add_subdirectory ( daq_regtest )
 
index aa4f65e0784ba333e66fbbbd62d5d02db0652789..52e41c99f2739ca45bc91a8d66ee553558a3c074 100644 (file)
@@ -1,5 +1,6 @@
 SUBDIRS = \
-daq_socket
+daq_socket \
+daq_regtest
 
 AM_CPPFLAGS = @AM_CPPFLAGS@
 AM_CFLAGS = @AM_CFLAGS@
diff --git a/extra/src/daqs/daq_regtest/CMakeLists.txt b/extra/src/daqs/daq_regtest/CMakeLists.txt
new file mode 100644 (file)
index 0000000..471fd92
--- /dev/null
@@ -0,0 +1,41 @@
+cmake_minimum_required ( VERSION 2.8.11 )
+project ( daq_regtest C )
+
+if ( APPLE )
+    set ( CMAKE_MACOSX_RPATH OFF )
+endif ( APPLE )
+
+include ( FindPkgConfig )
+pkg_search_module ( SNORT3 REQUIRED snort>=3 )
+
+add_library (
+    daq_regtest MODULE
+    daq_regtest.c
+)
+
+if ( APPLE )
+    set_target_properties (
+        daq_regtest
+        PROPERTIES
+            LINK_FLAGS "-undefined dynamic_lookup"
+    )
+endif ( APPLE )
+
+set_target_properties (
+    daq_regtest
+    PROPERTIES
+        PREFIX ""
+)
+
+set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99" )
+
+target_include_directories (
+    daq_regtest PUBLIC
+    ${SNORT3_INCLUDE_DIRS}
+)
+
+install (
+    TARGETS daq_regtest
+    LIBRARY
+        DESTINATION "lib/${CMAKE_PROJECT_NAME}/daqs"
+)
diff --git a/extra/src/daqs/daq_regtest/Makefile.am b/extra/src/daqs/daq_regtest/Makefile.am
new file mode 100644 (file)
index 0000000..440984c
--- /dev/null
@@ -0,0 +1,8 @@
+daq_regtestlibdir = $(pkglibdir)/daqs
+
+AM_CFLAGS   = @SNORT3_CFLAGS@ -std=gnu99
+
+daq_regtestlib_LTLIBRARIES = daq_regtest.la
+daq_regtest_la_CFLAGS   = $(AM_CFLAGS)
+daq_regtest_la_LDFLAGS  = -module -export-dynamic -avoid-version -shared
+daq_regtest_la_SOURCES  = daq_regtest.c
diff --git a/extra/src/daqs/daq_regtest/daq_regtest.c b/extra/src/daqs/daq_regtest/daq_regtest.c
new file mode 100644 (file)
index 0000000..57f9160
--- /dev/null
@@ -0,0 +1,369 @@
+/*--------------------------------------------------------------------------
+// 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.
+//--------------------------------------------------------------------------
+*/
+/* daq_regtest.c author Bhagya Tholpady <bbantwal@cisco.com> */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <pcap.h>
+
+#include "daq.h"
+#include "daq_api.h"
+
+#define DAQ_MOD_VERSION 0
+#define DAQ_NAME "regtest"
+#define DAQ_TYPE (DAQ_TYPE_FILE_CAPABLE | DAQ_TYPE_INTF_CAPABLE | \
+                          DAQ_TYPE_INLINE_CAPABLE | DAQ_TYPE_MULTI_INSTANCE)
+#define REGTEST_DEBUG_FILE "daq_regtest_debug"
+#define REGTEST_CONFIG_FILE "daq_regtest.conf"
+
+typedef struct
+{
+    char* buf;
+    int config_num;
+}DAQRegTestConfig;
+
+typedef struct
+{
+    DAQRegTestConfig* daq_regtest_cfg;
+    FILE* debug_fh;
+    int daq_config_reads;
+    const DAQ_Module_t* module;
+    void *handle;
+}DAQRegTestContext;
+
+static int daq_regtest_parse_config(DAQRegTestContext *context, DAQRegTestConfig** new_config, char* errBuf, size_t errMax)
+{
+    long size = 0;
+    FILE* fh = fopen(REGTEST_CONFIG_FILE, "r");
+
+    if (!fh)
+    {
+        if ( errBuf )
+            snprintf(errBuf, errMax, "%s: failed to open the daq_regtest config file", DAQ_NAME);
+        return DAQ_ERROR;
+    }
+    DAQRegTestConfig* config = calloc(1, sizeof(DAQRegTestConfig));
+    if ( !config )
+    {
+        if ( errBuf )
+            snprintf(errBuf, errMax, "%s: failed to allocate daq_regtest config", DAQ_NAME);
+        fclose(fh);
+        return DAQ_ERROR_NOMEM;
+    }
+
+    fseek(fh, 0, SEEK_END);
+    size = ftell(fh);
+    config->buf = (char*) calloc(size, sizeof(char));
+    if ( !config->buf )
+    {
+        if ( errBuf )
+            snprintf(errBuf, errMax, "%s: failed to allocate daq_regtest buffer", DAQ_NAME);
+        free(config);
+        fclose(fh);
+        return DAQ_ERROR_NOMEM;
+    }
+    rewind(fh);
+    if ( fgets(config->buf , size, fh) == NULL )
+    {
+        if ( errBuf )
+            snprintf(errBuf, errMax, "%s: failed to read daq_regtest config file", DAQ_NAME);
+        free(config);
+        fclose(fh);
+        return DAQ_ERROR;
+    }
+    context->daq_config_reads++;
+    config->config_num = context->daq_config_reads;
+    *new_config = config;
+    fclose(fh);
+
+    return DAQ_SUCCESS;
+}
+
+static int daq_regtest_init_context(DAQRegTestContext* context, char* errBuf, size_t errMax)
+{
+    context->debug_fh = NULL;
+
+    return daq_regtest_parse_config(context, &(context->daq_regtest_cfg), errBuf, errMax);
+}
+static void daq_regtest_cleanup(DAQRegTestContext* context)
+{
+    context->module = NULL;
+    context->handle = NULL;
+
+    if ( context->debug_fh )
+        fclose(context->debug_fh);
+
+    if ( context->daq_regtest_cfg )
+    {
+        if ( context->daq_regtest_cfg->buf )
+            free(context->daq_regtest_cfg->buf);
+        free(context->daq_regtest_cfg);
+    }
+
+    free(context);
+}
+//-------------------------------------------------------------------------
+// daq
+//-------------------------------------------------------------------------
+
+static void daq_regtest_shutdown (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+
+    if (context->debug_fh)
+        fprintf (context->debug_fh, "daq_regtest shutdown\n");
+
+    context->module->shutdown(context->handle);
+    daq_regtest_cleanup(context);
+}
+
+static void daq_regtest_debug(DAQRegTestContext* context, char* msg)
+{
+    if (context->debug_fh)
+    {
+        fprintf (context->debug_fh, "%s\n", msg);
+        fprintf (context->debug_fh, "daq_regtest config : \n\tbuf = %s \n\tconfig_num = %d \n", 
+                context->daq_regtest_cfg->buf, context->daq_regtest_cfg->config_num);
+        fflush(context->debug_fh);
+    }
+}
+
+//-------------------------------------------------------------------------
+
+static int daq_regtest_initialize (
+    const DAQ_Config_t* cfg, void** handle, char* errBuf, size_t errMax)
+{
+    DAQRegTestContext* context;
+    int rval = DAQ_SUCCESS;
+
+    context = calloc(1, sizeof(*context));
+    if ( !context )
+    {
+        snprintf(errBuf, errMax, "%s: Couldn't allocate memory for the new daq_regtest context!", DAQ_NAME);
+        return DAQ_ERROR_NOMEM;
+    }
+
+    rval = daq_regtest_init_context(context, errBuf, errMax);
+
+    if ( rval != DAQ_SUCCESS )
+    {
+        free(context);
+        return rval;
+    }
+
+    context->module = daq_find_module("dump");
+
+    if (!context->module)
+    {
+        snprintf(errBuf, errMax, "%s: Can't find dump daq required by daq_regtest module!", DAQ_NAME);
+        daq_regtest_cleanup(context);
+        return DAQ_ERROR;
+    }
+
+    context->debug_fh = fopen(REGTEST_DEBUG_FILE, "w");
+
+    rval = context->module->initialize(cfg, &context->handle, errBuf, errMax);
+    if ( rval != DAQ_SUCCESS )
+    {
+        daq_regtest_cleanup(context);
+        return rval;
+    }
+    daq_regtest_debug(context, "daq_regtest initialized");
+    *handle = context;
+    return rval;
+}
+
+//-------------------------------------------------------------------------
+
+static int daq_regtest_start (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->start(context->handle);
+}
+
+static int daq_regtest_stop (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->stop(context->handle);
+}
+
+//-------------------------------------------------------------------------
+
+static int daq_regtest_inject (
+    void* handle, const DAQ_PktHdr_t* hdr, const uint8_t* buf, uint32_t len,
+    int reverse)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->inject(context->handle, hdr, buf, len, reverse);
+}
+
+//-------------------------------------------------------------------------
+
+static int daq_regtest_acquire (
+    void* handle, int cnt, DAQ_Analysis_Func_t callback, DAQ_Meta_Func_t meta, void* user)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->acquire(context->handle, cnt, callback, meta, user);
+}
+
+//-------------------------------------------------------------------------
+
+static int daq_regtest_breakloop (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->breakloop(context->handle);
+}
+
+static DAQ_State daq_regtest_check_status (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->check_status(context->handle);
+}
+
+static int daq_regtest_get_stats (void* handle, DAQ_Stats_t* stats)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_stats(context->handle, stats);
+}
+
+static void daq_regtest_reset_stats (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    context->module->reset_stats(context->handle);
+}
+
+static int daq_regtest_get_snaplen (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_snaplen(context->handle);
+}
+
+static uint32_t daq_regtest_get_capabilities (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_capabilities(context->handle);
+}
+
+static int daq_regtest_get_datalink_type(void *handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_datalink_type(context->handle);
+}
+
+static const char* daq_regtest_get_errbuf (void* handle)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_errbuf(context->handle);
+}
+
+static void daq_regtest_set_errbuf (void* handle, const char* s)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    context->module->set_errbuf(context->handle, s);
+}
+
+static int daq_regtest_get_device_index(void* handle, const char* device)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->get_device_index(context->handle, device);
+}
+
+static int daq_regtest_set_filter (void* handle, const char* filter)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    return context->module->set_filter(context->handle, filter);
+}
+
+static int daq_regtest_hup_prep(void *handle, void **new_config)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    DAQRegTestConfig* newConf;
+    int rval = DAQ_SUCCESS;
+
+    if ( ( rval = daq_regtest_parse_config(context, &newConf, NULL, 0) ) == DAQ_SUCCESS )
+    {
+        daq_regtest_debug(context, "daq_regtest hup_prep succeeded");
+        *new_config = newConf;
+    }
+    else
+        daq_regtest_debug(context, "daq_regtest hup_prep failed");
+    return rval;
+}
+
+static int daq_regtest_hup_apply(void *handle, void *new_config, void **old_config)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    DAQRegTestConfig* config = (DAQRegTestConfig*)new_config;
+
+    *old_config = context->daq_regtest_cfg;
+    context->daq_regtest_cfg = config;
+    daq_regtest_debug(context, "daq_regtest hup_apply succeeded");
+
+    return DAQ_SUCCESS;
+}
+
+static int daq_regtest_hup_post(void *handle, void *old_config)
+{
+    DAQRegTestContext* context = (DAQRegTestContext*)handle;
+    DAQRegTestConfig* config = (DAQRegTestConfig*)old_config;
+
+    daq_regtest_debug(context, "daq_regtest hup_post succeeded");
+
+    if ( config->buf ) 
+        free(config->buf);
+    free(config);
+
+    return DAQ_SUCCESS;
+}
+
+
+//-------------------------------------------------------------------------
+
+DAQ_SO_PUBLIC DAQ_Module_t DAQ_MODULE_DATA =
+{
+    .api_version = DAQ_API_VERSION,
+    .module_version = DAQ_MOD_VERSION,
+    .name = DAQ_NAME,
+    .type = DAQ_TYPE,
+    .initialize = daq_regtest_initialize,
+    .set_filter = daq_regtest_set_filter,
+    .start = daq_regtest_start,
+    .acquire = daq_regtest_acquire,
+    .inject = daq_regtest_inject,
+    .breakloop = daq_regtest_breakloop,
+    .stop = daq_regtest_stop,
+    .shutdown = daq_regtest_shutdown,
+    .check_status = daq_regtest_check_status,
+    .get_stats = daq_regtest_get_stats,
+    .reset_stats = daq_regtest_reset_stats,
+    .get_snaplen = daq_regtest_get_snaplen,
+    .get_capabilities = daq_regtest_get_capabilities,
+    .get_datalink_type = daq_regtest_get_datalink_type,
+    .get_errbuf = daq_regtest_get_errbuf,
+    .set_errbuf = daq_regtest_set_errbuf,
+    .get_device_index = daq_regtest_get_device_index,
+    .modify_flow = NULL,
+    .hup_prep = daq_regtest_hup_prep,
+    .hup_apply = daq_regtest_hup_apply,
+    .hup_post = daq_regtest_hup_post,
+};
index 560fa952c84d00f46e9a0f34204156dceba2bd19..299d9bcbe2d89e799c6fdf7a62a458daa3037f84 100644 (file)
@@ -333,6 +333,16 @@ int main_reload_config(lua_State* L)
     return 0;
 }
 
+int main_reload_daq(lua_State* L)
+{
+    bool from_shell = ( L != nullptr );
+    current_request->respond(".. reloading daq module\n", from_shell);
+    broadcast(get_command(new ACDAQSwap(), from_shell));
+    proc_stats.daq_reloads++;
+
+    return 0;
+}
+
 int main_reload_hosts(lua_State* L)
 {
     if ( Swapper::get_reload_in_progress() )
index 79960e48270c25684c36e7066f9274b7e5dfaede..555ae3f8a4db5a30fb7f924775ed2e01d5f44d2a 100644 (file)
@@ -29,6 +29,7 @@ const char* get_prompt();
 int main_dump_stats(lua_State* = nullptr);
 int main_rotate_stats(lua_State* = nullptr);
 int main_reload_config(lua_State* = nullptr);
+int main_reload_daq(lua_State* = nullptr);
 int main_reload_hosts(lua_State* = nullptr);
 int main_process(lua_State* = nullptr);
 int main_pause(lua_State* = nullptr);
index f10da07d4a24f4cb2ece09957b69a24d531fbf5a..b5cc63b6fdb5605f801549853acb222c370bef78 100644 (file)
@@ -214,3 +214,10 @@ void Analyzer::resume()
                 get_state_string());
 }
 
+void Analyzer::reload_daq()
+{
+    if (daq_instance)
+        daq_instance->reload();
+    DebugMessage(DEBUG_ANALYZER, "Handled RELOAD command\n");
+}
+
index 3e56361ad26c3c85a1618c5741c51d52223e637b..85a064f56da9eb4a71e3cba329519a80df63ee2f 100644 (file)
@@ -62,6 +62,7 @@ public:
     void stop();
     void pause();
     void resume();
+    void reload_daq();
 
 private:
     void analyze();
index cd71395812da5e01694c1d6437fef023555be883..158e064ede428e5f08f6c743bbacb28f8b85c7f8 100644 (file)
@@ -98,3 +98,13 @@ ACSwap::~ACSwap()
     LogMessage("== reload complete\n");
 }
 
+void ACDAQSwap::execute(Analyzer& analyzer)
+{
+    analyzer.reload_daq();
+}
+
+ACDAQSwap::~ACDAQSwap()
+{
+    LogMessage("== daq module reload complete\n");
+}
+
index c603b98137bb620fff7feb39601e2b0fed106399..f4ae88e99d2eb8a28024eb853ac682e05280c49d 100644 (file)
@@ -97,5 +97,13 @@ private:
     Swapper *ps;
 };
 
+class ACDAQSwap : public AnalyzerCommand
+{
+public:
+    void execute(Analyzer&) override;
+    const char* stringify() override { return "DAQ_SWAP"; }
+    ~ACDAQSwap();
+};
+
 #endif
 
index b98422aa0bb0a64ffba12d408c6c7672122b72ca..424b03b635c036efa25fc3a156c1757367543fab 100644 (file)
@@ -65,6 +65,7 @@ static const Command snort_cmds[] =
     { "dump_stats", main_dump_stats, nullptr, "show summary statistics" },
     { "rotate_stats", main_rotate_stats, nullptr, "roll perfmonitor log files" },
     { "reload_config", main_reload_config, s_reload, "load new configuration" },
+    { "reload_daq", main_reload_daq, nullptr, "reload daq module" },
     { "reload_hosts", main_reload_hosts, s_reload, "load a new hosts table" },
 
     // FIXIT-M rewrite trough to permit updates on the fly
index 41a7750831525aff9c2af6611c6a64c78a5fbf06..94102372dc8854910d0049185fb7adddbc0656a6 100644 (file)
@@ -348,7 +348,7 @@ bool SFDAQInstance::configure(const SnortConfig* sc)
     }
 
     // ideally this would be configurable ...
-    if (!strcasecmp(type, "dump"))
+    if (!strcasecmp(type, "dump") or !strcasecmp(type, "regtest"))
         cfg.extra = (char*)daq_find_module("pcap");
 
     err = daq_initialize(daq_mod, &cfg, &daq_hand, buf, sizeof(buf));
@@ -367,6 +367,20 @@ bool SFDAQInstance::configure(const SnortConfig* sc)
     return true;
 }
 
+void SFDAQInstance::reload(void)
+{
+    void* old_config = nullptr;
+    void* new_config = nullptr;
+    if (daq_mod && daq_hand)
+    {
+        if ( ( daq_hup_prep(daq_mod, daq_hand, &new_config) == DAQ_SUCCESS ) and
+            ( daq_hup_apply(daq_mod, daq_hand, new_config, &old_config) == DAQ_SUCCESS ) )
+        {
+            daq_hup_post(daq_mod, daq_hand, old_config);
+        }
+    }
+}
+
 void SFDAQInstance::abort()
 {
     if (was_started())
index a51e404e219c35428fbc24207db2849b606e6786..4b7709ecaf2a9c48a96574e8da151ddec0f6fbd9 100644 (file)
@@ -50,6 +50,7 @@ public:
     bool start();
     bool was_started();
     bool stop();
+    void reload();
     void set_metacallback(DAQ_Meta_Func_t);
     int acquire(int max, DAQ_Analysis_Func_t);
     int inject(const DAQ_PktHdr_t*, int rev, const uint8_t* buf, uint32_t len);
index 7e754c6cc9dbe3719c27f7048712f78398811b22..ab6db5521d943f6d6b0a7b466c840b42deb89bb0 100644 (file)
@@ -217,6 +217,7 @@ const PegInfo proc_names[] =
     { "remote_commands", "total remote commands processed" },
     { "signals", "total signals processed" },
     { "conf_reloads", "number of times configuration was reloaded" },
+    { "daq_reloads", "number of times daq configuration was reloaded" },
     { "attribute_table_reloads", "number of times hosts table was reloaded" },
     { "attribute_table_hosts", "total number of hosts in table" },
     { nullptr, nullptr }
index e9a7ffc4ddf5459ff199082e3e74535f10752f26..986531fc29754e5571c4d85fb0f18deba341e95c 100644 (file)
@@ -61,6 +61,7 @@ struct ProcessCount
     PegCount remote_commands;
     PegCount signals;
     PegCount conf_reloads;
+    PegCount daq_reloads;
     PegCount attribute_table_reloads;
     PegCount attribute_table_hosts;
 };