diff --git a/README.md b/README.md index 9d1d5fb..3e7cd29 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ systemd-netlogd reads configuration files named `/etc/systemd/netlogd.conf` and Specifies whether to use udp, tcp, tls or dtls (Datagram Transport Layer Security) protocol. Defaults to udp. LogFormat= - Specifies whether to use RFC 5424 format or RFC 3339 format. Takes one of rfc5424 or rfc3339. Defaults to rfc5424. + Specifies whether to use RFC 5424, RFC 5425, or RFC 3339 format. Takes one of rfc5424, rfc5425, or rfc3339. Defaults to rfc5424. RFC 5425 is mainly useful for sending over TLS; it prepends a message length field to the RFC 5424 format. Directory= Takes a directory path. Specifies whether to operate on the specified journal directory DIR instead of the default runtime and system journal paths. diff --git a/doc/index.rst b/doc/index.rst index 0849b84..7878c56 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -34,7 +34,7 @@ This will create a user systemd-journal-netlog Specifies whether to use udp, tcp, tls or dtls (Datagram Transport Layer Security) protocol. Defaults to udp. | ``LogFormat=`` - Specifies whether to use RFC 5424 format or RFC 3339 format. Takes one of rfc5424 or rfc3339. Defaults to rfc5424. + Specifies whether to use RFC 5424, RFC 5425, or RFC 3339 format. Takes one of rfc5424, rfc5425, or rfc3339. Defaults to rfc5424. RFC 5425 is mainly useful for sending over TLS; it prepends a message length field to the RFC 5424 format. | ``Directory=`` Takes a directory path. Specifies whether to operate on the specified journal directory DIR instead of the default runtime and system journal paths. diff --git a/src/netlog/netlog-manager.c b/src/netlog/netlog-manager.c index 7ba18ae..fc7cc5c 100644 --- a/src/netlog/netlog-manager.c +++ b/src/netlog/netlog-manager.c @@ -39,6 +39,7 @@ DEFINE_STRING_TABLE_LOOKUP(protocol, SysLogTransmissionProtocol); static const char *const log_format_table[_SYSLOG_TRANSMISSION_LOG_FORMAT_MAX] = { [SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424] = "rfc5424", + [SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5425] = "rfc5425", [SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_3339] = "rfc3339", }; diff --git a/src/netlog/netlog-manager.h b/src/netlog/netlog-manager.h index 48adccb..148b1fb 100644 --- a/src/netlog/netlog-manager.h +++ b/src/netlog/netlog-manager.h @@ -25,6 +25,7 @@ typedef enum SysLogTransmissionProtocol { typedef enum SysLogTransmissionLogFormat { SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424 = 1 << 0, SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_3339 = 1 << 1, + SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5425 = 1 << 2, _SYSLOG_TRANSMISSION_LOG_FORMAT_MAX, _SYSLOG_TRANSMISSION_LOG_FORMAT_INVALID = -EINVAL, } SysLogTransmissionLogFormat; diff --git a/src/netlog/netlog-network.c b/src/netlog/netlog-network.c index 4081343..4bbb148 100644 --- a/src/netlog/netlog-network.c +++ b/src/netlog/netlog-network.c @@ -112,7 +112,7 @@ int manager_push_to_network(Manager *m, break; } - if (m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424) + if (m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424 || m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5425) r = format_rfc5424(m, severity, facility, identifier, message, hostname, pid, tv, syslog_structured_data, syslog_msgid); else r = format_rfc3339(m, severity, facility, identifier, message, hostname, pid, tv); diff --git a/src/netlog/netlog-protocol.c b/src/netlog/netlog-protocol.c index 9260f4c..daeab90 100644 --- a/src/netlog/netlog-protocol.c +++ b/src/netlog/netlog-protocol.c @@ -97,15 +97,23 @@ int format_rfc5424(Manager *m, char header_time[FORMAT_TIMESTAMP_MAX]; char header_priority[sizeof("< >1 ")]; - struct iovec iov[14]; + char header_msglen[1 + sizeof("99999 ")]; + struct iovec iov[15]; uint8_t makepri; - int n = 0, r; + int n = 0, r, msglen_idx; + size_t msglen_len; assert(m); assert(message); makepri = (facility << 3) + severity; + /* Zeroth: for RFC5425, the message length (octet count). Will be filled below */ + if (m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5425) { + msglen_idx = n; + IOVEC_SET_STRING(iov[n++], ""); + } + /* First: priority field Second: Version 'version' */ r = snprintf(header_priority, sizeof(header_priority), "<%i>%i ", makepri, RFC_5424_PROTOCOL); assert(r > 0 && (size_t)r < sizeof(header_priority)); @@ -161,11 +169,23 @@ int format_rfc5424(Manager *m, IOVEC_SET_STRING(iov[n++], message); /* Last Optional newline message separator, if not implicitly terminated by end of UDP frame - * De facto standard: separate messages by a newline + * De facto standard: separate messages by a newline (alternative is RFC 5425, with explicit + * lengths) */ - if (m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TCP || m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TLS) + if (m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5424 + && (m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TCP || m->protocol == SYSLOG_TRANSMISSION_PROTOCOL_TLS)) IOVEC_SET_STRING(iov[n++], "\n"); + /* Finally, for RFC5425 format, compute the length field which goes at the start, before the + * message. This is what we left space for above. */ + if (m->log_format == SYSLOG_TRANSMISSION_LOG_FORMAT_RFC_5425) { + msglen_len = snprintf(header_msglen, sizeof(header_msglen), "%zi ", IOVEC_TOTAL_SIZE(iov, n)); + if (msglen_len >= sizeof(header_msglen)) + return -EMSGSIZE; + iov[msglen_idx].iov_base = header_msglen; + iov[msglen_idx].iov_len = msglen_len; + } + return protocol_send(m, iov, n); }