]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
add file destination
authorAlan T. DeKok <aland@freeradius.org>
Wed, 22 Nov 2023 15:07:09 +0000 (10:07 -0500)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 22 Nov 2023 15:07:22 +0000 (10:07 -0500)
doc/antora/modules/reference/pages/xlat/log.adoc
src/lib/unlang/xlat_builtin.c

index 0f22431560e448bf920e007bd53ade8991c305e1..9a94a77d187293d3df46aa6d9071b05d550d095c 100644 (file)
@@ -17,7 +17,7 @@ Logs a message at a DEBUG level.  This function returns nothing.
 
 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.
 
@@ -27,6 +27,12 @@ This function is normally used to _add_ a new log destination.  Any extra debug
 
 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 {
index 3d3c57d69c7a65fdda3481561b5650f27c44370d..7e3ef596b000901818afe1ed163f9e1005ccc218 100644 (file)
@@ -1152,9 +1152,16 @@ static xlat_action_t xlat_func_log_warn(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcurso
        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
 };
 
@@ -1171,11 +1178,11 @@ static xlat_action_t xlat_func_log_dst(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor
                                       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);
@@ -1187,7 +1194,33 @@ static xlat_action_t xlat_func_log_dst(UNUSED TALLOC_CTX *ctx, UNUSED fr_dcursor
 
        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;
 }