git: 8cc248fb92bf - main - syslogd: Add rfc3164-strict format option

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 23 Dec 2024 15:49:55 UTC
The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=8cc248fb92bfae1e6ef4e2b48a0064377c4b3c11

commit 8cc248fb92bfae1e6ef4e2b48a0064377c4b3c11
Author:     Michal Scigocki <michal.os@hotmail.com>
AuthorDate: 2024-12-23 04:36:57 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-12-23 15:46:14 +0000

    syslogd: Add rfc3164-strict format option
    
    The syslogd bsd/rfc3164 message format does not strictly conform to the
    format recommended in RFC 3164 when syslog messages are forwarded from
    remote hosts.
    
    The new rfc3164-strict format generates messages that conform with the
    RFC 3164 recommended format. The existing format is maintained for
    backwards compatibility.
    
    PR:             220246
    Reviewed by:    markj
    MFC after:      3 weeks
    Pull Request:   https://github.com/freebsd/freebsd-src/pull/1536
---
 usr.sbin/syslogd/syslogd.8                         | 11 +++++--
 usr.sbin/syslogd/syslogd.c                         | 34 ++++++++++++++++------
 .../syslogd/tests/syslogd_basic_format_test.sh     | 20 +++++++++++++
 .../syslogd/tests/syslogd_forwarded_format_test.sh | 26 +++++++++++++++++
 .../syslogd/tests/syslogd_relayed_format_test.sh   | 27 +++++++++++++++++
 5 files changed, 107 insertions(+), 11 deletions(-)

diff --git a/usr.sbin/syslogd/syslogd.8 b/usr.sbin/syslogd/syslogd.8
index b23d0327b76c..fa61e78eaf3e 100644
--- a/usr.sbin/syslogd/syslogd.8
+++ b/usr.sbin/syslogd/syslogd.8
@@ -269,14 +269,21 @@ The values
 .Ar bsd
 and
 .Ar rfc3164
-are used to generate RFC 3164 log messages.
+are used to generate legacy RFC 3164 log messages.
+The value
+.Ar rfc3164-strict
+is used to generate log messages using the RFC 3164 recommended format,
+where messages sent over the network include the hostname,
+and messages forwarded by a relay exclude the
+.Dq Forwarded from
+field.
 The values
 .Ar syslog
 and
 .Ar rfc5424
 are used to generate RFC 5424 log messages,
 having RFC 3339 timestamps with microsecond precision.
-The default is to generate RFC 3164 log messages.
+The default is to generate legacy RFC 3164 log messages.
 .It Fl o
 Prefix kernel messages with the full kernel boot file as determined by
 .Xr getbootfile 3 .
diff --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c
index 23ef5d78c319..be4eaa235d36 100644
--- a/usr.sbin/syslogd/syslogd.c
+++ b/usr.sbin/syslogd/syslogd.c
@@ -194,6 +194,13 @@ static STAILQ_HEAD(, socklist) shead = STAILQ_HEAD_INITIALIZER(shead);
 #define	RFC3164_DATELEN	15
 #define	RFC3164_DATEFMT	"%b %e %H:%M:%S"
 
+/*
+ * FORMAT_BSD_LEGACY and FORMAT_RFC3164_STRICT are two variations of
+ * the RFC 3164 logging format.
+ */
+#define IS_RFC3164_FORMAT (output_format == FORMAT_BSD_LEGACY ||	\
+output_format == FORMAT_RFC3164_STRICT)
+
 static STAILQ_HEAD(, filed) fhead =
     STAILQ_HEAD_INITIALIZER(fhead);	/* Log files that we write to */
 static struct filed consfile;		/* Console */
@@ -315,7 +322,11 @@ static int	LogFacPri;	/* Put facility and priority in log message: */
 static bool	KeepKernFac;	/* Keep remotely logged kernel facility */
 static bool	needdofsync = true; /* Are any file(s) waiting to be fsynced? */
 static struct pidfh *pfh;
-static bool	RFC3164OutputFormat = true; /* Use legacy format by default. */
+static enum {
+	FORMAT_BSD_LEGACY,	/* default, RFC 3164 with legacy deviations */
+	FORMAT_RFC3164_STRICT,	/* compliant to RFC 3164 recommendataions */
+	FORMAT_RFC5424,		/* RFC 5424 format */
+} output_format = FORMAT_BSD_LEGACY;
 static int	kq;		/* kqueue(2) descriptor. */
 
 struct iovlist;
@@ -635,10 +646,12 @@ main(int argc, char *argv[])
 		case 'O':
 			if (strcmp(optarg, "bsd") == 0 ||
 			    strcmp(optarg, "rfc3164") == 0)
