]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
logger: bugfix: tcp syslog framing is broken, -T unusable
authorRainer Gerhards <rgerhards@adiscon.com>
Fri, 6 Mar 2015 11:12:15 +0000 (12:12 +0100)
committerRainer Gerhards <rgerhards@adiscon.com>
Fri, 6 Mar 2015 11:12:15 +0000 (12:12 +0100)
Logger can send via plain tcp syslog if -n -T options are given.
However, the framing is broken so that a syslog receiver can not
know where the first message ends and the next one starts. It
actually looks like no framing at all is used. Plain TCP syslog
framing is described in RFC6587.

This patch adds RFC6587 octet-stuffed framing to TCP syslog. For
local logging, this is always fine, for remote logging this is
NOT recommended by the IETF (the RFC is historic). However, a
full blown RFC5425 TLS sender seems to be out of scope for a tool
like logger IMO.

This patch also refactors the way output is written, seperating
the message format generators from the output writer.

misc-utils/logger.c

index 6869f44d75d52a57b1ed508ff25db4d2d6701799..e19ef05903ac1c157094e54e7009c591c89caa90 100644 (file)
@@ -332,11 +332,26 @@ rfc3164_current_time(void)
        return time;
 }
 
+/* writes generated buffer to desired destination. For TCP syslog,
+ * we use RFC6587 octet-stuffing. This is not great, but doing
+ * full blown RFC5425 (TLS) looks like it is too much for the
+ * logger utility.
+ */
 static void write_output(const struct logger_ctl *ctl, const char *const buf,
        const size_t len)
 {
        if (write_all(ctl->fd, buf, len) < 0)
                warn(_("write failed"));
+       else
+               if (ctl->socket_type == TYPE_TCP)
+                       /* using an additional write seems like the best compromise:
+                        * - writev() is not yet supported by framework
+                        * - adding the \n to the buffer in formatters violates layers
+                        * - adding \n after the fact requires memory copy
+                        * - logger is not a high-performance app
+                        */
+                       if (write_all(ctl->fd, "\n", 1) < 0)
+                               warn(_("write failed"));
        if (ctl->stderr_printout)
                fprintf(stderr, "%s\n", buf);
 }