mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
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 <n>`. 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.
This commit is contained in:
1 parent
9d4e531306
commit
cb43b3cbd6
6 files changed
+101
-4
No files matched your search
+65
-2
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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$/,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in new issue
Block a user