1#- 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2021, 2023 The FreeBSD Foundation 5# 6# This software was developed by Mark Johnston under sponsorship from 7# the FreeBSD Foundation. 8# 9# This software was developed by Jake Freeland under sponsorship from 10# the FreeBSD Foundation. 11# 12 13# Tests to-do: 14# actions: hostname, users 15 16readonly SYSLOGD_UDP_PORT="5140" 17readonly SYSLOGD_CONFIG="${PWD}/syslog.conf" 18readonly SYSLOGD_LOCAL_SOCKET="${PWD}/log.sock" 19readonly SYSLOGD_PIDFILE="${PWD}/syslogd.pid" 20readonly SYSLOGD_LOCAL_PRIVSOCKET="${PWD}/logpriv.sock" 21 22# Start a private syslogd instance. 23syslogd_start() 24{ 25 syslogd \ 26 -b ":${SYSLOGD_UDP_PORT}" \ 27 -C \ 28 -d \ 29 -f "${SYSLOGD_CONFIG}" \ 30 -H \ 31 -p "${SYSLOGD_LOCAL_SOCKET}" \ 32 -P "${SYSLOGD_PIDFILE}" \ 33 -S "${SYSLOGD_LOCAL_PRIVSOCKET}" \ 34 $@ \ 35 & 36 37 # Give syslogd a bit of time to spin up. 38 while [ "$((i+=1))" -le 20 ]; do 39 [ -S "${SYSLOGD_LOCAL_SOCKET}" ] && return 40 sleep 0.1 41 done 42 atf_fail "timed out waiting for syslogd to start" 43} 44 45# Simple logger(1) wrapper. 46syslogd_log() 47{ 48 atf_check -s exit:0 -o empty -e empty logger $* 49} 50 51# Make syslogd reload its configuration file. 52syslogd_reload() 53{ 54 pkill -HUP -F "${SYSLOGD_PIDFILE}" 55} 56 57# Stop a private syslogd instance. 58syslogd_stop() 59{ 60 pid=$(cat "${SYSLOGD_PIDFILE}") 61 if pkill -F "${SYSLOGD_PIDFILE}"; then 62 wait "${pid}" 63 rm -f "${SYSLOGD_PIDFILE}" "${SYSLOGD_LOCAL_SOCKET}" \ 64 "${SYSLOGD_LOCAL_PRIVSOCKET}" 65 fi 66} 67 68atf_test_case "basic" "cleanup" 69basic_head() 70{ 71 atf_set descr "Messages are logged via supported transports" 72} 73basic_body() 74{ 75 logfile="${PWD}/basic.log" 76 printf "user.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 77 syslogd_start 78 79 syslogd_log -p user.debug -t basic -h "${SYSLOGD_LOCAL_SOCKET}" \ 80 "hello, world (unix)" 81 atf_check -s exit:0 -o match:"basic: hello, world \(unix\)" \ 82 tail -n 1 "${logfile}" 83 84 # Grab kernel configuration file. 85 sysctl kern.conftxt > conf.txt 86 87 # We have INET transport; make sure we can use it. 88 if grep -qw "INET" conf.txt; then 89 syslogd_log -4 -p user.debug -t basic -h 127.0.0.1 -P "${SYSLOGD_UDP_PORT}" \ 90 "hello, world (v4)" 91 atf_check -s exit:0 -o match:"basic: hello, world \(v4\)" \ 92 tail -n 1 "${logfile}" 93 fi 94 # We have INET6 transport; make sure we can use it. 95 if grep -qw "INET6" conf.txt; then 96 syslogd_log -6 -p user.debug -t basic -h ::1 -P "${SYSLOGD_UDP_PORT}" \ 97 "hello, world (v6)" 98 atf_check -s exit:0 -o match:"basic: hello, world \(v6\)" \ 99 tail -n 1 "${logfile}" 100 fi 101} 102basic_cleanup() 103{ 104 syslogd_stop 105} 106 107atf_test_case "reload" "cleanup" 108reload_head() 109{ 110 atf_set descr "SIGHUP correctly refreshes configuration" 111} 112reload_body() 113{ 114 logfile="${PWD}/reload.log" 115 printf "user.debug\t/${logfile}\n" > "${SYSLOGD_CONFIG}" 116 syslogd_start 117 118 syslogd_log -p user.debug -t reload -h "${SYSLOGD_LOCAL_SOCKET}" \ 119 "pre-reload" 120 atf_check -s exit:0 -o match:"reload: pre-reload" tail -n 1 "${logfile}" 121 122 # Override the old rule. 123 truncate -s 0 "${logfile}" 124 printf "news.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 125 syslogd_reload 126 127 syslogd_log -p user.debug -t reload -h "${SYSLOGD_LOCAL_SOCKET}" \ 128 "post-reload user" 129 syslogd_log -p news.debug -t reload -h "${SYSLOGD_LOCAL_SOCKET}" \ 130 "post-reload news" 131 atf_check -s exit:0 -o not-match:"reload: post-reload user" cat ${logfile} 132 atf_check -s exit:0 -o match:"reload: post-reload news" cat ${logfile} 133} 134reload_cleanup() 135{ 136 syslogd_stop 137} 138 139atf_test_case "prog_filter" "cleanup" 140prog_filter_head() 141{ 142 atf_set descr "Messages are only received from programs in the filter" 143} 144prog_filter_body() 145{ 146 logfile="${PWD}/prog_filter.log" 147 printf "!prog1,prog2\nuser.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 148 syslogd_start 149 150 for i in 1 2 3; do 151 syslogd_log -p user.debug -t "prog${i}" -h "${SYSLOGD_LOCAL_SOCKET}" \ 152 "hello this is prog${i}" 153 done 154 atf_check -s exit:0 -o match:"prog1: hello this is prog1" cat "${logfile}" 155 atf_check -s exit:0 -o match:"prog2: hello this is prog2" cat "${logfile}" 156 atf_check -s exit:0 -o not-match:"prog3: hello this is prog3" cat "${logfile}" 157 158 # Override the old rule. 159 truncate -s 0 ${logfile} 160 printf "!-prog1,prog2\nuser.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 161 syslogd_reload 162 163 for i in 1 2 3; do 164 syslogd_log -p user.debug -t "prog${i}" -h "${SYSLOGD_LOCAL_SOCKET}" \ 165 "hello this is prog${i}" 166 done 167 atf_check -s exit:0 -o not-match:"prog1: hello this is prog1" cat "${logfile}" 168 atf_check -s exit:0 -o not-match:"prog2: hello this is prog2" cat "${logfile}" 169 atf_check -s exit:0 -o match:"prog3: hello this is prog3" cat "${logfile}" 170} 171prog_filter_cleanup() 172{ 173 syslogd_stop 174} 175 176atf_test_case "host_filter" "cleanup" 177host_filter_head() 178{ 179 atf_set descr "Messages are only received from hostnames in the filter" 180} 181host_filter_body() 182{ 183 logfile="${PWD}/host_filter.log" 184 printf "+host1,host2\nuser.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 185 syslogd_start 186 187 for i in 1 2 3; do 188 syslogd_log -p user.debug -t "host${i}" -H "host${i}" \ 189 -h "${SYSLOGD_LOCAL_SOCKET}" "hello this is host${i}" 190 done 191 atf_check -s exit:0 -o match:"host1: hello this is host1" cat "${logfile}" 192 atf_check -s exit:0 -o match:"host2: hello this is host2" cat "${logfile}" 193 atf_check -s exit:0 -o not-match:"host3: hello this is host3" cat "${logfile}" 194 195 # Override the old rule. 196 truncate -s 0 ${logfile} 197 printf "\-host1,host2\nuser.debug\t${logfile}\n" > "${SYSLOGD_CONFIG}" 198 syslogd_reload 199 200 for i in 1 2 3; do 201 syslogd_log -p user.debug -t "host${i}" -H "host${i}" \ 202 -h "${SYSLOGD_LOCAL_SOCKET}" "hello this is host${i}" 203 done 204 atf_check -s exit:0 -o not-match:"host1: hello this is host1" cat "${logfile}" 205 atf_check -s exit:0 -o not-match:"host2: hello this is host2" cat "${logfile}" 206 atf_check -s exit:0 -o match:"host3: hello this is host3" cat "${logfile}" 207} 208host_filter_cleanup() 209{ 210 syslogd_stop 211} 212 213atf_test_case "prop_filter" "cleanup" 214prop_filter_head() 215{ 216 atf_set descr "Messages are received based on conditions in the propery based filter" 217} 218prop_filter_body() 219{ 220 logfile="${PWD}/prop_filter.log" 221 printf ":msg,contains,\"FreeBSD\"\nuser.debug\t${logfile}\n" \ 222 > "${SYSLOGD_CONFIG}" 223 syslogd_start 224 225 syslogd_log -p user.debug -t "prop1" -h "${SYSLOGD_LOCAL_SOCKET}" "FreeBSD" 226 syslogd_log -p user.debug -t "prop2" -h "${SYSLOGD_LOCAL_SOCKET}" "freebsd" 227 atf_check -s exit:0 -o match:"prop1: FreeBSD" cat "${logfile}" 228 atf_check -s exit:0 -o not-match:"prop2: freebsd" cat "${logfile}" 229 230 truncate -s 0 ${logfile} 231 printf ":msg,!contains,\"FreeBSD\"\nuser.debug\t${logfile}\n" \ 232 > "${SYSLOGD_CONFIG}" 233 syslogd_reload 234 235 syslogd_log -p user.debug -t "prop1" -h "${SYSLOGD_LOCAL_SOCKET}" "FreeBSD" 236 syslogd_log -p user.debug -t "prop2" -h "${SYSLOGD_LOCAL_SOCKET}" "freebsd" 237 atf_check -s exit:0 -o not-match:"prop1: FreeBSD" cat "${logfile}" 238 atf_check -s exit:0 -o match:"prop2: freebsd" cat "${logfile}" 239 240 truncate -s 0 ${logfile} 241 printf ":msg,icase_contains,\"FreeBSD\"\nuser.debug\t${logfile}\n" \ 242 > "${SYSLOGD_CONFIG}" 243 syslogd_reload 244 245 syslogd_log -p user.debug -t "prop1" -h "${SYSLOGD_LOCAL_SOCKET}" "FreeBSD" 246 syslogd_log -p user.debug -t "prop2" -h "${SYSLOGD_LOCAL_SOCKET}" "freebsd" 247 atf_check -s exit:0 -o match:"prop1: FreeBSD" cat "${logfile}" 248 atf_check -s exit:0 -o match:"prop2: freebsd" cat "${logfile}" 249 250 truncate -s 0 ${logfile} 251 printf ":msg,!icase_contains,\"FreeBSD\"\nuser.debug\t${logfile}\n" \ 252 > "${SYSLOGD_CONFIG}" 253 syslogd_reload 254 255 syslogd_log -p user.debug -t "prop1" -h "${SYSLOGD_LOCAL_SOCKET}" "FreeBSD" 256 syslogd_log -p user.debug -t "prop2" -h "${SYSLOGD_LOCAL_SOCKET}" "freebsd" 257 syslogd_log -p user.debug -t "prop3" -h "${SYSLOGD_LOCAL_SOCKET}" "Solaris" 258 atf_check -s exit:0 -o not-match:"prop1: FreeBSD" cat "${logfile}" 259 atf_check -s exit:0 -o not-match:"prop2: freebsd" cat "${logfile}" 260 atf_check -s exit:0 -o match:"prop3: Solaris" cat "${logfile}" 261} 262prop_filter_cleanup() 263{ 264 syslogd_stop 265} 266 267atf_test_case "pipe_action" "cleanup" 268pipe_action_head() 269{ 270 atf_set descr "The pipe action evaluates provided command in sh(1)" 271} 272pipe_action_body() 273{ 274 logfile="${PWD}/pipe_action.log" 275 printf "\"While I'm digging in the tunnel, the elves will often come to me \ 276 with solutions to my problem.\"\n-Saymore Crey" > ${logfile} 277 278 printf "!pipe\nuser.debug\t| sed -i '' -e 's/Saymore Crey/Seymour Cray/g' \ 279 ${logfile}\n" > "${SYSLOGD_CONFIG}" 280 syslogd_start 281 282 syslogd_log -p user.debug -t "pipe" -h "${SYSLOGD_LOCAL_SOCKET}" \ 283 "fix spelling error" 284 atf_check -s exit:0 -o match:"Seymour Cray" cat "${logfile}" 285} 286pipe_action_cleanup() 287{ 288 syslogd_stop 289} 290 291atf_init_test_cases() 292{ 293 atf_add_test_case "basic" 294 atf_add_test_case "reload" 295 atf_add_test_case "prog_filter" 296 atf_add_test_case "host_filter" 297 atf_add_test_case "prop_filter" 298 atf_add_test_case "pipe_action" 299} 300