The DEBUG messages are printed only when the server has the debug flag set.
-== %log.destination(_string_, [_uint32_])
+== %log.destination(_string_, [_uint32_], [_filename_])
The `%log.destination()` function updates the current request to add a new debug log destination. The second argument sets the debug level (0..4). If omitted, the default is `2`. The special value `0` will remove the named log destination.
An existing log destination can be set multiple times. The first time it is set, the log destination is added. The second and subsequent times it is set, the log level is changed. The server will not send duplicate messages to the same logging destination.
+If a filename is specified, then the first argument must be a log section which has `destination = files`. If so, that section is used as a template for log configuration. However, the given `filename` is used instead of the `filename` in the log section.
+
+This parameter allows for logging to go to a file which is specific to a particular request.
+
+When the request finishes, the file is closed. Multiple requests may use the same file, however there is no inter-request locking, so log messages might be interspersed.
+
.Log Configuration in radiusd.conf
----
log tmp {
return XLAT_ACTION_DONE;
}
+static int _log_dst_free(fr_log_t *log)
+{
+ close(log->fd);
+ return 0;
+}
+
static xlat_arg_parser_t const xlat_func_log_dst_args[] = {
{ .required = true, .type = FR_TYPE_STRING },
{ .required = false, .type = FR_TYPE_UINT32 },
+ { .required = false, .type = FR_TYPE_STRING },
XLAT_ARG_PARSER_TERMINATOR
};
UNUSED xlat_ctx_t const *xctx,
request_t *request, fr_value_box_list_t *args)
{
- fr_value_box_t *dst, *lvl;
- fr_log_t *log;
+ fr_value_box_t *dst, *lvl, *file;
+ fr_log_t *log, *dbg;
uint32_t level = 2;
- XLAT_ARGS(args, &dst, &lvl);
+ XLAT_ARGS(args, &dst, &lvl, &file);
if (!dst || !*dst->vb_strvalue) {
request_log_prepend(request, NULL, L_DBG_LVL_OFF);
if (lvl) level = lvl->vb_uint32;
- request_log_prepend(request, log, level);
+ if (!file || (log->dst != L_DST_FILES)) {
+ request_log_prepend(request, log, level);
+ return XLAT_ACTION_DONE;
+ }
+
+ /*
+ * Clone it.
+ */
+ MEM(dbg = talloc_memdup(request, log, sizeof(*log)));
+
+ /*
+ * Open the new filename.
+ */
+ dbg->file = talloc_strdup(dbg, file->vb_strvalue);
+ dbg->fd = open(dbg->file, O_WRONLY | O_CREAT | O_CLOEXEC);
+ if (!dbg->fd) {
+ REDEBUG("Failed opening %s - %s", dbg->file, fr_syserror(errno));
+ talloc_free(dbg);
+ return XLAT_ACTION_DONE;
+ }
+
+ /*
+ * Ensure that we close the file handle when done.
+ */
+ talloc_set_destructor(dbg, _log_dst_free);
+
+ request_log_prepend(request, dbg, level);
return XLAT_ACTION_DONE;
}