diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /src/util-debug.h | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/util-debug.h')
-rw-r--r-- | src/util-debug.h | 550 |
1 files changed, 550 insertions, 0 deletions
diff --git a/src/util-debug.h b/src/util-debug.h new file mode 100644 index 0000000..2a0864c --- /dev/null +++ b/src/util-debug.h @@ -0,0 +1,550 @@ +/* Copyright (C) 2007-2022 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * 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 + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Anoop Saldanha <anoopsaldanha@gmail.com> + */ + +#ifndef __UTIL_DEBUG_H__ +#define __UTIL_DEBUG_H__ + +#include "suricata-common.h" + +#include "threads.h" +#include "util-error.h" +#include "util-debug-filters.h" + +/** + * \brief ENV vars that can be used to set the properties for the logging module + */ +#define SC_LOG_ENV_LOG_LEVEL "SC_LOG_LEVEL" +#define SC_LOG_ENV_LOG_OP_IFACE "SC_LOG_OP_IFACE" +#define SC_LOG_ENV_LOG_FILE "SC_LOG_FILE" +#define SC_LOG_ENV_LOG_FACILITY "SC_LOG_FACILITY" +#define SC_LOG_ENV_LOG_FORMAT "SC_LOG_FORMAT" +#define SC_LOG_ENV_LOG_OP_FILTER "SC_LOG_OP_FILTER" + +/** + * \brief The various log levels + * NOTE: when adding new level, don't forget to update SCLogMapLogLevelToSyslogLevel() + * or it may result in logging to syslog with LOG_EMERG priority. + */ +typedef enum { + SC_LOG_NOTSET = -1, + SC_LOG_NONE = 0, + SC_LOG_ERROR, + SC_LOG_WARNING, + SC_LOG_NOTICE, + SC_LOG_INFO, + SC_LOG_PERF, + SC_LOG_CONFIG, + SC_LOG_DEBUG, + SC_LOG_LEVEL_MAX, +} SCLogLevel; + +/** + * \brief The various output interfaces supported + */ +typedef enum { + SC_LOG_OP_IFACE_CONSOLE, + SC_LOG_OP_IFACE_FILE, + SC_LOG_OP_IFACE_SYSLOG, + SC_LOG_OP_IFACE_MAX, +} SCLogOPIface; + +typedef enum { + SC_LOG_OP_TYPE_REGULAR = 0, + SC_LOG_OP_TYPE_JSON, +} SCLogOPType; + +/* The default log_format, if it is not supplied by the user */ +#define SC_LOG_DEF_FILE_FORMAT "[%i - %m] %z %d: %S: %M" +#define SC_LOG_DEF_LOG_FORMAT_REL_NOTICE "%D: %S: %M" +#define SC_LOG_DEF_LOG_FORMAT_REL_INFO "%d: %S: %M" +#define SC_LOG_DEF_LOG_FORMAT_REL_CONFIG "[%i] %d: %S: %M" +#define SC_LOG_DEF_LOG_FORMAT_DEBUG "%d: %S: %M [%n:%f:%l]" + +/* The maximum length of the log message */ +#define SC_LOG_MAX_LOG_MSG_LEN 2048 + +/* The maximum length of the log format */ +#define SC_LOG_MAX_LOG_FORMAT_LEN 128 + +/* The default log level, if it is not supplied by the user */ +#define SC_LOG_DEF_LOG_LEVEL SC_LOG_INFO + +/* The default output interface to be used */ +#define SC_LOG_DEF_LOG_OP_IFACE SC_LOG_OP_IFACE_CONSOLE + +/* The default log file to be used */ +#define SC_LOG_DEF_LOG_FILE "suricata.log" + +/* The default syslog facility to be used */ +#define SC_LOG_DEF_SYSLOG_FACILITY_STR "local0" +#define SC_LOG_DEF_SYSLOG_FACILITY LOG_LOCAL0 + +/** + * \brief Structure to be used when log_level override support would be provided + * by the logging module + */ +typedef struct SCLogOPBuffer_ { + char msg[SC_LOG_MAX_LOG_MSG_LEN]; + char *temp; + const char *log_format; +} SCLogOPBuffer; + +/** + * \brief The output interface context for the logging module + */ +typedef struct SCLogOPIfaceCtx_ { + SCLogOPIface iface; + + int16_t use_color; + SCLogOPType type; + + /* the output file to be used if the interface is SC_LOG_IFACE_FILE */ + const char *file; + /* the output file descriptor for the above file */ + FILE * file_d; + + /* registered to be set on a file rotation signal */ + int rotation_flag; + + /* the facility code if the interface is SC_LOG_IFACE_SYSLOG */ + int facility; + + /* override for the global_log_level */ + SCLogLevel log_level; + + /* override for the global_log_format(currently not used) */ + const char *log_format; + + /* Mutex used for locking around rotate/write to a file. */ + SCMutex fp_mutex; + + struct SCLogOPIfaceCtx_ *next; +} SCLogOPIfaceCtx; + +/** + * \brief Structure containing init data, that would be passed to + * SCInitDebugModule() + */ +typedef struct SCLogInitData_ { + /* startup message */ + const char *startup_message; + + /* the log level */ + SCLogLevel global_log_level; + + /* the log format */ + const char *global_log_format; + + /* output filter */ + const char *op_filter; + + /* list of output interfaces to be used */ + SCLogOPIfaceCtx *op_ifaces; + /* no of op ifaces */ + uint8_t op_ifaces_cnt; +} SCLogInitData; + +/** + * \brief Holds the config state used by the logging api + */ +typedef struct SCLogConfig_ { + char *startup_message; + SCLogLevel log_level; + char *log_format; + + char *op_filter; + /* compiled pcre filter expression */ + pcre2_code *op_filter_regex; + pcre2_match_data *op_filter_regex_match; + + /* op ifaces used */ + SCLogOPIfaceCtx *op_ifaces; + /* no of op ifaces */ + uint8_t op_ifaces_cnt; +} SCLogConfig; + +/* The different log format specifiers supported by the API */ +#define SC_LOG_FMT_TIME 'z' /* Timestamp in RFC3339 like format */ +#define SC_LOG_FMT_TIME_LEGACY 't' /* Timestamp in legacy format */ +#define SC_LOG_FMT_PID 'p' /* PID */ +#define SC_LOG_FMT_TID 'i' /* Thread ID */ +#define SC_LOG_FMT_TM 'm' /* Thread module name */ +#define SC_LOG_FMT_LOG_LEVEL 'd' /* Log level */ +#define SC_LOG_FMT_LOG_SLEVEL 'D' /* Log level */ +#define SC_LOG_FMT_FILE_NAME 'f' /* File name */ +#define SC_LOG_FMT_LINE 'l' /* Line number */ +#define SC_LOG_FMT_FUNCTION 'n' /* Function */ +#define SC_LOG_FMT_SUBSYSTEM 'S' /* Subsystem name */ +#define SC_LOG_FMT_THREAD_NAME 'T' /* thread name */ +#define SC_LOG_FMT_MESSAGE 'M' /* log message body */ + +/* The log format prefix for the format specifiers */ +#define SC_LOG_FMT_PREFIX '%' + +/* Module and thread tagging */ +/* The module name, usually the containing source-module name */ +static const char *_sc_module __attribute__((unused)) = __SCFILENAME__; + +extern SCLogLevel sc_log_global_log_level; + +extern int sc_log_module_initialized; + +extern int sc_log_module_cleaned; + +void SCLog(int x, const char *file, const char *func, const int line, const char *module, + const char *fmt, ...) ATTR_FMT_PRINTF(6, 7); +void SCLogErr(int x, const char *file, const char *func, const int line, const char *module, + const char *fmt, ...) ATTR_FMT_PRINTF(6, 7); + +/** + * \brief Macro used to log INFORMATIONAL messages. + * + * \retval ... Takes as argument(s), a printf style format message + */ +#define SCLogInfo(...) SCLog(SC_LOG_INFO, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) +#define SCLogInfoRaw(file, func, line, ...) \ + SCLog(SC_LOG_INFO, (file), (func), (line), _sc_module, __VA_ARGS__) + +#define SCLogConfig(...) \ + SCLog(SC_LOG_CONFIG, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) +#define SCLogPerf(...) SCLog(SC_LOG_PERF, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) + +/** + * \brief Macro used to log NOTICE messages. + * + * \retval ... Takes as argument(s), a printf style format message + */ +#define SCLogNotice(...) \ + SCLog(SC_LOG_NOTICE, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) +#define SCLogNoticeRaw(file, func, line, ...) \ + SCLog(SC_LOG_NOTICE, (file), (func), (line), _sc_module, __VA_ARGS__) + +/** + * \brief Macro used to log WARNING messages. + * + * \retval err_code Error code that has to be logged along with the + * warning message + * \retval ... Takes as argument(s), a printf style format message + */ +#define SCLogWarning(...) \ + SCLogErr(SC_LOG_WARNING, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) +#define SCLogWarningRaw(file, func, line, ...) \ + SCLogErr(SC_LOG_WARNING, (file), (func), (line), _sc_module, __VA_ARGS__) + +/** + * \brief Macro used to log ERROR messages. + * + * \retval err_code Error code that has to be logged along with the + * error message + * \retval ... Takes as argument(s), a printf style format message + */ +#define SCLogError(...) \ + SCLogErr(SC_LOG_ERROR, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) +#define SCLogErrorRaw(file, func, line, ...) \ + SCLogErr(SC_LOG_ERROR, (file), (func), (line), _sc_module, __VA_ARGS__) + +/* Avoid the overhead of using the debugging subsystem, in production mode */ +#ifndef DEBUG + +#define SCLogDebug(...) do { } while (0) + +#define SCEnter(...) + +#define SCReturn return + +#define SCReturnInt(x) return x + +#define SCReturnUInt(x) return x + +#define SCReturnDbl(x) return x + +#define SCReturnChar(x) return x + +#define SCReturnCharPtr(x) return x + +#define SCReturnCT(x, type) return x + +#define SCReturnPtr(x, type) return x + +#define SCReturnBool(x) return x + +#define SCReturnStruct(x) return x + +/* Please use it only for debugging purposes */ +#else + + +/** + * \brief Macro used to log DEBUG messages. Comes under the debugging subsystem, + * and hence will be enabled only in the presence of the DEBUG macro. + * + * \retval ... Takes as argument(s), a printf style format message + */ +#define SCLogDebug(...) \ + SCLog(SC_LOG_DEBUG, __FILE__, __FUNCTION__, __LINE__, _sc_module, __VA_ARGS__) + +/** + * \brief Macro used to log debug messages on function entry. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_entry logs, it also + * processes the FD filters, if any FD filters are registered. + * + * \retval f An argument can be supplied, although it is not used + */ +#define SCEnter(f) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG &&\ + SCLogCheckFDFilterEntry(__FUNCTION__)) \ + { \ + SCLogDebug("Entering ... >>"); \ + } \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that don't return + * a value. + */ +#define SCReturn do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning ... <<" ); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns an + * integer value. + * + * \retval x Variable of type 'integer' that has to be returned + */ +#define SCReturnInt(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: %"PRIdMAX" ... <<", (intmax_t)x); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns an + * unsigned integer value. + * + * \retval x Variable of type 'unsigned integer' that has to be returned + */ +#define SCReturnUInt(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: %"PRIuMAX" ... <<", (uintmax_t)x); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a + * float/double value. + * + * \retval x Variable of type 'float/double' that has to be returned + */ +#define SCReturnDbl(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: %f ... <<", x); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a var + * of character type. + * + * \retval x Variable of type 'char' that has to be returned + */ +#define SCReturnChar(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: %c ... <<", x); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a + * character string. + * + * \retval x Pointer to the char string that has to be returned + */ +#define SCReturnCharPtr(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + if ((x) != NULL) { \ + SCLogDebug("Returning: %s ... <<", x); \ + } else { \ + SCLogDebug("Returning: NULL ... <<"); \ + } SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a var + * of custom type + * + * \retval x Variable instance of a custom type that has to be returned + * \retval type Pointer to a character string holding the name of the custom + * type(the argument x) that has to be returned + */ +#define SCReturnCT(x, type) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning var of " \ + "type %s ... <<", type); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a + * pointer to a custom type + * + * \retval x Pointer to a variable instance of a custom type that has to be + * returned + * \retval type Pointer to a character string holding the name of the custom + * type(the argument x) that has to be returned + */ +#define SCReturnPtr(x, type) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning pointer %p of " \ + "type %s ... <<", x, type); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +/** + * \brief Macro used to log debug messages on function exit. Comes under the + * debugging subsystem, and hence will be enabled only in the presence + * of the DEBUG macro. Apart from logging function_exit logs, it also + * processes the FD filters, if any FD filters are registered. This + * function_exit macro should be used for functions that returns a + * boolean value. + * + * \retval x Variable of type 'bool' that has to be returned + */ +#define SCReturnBool(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: %s ... <<", x ? "true" : "false"); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +#define SCReturnStruct(x) do { \ + if (sc_log_global_log_level >= SC_LOG_DEBUG) { \ + SCLogDebug("Returning: ... <<"); \ + SCLogCheckFDFilterExit(__FUNCTION__); \ + } \ + return x; \ + } while(0) + +#endif /* DEBUG */ + +#define FatalError(...) \ + do { \ + SCLogError(__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } while (0) + +/** \brief Fatal error IF we're starting up, and configured to consider + * errors to be fatal errors */ +#if !defined(__clang_analyzer__) +#define FatalErrorOnInit(...) \ + do { \ + SC_ATOMIC_EXTERN(unsigned int, engine_stage); \ + int init_errors_fatal = 0; \ + (void)ConfGetBool("engine.init-failure-fatal", &init_errors_fatal); \ + if (init_errors_fatal && (SC_ATOMIC_GET(engine_stage) == SURICATA_INIT)) { \ + SCLogError(__VA_ARGS__); \ + exit(EXIT_FAILURE); \ + } \ + SCLogWarning(__VA_ARGS__); \ + } while (0) +/* make it simpler for scan-build */ +#else +#define FatalErrorOnInit(...) FatalError(__VA_ARGS__) +#endif + +#define BOOL2STR(b) (b) ? "true" : "false" + +SCLogInitData *SCLogAllocLogInitData(void); + +void SCLogAppendOPIfaceCtx(SCLogOPIfaceCtx *, SCLogInitData *); + +void SCLogInitLogModule(SCLogInitData *); + +void SCLogDeInitLogModule(void); + +SCError SCLogMessage(const SCLogLevel, const char *, const unsigned int, const char *, const char *, + const char *message); + +SCLogOPBuffer *SCLogAllocLogOPBuffer(void); + +int SCLogDebugEnabled(void); + +void SCLogRegisterTests(void); + +void SCLogLoadConfig(int daemon, int verbose, uint32_t userid, uint32_t groupid); + +SCLogLevel SCLogGetLogLevel(void); + +#endif /* __UTIL_DEBUG_H__ */ |