summaryrefslogtreecommitdiffstats
path: root/src/include/log.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/include/log.h390
1 files changed, 390 insertions, 0 deletions
diff --git a/src/include/log.h b/src/include/log.h
new file mode 100644
index 0000000..2736591
--- /dev/null
+++ b/src/include/log.h
@@ -0,0 +1,390 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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 St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef FR_LOG_H
+#define FR_LOG_H
+/**
+ * $Id$
+ *
+ * @file log.h
+ * @brief Macros and function definitions to write log messages, and control the logging system.
+ *
+ * @copyright 2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ * @copyright 2013 Alan DeKok <aland@freeradius.org>
+ */
+RCSIDH(log_h, "$Id$")
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum log_type {
+ L_AUTH = 2, //!< Authentication message.
+ L_INFO = 3, //!< Informational message.
+ L_ERR = 4, //!< Error message.
+ L_WARN = 5, //!< Warning.
+ L_PROXY = 6, //!< Proxy messages
+ L_ACCT = 7, //!< Accounting messages
+
+ L_DBG = 16, //!< Only displayed when debugging is enabled.
+ L_DBG_WARN = 17, //!< Warning only displayed when debugging is enabled.
+ L_DBG_ERR = 18, //!< Error only displayed when debugging is enabled.
+ L_DBG_WARN_REQ = 19, //!< Less severe warning only displayed when debugging is enabled.
+ L_DBG_ERR_REQ = 20 //!< Less severe error only displayed when debugging is enabled.
+} log_type_t;
+
+typedef enum log_lvl {
+ L_DBG_LVL_DISABLE = -1, //!< Don't print messages.
+ L_DBG_LVL_OFF = 0, //!< No debug messages.
+ L_DBG_LVL_1, //!< Highest priority debug messages (-x).
+ L_DBG_LVL_2, //!< 2nd highest priority debug messages (-xx | -X).
+ L_DBG_LVL_3, //!< 3rd highest priority debug messages (-xxx | -Xx).
+ L_DBG_LVL_MAX //!< Lowest priority debug messages (-xxxx | -Xxx).
+} log_lvl_t;
+
+typedef enum log_dst {
+ L_DST_STDOUT = 0, //!< Log to stdout.
+ L_DST_FILES, //!< Log to a file on disk.
+ L_DST_SYSLOG, //!< Log to syslog.
+ L_DST_STDERR, //!< Log to stderr.
+ L_DST_NULL, //!< Discard log messages.
+ L_DST_NUM_DEST
+} log_dst_t;
+
+typedef struct fr_log_t {
+ bool colourise; //!< Prefix log messages with VT100 escape codes to change text
+ //!< colour.
+ int fd; //!< File descriptor to write messages to.
+ log_dst_t dst; //!< Log destination.
+ char const *file; //!< Path to log file.
+ char const *debug_file; //!< Path to debug log file.
+} fr_log_t;
+
+typedef void (*radlog_func_t)(log_type_t lvl, log_lvl_t priority, REQUEST *, char const *, va_list ap);
+
+extern FR_NAME_NUMBER const syslog_facility_table[];
+extern FR_NAME_NUMBER const syslog_severity_table[];
+extern FR_NAME_NUMBER const log_str2dst[];
+extern fr_log_t default_log;
+
+int radlog_init(fr_log_t *log, bool daemonize);
+
+int vradlog(log_type_t lvl, char const *fmt, va_list ap)
+ CC_HINT(format (printf, 2, 0)) CC_HINT(nonnull);
+int radlog(log_type_t lvl, char const *fmt, ...)
+ CC_HINT(format (printf, 2, 3)) CC_HINT(nonnull (2));
+
+bool debug_enabled(log_type_t type, log_lvl_t lvl);
+
+bool rate_limit_enabled(void);
+
+bool radlog_debug_enabled(log_type_t type, log_lvl_t lvl, REQUEST *request)
+ CC_HINT(nonnull);
+
+void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap)
+ CC_HINT(format (printf, 4, 0)) CC_HINT(nonnull (3, 4));
+
+void radlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
+ CC_HINT(format (printf, 4, 5)) CC_HINT(nonnull (3, 4));
+
+void radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
+ CC_HINT(format (printf, 4, 5)) CC_HINT(nonnull (3, 4));
+
+void radlog_request_marker(log_type_t type, log_lvl_t lvl, REQUEST *request,
+ char const *fmt, size_t indent, char const *error)
+ CC_HINT(nonnull);
+
+void fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg);
+
+/** @name Log global messages
+ *
+ * Write to the global log.
+ *
+ * Messages will always be written irrespective of the debugging level set with ``-x`` or ``-X``.
+ *
+ * @warning If a REQUEST * is **NOT** available, these macros **MUST** be used.
+ *
+ * @note These macros should only be used for important global events.
+ *
+ * **Debug categories**
+ * Name | Syslog severity | Colour/style | When to use
+ * -------- | ----------------------- | ------------ | -----------
+ * AUTH | LOG_NOTICE | Bold | Never - Deprecated
+ * ACCT | LOG_NOTICE | Bold | Never - Deprecated
+ * PROXY | LOG_NOTICE | Bold | Never - Deprecated
+ * INFO | LOG_INFO | Bold | TBD
+ * WARN | LOG_WARNING | Yellow | Warnings. Impending resource exhaustion, resource exhaustion
+ * ERROR | LOG_ERR | Red | Critical server errors. Malformed queries, failed operations, connection errors, packet processing errors
+ *
+ * @{
+ */
+#define AUTH(fmt, ...) radlog(L_AUTH, fmt, ## __VA_ARGS__)
+#define ACCT(fmt, ...) radlog(L_ACCT, fmt, ## __VA_ARGS__)
+#define PROXY(fmt, ...) radlog(L_PROXY, fmt, ## __VA_ARGS__)
+
+#define INFO(fmt, ...) radlog(L_INFO, fmt, ## __VA_ARGS__)
+#define WARN(fmt, ...) radlog(L_WARN, fmt, ## __VA_ARGS__)
+#define ERROR(fmt, ...) radlog(L_ERR, fmt, ## __VA_ARGS__)
+/** @} */
+
+/** @name Log global debug messages (DEBUG*)
+ *
+ * Write debugging messages to the global log.
+ *
+ * Messages will be written if the debug level is high enough.
+ *
+ * **Debug categories**
+ * Name | Syslog severity | Colour/style | When to use
+ * -------- | ----------------------- | -------------| -----------
+ * DEBUG | LOG_DEBUG | Regular | Normal debug output
+ *
+ * **Debug levels**
+ * Level | Debug arguments | Macro(s) enabled | When to use
+ * -------- | ----------------------- | ----------------------------- | -----------
+ * 1 | ``-x`` | DEBUG | Never - Deprecated
+ * 2 | ``-xx`` or ``-X`` | DEBUG, DEBUG2 | Interactions with external entities. Connection management, control socket, triggers, etc...
+ * 3 | ``-xxx`` or ``-Xx`` | DEBUG, DEBUG2, DEBUG3 | Lower priority events. Polling for detail files, cleanups, etc...
+ * 4 | ``-xxxx`` or ``-Xxx`` | DEBUG, DEBUG2, DEBUG3, DEBUG4 | Internal server state debugging.
+ *
+ * @{
+ */
+#define DEBUG_ENABLED debug_enabled(L_DBG, L_DBG_LVL_1) //!< True if global debug level 1 messages are enabled
+#define DEBUG_ENABLED2 debug_enabled(L_DBG, L_DBG_LVL_2) //!< True if global debug level 1-2 messages are enabled
+#define DEBUG_ENABLED3 debug_enabled(L_DBG, L_DBG_LVL_3) //!< True if global debug level 1-3 messages are enabled
+#define DEBUG_ENABLED4 debug_enabled(L_DBG, L_DBG_LVL_MAX) //!< True if global debug level 1-4 messages are enabled
+
+#define _SL(_l, _p, _f, ...) if (rad_debug_lvl >= _p) radlog(_l, _f, ## __VA_ARGS__)
+#define DEBUG(fmt, ...) _SL(L_DBG, L_DBG_LVL_1, fmt, ## __VA_ARGS__)
+#define DEBUG2(fmt, ...) _SL(L_DBG, L_DBG_LVL_2, fmt, ## __VA_ARGS__)
+#define DEBUG3(fmt, ...) _SL(L_DBG, L_DBG_LVL_3, fmt, ## __VA_ARGS__)
+#define DEBUG4(fmt, ...) _SL(L_DBG, L_DBG_LVL_MAX, fmt, ## __VA_ARGS__)
+/** @} */
+
+/** @name Log request-specific messages (R*)
+ *
+ * Write to the request log, or the global log if a request logging function is not set.
+ *
+ * Messages will always be written irrespective of the debugging level set with ``-x`` or ``-X``.
+ *
+ * @note Automatically prepends date (at lvl >= 3), request number, and module, to the log message.
+ * @note If a REQUEST * is available, these macros should be used.
+ * @note These macros should only be used for important global events.
+ *
+ * **Debug categories**
+ * Name | Syslog severity | Colour/style | When to use
+ * -------- | ----------------------- | -------------| -----------
+ * RAUTH | LOG_NOTICE | Bold | Never - Deprecated
+ * RACCT | LOG_NOTICE | Bold | Never - Deprecated
+ * RPROXY | LOG_NOTICE | Bold | Never - Deprecated
+ * RINFO | LOG_INFO | Bold | TBD
+ * RWARN | LOG_WARNING | Yellow/Bold | Warnings. Impending resource exhaustion, or resource exhaustion.
+ * RERROR | LOG_ERR | Red/Bold | Critical server errors. Malformed queries, failed operations, connection errors, packet processing errors.
+ * @{
+ */
+#define RAUTH(fmt, ...) radlog_request(L_AUTH, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+#define RACCT(fmt, ...) radlog_request(L_ACCT, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+#define RPROXY(fmt, ...) radlog_request(L_PROXY, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+#define RINFO(fmt, ...) radlog_request(L_INFO, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+#define RWARN(fmt, ...) radlog_request(L_DBG_WARN, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+#define RERROR(fmt, ...) radlog_request_error(L_DBG_ERR, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
+/** @} */
+
+/** @name Log request-specific debug (R*DEBUG*)
+ *
+ * Write debug messages to the request log.
+ *
+ * Messages will only be written if a request log function is set and the request or global
+ * debug level is high enough.
+ *
+ * @note Automatically prepends date (at lvl >= 3), request number, and module, to the log message.
+ *
+ * **Debug categories**
+ * Name | Syslog severity | Colour and style | When to use
+ * -------- | ----------------------- | -----------------| -----------
+ * RDEBUG* | LOG_DEBUG | Regular | Normal debugging messages
+ * RIDEBUG* | LOG_DEBUG | Bold | Informational messages.
+ * RWDEBUG* | LOG_DEBUG | Yellow/Bold | Warnings. Invalid configuration, missing or invalid attributes etc...
+ * REDEBUG* | LOG_DEBUG | Red/Bold | Errors. Reject messages, bad values etc...
+ *
+ * **Debug levels**
+ * Level | Debug arguments | Macro(s) enabled | When to use
+ * -------- | ----------------------- | -------------------------------------- | -----------
+ * 1 | ``-x`` | R*DEBUG | Never - Deprecated
+ * 2 | ``-xx`` or ``-X`` | R*DEBUG, R*DEBUG2 | Normal request flow. Operations, Results of queries, or execs, etc...
+ * 3 | ``-xxx`` or ``-Xx`` | R*DEBUG, R*DEBUG2, R*DEBUG3 | Internal server state or packet input. State machine changes, extra attribute info, etc...
+ * 4 | ``-xxxx`` or ``-Xxx`` | R*DEBUG, R*DEBUG2, R*DEBUG3, R*DEBUG4 | Verbose internal server state messages or packet input. Hex dumps, structure dumps, pointer values.
+ *
+ * @{
+ */
+#define RDEBUG_ENABLED radlog_debug_enabled(L_DBG, L_DBG_LVL_1, request) //!< True if request debug level 1 messages are enabled
+#define RDEBUG_ENABLED2 radlog_debug_enabled(L_DBG, L_DBG_LVL_2, request) //!< True if request debug level 1-2 messages are enabled
+#define RDEBUG_ENABLED3 radlog_debug_enabled(L_DBG, L_DBG_LVL_3, request) //!< True if request debug level 1-3 messages are enabled
+#define RDEBUG_ENABLED4 radlog_debug_enabled(L_DBG, L_DBG_LVL_MAX, request) //!< True if request debug level 1-4 messages are enabled
+
+#define RDEBUGX(_l, fmt, ...) radlog_request(L_DBG, _l, request, fmt, ## __VA_ARGS__)
+#define RDEBUG(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
+#define RDEBUG2(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
+#define RDEBUG3(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_3, request, fmt, ## __VA_ARGS__)
+#define RDEBUG4(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_MAX, request, fmt, ## __VA_ARGS__)
+
+#define RIDEBUG(fmt, ...) radlog_request(L_INFO, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
+#define RIDEBUG2(fmt, ...) radlog_request(L_INFO, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
+
+#define RWDEBUG(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG_WARN, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
+#define RWDEBUG2(fmt, ...) if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG_WARN, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
+
+#define REDEBUG(fmt, ...) radlog_request_error(L_DBG_ERR, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
+#define REDEBUG2(fmt, ...) radlog_request_error(L_DBG_ERR, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
+#define REDEBUG3(fmt, ...) radlog_request_error(L_DBG_ERR, L_DBG_LVL_3, request, fmt, ## __VA_ARGS__)
+#define REDEBUG4(fmt, ...) radlog_request_error(L_DBG_ERR, L_DBG_LVL_MAX, request, fmt, ## __VA_ARGS__)
+/** @} */
+
+/** Indent R* messages by one level
+ *
+ * @note Has no effect on the indentation of INFO, WARN, ERROR, DEBUG messages,
+ * only RINFO, RWARN, RERROR etc...
+ */
+#define RINDENT() (request->log.indent += 2)
+
+/** Exdent (unindent) R* messages by one level
+ *
+ * @note Has no effect on the indentation of INFO, WARN, ERROR, DEBUG messages,
+ * only RINFO, RWARN, RERROR etc...
+ */
+#define REXDENT() (request->log.indent -= 2)
+
+/** Output string with error marker, showing where format error occurred
+ *
+ @verbatim
+ my pet kitty
+ ^ kitties are not pets, are nature devouring hell beasts
+ @endverbatim
+ *
+ * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
+ *
+ * @param _l log category, a log_type_t value.
+ * @param _p log priority, a log_lvl_t value.
+ * @param _m string to mark e.g. "my pet kitty".
+ * @param _i index e.g. 3 (starts from 0).
+ * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
+ */
+#define RMARKER(_l, _p, _m, _i, _e) radlog_request_marker(_l, _p, request, _m, _i, _e)
+
+/** Output string with error marker, showing where format error occurred
+ *
+ * These are logged as RERROR messages.
+ *
+ @verbatim
+ my pet kitty
+ ^ kitties are not pets, are nature devouring hell beasts
+ @endverbatim
+ *
+ * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
+ *
+ * @param _m string to mark e.g. "my pet kitty".
+ * @param _i index e.g. 3 (starts from 0).
+ * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
+ */
+#define REMARKER(_m, _i, _e) RMARKER(L_DBG_ERR, L_DBG_LVL_1, _m, _i, _e)
+
+/** Output string with error marker, showing where format error occurred
+ *
+ * These are logged as RDEBUG messages.
+ *
+ @verbatim
+ my pet kitty
+ ^ kitties are not pets, are nature devouring hell beasts
+ @endverbatim
+ *
+ * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
+ *
+ * @param _m string to mark e.g. "my pet kitty".
+ * @param _i index e.g. 3 (starts from 0).
+ * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
+ */
+#define RDMARKER(_m, _i, _e) RMARKER(L_DBG, L_DBG_LVL_1, _m, _i, _e)
+
+/** Use different logging functions depending on whether request is NULL or not.
+ *
+ * @note The module must define MOD_PREFIX as its name (do this in the module
+ * header file) e.g. @code{.c}#define MOD_PREFIX "rlm_example"@endcode
+ *
+ * This is useful for areas of code which are run on server startup, and when
+ * processing requests.
+ *
+ * @param _l_request The name of a R* logging macro e.g. RDEBUG3.
+ * @param _l_global The name of a global logging macro e.g. DEBUG3.
+ * @param fmt printf style format string.
+ * @param ... printf arguments.
+ */
+ #define MOD_ROPTIONAL(_l_request, _l_global, fmt, ...) \
+do {\
+ if (request) {\
+ _l_request(fmt, ## __VA_ARGS__);\
+ } else {\
+ _l_global(MOD_PREFIX " (%s): " fmt, inst->name, ## __VA_ARGS__);\
+ }\
+} while (0)
+
+/** Use different logging functions depending on whether request is NULL or not.
+ *
+ * This is useful for areas of code which are run on server startup, and when
+ * processing requests.
+ *
+ * @param _l_request The name of a R* logging macro e.g. RDEBUG3.
+ * @param _l_global The name of a global logging macro e.g. DEBUG3.
+ * @param fmt printf style format string.
+ * @param ... printf arguments.
+ */
+ #define ROPTIONAL(_l_request, _l_global, fmt, ...) \
+do {\
+ if (request) {\
+ _l_request(fmt, ## __VA_ARGS__);\
+ } else {\
+ _l_global(LOG_PREFIX ": " fmt, ## __VA_ARGS__);\
+ }\
+} while (0)
+
+#define RATE_LIMIT_ENABLED rate_limit_enabled() //!< True if rate limiting is enabled.
+/** Rate limit messages
+ *
+ * Rate limit log messages so they're written a maximum of once per second.
+ *
+ @code{.c}
+ RATE_LIMIT(RERROR("Home servers alive in pool %s", pool->name));
+ @endcode
+ * @note Rate limits the macro, not the message. If five different messages are
+ * produced using the same macro in the same second, only the first will
+ * be written to the log.
+ *
+ * @param _x Logging macro to limit.
+ */
+#define RATE_LIMIT(_x) \
+do {\
+ if (RATE_LIMIT_ENABLED) {\
+ static time_t _last_complained = 0;\
+ time_t _now = time(NULL);\
+ if (_now != _last_complained) {\
+ _last_complained = _now;\
+ _x;\
+ }\
+ } else _x;\
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FR_LOG_H */