-				RFC3164OutputFormat = true;
+				output_format = FORMAT_BSD_LEGACY;
+			else if (strcmp(optarg, "rfc3164-strict") == 0)
+				output_format = FORMAT_RFC3164_STRICT;
 			else if (strcmp(optarg, "syslog") == 0 ||
 			    strcmp(optarg, "rfc5424") == 0)
-				RFC3164OutputFormat = false;
+				output_format = FORMAT_RFC5424;
 			else
 				usage();
 			break;
@@ -666,7 +679,7 @@ main(int argc, char *argv[])
 	if ((argc -= optind) != 0)
 		usage();
 
-	if (RFC3164OutputFormat && MaxForwardLen > 1024)
+	if (IS_RFC3164_FORMAT && MaxForwardLen > 1024)
 		errx(1, "RFC 3164 messages may not exceed 1024 bytes");
 
 	pfh = pidfile_open(PidFile, 0600, &spid);
@@ -1993,7 +2006,10 @@ fprintlog_rfc3164(struct filed *f, const char *hostname, const char *app_name,
 		iovlist_append(&il, priority_number);
 		iovlist_append(&il, ">");
 		iovlist_append(&il, timebuf);
-		if (strcasecmp(hostname, LocalHostName) != 0) {
+		if (output_format == FORMAT_RFC3164_STRICT) {
+			iovlist_append(&il, " ");
+			iovlist_append(&il, hostname);
+		} else if (strcasecmp(hostname, LocalHostName) != 0) {
 			iovlist_append(&il, " Forwarded from ");
 			iovlist_append(&il, hostname);
 			iovlist_append(&il, ":");
@@ -2092,7 +2108,7 @@ fprintlog_first(struct filed *f, const char *hostname, const char *app_name,
 		return;
 	}
 
-	if (RFC3164OutputFormat)
+	if (IS_RFC3164_FORMAT)
 		fprintlog_rfc3164(f, hostname, app_name, procid, msg, flags);
 	else
 		fprintlog_rfc5424(f, hostname, app_name, procid, msgid,
@@ -2215,7 +2231,7 @@ cvthname(struct sockaddr *f)
 	if (hl > 0 && hname[hl-1] == '.')
 		hname[--hl] = '\0';
 	/* RFC 5424 prefers logging FQDNs. */
-	if (RFC3164OutputFormat)
+	if (IS_RFC3164_FORMAT)
 		trimdomain(hname, hl);
 	return (hname);
 }
@@ -2599,7 +2615,7 @@ init(bool reload)
 		err(EX_OSERR, "gethostname() failed");
 	if ((p = strchr(LocalHostName, '.')) != NULL) {
 		/* RFC 5424 prefers logging FQDNs. */
-		if (RFC3164OutputFormat)
+		if (IS_RFC3164_FORMAT)
 			*p = '\0';
 		LocalDomain = p + 1;
 	} else {
@@ -3134,7 +3150,7 @@ cfline(const char *line, const char *prog, const char *host,
 		if (hl > 0 && f.f_host[hl-1] == '.')
 			f.f_host[--hl] = '\0';
 		/* RFC 5424 prefers logging FQDNs. */
-		if (RFC3164OutputFormat)
+		if (IS_RFC3164_FORMAT)
 			trimdomain(f.f_host, hl);
 	}
 
diff --git a/usr.sbin/syslogd/tests/syslogd_basic_format_test.sh b/usr.sbin/syslogd/tests/syslogd_basic_format_test.sh
index 1969ce180f66..09477a568ba8 100644
--- a/usr.sbin/syslogd/tests/syslogd_basic_format_test.sh
+++ b/usr.sbin/syslogd/tests/syslogd_basic_format_test.sh
@@ -63,6 +63,25 @@ O_flag_rfc3164_basic_cleanup()
     syslogd_stop
 }
 
+atf_test_case "O_flag_rfc3164strict_basic" "cleanup"
+O_flag_rfc3164strict_basic_head()
+{
+    atf_set descr "rfc3164-strict format test on local syslog message"
+}
+O_flag_rfc3164strict_basic_body()
+{
+    local format="rfc3164-strict"
+    local logfile="${PWD}/O_flag_${format}_basic.log"
+
+    setup_basic_format_test "${format}" "${logfile}"
+
+    atf_check -s exit:0 -o match:"${REGEX_RFC3164_LOGFILE}" cat "${logfile}"
+}
+O_flag_rfc3164strict_basic_cleanup()
+{
+    syslogd_stop
+}
+
 atf_test_case "O_flag_syslog_basic" "cleanup"
 O_flag_syslog_basic_head()
 {
@@ -105,6 +124,7 @@ atf_init_test_cases()
 {
     atf_add_test_case "O_flag_bsd_basic"
     atf_add_test_case "O_flag_rfc3164_basic"
+    atf_add_test_case "O_flag_rfc3164strict_basic"
     atf_add_test_case "O_flag_syslog_basic"
     atf_add_test_case "O_flag_rfc5424_basic"
 }
diff --git a/usr.sbin/syslogd/tests/syslogd_forwarded_format_test.sh b/usr.sbin/syslogd/tests/syslogd_forwarded_format_test.sh
index 3d220a80b7e8..b17627a935c8 100644
--- a/usr.sbin/syslogd/tests/syslogd_forwarded_format_test.sh
+++ b/usr.sbin/syslogd/tests/syslogd_forwarded_format_test.sh
@@ -94,6 +94,31 @@ O_flag_rfc3164_forwarded_cleanup()
         "${SERVER_2_PORT}"
 }
 
+atf_test_case "O_flag_rfc3164strict_forwarded" "cleanup"
+O_flag_rfc3164strict_forwarded_head()
+{
+    atf_set descr "rfc3164-strict format test on a forwarded syslog message"
+    set_common_atf_metadata
+}
+O_flag_rfc3164strict_forwarded_body()
+{
+    local format="rfc3164-strict"
+    local logfile="${PWD}/${format}_forwarded.log"
+    local pcapfile="${PWD}/${format}_forwarded.pcap"
+
+    setup_forwarded_format_test "${format}" "${logfile}" "${pcapfile}"
+
+    atf_check -s exit:0 -o match:"${REGEX_RFC3164_LOGFILE}" cat "${logfile}"
+    atf_check -s exit:0 -e ignore -o match:"${REGEX_RFC3164_PAYLOAD}" \
+        tcpdump -A -r "${pcapfile}"
+}
+O_flag_rfc3164strict_forwarded_cleanup()
+{
+    syslogd_stop_on_ports \
+        "${SYSLOGD_UDP_PORT_1}" \
+        "${SYSLOGD_UDP_PORT_2}"
+}
+
 atf_test_case "O_flag_syslog_forwarded" "cleanup"
 O_flag_syslog_forwarded_head()
 {
@@ -205,6 +230,7 @@ atf_init_test_cases()
 {
     atf_add_test_case "O_flag_bsd_forwarded"
     atf_add_test_case "O_flag_rfc3164_forwarded"
+    atf_add_test_case "O_flag_rfc3164strict_forwarded"
     atf_add_test_case "O_flag_syslog_forwarded"
     atf_add_test_case "O_flag_rfc5424_forwarded"
 
diff --git a/usr.sbin/syslogd/tests/syslogd_relayed_format_test.sh b/usr.sbin/syslogd/tests/syslogd_relayed_format_test.sh
index 21481823068d..d3e0db4e0f1c 100644
--- a/usr.sbin/syslogd/tests/syslogd_relayed_format_test.sh
+++ b/usr.sbin/syslogd/tests/syslogd_relayed_format_test.sh
@@ -101,6 +101,32 @@ O_flag_rfc3164_relayed_cleanup()
         "${SERVER_3_PORT}"
 }
 
+atf_test_case "O_flag_rfc3164strict_relayed" "cleanup"
+O_flag_rfc3164strict_relayed_head()
+{
+    atf_set descr "rfc3164-strict format test on a relayed syslog message"
+    set_common_atf_metadata
+}
+O_flag_rfc3164strict_relayed_body()
+{
+    local format="rfc3164-strict"
+    local logfile="${PWD}/${format}_relayed.log"
+    local pcapfile="${PWD}/${format}_relayed.pcap"
+
+    setup_relayed_format_test "${format}" "${logfile}" "${pcapfile}"
+
+    atf_check -s exit:0 -o match:"${REGEX_RFC3164_LOGFILE}" cat "${logfile}"
+    atf_check -s exit:0 -e ignore -o match:"${REGEX_RFC3164_PAYLOAD}" \
+        tcpdump -A -r "${pcapfile}"
+}
+O_flag_rfc3164strict_relayed_cleanup()
+{
+    syslogd_stop_on_ports \
+        "${SYSLOGD_UDP_PORT_1}" \
+        "${SYSLOGD_UDP_PORT_2}" \
+        "${SYSLOGD_UDP_PORT_3}"
+}
+
 atf_test_case "O_flag_syslog_relayed" "cleanup"
 O_flag_syslog_relayed_head()
 {
@@ -157,6 +183,7 @@ atf_init_test_cases()
 {
     atf_add_test_case "O_flag_bsd_relayed"
     atf_add_test_case "O_flag_rfc3164_relayed"
+    atf_add_test_case "O_flag_rfc3164strict_relayed"
     atf_add_test_case "O_flag_syslog_relayed"
     atf_add_test_case "O_flag_rfc5424_relayed"
 }