Skip to content

RFC Compliance Matrix

SolidSyslog implements the sender (client) side of four syslog RFCs. This document tracks which requirements are currently met, partially met, or planned.

Status key:

  • Supported: implemented and tested
  • Partial: implemented with known limitations
  • Planned: tracked in an issue or epic
  • N/A: not applicable to a sender implementation

RFC 5424 — The Syslog Protocol

Section Requirement Status Notes
6.1 PRI — facility * 8 + severity Supported Invalid values fall back to syslog.err (facility 5, severity 3)
6.2.1 VERSION = 1 Supported
6.2.2 TIMESTAMP — ISO 8601 with microseconds Supported 6-digit fractional seconds, UTC offset or Z
6.2.2 TIMESTAMP — NILVALUE when clock unavailable Supported NilClock produces -
6.2.3 HOSTNAME — max 255 chars, PRINTUSASCII Supported Truncated to 255. Non-PRINTUSASCII bytes substituted with ?. Written through the public SolidSyslogHeaderField sink (_PrintUsAscii); the underlying formatter is library-private
6.2.4 APP-NAME — max 48 chars, PRINTUSASCII Supported Truncated to 48. Non-PRINTUSASCII bytes substituted with ?
6.2.5 PROCID — max 128 chars, PRINTUSASCII Supported Truncated to 128. Non-PRINTUSASCII bytes substituted with ?
6.2.6 MSGID — max 32 chars, PRINTUSASCII Supported Truncated to 32. Non-PRINTUSASCII bytes substituted with ?
6.3 STRUCTURED-DATA — SD-ELEMENTs or NILVALUE Supported Extensible via SolidSyslogStructuredData vtable
6.3.3 SD-PARAM value escaping (], \, ") Supported SolidSyslogSdValue — every SD-PARAM value is written through this sink, which applies the escaping: RFC 3629 UTF-8 validated, ill-formed input substituted per-byte with U+FFFD (Unicode §3.9). OriginSd streams software, swVersion, enterpriseId, and each ip into it; MetaSd streams language via the integrator's SolidSyslogSdValueFunction callback. Both get the same escaping. SD-NAME / SD-ID syntax validation only matters once callers can supply names, via Custom Structured Data; the standard SDs (meta / timeQuality / origin) use compile-time-constant names
6.3.3 timeQuality SD — tzKnown, isSynced, syncAccuracy Supported SolidSyslogTimeQualitySd
6.3.4, 7.2 origin SD — software, swVersion, enterpriseId, ip Supported SolidSyslogOriginSd covers all four §7.2 parameters. software, swVersion, and enterpriseId are static strings supplied via SolidSyslogOriginSdConfig; the config strings are borrowed for the SD's lifetime and each is escaped per §6.3.3 by the SolidSyslogSdValue writer it is streamed into at Format time (no pre-formatted scratch storage). ip is repeatable per RFC 5424 §7.2 and sourced via two callbacks (SolidSyslogOriginIpCountFunction, SolidSyslogOriginIpAtFunction) so multi-homed hosts can reflect runtime address changes; the library asks for a count then loops 0..N-1, opening an ip param per token (with a leading space) while the integrator's at-callback writes one IP value per call into the SolidSyslogSdValue it is handed, which applies the escaping. All four parameters are independently optional — a NULL field or NULL callback omits the corresponding parameter from the SD-ELEMENT. The library frames and escapes; the IP value length is the integrator's to bound (ultimately by SOLIDSYSLOG_MAX_MESSAGE_SIZE), as is the IP count. Bare [origin] with no parameters is RFC-legal (§7.2 marks all params OPTIONAL, no SHOULD enforcement) and is what the library emits when the integrator wires nothing
6.3.5, 7.3 meta SD — sequenceId, sysUpTime, language Supported SolidSyslogMetaSd covers all three IANA-registered parameters. sequenceId (§7.3.1) sourced via an injected SolidSyslogAtomicCounter. sysUpTime (§7.3.2 / RFC 3418 TimeTicks) sourced via a SolidSyslogSysUpTimeFunction callback returning uint32_t hundredths; reference platform integrations are SolidSyslogPosixSysUpTime (clock_gettime(CLOCK_BOOTTIME)) and SolidSyslogWindowsSysUpTime (GetTickCount64), with the cast to uint32_t providing RFC 3418's natural wrap. language (§7.3.3 / BCP 47) sourced via a SolidSyslogSdValueFunction callback streaming into a SolidSyslogSdValue, which applies SD-PARAM-VALUE escaping per §6.3.3. All three independently optional — a NULL field in SolidSyslogMetaSdConfig omits that parameter from the SD-ELEMENT
6.3.5, 7.3.1 meta SD — sequenceId wraps at 2147483647 to 1 Supported SolidSyslogAtomicCounter wraps via CAS-loop in [1, 2³¹ - 1]; never returns 0; never above max. AtomicCounter is a vtable abstraction — concrete impls are SolidSyslogStdAtomicCounter (C11 <stdatomic.h> + atomic_compare_exchange_strong_explicit) on POSIX/clang/gcc/modern MSVC, and SolidSyslogWindowsAtomicCounter (volatile LONG + InterlockedCompareExchange) on legacy MSVC. The integrator picks one at setup time by calling the relevant platform's _Create; CMake's HAVE_STDATOMIC_H / HAVE_WINDOWS_INTERLOCKED checks gate which platform sources are compiled. sequenceId is assigned at the point of message raise (application-layer originator), preserving end-to-end loss-detection across the internal buffer / store-and-forward / transport pipeline. Trade-off: under concurrent raise from multiple threads, a small reorder window may occur in transmitted IDs (adjacent IDs may invert, since buffer/transport scheduling between raise and wire is not under library control). All IDs remain unique and non-zero — SIEMs performing gap detection identify message loss correctly; SIEMs requiring strict monotonic ordering should sort by timestamp
6.4 MSG — UTF-8 preferred Supported RFC 3629 UTF-8 validated at the formatter primitives (SolidSyslogFormatter_BoundedString), with ill-formed input substituted per-byte with U+FFFD (Unicode §3.9). MSG is prefixed with the §6.4 UTF-8 BOM (%xEF.BB.BF) unconditionally; if the caller's body already begins with a BOM it is stripped so the wire frame contains exactly one. Truncation preserves codepoint boundaries at both layers: the formatter clips at SOLIDSYSLOG_MAX_MESSAGE_SIZE without splitting a codepoint, and on UDP the sender walks back over any partial codepoint when the kernel reports EMSGSIZE for the path MTU. TCP/TLS streams fragment transparently at the transport layer and so do not need a path-MTU trim
8.1 Message size — max 2048 recommended Supported Default SOLIDSYSLOG_MAX_MESSAGE_SIZE = 2048, matching the §8.1 SHOULD value; override it for memory-constrained MCUs via the standard tunable mechanism
9 PRINTUSASCII in header fields (codes 33-126) Supported Non-compliant bytes substituted with ? at format time (HOSTNAME, APP-NAME, PROCID, MSGID)

