git: 8b63477e5e00 - main - syslogd: Add host forwarding test

From: Jake Freeland <jfree_at_FreeBSD.org>
Date: Wed, 27 Nov 2024 22:27:17 UTC
The branch main has been updated by jfree:

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

commit 8b63477e5e008574cfdc14185e993234244dc908
Author:     Jake Freeland <jfree@FreeBSD.org>
AuthorDate: 2024-11-27 22:26:10 +0000
Commit:     Jake Freeland <jfree@FreeBSD.org>
CommitDate: 2024-11-27 22:26:10 +0000

    syslogd: Add host forwarding test
    
    Test communication between hosts by setting up two syslogd instances,
    each binded to their own addresses, and sending a message from one to
    the other. The tests passes if the message was delivered and logged
    successfully.
    
    This required some tweaking to the syslogd start and stop routines so
    they could handle launching multiple syslogd instances with different
    runtime files.
    
    Run the tests in jails with an isolated VNET so they don't fail due to
    an address bind collision in the host's VNET.
    
    Reviewed by:    markj
    Differential Revision:  https://reviews.freebsd.org/D47649
---
 usr.sbin/syslogd/tests/Makefile        |   4 ++
 usr.sbin/syslogd/tests/syslogd_test.sh | 125 ++++++++++++++++++++++++++++-----
 2 files changed, 110 insertions(+), 19 deletions(-)

diff --git a/usr.sbin/syslogd/tests/Makefile b/usr.sbin/syslogd/tests/Makefile
index 781730a1102a..30972d3fced5 100644
--- a/usr.sbin/syslogd/tests/Makefile
+++ b/usr.sbin/syslogd/tests/Makefile
@@ -1,5 +1,9 @@
 ATF_TESTS_SH+=	syslogd_test
+# Run in jail with new vnet so we don't need to worry about address conflicts
+TEST_METADATA+=	execenv="jail"
+TEST_METADATA+=	execenv_jail_params="vnet=new"
 # Several syslogd listening on the same port prevent parallel operation
 TEST_METADATA+=	is_exclusive="true"
+TEST_METADATA+=	timeout=20
 
 .include <bsd.test.mk>
diff --git a/usr.sbin/syslogd/tests/syslogd_test.sh b/usr.sbin/syslogd/tests/syslogd_test.sh
index 08e6d76b9ba6..aa8d48e64f5c 100644
--- a/usr.sbin/syslogd/tests/syslogd_test.sh
+++ b/usr.sbin/syslogd/tests/syslogd_test.sh
@@ -11,7 +11,7 @@
 #
 
 # Tests to-do:
-# actions: hostname, users
+# actions: users
 
 readonly SYSLOGD_UDP_PORT="5140"
 readonly SYSLOGD_CONFIG="${PWD}/syslog.conf"
@@ -22,27 +22,72 @@ readonly SYSLOGD_LOCAL_PRIVSOCKET="${PWD}/logpriv.sock"
 # Start a private syslogd instance.
 syslogd_start()
 {
-    local jail
+    local jail bind_addr conf_file pid_file socket privsocket
+    local opt next other_args
+
+    # Setup loopback so we can deliver messages to ourself.
+    atf_check ifconfig lo0 inet 127.0.0.1/16
+
+    OPTIND=1
+    while getopts ":b:f:j:P:p:S:" opt; do
+        case "${opt}" in
+        b)
+            bind_addr="${OPTARG}"
+            ;;
+        f)
+            conf_file="${OPTARG}"
+            ;;
+        j)
+            jail="jexec ${OPTARG}"
+            ;;
+        P)
+            pid_file="${OPTARG}"
+            ;;
+        p)
+            socket="${OPTARG}"
+            ;;
+        S)
+            privsocket="${OPTARG}"
+            ;;
+        ?)
+            opt="${OPTARG}"
+            next="$(eval echo \${${OPTIND}})"
+
+            case "${next}" in
+            -* | "")
+                other_args="${other_args} -${opt}"
+                shift $((OPTIND - 1))
+                ;;
+            *)
+                other_args="${other_args} -${opt} ${next}"
+                shift ${OPTIND}
+                ;;
+            esac
+
+            # Tell getopts to continue parsing.
+            OPTIND=1
+            ;;
+        :)
+            atf_fail "The -${OPTARG} flag requires an argument"
+            ;;
+        esac
+    done
 
-    if [ "$1" = "-j" ]; then
-        jail="jexec $2"
-        shift 2
-    fi
     $jail syslogd \
-        -b ":${SYSLOGD_UDP_PORT}" \
+        -b "${bind_addr:-":${SYSLOGD_UDP_PORT}"}" \
         -C \
         -d \
