All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
log.c
Go to the documentation of this file.
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 
17 /**
18  * $Id: a4a1d89fff3d499509b384c7986132f06759dc0b $
19  *
20  * @brief Logging functions used by the server core.
21  * @file main/log.c
22  *
23  * @copyright 2000,2006 The FreeRADIUS server project
24  * @copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
25  * @copyright 2000 Alan DeKok <aland@ox.org>
26  * @copyright 2001 Chad Miller <cmiller@surfsouth.com>
27  */
28 RCSID("$Id: a4a1d89fff3d499509b384c7986132f06759dc0b $")
29 
30 #include <freeradius-devel/radiusd.h>
31 #include <freeradius-devel/rad_assert.h>
32 
33 #ifdef HAVE_SYS_STAT_H
34 # include <sys/stat.h>
35 #endif
36 
37 #include <fcntl.h>
38 
39 #ifdef HAVE_SYSLOG_H
40 # include <syslog.h>
41 #endif
42 
43 #include <sys/file.h>
44 
45 #ifdef HAVE_PTHREAD_H
46 #include <pthread.h>
47 #endif
48 
49 log_lvl_t rad_debug_lvl = 0; //!< Global debugging level
50 static bool rate_limit = true; //!< Whether repeated log entries should be rate limited
51 
52 /** Maps log categories to message prefixes
53  */
54 static const FR_NAME_NUMBER levels[] = {
55  { ": Debug: ", L_DBG },
56  { ": Auth: ", L_AUTH },
57  { ": Proxy: ", L_PROXY },
58  { ": Info: ", L_INFO },
59  { ": Warning: ", L_WARN },
60  { ": Acct: ", L_ACCT },
61  { ": Error: ", L_ERR },
62  { ": WARNING: ", L_DBG_WARN },
63  { ": ERROR: ", L_DBG_ERR },
64  { ": WARNING: ", L_DBG_WARN_REQ },
65  { ": ERROR: ", L_DBG_ERR_REQ },
66  { NULL, 0 }
67 };
68 
69 /** @name VT100 escape sequences
70  *
71  * These sequences may be written to VT100 terminals to change the
72  * colour and style of the text.
73  *
74  @code{.c}
75  fprintf(stdout, VTC_RED "This text will be coloured red" VTC_RESET);
76  @endcode
77  * @{
78  */
79 #define VTC_RED "\x1b[31m" //!< Colour following text red.
80 #define VTC_YELLOW "\x1b[33m" //!< Colour following text yellow.
81 #define VTC_BOLD "\x1b[1m" //!< Embolden following text.
82 #define VTC_RESET "\x1b[0m" //!< Reset terminal text to default style/colour.
83 /** @} */
84 
85 /** Maps log categories to VT100 style/colour escape sequences
86  */
87 static const FR_NAME_NUMBER colours[] = {
88  { "", L_DBG },
89  { VTC_BOLD, L_AUTH },
90  { VTC_BOLD, L_PROXY },
91  { VTC_BOLD, L_INFO },
92  { VTC_BOLD, L_ACCT },
93  { VTC_RED, L_ERR },
99  { NULL, 0 }
100 };
101 
102 /** Syslog facility table
103  *
104  * Maps syslog facility keywords, to the syslog facility macros defined
105  * in the system's syslog.h.
106  *
107  * @note Not all facilities are supported by every operating system.
108  * If a facility is unavailable it will not appear in the table.
109  */
111 #ifdef LOG_KERN
112  { "kern", LOG_KERN },
113 #endif
114 #ifdef LOG_USER
115  { "user", LOG_USER },
116 #endif
117 #ifdef LOG_MAIL
118  { "mail", LOG_MAIL },
119 #endif
120 #ifdef LOG_DAEMON
121  { "daemon", LOG_DAEMON },
122 #endif
123 #ifdef LOG_AUTH
124  { "auth", LOG_AUTH },
125 #endif
126 #ifdef LOG_LPR
127  { "lpr", LOG_LPR },
128 #endif
129 #ifdef LOG_NEWS
130  { "news", LOG_NEWS },
131 #endif
132 #ifdef LOG_UUCP
133  { "uucp", LOG_UUCP },
134 #endif
135 #ifdef LOG_CRON
136  { "cron", LOG_CRON },
137 #endif
138 #ifdef LOG_AUTHPRIV
139  { "authpriv", LOG_AUTHPRIV },
140 #endif
141 #ifdef LOG_FTP
142  { "ftp", LOG_FTP },
143 #endif
144 #ifdef LOG_LOCAL0
145  { "local0", LOG_LOCAL0 },
146 #endif
147 #ifdef LOG_LOCAL1
148  { "local1", LOG_LOCAL1 },
149 #endif
150 #ifdef LOG_LOCAL2
151  { "local2", LOG_LOCAL2 },
152 #endif
153 #ifdef LOG_LOCAL3
154  { "local3", LOG_LOCAL3 },
155 #endif
156 #ifdef LOG_LOCAL4
157  { "local4", LOG_LOCAL4 },
158 #endif
159 #ifdef LOG_LOCAL5
160  { "local5", LOG_LOCAL5 },
161 #endif
162 #ifdef LOG_LOCAL6
163  { "local6", LOG_LOCAL6 },
164 #endif
165 #ifdef LOG_LOCAL7
166  { "local7", LOG_LOCAL7 },
167 #endif
168  { NULL, -1 }
169 };
170 
171 /** Syslog severity table
172  *
173  * Maps syslog severity keywords, to the syslog severity macros defined
174  * in the system's syslog.h file.
175  *
176  */
178 #ifdef LOG_EMERG
179  { "emergency", LOG_EMERG },
180 #endif
181 #ifdef LOG_ALERT
182  { "alert", LOG_ALERT },
183 #endif
184 #ifdef LOG_CRIT
185  { "critical", LOG_CRIT },
186 #endif
187 #ifdef LOG_ERR
188  { "error", LOG_ERR },
189 #endif
190 #ifdef LOG_WARNING
191  { "warning", LOG_WARNING },
192 #endif
193 #ifdef LOG_NOTICE
194  { "notice", LOG_NOTICE },
195 #endif
196 #ifdef LOG_INFO
197  { "info", LOG_INFO },
198 #endif
199 #ifdef LOG_DEBUG
200  { "debug", LOG_DEBUG },
201 #endif
202  { NULL, -1 }
203 };
204 
206  { "null", L_DST_NULL },
207  { "files", L_DST_FILES },
208  { "syslog", L_DST_SYSLOG },
209  { "stdout", L_DST_STDOUT },
210  { "stderr", L_DST_STDERR },
211  { NULL, L_DST_NUM_DEST }
212 };
213 
214 bool log_dates_utc = false;
215 
217  .colourise = false, //!< Will be set later. Should be off before we do terminal detection.
218  .fd = STDOUT_FILENO,
219  .dst = L_DST_STDOUT,
220  .file = NULL,
221 };
222 
223 static int stderr_fd = -1; //!< The original unmolested stderr file descriptor
224 static int stdout_fd = -1; //!< The original unmolested stdout file descriptor
225 
226 static char const spaces[] = " ";
227 
228 /** On fault, reset STDOUT and STDERR to something useful
229  *
230  * @return 0
231  */
232 static int _restore_std(UNUSED int sig)
233 {
234  if ((stderr_fd > 0) && (stdout_fd > 0)) {
235  dup2(stderr_fd, STDOUT_FILENO);
236  dup2(stdout_fd, STDERR_FILENO);
237  return 0;
238  }
239 
240  if (default_log.fd > 0) {
241  dup2(default_log.fd, STDOUT_FILENO);
242  dup2(default_log.fd, STDERR_FILENO);
243  return 0;
244  }
245 
246  return 0;
247 }
248 
249 /** Initialise file descriptors based on logging destination
250  *
251  * @param log Logger to manipulate.
252  * @param daemonize Whether the server is starting as a daemon.
253  * @return
254  * - 0 on success.
255  * - -1 on failure.
256  */
257 int radlog_init(fr_log_t *log, bool daemonize)
258 {
259  int devnull;
260 
261  rate_limit = daemonize;
262 
263  /*
264  * If we're running in foreground mode, save STDIN /
265  * STDERR as higher FDs, which won't get used by anyone
266  * else. When we fork/exec a program, it's STD FDs will
267  * get set to pipes. We later set STDOUT / STDERR to
268  * /dev/null, so that any library trying to write to them
269  * doesn't screw anything up.
270  *
271  * Then, when something goes wrong, restore them so that
272  * any debugger called from the panic action has access
273  * to STDOUT / STDERR.
274  */
275  if (!daemonize) {
277 
278  stdout_fd = dup(STDOUT_FILENO);
279  stderr_fd = dup(STDERR_FILENO);
280  }
281 
282  devnull = open("/dev/null", O_RDWR);
283  if (devnull < 0) {
284  fr_strerror_printf("Error opening /dev/null: %s", fr_syserror(errno));
285  return -1;
286  }
287 
288  /*
289  * STDOUT & STDERR go to /dev/null, unless we have "-x",
290  * then STDOUT & STDERR go to the "-l log" destination.
291  *
292  * The complexity here is because "-l log" can go to
293  * STDOUT or STDERR, too.
294  */
295  if (log->dst == L_DST_STDOUT) {
296  setlinebuf(stdout);
297  log->fd = STDOUT_FILENO;
298 
299  /*
300  * If we're debugging, allow STDERR to go to
301  * STDOUT too, for executed programs.
302  *
303  * Allow stdout when running in foreground mode
304  * as it's useful for some profiling tools,
305  * like mutrace.
306  */
307  if (rad_debug_lvl || !daemonize) {
308  dup2(STDOUT_FILENO, STDERR_FILENO);
309  } else {
310  dup2(devnull, STDERR_FILENO);
311  }
312 
313  } else if (log->dst == L_DST_STDERR) {
314  setlinebuf(stderr);
315  log->fd = STDERR_FILENO;
316 
317  /*
318  * If we're debugging, allow STDOUT to go to
319  * STDERR too, for executed programs.
320  *
321  * Allow stdout when running in foreground mode
322  * as it's useful for some profiling tools,
323  * like mutrace.
324  */
325  if (rad_debug_lvl || !daemonize) {
326  dup2(STDERR_FILENO, STDOUT_FILENO);
327  } else {
328  dup2(devnull, STDOUT_FILENO);
329  }
330 
331  } else if (log->dst == L_DST_SYSLOG) {
332  /*
333  * Discard STDOUT and STDERR no matter what the
334  * status of debugging. Syslog isn't a file
335  * descriptor, so we can't use it.
336  */
337  dup2(devnull, STDOUT_FILENO);
338  dup2(devnull, STDERR_FILENO);
339 
340  } else if (rad_debug_lvl) {
341  /*
342  * If we're debugging, allow STDOUT and STDERR to
343  * go to the log file.
344  */
345  dup2(log->fd, STDOUT_FILENO);
346  dup2(log->fd, STDERR_FILENO);
347 
348  } else {
349  /*
350  * Not debugging, and the log isn't STDOUT or
351  * STDERR. Ensure that we move both of them to
352  * /dev/null, so that the calling terminal can
353  * exit, and the output from executed programs
354  * doesn't pollute STDOUT / STDERR.
355  */
356  dup2(devnull, STDOUT_FILENO);
357  dup2(devnull, STDERR_FILENO);
358  }
359 
360  close(devnull);
361 
362  fr_fault_set_log_fd(log->fd);
363 
364  return 0;
365 }
366 
367 /** Send a server log message to its destination
368  *
369  * @param type of log message.
370  * @param msg with printf style substitution tokens.
371  * @param ap Substitution arguments.
372  */
373 int vradlog(log_type_t type, char const *msg, va_list ap)
374 {
375  unsigned char *p;
376  char buffer[10240]; /* The largest config item size, then extra for prefixes and suffixes */
377  char *unsan;
378  size_t len;
379  int colourise = default_log.colourise;
380 
381  /*
382  * If we don't want any messages, then
383  * throw them away.
384  */
385  if (default_log.dst == L_DST_NULL) {
386  return 0;
387  }
388 
389  buffer[0] = '\0';
390  len = 0;
391 
392  if (colourise) {
393  len += strlcpy(buffer + len, fr_int2str(colours, type, ""), sizeof(buffer) - len) ;
394  if (len == 0) {
395  colourise = false;
396  }
397  }
398 
399  /*
400  * Mark the point where we treat the buffer as unsanitized.
401  */
402  unsan = buffer + len;
403 
404  /*
405  * Don't print timestamps to syslog, it does that for us.
406  * Don't print timestamps and error types for low levels
407  * of debugging.
408  *
409  * Print timestamps for non-debugging, and for high levels
410  * of debugging.
411  */
412  if (default_log.dst != L_DST_SYSLOG) {
413  if ((rad_debug_lvl != 1) && (rad_debug_lvl != 2)) {
414  time_t timeval;
415 
416  timeval = time(NULL);
417  CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
418 
419  len = strlen(buffer);
420  len += strlcpy(buffer + len, fr_int2str(levels, type, ": "), sizeof(buffer) - len);
421  } else goto add_prefix;
422  } else {
423  add_prefix:
424  if (len < sizeof(buffer)) switch (type) {
425  case L_DBG_WARN:
426  len += strlcpy(buffer + len, "WARNING: ", sizeof(buffer) - len);
427  break;
428 
429  case L_DBG_ERR:
430  len += strlcpy(buffer + len, "ERROR: ", sizeof(buffer) - len);
431  break;
432 
433  default:
434  break;
435  }
436  }
437 
438  if (len < sizeof(buffer)) {
439  len += vsnprintf(buffer + len, sizeof(buffer) - len - 1, msg, ap);
440  }
441 
442  /*
443  * Filter out control chars and non UTF8 chars
444  */
445  for (p = (unsigned char *)unsan; *p != '\0'; p++) {
446  int clen;
447 
448  switch (*p) {
449  case '\r':
450  case '\n':
451  *p = ' ';
452  break;
453 
454  case '\t':
455  continue;
456 
457  default:
458  clen = fr_utf8_char(p, -1);
459  if (!clen) {
460  *p = '?';
461  continue;
462  }
463  p += (clen - 1);
464  break;
465  }
466  }
467 
468  if (colourise && (len < sizeof(buffer))) {
469  len += strlcpy(buffer + len, VTC_RESET, sizeof(buffer) - len);
470  }
471 
472  if (len < (sizeof(buffer) - 2)) {
473  buffer[len] = '\n';
474  buffer[len + 1] = '\0';
475  } else {
476  buffer[sizeof(buffer) - 2] = '\n';
477  buffer[sizeof(buffer) - 1] = '\0';
478  }
479 
480  switch (default_log.dst) {
481 
482 #ifdef HAVE_SYSLOG_H
483  case L_DST_SYSLOG:
484  switch (type) {
485  case L_DBG:
486  case L_DBG_WARN:
487  case L_DBG_ERR:
488  case L_DBG_ERR_REQ:
489  case L_DBG_WARN_REQ:
490  type = LOG_DEBUG;
491  break;
492 
493  case L_AUTH:
494  case L_PROXY:
495  case L_ACCT:
496  type = LOG_NOTICE;
497  break;
498 
499  case L_INFO:
500  type = LOG_INFO;
501  break;
502 
503  case L_WARN:
504  type = LOG_WARNING;
505  break;
506 
507  case L_ERR:
508  type = LOG_ERR;
509  break;
510  }
511  syslog(type, "%s", buffer);
512  break;
513 #endif
514 
515  case L_DST_FILES:
516  case L_DST_STDOUT:
517  case L_DST_STDERR:
518  return write(default_log.fd, buffer, strlen(buffer));
519 
520  default:
521  case L_DST_NULL: /* should have been caught above */
522  break;
523  }
524 
525  return 0;
526 }
527 
528 /** Send a server log message to its destination
529  *
530  * @param type of log message.
531  * @param msg with printf style substitution tokens.
532  * @param ... Substitution arguments.
533  */
534 int radlog(log_type_t type, char const *msg, ...)
535 {
536  va_list ap;
537  int r = 0;
538 
539  va_start(ap, msg);
540 
541  /*
542  * Non-debug message, or debugging is enabled. Log it.
543  */
544  if (((type & L_DBG) == 0) || (rad_debug_lvl > 0)) {
545  r = vradlog(type, msg, ap);
546  }
547  va_end(ap);
548 
549  return r;
550 }
551 
552 /** Send a server log message to its destination without evaluating its debug level
553  *
554  * @param type of log message.
555  * @param msg with printf style substitution tokens.
556  * @param ... Substitution arguments.
557  */
558 static int radlog_always(log_type_t type, char const *msg, ...) CC_HINT(format (printf, 2, 3));
559 static int radlog_always(log_type_t type, char const *msg, ...)
560 {
561  va_list ap;
562  int r;
563 
564  va_start(ap, msg);
565  r = vradlog(type, msg, ap);
566  va_end(ap);
567 
568  return r;
569 }
570 
571 /** Whether a server debug message should be logged
572  *
573  * @param type of message.
574  * @param lvl of debugging this message should be logged at.
575  * @return
576  * - true if message should be logged.
577  * - false if message shouldn't be logged.
578  */
579 inline bool debug_enabled(log_type_t type, log_lvl_t lvl)
580 {
581  if ((type & L_DBG) && (lvl <= rad_debug_lvl)) return true;
582 
583  return false;
584 }
585 
586 /** Whether rate limiting is enabled
587  */
589 {
590  if (rate_limit || (rad_debug_lvl < 1)) return true;
591 
592  return false;
593 }
594 
595 /** Whether a request specific debug message should be logged
596  *
597  * @param type of message.
598  * @param lvl of debugging this message should be logged at.
599  * @param request The current request.
600  * @return
601  * - true if message should be logged.
602  * - false if message shouldn't be logged.
603  */
604 inline bool radlog_debug_enabled(log_type_t type, log_lvl_t lvl, REQUEST *request)
605 {
606  /*
607  * It's a debug class message, note this doesn't mean it's a debug type message.
608  *
609  * For example it could be a RIDEBUG message, which would be an informational message,
610  * instead of an RDEBUG message which would be a debug debug message.
611  *
612  * There is log function, but the request debug level isn't high enough.
613  * OR, we're in debug mode, and the global debug level isn't high enough,
614  * then don't log the message.
615  */
616  if ((type & L_DBG) &&
617  ((request->log.func && (lvl <= request->log.lvl)) ||
618  ((rad_debug_lvl != 0) && (lvl <= rad_debug_lvl)))) {
619  return true;
620  }
621 
622  return false;
623 }
624 
625 /** Send a log message to its destination, possibly including fields from the request
626  *
627  * @param type of log message, #L_ERR, #L_WARN, #L_INFO, #L_DBG.
628  * @param lvl Minimum required server or request level to output this message.
629  * @param request The current request.
630  * @param msg with printf style substitution tokens.
631  * @param ap Substitution arguments.
632  */
633 void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap)
634 {
635  size_t len = 0;
636  char const *filename = default_log.file;
637  FILE *fp = NULL;
638 
639  char buffer[10240]; /* The largest config item size, then extra for prefixes and suffixes */
640 
641  char *p;
642  char const *extra = "";
643  uint8_t indent;
644  va_list aq;
645 
646  rad_assert(request);
647 
648  /*
649  * Debug messages get treated specially.
650  */
651  if ((type & L_DBG) != 0) {
652  if (!radlog_debug_enabled(type, lvl, request)) {
653  return;
654  }
655 
656 #ifdef WITH_COMMAND_SOCKET
657  /*
658  * If we're debugging to a file, then use that.
659  *
660  * @todo: have vradlog() take a fr_log_t*, so
661  * that we can cache the opened descriptor, and
662  * we don't need to re-open it on every log
663  * message.
664  */
665  if (request->log.output) {
666  if (request->log.output->dst == L_DST_FILES) {
667  fp = fopen(request->log.output->file, "a");
668 
669 #if defined(HAVE_FOPENCOOKIE) || defined (HAVE_FUNOPEN)
670  } else if (request->log.output->dst == L_DST_EXTRA) {
671 # ifdef HAVE_FOPENCOOKIE
672  cookie_io_functions_t io;
673 
674  /*
675  * These must be set separately as they have different prototypes.
676  */
677  io.read = NULL;
678  io.seek = NULL;
679  io.close = NULL;
680  io.write = request->log.output->cookie_write;
681 
682  fp = fopencookie(request->log.output->cookie, "w", io);
683 # else
684  fp = funopen(request->log.output->cookie,
685  NULL, request->log.output->cookie_write, NULL, NULL);
686 # endif
687 #endif
688  }
689  if (!fp) return;
690 
691  goto print_msg;
692  }
693 #endif
694  }
695 
696  if (filename) {
697  radlog_func_t rl = request->log.func;
698 
699  request->log.func = NULL;
700 
701  /*
702  * This is SLOW! Doing it for every log message
703  * in every request is NOT recommended!
704  */
705  if (radius_xlat(buffer, sizeof(buffer), request, filename, rad_filename_escape, NULL) < 0) return;
706  request->log.func = rl;
707 
708  /*
709  * Ensure the directory structure exists, for
710  * where we're going to write the log file.
711  */
712  p = strrchr(buffer, FR_DIR_SEP);
713  if (p) {
714  *p = '\0';
715  if (rad_mkdir(buffer, S_IRWXU, -1, -1) < 0) {
716  ERROR("Failed creating %s: %s", buffer, fr_syserror(errno));
717  return;
718  }
719  *p = FR_DIR_SEP;
720  }
721 
722  fp = fopen(buffer, "a");
723  }
724 
725 print_msg:
726  /*
727  * If we don't copy the original ap we get a segfault from vasprintf. This is apparently
728  * due to ap sometimes being implemented with a stack offset which is invalidated if
729  * ap is passed into another function. See here:
730  * http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html
731  *
732  * I don't buy that explanation, but doing a va_copy here does prevent SEGVs seen when
733  * running unit tests which generate errors under CI.
734  */
735  va_copy(aq, ap);
736  vsnprintf(buffer + len, sizeof(buffer) - len, msg, aq);
737  va_end(aq);
738 
739  /*
740  * Make sure the indent isn't set to something crazy
741  */
742  indent = request->log.indent > sizeof(spaces) ?
743  sizeof(spaces) :
744  request->log.indent;
745 
746  /*
747  * Logging to a file descriptor
748  */
749  if (fp) {
750  char time_buff[64]; /* The current timestamp */
751 
752  time_t timeval;
753  timeval = time(NULL);
754 
755 #ifdef HAVE_GMTIME_R
756  if (log_dates_utc) {
757  struct tm utc;
758  gmtime_r(&timeval, &utc);
759  ASCTIME_R(&utc, time_buff, sizeof(time_buff));
760  } else
761 #endif
762  {
763  CTIME_R(&timeval, time_buff, sizeof(time_buff));
764  }
765 
766  /*
767  * Strip trailing new lines
768  */
769  p = strrchr(time_buff, '\n');
770  if (p) p[0] = '\0';
771 
772  if (request->module && (request->module[0] != '\0')) {
773  fprintf(fp, "(%u) %s%s%s: %.*s%s\n",
774  request->number, time_buff, fr_int2str(levels, type, ""),
775  request->module, indent, spaces, buffer);
776  } else {
777  fprintf(fp, "(%u) %s%s%.*s%s\n",
778  request->number, time_buff, fr_int2str(levels, type, ""),
779  indent, spaces, buffer);
780  }
781  fclose(fp);
782  return;
783  }
784 
785  /*
786  * Logging everywhere else
787  */
788  if (!DEBUG_ENABLED3) switch (type) {
789  case L_DBG_WARN:
790  extra = "WARNING: ";
791  type = L_DBG_WARN_REQ;
792  break;
793 
794  case L_DBG_ERR:
795  extra = "ERROR: ";
796  type = L_DBG_ERR_REQ;
797  break;
798  default:
799  break;
800  }
801 
802  if (request->module && (request->module[0] != '\0')) {
803  radlog_always(type, "(%u) %s: %.*s%s%s", request->number,
804  request->module, indent, spaces, extra, buffer);
805  } else {
806  radlog_always(type, "(%u) %.*s%s%s", request->number,
807  indent, spaces, extra, buffer);
808  }
809 }
810 
811 /** Martial variadic log arguments into a va_list and pass to normal logging functions
812  *
813  * @see radlog_request_error for more details.
814  *
815  * @param type the log category.
816  * @param lvl of debugging this message should be logged at.
817  * @param request The current request.
818  * @param msg with printf style substitution tokens.
819  * @param ... Substitution arguments.
820  */
821 void radlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
822 {
823  va_list ap;
824 
825  rad_assert(request);
826 
827  if (!request->log.func && !(type & L_DBG)) return;
828 
829  va_start(ap, msg);
830  if (request->log.func) request->log.func(type, lvl, request, msg, ap);
831  else if (!(type & L_DBG)) vradlog_request(type, lvl, request, msg, ap);
832  va_end(ap);
833 }
834 
835 /** Martial variadic log arguments into a va_list and pass to error logging functions
836  *
837  * This could all be done in a macro, but it turns out some implementations of the
838  * variadic macros do not work at all well if the va_list being written to is further
839  * up the stack (which is required as you still need a function to convert the elipses
840  * into a va_list).
841  *
842  * So, we use this small wrapper function instead, which will hopefully guarantee
843  * consistent behaviour.
844  *
845  * @param type the log category.
846  * @param lvl of debugging this message should be logged at.
847  * @param request The current request.
848  * @param msg with printf style substitution tokens.
849  * @param ... Substitution arguments.
850  */
851 void radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, ...)
852 {
853  va_list ap;
854 
855  rad_assert(request);
856 
857  va_start(ap, msg);
858  if (request->log.func) request->log.func(type, lvl, request, msg, ap);
859  else if (!(type & L_DBG)) vradlog_request(type, lvl, request, msg, ap);
860  vmodule_failure_msg(request, msg, ap);
861  va_end(ap);
862 }
863 
864 /** Write the string being parsed, and a marker showing where the parse error occurred
865  *
866  * @param type the log category.
867  * @param lvl of debugging this message should be logged at.
868  * @param request The current request.
869  * @param msg string we were parsing.
870  * @param idx The position of the marker relative to the string.
871  * @param error What the parse error was.
872  */
874  char const *msg, size_t idx, char const *error)
875 {
876  char const *prefix = "";
877  uint8_t indent;
878 
879  rad_assert(request);
880 
881  if (idx >= sizeof(spaces)) {
882  size_t offset = (idx - (sizeof(spaces) - 1)) + (sizeof(spaces) * 0.75);
883  idx -= offset;
884  msg += offset;
885 
886  prefix = "... ";
887  }
888 
889  /*
890  * Don't want format markers being indented
891  */
892  indent = request->log.indent;
893  request->log.indent = 0;
894 
895  radlog_request(type, lvl, request, "%s%s", prefix, msg);
896  radlog_request(type, lvl, request, "%s%.*s^ %s", prefix, (int) idx, spaces, error);
897 
898  request->log.indent = indent;
899 }
PUBLIC int vsnprintf(char *string, size_t length, char *format, va_list args)
Definition: snprintf.c:503
Only displayed when debugging is enabled.
Definition: log.h:41
static const FR_NAME_NUMBER levels[]
Maps log categories to message prefixes.
Definition: log.c:54
Send log messages to a FILE*, via fopencookie()
Definition: log.h:62
void(* radlog_func_t)(log_type_t lvl, log_lvl_t priority, REQUEST *, char const *, va_list ap)
Definition: log.h:83
enum log_type log_type_t
struct rad_request::@7 log
Less severe warning only displayed when debugging is enabled.
Definition: log.h:44
void fr_fault_set_cb(fr_fault_cb_t func)
Set a callback to be called before fr_fault()
Definition: debug.c:1043
#define DEBUG_ENABLED3
True if global debug level 1-3 messages are enabled.
Definition: log.h:171
bool debug_enabled(log_type_t type, log_lvl_t lvl)
Whether a server debug message should be logged.
Definition: log.c:579
static int stderr_fd
The original unmolested stderr file descriptor.
Definition: log.c:223
Warning.
Definition: log.h:37
fr_log_t default_log
Definition: log.c:216
Less severe error only displayed when debugging is enabled.
Definition: log.h:45
#define CC_HINT(_x)
Definition: build.h:71
Log to syslog.
Definition: log.h:60
size_t rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen, char const *in, UNUSED void *arg)
Escapes the raw string such that it should be safe to use as part of a file path. ...
Definition: util.c:269
#define UNUSED
Definition: libradius.h:134
static bool rate_limit
Whether repeated log entries should be rate limited.
Definition: log.c:50
Error message.
Definition: log.h:36
#define VTC_BOLD
Embolden following text.
Definition: log.c:81
void fr_strerror_printf(char const *fmt,...)
Log to thread local error buffer.
Definition: log.c:152
unsigned int number
Monotonically increasing request number. Reset on server restart.
Definition: radiusd.h:213
static int stdout_fd
The original unmolested stdout file descriptor.
Definition: log.c:224
int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid)
Create possibly many directories.
Definition: util.c:90
bool radlog_debug_enabled(log_type_t type, log_lvl_t lvl, REQUEST *request)
Whether a request specific debug message should be logged.
Definition: log.c:604
void radlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg,...)
Martial variadic log arguments into a va_list and pass to normal logging functions.
Definition: log.c:821
#define rad_assert(expr)
Definition: rad_assert.h:38
#define VTC_RED
Colour following text red.
Definition: log.c:79
Accounting messages.
Definition: log.h:39
Log to stderr.
Definition: log.h:61
int vradlog(log_type_t type, char const *msg, va_list ap)
Send a server log message to its destination.
Definition: log.c:373
const FR_NAME_NUMBER syslog_facility_table[]
Syslog facility table.
Definition: log.c:110
void fr_fault_set_log_fd(int fd)
Set a file descriptor to log memory reports to.
Definition: debug.c:1072
int radlog(log_type_t type, char const *msg,...)
Send a server log message to its destination.
Definition: log.c:534
void radlog_request_error(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg,...)
Martial variadic log arguments into a va_list and pass to error logging functions.
Definition: log.c:851
bool rate_limit_enabled(void)
Whether rate limiting is enabled.
Definition: log.c:588
Definition: log.h:68
log_lvl_t rad_debug_lvl
Global debugging level.
Definition: log.c:49
static char const spaces[]
Definition: log.c:226
void vradlog_request(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, va_list ap)
Send a log message to its destination, possibly including fields from the request.
Definition: log.c:633
Authentication message.
Definition: log.h:34
void void vmodule_failure_msg(REQUEST *request, char const *fmt, va_list ap) CC_HINT(format(printf
ssize_t radius_xlat(char *out, size_t outlen, REQUEST *request, char const *fmt, xlat_escape_t escape, void *escape_ctx) CC_HINT(nonnull(1
char const * file
Path to log file.
Definition: log.h:73
Log to a file on disk.
Definition: log.h:59
static char const * prefix
Definition: mainconfig.c:81
#define VTC_RESET
Reset terminal text to default style/colour.
Definition: log.c:82
#define VTC_YELLOW
Colour following text yellow.
Definition: log.c:80
enum log_lvl log_lvl_t
int radlog_init(fr_log_t *log, bool daemonize)
Initialise file descriptors based on logging destination.
Definition: log.c:257
static int _restore_std(UNUSED int sig)
On fault, reset STDOUT and STDERR to something useful.
Definition: log.c:232
bool log_dates_utc
Definition: log.c:214
Proxy messages.
Definition: log.h:38
Discard log messages.
Definition: log.h:63
Error only displayed when debugging is enabled.
Definition: log.h:43
size_t strlcpy(char *dst, char const *src, size_t siz)
Definition: strlcpy.c:38
char const * fr_int2str(FR_NAME_NUMBER const *table, int number, char const *def)
Definition: token.c:506
bool colourise
Prefix log messages with VT100 escape codes to change text colour.
Definition: log.h:69
int fr_utf8_char(uint8_t const *str, ssize_t inlen)
Checks for utf-8, taken from http://www.w3.org/International/questions/qa-forms-utf-8.
Definition: print.c:34
Warning only displayed when debugging is enabled.
Definition: log.h:42
log_dst_t dst
Log destination.
Definition: log.h:72
static const FR_NAME_NUMBER colours[]
Maps log categories to VT100 style/colour escape sequences.
Definition: log.c:87
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
Definition: log.c:238
Log to stdout.
Definition: log.h:58
Informational message.
Definition: log.h:35
const FR_NAME_NUMBER syslog_severity_table[]
Syslog severity table.
Definition: log.c:177
const FR_NAME_NUMBER log_str2dst[]
Definition: log.c:205
#define RCSID(id)
Definition: build.h:135
static int r
Definition: rbmonkey.c:66
char const * module
Module the request is currently being processed by.
Definition: radiusd.h:253
static int radlog_always(log_type_t type, char const *msg,...) CC_HINT(format(printf
Send a server log message to its destination without evaluating its debug level.
Definition: log.c:559
int fd
File descriptor to write messages to.
Definition: log.h:71
#define ERROR(fmt,...)
Definition: log.h:145
void radlog_request_marker(log_type_t type, log_lvl_t lvl, REQUEST *request, char const *msg, size_t idx, char const *error)
Write the string being parsed, and a marker showing where the parse error occurred.
Definition: log.c:873
struct tm * gmtime_r(time_t const *l_clock, struct tm *result)
Definition: missing.c:190