From f258d61c6b679db940430c1390d6eda2ac3b78de Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Thu, 21 Jan 2010 10:22:02 -0800 Subject: [PATCH 1/2] Making logging configurable. If no logging outputs are defined the default will be used. - Currently per output log formatting is not available. --- src/util-debug.c | 114 ++++++++++++++++++++++++++++++++++++++--------------- src/util-error.c | 2 +- src/util-error.h | 1 + suricata.yaml | 47 ++++++++-------------- 4 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/util-debug.c b/src/util-debug.c index 53b387d..3f86b19 100644 --- a/src/util-debug.c +++ b/src/util-debug.c @@ -256,9 +256,9 @@ void SCLogOutputBuffer(SCLogLevel log_level, char *msg) SCError SCLogMessage(SCLogLevel log_level, char **msg, const char *file, unsigned line, const char *function) { - char *temp_fmt = strdup(sc_log_config->log_format); + char *temp_fmt = strdup(sc_log_config->log_format); char *temp_fmt_h = temp_fmt; - char *substr = temp_fmt; + char *substr = temp_fmt; char *temp = *msg; const char *s = NULL; @@ -1010,53 +1010,103 @@ void SCLogInitLogModule(SCLogInitData *sc_lid) void SCLogLoadConfig(void) { ConfNode *outputs; + SCLogInitData *sc_lid; - outputs = ConfGetNode("logging.output"); + outputs = ConfGetNode("logging.outputs"); if (outputs == NULL) { SCLogDebug("No logging.output configuration section found."); return; } - /* Process each output. */ - ConfNode *output; - TAILQ_FOREACH(output, &outputs->head, next) { - //ConfNode *param; - const char *interface = NULL; - const char *log_level = NULL; - const char *facility = NULL; - //const char *filename = NULL; - const char *format = NULL; - - interface = ConfNodeLookupChildValue(output, "interface"); - if (interface == NULL) { - /* No interface in this item, ignore. */ - continue; - } - if (SCMapEnumNameToValue(interface, sc_log_op_iface_map) < 0) { - SCLogError(SC_INVALID_ARGUMENT, - "Invalid logging interface: %s", interface); + sc_lid = SCLogAllocLogInitData(); + + /* Get default log level and format. */ + char *default_log_level_s = NULL; + if (ConfGet("logging.default-log-level", &default_log_level_s) == 1) { + sc_lid->global_log_level = + SCMapEnumNameToValue(default_log_level_s, sc_log_level_map); + if (sc_lid->global_log_level == -1) { + SCLogError(SC_INVALID_ARGUMENT, "Invalid default log level: %s", + default_log_level_s); exit(EXIT_FAILURE); } + } + else { + SCLogWarning(SC_ERR_MISSING_CONFIG_PARAM, + "No default log level set, will use info."); + sc_lid->global_log_level = SC_LOG_INFO; + } + if (ConfGet("logging.default-log-format", &sc_lid->global_log_format) != 1) + sc_lid->global_log_format = SC_LOG_DEF_LOG_FORMAT; + + ConfNode *seq_node, *output; + TAILQ_FOREACH(seq_node, &outputs->head, next) { + SCLogLevel level = sc_lid->global_log_level; + SCLogOPIfaceCtx *op_iface_ctx = NULL; + const char *format; + const char *level_s; + + output = ConfNodeLookupChild(seq_node, seq_node->val); + if (output == NULL) + continue; - /* Any output may have a log-level set. */ - log_level = ConfNodeLookupChildValue(output, "log-level"); + /* By default an output is enabled. */ + const char *enabled = ConfNodeLookupChildValue(output, "enabled"); + if (enabled != NULL && strcmp(enabled, "no") == 0) + continue; - /* Any output may have a format set. */ format = ConfNodeLookupChildValue(output, "format"); + level_s = ConfNodeLookupChildValue(output, "level"); + if (level_s != NULL) { + level = SCMapEnumNameToValue(level_s, sc_log_level_map); + if (level == -1) { + SCLogError(SC_INVALID_ARGUMENT, "Invalid log level: %s", + level_s); + exit(EXIT_FAILURE); + } + } - if (strcmp(interface, "console") == 0) { - /* No other lookups required for console logging. */ - /* \todo Setup console logging... */ + if (strcmp(output->name, "console") == 0) { + op_iface_ctx = SCLogInitConsoleOPIface(format, level); + } + else if (strcmp(output->name, "file") == 0) { + const char *filename = ConfNodeLookupChildValue(output, "filename"); + if (filename == NULL) { + SCLogError(SC_ERR_MISSING_CONFIG_PARAM, + "Logging to file requires a filename"); + exit(EXIT_FAILURE); + } + op_iface_ctx = SCLogInitFileOPIface(filename, format, level); } - else if (strcmp(interface, "syslog") == 0) { - /* \todo Setup syslog logging. */ - facility = ConfNodeLookupChildValue(output, "facility"); + else if (strcmp(output->name, "syslog") == 0) { + int facility = SC_LOG_DEF_SYSLOG_FACILITY; + const char *facility_s = ConfNodeLookupChildValue(output, + "facility"); + if (facility_s != NULL) { + facility = SCMapEnumNameToValue(facility_s, + sc_syslog_facility_map); + if (facility == -1) { + SCLogError(SC_INVALID_ARGUMENT, + "Invalid syslog facility: %s", facility_s); + exit(EXIT_FAILURE); + } + } + printf("Initialization syslog logging with format \"%s\".\n", + format); + op_iface_ctx = SCLogInitSyslogOPIface(facility, format, level); } else { - SCLogWarning(SC_UNIMPLEMENTED, - "Ignoring unknown logging interface: %s", interface); + SCLogWarning(SC_INVALID_ARGUMENT, "Invalid logging method: %s, " + "ignoring", output->name); + } + if (op_iface_ctx != NULL) { + SCLogAppendOPIfaceCtx(op_iface_ctx, sc_lid); } } + + SCLogInitLogModule(sc_lid); + //exit(1); + /* \todo Can we free sc_lid now? */ } /** diff --git a/src/util-error.c b/src/util-error.c index bec4056..beba4ce 100644 --- a/src/util-error.c +++ b/src/util-error.c @@ -77,7 +77,7 @@ const char * SCErrorToString(SCError err) CASE_CODE (SC_ERR_MISSING_QUOTE); CASE_CODE (SC_ERR_UNKNOWN_PROTOCOL); CASE_CODE (SC_ERR_UNKNOWN_RUN_MODE); - + CASE_CODE (SC_ERR_MISSING_CONFIG_PARAM); default: return "UNKNOWN_ERROR"; } diff --git a/src/util-error.h b/src/util-error.h index f9d7e12..343d5e3 100644 --- a/src/util-error.h +++ b/src/util-error.h @@ -91,6 +91,7 @@ typedef enum { SC_ERR_STAT_ERROR, SC_ERR_LOGDIR_CONFIG, SC_ERR_LOGDIR_CMDLINE, + SC_ERR_MISSING_CONFIG_PARAM, SC_RADIX_TREE_GENERIC_ERROR, SC_ERR_MISSING_QUOTE, SC_ERR_MUTEX, diff --git a/suricata.yaml b/suricata.yaml index 3f9bd0f..9a2c0a0 100644 --- a/suricata.yaml +++ b/suricata.yaml @@ -6,6 +6,7 @@ # overridden with the -l command line parameter. default-log-dir: /var/log/suricata +# Configure the type of alert (and other) logging you would like. outputs: - fast: @@ -99,43 +100,31 @@ flow-timeouts: logging: # The default log level, can be overridden in an output section. - default-log-level: debug + # Note that debug level logging will only be emitted if Suricata was + # compiled with the --enable-debug configure option. + default-log-level: info # The default output format. Optional parameter, should default to # something reasonable if not provided. Can be overriden in an - # output section. - default-format: "<%t> - <%l>" - - # Default startup message. Optional parameter, should default to - # something reasonable if not provided. Can be overridden in an - # output section. - default-startup-message: Your IDS has started. + # output section. You can leave this out to get the default. + #default-log-format: "[%i] %t - (%f:%l) <%d> (%n) -- " # A regex to filter output. Can be overridden in an output section. # Defaults to empty (no filter). default-output-filter: - # Configure the outputs. If no outputs are specified the engine - # will log to the console with an error log level. - output: - - # Enable logging to the console. Be a little more verbose than - # default, log info and more critical. - - interface: console - log-level: error - - # Log to a file as well. No log level specified so level will be - # set to the default-log-level. - - interface: file - filename: /var/log/suricata.log - - # Log to syslog with facility local5. Again, no level specified so - # will level will be set to default-log-level. We also override the - # format as we don't want to log a timestamp, syslog will do that - # for us. - - interface: syslog - facility: local5 - format: "%l" + # Define your logging outputs. If none are define, or they are all + # disabled you will get the default - console output. + outputs: + - console: + enabled: yes + - file: + enabled: no + filename: /var/log/suricata.log + - syslog: + enabled: no + facility: local5 + format: "[%i] <%d> -- " # PF_RING configuration. for use with native PF_RING support # for more info see http://www.ntop.org/PF_RING.html -- 1.6.6