RFC 5426 — Transmission of Syslog Messages over UDP

Section Requirement Status Notes
3.1 One message per UDP datagram Supported SolidSyslogUdpSender sends one datagram per Send call
3.2 Default port 514 Supported SOLIDSYSLOG_UDP_DEFAULT_PORT = 514
3.2 Message fits in single datagram Supported Bounded by SOLIDSYSLOG_MAX_MESSAGE_SIZE
3.2 Avoid IP fragmentation (respect MTU) Supported SolidSyslogUdpSender lazily connects on first send, enables Linux IP_MTU_DISCOVER / Windows equivalent with IP_PMTUDISC_DO so the kernel returns EMSGSIZE (Winsock WSAEMSGSIZE) for path-MTU oversize, queries the path MTU via getsockopt(IP_MTU), and resends a UTF-8-safe trimmed datagram via SolidSyslogUdpPayload_TrimToCodepointBoundary. Falls back to SOLIDSYSLOG_UDP_IPV6_SAFE_PAYLOAD = 1232 (RFC 8200 §5) when the MTU lookup fails
3.3 Unreliable delivery — no confirmation N/A Inherent in UDP. Caller should be aware
4 No authentication/integrity/confidentiality N/A Use TLS transport for security

RFC 6587 — Transmission of Syslog Messages over TCP

