diff --git a/patches/sysklogd/2.5.2/0001-Fix-72-loss-of-raw-kernel-log-messages-to-console.patch b/patches/sysklogd/2.5.2/0001-Fix-72-loss-of-raw-kernel-log-messages-to-console.patch index e9e78353..d6033dd4 100644 --- a/patches/sysklogd/2.5.2/0001-Fix-72-loss-of-raw-kernel-log-messages-to-console.patch +++ b/patches/sysklogd/2.5.2/0001-Fix-72-loss-of-raw-kernel-log-messages-to-console.patch @@ -1,7 +1,7 @@ -From 1727f7a5ea142ab923ca07f23b2457cf8db94d1d Mon Sep 17 00:00:00 2001 +From ad9a464806fe27fe65d403f56f1dc701f7d0a10a Mon Sep 17 00:00:00 2001 From: Joachim Wiberg Date: Wed, 24 Apr 2024 13:19:09 +0200 -Subject: [PATCH 1/1] Fix #72: loss of raw kernel log messages to console +Subject: [PATCH 01/15] Fix #72: loss of raw kernel log messages to console Organization: Addiva Elektronik This patch adds a command line flag `-l` to keep kernel logs to console. @@ -56,7 +56,7 @@ index dcfb564..70f1b8b 100644 Select the number of minutes between .Dq mark diff --git a/src/syslogd.c b/src/syslogd.c -index e7b05b0..68040fe 100644 +index c02d064..c9ea7fd 100644 --- a/src/syslogd.c +++ b/src/syslogd.c @@ -154,6 +154,7 @@ static int RemoteHostname; /* Log remote hostname from the message */ @@ -113,5 +113,5 @@ index 68ceafb..1703df2 100644 #define kern_console_off() do { } while (0) #define kern_console_on() do { } while (0) -- -2.34.1 +2.43.0 diff --git a/patches/sysklogd/2.5.2/0002-Fix-80-add-global-log-rotation-options-to-.conf-file.patch b/patches/sysklogd/2.5.2/0002-Fix-80-add-global-log-rotation-options-to-.conf-file.patch new file mode 100644 index 00000000..76e8fe73 --- /dev/null +++ b/patches/sysklogd/2.5.2/0002-Fix-80-add-global-log-rotation-options-to-.conf-file.patch @@ -0,0 +1,177 @@ +From 7e0882688b0ea459c850e6e0ace66cca7100fd0a Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Fri, 12 Jul 2024 22:54:51 +0200 +Subject: [PATCH 02/15] Fix #80: add global log rotation options to .conf file +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + man/syslog.conf.5 | 20 ++++++++++++++++---- + src/syslogd.c | 36 ++++++++++++++++++++++++++++++++++-- + syslog.conf | 14 +++++++++++--- + 3 files changed, 61 insertions(+), 9 deletions(-) + +diff --git a/man/syslog.conf.5 b/man/syslog.conf.5 +index 73c11e1..030c377 100644 +--- a/man/syslog.conf.5 ++++ b/man/syslog.conf.5 +@@ -71,6 +71,9 @@ OPTION := [OPTION,] + + secure_mode [0,1,2] + ++rotate_size SIZE ++rotate_count NUMBER ++ + include /etc/syslog.d/*.conf + notify /path/to/script-on-rotate + .Ed +@@ -107,6 +110,15 @@ a file can reach before it is rotated, and later compressed. This + feature is mostly intended for embedded systems that do not want to have + cron or a separate log rotate daemon. + .Pp ++The ++.Ql rotate_size SIZE ++and ++.Ql rotate_count COUNT ++are the same as the ++.Nm syslogd Fl r Ar SIZE:COUNT ++command line option. Remember, command line options take precedence ++over .conf file settings. ++.Pp + .Sy Note: + the permissions of the rotated files are kept. Meaning the + administrator can create all log files, before starting +@@ -120,13 +132,13 @@ permissions. + Comments, lines starting with a hash mark ('#'), and empty lines are + ignored. If an error occurs during parsing the whole line is ignored. + .Pp +-Additional options include ++The + .Ql secure_mode <0-2> +-which is the same as the ++option is the same as the + .Nm syslogd Fl s +-commandline option. ++command line option. + .Sy Note: +-command line option always wins, so you need to drop ++again, command line option always wins, so you need to drop + .Fl s + from the command line to use this .conf file option instead. + .Pp +diff --git a/src/syslogd.c b/src/syslogd.c +index c9ea7fd..5061376 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -156,6 +156,7 @@ static int KeepKernFac; /* Keep remotely logged kernel facility */ + static int KeepKernTime; /* Keep kernel timestamp, evern after initial read */ + static int KeepKernConsole; /* Keep kernel logging to console */ + ++static int rotate_opt; /* Set if command line option has been given (wins) */ + static off_t RotateSz = 0; /* Max file size (bytes) before rotating, disabled by default */ + static int RotateCnt = 5; /* Max number (count) of log files to keep, set with -c */ + +@@ -180,13 +181,17 @@ static SIMPLEQ_HEAD(, allowedpeer) aphead = SIMPLEQ_HEAD_INITIALIZER(aphead); + * parser moves the argument to the beginning of the parsed line. + */ + char *secure_str; /* string value of secure_mode */ ++char *rotate_sz_str; /* string value of RotateSz */ ++char *rotate_cnt_str; /* string value of RotateCnt */ + + const struct cfkey { + const char *key; + char **var; + } cfkey[] = { +- { "notify", NULL }, +- { "secure_mode", &secure_str }, ++ { "notify", NULL }, ++ { "secure_mode", &secure_str }, ++ { "rotate_size", &rotate_sz_str }, ++ { "rotate_count", &rotate_cnt_str }, + }; + + /* Function prototypes. */ +@@ -499,6 +504,7 @@ int main(int argc, char *argv[]) + + case 'r': + parse_rotation(optarg, &RotateSz, &RotateCnt); ++ rotate_opt++; + break; + + case 's': +@@ -3296,6 +3302,32 @@ static int cfparse(FILE *fp, struct files *newf, struct notifiers *newn) + secure_str = NULL; + } + ++ if (rotate_sz_str) { ++ if (rotate_opt) { ++ logit("Skipping 'rotate_size', already set on command line."); ++ } else { ++ int val = strtobytes(rotate_sz_str); ++ if (val > 0) ++ RotateSz = val; ++ } ++ ++ free(rotate_sz_str); ++ rotate_sz_str = NULL; ++ } ++ ++ if (rotate_cnt_str) { ++ if (rotate_opt) { ++ logit("Skipping 'rotate_count', already set on command line."); ++ } else { ++ int val = atoi(rotate_cnt_str); ++ if (val > 0) ++ RotateCnt = val; ++ } ++ ++ free(rotate_cnt_str); ++ rotate_cnt_str = NULL; ++ } ++ + return 0; + } + +diff --git a/syslog.conf b/syslog.conf +index c4c7525..52161a1 100644 +--- a/syslog.conf ++++ b/syslog.conf +@@ -42,9 +42,11 @@ mail.err /var/log/mail.err + cron,daemon.none;\ + mail,news.none -/var/log/messages + +-# Store all critical eventes, except kernel logs in critical + # +-#*.=crit;kern.none /var/log/critical ++# Store all critical events, except kernel logs, in critical RFC5424 format. ++# Overide global log rotation settings, rotate every 10MiB, keep 5 old logs, ++# ++#*.=crit;kern.none /var/log/critical ;rotate=10M:5,RFC5424 + + # Example of sending events to remote syslog server. + # All events from notice and above, except auth, authpriv +@@ -60,7 +62,7 @@ mail.err /var/log/mail.err + + # Priority alert and above are sent to the operator + # +-#*.alert root,joey ++#*.alert root,joey + + # + # Secure mode, same as -s, none(0), on(1), full(2). When enabled +@@ -70,6 +72,12 @@ mail.err /var/log/mail.err + # + secure_mode 1 + ++# ++# Global log rotation, same as -r SIZE:COUNT, command line wins. ++# ++#rotate_size 1M ++#rotate_count 5 ++ + # + # Include all config files in /etc/syslog.d/ + # +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0003-Refactor-rely-on-global-file-rotation-if-not-set-per.patch b/patches/sysklogd/2.5.2/0003-Refactor-rely-on-global-file-rotation-if-not-set-per.patch new file mode 100644 index 00000000..6bd0a0e5 --- /dev/null +++ b/patches/sysklogd/2.5.2/0003-Refactor-rely-on-global-file-rotation-if-not-set-per.patch @@ -0,0 +1,102 @@ +From a2c47f81bf3d358dddb475cbaa8125f2cb776587 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 14 Jul 2024 09:19:01 +0200 +Subject: [PATCH 03/15] Refactor, rely on global file rotation if not set + per-file +Organization: Addiva Elektronik + +Instead of initializing per-file rotation with global values, leave them +unset to allow global settings to be changed from config file. + +This changes the semantics so that it is no longer possible to disable +log rotation on a per-file basis. + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 37 +++++++++++++++++++++++++------------ + 1 file changed, 25 insertions(+), 12 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 5061376..fa8964b 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -1732,21 +1732,34 @@ static void logmsg(struct buf_msg *buffer) + static void logrotate(struct filed *f) + { + struct stat statf; ++ off_t sz; + +- if (!f->f_rotatesz) ++ if (!f->f_rotatesz && !RotateSz) + return; + ++ if (f->f_rotatesz) ++ sz = f->f_rotatesz; ++ else ++ sz = RotateSz; ++ + if (fstat(f->f_file, &statf)) + return; + + /* bug (mostly harmless): can wrap around if file > 4gb */ +- if (S_ISREG(statf.st_mode) && statf.st_size > f->f_rotatesz) ++ if (S_ISREG(statf.st_mode) && statf.st_size > sz) + rotate_file(f, &statf); + } + + static void rotate_file(struct filed *f, struct stat *stp_or_null) + { +- if (f->f_rotatecount > 0) { /* always 0..999 */ ++ int cnt; ++ ++ if (f->f_rotatecount) ++ cnt = f->f_rotatecount; ++ else ++ cnt = RotateCnt; ++ ++ if (cnt > 0) { /* always 0..999 */ + struct stat st_stack; + int len = strlen(f->f_un.f_fname) + 10 + 5; + int i; +@@ -1754,7 +1767,7 @@ static void rotate_file(struct filed *f, struct stat *stp_or_null) + char newFile[len]; + + /* First age zipped log files */ +- for (i = f->f_rotatecount; i > 1; i--) { ++ for (i = cnt; i > 1; i--) { + snprintf(oldFile, len, "%s.%d.gz", f->f_un.f_fname, i - 1); + snprintf(newFile, len, "%s.%d.gz", f->f_un.f_fname, i); + +@@ -1808,7 +1821,14 @@ static void rotate_all_files(void) + struct filed *f; + + SIMPLEQ_FOREACH(f, &fhead, f_link) { +- if (f->f_type == F_FILE && f->f_rotatesz) ++ off_t sz; ++ ++ if (f->f_rotatesz) ++ sz = f->f_rotatesz; ++ else ++ sz = RotateSz; ++ ++ if (f->f_type == F_FILE && sz) + rotate_file(f, NULL); + } + } +@@ -3140,13 +3160,6 @@ static struct filed *cfline(char *line) + break; + + case F_FILE: +- /* default rotate from command line */ +- if (f->f_rotatesz == 0) { +- f->f_rotatecount = RotateCnt; +- f->f_rotatesz = RotateSz; +- } +- /* fallthrough */ +- + default: + /* All other targets default to RFC3164 */ + if (f->f_flags & (RFC3164 | RFC5424)) +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0004-Allow-per-file-rotation-settings-to-set-only-one-val.patch b/patches/sysklogd/2.5.2/0004-Allow-per-file-rotation-settings-to-set-only-one-val.patch new file mode 100644 index 00000000..c382c842 --- /dev/null +++ b/patches/sysklogd/2.5.2/0004-Allow-per-file-rotation-settings-to-set-only-one-val.patch @@ -0,0 +1,67 @@ +From 0366909927cebecdf6c35b83a976a25c529043e1 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 14 Jul 2024 09:26:50 +0200 +Subject: [PATCH 04/15] Allow per-file rotation settings to set only one value +Organization: Addiva Elektronik + +This change makes it possible to set rotate=2M, or rotate=:5, and then +rely on the global settings for the other. + +Signed-off-by: Joachim Wiberg +--- + man/syslog.conf.5 | 10 ++++++++-- + src/syslogd.c | 7 +++---- + 2 files changed, 11 insertions(+), 6 deletions(-) + +diff --git a/man/syslog.conf.5 b/man/syslog.conf.5 +index 030c377..f436dc3 100644 +--- a/man/syslog.conf.5 ++++ b/man/syslog.conf.5 +@@ -67,7 +67,10 @@ ACTION := /path/to/file + OPTION := [OPTION,] + |= RFC3164 + |= RFC5424 +- |= rotate=SIZE:COUNT ++ |= rotate=ROT ++ROT := SIZE:COUNT ++ |= SIZE ++ |= :COUNT + + secure_mode [0,1,2] + +@@ -108,7 +111,10 @@ The log rotation, which is only relevant for files, details the max + .Ar SIZE:COUNT + a file can reach before it is rotated, and later compressed. This + feature is mostly intended for embedded systems that do not want to have +-cron or a separate log rotate daemon. ++cron or a separate log rotate daemon. It is possible to specify only ++size or count, in which case the global setting covers the other. E.g., ++to set only the rotation count, use: ++.Ar rotate=:COUNT . + .Pp + The + .Ql rotate_size SIZE +diff --git a/src/syslogd.c b/src/syslogd.c +index fa8964b..2264a75 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -2876,13 +2876,12 @@ static void cfrot(char *ptr, struct filed *f) + *c++ = 0; + cnt = atoi(c); + } ++ if (cnt > 0) ++ f->f_rotatecount = cnt; + + sz = strtobytes(ptr); +- if (sz > 0 && cnt > 0) { +- logit("Set rotate size %d bytes, %d rotations\n", sz, cnt); +- f->f_rotatecount = cnt; ++ if (sz > 0) + f->f_rotatesz = sz; +- } + } + + static int cfopt(char **ptr, const char *opt) +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0005-Fix-81-blocking-delay-for-unreachable-remote.patch b/patches/sysklogd/2.5.2/0005-Fix-81-blocking-delay-for-unreachable-remote.patch new file mode 100644 index 00000000..27294d46 --- /dev/null +++ b/patches/sysklogd/2.5.2/0005-Fix-81-blocking-delay-for-unreachable-remote.patch @@ -0,0 +1,150 @@ +From a1dc835fd5d11ce0dd6d9983c1aa2ca188460ac9 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 14 Jul 2024 17:46:41 +0200 +Subject: [PATCH 05/15] Fix #81: blocking delay for unreachable remote +Organization: Addiva Elektronik + +This patch fixes a blocking delay when a named remote action is set up. +On GLIBC systems, with the default resolver setup, this may be as long +as 10 seconds, meaning syslogd retried nslookup() every log message, +which in turn lead to snail speed on logging to other targets. + +Additionally it re-enables the warning for failure to resolve the DNS +name -- a user is likely very interested in why they are not seeing any +logs on their remote server. Logs age out, so logging in to a device +which may have logged this once is not very useful. + +Signed-off-by: Joachim Wiberg +--- + configure.ac | 12 ++++++++++++ + src/syslogd.c | 27 ++++++++++++++++----------- + src/syslogd.h | 5 ++++- + 3 files changed, 32 insertions(+), 12 deletions(-) + +diff --git a/configure.ac b/configure.ac +index c370877..cf2488a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -67,6 +67,10 @@ AC_CHECK_FUNCS([setsid]) + AC_CHECK_FUNCS([getprogname strtobytes]) + + # Command line options ++AC_ARG_WITH(dns-delay, ++ AS_HELP_STRING([--with-dns-delay=SEC], [Retry delay resolving DNS names, default: 60]), ++ [dns_delay=$withval], [dns_delay='no']) ++ + AC_ARG_WITH(suspend-time, + AS_HELP_STRING([--with-suspend-time=SEC], [Retry delay for sending to remote, default: 180]), + [suspend_time=$withval], [suspend_time='no']) +@@ -82,6 +86,13 @@ AC_ARG_WITH(logger, + AS_IF([test "x$logger" != "xno"], with_logger="yes", with_logger="no") + AM_CONDITIONAL([ENABLE_LOGGER], [test "x$with_logger" != "xno"]) + ++AS_IF([test "x$dns_delay" != "xno"],[ ++ AS_IF([test "x$dns_delay" = "xyes"],[ ++ AC_MSG_ERROR([Must supply argument])]) ++ ] ++ AC_DEFINE_UNQUOTED(INET_DNS_DELAY, $dns_delay, [Retry delay for resolving DNS names, default: 60]), ++ dns_delay=60) ++ + AS_IF([test "x$suspend_time" != "xno"],[ + AS_IF([test "x$suspend_time" = "xyes"],[ + AC_MSG_ERROR([Must supply argument])]) +@@ -134,6 +145,7 @@ cat <f_un.f_forw.f_hname; + char *serv = f->f_un.f_forw.f_serv; + struct addrinfo *ai; ++ time_t now, diff; + int err, first; +- time_t diff; + + if (SecureMode > 1) { + if (f->f_un.f_forw.f_addr) +@@ -2419,27 +2424,27 @@ static void forw_lookup(struct filed *f) + /* Called from cfline() for initial lookup? */ + first = f->f_type == F_UNUSED ? 1 : 0; + ++ now = timer_now(); ++ diff = now - f->f_time; ++ + /* +- * Not INET_SUSPEND_TIME, but back off a few seconds at least +- * to prevent syslogd from hammering the resolver for every +- * little message that is logged. E.g., at boot when we read +- * the kernel ring buffer. ++ * Back off a minute to prevent unnecessary delays on other log ++ * targets due to being blockd in nslookup(). This means bootup ++ * log messages may not be logged for named remote targets since ++ * networking may not be available until later. + */ +- diff = timer_now() - f->f_time; +- if (!first && diff < 5) ++ if (!first && diff < INET_DNS_DELAY) + return; + + err = nslookup(host, serv, &ai); + if (err) { + f->f_type = F_FORW_UNKN; +- f->f_time = timer_now(); +- if (!first && !(f->f_flags & SUSP_RETR)) ++ f->f_time = now; ++ if (!first) + WARN("Failed resolving '%s:%s': %s", host, serv, gai_strerror(err)); +- f->f_flags |= SUSP_RETR; /* Retry silently */ + return; + } + +- f->f_flags &= ~SUSP_RETR; + f->f_type = F_FORW; + f->f_un.f_forw.f_addr = ai; + f->f_prevcount = 0; +diff --git a/src/syslogd.h b/src/syslogd.h +index 1703df2..a14b6a0 100644 +--- a/src/syslogd.h ++++ b/src/syslogd.h +@@ -119,6 +119,10 @@ + #define MAXUNAMES 20 /* maximum number of user names */ + #define MAXFNAME 200 /* max file pathname length */ + ++#ifndef INET_DNS_DELAY ++#define INET_DNS_DELAY 60 ++#endif ++ + #ifndef INET_SUSPEND_TIME + #define INET_SUSPEND_TIME 180 /* equal to 3 minutes */ + #endif +@@ -185,7 +189,6 @@ + #define MARK 0x008 /* this message is a mark */ + #define RFC3164 0x010 /* format log message according to RFC 3164 */ + #define RFC5424 0x020 /* format log message according to RFC 5424 */ +-#define SUSP_RETR 0x040 /* suspend/forw_unkn, retrying nslookup */ + + /* Syslog timestamp formats. */ + #define BSDFMT_DATELEN 0 +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0006-Fix-annoying-gcc-warning-in-rotate_file.patch b/patches/sysklogd/2.5.2/0006-Fix-annoying-gcc-warning-in-rotate_file.patch new file mode 100644 index 00000000..5b988209 --- /dev/null +++ b/patches/sysklogd/2.5.2/0006-Fix-annoying-gcc-warning-in-rotate_file.patch @@ -0,0 +1,40 @@ +From 2d626af27e8f3115175749d183a8b7f91849bf10 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 14 Jul 2024 17:43:39 +0200 +Subject: [PATCH 06/15] Fix annoying gcc warning in rotate_file() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit +Organization: Addiva Elektronik + +syslogd.c: In function ‘rotate_file’: +syslogd.c:1787:69: warning: ‘%s’ directive output between 0 and 2147483646 bytes may cause result to exceed ‘INT_MAX’ [-Wformat-truncation=] + 1787 | snprintf(cmd, sizeof(cmd), "gzip -f %s", newFile); + | ^~ + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index c838c36..461bbb1 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -1786,10 +1786,11 @@ static void rotate_file(struct filed *f, struct stat *stp_or_null) + snprintf(newFile, len, "%s.%d", f->f_un.f_fname, i); + + if (!rename(oldFile, newFile) && i > 0) { +- size_t clen = 18 + strlen(newFile) + 1; ++ const char *gzip = "gzip -f"; ++ size_t clen = strlen(gzip) + len + 1; + char cmd[clen]; + +- snprintf(cmd, sizeof(cmd), "gzip -f %s", newFile); ++ snprintf(cmd, clen, "%s %s", gzip, newFile); + system(cmd); + } + } +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0007-Refactor-cfparse-to-add-a-per-keyword-parser.patch b/patches/sysklogd/2.5.2/0007-Refactor-cfparse-to-add-a-per-keyword-parser.patch new file mode 100644 index 00000000..2c4d4dc4 --- /dev/null +++ b/patches/sysklogd/2.5.2/0007-Refactor-cfparse-to-add-a-per-keyword-parser.patch @@ -0,0 +1,239 @@ +From 2aa73f85580614b9162aaaa74b2a9e817c6396bd Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 15 Jul 2024 10:46:50 +0200 +Subject: [PATCH 07/15] Refactor cfparse() to add a per-keyword parser +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 74 +++++++++++++++++++++++++++------------------------ + src/syslogd.h | 2 +- + 2 files changed, 40 insertions(+), 36 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 461bbb1..452513f 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -163,7 +163,7 @@ static int RotateCnt = 5; /* Max number (count) of log files to keep, set wi + /* + * List of notifiers + */ +-static SIMPLEQ_HEAD(notifiers, notifier) nothead = SIMPLEQ_HEAD_INITIALIZER(nothead); ++static TAILQ_HEAD(notifiers, notifier) nothead = TAILQ_HEAD_INITIALIZER(nothead); + + /* + * List of peers and sockets for binding. +@@ -184,16 +184,6 @@ char *secure_str; /* string value of secure_mode */ + char *rotate_sz_str; /* string value of RotateSz */ + char *rotate_cnt_str; /* string value of RotateCnt */ + +-const struct cfkey { +- const char *key; +- char **var; +-} cfkey[] = { +- { "notify", NULL }, +- { "secure_mode", &secure_str }, +- { "rotate_size", &rotate_sz_str }, +- { "rotate_count", &rotate_cnt_str }, +-}; +- + /* Function prototypes. */ + static int allowaddr(char *s); + void untty(void); +@@ -221,10 +211,10 @@ static void signal_init(void); + static void boot_time_init(void); + static void init(void); + static int strtobytes(char *arg); +-static int cfparse(FILE *fp, struct files *newf, struct notifiers *newn); ++static int cfparse(FILE *fp, struct files *newf); + int decode(char *name, struct _code *codetab); + static void logit(char *, ...); +-static void notifier_add(struct notifiers *newn, const char *program); ++static void notifier_add(char *program, void *arg); + static void notifier_invoke(const char *logfile); + static void notifier_free_all(void); + void reload(int); +@@ -233,6 +223,20 @@ static int validate(struct sockaddr *sa, const char *hname); + static int waitdaemon(int); + static void timedout(int); + ++/* ++ * Configuration file keywords, variables, and optional callbacks ++ */ ++const struct cfkey { ++ const char *key; ++ char **var; ++ void (*cb)(char *, void *); ++ void *arg; ++} cfkey[] = { ++ { "notify", NULL, notifier_add, ¬head }, ++ { "rotate_size", &rotate_sz_str, NULL, NULL }, ++ { "rotate_count", &rotate_cnt_str, NULL, NULL }, ++ { "secure_mode", &secure_str, NULL, NULL }, ++}; + + /* + * Very basic, and incomplete, check if we're running in a container. +@@ -1816,7 +1820,7 @@ static void rotate_file(struct filed *f, struct stat *stp_or_null) + return; + } + +- if (!SIMPLEQ_EMPTY(¬head)) ++ if (!TAILQ_EMPTY(¬head)) + notifier_invoke(f->f_un.f_fname); + } + ftruncate(f->f_file, 0); +@@ -2708,7 +2712,6 @@ static void boot_time_init(void) + */ + static void init(void) + { +- struct notifiers newn = SIMPLEQ_HEAD_INITIALIZER(newn); + struct files newf = SIMPLEQ_HEAD_INITIALIZER(newf); + struct filed *f; + struct peer *pe; +@@ -2762,6 +2765,11 @@ static void init(void) + */ + tzset(); + ++ /* ++ * Free all notifiers ++ */ ++ notifier_free_all(); ++ + /* + * Read configuration file(s) + */ +@@ -2776,7 +2784,7 @@ static void init(void) + } + } + +- if (cfparse(fp, &newf, &newn)) { ++ if (cfparse(fp, &newf)) { + fclose(fp); + return; + } +@@ -2789,13 +2797,6 @@ static void init(void) + + fhead = newf; + +- /* +- * Free all notifiers +- */ +- notifier_free_all(); +- +- nothead = newn; +- + /* + * Open or close sockets for local and remote communication + */ +@@ -2815,11 +2816,12 @@ static void init(void) + Initialized = 1; + + if (Debug) { +- if (!SIMPLEQ_EMPTY(¬head)) { ++ if (!TAILQ_EMPTY(¬head)) { + struct notifier *np; + +- SIMPLEQ_FOREACH(np, ¬head, n_link) ++ TAILQ_FOREACH(np, ¬head, n_link) { + printf("notify %s\n", np->n_program); ++ } + printf("\n"); + } + +@@ -3208,6 +3210,8 @@ const struct cfkey *cfkey_match(char *cline) + + if (cfk->var) + *cfk->var = strdup(p); ++ else if (cfk->cb) ++ cfk->cb(p, cfk->arg); + else + memmove(cline, p, strlen(p) + 1); + +@@ -3220,7 +3224,7 @@ const struct cfkey *cfkey_match(char *cline) + /* + * Parse .conf file and append to list + */ +-static int cfparse(FILE *fp, struct files *newf, struct notifiers *newn) ++static int cfparse(FILE *fp, struct files *newf) + { + const struct cfkey *cfk; + struct filed *f; +@@ -3286,7 +3290,7 @@ static int cfparse(FILE *fp, struct files *newf, struct notifiers *newn) + } + + logit("Parsing %s ...\n", gl.gl_pathv[i]); +- cfparse(fpi, newf, newn); ++ cfparse(fpi, newf); + fclose(fpi); + } + globfree(&gl); +@@ -3294,11 +3298,8 @@ static int cfparse(FILE *fp, struct files *newf, struct notifiers *newn) + } + + cfk = cfkey_match(cline); +- if (cfk) { +- if (!strcmp(cfk->key, "notify")) +- notifier_add(newn, cline); ++ if (cfk) + continue; +- } + + f = cfline(cline); + if (!f) +@@ -3681,8 +3682,10 @@ static void logit(char *fmt, ...) + fflush(stdout); + } + +-static void notifier_add(struct notifiers *newn, const char *program) ++static void notifier_add(char *program, void *arg) + { ++ struct notifiers *newn = (struct notifiers *)arg; ++ + while (*program && isspace(*program)) + ++program; + +@@ -3701,7 +3704,7 @@ static void notifier_add(struct notifiers *newn, const char *program) + ERR("Cannot allocate memory for a notify program"); + return; + } +- SIMPLEQ_INSERT_TAIL(newn, np, n_link); ++ TAILQ_INSERT_TAIL(newn, np, n_link); + } else + logit("notify: non-existing, or not executable program\n"); + } +@@ -3714,7 +3717,7 @@ static void notifier_invoke(const char *logfile) + + logit("notify: rotated %s, invoking hooks\n", logfile); + +- SIMPLEQ_FOREACH(np, ¬head, n_link) { ++ TAILQ_FOREACH(np, ¬head, n_link) { + childpid = fork(); + + switch (childpid) { +@@ -3739,7 +3742,8 @@ static void notifier_free_all(void) + { + struct notifier *np, *npnext; + +- SIMPLEQ_FOREACH_SAFE(np, ¬head, n_link, npnext) { ++ TAILQ_FOREACH_SAFE(np, ¬head, n_link, npnext) { ++ TAILQ_REMOVE(¬head, np, n_link); + free(np->n_program); + free(np); + } +diff --git a/src/syslogd.h b/src/syslogd.h +index a14b6a0..14c66a7 100644 +--- a/src/syslogd.h ++++ b/src/syslogd.h +@@ -314,7 +314,7 @@ struct filed { + * Log rotation notifiers + */ + struct notifier { +- SIMPLEQ_ENTRY(notifier) n_link; ++ TAILQ_ENTRY(notifier) n_link; + char *n_program; + }; + +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0008-Fix-gcc-warning-in-vsyslogp_r.patch b/patches/sysklogd/2.5.2/0008-Fix-gcc-warning-in-vsyslogp_r.patch new file mode 100644 index 00000000..22e4de08 --- /dev/null +++ b/patches/sysklogd/2.5.2/0008-Fix-gcc-warning-in-vsyslogp_r.patch @@ -0,0 +1,42 @@ +From c15bb6208cdd0e0629a28c10cb448a11aa7a1624 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 15 Jul 2024 14:24:08 +0200 +Subject: [PATCH 08/15] Fix gcc warning in vsyslogp_r() +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/syslog.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/syslog.c b/src/syslog.c +index 1510258..fbbdfdf 100644 +--- a/src/syslog.c ++++ b/src/syslog.c +@@ -267,7 +267,7 @@ vsyslogp_r(int pri, struct syslog_data *data, const char *msgid, + /* Default log format is RFC5424, continues below BSD format */ + if (data->log_stat & LOG_RFC3164) { + const char *tag = data->log_tag; +- char tmp[33]; ++ char tmp[256]; + + if (!(data->log_stat & LOG_NLOG)) { + prlen = snprintf(p, tbuf_left, "<%d>", pri); +@@ -303,12 +303,12 @@ vsyslogp_r(int pri, struct syslog_data *data, const char *msgid, + + /* + * When sending remote we MUST follow RFC3164 sec 4.1.3, +- * otherwise we "cheat" and allow max lenght hostname, ++ * otherwise we "cheat" and allow max length hostname, + * for either log file or local syslogd -- it is up to + * the local syslogd then to fulfill RFC req. on output + */ + if (data->log_host) { +- strlcpy(tmp, data->log_tag, sizeof(tbuf)); ++ strlcpy(tmp, data->log_tag, sizeof(tmp)); + tag = tmp; + } + +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0009-Fix-83-add-support-for-listen-addr-port-to-.conf-fil.patch b/patches/sysklogd/2.5.2/0009-Fix-83-add-support-for-listen-addr-port-to-.conf-fil.patch new file mode 100644 index 00000000..9955c07d --- /dev/null +++ b/patches/sysklogd/2.5.2/0009-Fix-83-add-support-for-listen-addr-port-to-.conf-fil.patch @@ -0,0 +1,285 @@ +From f5fae387b92e81cc1f1f9e8f6656b20bb9e2e929 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 15 Jul 2024 14:57:54 +0200 +Subject: [PATCH 09/15] Fix #83: add support for listen addr:port to .conf file +Organization: Addiva Elektronik + +This complements the command line '-b addr:port' support with a 'listen' +directive in the .conf file. The command line listen directives are in +this implementation treated as "static" and cannot be removed using the +.conf file. + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 104 +++++++++++++++++++++++++++++++++++++++++--------- + src/syslogd.h | 3 +- + 2 files changed, 88 insertions(+), 19 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 452513f..8ad5109 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -168,12 +168,12 @@ static TAILQ_HEAD(notifiers, notifier) nothead = TAILQ_HEAD_INITIALIZER(nothead) + /* + * List of peers and sockets for binding. + */ +-static SIMPLEQ_HEAD(, peer) pqueue = SIMPLEQ_HEAD_INITIALIZER(pqueue); ++static TAILQ_HEAD(peers, peer) pqueue = TAILQ_HEAD_INITIALIZER(pqueue); + + /* + * List fo peers allowed to log to us. + */ +-static SIMPLEQ_HEAD(, allowedpeer) aphead = SIMPLEQ_HEAD_INITIALIZER(aphead); ++static SIMPLEQ_HEAD(allowed, allowedpeer) aphead = SIMPLEQ_HEAD_INITIALIZER(aphead); + + /* + * central list of recognized configuration keywords with an optional +@@ -211,6 +211,7 @@ static void signal_init(void); + static void boot_time_init(void); + static void init(void); + static int strtobytes(char *arg); ++static void cflisten(char *ptr, void *arg); + static int cfparse(FILE *fp, struct files *newf); + int decode(char *name, struct _code *codetab); + static void logit(char *, ...); +@@ -232,6 +233,7 @@ const struct cfkey { + void (*cb)(char *, void *); + void *arg; + } cfkey[] = { ++ { "listen", NULL, cflisten, NULL }, + { "notify", NULL, notifier_add, ¬head }, + { "rotate_size", &rotate_sz_str, NULL, NULL }, + { "rotate_count", &rotate_cnt_str, NULL, NULL }, +@@ -276,11 +278,24 @@ static int addpeer(struct peer *pe0) + { + struct peer *pe; + ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { ++ if (((pe->pe_name == NULL && pe0->pe_name == NULL) || ++ (pe->pe_name != NULL && pe0->pe_name != NULL && strcmp(pe->pe_name, pe0->pe_name) == 0)) && ++ ((pe->pe_serv == NULL && pe0->pe_serv == NULL) || ++ (pe->pe_serv != NULL && pe0->pe_serv != NULL && strcmp(pe->pe_serv, pe0->pe_serv) == 0))) { ++ /* update flags */ ++ pe->pe_mark = pe0->pe_mark; ++ pe->pe_mode = pe0->pe_mode; ++ ++ return 0; ++ } ++ } ++ + pe = calloc(1, sizeof(*pe)); + if (pe == NULL) + err(1, "malloc failed"); + *pe = *pe0; +- SIMPLEQ_INSERT_TAIL(&pqueue, pe, pe_link); ++ TAILQ_INSERT_TAIL(&pqueue, pe, pe_link); + + return 0; + } +@@ -406,7 +421,6 @@ int main(int argc, char *argv[]) + pid_t ppid = 1; + int no_sys = 0; + int pflag = 0; +- int bflag = 0; + char *ptr; + int ch; + +@@ -434,13 +448,13 @@ int main(int argc, char *argv[]) + break; + + case 'b': +- bflag = 1; + ptr = strchr(optarg, ':'); + if (ptr) + *ptr++ = 0; + addpeer(&(struct peer) { + .pe_name = optarg, + .pe_serv = ptr, ++ .pe_mark = -1, + }); + break; + +@@ -503,6 +517,7 @@ int main(int argc, char *argv[]) + addpeer(&(struct peer) { + .pe_name = optarg, + .pe_mode = 0666, ++ .pe_mark = -1, + }); + break; + +@@ -538,13 +553,6 @@ int main(int argc, char *argv[]) + if ((argc -= optind)) + return usage(1); + +- /* Default to listen to :514 (syslog/udp) */ +- if (!bflag) +- addpeer(&(struct peer) { +- .pe_name = NULL, +- .pe_serv = "syslog", +- }); +- + /* Figure out where to read system log messages from */ + if (!pflag) { + /* Do we run under systemd-journald (Requires=syslog.socket)? */ +@@ -556,6 +564,7 @@ int main(int argc, char *argv[]) + addpeer(&(struct peer) { + .pe_name = _PATH_LOG, + .pe_mode = 0666, ++ .pe_mark = -1, + }); + } + } +@@ -2545,7 +2554,9 @@ void die(int signo) + /* + * Close all UNIX and inet sockets + */ +- SIMPLEQ_FOREACH_SAFE(pe, &pqueue, pe_link, next) { ++ TAILQ_FOREACH_SAFE(pe, &pqueue, pe_link, next) { ++ TAILQ_REMOVE(&pqueue, pe, pe_link); ++ + for (size_t i = 0; i < pe->pe_socknum; i++) { + logit("Closing socket %d ...\n", pe->pe_sock[i]); + socket_close(pe->pe_sock[i]); +@@ -2713,8 +2724,9 @@ static void boot_time_init(void) + static void init(void) + { + struct files newf = SIMPLEQ_HEAD_INITIALIZER(newf); ++ struct peer *pe, *penext; + struct filed *f; +- struct peer *pe; ++ int bflag = 0; + FILE *fp; + char *p; + +@@ -2765,6 +2777,16 @@ static void init(void) + */ + tzset(); + ++ /* ++ * mark ++ */ ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { ++ if (pe->pe_mark == -1) ++ continue; ++ ++ pe->pe_mark = 1; ++ } ++ + /* + * Free all notifiers + */ +@@ -2797,10 +2819,31 @@ static void init(void) + + fhead = newf; + ++ /* ++ * Ensure a default listen *:514 exists (compat) ++ */ ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { ++ if (pe->pe_mark == 1) ++ continue; /* marked for deletion */ ++ if (pe->pe_name && pe->pe_name[0] == '/') ++ continue; /* named pipe */ ++ if (pe->pe_name || pe->pe_serv) { ++ bflag = 1; ++ break; /* static or from .conf */ ++ } ++ } ++ if (!bflag) { ++ /* Default to listen to :514 (syslog/udp) */ ++ addpeer(&(struct peer) { ++ .pe_name = NULL, ++ .pe_serv = "514", ++ }); ++ } ++ + /* + * Open or close sockets for local and remote communication + */ +- SIMPLEQ_FOREACH(pe, &pqueue, pe_link) { ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { + if (pe->pe_name && pe->pe_name[0] == '/') { + create_unix_socket(pe); + } else { +@@ -2808,11 +2851,23 @@ static void init(void) + socket_close(pe->pe_sock[i]); + pe->pe_socknum = 0; + +- if (SecureMode < 2) ++ /* skip any marked for deletion */ ++ if (SecureMode < 2 && pe->pe_mark <= 0) + create_inet_socket(pe); + } + } + ++ /* ++ * Sweep ++ */ ++ TAILQ_FOREACH_SAFE(pe, &pqueue, pe_link, penext) { ++ if (pe->pe_mark <= 0) ++ continue; ++ ++ TAILQ_REMOVE(&pqueue, pe, pe_link); ++ free(pe); ++ } ++ + Initialized = 1; + + if (Debug) { +@@ -2874,6 +2929,19 @@ static void init(void) + logit("syslogd: restarted.\n"); + } + ++static void cflisten(char *ptr, void *arg) ++{ ++ char *peer = ptr; ++ ++ ptr = strchr(peer, ':'); ++ if (ptr) ++ *ptr++ = 0; ++ addpeer(&(struct peer) { ++ .pe_name = peer, ++ .pe_serv = ptr, ++ }); ++} ++ + static void cfrot(char *ptr, struct filed *f) + { + char *c; +@@ -3096,7 +3164,7 @@ static struct filed *cfline(char *line) + if (bp) + *bp++ = 0; + else +- bp = "syslog"; /* default: 514/udp */ ++ bp = "514"; /* default: 514/udp */ + + strlcpy(f->f_un.f_forw.f_hname, p, sizeof(f->f_un.f_forw.f_hname)); + strlcpy(f->f_un.f_forw.f_serv, bp, sizeof(f->f_un.f_forw.f_serv)); +@@ -3426,7 +3494,7 @@ static int allowaddr(char *s) + goto err; + } + } else { +- if ((se = getservbyname("syslog", "udp"))) ++ if ((se = getservbyname("514", "udp"))) + ap->port = ntohs(se->s_port); + else + /* sanity, should not happen */ +diff --git a/src/syslogd.h b/src/syslogd.h +index 14c66a7..d74c0ed 100644 +--- a/src/syslogd.h ++++ b/src/syslogd.h +@@ -225,9 +225,10 @@ + * Struct to hold records of peers and sockets + */ + struct peer { +- SIMPLEQ_ENTRY(peer) pe_link; ++ TAILQ_ENTRY(peer) pe_link; + const char *pe_name; + const char *pe_serv; ++ int pe_mark; + mode_t pe_mode; + int pe_sock[16]; + size_t pe_socknum; +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0010-Fix-82-retry-creating-UNIX-and-network-sockets-on-fa.patch b/patches/sysklogd/2.5.2/0010-Fix-82-retry-creating-UNIX-and-network-sockets-on-fa.patch new file mode 100644 index 00000000..70b3c0de --- /dev/null +++ b/patches/sysklogd/2.5.2/0010-Fix-82-retry-creating-UNIX-and-network-sockets-on-fa.patch @@ -0,0 +1,346 @@ +From ad8dedd04a979279d245b53a60311ad91acaaf14 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 15 Jul 2024 15:02:32 +0200 +Subject: [PATCH 10/15] Fix #82: retry creating UNIX and network sockets on + failure +Organization: Addiva Elektronik + +When starting up, or on SIGHUP, syslogd may fail to create a UNIX socket +or (bind) an Internet socket. The latter may be because the system is +in bootstrap and the interface and/or address syslogd tries to bind() to +does not yet exist. + +This commit adds a very basic retry loop every five seconds. + +Also, with the new retry logic it was deemed worth it to increase the +logging from syslogd itself. I.e., when failing to create a socket, +or when retrying and succeeding, as well as when closing sockets. In +particular when opening and closing Internet facing ports. + +Since startup, or reconfiguration, is not failure to send() the we do +not want to inadvertedly trigger F_FORW_SUSP for remote log actions. +This is the reason for the ENONET error code from socket_ffs(), to +ensure we retry sending to remote on the next log message instead of +waiting 180 sec. Ordering at boot, or reconf, is also the reason for +setting Initialized earlier -- this prevents inadvertedly logging to the +console instead of to a file that actually is open. We can usually log +to file but maybe not yet to a remote. + +To not terrify casual readers of the logs, messages for opening and +closing Inet (Internet) sockets are tracked from what context they were +opened in. Context, in this context, is the secure_mode switch in which +syslogd only opens UDP sockets for sending messages to other syslog +servers, i.e., without binding to a server port. + +Signed-off-by: Joachim Wiberg +--- + src/socket.c | 1 + + src/syslogd.c | 145 +++++++++++++++++++++++++++++++++++--------------- + 2 files changed, 102 insertions(+), 44 deletions(-) + +diff --git a/src/socket.c b/src/socket.c +index 4b64888..8c32dac 100644 +--- a/src/socket.c ++++ b/src/socket.c +@@ -217,6 +217,7 @@ int socket_ffs(int family) + return entry->sd; + } + ++ errno = ENONET; + return -1; + } + +diff --git a/src/syslogd.c b/src/syslogd.c +index 8ad5109..402a85e 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -160,6 +160,9 @@ static int rotate_opt; /* Set if command line option has been given + static off_t RotateSz = 0; /* Max file size (bytes) before rotating, disabled by default */ + static int RotateCnt = 5; /* Max number (count) of log files to keep, set with -c */ + ++struct timeval *retry = NULL; /* Set by init() to &init_tv whenever retry jobs exist */ ++struct timeval init_tv = { 5, 0 }; /* Retry every 5 seconds. */ ++ + /* + * List of notifiers + */ +@@ -209,6 +212,7 @@ void debug_switch(); + void die(int sig); + static void signal_init(void); + static void boot_time_init(void); ++static void retry_init(void); + static void init(void); + static int strtobytes(char *arg); + static void cflisten(char *ptr, void *arg); +@@ -642,7 +646,7 @@ no_klogd: + for (;;) { + int rc; + +- rc = socket_poll(NULL); ++ rc = socket_poll(retry); + if (restart > 0) { + restart--; + logit("\nReceived SIGHUP, reloading syslogd.\n"); +@@ -660,8 +664,11 @@ no_klogd: + rotate_all_files(); + } + +- if (rc < 0 && errno != EINTR) +- ERR("select()"); ++ if (rc < 0) { ++ if (errno != EINTR) ++ ERR("select()"); ++ } else if (rc == 0) ++ retry_init(); + + if (KernLog) + sys_seqno_save(); +@@ -769,14 +776,14 @@ static void unix_cb(int sd, void *arg) + parsemsg(LocalHostName, msg); + } + +-static void create_unix_socket(struct peer *pe) ++static int create_unix_socket(struct peer *pe) + { + struct sockaddr_un sun; + struct addrinfo ai; + int sd = -1; + + if (pe->pe_socknum) +- return; /* Already set up */ ++ return 0; /* Already set up */ + + memset(&ai, 0, sizeof(ai)); + ai.ai_addr = (struct sockaddr *)&sun; +@@ -790,11 +797,12 @@ static void create_unix_socket(struct peer *pe) + if (sd < 0) + goto err; + +- logit("Created UNIX socket %d ...\n", sd); ++ NOTE("Created UNIX socket %s", sun.sun_path); + pe->pe_sock[pe->pe_socknum++] = sd; +- return; ++ return 0; + err: + ERR("cannot create %s", pe->pe_name); ++ return 1; + } + + static void unmapped(struct sockaddr *sa) +@@ -866,7 +874,7 @@ static int nslookup(const char *host, const char *service, struct addrinfo **ai) + /* Reset resolver cache and retry name lookup */ + res_init(); + +- logit("nslookup '%s:%s'\n", node ?: "none", service); ++ logit("nslookup '%s:%s'\n", node ?: "*", service); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = !node ? AI_PASSIVE : 0; + hints.ai_family = family; +@@ -875,22 +883,25 @@ static int nslookup(const char *host, const char *service, struct addrinfo **ai) + return getaddrinfo(node, service, &hints, ai); + } + +-static void create_inet_socket(struct peer *pe) ++static int create_inet_socket(struct peer *pe) + { + struct addrinfo *ai, *res; +- int sd, err; ++ int err, rc = 0; ++ ++ if (pe->pe_socknum) ++ return 0; /* Already set up */ + + err = nslookup(pe->pe_name, pe->pe_serv, &res); + if (err) { +- ERRX("%s/udp service unknown: %s", pe->pe_serv, +- gai_strerror(err)); +- return; ++ ERRX("%s:%s/udp service unknown: %s", pe->pe_name ?: "*", pe->pe_serv, gai_strerror(err)); ++ return 1; + } + + for (ai = res; ai; ai = ai->ai_next) { ++ int sd; ++ + if (pe->pe_socknum + 1 >= NELEMS(pe->pe_sock)) { +- WARN("Only %zd IP addresses per socket supported.", +- NELEMS(pe->pe_sock)); ++ WARN("Only %zd IP addresses per socket supported.", NELEMS(pe->pe_sock)); + break; + } + +@@ -900,15 +911,35 @@ static void create_inet_socket(struct peer *pe) + ai->ai_flags &= ~AI_SECURE; + + sd = socket_create(ai, inet_cb, NULL); +- if (sd < 0) ++ if (sd < 0) { ++ WARN("Failed creating socket for %s:%s: %s", pe->pe_name ?: "*", ++ pe->pe_serv, strerror(errno)); ++ rc = 1; + continue; ++ } + +- logit("Created inet socket %d for %s:%s ...\n", sd, +- pe->pe_name, pe->pe_serv); ++ if (!SecureMode) { ++ pe->pe_mode |= 01000; ++ NOTE("Opened inet socket %s:%s", pe->pe_name ?: "*", pe->pe_serv); ++ } + pe->pe_sock[pe->pe_socknum++] = sd; + } + + freeaddrinfo(res); ++ if (rc && pe->pe_socknum == 0) ++ return rc; ++ ++ return 0; ++} ++ ++static void close_socket(struct peer *pe) ++{ ++ for (size_t i = 0; i < pe->pe_socknum; i++) { ++ if (pe->pe_mode & 01000) ++ NOTE("Closing inet socket %s:%s", pe->pe_name ?: "*", pe->pe_serv); ++ socket_close(pe->pe_sock[i]); ++ } ++ pe->pe_socknum = 0; + } + + void untty(void) +@@ -1947,6 +1978,7 @@ void fprintlog_write(struct filed *f, struct iovec *iov, int iovcnt, int flags) + if (lsent != len) { + switch (errno) { + case ENOBUFS: ++ case ENONET: /* returned by socket_ffs() */ + case ENETDOWN: + case ENETUNREACH: + case EHOSTUNREACH: +@@ -2556,11 +2588,7 @@ void die(int signo) + */ + TAILQ_FOREACH_SAFE(pe, &pqueue, pe_link, next) { + TAILQ_REMOVE(&pqueue, pe, pe_link); +- +- for (size_t i = 0; i < pe->pe_socknum; i++) { +- logit("Closing socket %d ...\n", pe->pe_sock[i]); +- socket_close(pe->pe_sock[i]); +- } ++ close_socket(pe); + free(pe); + } + +@@ -2718,6 +2746,31 @@ static void boot_time_init(void) + #endif + } + ++/* ++ * Used by init() to trigger retries of, e.g., binding to interfaces. ++ */ ++static void retry_init(void) ++{ ++ struct peer *pe; ++ int fail = 0; ++ ++ logit("Retrying socket init ...\n"); ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { ++ if (pe->pe_name && pe->pe_name[0] == '/') { ++ fail |= create_unix_socket(pe); ++ } else { ++ /* skip any marked for deletion */ ++ if (SecureMode < 2) ++ fail |= create_inet_socket(pe); ++ } ++ } ++ ++ if (!fail) { ++ logit("Socket re-init done.\n"); ++ retry = NULL; ++ } ++} ++ + /* + * INIT -- Initialize syslogd from configuration table + */ +@@ -2725,8 +2778,8 @@ static void init(void) + { + struct files newf = SIMPLEQ_HEAD_INITIALIZER(newf); + struct peer *pe, *penext; ++ int bflag = 0, fail = 0; + struct filed *f; +- int bflag = 0; + FILE *fp; + char *p; + +@@ -2840,23 +2893,6 @@ static void init(void) + }); + } + +- /* +- * Open or close sockets for local and remote communication +- */ +- TAILQ_FOREACH(pe, &pqueue, pe_link) { +- if (pe->pe_name && pe->pe_name[0] == '/') { +- create_unix_socket(pe); +- } else { +- for (size_t i = 0; i < pe->pe_socknum; i++) +- socket_close(pe->pe_sock[i]); +- pe->pe_socknum = 0; +- +- /* skip any marked for deletion */ +- if (SecureMode < 2 && pe->pe_mark <= 0) +- create_inet_socket(pe); +- } +- } +- + /* + * Sweep + */ +@@ -2865,11 +2901,35 @@ static void init(void) + continue; + + TAILQ_REMOVE(&pqueue, pe, pe_link); ++ close_socket(pe); + free(pe); + } + + Initialized = 1; + ++ flog(LOG_SYSLOG | LOG_INFO, "syslogd v" VERSION ": restart."); ++ logit("syslogd: restarted.\n"); ++ ++ /* ++ * Open or close sockets for local and remote communication ++ * These may be delayed, so start local logging first. ++ */ ++ TAILQ_FOREACH(pe, &pqueue, pe_link) { ++ if (pe->pe_name && pe->pe_name[0] == '/') { ++ fail |= create_unix_socket(pe); ++ } else { ++ close_socket(pe); ++ ++ if (SecureMode < 2) ++ fail |= create_inet_socket(pe); ++ } ++ } ++ ++ if (fail) ++ retry = &init_tv; ++ else ++ retry = NULL; ++ + if (Debug) { + if (!TAILQ_EMPTY(¬head)) { + struct notifier *np; +@@ -2924,9 +2984,6 @@ static void init(void) + printf("\n"); + } + } +- +- flog(LOG_SYSLOG | LOG_INFO, "syslogd v" VERSION ": restart."); +- logit("syslogd: restarted.\n"); + } + + static void cflisten(char *ptr, void *arg) +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0011-Read-.conf-files-from-include-directories-sorted.patch b/patches/sysklogd/2.5.2/0011-Read-.conf-files-from-include-directories-sorted.patch new file mode 100644 index 00000000..940977a5 --- /dev/null +++ b/patches/sysklogd/2.5.2/0011-Read-.conf-files-from-include-directories-sorted.patch @@ -0,0 +1,30 @@ +From 87ccd3eb37087ffb4b5f5b0322a558522a705215 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Thu, 18 Jul 2024 11:42:36 +0200 +Subject: [PATCH 11/15] Read *.conf files from include/ directories sorted +Organization: Addiva Elektronik + +No point in "saving time" on this operation. It is more important to +users that we read the files in a predefined order, alphabetically. + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 402a85e..87da475 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -3400,7 +3400,7 @@ static int cfparse(FILE *fp, struct files *newf) + p++; + + logit("Searching for %s ...\n", p); +- if (glob(p, GLOB_NOSORT, NULL, &gl)) ++ if (glob(p, 0, NULL, &gl)) + logit("No files match %s\n", p); + + for (size_t i = 0; i < gl.gl_pathc; i++) { +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0012-Fix-87-segfault-on-shutdown.patch b/patches/sysklogd/2.5.2/0012-Fix-87-segfault-on-shutdown.patch new file mode 100644 index 00000000..0f8dbb73 --- /dev/null +++ b/patches/sysklogd/2.5.2/0012-Fix-87-segfault-on-shutdown.patch @@ -0,0 +1,44 @@ +From 035dccad53efcd4237f040dc702ab435212ecf03 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Sun, 21 Jul 2024 19:15:48 +0200 +Subject: [PATCH 12/15] Fix #87: segfault on shutdown +Organization: Addiva Elektronik + +Regression introduced in in 36295e3, for issue #82. + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 87da475..64da821 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -2578,11 +2578,6 @@ void die(int signo) + */ + timer_exit(); + +- /* +- * Close all open log files. +- */ +- close_open_log_files(); +- + /* + * Close all UNIX and inet sockets + */ +@@ -2592,6 +2587,11 @@ void die(int signo) + free(pe); + } + ++ /* ++ * Close all open log files. ++ */ ++ close_open_log_files(); ++ + kern_console_on(); + + exit(0); +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0013-Fix-85-logging-to-remote-IPv6-address-does-not-work.patch b/patches/sysklogd/2.5.2/0013-Fix-85-logging-to-remote-IPv6-address-does-not-work.patch new file mode 100644 index 00000000..d68a9e57 --- /dev/null +++ b/patches/sysklogd/2.5.2/0013-Fix-85-logging-to-remote-IPv6-address-does-not-work.patch @@ -0,0 +1,62 @@ +From c7267011224ebd28d8a9daccd589109288fbde11 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 26 Aug 2024 11:47:10 +0200 +Subject: [PATCH 13/15] Fix #85: logging to remote IPv6 address does not work +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 13 ++++++++++++- + test/fwd.sh | 4 ++-- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index 64da821..a2502c9 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -3216,8 +3216,19 @@ static struct filed *cfline(char *line) + switch (*p) { + case '@': + cfopts(p, f); ++ p++; ++ if (*p == '[') { ++ p++; + +- bp = strchr(++p, ':'); ++ q = strchr(p, ']'); ++ if (!q) { ++ ERR("Invalid IPv6 address in remote target, missing ']'"); ++ break; ++ } ++ *q++ = 0; ++ bp = strchr(q, ':'); ++ } else ++ bp = strchr(p, ':'); + if (bp) + *bp++ = 0; + else +diff --git a/test/fwd.sh b/test/fwd.sh +index 70fba5b..e37dc1f 100755 +--- a/test/fwd.sh ++++ b/test/fwd.sh +@@ -13,7 +13,7 @@ MSG="fwd and allow" + + cat <"${CONFD}/fwd.conf" + kern.* /dev/null +-ntp.* @127.0.0.2:${PORT2} ;RFC5424 ++ntp.* @[::1]:${PORT2} ;RFC5424 + EOF + + reload +@@ -23,7 +23,7 @@ kern.* /dev/null + *.*;kern.none ${LOG2} ;RFC5424 + EOF + +-setup2 -m0 -a 127.0.0.2:* -b ":${PORT2}" ++setup2 -m0 -a "[::1]:*" -b ":${PORT2}" + + print "TEST: Starting" + +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0014-Fix-86-adapt-facilities-for-RFC5424-compliance.patch b/patches/sysklogd/2.5.2/0014-Fix-86-adapt-facilities-for-RFC5424-compliance.patch new file mode 100644 index 00000000..babc044c --- /dev/null +++ b/patches/sysklogd/2.5.2/0014-Fix-86-adapt-facilities-for-RFC5424-compliance.patch @@ -0,0 +1,45 @@ +From 1a2e13cb3f3e4fb9f33a56cc87fb96ebc3bb45c7 Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 26 Aug 2024 11:49:27 +0200 +Subject: [PATCH 14/15] Fix #86: adapt facilities for RFC5424 compliance +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/syslog.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/syslog.h b/src/syslog.h +index 873e7f8..0a9c31b 100644 +--- a/src/syslog.h ++++ b/src/syslog.h +@@ -118,8 +118,10 @@ CODE prioritynames[] = { + #define LOG_FTP (11<<3) /* ftp daemon */ + #define LOG_NTP (12<<3) /* NTP subsystem */ + #define LOG_SECURITY (13<<3) /* Log audit, for audit trails */ ++#define LOG_AUDIT LOG_SECURITY /* Alias for RFC5424 compat. */ + #define LOG_CONSOLE (14<<3) /* Log alert */ + #define LOG_CRON_SOL (15<<3) /* clock daemon (Solaris) */ ++#define LOG_CRON2 LOG_CRON_SOL /* Alias for RFC5424 compat. */ + #define LOG_LOCAL0 (16<<3) /* reserved for local use */ + #define LOG_LOCAL1 (17<<3) /* reserved for local use */ + #define LOG_LOCAL2 (18<<3) /* reserved for local use */ +@@ -141,6 +143,7 @@ CODE facilitynames[] = { + { "console", LOG_CONSOLE }, + { "cron", LOG_CRON }, + { "cron_sol", LOG_CRON_SOL }, /* Solaris cron */ ++ { "cron2", LOG_CRON2 }, + { "daemon", LOG_DAEMON }, + { "ftp", LOG_FTP }, + { "kern", LOG_KERN }, +@@ -150,6 +153,7 @@ CODE facilitynames[] = { + { "news", LOG_NEWS }, + { "ntp", LOG_NTP }, + { "security", LOG_SECURITY }, ++ { "audit", LOG_AUDIT }, + { "syslog", LOG_SYSLOG }, + { "user", LOG_USER }, + { "uucp", LOG_UUCP }, +-- +2.43.0 + diff --git a/patches/sysklogd/2.5.2/0015-Fix-88-initial-delay-for-unresolvable-remote-target.patch b/patches/sysklogd/2.5.2/0015-Fix-88-initial-delay-for-unresolvable-remote-target.patch new file mode 100644 index 00000000..e792755e --- /dev/null +++ b/patches/sysklogd/2.5.2/0015-Fix-88-initial-delay-for-unresolvable-remote-target.patch @@ -0,0 +1,34 @@ +From d6e7d2c6ee36cfc67eeef643d4a6c69dfbbd36ab Mon Sep 17 00:00:00 2001 +From: Joachim Wiberg +Date: Mon, 26 Aug 2024 11:50:13 +0200 +Subject: [PATCH 15/15] Fix #88: initial delay for unresolvable remote target +Organization: Addiva Elektronik + +Signed-off-by: Joachim Wiberg +--- + src/syslogd.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/src/syslogd.c b/src/syslogd.c +index a2502c9..fecf281 100644 +--- a/src/syslogd.c ++++ b/src/syslogd.c +@@ -871,8 +871,14 @@ static int nslookup(const char *host, const char *service, struct addrinfo **ai) + if (!node || !node[0]) + node = NULL; + +- /* Reset resolver cache and retry name lookup */ ++ /* ++ * Reset resolver cache and retry name lookup. The use of ++ * `_res` here seems to be the most portable way to adjust ++ * the per-process timeout and retry. ++ */ + res_init(); ++ _res.retrans = 1; ++ _res.retry = 1; + + logit("nslookup '%s:%s'\n", node ?: "*", service); + memset(&hints, 0, sizeof(hints)); +-- +2.43.0 +