1 /*
2  *   This program is free software; you can redistribute it and/or modify
3  *   it under the terms of the GNU General Public License as published by
4  *   the Free Software Foundation; either version 2 of the License, or
5  *   (at your option) any later version.
6  *
7  *   This program is distributed in the hope that it will be useful,
8  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *   GNU General Public License for more details.
11  *
12  *   You should have received a copy of the GNU General Public License
13  *   along with this program; if not, write to the Free Software
14  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 #ifndef FR_LOG_H
17 #define FR_LOG_H
18 /**
19  * $Id: 2736591779e3c80137b1a753bf75e5d2182595c5 $
20  *
21  * @file log.h
22  * @brief Macros and function definitions to write log messages, and control the logging system.
23  *
24  * @copyright 2015 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
25  * @copyright 2013 Alan DeKok <aland@freeradius.org>
26  */
27 RCSIDH(log_h, "$Id: 2736591779e3c80137b1a753bf75e5d2182595c5 $")
28 
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
32 
33 typedef enum log_type {
34 	L_AUTH = 2,		//!< Authentication message.
35 	L_INFO = 3,		//!< Informational message.
36 	L_ERR = 4,		//!< Error message.
37 	L_WARN = 5,		//!< Warning.
38 	L_PROXY	= 6,		//!< Proxy messages
39 	L_ACCT = 7,		//!< Accounting messages
40 
41 	L_DBG = 16,		//!< Only displayed when debugging is enabled.
42 	L_DBG_WARN = 17,	//!< Warning only displayed when debugging is enabled.
43 	L_DBG_ERR = 18,		//!< Error only displayed when debugging is enabled.
44 	L_DBG_WARN_REQ = 19,	//!< Less severe warning only displayed when debugging is enabled.
45 	L_DBG_ERR_REQ = 20	//!< Less severe error only displayed when debugging is enabled.
46 } log_type_t;
47 
48 typedef enum log_lvl {
49 	L_DBG_LVL_DISABLE = -1,	//!< Don't print messages.
50 	L_DBG_LVL_OFF = 0,	//!< No debug messages.
51 	L_DBG_LVL_1,		//!< Highest priority debug messages (-x).
52 	L_DBG_LVL_2,		//!< 2nd highest priority debug messages (-xx | -X).
53 	L_DBG_LVL_3,		//!< 3rd highest priority debug messages (-xxx | -Xx).
54 	L_DBG_LVL_MAX		//!< Lowest priority debug messages (-xxxx | -Xxx).
55 } log_lvl_t;
56 
57 typedef enum log_dst {
58 	L_DST_STDOUT = 0,	//!< Log to stdout.
59 	L_DST_FILES,		//!< Log to a file on disk.
60 	L_DST_SYSLOG,		//!< Log to syslog.
61 	L_DST_STDERR,		//!< Log to stderr.
62 	L_DST_NULL,		//!< Discard log messages.
63 	L_DST_NUM_DEST
64 } log_dst_t;
65 
66 typedef struct fr_log_t {
67 	bool		colourise;	//!< Prefix log messages with VT100 escape codes to change text
68 					//!< colour.
69 	int		fd;		//!< File descriptor to write messages to.
70 	log_dst_t	dst;		//!< Log destination.
71 	char const	*file;		//!< Path to log file.
72 	char const	*debug_file;	//!< Path to debug log file.
73 } fr_log_t;
74 
75 typedef		void (*radlog_func_t)(log_type_t lvl, log_lvl_t priority, REQUEST *, char const *, va_list ap);
76 
77 extern FR_NAME_NUMBER const syslog_facility_table[];
78 extern FR_NAME_NUMBER const syslog_severity_table[];
79 extern FR_NAME_NUMBER const log_str2dst[];
80 extern fr_log_t default_log;
81 
82 int	radlog_init(fr_log_t *log, bool daemonize);
83 
84 int	vradlog(log_type_t lvl, char const *fmt, va_list ap)
85 	CC_HINT(format (printf, 2, 0)) CC_HINT(nonnull);
86 int	radlog(log_type_t lvl, char const *fmt, ...)
87 	CC_HINT(format (printf, 2, 3)) CC_HINT(nonnull (2));
88 
89 bool	debug_enabled(log_type_t type, log_lvl_t lvl);
90 
91 bool	rate_limit_enabled(void);
92 
93 bool	radlog_debug_enabled(log_type_t type, log_lvl_t lvl, REQUEST *request)
94 	CC_HINT(nonnull);
95 
96 void	vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap)
97 	CC_HINT(format (printf, 4, 0)) CC_HINT(nonnull (3, 4));
98 
99 void	radlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
100 	CC_HINT(format (printf, 4, 5)) CC_HINT(nonnull (3, 4));
101 
102 void	radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
103 	CC_HINT(format (printf, 4, 5)) CC_HINT(nonnull (3, 4));
104 
105 void	radlog_request_marker(log_type_t type, log_lvl_t lvl, REQUEST *request,
106 			      char const *fmt, size_t indent, char const *error)
107 	CC_HINT(nonnull);
108 
109 void	fr_canonicalize_error(TALLOC_CTX *ctx, char **spaces, char **text, ssize_t slen, char const *msg);
110 
111 /** @name Log global messages
112  *
113  * Write to the global log.
114  *
115  * Messages will always be written irrespective of the debugging level set with ``-x`` or ``-X``.
116  *
117  * @warning If a REQUEST * is **NOT** available, these macros **MUST** be used.
118  *
119  * @note These macros should only be used for important global events.
120  *
121  * **Debug categories**
122  * Name     | Syslog severity         | Colour/style | When to use
123  * -------- | ----------------------- | ------------ | -----------
124  * AUTH     | LOG_NOTICE              | Bold         | Never - Deprecated
125  * ACCT     | LOG_NOTICE              | Bold         | Never - Deprecated
126  * PROXY    | LOG_NOTICE              | Bold         | Never - Deprecated
127  * INFO     | LOG_INFO                | Bold         | TBD
128  * WARN     | LOG_WARNING             | Yellow       | Warnings. Impending resource exhaustion, resource exhaustion
129  * ERROR    | LOG_ERR                 | Red          | Critical server errors. Malformed queries, failed operations, connection errors, packet processing errors
130  *
131  * @{
132  */
133 #define AUTH(fmt, ...)		radlog(L_AUTH, fmt, ## __VA_ARGS__)
134 #define ACCT(fmt, ...)		radlog(L_ACCT, fmt, ## __VA_ARGS__)
135 #define PROXY(fmt, ...)		radlog(L_PROXY, fmt, ## __VA_ARGS__)
136 
137 #define INFO(fmt, ...)		radlog(L_INFO,  fmt, ## __VA_ARGS__)
138 #define WARN(fmt, ...)		radlog(L_WARN, fmt, ## __VA_ARGS__)
139 #define ERROR(fmt, ...)		radlog(L_ERR, fmt, ## __VA_ARGS__)
140 /** @} */
141 
142 /** @name Log global debug messages (DEBUG*)
143  *
144  * Write debugging messages to the global log.
145  *
146  * Messages will be written if the debug level is high enough.
147  *
148  * **Debug categories**
149  * Name     | Syslog severity         | Colour/style | When to use
150  * -------- | ----------------------- | -------------| -----------
151  * DEBUG    | LOG_DEBUG               | Regular      | Normal debug output
152  *
153  * **Debug levels**
154  * Level    | Debug arguments         | Macro(s) enabled              | When to use
155  * -------- | ----------------------- | ----------------------------- | -----------
156  * 1        | ``-x``                  | DEBUG                         | Never - Deprecated
157  * 2        | ``-xx`` or ``-X``       | DEBUG, DEBUG2                 | Interactions with external entities. Connection management, control socket, triggers, etc...
158  * 3        | ``-xxx`` or ``-Xx``     | DEBUG, DEBUG2, DEBUG3         | Lower priority events. Polling for detail files, cleanups, etc...
159  * 4        | ``-xxxx`` or ``-Xxx``   | DEBUG, DEBUG2, DEBUG3, DEBUG4 | Internal server state debugging.
160  *
161  * @{
162  */
163 #define DEBUG_ENABLED		debug_enabled(L_DBG, L_DBG_LVL_1)			//!< True if global debug level 1 messages are enabled
164 #define DEBUG_ENABLED2		debug_enabled(L_DBG, L_DBG_LVL_2)			//!< True if global debug level 1-2 messages are enabled
165 #define DEBUG_ENABLED3		debug_enabled(L_DBG, L_DBG_LVL_3)			//!< True if global debug level 1-3 messages are enabled
166 #define DEBUG_ENABLED4		debug_enabled(L_DBG, L_DBG_LVL_MAX)			//!< True if global debug level 1-4 messages are enabled
167 
168 #define _SL(_l, _p, _f, ...)	if (rad_debug_lvl >= _p) radlog(_l, _f, ## __VA_ARGS__)
169 #define DEBUG(fmt, ...)		_SL(L_DBG, L_DBG_LVL_1, fmt, ## __VA_ARGS__)
170 #define DEBUG2(fmt, ...)	_SL(L_DBG, L_DBG_LVL_2, fmt, ## __VA_ARGS__)
171 #define DEBUG3(fmt, ...)	_SL(L_DBG, L_DBG_LVL_3, fmt, ## __VA_ARGS__)
172 #define DEBUG4(fmt, ...)	_SL(L_DBG, L_DBG_LVL_MAX, fmt, ## __VA_ARGS__)
173 /** @} */
174 
175 /** @name Log request-specific messages (R*)
176  *
177  * Write to the request log, or the global log if a request logging function is not set.
178  *
179  * Messages will always be written irrespective of the debugging level set with ``-x`` or ``-X``.
180  *
181  * @note Automatically prepends date (at lvl >= 3), request number, and module, to the log message.
182  * @note If a REQUEST * is available, these macros should be used.
183  * @note These macros should only be used for important global events.
184  *
185  * **Debug categories**
186  * Name     | Syslog severity         | Colour/style | When to use
187  * -------- | ----------------------- | -------------| -----------
188  * RAUTH    | LOG_NOTICE              | Bold         | Never - Deprecated
189  * RACCT    | LOG_NOTICE              | Bold         | Never - Deprecated
190  * RPROXY   | LOG_NOTICE              | Bold         | Never - Deprecated
191  * RINFO    | LOG_INFO                | Bold         | TBD
192  * RWARN    | LOG_WARNING             | Yellow/Bold  | Warnings. Impending resource exhaustion, or resource exhaustion.
193  * RERROR   | LOG_ERR                 | Red/Bold     | Critical server errors. Malformed queries, failed operations, connection errors, packet processing errors.
194  * @{
195  */
196 #define RAUTH(fmt, ...)		radlog_request(L_AUTH, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
197 #define RACCT(fmt, ...)		radlog_request(L_ACCT, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
198 #define RPROXY(fmt, ...)	radlog_request(L_PROXY, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
199 #define RINFO(fmt, ...)		radlog_request(L_INFO, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
200 #define RWARN(fmt, ...)		radlog_request(L_DBG_WARN, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
201 #define RERROR(fmt, ...)	radlog_request_error(L_DBG_ERR, L_DBG_LVL_OFF, request, fmt, ## __VA_ARGS__)
202 /** @} */
203 
204 /** @name Log request-specific debug (R*DEBUG*)
205  *
206  * Write debug messages to the request log.
207  *
208  * Messages will only be written if a request log function is set and the request or global
209  * debug level is high enough.
210  *
211  * @note Automatically prepends date (at lvl >= 3), request number, and module, to the log message.
212  *
213  * **Debug categories**
214  * Name     | Syslog severity         | Colour and style | When to use
215  * -------- | ----------------------- | -----------------| -----------
216  * RDEBUG*  | LOG_DEBUG               | Regular          | Normal debugging messages
217  * RIDEBUG* | LOG_DEBUG               | Bold             | Informational messages.
218  * RWDEBUG* | LOG_DEBUG               | Yellow/Bold      | Warnings. Invalid configuration, missing or invalid attributes etc...
219  * REDEBUG* | LOG_DEBUG               | Red/Bold         | Errors. Reject messages, bad values etc...
220  *
221  * **Debug levels**
222  * Level    | Debug arguments         | Macro(s) enabled                       | When to use
223  * -------- | ----------------------- | -------------------------------------- | -----------
224  * 1        | ``-x``                  | R*DEBUG                                | Never - Deprecated
225  * 2        | ``-xx`` or ``-X``       | R*DEBUG, R*DEBUG2                      | Normal request flow. Operations, Results of queries, or execs, etc...
226  * 3        | ``-xxx`` or ``-Xx``     | R*DEBUG, R*DEBUG2, R*DEBUG3            | Internal server state or packet input. State machine changes, extra attribute info, etc...
227  * 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.
228  *
229  * @{
230  */
231 #define RDEBUG_ENABLED		radlog_debug_enabled(L_DBG, L_DBG_LVL_1, request)	//!< True if request debug level 1 messages are enabled
232 #define RDEBUG_ENABLED2		radlog_debug_enabled(L_DBG, L_DBG_LVL_2, request)	//!< True if request debug level 1-2 messages are enabled
233 #define RDEBUG_ENABLED3		radlog_debug_enabled(L_DBG, L_DBG_LVL_3, request)	//!< True if request debug level 1-3 messages are enabled
234 #define RDEBUG_ENABLED4		radlog_debug_enabled(L_DBG, L_DBG_LVL_MAX, request)	//!< True if request debug level 1-4 messages are enabled
235 
236 #define RDEBUGX(_l, fmt, ...)	radlog_request(L_DBG, _l, request, fmt, ## __VA_ARGS__)
237 #define RDEBUG(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
238 #define RDEBUG2(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
239 #define RDEBUG3(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_3, request, fmt, ## __VA_ARGS__)
240 #define RDEBUG4(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG, L_DBG_LVL_MAX, request, fmt, ## __VA_ARGS__)
241 
242 #define RIDEBUG(fmt, ...)	radlog_request(L_INFO, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
243 #define RIDEBUG2(fmt, ...)	radlog_request(L_INFO, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
244 
245 #define RWDEBUG(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG_WARN, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
246 #define RWDEBUG2(fmt, ...)	if (rad_debug_lvl || request->log.lvl) radlog_request(L_DBG_WARN, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
247 
248 #define REDEBUG(fmt, ...)	radlog_request_error(L_DBG_ERR, L_DBG_LVL_1, request, fmt, ## __VA_ARGS__)
249 #define REDEBUG2(fmt, ...)	radlog_request_error(L_DBG_ERR, L_DBG_LVL_2, request, fmt, ## __VA_ARGS__)
250 #define REDEBUG3(fmt, ...)	radlog_request_error(L_DBG_ERR, L_DBG_LVL_3, request, fmt, ## __VA_ARGS__)
251 #define REDEBUG4(fmt, ...)	radlog_request_error(L_DBG_ERR, L_DBG_LVL_MAX, request, fmt, ## __VA_ARGS__)
252 /** @} */
253 
254 /** Indent R* messages by one level
255  *
256  * @note Has no effect on the indentation of INFO, WARN, ERROR, DEBUG messages,
257  *	 only RINFO, RWARN, RERROR etc...
258  */
259 #define RINDENT() (request->log.indent += 2)
260 
261 /** Exdent (unindent) R* messages by one level
262  *
263  * @note Has no effect on the indentation of INFO, WARN, ERROR, DEBUG messages,
264  *	 only RINFO, RWARN, RERROR etc...
265  */
266 #define REXDENT() (request->log.indent -= 2)
267 
268 /** Output string with error marker, showing where format error occurred
269  *
270  @verbatim
271    my pet kitty
272       ^ kitties are not pets, are nature devouring hell beasts
273  @endverbatim
274  *
275  * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
276  *
277  * @param _l log category, a log_type_t value.
278  * @param _p log priority, a log_lvl_t value.
279  * @param _m string to mark e.g. "my pet kitty".
280  * @param _i index e.g. 3 (starts from 0).
281  * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
282  */
283 #define RMARKER(_l, _p, _m, _i, _e)	radlog_request_marker(_l, _p, request, _m, _i, _e)
284 
285 /** Output string with error marker, showing where format error occurred
286  *
287  * These are logged as RERROR messages.
288  *
289  @verbatim
290    my pet kitty
291       ^ kitties are not pets, are nature devouring hell beasts
292  @endverbatim
293  *
294  * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
295  *
296  * @param _m string to mark e.g. "my pet kitty".
297  * @param _i index e.g. 3 (starts from 0).
298  * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
299  */
300 #define REMARKER(_m, _i, _e)		RMARKER(L_DBG_ERR, L_DBG_LVL_1, _m, _i, _e)
301 
302 /** Output string with error marker, showing where format error occurred
303  *
304  * These are logged as RDEBUG messages.
305  *
306  @verbatim
307    my pet kitty
308       ^ kitties are not pets, are nature devouring hell beasts
309  @endverbatim
310  *
311  * @warning If a REQUEST * is **NOT** available, or is NULL, this macro must **NOT** be used.
312  *
313  * @param _m string to mark e.g. "my pet kitty".
314  * @param _i index e.g. 3 (starts from 0).
315  * @param _e error e.g. "kitties are not pets, are nature devouring hell beasts".
316  */
317 #define RDMARKER(_m, _i, _e)		RMARKER(L_DBG, L_DBG_LVL_1, _m, _i, _e)
318 
319 /** Use different logging functions depending on whether request is NULL or not.
320  *
321  * @note The module must define MOD_PREFIX as its name (do this in the module
322  *	 header file) e.g. @code{.c}#define MOD_PREFIX "rlm_example"@endcode
323  *
324  * This is useful for areas of code which are run on server startup, and when
325  * processing requests.
326  *
327  * @param _l_request The name of a R* logging macro e.g. RDEBUG3.
328  * @param _l_global The name of a global logging macro e.g. DEBUG3.
329  * @param fmt printf style format string.
330  * @param ... printf arguments.
331  */
332  #define MOD_ROPTIONAL(_l_request, _l_global, fmt, ...) \
333 do {\
334 	if (request) {\
335 		_l_request(fmt, ## __VA_ARGS__);\
336 	} else {\
337 		_l_global(MOD_PREFIX " (%s): " fmt, inst->name, ## __VA_ARGS__);\
338  	}\
339 } while (0)
340 
341 /** Use different logging functions depending on whether request is NULL or not.
342  *
343  * This is useful for areas of code which are run on server startup, and when
344  * processing requests.
345  *
346  * @param _l_request The name of a R* logging macro e.g. RDEBUG3.
347  * @param _l_global The name of a global logging macro e.g. DEBUG3.
348  * @param fmt printf style format string.
349  * @param ... printf arguments.
350  */
351  #define ROPTIONAL(_l_request, _l_global, fmt, ...) \
352 do {\
353 	if (request) {\
354 		_l_request(fmt, ## __VA_ARGS__);\
355 	} else {\
356 		_l_global(LOG_PREFIX ": " fmt, ## __VA_ARGS__);\
357  	}\
358 } while (0)
359 
360 #define RATE_LIMIT_ENABLED rate_limit_enabled()		//!< True if rate limiting is enabled.
361 /** Rate limit messages
362  *
363  * Rate limit log messages so they're written a maximum of once per second.
364  *
365  @code{.c}
366    RATE_LIMIT(RERROR("Home servers alive in pool %s", pool->name));
367  @endcode
368  * @note Rate limits the macro, not the message. If five different messages are
369  *	 produced using the same macro in the same second, only the first will
370  *	 be written to the log.
371  *
372  * @param _x Logging macro to limit.
373  */
374 #define RATE_LIMIT(_x) \
375 do {\
376 	if (RATE_LIMIT_ENABLED) {\
377 		static time_t _last_complained = 0;\
378 		time_t _now = time(NULL);\
379 		if (_now != _last_complained) {\
380 			_last_complained = _now;\
381 			_x;\
382 		}\
383 	} else _x;\
384 } while (0)
385 
386 #ifdef __cplusplus
387 }
388 #endif
389 
390 #endif /* FR_LOG_H */
391