From 9d4e5313060dc61c21237485549282a001926244 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Fri, 14 Aug 2026 02:24:27 +0200 Subject: [PATCH] syslog: put our hostname where the receiver expects it RFC 3164 has a hostname between the priority and the message text, and we were sending nothing there. A receiver still has to fill that field, so it takes the first word of the text instead, so every line arrives attributed to "STP:", or "REGGET:", or whatever the log happens to start with. The sender is then impossible to select on: the name changes with the content, and anything in front of us on the path replaces the source address with its own. Observed on a collector behind a UDP proxy: the same switch showed up as two different hosts depending on which subsystem had logged last. Send the configured hostname. Skipped when it is empty, so we never emit a lone separator. The header length lives in xdata rather than on the stack. syslog_callback() is __banked, so a local there cannot be overlaid, and while the variable itself is only two bytes it costs more than that: it takes a register, which pushes log_start out of one and into internal RAM. Those two bytes are enough to stop an image carrying LACP and STP from linking at all. --- syslog.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/syslog.c b/syslog.c index 021ef720..81d722b2 100644 --- a/syslog.c +++ b/syslog.c @@ -12,6 +12,11 @@ __xdata char logbuf[LOGBUF_SIZE]; __xdata struct syslog_state syslog_state; __xdata uip_ipaddr_t server_ip; +/* Header length, in xdata rather than on the stack: syslog_callback() is + * __banked, so a local here takes a byte of internal RAM nobody can overlay, + * and the two it costs are enough to stop the image from linking. */ +__xdata uint16_t syslog_hdr; + #define state syslog_state void syslog_init(void) __banked @@ -91,14 +96,31 @@ void syslog_callback(uint16_t lport) __banked memcpyc(SYSLOG_P, "<14>", 4); // Syslog priority prefix - if (log_end < log_start) { - memcpy(SYSLOG_P + 4, logbuf + log_start, LOGBUF_SIZE - log_start); - memcpy(SYSLOG_P + 4 + LOGBUF_SIZE - log_start, logbuf, log_end); + /* RFC 3164 puts a hostname between the priority and the text, and + * we were leaving that slot empty. A receiver still has to fill + * the field, so it takes the first word of the message instead: + * every line arrives attributed to "STP:" or "REGGET:" or + * whatever the log happens to start with, and the sender cannot + * be selected on at all. Send our own name and the field means + * something. Skipped when the name is empty, so we never emit a + * lone separator. */ + syslog_hdr = strlen_x(hostname); + if (syslog_hdr) { + memcpy(SYSLOG_P + 4, hostname, syslog_hdr); + SYSLOG_P[4 + syslog_hdr] = ' '; + syslog_hdr += 5; } else { - memcpy(SYSLOG_P + 4, logbuf + log_start, log_end - log_start); + syslog_hdr = 4; } - uip_udp_send(log_size+4); + if (log_end < log_start) { + memcpy(SYSLOG_P + syslog_hdr, logbuf + log_start, LOGBUF_SIZE - log_start); + memcpy(SYSLOG_P + syslog_hdr + LOGBUF_SIZE - log_start, logbuf, log_end); + } else { + memcpy(SYSLOG_P + syslog_hdr, logbuf + log_start, log_end - log_start); + } + + uip_udp_send(log_size + syslog_hdr); state.readptr = state.writeptr; state.line_available = 0; }