Before opening new IPv4/IPv6 server sockets, chronyd will check for matching reusable sockets passed from the service manager (for example, passed via systemd socket activation: https://www.freedesktop.org/software/systemd/man/latest/sd_listen_fds.html) and use those instead. Aside from IPV6_V6ONLY (which cannot be set on already-bound sockets), the daemon sets the same socket options on reusable sockets as it would on sockets it opens itself. Unit tests test the correct parsing of the LISTEN_FDS environment variable. Add 011-systemd system test to test socket activation for DGRAM and STREAM sockets (both IPv4 and IPv6). The tests use the systemd-socket-activate test tool, which has some limitations requiring workarounds discussed in inline comments.
140 lines
5.3 KiB
Bash
Executable file
140 lines
5.3 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
. ./test.common
|
|
|
|
check_chronyd_features NTS || test_skip "NTS support disabled"
|
|
certtool --help &> /dev/null || test_skip "certtool missing"
|
|
check_chronyd_features DEBUG || test_skip "DEBUG support disabled"
|
|
systemd-socket-activate -h &> /dev/null || test_skip "systemd-socket-activate missing"
|
|
has_ipv6=$(check_chronyd_features IPV6 && ping6 -c 1 ::1 > /dev/null 2>&1 && echo 1 || echo 0)
|
|
|
|
test_start "systemd socket activation"
|
|
|
|
cat > $TEST_DIR/cert.cfg <<EOF
|
|
cn = "chrony-nts-test"
|
|
dns_name = "chrony-nts-test"
|
|
ip_address = "$server"
|
|
$([ "$has_ipv6" = "1" ] && echo 'ip_address = "::1"')
|
|
serial = 001
|
|
activation_date = "$[$(date '+%Y') - 1]-01-01 00:00:00 UTC"
|
|
expiration_date = "$[$(date '+%Y') + 2]-01-01 00:00:00 UTC"
|
|
signing_key
|
|
encryption_key
|
|
EOF
|
|
|
|
certtool --generate-privkey --key-type=ed25519 --outfile $TEST_DIR/server.key \
|
|
&> $TEST_DIR/certtool.log
|
|
certtool --generate-self-signed --load-privkey $TEST_DIR/server.key \
|
|
--template $TEST_DIR/cert.cfg --outfile $TEST_DIR/server.crt &>> $TEST_DIR/certtool.log
|
|
chown $user $TEST_DIR/server.*
|
|
|
|
ntpport=$(get_free_port)
|
|
ntsport=$(get_free_port)
|
|
|
|
server_options="port $ntpport nts ntsport $ntsport"
|
|
extra_chronyd_directives="
|
|
port $ntpport
|
|
ntsport $ntsport
|
|
ntsserverkey $TEST_DIR/server.key
|
|
ntsservercert $TEST_DIR/server.crt
|
|
ntstrustedcerts $TEST_DIR/server.crt
|
|
ntsdumpdir $TEST_LIBDIR
|
|
ntsprocesses 3"
|
|
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
extra_chronyd_directives="$extra_chronyd_directives
|
|
bindaddress ::1
|
|
server ::1 minpoll -6 maxpoll -6 $server_options"
|
|
fi
|
|
|
|
# enable debug logging
|
|
extra_chronyd_options="-L -1"
|
|
# Hack to trigger systemd-socket-activate to activate the service. Normally,
|
|
# chronyd.service would be configured with the WantedBy= directive so it starts
|
|
# without waiting for socket activation.
|
|
# (https://0pointer.de/blog/projects/socket-activation.html).
|
|
for i in $(seq 10); do
|
|
sleep 1
|
|
(echo "wake up" > /dev/udp/127.0.0.1/$ntpport) 2>/dev/null
|
|
(echo "wake up" > /dev/tcp/127.0.0.1/$ntsport) 2>/dev/null
|
|
done &
|
|
|
|
# Test with UDP sockets (unfortunately systemd-socket-activate doesn't support
|
|
# both datagram and stream sockets in the same invocation:
|
|
# https://github.com/systemd/systemd/issues/9983).
|
|
CHRONYD_WRAPPER="systemd-socket-activate \
|
|
--datagram \
|
|
--listen 127.0.0.1:$ntpport \
|
|
--listen 127.0.0.1:$ntsport"
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
CHRONYD_WRAPPER="$CHRONYD_WRAPPER \
|
|
--listen [::1]:$ntpport \
|
|
--listen [::1]:$ntsport"
|
|
fi
|
|
|
|
start_chronyd || test_fail
|
|
wait_for_sync || test_fail
|
|
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
run_chronyc "ntpdata ::1" || test_fail
|
|
check_chronyc_output "Total RX +: [1-9]" || test_fail
|
|
fi
|
|
run_chronyc "authdata" || test_fail
|
|
check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen
|
|
=========================================================================\
|
|
$([ "$has_ipv6" = "1" ] && printf "\n%s\n" '::1 NTS 1 (30|15) (128|256) [0-9] 0 0 [78] ( 64|100)')
|
|
127\.0\.0\.1 NTS 1 (30|15) (128|256) [0-9] 0 0 [78] ( 64|100)$" || test_fail
|
|
|
|
stop_chronyd || test_fail
|
|
# DGRAM ntpport socket should be used
|
|
check_chronyd_message_count "Reusing UDPv4 socket fd=3 local=127.0.0.1:$ntpport" 1 1 || test_fail
|
|
# DGRAM ntsport socket should be ignored
|
|
check_chronyd_message_count "Reusing TCPv4 socket fd=4 local=127.0.0.1:$ntsport" 0 0 || test_fail
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
# DGRAM ntpport socket should be used
|
|
check_chronyd_message_count "Reusing UDPv6 socket fd=5 local=\[::1\]:$ntpport" 1 1 || test_fail
|
|
# DGRAM ntsport socket should be ignored
|
|
check_chronyd_message_count "Reusing TCPv6 socket fd=6 local=\[::1\]:$ntsport" 0 0 || test_fail
|
|
fi
|
|
|
|
check_chronyd_messages || test_fail
|
|
check_chronyd_files || test_fail
|
|
|
|
# Test with TCP sockets
|
|
CHRONYD_WRAPPER="systemd-socket-activate \
|
|
--listen 127.0.0.1:$ntpport \
|
|
--listen 127.0.0.1:$ntsport"
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
CHRONYD_WRAPPER="$CHRONYD_WRAPPER \
|
|
--listen [::1]:$ntpport \
|
|
--listen [::1]:$ntsport"
|
|
fi
|
|
|
|
start_chronyd || test_fail
|
|
wait_for_sync || test_fail
|
|
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
run_chronyc "ntpdata ::1" || test_fail
|
|
check_chronyc_output "Total RX +: [1-9]" || test_fail
|
|
fi
|
|
run_chronyc "authdata" || test_fail
|
|
check_chronyc_output "^Name/IP address Mode KeyID Type KLen Last Atmp NAK Cook CLen
|
|
=========================================================================\
|
|
$([ "$has_ipv6" = "1" ] && printf "\n%s\n" '::1 NTS 1 (30|15) (128|256) [0-9] 0 0 [78] ( 64|100)')
|
|
127\.0\.0\.1 NTS 1 (30|15) (128|256) [0-9] 0 0 [78] ( 64|100)$" || test_fail
|
|
|
|
stop_chronyd || test_fail
|
|
# STREAM ntpport should be ignored
|
|
check_chronyd_message_count "Reusing TCPv4 socket fd=3 local=127.0.0.1:$ntpport" 0 0 || test_fail
|
|
# STREAM ntsport should be used
|
|
check_chronyd_message_count "Reusing TCPv4 socket fd=4 local=127.0.0.1:$ntsport" 1 1 || test_fail
|
|
if [ "$has_ipv6" = "1" ]; then
|
|
# STREAM ntpport should be ignored
|
|
check_chronyd_message_count "Reusing TCPv6 socket fd=5 local=\[::1\]:$ntpport" 0 0 || test_fail
|
|
# STREAM ntsport should be used
|
|
check_chronyd_message_count "Reusing TCPv6 socket fd=6 local=\[::1\]:$ntsport" 1 1 || test_fail
|
|
fi
|
|
check_chronyd_messages || test_fail
|
|
check_chronyd_files || test_fail
|
|
|
|
test_pass
|