Hi,

Implement octet counting for syslog TCP and TLS streams.  For TCP
it is optional, but TLS must use this framing.

Some interoperability tests with remote syslog servers would help.

bluhm

Index: usr.sbin/syslogd/syslogd.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/usr.sbin/syslogd/syslogd.c,v
retrieving revision 1.147
diff -u -p -r1.147 syslogd.c
--- usr.sbin/syslogd/syslogd.c  2 Feb 2015 17:27:43 -0000       1.147
+++ usr.sbin/syslogd/syslogd.c  5 Feb 2015 00:39:01 -0000
@@ -787,6 +787,8 @@ void
 tcp_errorcb(struct bufferevent *bufev, short event, void *arg)
 {
        struct filed    *f = arg;
+       char            *p, *buf, *end;
+       int              i;
        char             ebuf[256];
 
        if (event & EVBUFFER_EOF)
@@ -810,10 +812,29 @@ tcp_errorcb(struct bufferevent *bufev, s
        f->f_file = -1;
 
        /*
-        * XXX The messages in the output buffer may be out of sync.
-        * Here we should clear the buffer or at least remove partial
-        * messages from the beginning.
+        * The messages in the output buffer may be out of sync.
+        * Check that the buffer starts with "1234 <1234 octets>\n".
+        * Otherwise remove the partial message from the beginning.
         */
+       buf = EVBUFFER_DATA(bufev->output);
+       end = buf + EVBUFFER_LENGTH(bufev->output);
+       for (p = buf; p < end && p < buf + 4; p++) {
+               if (!isdigit(*p))
+                       break;
+       }
+       if (!(buf + 1 <= p && p < end && *p == ' ' &&
+           (i = atoi(buf)) > 0 && buf + i < end && buf[i] == '\n')) {
+               for (p = buf; p < end; p++) {
+                       if (*p == '\n') {
+                               evbuffer_drain(bufev->output, p - buf + 1);
+                               break;
+                       }
+               }
+               /* Without '\n' discard everything. */
+               if (p == end)
+                       evbuffer_drain(bufev->output, p - buf);
+       }
+
        tcp_connectcb(-1, 0, f);
 
        /* Log the connection error to the fresh buffer after reconnecting. */
@@ -1216,12 +1237,21 @@ fprintlog(struct filed *f, int flags, ch
                    MAX_TCPBUF)
                        break;  /* XXX log error message */
                /*
-                * RFC 6587  3.4.2.  Non-Transparent-Framing
-                * Use \n to split messages for now.
-                * 3.4.1.  Octet Counting might be implemented later.
+                * RFC 6587  3.4.1.  Octet Counting
+                * Use an additional '\n' to split messages.  This allows
+                * buffer synchronisation, helps legacy implementations,
+                * and makes line based testing easier.
                 */
+               l = snprintf(line, sizeof(line), "<%d>%.15s %s%s\n",
+                   f->f_prevpri, (char *)iov[0].iov_base,
+                   IncludeHostname ? LocalHostName : "",
+                   IncludeHostname ? " " : "");
+               if (l < 0)
+                       break;  /* XXX log error message */
                l = evbuffer_add_printf(f->f_un.f_forw.f_bufev->output,
-                   "<%d>%.15s %s%s%s\n", f->f_prevpri, (char *)iov[0].iov_base,
+                   "%zu <%d>%.15s %s%s%s\n",
+                   (size_t)l + strlen(iov[4].iov_base),
+                   f->f_prevpri, (char *)iov[0].iov_base,
                    IncludeHostname ? LocalHostName : "",
                    IncludeHostname ? " " : "",
                    (char *)iov[4].iov_base);

Reply via email to