Section Requirement Status Notes
3.2 Sender initiates TCP connection Supported SolidSyslogStreamSender connects lazily on first send
3.2 Default port 601 Supported SOLIDSYSLOG_TCP_DEFAULT_PORT = 601 per IANA assignment (defined in Core/Interface/SolidSyslogTransport.h)
3.4.1 Octet counting framing Supported MSG-LEN SP MSG prefix on every send
3.4.2 Non-transparent framing (LF trailer) N/A RFC 6587 octet counting (§3.4.1) is the recommended method and is what the library ships; non-transparent framing is the legacy alternative
3.5 Session closure handling Supported On send failure the stream is closed; the next Send transparently reconnects
3.5 Handle receiver-initiated close Supported Detected via send failure path — same reconnect-on-next-Send mechanism
3.5 Address rotation without app restart Supported App bumps endpointVersion; sender Disconnects and reconnects on next Send
Partial write handling (send returns short) Supported A short return from send() is treated as failure: Send returns false, the caller closes and reconnects on the next attempt, store-and-forward replays the message on the fresh socket. The TCP socket is non-blocking from the moment it is created, so Send never blocks the service thread on a wedged peer or a full kernel send buffer — EAGAIN/EWOULDBLOCK (POSIX) and WSAEWOULDBLOCK (Winsock) propagate immediately as failure. On POSIX, EINTR is the only retried errno (portability shim for kernels without SA_RESTART); Winsock has no signal-interruption semantics on send(), so the EINTR retry path is omitted. Long-term wedge is detected out-of-band via kernel TCP keepalive (TCP_KEEPIDLE / TCP_KEEPINTVL / TCP_KEEPCNT) and TCP_USER_TIMEOUT for pending-write death; both are configured at socket open. Bounded connect is via non-blocking connect() + select(), with the timeout sourced from SOLIDSYSLOG_TCP_CONNECT_TIMEOUT_MS (default 200 ms) or runtime-overridable via the per-Stream GetConnectTimeoutMs(ConnectTimeoutContext) accessor — see Platform/Posix/Source/SolidSyslogPosixTcpStream.c and Platform/Windows/Source/SolidSyslogWinsockTcpStream.c.

RFC 5425 — TLS Transport Mapping for Syslog

The library ships two reference TLS adapters that satisfy this RFC: SolidSyslogTlsStream (OpenSSL, the POSIX / Windows reference) and SolidSyslogMbedTlsStream (Mbed TLS, the embedded / FreeRTOS reference). Both implement the same SolidSyslogStream vtable, so the section-by-section requirements below apply to whichever the integrator selects. mbedTLS-specific integration guidance lives in docs/integrating-mbedtls.md.

Section Requirement Status Notes
4.1 TLS over TCP Supported SolidSyslogTlsStream (OpenSSL) or SolidSyslogMbedTlsStream (Mbed TLS) wraps a TCP Stream (SolidSyslogPosixTcpStream / SolidSyslogWinsockTcpStream / SolidSyslogPlusTcpTcpStream / SolidSyslogLwipRawTcpStream / caller-supplied)
4.2 Default port 6514 Supported SOLIDSYSLOG_TLS_DEFAULT_PORT constant in SolidSyslogTransport.h, alongside the UDP and TCP defaults. Caller-supplied via the endpoint callback so multi-port deployments can override
5.1 Server certificate validation Supported OpenSSL adapter: SSL_VERIFY_PEER + SSL_CTX_load_verify_locations + SSL_set1_host. Mbed TLS adapter: MBEDTLS_SSL_VERIFY_REQUIRED + mbedtls_ssl_conf_ca_chain against the caller's mbedtls_x509_crt* + mbedtls_ssl_set_hostname
5.2 Mutual TLS (client certificate) Supported OpenSSL: optional clientCertChainPath / clientKeyPath on SolidSyslogTlsStreamConfig; SSL_CTX_check_private_key confirms pairing. Mbed TLS: optional ClientCertChain / ClientKey handles on SolidSyslogMbedTlsStreamConfig; mbedtls_ssl_conf_own_cert
5.3 TLS 1.2+ cipher suites Supported OpenSSL: SSL_CTX_set_min_proto_version(TLS1_2_VERSION) pinned; caller-supplied cipherList via SSL_CTX_set_cipher_list. Mbed TLS: inherited from mbedtls_ssl_config_defaults(... PRESET_DEFAULT); cipher policy owned by the integrator's mbedtls_config.h
5.4 Octet counting framing (mandatory for TLS) Supported Reuses SolidSyslogStreamSender (RFC 6587 framing is identical) for both adapters
5.5 TLS close_notify handling Supported OpenSSL: SSL_shutdown in TlsStream_Close. Mbed TLS: mbedtls_ssl_close_notify in MbedTlsStream_Close

Summary

RFC Total requirements Supported Partial Planned N/A
RFC 5424 17 17 0 0 0
RFC 5426 6 4 0 0 2
RFC 6587 8 7 0 0 1
RFC 5425 7 7 0 0 0