From: Michael Altizer (mialtize) Date: Tue, 23 May 2017 19:22:48 +0000 (-0400) Subject: Merge pull request #906 in SNORT/snort3 from daq_reload to master X-Git-Tag: 3.0.0-239~69 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d1f9f53f421c585624ebad8a1a8aef38d2ed0d11;p=thirdparty%2Fsnort3.git Merge pull request #906 in SNORT/snort3 from daq_reload to master Squashed commit of the following: commit 19f347e73b9ab4f23a7017809f4c51150954a106 Author: Bhagya Tholpady Date: Mon May 22 12:08:07 2017 -0400 control_mgmt: add support for daq module reload --- diff --git a/extra/configure.ac b/extra/configure.ac index 0b825f662..2ea26c834 100644 --- a/extra/configure.ac +++ b/extra/configure.ac @@ -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 \ diff --git a/extra/src/daqs/CMakeLists.txt b/extra/src/daqs/CMakeLists.txt index 560a9a5ce..27c1f50f7 100644 --- a/extra/src/daqs/CMakeLists.txt +++ b/extra/src/daqs/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory ( daq_socket ) +add_subdirectory ( daq_regtest ) diff --git a/extra/src/daqs/Makefile.am b/extra/src/daqs/Makefile.am index aa4f65e07..52e41c99f 100644 --- a/extra/src/daqs/Makefile.am +++ b/extra/src/daqs/Makefile.am @@ -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 index 000000000..471fd9292 --- /dev/null +++ b/extra/src/daqs/daq_regtest/CMakeLists.txt @@ -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 index 000000000..440984c52 --- /dev/null +++ b/extra/src/daqs/daq_regtest/Makefile.am @@ -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 index 000000000..57f9160eb --- /dev/null +++ b/extra/src/daqs/daq_regtest/daq_regtest.c @@ -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 */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#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, +}; diff --git a/src/main.cc b/src/main.cc index 560fa952c..299d9bcbe 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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() ) diff --git a/src/main.h b/src/main.h index 79960e482..555ae3f8a 100644 --- a/src/main.h +++ b/src/main.h @@ -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); diff --git a/src/main/analyzer.cc b/src/main/analyzer.cc index f10da07d4..b5cc63b6f 100644 --- a/src/main/analyzer.cc +++ b/src/main/analyzer.cc @@ -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"); +} + diff --git a/src/main/analyzer.h b/src/main/analyzer.h index 3e56361ad..85a064f56 100644 --- a/src/main/analyzer.h +++ b/src/main/analyzer.h @@ -62,6 +62,7 @@ public: void stop(); void pause(); void resume(); + void reload_daq(); private: void analyze(); diff --git a/src/main/analyzer_command.cc b/src/main/analyzer_command.cc index cd7139581..158e064ed 100644 --- a/src/main/analyzer_command.cc +++ b/src/main/analyzer_command.cc @@ -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"); +} + diff --git a/src/main/analyzer_command.h b/src/main/analyzer_command.h index c603b9813..f4ae88e99 100644 --- a/src/main/analyzer_command.h +++ b/src/main/analyzer_command.h @@ -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 diff --git a/src/main/snort_module.cc b/src/main/snort_module.cc index b98422aa0..424b03b63 100644 --- a/src/main/snort_module.cc +++ b/src/main/snort_module.cc @@ -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 diff --git a/src/packet_io/sfdaq.cc b/src/packet_io/sfdaq.cc index 41a775083..94102372d 100644 --- a/src/packet_io/sfdaq.cc +++ b/src/packet_io/sfdaq.cc @@ -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()) diff --git a/src/packet_io/sfdaq.h b/src/packet_io/sfdaq.h index a51e404e2..4b7709eca 100644 --- a/src/packet_io/sfdaq.h +++ b/src/packet_io/sfdaq.h @@ -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); diff --git a/src/utils/stats.cc b/src/utils/stats.cc index 7e754c6cc..ab6db5521 100644 --- a/src/utils/stats.cc +++ b/src/utils/stats.cc @@ -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 } diff --git a/src/utils/stats.h b/src/utils/stats.h index e9a7ffc4d..986531fc2 100644 --- a/src/utils/stats.h +++ b/src/utils/stats.h @@ -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; };