-        -f "${SYSLOGD_CONFIG}" \
+        -f "${conf_file:-${SYSLOGD_CONFIG}}" \
         -H \
-        -p "${SYSLOGD_LOCAL_SOCKET}" \
-        -P "${SYSLOGD_PIDFILE}" \
-        -S "${SYSLOGD_LOCAL_PRIVSOCKET}" \
-        $@ \
+        -P "${pid_file:-${SYSLOGD_PIDFILE}}" \
+        -p "${socket:-${SYSLOGD_LOCAL_SOCKET}}" \
+        -S "${privsocket:-${SYSLOGD_LOCAL_PRIVSOCKET}}" \
+        ${other_args} \
         &
 
     # Give syslogd a bit of time to spin up.
     while [ "$((i+=1))" -le 20 ]; do
-        [ -S "${SYSLOGD_LOCAL_SOCKET}" ] && return
+        [ -S "${socket:-${SYSLOGD_LOCAL_SOCKET}}" ] && return
         sleep 0.1
     done
     atf_fail "timed out waiting for syslogd to start"
@@ -57,17 +102,19 @@ syslogd_log()
 # Make syslogd reload its configuration file.
 syslogd_reload()
 {
-    pkill -HUP -F "${SYSLOGD_PIDFILE}"
+    pkill -HUP -F "${1:-${SYSLOGD_PIDFILE}}"
 }
 
 # Stop a private syslogd instance.
 syslogd_stop()
 {
-    pid=$(cat "${SYSLOGD_PIDFILE}")
-    if pkill -F "${SYSLOGD_PIDFILE}"; then
+    local pid_file="${1:-${SYSLOGD_PIDFILE}}"
+
+    pid=$(cat "${pid_file}")
+    if pkill -F "${pid_file}"; then
         wait "${pid}"
-        rm -f "${SYSLOGD_PIDFILE}" "${SYSLOGD_LOCAL_SOCKET}" \
-            "${SYSLOGD_LOCAL_PRIVSOCKET}"
+        rm -f "${pid_file}" "${2:-${SYSLOGD_LOCAL_SOCKET}}" \
+            "${3:-${SYSLOGD_LOCAL_PRIVSOCKET}}"
     fi
 }
 
@@ -270,6 +317,45 @@ prop_filter_cleanup()
     syslogd_stop
 }
 
+atf_test_case "host_action" "cleanup"
+host_action_head()
+{
+    atf_set descr "Sends a message to a specified host"
+}
+host_action_body()
+{
+    local addr="192.0.2.100"
+    local logfile="${PWD}/host_action.log"
+
+    atf_check ifconfig lo1 create
+    atf_check ifconfig lo1 inet "${addr}/24"
+    atf_check ifconfig lo1 up
+
+    printf "user.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}"
+    syslogd_start -b "${addr}"
+
+    printf "user.debug\t@${addr}\n" > "${SYSLOGD_CONFIG}.2"
+    syslogd_start \
+        -f "${SYSLOGD_CONFIG}.2" \
+        -P "${SYSLOGD_PIDFILE}.2" \
+        -p "${SYSLOGD_LOCAL_SOCKET}.2" \
+        -S "${SYSLOGD_LOCAL_PRIVSOCKET}.2"
+
+    syslogd_log -p user.debug -t "test" -h "${SYSLOGD_LOCAL_SOCKET}.2" \
+        "message from syslogd2"
+    atf_check -s exit:0 -o match:"test: message from syslogd2" \
+        cat "${logfile}"
+}
+host_action_cleanup()
+{
+    syslogd_stop
+    syslogd_stop \
+        "${SYSLOGD_PIDFILE}.2" \
+        "${SYSLOGD_LOCAL_SOCKET}.2" \
+        "${SYSLOGD_LOCAL_PRIVSOCKET}.2"
+    atf_check ifconfig lo1 destroy
+}
+
 atf_test_case "pipe_action" "cleanup"
 pipe_action_head()
 {
@@ -308,7 +394,7 @@ jail_noinet_body()
 
     logfile="${PWD}/jail_noinet.log"
     printf "user.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}"
-    syslogd_start -j syslogd_noinet -ss
+    syslogd_start -j syslogd_noinet -s -s
 
     syslogd_log -p user.debug -t "test" -h "${SYSLOGD_LOCAL_SOCKET}" \
         "hello, world"
@@ -326,6 +412,7 @@ atf_init_test_cases()
     atf_add_test_case "prog_filter"
     atf_add_test_case "host_filter"
     atf_add_test_case "prop_filter"
+    atf_add_test_case "host_action"
     atf_add_test_case "pipe_action"
     atf_add_test_case "jail_noinet"
 }