]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add header option to linelog
authorNick Porter <nick@portercomputing.co.uk>
Fri, 11 Nov 2022 13:54:53 +0000 (13:54 +0000)
committerNick Porter <nick@portercomputing.co.uk>
Tue, 22 Nov 2022 11:16:02 +0000 (11:16 +0000)
raddb/mods-available/linelog
src/modules/rlm_linelog/rlm_linelog.c

index bfe684252ea4311030c46b5ac54dc412d15d03c7..e484acc0e86877fc9f7e14026b21ae1a92cafa7e 100644 (file)
@@ -84,6 +84,15 @@ linelog {
                Access-Challenge = "Sent challenge: %{User-Name}"
        }
 
+       #
+       #  header:: Optional header line format for file output
+       #
+       #  If the destination is "file" and header is set, then this
+       #  is expanded and output as the first line when a new file
+       #  is created.
+       #
+#      header = ""
+
        #
        #  destination:: What should be done with log messages.
        #
index fa480bd2d512dcf0ed63e8f15a0e31d5dc5e0cef..a68035de8aa75b849b66f4ed2b75123e78d459ac 100644 (file)
@@ -89,6 +89,8 @@ typedef struct {
        tmpl_t                  *log_ref;               //!< Path to a #CONF_PAIR (to use as the source of
                                                        ///< log messages).
 
+       tmpl_t                  *log_head;              //!< Header to add to each new log file.
+
        linefr_log_dst_t        log_dst;                //!< Logging destination.
        char const              *log_dst_str;           //!< Logging destination string.
 
@@ -163,6 +165,7 @@ static const CONF_PARSER module_config[] = {
        { FR_CONF_OFFSET("delimiter", FR_TYPE_STRING, rlm_linelog_t, delimiter), .dflt = "\n" },
        { FR_CONF_OFFSET("format", FR_TYPE_TMPL, rlm_linelog_t, log_src) },
        { FR_CONF_OFFSET("reference", FR_TYPE_TMPL, rlm_linelog_t, log_ref) },
+       { FR_CONF_OFFSET("header", FR_TYPE_TMPL, rlm_linelog_t, log_head) },
 
        /*
         *      Log destinations
@@ -646,6 +649,7 @@ build_vector:
        {
                int fd = -1;
                char path[2048];
+               off_t offset;
 
                if (xlat_eval(path, sizeof(path), request, inst->file.name, inst->file.escape_func, NULL) < 0) {
                        RETURN_MODULE_FAIL;
@@ -663,7 +667,7 @@ build_vector:
                        *p = '/';
                }
 
-               fd = exfile_open(inst->file.ef, path, inst->file.permissions, NULL);
+               fd = exfile_open(inst->file.ef, path, inst->file.permissions, &offset);
                if (fd < 0) {
                        RERROR("Failed to open %s: %s", path, fr_syserror(errno));
                        rcode = RLM_MODULE_FAIL;
@@ -674,6 +678,47 @@ build_vector:
                        RPWARN("Unable to change system group of \"%s\": %s", path, fr_strerror());
                }
 
+               /*
+                *      If a header format is defined and we are at the beginning
+                *      of the file then expand the format and write it out before
+                *      writing the actual log entries.
+                */
+               if (inst->log_head && (offset == 0)) {
+                       char            head[4096];
+                       char            *head_value;
+                       struct iovec    head_vector_s[2];
+                       size_t          head_vector_len;
+
+                       slen = tmpl_expand(&head_value, head, sizeof(head), request, inst->log_head,
+                                         linelog_escape_func, NULL);
+                       if (slen < 0) {
+                               rcode = RLM_MODULE_FAIL;
+                               goto finish;
+                       }
+
+                       memcpy(&head_vector_s[0].iov_base, &head_value, sizeof(head_vector_s[0].iov_base));
+                       head_vector_s[0].iov_len = slen;
+
+                       if (!with_delim) {
+                               head_vector_len = 1;
+                       } else {
+                               memcpy(&head_vector_s[1].iov_base, &(inst->delimiter),
+                                      sizeof(head_vector_s[1].iov_base));
+                               head_vector_s[1].iov_len = inst->delimiter_len;
+                               head_vector_len = 2;
+                       }
+
+                       if (writev(fd, &head_vector_s[0], head_vector_len) < 0) {
+                               RERROR("Failed writing to \"%s\": %s", path, fr_syserror(errno));
+                               exfile_close(inst->file.ef, fd);
+
+                               /* Assert on the extra fatal errors */
+                               fr_assert((errno != EINVAL) && (errno != EFAULT));
+
+                               RETURN_MODULE_FAIL;
+                       }
+               }
+
                if (writev(fd, vector_p, vector_len) < 0) {
                        RERROR("Failed writing to \"%s\": %s", path, fr_syserror(errno));
                        exfile_close(inst->file.ef, fd);