From e7799b37cac0529656fa7fa3fa594806c92e8ff0 Mon Sep 17 00:00:00 2001 From: "Bhagya Tholpady (bbantwal)" Date: Fri, 31 Jul 2020 17:40:54 +0000 Subject: [PATCH] Merge pull request #2334 in SNORT/snort3 from ~SVLASIUK/snort3:dump_config_text to master Squashed commit of the following: commit 252af2d5de8f3b68bd43e649e49d11a7c7bb742b Author: Serhii Vlasiuk Date: Fri Jul 3 15:25:57 2020 +0300 main: dump consolidated config in the text format --- src/detection/fp_create.cc | 2 +- src/framework/value.cc | 33 +++++++ src/framework/value.h | 65 +++++++++++--- src/log/messages.cc | 10 +++ src/log/messages.h | 1 + src/main.cc | 3 + src/main/CMakeLists.txt | 2 + src/main/config_tree.cc | 103 ++++++++++++++++++++++ src/main/config_tree.h | 109 +++++++++++++++++++++++ src/main/dev_notes.txt | 9 ++ src/main/shell.cc | 153 ++++++++++++++++++++++++++++++++- src/main/shell.h | 22 +++++ src/main/snort.cc | 2 +- src/main/snort_config.h | 11 ++- src/main/snort_module.cc | 12 ++- src/managers/module_manager.cc | 32 +++++++ src/trace/trace_module.cc | 47 ++++++---- 17 files changed, 575 insertions(+), 41 deletions(-) create mode 100644 src/main/config_tree.cc create mode 100644 src/main/config_tree.h diff --git a/src/detection/fp_create.cc b/src/detection/fp_create.cc index cbc8405a2..21a0cd084 100644 --- a/src/detection/fp_create.cc +++ b/src/detection/fp_create.cc @@ -1613,7 +1613,7 @@ int fpCreateFastPacketDetection(SnortConfig* sc) if ( log_rule_group_details ) LogMessage("Service Based Rule Maps Done....\n"); - if ( !sc->test_mode() or sc->mem_check() ) + if ( !sc->validation_mode() or sc->mem_check() ) { unsigned c = compile_mpses(sc, can_build_mt(fp)); unsigned expected = mpse_count + offload_mpse_count; diff --git a/src/framework/value.cc b/src/framework/value.cc index 0cff82c9c..82bdfec89 100644 --- a/src/framework/value.cc +++ b/src/framework/value.cc @@ -217,6 +217,39 @@ const char* Value::get_as_string() return str.c_str(); } +std::string Value::get_origin_string() const +{ + std::string value; + std::string token; + + stringstream ss(origin_str); + while ( ss >> token ) + { + value += token; + value += " "; + } + value.erase(value.size() - 1); + + if ( param && param->type != Parameter::PT_BOOL + && param->type != Parameter::PT_REAL + && param->type != Parameter::PT_INT + && param->type != Parameter::PT_IMPLIED ) + { + value.insert(0, "'"); + value.insert(value.length(), "'"); + } + + return value; +} + +Parameter::Type Value::get_param_type() const +{ + if ( param ) + return param->type; + + return Parameter::PT_MAX; +} + void Value::update_mask(uint8_t& mask, uint8_t flag, bool invert) { if ( get_bool() xor invert ) diff --git a/src/framework/value.h b/src/framework/value.h index b8190bd9d..df1760857 100644 --- a/src/framework/value.h +++ b/src/framework/value.h @@ -42,35 +42,72 @@ public: enum ValueType { VT_BOOL, VT_NUM, VT_STR }; Value(bool b) - { set(b); init(); } + { set(b); set_origin(b); } Value(double d) - { set(d); init(); } + { set(d); set_origin(d); } Value(const char* s) - { set(s); init(); } + { set(s); set_origin(s); } + + Value(const Value& v) : + type(v.type), + num(v.num), + str(v.str), + origin_str(v.origin_str), + ss(nullptr), + param(v.param) + {} + + Value& operator=(const Value& v) + { + if ( this == &v ) + return *this; + + delete ss; + ss = nullptr; + + type = v.type; + num = v.num; + str = v.str; + origin_str = v.origin_str; + param = v.param; + + return *this; + } ValueType get_type() { return type; } ~Value() - { - if ( ss ) - delete ss; - } + { delete ss; } void set(bool b) { type = VT_BOOL; num = b ? 1 : 0; str.clear(); } + void set_origin(bool val) + { origin_str = val ? "true" : "false"; } + void set(double d) { type = VT_NUM; num = d; str.clear(); } + void set_origin(double val) + { + auto temp = new std::stringstream; + *temp << val; + origin_str = temp->str(); + delete temp; + } + void set(long n) { set((double)n); } void set(const char* s) { type = VT_STR; str = s; num = 0; } + void set_origin(const char* val) + { origin_str = val; } + void set(const uint8_t* s, unsigned len) { type = VT_STR; str.assign((const char*)s, len); num = 0; } @@ -89,6 +126,9 @@ public: bool is(const char* s) const { return param ? !strcmp(param->name, s) : false; } + bool has_default() const + { return param ? param->deflt != nullptr : false; } + bool get_bool() const { return num != 0; } @@ -129,6 +169,8 @@ public: { return str.c_str(); } const char* get_as_string(); + Parameter::Type get_param_type() const; + std::string get_origin_string() const; bool strtol(long&) const; bool strtol(long&, const std::string&) const; @@ -171,16 +213,13 @@ public: void update_mask(uint32_t& mask, uint32_t flag, bool invert = false); void update_mask(uint64_t& mask, uint64_t flag, bool invert = false); -private: - void init() - { param = nullptr; ss = nullptr; } - private: ValueType type; double num; std::string str; - std::stringstream* ss; - const Parameter* param; + std::string origin_str; + std::stringstream* ss = nullptr; + const Parameter* param = nullptr; }; } #endif diff --git a/src/log/messages.cc b/src/log/messages.cc index e805d987f..7c308b38b 100644 --- a/src/log/messages.cc +++ b/src/log/messages.cc @@ -235,6 +235,16 @@ void LogMessage(FILE* fh, const char* format,...) va_end(ap); } +void LogConfig(const char* format, ...) +{ + va_list ap; + va_start(ap, format); + + WriteLogMessage(stdout, false, format, ap); + + va_end(ap); +} + /* * Function: WarningMessage(const char *, ...) * diff --git a/src/log/messages.h b/src/log/messages.h index a2ab4d282..d61e2e870 100644 --- a/src/log/messages.h +++ b/src/log/messages.h @@ -61,6 +61,7 @@ SO_PUBLIC void ParseError(const char*, ...) __attribute__((format (printf, 1, 2) SO_PUBLIC void ReloadError(const char*, ...) __attribute__((format (printf, 1, 2))); [[noreturn]] SO_PUBLIC void ParseAbort(const char*, ...) __attribute__((format (printf, 1, 2))); +SO_PUBLIC void LogConfig(const char*, ...) __attribute__((format (printf, 1, 2))); SO_PUBLIC void LogMessage(const char*, ...) __attribute__((format (printf, 1, 2))); SO_PUBLIC void LogMessage(FILE*, const char*, ...) __attribute__((format (printf, 2, 3))); SO_PUBLIC void WarningMessage(const char*, ...) __attribute__((format (printf, 1, 2))); diff --git a/src/main.cc b/src/main.cc index fcb8696b6..42db72182 100644 --- a/src/main.cc +++ b/src/main.cc @@ -822,6 +822,9 @@ static bool set_mode() return false; } + if ( sc->dump_config() ) + return false; + if ( just_validate(sc) ) { LogMessage("\nSnort successfully validated the configuration (with %u warnings).\n", diff --git a/src/main/CMakeLists.txt b/src/main/CMakeLists.txt index 502e5710d..954e543a9 100644 --- a/src/main/CMakeLists.txt +++ b/src/main/CMakeLists.txt @@ -21,6 +21,8 @@ add_library (main OBJECT analyzer.h analyzer_command.cc build.h + config_tree.cc + config_tree.h help.cc help.h modules.cc diff --git a/src/main/config_tree.cc b/src/main/config_tree.cc new file mode 100644 index 000000000..a68986923 --- /dev/null +++ b/src/main/config_tree.cc @@ -0,0 +1,103 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 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. +//-------------------------------------------------------------------------- +// config_tree.cc author Serhii Vlasiuk + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "config_tree.h" + +#include + +#include "log/messages.h" + +using namespace snort; + +void ConfigTextFormat::print(const BaseConfigNode* parent, const std::string& config_name) +{ + static char buf[16]; + int list_index = 0; + for ( const auto node : parent->get_children() ) + { + std::string full_config_name(config_name); + std::string node_name = node->get_name(); + + if ( !node_name.empty() ) + { + full_config_name += "."; + full_config_name += node_name; + } + else + { + sprintf(buf, "%i", list_index++); + full_config_name += "["; + full_config_name += buf; + full_config_name += "]"; + } + + print(node, full_config_name); + } + + std::string config_data = parent->data(); + if ( !config_data.empty() ) + LogConfig("%s=%s\n", config_name.c_str(), config_data.c_str()); +} + +BaseConfigNode::BaseConfigNode(BaseConfigNode* p) : + parent(p) +{} + +void BaseConfigNode::add_child_node(BaseConfigNode* node) +{ + assert(node); + children.push_back(node); +} + +void BaseConfigNode::clear_nodes(BaseConfigNode* node) +{ + for ( auto& config_node : node->children ) + clear_nodes(config_node); + + delete node; +} + +TreeConfigNode::TreeConfigNode(BaseConfigNode* parent_node, + const std::string& node_name, const Parameter::Type node_type) : + BaseConfigNode(parent_node), name(node_name), type(node_type) +{} + +BaseConfigNode* TreeConfigNode::get_node(const std::string& name) +{ + for ( auto node : children ) + { + if ( node->get_name() == name ) + return node; + } + return nullptr; +} + +ValueConfigNode::ValueConfigNode(BaseConfigNode* parent_node, const Value& val) : + BaseConfigNode(parent_node), value(val) +{} + +BaseConfigNode* ValueConfigNode::get_node(const std::string& name) +{ + return value.is(name.c_str()) and value.has_default() ? this : nullptr; +} + diff --git a/src/main/config_tree.h b/src/main/config_tree.h new file mode 100644 index 000000000..598dbb12e --- /dev/null +++ b/src/main/config_tree.h @@ -0,0 +1,109 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 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. +//-------------------------------------------------------------------------- +// config_tree.h author Serhii Vlasiuk + +#ifndef CONFIG_TREE_H +#define CONFIG_TREE_H + +#include + +#include "framework/value.h" + +class BaseConfigNode; + +using ChildrenNodes = std::list; + +class ConfigTextFormat +{ +public: + static void print(const BaseConfigNode* parent, const std::string& config_name); +}; + +class BaseConfigNode +{ +public: + BaseConfigNode(BaseConfigNode* parent); + virtual ~BaseConfigNode() = default; + + virtual std::string get_name() const = 0; + virtual snort::Parameter::Type get_type() const = 0; + virtual BaseConfigNode* get_node(const std::string& name) = 0; + virtual std::string data() const { return ""; } + virtual void set_value(const snort::Value&) {} + + const ChildrenNodes& get_children() const + { return children; } + + BaseConfigNode* get_parent_node() const + { return parent; } + + void add_child_node(BaseConfigNode* node); + + static void clear_nodes(BaseConfigNode* root); + +protected: + ChildrenNodes children; + BaseConfigNode* parent = nullptr; +}; + +class TreeConfigNode : public BaseConfigNode +{ +public: + TreeConfigNode(BaseConfigNode* parent, const std::string& node_name, + const snort::Parameter::Type node_type); + +private: + virtual std::string get_name() const override + { return name; } + + virtual snort::Parameter::Type get_type() const override + { return type; } + + virtual BaseConfigNode* get_node(const std::string& name) override; + +private: + std::string name; + snort::Parameter::Type type = snort::Parameter::PT_MAX; +}; + +class ValueConfigNode : public BaseConfigNode +{ +public: + ValueConfigNode(BaseConfigNode* parent, const snort::Value& value); + +private: + virtual std::string get_name() const override + { return value.get_name(); } + + virtual snort::Parameter::Type get_type() const override + { return value.get_param_type(); } + + virtual std::string data() const override + { return value.get_origin_string(); } + + virtual void set_value(const snort::Value& v) override + { value = v; } + + virtual BaseConfigNode* get_node(const std::string& name) override; + +private: + snort::Value value; +}; + +#endif // CONFIG_TREE_H + diff --git a/src/main/dev_notes.txt b/src/main/dev_notes.txt index aeae057fc..c4cae9e04 100644 --- a/src/main/dev_notes.txt +++ b/src/main/dev_notes.txt @@ -62,3 +62,12 @@ platform-independent abstraction layer for CPU and memory architecture information and management. Currently it is being used as a cross-platform mechanism for managing CPU affinity of threads, but it will be used in the future for NUMA (non-uniform memory access) awareness among other things. + +Consolidated Config output + +The snort config parsed is stored as an internal tree structure within the Shell. +A unique shell is associated with every base and targeted policy file. +Every module in a lua file is represented by the General Tree. +The Tree node can be one of the following types: TreeConfigNode, ValueConfigNode. +The TreeConfigNode represents a table or list. +The ValueConfigNode represents a config value itself. diff --git a/src/main/shell.cc b/src/main/shell.cc index b20f11666..c8b1c9bcd 100644 --- a/src/main/shell.cc +++ b/src/main/shell.cc @@ -26,9 +26,9 @@ #include #include -#include #include +#include "config_tree.h" #include "log/messages.h" #include "lua/lua.h" #include "main/policy.h" @@ -101,6 +101,125 @@ void Shell::whitelist_append(const char* keyword, bool is_prefix) sh->whitelist_update(keyword, is_prefix); } +void Shell::config_open_table(bool is_root_node, bool is_list, int idx, + const std::string& table_name, const Parameter* p) +{ + Parameter::Type node_type = is_list ? Parameter::PT_LIST : Parameter::PT_TABLE; + if ( is_root_node ) + add_config_root_node(table_name, node_type); + else + { + if ( p ) + node_type = p->type; + + if ( node_type == Parameter::PT_TABLE ) + update_current_config_node(table_name); + else + { + if ( idx ) + node_type = Parameter::PT_TABLE; + + add_config_child_node(table_name, node_type); + } + } +} + +void Shell::add_config_child_node(const std::string& node_name, snort::Parameter::Type type) +{ + Shell* sh = Shell::get_current_shell(); + + if ( !sh ) + return; + + std::string name; + if ( sh->s_current_node->get_name() != node_name ) + name = node_name; + + auto new_node = new TreeConfigNode(sh->s_current_node, name, type); + sh->s_current_node->add_child_node(new_node); + sh->s_current_node = new_node; +} + +void Shell::add_config_root_node(const std::string& root_name, snort::Parameter::Type node_type) +{ + Shell* sh = Shell::get_current_shell(); + + if ( !sh ) + return; + + sh->s_current_node = new TreeConfigNode(nullptr, root_name, node_type); + sh->config_trees.push_back(sh->s_current_node); +} + +void Shell::update_current_config_node(const std::string& node_name) +{ + Shell* sh = Shell::get_current_shell(); + + if ( !sh ) + return; + + if ( !sh->s_current_node ) + return; + + // node has been added during setting default options + if ( !node_name.empty() ) + sh->s_current_node = sh->s_current_node->get_node(node_name); + else if ( sh->s_current_node->get_parent_node() and + sh->s_current_node->get_type() == Parameter::PT_TABLE and + !sh->s_current_node->get_name().empty() ) + sh->s_current_node = sh->s_current_node->get_parent_node(); + + assert(sh->s_current_node); +} + +void Shell::config_close_table() +{ + Shell* sh = Shell::get_current_shell(); + + if ( !sh ) + return; + + if ( !sh->s_current_node ) + return; + + sh->s_current_node = sh->s_current_node->get_parent_node(); +} + +void Shell::set_config_value(const snort::Value& value) +{ + Shell* sh = Shell::get_current_shell(); + + if ( !sh ) + return; + + if ( !sh->s_current_node ) + return; + + // lua interpreter does not call open_table for simple list items like (string) + // we have to add tree node for this item too + if ( sh->s_current_node->get_type() == Parameter::PT_LIST ) + { + add_config_child_node("", Parameter::PT_TABLE); + sh->s_current_node->add_child_node(new ValueConfigNode(sh->s_current_node, value)); + sh->s_current_node = sh->s_current_node->get_parent_node(); + + return; + } + + BaseConfigNode* child_node = nullptr; + for ( auto node : sh->s_current_node->get_children() ) + { + child_node = node->get_node(value.get_name()); + if ( child_node ) + break; + } + + if ( !child_node ) + sh->s_current_node->add_child_node(new ValueConfigNode(sh->s_current_node, value)); + else + child_node->set_value(value); +} + // FIXIT-L shell --pause should stop before loading config so Lua state // can be examined and modified. @@ -155,7 +274,6 @@ static void load_string(lua_State* L, const char* s) FatalError("can't init overrides: %s\n", lua_tostring(L, -1)); } - //------------------------------------------------------------------------- // public methods //------------------------------------------------------------------------- @@ -264,6 +382,14 @@ bool Shell::configure(SnortConfig* sc, bool is_fatal, bool is_root) load_string(lua, ModuleManager::get_lua_finalize()); clear_whitelist(); + + if ( SnortConfig::get_conf()->dump_config() ) + { + sort_config(); + print_config_text(); + clear_config_tree(); + } + current_shells.pop(); set_default_policy(sc); @@ -333,6 +459,29 @@ static void print_list(const Shell::Whitelist& wlist, const std::string& msg) //------------------------------------------------------------------------- // private methods //------------------------------------------------------------------------- +void Shell::sort_config() +{ + config_trees.sort([](const BaseConfigNode* l, const BaseConfigNode* r) + { return l->get_name() < r->get_name(); }); +} + +void Shell::print_config_text() const +{ + std::string output("consolidated config for "); + output += file; + LogConfig("%s\n", output.c_str()); + + for ( const auto config_tree: config_trees ) + ConfigTextFormat::print(config_tree, config_tree->get_name()); +} + +void Shell::clear_config_tree() +{ + for ( auto config_tree: config_trees ) + BaseConfigNode::clear_nodes(config_tree); + + config_trees.clear(); +} void Shell::print_whitelist() const { diff --git a/src/main/shell.h b/src/main/shell.h index e3578105a..ef6883d98 100644 --- a/src/main/shell.h +++ b/src/main/shell.h @@ -22,15 +22,21 @@ // Shell encapsulates a Lua state. There is one for each policy file. +#include #include #include #include +#include "framework/parameter.h" + struct lua_State; +class BaseConfigNode; + namespace snort { struct SnortConfig; +class Value; } class Shell @@ -62,6 +68,16 @@ public: static bool is_whitelisted(const std::string& key); static void whitelist_append(const char* keyword, bool is_prefix); + static void config_open_table(bool is_root_node, bool is_list, int idx, + const std::string& table_name, const snort::Parameter* p); + static void set_config_value(const snort::Value& value); + static void add_config_child_node(const std::string& node_name, snort::Parameter::Type type); + static void update_current_config_node(const std::string& node_name = ""); + static void config_close_table(); + +private: + static void add_config_root_node(const std::string& root_name, snort::Parameter::Type type); + private: [[noreturn]] static int panic(lua_State*); static Shell* get_current_shell(); @@ -90,6 +106,10 @@ private: void print_whitelist() const; void whitelist_update(const char* keyword, bool is_prefix); + void sort_config(); + void print_config_text() const; + void clear_config_tree(); + private: bool loaded; bool bootstrapped = false; @@ -100,6 +120,8 @@ private: Whitelist whitelist; Whitelist internal_whitelist; Whitelist whitelist_prefixes; + std::list config_trees; + BaseConfigNode* s_current_node = nullptr; }; #endif diff --git a/src/main/snort.cc b/src/main/snort.cc index 432cbf5c5..28e665b43 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -426,7 +426,7 @@ void Snort::cleanup() SFDAQ::term(); FileService::close(); - if ( !SnortConfig::get_conf()->test_mode() ) // FIXIT-M ideally the check is in one place + if ( !SnortConfig::get_conf()->validation_mode() ) // FIXIT-M ideally the check is in one place PrintStatistics(); CloseLogger(); diff --git a/src/main/snort_config.h b/src/main/snort_config.h index 70ba985f4..30a7fbbec 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -81,6 +81,7 @@ enum RunFlag RUN_FLAG__IP_FRAGS_ONLY = 0x08000000, RUN_FLAG__DUMP_RULE_STATE = 0x10000000, + RUN_FLAG__DUMP_CONFIG = 0x20000000, }; enum OutputFlag @@ -500,6 +501,9 @@ public: { return address_anomaly_check_enabled; } // mode related + bool dump_config() const + { return run_flags & RUN_FLAG__DUMP_CONFIG; } + bool dump_msg_map() const { return run_flags & RUN_FLAG__DUMP_MSG_MAP; } @@ -518,11 +522,14 @@ public: bool test_mode() const { return run_flags & RUN_FLAG__TEST; } + bool validation_mode() const + { return test_mode() or dump_config(); } + bool mem_check() const - { return run_flags & RUN_FLAG__MEM_CHECK; } + { return (run_flags & RUN_FLAG__MEM_CHECK) and !dump_config(); } bool daemon_mode() const - { return run_flags & RUN_FLAG__DAEMON; } + { return (run_flags & RUN_FLAG__DAEMON) and !dump_config(); } bool read_mode() const { return run_flags & RUN_FLAG__READ; } diff --git a/src/main/snort_module.cc b/src/main/snort_module.cc index e936098fa..5de0697ee 100644 --- a/src/main/snort_module.cc +++ b/src/main/snort_module.cc @@ -347,6 +347,9 @@ static const Parameter s_params[] = { "--dump-builtin-rules", Parameter::PT_STRING, "(optional)", nullptr, "[] output stub rules for selected modules" }, + { "--dump-config-text", Parameter::PT_IMPLIED, nullptr, nullptr, + "dump config in text format" }, + // FIXIT-L add --list-dynamic-rules like --list-builtin-rules { "--dump-dynamic-rules", Parameter::PT_IMPLIED, nullptr, nullptr, "output stub rules for all loaded rules libraries" }, @@ -601,9 +604,6 @@ static const Parameter s_params[] = { "--x2s", Parameter::PT_STRING, nullptr, nullptr, "output ASCII string for given byte code (see also --x2c)" }, - { "--trace", Parameter::PT_IMPLIED, nullptr, nullptr, - "turn on main loop debug trace" }, - { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; @@ -868,6 +868,12 @@ bool SnortModule::set(const char*, Value& v, SnortConfig* sc) else if ( v.is("--dump-builtin-rules") ) dump_builtin_rules(sc, v.get_string()); + else if ( v.is("--dump-config-text") ) + { + sc->run_flags |= RUN_FLAG__DUMP_CONFIG; + sc->set_quiet(true); + } + else if ( v.is("--dump-dynamic-rules") ) dump_dynamic_rules(sc, v.get_string()); diff --git a/src/managers/module_manager.cc b/src/managers/module_manager.cc index fb9371269..b27bd269d 100644 --- a/src/managers/module_manager.cc +++ b/src/managers/module_manager.cc @@ -166,6 +166,14 @@ void ModHook::init() //------------------------------------------------------------------------- // helper functions //------------------------------------------------------------------------- +static std::string get_sub_table(const std::string& fqn) +{ + auto pos = fqn.find_last_of("."); + if ( pos != std::string::npos ) + return fqn.substr(pos + 1); + else + return fqn; +} static void set_type(string& fqn) { @@ -446,6 +454,9 @@ static bool set_var(const char* fqn, Value& v) static bool set_param(Module* mod, const char* fqn, Value& val) { + if ( s_config->dump_config() ) + Shell::set_config_value(val); + if ( !mod->verified_set(fqn, val, s_config) ) { ParseError("%s is invalid", fqn); @@ -583,6 +594,9 @@ static bool begin(Module* m, const Parameter* p, const char* s, int idx, int dep { const Parameter* table_item_params = reinterpret_cast(p->range); + if ( s_config->dump_config() ) + Shell::add_config_child_node(get_sub_table(fqn), p->type); + if ( !begin(m, table_item_params, fqn.c_str(), idx, depth+1) ) return false; } @@ -619,6 +633,8 @@ static bool begin(Module* m, const Parameter* p, const char* s, int idx, int dep } ++p; } + if ( s_config->dump_config() ) + Shell::update_current_config_node(); return true; } @@ -747,6 +763,19 @@ SO_PUBLIC bool open_table(const char* s, int idx) s_current = unique_key; } + if ( s_config->dump_config() ) + { + std::string table_name = get_sub_table(s); + bool is_top_level = false; + if ( top_level(s) && !idx ) + { + table_name = s_current; + is_top_level = true; + } + + Shell::config_open_table(is_top_level, m->is_list(), idx, table_name, p); + } + if ( !begin(m, p, s, idx, 0) ) { ParseError("can't open %s", m->get_name()); @@ -786,6 +815,9 @@ SO_PUBLIC void close_table(const char* s, int idx) s_name.clear(); s_type.clear(); } + + if ( s_config->dump_config() ) + Shell::config_close_table(); } SO_PUBLIC bool set_bool(const char* fqn, bool b) diff --git a/src/trace/trace_module.cc b/src/trace/trace_module.cc index 68f8e6368..6d4a0353a 100644 --- a/src/trace/trace_module.cc +++ b/src/trace/trace_module.cc @@ -84,6 +84,9 @@ void TraceModule::generate_params() } } + std::sort(modules_params.begin(), modules_params.end(), + [](const Parameter& l, const Parameter& r) { return (strcmp(l.name, r.name) < 0); }); + modules_params.emplace_back(nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr); const static Parameter trace_constraints_params[] = @@ -174,28 +177,34 @@ bool TraceModule::end(const char* fqn, int, SnortConfig* sc) if ( !strcmp(fqn, "trace") ) { assert(trace_parser); - switch ( log_output_type ) - { - case OUTPUT_TYPE_STDOUT: - trace_parser->get_trace_config()->logger_factory = new StdoutLoggerFactory(); - break; - case OUTPUT_TYPE_SYSLOG: - trace_parser->get_trace_config()->logger_factory = new SyslogLoggerFactory(); - break; - default: - break; - } - // "output=syslog" config override case - // do not closelog() here since it will be closed in Snort::clean_exit() - if ( !sc->log_syslog() and log_output_type == OUTPUT_TYPE_SYSLOG - and !local_syslog ) + if ( sc->dump_config() ) + trace_parser->clear_traces(); + else { - local_syslog = true; - openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON); - } + switch ( log_output_type ) + { + case OUTPUT_TYPE_STDOUT: + trace_parser->get_trace_config()->logger_factory = new StdoutLoggerFactory(); + break; + case OUTPUT_TYPE_SYSLOG: + trace_parser->get_trace_config()->logger_factory = new SyslogLoggerFactory(); + break; + default: + break; + } - trace_parser->finalize_constraints(); + // "output=syslog" config override case + // do not closelog() here since it will be closed in Snort::clean_exit() + if ( !sc->log_syslog() and log_output_type == OUTPUT_TYPE_SYSLOG + and !local_syslog ) + { + local_syslog = true; + openlog("snort", LOG_PID | LOG_CONS, LOG_DAEMON); + } + + trace_parser->finalize_constraints(); + } delete trace_parser; trace_parser = nullptr; -- 2.47.3