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 1/7] 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; } From cb43b3cbd6d14b21b9f9dfb5d3b50438622b7aaf 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 2/7] syslog: make the destination port configurable The port was frozen at 514 in the call that opens the connection, so a collector listening anywhere else was simply out of reach, and plenty do, because 514 is privileged and containerised collectors usually get a high port instead. Working around it meant putting a proxy in front, which then rewrites the source address and hides which device actually sent the line. Add `syslog port `. The default stays 514, so nothing changes for an existing configuration. Setting it tears the connection down and builds a new one, the same dance the address already does, because uip_udp_new() freezes the port into the connection. The value is parsed here rather than through atoi_short(), which reports "no digits" but not overflow: 65540 would quietly wrap to 4 and we would open a connection to a port nobody asked for. Checking before each multiply keeps it in 16-bit arithmetic. Zero then covers all three ways to be wrong - no digits, past 65535, or an explicit "0", which is not a port either. Whitelist the new command in config.js as well, next to `syslog ip`, or the line is dropped without a word when the configuration is saved and the setting quietly fails to survive a reboot. The dedup entry has to precede the general `^syslog\b` one, otherwise it would deduplicate against `syslog on`. itoa_short() is new: itoa() only handles a byte and print_short() prints hex, so there was no way to show a port as a decimal number. Kept separate from itoa() rather than widening it, because every existing caller passes a byte and would start paying for 16-bit divisions it does not need. The scratch variables for the parser live in xdata. Locals there would take internal RAM, and this image has none left: data ends at 0x77, the overlay occupies 0x78-0x7f and the stack starts at 0x80. Measured: no module's DSEG grew. --- cmd_parser.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++-- html/config.js | 2 ++ rtl837x_common.h | 1 + rtlplayground.c | 26 +++++++++++++++++++ syslog.c | 6 +++-- syslog.h | 3 +++ 6 files changed, 101 insertions(+), 4 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 66b05bde..0c3cbff4 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -65,6 +65,13 @@ __xdata char save_cmd; __xdata uint8_t ip[4]; +/* Scratch for parse_syslog()'s port parser, in xdata: locals here would take + * internal RAM the linker has none of. */ +__xdata uint16_t syslog_port_scratch; +__xdata uint8_t syslog_port_idx; +__xdata uint8_t syslog_port_digit; +__xdata uint8_t syslog_port_was_on; + // These variables combined create a Fixed-capacity vector/bounded buffer. // `N_WORDS`: The total number of command arguments that can be tracked. // `cmd_words_len` stores the number of arguments found inside `cmd_buffer` @@ -1411,6 +1418,7 @@ void parse_syslog(void) if (syslog_state.enabled) { print_string("enabled, sending to "); print_ip(syslog_state.server_ip); + write_char(':'); itoa_short(syslog_state.server_port); write_char('\n'); } else { print_string("disabled\n"); @@ -1439,11 +1447,66 @@ void parse_syslog(void) } else { print_string("Invalid IP address\n"); } + } else if (cmd_compare(1, "port")) { + if (cmd_words_len < 3) { // no additional argument -> print current port + print_string("Current syslog port: "); + itoa_short(syslog_state.server_port); write_char('\n'); + return; + } + /* Parsed here rather than with atoi_short(), which reports "no + * digits" but not overflow - 65540 would quietly wrap to 4 and we + * would open a connection to a port nobody asked for. Checking + * before each multiply keeps this in 16-bit arithmetic. */ + syslog_port_scratch = 0; + syslog_port_idx = cmd_words_b[2]; + for (;;) { + /* Plain comparisons instead of isnumber() in the loop + * condition, and nested ifs instead of || and &&: either form + * makes SDCC park a boolean in the bit area, and an image + * carrying LACP and STP as well is one bit short of needing a + * third byte of it - which would push everything up and stop + * the link. */ + syslog_port_digit = cmd_buffer[syslog_port_idx]; + if (syslog_port_digit < '0') + break; + if (syslog_port_digit > '9') + break; + syslog_port_digit -= '0'; + if (syslog_port_scratch > 6553) { + syslog_port_scratch = 0; /* too large - reject below */ + break; + } + if (syslog_port_scratch == 6553) { + if (syslog_port_digit > 5) { + syslog_port_scratch = 0; + break; + } + } + syslog_port_scratch = syslog_port_scratch * 10 + syslog_port_digit; + syslog_port_idx++; + } + /* Zero covers all three ways to be wrong: no digits at all, a value + * past 65535, and an explicit "0", which is not a port either. */ + if (!syslog_port_scratch) { + print_string("Invalid port\n"); + return; + } + /* The port is frozen into the connection by uip_udp_new(), so + * changing it has to tear the connection down and build a new one - + * same dance as setting the address above. */ + syslog_port_was_on = syslog_state.enabled; + if (syslog_port_was_on) + syslog_stop(); + print_string("Setting new syslog port.\n"); + syslog_state.server_port = syslog_port_scratch; + if (syslog_port_was_on) + syslog_start(); } else { - print_string("Error: syslog [on|off|ip [ip-address]]\n"); - print_string(" on/off enables or disables syslog, ip sets the syslog server IP address\n"); + print_string("Error: syslog [on|off|ip [ip-address]|port [number]]\n"); + print_string(" on/off enables or disables syslog, ip sets the syslog server IP address,\n"); + print_string(" port sets the destination UDP port (default 514)\n"); } } diff --git a/html/config.js b/html/config.js index 8af3fbaa..7edeafd7 100644 --- a/html/config.js +++ b/html/config.js @@ -7,6 +7,7 @@ const conf_cmds = [ /^netmask\s+(\d{1,3}\.){3}\d{1,3}$/, /^syslog\s+(on|off)$/, /^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/, + /^syslog\s+port\s+\d{1,5}$/, /^passwd\s+\S+$/, /^vlan\s+\d{1,4}\s+d$/, /^vlan\s+\d{1,4}\s+mgmt$/, @@ -32,6 +33,7 @@ const conf_overwrite = [ /^gw\b/, /^netmask\b/, /^syslog\s+ip\b/, + /^syslog\s+port\b/, /^syslog\b/, /^passwd\b/, /^vlan\s+\d{1,4}\s+mgmt$/, diff --git a/rtl837x_common.h b/rtl837x_common.h index c3d83cb2..5547ca7e 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -133,6 +133,7 @@ void print_long(uint32_t a); void print_short(uint16_t a); void print_byte(uint8_t a); void itoa(uint8_t v); +void itoa_short(uint16_t v); void print_sfr_data(void); void print_phy_data(void); void print_cmd_prompt(void); diff --git a/rtlplayground.c b/rtlplayground.c index cd5e14eb..31695504 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -278,6 +278,32 @@ void itoa(uint8_t v) } +/* Same as itoa(), one decade wider: enough for a port number. Kept separate + * rather than widening itoa() itself, because every existing caller passes a + * byte and would start paying for 16-bit divisions it does not need. */ +void itoa_short(uint16_t v) +{ + uint8_t t = v / 10000; + uint8_t print_zeros = t; + + if (print_zeros) + write_char('0' + t); + t = (v / 1000) % 10; + print_zeros |= t; + if (print_zeros) + write_char('0' + t); + t = (v / 100) % 10; + print_zeros |= t; + if (print_zeros) + write_char('0' + t); + t = (v / 10) % 10; + print_zeros |= t; + if (print_zeros) + write_char('0' + t); + write_char('0' + (v % 10)); +} + + void print_string(__code char *p) { while (*p) diff --git a/syslog.c b/syslog.c index 81d722b2..7b3edca7 100644 --- a/syslog.c +++ b/syslog.c @@ -27,20 +27,22 @@ void syslog_init(void) __banked state.readptr = 0; state.line_available = 0; state.server_ip[0] = 0; state.server_ip[1] = 0; state.server_ip[2] = 0; state.server_ip[3] = 0;// Default to 0.0.0.0 + state.server_port = SYSLOG_PORT_DEFAULT; } void syslog_start(void) __banked { if (state.syslog_conn == 0) { uip_ipaddr(server_ip, state.server_ip[0], state.server_ip[1], state.server_ip[2], state.server_ip[3]); - state.syslog_conn = uip_udp_new(&server_ip, HTONS(514)); + state.syslog_conn = uip_udp_new(&server_ip, HTONS(state.server_port)); if (state.syslog_conn == 0) { print_string_newline_no_syslog("Failed to create a new UDP client"); return; } print_string_newline_no_syslog("Started syslog to IP "); itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.'); - itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); write_char('\n'); + itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); + write_char(':'); itoa_short(state.server_port); write_char('\n'); state.enabled = 1; } else { diff --git a/syslog.h b/syslog.h index f3666da8..47bf968f 100644 --- a/syslog.h +++ b/syslog.h @@ -5,12 +5,15 @@ #define LOGBUF_SIZE 512 +#define SYSLOG_PORT_DEFAULT 514 + struct syslog_state { uint8_t enabled; uint8_t line_available; uint16_t writeptr ; uint16_t readptr; uint8_t server_ip[4]; + uint16_t server_port; struct uip_udp_conn *syslog_conn; }; From ccafa01c7414f286c7b174d04fad144f837e9da6 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 3/7] system: stop "syslog on" from wiping the server address Saving the configuration drops the syslog server address whenever the log of executed commands also contains "syslog on", which it almost always does, since you have to enable the thing after pointing it somewhere. parseConf() deduplicates by taking the matched text of a conf_overwrite entry and removing every stored line that starts with it. For "syslog on" the entry that matches is the catch-all ^syslog\b, so the matched text is just "syslog" and the filter removes anything beginning with "syslog ", including the "syslog ip ..." line saved a moment earlier. The address then falls back to 0.0.0.0 on the next boot. It fails quietly: nothing is reported, the running switch keeps logging until it is restarted, and the loss looks like the firmware forgetting a setting rather than the page dropping it. Narrow the entry to the commands it is meant to collapse, so the address and the port keep their own entries and are no longer collateral. That alone would stop "syslog on" and "syslog off" from replacing each other, because the list drops lines starting with the text it matched and "syslog off" does not start with "syslog on". A separate list names the stem of such a pair and collapses the two, which is what the catch-all used to do by accident. --- html/config.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/html/config.js b/html/config.js index 7edeafd7..ecf660fb 100644 --- a/html/config.js +++ b/html/config.js @@ -28,13 +28,21 @@ const conf_cmds = [ /^bw\s+(in|out)\s+\d{1,2}\s+\S+$/, /^hostname\s+.{1,23}$/, ]; +/* Commands that come in an on/off pair replace each other, which the list + * below cannot express: it drops lines starting with the text it matched, and + * "syslog off" does not start with "syslog on". Naming the stem separately + * keeps the pair collapsed without widening the match to the whole family. */ +const conf_toggle = [ + /^(syslog)\s+(?:on|off)$/, +]; + const conf_overwrite = [ /^ip\b/, /^gw\b/, /^netmask\b/, /^syslog\s+ip\b/, /^syslog\s+port\b/, - /^syslog\b/, + /^syslog\s+(on|off)$/, /^passwd\b/, /^vlan\s+\d{1,4}\s+mgmt$/, /^vlan\s+\d{1,4}(?!\s+mgmt\b)/, @@ -71,6 +79,13 @@ function parseConf(s){ for (const x of conf_cmds) if (x.test(line)) { ignore = false; break; } if (ignore) continue; + for (const x of conf_toggle) { + const t = line.match(x); + if (t) { + configuration = configuration.filter(item => item !== t[1] + " on" && item !== t[1] + " off"); + break; + } + } for (const x of conf_overwrite) { if (x.test(line)) { let m = line.match(x); From 4db1ccbbd92836e9078c0ee42780a415fba69111 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:51:34 +0200 Subject: [PATCH 4/7] syslog: fold the port parser's split conditions back together The loop tested the digit range and the overflow bound with separate ifs, on the strength of a comment saying the joined form makes sdcc park a boolean in the bit area, and that an image carrying LACP and STP as well is one bit short of needing a third byte of it. Measured on this branch that is not what happens: the joined form links, the bit segment is unchanged at fourteen bits overall and nine in cmd_parser, and BANK2 comes out ten bytes smaller. The claim was about an image this branch does not build, and no branch currently carries LACP, STP and this parser at once, so there is nothing left to check it against. A justification nobody can verify, for a shape nobody would otherwise write, is worse than no comment at all. Behaviour is unchanged. The two forms agree on every input from 0 to 99999 and on the edges: empty, non digits, trailing junk, leading zeros, 65535 and 65536. The note about atoi_short() stays, because that one still reports "no digits" without reporting overflow. #326 replaces it with a version that does both, and this should move onto it once that lands. --- cmd_parser.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 0c3cbff4..40c74820 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -1460,28 +1460,15 @@ void parse_syslog(void) syslog_port_scratch = 0; syslog_port_idx = cmd_words_b[2]; for (;;) { - /* Plain comparisons instead of isnumber() in the loop - * condition, and nested ifs instead of || and &&: either form - * makes SDCC park a boolean in the bit area, and an image - * carrying LACP and STP as well is one bit short of needing a - * third byte of it - which would push everything up and stop - * the link. */ syslog_port_digit = cmd_buffer[syslog_port_idx]; - if (syslog_port_digit < '0') - break; - if (syslog_port_digit > '9') + if (syslog_port_digit < '0' || syslog_port_digit > '9') break; syslog_port_digit -= '0'; - if (syslog_port_scratch > 6553) { + if (syslog_port_scratch > 6553 + || (syslog_port_scratch == 6553 && syslog_port_digit > 5)) { syslog_port_scratch = 0; /* too large - reject below */ break; } - if (syslog_port_scratch == 6553) { - if (syslog_port_digit > 5) { - syslog_port_scratch = 0; - break; - } - } syslog_port_scratch = syslog_port_scratch * 10 + syslog_port_digit; syslog_port_idx++; } From e50d3c6950fca6f3cd7375cf09849b4e29cc932f Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Sun, 30 Aug 2026 22:17:52 +0200 Subject: [PATCH 5/7] syslog: parse the port with atoi_short() The hand rolled loop was here because atoi_short() reported "no digits" but not overflow, so 65540 would have wrapped to 4 and opened a connection to a port nobody asked for. #326 gave it the same bound this loop was carrying, so the reason is gone. Zero still covers all three ways to be wrong, except that "no digits" and overflow now come back as a zero return and port zero as a zero value, so both are tested. Three xdata scratch variables go with the loop. --- cmd_parser.c | 34 ++++++---------------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/cmd_parser.c b/cmd_parser.c index 40c74820..a92a2a0a 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -65,11 +65,8 @@ __xdata char save_cmd; __xdata uint8_t ip[4]; -/* Scratch for parse_syslog()'s port parser, in xdata: locals here would take - * internal RAM the linker has none of. */ -__xdata uint16_t syslog_port_scratch; -__xdata uint8_t syslog_port_idx; -__xdata uint8_t syslog_port_digit; +/* Scratch for parse_syslog(), in xdata: a local here would take internal RAM + * the linker has none of. */ __xdata uint8_t syslog_port_was_on; // These variables combined create a Fixed-capacity vector/bounded buffer. @@ -1453,28 +1450,9 @@ void parse_syslog(void) itoa_short(syslog_state.server_port); write_char('\n'); return; } - /* Parsed here rather than with atoi_short(), which reports "no - * digits" but not overflow - 65540 would quietly wrap to 4 and we - * would open a connection to a port nobody asked for. Checking - * before each multiply keeps this in 16-bit arithmetic. */ - syslog_port_scratch = 0; - syslog_port_idx = cmd_words_b[2]; - for (;;) { - syslog_port_digit = cmd_buffer[syslog_port_idx]; - if (syslog_port_digit < '0' || syslog_port_digit > '9') - break; - syslog_port_digit -= '0'; - if (syslog_port_scratch > 6553 - || (syslog_port_scratch == 6553 && syslog_port_digit > 5)) { - syslog_port_scratch = 0; /* too large - reject below */ - break; - } - syslog_port_scratch = syslog_port_scratch * 10 + syslog_port_digit; - syslog_port_idx++; - } - /* Zero covers all three ways to be wrong: no digits at all, a value - * past 65535, and an explicit "0", which is not a port either. */ - if (!syslog_port_scratch) { + /* atoi_short() returns zero for no digits and for a value past + * 65535; port zero is not a port either, so both tests are needed. */ + if (!atoi_short(cmd_words_b[2]) || !atoi_results_short) { print_string("Invalid port\n"); return; } @@ -1485,7 +1463,7 @@ void parse_syslog(void) if (syslog_port_was_on) syslog_stop(); print_string("Setting new syslog port.\n"); - syslog_state.server_port = syslog_port_scratch; + syslog_state.server_port = atoi_results_short; if (syslog_port_was_on) syslog_start(); } From 40ce742d048215ba4d0240885fb5adb11ee855de Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Tue, 1 Sep 2026 23:08:42 +0200 Subject: [PATCH 6/7] syslog: take the review notes on the state flag and the header length The enabled flag is a flag, so say bool. The header length no longer needs to live in xdata: it was put there when a local would not link, and there is room for it here. The overview names the row after the JSON key, so the syslog row said "syslog_server_ip" while carrying only an address. It now says "syslog_server" and carries the port with it. --- httpd/page_impl.c | 5 +++-- syslog.c | 6 +----- syslog.h | 3 ++- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/httpd/page_impl.c b/httpd/page_impl.c index 2f945689..e7edb0be 100644 --- a/httpd/page_impl.c +++ b/httpd/page_impl.c @@ -221,11 +221,12 @@ void send_basic_info(void) itoa_html(uip_netmask[0] >> 8); char_to_html('.'); itoa_html(uip_netmask[1]); char_to_html('.'); itoa_html(uip_netmask[1] >> 8); - slen += strtox(outbuf + slen, "\",\"syslog_server_ip\":\""); + slen += strtox(outbuf + slen, "\",\"syslog_server\":\""); itoa_html(syslog_state.server_ip[0]); char_to_html('.'); itoa_html(syslog_state.server_ip[1]); char_to_html('.'); itoa_html(syslog_state.server_ip[2]); char_to_html('.'); - itoa_html(syslog_state.server_ip[3]); + itoa_html(syslog_state.server_ip[3]); char_to_html(':'); + itoa_html(syslog_state.server_port); slen += strtox(outbuf + slen, "\",\"mac_address\":\""); byte_to_html(uip_ethaddr.addr[0]); char_to_html(':'); byte_to_html(uip_ethaddr.addr[1]); char_to_html(':'); diff --git a/syslog.c b/syslog.c index 7b3edca7..c552ac58 100644 --- a/syslog.c +++ b/syslog.c @@ -12,11 +12,6 @@ __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 @@ -64,6 +59,7 @@ void syslog_stop(void) __banked void syslog_callback(uint16_t lport) __banked { + uint16_t syslog_hdr; if (lport != state.syslog_conn->lport) return; diff --git a/syslog.h b/syslog.h index 47bf968f..ad9c3fe1 100644 --- a/syslog.h +++ b/syslog.h @@ -1,6 +1,7 @@ #ifndef _SYSLOG_H_ #define _SYSLOG_H_ +#include #include #define LOGBUF_SIZE 512 @@ -8,7 +9,7 @@ #define SYSLOG_PORT_DEFAULT 514 struct syslog_state { - uint8_t enabled; + bool enabled; uint8_t line_available; uint16_t writeptr ; uint16_t readptr; From 2e2529be27ab61dc0a2a999b920f477179844312 Mon Sep 17 00:00:00 2001 From: d00f <8052722+DrDoof@users.noreply.github.com> Date: Thu, 3 Sep 2026 21:27:02 +0200 Subject: [PATCH 7/7] syslog: print the server address with print_ip() The status line built the dotted quad by hand, which is what print_ip() from cmd_parser.c already does. Reusing it drops seven calls to one and takes 48 bytes off BANK2. The prototype is not __banked because cmd_parser.c and syslog.c are both in BANK2; a plain call is what the compiler needs here. Should either file move to another bank, this has to become __banked with it. --- cmd_parser.h | 1 + syslog.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmd_parser.h b/cmd_parser.h index a8bf7975..0afd0327 100644 --- a/cmd_parser.h +++ b/cmd_parser.h @@ -13,6 +13,7 @@ void cmd_tokenize(void) __banked; void cmd_parser(void) __banked; void execute_config(void) __banked; void execute_commands(__xdata uint8_t *p) __banked; +void print_ip(__xdata uint8_t *ptr); void print_sw_version(void) __banked; void clear_command_history(void) __banked; diff --git a/syslog.c b/syslog.c index c552ac58..de11af53 100644 --- a/syslog.c +++ b/syslog.c @@ -1,5 +1,6 @@ #include "machine.h" #include "syslog.h" +#include "cmd_parser.h" #include "uip/uip.h" #include "rtl837x_common.h" @@ -35,8 +36,7 @@ void syslog_start(void) __banked return; } print_string_newline_no_syslog("Started syslog to IP "); - itoa(state.server_ip[0]); write_char('.'); itoa(state.server_ip[1]); write_char('.'); - itoa(state.server_ip[2]); write_char('.'); itoa(state.server_ip[3]); + print_ip(state.server_ip); write_char(':'); itoa_short(state.server_port); write_char('\n'); state.enabled = 1; }