diff options
author | Felipe Sateler <fsateler@debian.org> | 2019-02-20 21:24:33 -0300 |
---|---|---|
committer | Felipe Sateler <fsateler@debian.org> | 2019-02-20 21:24:33 -0300 |
commit | 7c20daf69c4411979b7f8902f3601d1cdc56cc07 (patch) | |
tree | d59b9989ce55ed23693e80974d94c856f1c2c8b1 /test | |
parent | 6e866b331d7cd4a5e0759dd160dea6edabd3678e (diff) | |
download | systemd-upstream/241.tar.gz |
New upstream version 241upstream/241
Diffstat (limited to 'test')
22 files changed, 682 insertions, 78 deletions
diff --git a/test/TEST-01-BASIC/test.sh b/test/TEST-01-BASIC/test.sh index 1d2f833478..1c64017aaa 100755 --- a/test/TEST-01-BASIC/test.sh +++ b/test/TEST-01-BASIC/test.sh @@ -3,7 +3,7 @@ # ex: ts=8 sw=4 sts=4 et filetype=sh set -e TEST_DESCRIPTION="Basic systemd setup" -RUN_IN_UNPRIVILEGED_CONTAINER=yes +RUN_IN_UNPRIVILEGED_CONTAINER=${RUN_IN_UNPRIVILEGED_CONTAINER:-yes} . $TEST_BASE_DIR/test-functions @@ -26,7 +26,7 @@ Description=Testsuite service After=multi-user.target [Service] -ExecStart=/bin/sh -x -c 'systemctl --state=failed --no-legend --no-pager > /failed ; echo OK > /testok' +ExecStart=/bin/sh -x -c 'systemctl --state=failed --no-legend --no-pager > /failed ; systemctl daemon-reload ; echo OK > /testok' Type=oneshot EOF @@ -34,13 +34,6 @@ EOF ) || return 1 setup_nspawn_root - # mask some services that we do not want to run in these tests - ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service - ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service - ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service - ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket - ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service - ddebug "umount $TESTDIR/root" umount $TESTDIR/root } diff --git a/test/TEST-10-ISSUE-2467/test.sh b/test/TEST-10-ISSUE-2467/test.sh index d8959187a1..c85433d7d3 100755 --- a/test/TEST-10-ISSUE-2467/test.sh +++ b/test/TEST-10-ISSUE-2467/test.sh @@ -17,7 +17,7 @@ test_setup() { eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) setup_basic_environment - dracut_install true rm + dracut_install true rm socat # setup the testsuite service cat >$initdir/etc/systemd/system/testsuite.service <<'EOF' @@ -28,13 +28,13 @@ Description=Testsuite service Type=oneshot StandardOutput=tty StandardError=tty -ExecStart=/bin/sh -e -x -c 'rm -f /tmp/nonexistent; systemctl start test.socket; echo > /run/test.ctl; >/testok' +ExecStart=/bin/sh -e -x -c 'rm -f /tmp/nonexistent; systemctl start test.socket; printf x > test.file; socat -t20 OPEN:test.file UNIX-CONNECT:/run/test.ctl; >/testok' TimeoutStartSec=10s EOF cat >$initdir/etc/systemd/system/test.socket <<'EOF' [Socket] -ListenFIFO=/run/test.ctl +ListenStream=/run/test.ctl EOF cat > $initdir/etc/systemd/system/test.service <<'EOF' diff --git a/test/TEST-19-DELEGATE/testsuite.sh b/test/TEST-19-DELEGATE/testsuite.sh index abfcee3cd2..fdfab950b1 100755 --- a/test/TEST-19-DELEGATE/testsuite.sh +++ b/test/TEST-19-DELEGATE/testsuite.sh @@ -33,7 +33,7 @@ if grep -q cgroup2 /proc/filesystems ; then # And now check again, "io" should have vanished grep -qv io /sys/fs/cgroup/system.slice/cgroup.controllers else - echo "Skipping TEST-19-DELEGATE, as the kernel doesn't actually support cgroupsv2" >&2 + echo "Skipping TEST-19-DELEGATE, as the kernel doesn't actually support cgroup v2" >&2 fi echo OK > /testok diff --git a/test/TEST-22-TMPFILES/test-02.sh b/test/TEST-22-TMPFILES/test-02.sh index fe8b903298..d1bf1ea04b 100755 --- a/test/TEST-22-TMPFILES/test-02.sh +++ b/test/TEST-22-TMPFILES/test-02.sh @@ -6,8 +6,8 @@ set -e set -x -rm -fr /tmp/{d,D,e} -mkdir /tmp/{d,D,e} +rm -fr /tmp/{C,d,D,e} +mkdir /tmp/{C,d,D,e} # # 'd' @@ -93,3 +93,30 @@ test $(stat -c %U:%G:%a /tmp/e/3/d2) = "daemon:daemon:755" test -f /tmp/e/3/f1 test $(stat -c %U:%G:%a /tmp/e/3/f1) = "root:root:644" + +# +# 'C' +# + +mkdir /tmp/C/{1,2,3}-origin +touch /tmp/C/{1,2,3}-origin/f1 +chmod 755 /tmp/C/{1,2,3}-origin/f1 + +mkdir /tmp/C/{2,3} +touch /tmp/C/3/f1 + +systemd-tmpfiles --create - <<EOF +C /tmp/C/1 0755 daemon daemon - /tmp/C/1-origin +C /tmp/C/2 0755 daemon daemon - /tmp/C/2-origin +EOF + +test -d /tmp/C/1 +test $(stat -c %U:%G:%a /tmp/C/1/f1) = "daemon:daemon:755" +test -d /tmp/C/2 +test $(stat -c %U:%G:%a /tmp/C/2/f1) = "daemon:daemon:755" + +! systemd-tmpfiles --create - <<EOF +C /tmp/C/3 0755 daemon daemon - /tmp/C/3-origin +EOF + +test $(stat -c %U:%G:%a /tmp/C/3/f1) = "root:root:644" diff --git a/test/TEST-28-PERCENTJ-WANTEDBY/Makefile b/test/TEST-28-PERCENTJ-WANTEDBY/Makefile new file mode 100644 index 0000000000..45e9bfc67c --- /dev/null +++ b/test/TEST-28-PERCENTJ-WANTEDBY/Makefile @@ -0,0 +1,9 @@ +BUILD_DIR=$(shell ../../tools/find-build-dir.sh) + +all setup run: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@ + +clean clean-again: + @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --clean + +.PHONY: all setup run clean clean-again diff --git a/test/TEST-28-PERCENTJ-WANTEDBY/test.sh b/test/TEST-28-PERCENTJ-WANTEDBY/test.sh new file mode 100755 index 0000000000..68935d0da0 --- /dev/null +++ b/test/TEST-28-PERCENTJ-WANTEDBY/test.sh @@ -0,0 +1,68 @@ +#!/bin/bash +# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- +# ex: ts=8 sw=4 sts=4 et filetype=sh +set -e +TEST_DESCRIPTION="Ensure %j Wants directives work" +RUN_IN_UNPRIVILEGED_CONTAINER=yes + +. $TEST_BASE_DIR/test-functions + +test_setup() { + create_empty_image + mkdir -p $TESTDIR/root + mount ${LOOPDEV}p1 $TESTDIR/root + + # Create what will eventually be our root filesystem onto an overlay + ( + LOG_LEVEL=5 + eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) + + setup_basic_environment + + # Set up the services. + cat >$initdir/etc/systemd/system/specifier-j-wants.service << EOF +[Unit] +Description=Wants with percent-j specifier +Wants=specifier-j-depends-%j.service +After=specifier-j-depends-%j.service + +[Service] +Type=oneshot +ExecStart=test -f /tmp/test-specifier-j-%j +ExecStart=/bin/sh -c 'echo OK > /testok' +EOF + cat >$initdir/etc/systemd/system/specifier-j-depends-wants.service << EOF +[Unit] +Description=Dependent service for percent-j specifier + +[Service] +Type=oneshot +ExecStart=touch /tmp/test-specifier-j-wants +EOF + cat >$initdir/etc/systemd/system/testsuite.service << EOF +[Unit] +Description=Testsuite: Ensure %j Wants directives work +Wants=specifier-j-wants.service +After=specifier-j-wants.service + +[Service] +Type=oneshot +ExecStart=/bin/true +EOF + + setup_testsuite + ) || return 1 + setup_nspawn_root + + # mask some services that we do not want to run in these tests + ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service + ln -s /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service + ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.service + ln -s /dev/null $initdir/etc/systemd/system/systemd-networkd.socket + ln -s /dev/null $initdir/etc/systemd/system/systemd-resolved.service + + ddebug "umount $TESTDIR/root" + umount $TESTDIR/root +} + +do_test "$@" diff --git a/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 b/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 new file mode 100644 index 0000000000..37846f42fa --- /dev/null +++ b/test/fuzz/fuzz-udev-rules/oss-fuzz-12980 @@ -0,0 +1 @@ + SUBSYSTEM==" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE=" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" "GROUP=" " KERNEL==" " GROUP=" " MODE =" "KERNEL==" " GROUP=" " KERNEL==" " GROUP=" "MODE =" " KERNEL==" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE=" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " GROUP=" " MODE="" MODE =" " KERNEL==" " GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL=="" GROUP=" " KERNEL==" " GROUP=" " MODE =" " KERNEL==" " KERNEL==" " OPTIONS =" string_escape=replace watch "
\ No newline at end of file diff --git a/test/meson.build b/test/meson.build index d98bfb80d2..94903934a5 100644 --- a/test/meson.build +++ b/test/meson.build @@ -252,7 +252,8 @@ if perl.found() udev_test_pl = find_program('udev-test.pl') if want_tests != 'false' test('udev-test', - udev_test_pl) + udev_test_pl, + timeout : 180) endif else message('Skipping udev-test because perl is not available') diff --git a/test/rule-syntax-check.py b/test/rule-syntax-check.py index dfb06d9ed9..8b26c988ab 100755 --- a/test/rule-syntax-check.py +++ b/test/rule-syntax-check.py @@ -17,6 +17,8 @@ if not rules_files: quoted_string_re = r'"(?:[^\\"]|\\.)*"' no_args_tests = re.compile(r'(ACTION|DEVPATH|KERNELS?|NAME|SYMLINK|SUBSYSTEMS?|DRIVERS?|TAG|PROGRAM|RESULT|TEST)\s*(?:=|!)=\s*' + quoted_string_re + '$') +# PROGRAM can also be specified as an assignment. +program_assign = re.compile(r'PROGRAM\s*=\s*' + quoted_string_re + '$') args_tests = re.compile(r'(ATTRS?|ENV|TEST){([a-zA-Z0-9/_.*%-]+)}\s*(?:=|!)=\s*' + quoted_string_re + '$') no_args_assign = re.compile(r'(NAME|SYMLINK|OWNER|GROUP|MODE|TAG|RUN|LABEL|GOTO|OPTIONS|IMPORT)\s*(?:\+=|:=|=)\s*' + quoted_string_re + '$') args_assign = re.compile(r'(ATTR|ENV|IMPORT|RUN){([a-zA-Z0-9/_.*%-]+)}\s*(=|\+=)\s*' + quoted_string_re + '$') @@ -51,7 +53,8 @@ for path in rules_files: for clause_match in comma_separated_group_re.finditer(line): clause = clause_match.group().strip() if not (no_args_tests.match(clause) or args_tests.match(clause) or - no_args_assign.match(clause) or args_assign.match(clause)): + no_args_assign.match(clause) or args_assign.match(clause) or + program_assign.match(clause)): print('Invalid line {}:{}: {}'.format(path, lineno, line)) print(' clause:', clause) diff --git a/test/test-execute/exec-privatenetwork-yes.service b/test/test-execute/exec-privatenetwork-yes.service index ded8d55126..8f5cbadf04 100644 --- a/test/test-execute/exec-privatenetwork-yes.service +++ b/test/test-execute/exec-privatenetwork-yes.service @@ -2,6 +2,6 @@ Description=Test for PrivateNetwork [Service] -ExecStart=/bin/sh -x -c '! ip link | grep ": " | grep -Ev ": (lo|(sit0|ip6tnl0|ip6gre0)@.*):"' +ExecStart=/bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -Ev ": (lo|(erspan|gre|gretap|ip_vti|ip6_vti|ip6gre|ip6tnl|sit|tunl)0@.*):"' Type=oneshot PrivateNetwork=yes diff --git a/test/test-functions b/test/test-functions index 37069396b7..a936202e4a 100644 --- a/test/test-functions +++ b/test/test-functions @@ -15,6 +15,7 @@ TIMED_OUT= # will be 1 after run_* if *_TIMEOUT is set and test timed out [[ "$LOOKS_LIKE_SUSE" ]] && FSTYPE="${FSTYPE:-btrfs}" || FSTYPE="${FSTYPE:-ext4}" UNIFIED_CGROUP_HIERARCHY="${UNIFIED_CGROUP_HIERARCHY:-default}" EFI_MOUNT="$(bootctl -p 2>/dev/null || echo /boot)" +QEMU_MEM="${QEMU_MEM:-512M}" if ! ROOTLIBDIR=$(pkg-config --variable=systemdutildir systemd); then echo "WARNING! Cannot determine rootlibdir from pkg-config, assuming /usr/lib/systemd" >&2 @@ -37,7 +38,7 @@ is_built_with_asan() { fi # Borrowed from https://github.com/google/oss-fuzz/blob/cd9acd02f9d3f6e80011cc1e9549be526ce5f270/infra/base-images/base-runner/bad_build_check#L182 - local _asan_calls=$(objdump -dC $BUILD_DIR/systemd | egrep "callq\s+[0-9a-f]+\s+<__asan" -c) + local _asan_calls=$(objdump -dC $BUILD_DIR/systemd-journald | egrep "callq\s+[0-9a-f]+\s+<__asan" -c) if (( $_asan_calls < 1000 )); then return 1 else @@ -51,6 +52,8 @@ if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then STRIP_BINARIES=no SKIP_INITRD=yes PATH_TO_INIT=$ROOTLIBDIR/systemd-under-asan + QEMU_MEM="1536M" + QEMU_SMP=4 fi function find_qemu_bin() { @@ -96,17 +99,28 @@ run_qemu() { && KERNEL_BIN="$EFI_MOUNT/$MACHINE_ID/$KERNEL_VER/linux" fi + CONSOLE=ttyS0 + if [[ ! "$KERNEL_BIN" ]]; then if [[ "$LOOKS_LIKE_ARCH" ]]; then KERNEL_BIN=/boot/vmlinuz-linux else - KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER + [ "$ARCH" ] || ARCH=$(uname -m) + case $ARCH in + ppc64*) + KERNEL_BIN=/boot/vmlinux-$KERNEL_VER + CONSOLE=hvc0 + ;; + *) + KERNEL_BIN=/boot/vmlinuz-$KERNEL_VER + ;; + esac fi fi default_fedora_initrd=/boot/initramfs-${KERNEL_VER}.img default_debian_initrd=/boot/initrd.img-${KERNEL_VER} - default_arch_initrd=/boot/initramfs-linux.img + default_arch_initrd=/boot/initramfs-linux-fallback.img default_suse_initrd=/boot/initrd-${KERNEL_VER} if [[ ! "$INITRD" ]]; then if [[ -e "$default_fedora_initrd" ]]; then @@ -147,7 +161,7 @@ root=/dev/sda1 \ raid=noautodetect \ loglevel=2 \ init=$PATH_TO_INIT \ -console=ttyS0 \ +console=$CONSOLE \ selinux=0 \ printk.devkmsg=on \ $_cgroup_args \ @@ -156,7 +170,7 @@ $KERNEL_APPEND \ QEMU_OPTIONS="-smp $QEMU_SMP \ -net none \ --m 512M \ +-m $QEMU_MEM \ -nographic \ -kernel $KERNEL_BIN \ -drive format=raw,cache=unsafe,file=${TESTDIR}/rootdisk.img \ @@ -330,8 +344,8 @@ create_asan_wrapper() { set -x DEFAULT_ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 -DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1 -DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS:halt_on_error=1" +DEFAULT_UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1 +DEFAULT_ENVIRONMENT="ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS" mount -t proc proc /proc mount -t sysfs sysfs /sys @@ -344,6 +358,7 @@ if [[ "\$PATH_TO_ASAN" ]]; then DEFAULT_ENVIRONMENT="\$DEFAULT_ENVIRONMENT LD_PRELOAD=\$PATH_TO_ASAN" fi echo DefaultEnvironment=\$DEFAULT_ENVIRONMENT >>/etc/systemd/system.conf +echo DefaultTimeoutStartSec=180s >>/etc/systemd/system.conf # ASAN and syscall filters aren't compatible with each other. find / -name '*.service' -type f | xargs sed -i 's/^\\(MemoryDeny\\|SystemCall\\)/#\\1/' @@ -354,6 +369,12 @@ JOURNALD_CONF_DIR=/etc/systemd/system/systemd-journald.service.d mkdir -p "\$JOURNALD_CONF_DIR" printf "[Service]\nEnvironment=ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd-journald.asan.log\n" >"\$JOURNALD_CONF_DIR/env.conf" +# 90s isn't enough for some services to finish when literally everything is run +# under ASan+UBSan in containers, which, in turn, are run in VMs. +# Let's limit which environments such services should be executed in. +mkdir -p /etc/systemd/system/systemd-hwdb-update.service.d +printf "[Unit]\nConditionVirtualization=container\n\n[Service]\nTimeoutSec=180s\n" >/etc/systemd/system/systemd-hwdb-update.service.d/env-override.conf + export ASAN_OPTIONS=\$DEFAULT_ASAN_OPTIONS:log_path=/systemd.asan.log UBSAN_OPTIONS=\$DEFAULT_UBSAN_OPTIONS exec $ROOTLIBDIR/systemd "\$@" EOF @@ -453,8 +474,47 @@ EOF fi } +check_asan_reports() { + local ret=0 + local root="$1" + + if [[ "$IS_BUILT_WITH_ASAN" = "yes" ]]; then + ls -l "$root" + if [[ -e "$root/systemd.asan.log.1" ]]; then + cat "$root/systemd.asan.log.1" + ret=$(($ret+1)) + fi + + journald_report=$(find "$root" -name "systemd-journald.asan.log*" -exec cat {} \;) + if [[ ! -z "$journald_report" ]]; then + printf "%s" "$journald_report" + ret=$(($ret+1)) + fi + + pids=$( + "$BUILD_DIR/journalctl" -D "$root/var/log/journal" | perl -alne ' + BEGIN { + %services_to_ignore = ( + "dbus-daemon" => undef, + ); + } + print $2 if /\s(\S*)\[(\d+)\]:\s*SUMMARY:\s+\w+Sanitizer/ && !exists $services_to_ignore{$1}' + ) + if [[ ! -z "$pids" ]]; then + ret=$(($ret+1)) + for pid in $pids; do + "$BUILD_DIR/journalctl" -D "$root/var/log/journal" _PID=$pid --no-pager + done + fi + fi + + return $ret +} + check_result_nspawn() { local ret=1 + local journald_report="" + local pids="" [[ -e $TESTDIR/$1/testok ]] && ret=0 [[ -f $TESTDIR/$1/failed ]] && cp -a $TESTDIR/$1/failed $TESTDIR cp -a $TESTDIR/$1/var/log/journal $TESTDIR @@ -462,6 +522,7 @@ check_result_nspawn() { ls -l $TESTDIR/journal/*/*.journal test -s $TESTDIR/failed && ret=$(($ret+1)) [ -n "$TIMED_OUT" ] && ret=$(($ret+1)) + check_asan_reports "$TESTDIR/$1" || ret=$(($ret+1)) return $ret } @@ -473,6 +534,7 @@ check_result_qemu() { [[ -e $TESTDIR/root/testok ]] && ret=0 [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR cp -a $TESTDIR/root/var/log/journal $TESTDIR + check_asan_reports "$TESTDIR/root" || ret=$(($ret+1)) umount $TESTDIR/root [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed ls -l $TESTDIR/journal/*/*.journal @@ -508,7 +570,9 @@ install_execs() { sed -r -n 's|^Exec[a-zA-Z]*=[@+!-]*([^ ]+).*|\1|gp' $initdir/{$systemdsystemunitdir,$systemduserunitdir}/*.service \ | sort -u | while read i; do # some {rc,halt}.local scripts and programs are okay to not exist, the rest should - inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] + # also, plymouth is pulled in by rescue.service, but even there the exit code + # is ignored; as it's not present on some distros, don't fail if it doesn't exist + inst $i || [ "${i%.local}" != "$i" ] || [ "${i%systemd-update-done}" != "$i" ] || [ "/bin/plymouth" == "$i" ] done ) } @@ -1526,7 +1590,7 @@ test_run() { else dwarn "can't run systemd-nspawn, skipping" fi - fi + fi fi return 0 } diff --git a/test/test-network/conf/24-search-domain.network b/test/test-network/conf/24-search-domain.network index 970b130ab0..124af438a3 100644 --- a/test/test-network/conf/24-search-domain.network +++ b/test/test-network/conf/24-search-domain.network @@ -2,6 +2,6 @@ Name=dummy98 [Network] -Address=192.168.42.100 +Address=192.168.42.100/24 DNS=192.168.42.1 Domains= one two three four five six seven eight nine ten diff --git a/test/test-network/conf/25-address-section.network b/test/test-network/conf/25-address-section.network index d0fae69361..3904953443 100644 --- a/test/test-network/conf/25-address-section.network +++ b/test/test-network/conf/25-address-section.network @@ -1,6 +1,9 @@ [Match] Name=dummy98 +[Network] +IPv6AcceptRA=no + [Address] Address=10.2.3.4/16 Peer=10.2.3.5/16 @@ -9,3 +12,7 @@ Label=32 [Address] Address=10.6.7.8/16 Label=33 + +[Address] +Address=2001:db8::20 +Peer=2001:db8::10/128 diff --git a/test/test-network/conf/25-link-local-addressing-no.network b/test/test-network/conf/25-link-local-addressing-no.network new file mode 100644 index 0000000000..8320414d9e --- /dev/null +++ b/test/test-network/conf/25-link-local-addressing-no.network @@ -0,0 +1,5 @@ +[Match] +Name=dummy98 + +[Network] +LinkLocalAddressing=no diff --git a/test/test-network/conf/25-link-local-addressing-yes.network b/test/test-network/conf/25-link-local-addressing-yes.network new file mode 100644 index 0000000000..dcf2f2f7b1 --- /dev/null +++ b/test/test-network/conf/25-link-local-addressing-yes.network @@ -0,0 +1,5 @@ +[Match] +Name=test1 + +[Network] +LinkLocalAddressing=yes diff --git a/test/test-network/conf/25-route-ipv6-src.network b/test/test-network/conf/25-route-ipv6-src.network new file mode 100644 index 0000000000..4e551c024a --- /dev/null +++ b/test/test-network/conf/25-route-ipv6-src.network @@ -0,0 +1,16 @@ +# This test cannot use a dummy interface: IPv6 addresses +# are added without having to go through tentative state + +[Match] +Name=bond199 + +[Network] +LinkLocalAddressing=ipv6 +Address=2001:1234:56:8f63::1/64 +Address=2001:1234:56:8f63::2/64 +IPv6AcceptRA=no + +[Route] +Destination=abcd::/16 +Gateway=2001:1234:56:8f63::1:1 +PreferredSource=2001:1234:56:8f63::2 diff --git a/test/test-network/conf/25-wireguard-23-peers.netdev b/test/test-network/conf/25-wireguard-23-peers.netdev new file mode 100644 index 0000000000..7f77dc1743 --- /dev/null +++ b/test/test-network/conf/25-wireguard-23-peers.netdev @@ -0,0 +1,148 @@ +[NetDev] +Name=wg98 +Kind=wireguard +Description=For issue #11404 +# Generated by the script https://launchpadlibrarian.net/405947185/systemd-wg + +[WireGuard] +# 51820 is common port for Wireguard, 4500 is IPSec/UDP +ListenPort=4500 +PrivateKey=CJQUtcS9emY2fLYqDlpSZiE/QJyHkPWr+WHtZLZ90FU= + +# peer 1 +[WireGuardPeer] +PublicKey=TxVmU/YJ2R3G3cbGKUiIx02y6CgcKlElVGAkzrwJuXg= +AllowedIPs=fd8d:4d6d:3ccb:0500:0c79:2339:edce:ece1/128 +AllowedIPs=fd8d:4d6d:3ccb:0c79:2339:edce::/96 + +# peer 2 +[WireGuardPeer] +PublicKey=coGr5lLn1RsCeh1RWBXn1GvcDqKSQ82HSeN0GrUugHg= +AllowedIPs=fd8d:4d6d:3ccb:0500:a072:80da:de4f:add1/128 +AllowedIPs=fd8d:4d6d:3ccb:a072:80da:de4f::/96 + +# peer 3 +[WireGuardPeer] +PublicKey=PeiULTZjyfjqg/OOqnzKtLSWnrU+ipinqMsMw0hY+1w= +AllowedIPs=fd8d:4d6d:3ccb:0500:f349:c4f0:10c1:06b4/128 +AllowedIPs=fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 + +# peer 4 +[WireGuardPeer] +PublicKey=PjdC8+BmQPdgheY7gle9s3gvM7r07L6A+gMBe5bOZXk= +AllowedIPs=fd8d:4d6d:3ccb:0500:b684:4f81:2e3e:132e/128 +AllowedIPs=fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 + +# peer 5 +[WireGuardPeer] +PublicKey=1MGQurlRaQIAgdH/sd0qDNamDKAepMy/+pzZUx9oEDI= +AllowedIPs=fd8d:4d6d:3ccb:0500:c624:6bf7:4c09:3b59/128 +AllowedIPs=fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 + +# peer 6 +[WireGuardPeer] +PublicKey=+FgzhoGfPIzNBvtIZfBwNtWls2FSGt/6Kve3M9Z1ZlE= +AllowedIPs=fd8d:4d6d:3ccb:0500:9c11:d820:2e96:9be0/128 +AllowedIPs=fd8d:4d6d:3ccb:9c11:d820:2e96::/96 + +# peer 7 +[WireGuardPeer] +PublicKey=Kb2ozFhzg9huKmV4miLlWgh05ToP+xVqd2N0e7Ebmyc= +AllowedIPs=fd8d:4d6d:3ccb:0500:bad5:495d:8e9c:3427/128 +AllowedIPs=fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 + +# peer 8 +[WireGuardPeer] +PublicKey=p2kY786d4vFO/PpstaQrn7UPuakoHRABUHmcDKzXVi4= +AllowedIPs=fd8d:4d6d:3ccb:0500:1e54:1415:35d0:a47c/128 +AllowedIPs=fd8d:4d6d:3ccb:1e54:1415:35d0::/96 + +# peer 9 +[WireGuardPeer] +PublicKey=FNiQqmeizNXTmd9jEU/gvNkuEs1MoWovNp8IpPkoqz4= +AllowedIPs=fd8d:4d6d:3ccb:0500:1dbf:ca8a:32d3:dd81/128 +AllowedIPs=fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 + +# peer 10 +[WireGuardPeer] +PublicKey=wAwyAuLSQTO7lwQnUQHTumrMgkwigIExGR26AthWTU8= +AllowedIPs=fd8d:4d6d:3ccb:0500:dcdd:d33b:90c9:6088/128 +AllowedIPs=fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 + +# peer 11 +[WireGuardPeer] +PublicKey=8gRYdXRyhgjiMSbqk3sj5kzXGsQqkZ4defvK2ONqHA0= +AllowedIPs=fd8d:4d6d:3ccb:0500:6f2e:6888:c6fd:dfb9/128 +AllowedIPs=fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 + +# peer 12 +[WireGuardPeer] +PublicKey=4Bj9Dalwnq2Trf5Bl7iJCpSOaxC83YEbxgrgBl0ljQk= +AllowedIPs=fd8d:4d6d:3ccb:0500:d4f9:05dc:9296:0a1a/128 +AllowedIPs=fd8d:4d6d:3ccb:d4f9:05dc:9296::/96 + +# peer 13 +[WireGuardPeer] +PublicKey=BOTxUDlPSIzYucVmML4IYcTIaX0TiqC7DOnfLUI7RRg= +AllowedIPs=fd8d:4d6d:3ccb:0500:b39c:9cdc:755a:ead3/128 +AllowedIPs=fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 + +# peer 14 +[WireGuardPeer] +PublicKey=PiqEvBzow5vElGD2uOtRtZG6G60tM82kmjbyJP02mFQ= +AllowedIPs=fd8d:4d6d:3ccb:0500:bfe5:c3c3:5d77:0fcb/128 +AllowedIPs=fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 + +# peer 15 +[WireGuardPeer] +PublicKey=Eor9QBsIoUG6C3ZKsKdqm4Vkt0n2N7qpSh2LzphQeho= +AllowedIPs=fd8d:4d6d:3ccb:0500:900c:d437:ec27:8822/128 +AllowedIPs=fd8d:4d6d:3ccb:900c:d437:ec27::/96 + +# peer 16 +[WireGuardPeer] +PublicKey=acXPW0Ar+TiTOqKuUDpop9AVLuPNdzqf0l+V8k5t7CM= +AllowedIPs=fd8d:4d6d:3ccb:0500:270d:b5dd:4a3f:8909/128 +AllowedIPs=fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 + +# peer 17 +[WireGuardPeer] +PublicKey=+0g/5jzbitHyfhB4gbJnWrhSMsSjCcOE2rftWTDEW3E= +AllowedIPs=fd8d:4d6d:3ccb:0500:e2e1:ae15:103f:f376/128 +AllowedIPs=fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 + +# peer 18 +[WireGuardPeer] +PublicKey=FC7mjuWpkM8bjM3vaLPbba2HwHGbTSDK9QsLEZvUZ2I= +AllowedIPs=fd8d:4d6d:3ccb:0500:5660:679d:3532:94d8/128 +AllowedIPs=fd8d:4d6d:3ccb:5660:679d:3532::/96 + +# peer 19 +[WireGuardPeer] +PublicKey=fRdm/tbE2jGuLd6zMxSQYMP6pPfMmXYW84TUPJCPjHM= +AllowedIPs=fd8d:4d6d:3ccb:0500:6825:573f:30f3:9472/128 +AllowedIPs=fd8d:4d6d:3ccb:6825:573f:30f3::/96 + +# peer 20 +[WireGuardPeer] +PublicKey=xm540z0UwfTF5f0YwfjmCX0eGdHY8bOb/4ovVA2SgCI= +AllowedIPs=fd8d:4d6d:3ccb:0500:a94b:cd6a:a32d:90e6/128 +AllowedIPs=fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 + +# peer 21 +[WireGuardPeer] +PublicKey=5X5+9IiRBjaadazEKNO+CozpomiKPMIBQT7uJ4SnbVs= +AllowedIPs=fd8d:4d6d:3ccb:0500:8d4d:0bab:7280:a09a/128 +AllowedIPs=fd8d:4d6d:3ccb:8d4d:0bab:7280::/96 + +# peer 22 +[WireGuardPeer] +PublicKey=d61T4K0wmS4Z3lK9M8/Z48IXzldLCOCm7a6Mx1r/A3I= +AllowedIPs=fd8d:4d6d:3ccb:0500:a3f3:df38:19b0:0721/128 +AllowedIPs=fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 + +# peer 23 +[WireGuardPeer] +PublicKey=Nt7N3hXfpMWsIsx9me4ID77okka+0Oe5eqnFDp00IFI= +AllowedIPs=fd8d:4d6d:3ccb:0500:9742:9931:5217:18d5/128 +AllowedIPs=fd8d:4d6d:3ccb:9742:9931:5217::/96 diff --git a/test/test-network/conf/25-wireguard-23-peers.network b/test/test-network/conf/25-wireguard-23-peers.network new file mode 100644 index 0000000000..4dc87f8d4c --- /dev/null +++ b/test/test-network/conf/25-wireguard-23-peers.network @@ -0,0 +1,97 @@ +[Match] +Name=wg98 + +[Network] +Address=fd8d:4d6d:3ccb:0500::1/64 + +# nat64 via 1 +[Route] +Destination = fd8d:4d6d:3ccb:0c79:2339:edce::/96 + +# nat64 via 2 +[Route] +Destination = fd8d:4d6d:3ccb:a072:80da:de4f::/96 + +# nat64 via 3 +[Route] +Destination = fd8d:4d6d:3ccb:f349:c4f0:10c1::/96 + +# nat64 via 4 +[Route] +Destination = fd8d:4d6d:3ccb:b684:4f81:2e3e::/96 + +# nat64 via 5 +[Route] +Destination = fd8d:4d6d:3ccb:c624:6bf7:4c09::/96 + +# nat64 via 6 +[Route] +Destination = fd8d:4d6d:3ccb:9c11:d820:2e96::/96 + +# nat64 via 7 +[Route] +Destination = fd8d:4d6d:3ccb:bad5:495d:8e9c::/96 + +# nat64 via 8 +[Route] +Destination = fd8d:4d6d:3ccb:1e54:1415:35d0::/96 + +# nat64 via 9 +[Route] +Destination = fd8d:4d6d:3ccb:1dbf:ca8a:32d3::/96 + +# nat64 via 10 +[Route] +Destination = fd8d:4d6d:3ccb:dcdd:d33b:90c9::/96 + +# nat64 via 11 +[Route] +Destination = fd8d:4d6d:3ccb:6f2e:6888:c6fd::/96 + +# nat64 via 12 +[Route] +Destination = fd8d:4d6d:3ccb:d4f9:05dc:9296::/96 + +# nat64 via 13 +[Route] +Destination = fd8d:4d6d:3ccb:b39c:9cdc:755a::/96 + +# nat64 via 14 +[Route] +Destination = fd8d:4d6d:3ccb:bfe5:c3c3:5d77::/96 + +# nat64 via 15 +[Route] +Destination = fd8d:4d6d:3ccb:900c:d437:ec27::/96 + +# nat64 via 16 +[Route] +Destination = fd8d:4d6d:3ccb:270d:b5dd:4a3f::/96 + +# nat64 via 17 +[Route] +Destination = fd8d:4d6d:3ccb:e2e1:ae15:103f::/96 + +# nat64 via 18 +[Route] +Destination = fd8d:4d6d:3ccb:5660:679d:3532::/96 + +# nat64 via 19 +[Route] +Destination = fd8d:4d6d:3ccb:6825:573f:30f3::/96 + +# nat64 via 20 +[Route] +Destination = fd8d:4d6d:3ccb:a94b:cd6a:a32d::/96 + +# nat64 via 21 +[Route] +Destination = fd8d:4d6d:3ccb:8d4d:0bab:7280::/96 + +# nat64 via 22 +[Route] +Destination = fd8d:4d6d:3ccb:a3f3:df38:19b0::/96 + +# nat64 via 23 +[Route] +Destination = fd8d:4d6d:3ccb:9742:9931:5217::/96 diff --git a/test/test-network/conf/25-wireguard.netdev b/test/test-network/conf/25-wireguard.netdev index 01c5f2a28d..4866c31cca 100644 --- a/test/test-network/conf/25-wireguard.netdev +++ b/test/test-network/conf/25-wireguard.netdev @@ -10,6 +10,7 @@ FwMark=1234 [WireGuardPeer] PublicKey=RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA= AllowedIPs=fd31:bf08:57cb::/48,192.168.26.0/24 -Endpoint=wireguard.example.com:51820 +#Endpoint=wireguard.example.com:51820 +Endpoint=192.168.27.3:51820 PresharedKey=IIWIV17wutHv7t4cR6pOT91z6NSz/T8Arh0yaywhw3M= PersistentKeepalive=20 diff --git a/test/test-network/conf/dhcp-server-veth-peer.network b/test/test-network/conf/dhcp-server-veth-peer.network index 7b38e72b7e..33d8be3964 100644 --- a/test/test-network/conf/dhcp-server-veth-peer.network +++ b/test/test-network/conf/dhcp-server-veth-peer.network @@ -2,5 +2,5 @@ Name=veth-peer [Network] -Address=2600::1 +Address=2600::1/0 Address=192.168.5.1/24 diff --git a/test/test-network/conf/dhcp-v4-server-veth-peer.network b/test/test-network/conf/dhcp-v4-server-veth-peer.network index 5c91d65432..3dfc5290ad 100644 --- a/test/test-network/conf/dhcp-v4-server-veth-peer.network +++ b/test/test-network/conf/dhcp-v4-server-veth-peer.network @@ -2,5 +2,5 @@ Name=veth-peer [Network] -Address=192.168.0.1 -Address=192.168.5.1 +Address=192.168.0.1/24 +Address=192.168.5.1/24 diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 19572be151..1fc7094d28 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -9,7 +9,6 @@ import signal import socket import subprocess import sys -import threading import time import unittest from shutil import copytree @@ -20,7 +19,6 @@ networkd_ci_path='/run/networkd-ci' network_sysctl_ipv6_path='/proc/sys/net/ipv6/conf' network_sysctl_ipv4_path='/proc/sys/net/ipv4/conf' -dnsmasq_config_file='/run/networkd-ci/test-dnsmasq.conf' dnsmasq_pid_file='/run/networkd-ci/test-test-dnsmasq.pid' dnsmasq_log_file='/run/networkd-ci/test-dnsmasq-log-file' @@ -37,6 +35,39 @@ def expectedFailureIfModuleIsNotAvailable(module_name): return f +def expectedFailureIfERSPANModuleIsNotAvailable(): + def f(func): + rc = subprocess.call(['ip', 'link', 'add', 'dev', 'erspan99', 'type', 'erspan', 'seq', 'key', '30', 'local', '192.168.1.4', 'remote', '192.168.1.1', 'erspan_ver', '1', 'erspan', '123']) + if rc == 0: + subprocess.call(['ip', 'link', 'del', 'erspan99']) + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfRoutingPolicyPortRangeIsNotAvailable(): + def f(func): + rc = subprocess.call(['ip', 'rule', 'add', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7']) + if rc == 0: + subprocess.call(['ip', 'rule', 'del', 'from', '192.168.100.19', 'sport', '1123-1150', 'dport', '3224-3290', 'table', '7']) + return func + else: + return unittest.expectedFailure(func) + + return f + +def expectedFailureIfRoutingPolicyIPProtoIsNotAvailable(): + def f(func): + rc = subprocess.call(['ip', 'rule', 'add', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7']) + if rc == 0: + subprocess.call(['ip', 'rule', 'del', 'not', 'from', '192.168.100.19', 'ipproto', 'tcp', 'table', '7']) + return func + else: + return unittest.expectedFailure(func) + + return f + def setUpModule(): os.makedirs(network_unit_file_path, exist_ok=True) @@ -100,8 +131,9 @@ class Utilities(): if (os.path.exists(os.path.join(network_unit_file_path, unit + '.d'))): shutil.rmtree(os.path.join(network_unit_file_path, unit + '.d')) - def start_dnsmasq(self): - subprocess.check_call('dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5', shell=True) + def start_dnsmasq(self, additional_options=''): + dnsmasq_command = 'dnsmasq -8 /var/run/networkd-ci/test-dnsmasq-log-file --log-queries=extra --log-dhcp --pid-file=/var/run/networkd-ci/test-test-dnsmasq.pid --conf-file=/dev/null --interface=veth-peer --enable-ra --dhcp-range=2600::10,2600::20 --dhcp-range=192.168.5.10,192.168.5.200 -R --dhcp-leasefile=/var/run/networkd-ci/lease --dhcp-option=26,1492 --dhcp-option=option:router,192.168.5.1 --dhcp-option=33,192.168.5.4,192.168.5.5 --port=0 ' + additional_options + subprocess.check_call(dnsmasq_command, shell=True) time.sleep(10) @@ -144,33 +176,6 @@ class Utilities(): time.sleep(5) print() -global ip -global port - -class DHCPServer(threading.Thread): - def __init__(self, name): - threading.Thread.__init__(self) - self.name = name - - def run(self): - self.start_dhcp_server() - - def start_dhcp_server(self): - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - - server_address = ('0.0.0.0', 67) - sock.bind(server_address) - - print('Starting DHCP Server ...\n') - data, addr = sock.recvfrom(1024) # buffer size is 1024 bytes - - global ip - ip = addr[0] - - global port - port = addr[1] - sock.close() - class NetworkdNetDevTests(unittest.TestCase, Utilities): links =[ @@ -201,6 +206,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): 'vti6tun99', 'vtitun99', 'vxlan99', + 'wg98', 'wg99'] units = [ @@ -234,6 +240,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): '25-vti6-tunnel.netdev', '25-vti-tunnel.netdev', '25-vxlan.netdev', + '25-wireguard-23-peers.netdev', + '25-wireguard-23-peers.network', '25-wireguard.netdev', '6rd.network', 'gre.network', @@ -388,9 +396,29 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): if shutil.which('wg'): subprocess.call('wg') + output = subprocess.check_output(['wg', 'show', 'wg99', 'listen-port']).rstrip().decode('utf-8') + self.assertTrue(output, '51820') + output = subprocess.check_output(['wg', 'show', 'wg99', 'fwmark']).rstrip().decode('utf-8') + self.assertTrue(output, '0x4d2') + output = subprocess.check_output(['wg', 'show', 'wg99', 'allowed-ips']).rstrip().decode('utf-8') + self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.26.0/24 fd31:bf08:57cb::/48') + output = subprocess.check_output(['wg', 'show', 'wg99', 'persistent-keepalive']).rstrip().decode('utf-8') + self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t20') + output = subprocess.check_output(['wg', 'show', 'wg99', 'endpoints']).rstrip().decode('utf-8') + self.assertTrue(output, 'RDf+LSpeEre7YEIKaxg+wbpsNV7du+ktR99uBEtIiCA=\t192.168.27.3:51820') self.assertTrue(self.link_exits('wg99')) + @expectedFailureIfModuleIsNotAvailable('wireguard') + def test_wireguard_23_peers(self): + self.copy_unit_to_networkd_unit_path('25-wireguard-23-peers.netdev', '25-wireguard-23-peers.network') + self.start_networkd() + + if shutil.which('wg'): + subprocess.call('wg') + + self.assertTrue(self.link_exits('wg98')) + def test_geneve(self): self.copy_unit_to_networkd_unit_path('25-geneve.netdev') self.start_networkd() @@ -478,6 +506,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities): self.assertTrue(self.link_exits('dummy98')) self.assertTrue(self.link_exits('sittun99')) + @expectedFailureIfERSPANModuleIsNotAvailable() def test_erspan_tunnel(self): self.copy_unit_to_networkd_unit_path('25-erspan-tunnel.netdev') self.start_networkd() @@ -536,9 +565,12 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): '25-fibrule-port-range.network', '25-ipv6-address-label-section.network', '25-neighbor-section.network', + '25-link-local-addressing-no.network', + '25-link-local-addressing-yes.network', '25-link-section-unmanaged.network', '25-route-gateway.network', '25-route-gateway-on-link.network', + '25-route-ipv6-src.network', '25-route-reverse-order.network', '25-route-section.network', '25-route-tcp-window-settings.network', @@ -618,6 +650,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): subprocess.call(['ip', 'rule', 'del', 'table', '7']) + @expectedFailureIfRoutingPolicyPortRangeIsNotAvailable() def test_routing_policy_rule_port_range(self): self.copy_unit_to_networkd_unit_path('25-fibrule-port-range.network', '11-dummy.netdev') self.start_networkd() @@ -635,6 +668,7 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): subprocess.call(['ip', 'rule', 'del', 'table', '7']) + @expectedFailureIfRoutingPolicyIPProtoIsNotAvailable() def test_routing_policy_rule_invert(self): self.copy_unit_to_networkd_unit_path('25-fibrule-invert.network', '11-dummy.netdev') self.start_networkd() @@ -650,6 +684,22 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): subprocess.call(['ip', 'rule', 'del', 'table', '7']) + def test_address_peer(self): + self.copy_unit_to_networkd_unit_path('25-address-section.network', '12-dummy.netdev') + self.start_networkd() + + self.assertTrue(self.link_exits('dummy98')) + + output = subprocess.check_output(['ip', 'address', 'show', 'dummy98']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'inet 10.2.3.4 peer 10.2.3.5/16 scope global 32') + self.assertRegex(output, 'inet 10.6.7.8/16 brd 10.6.255.255 scope global 33') + self.assertRegex(output, 'inet6 2001:db8::20 peer 2001:db8::10/128 scope global') + + output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'State: routable \(configured\)') + def test_address_preferred_lifetime_zero_ipv6(self): self.copy_unit_to_networkd_unit_path('25-address-section-miscellaneous.network', '12-dummy.netdev') self.start_networkd() @@ -756,6 +806,22 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): self.assertRegex(output, 'scope') self.assertRegex(output, 'link') + def test_ip_route_ipv6_src_route(self): + # a dummy device does not make the addresses go through tentative state, so we + # reuse a bond from an earlier test, which does make the addresses go through + # tentative state, and do our test on that + self.copy_unit_to_networkd_unit_path('23-active-slave.network', '25-route-ipv6-src.network', '25-bond-active-backup-slave.netdev', '12-dummy.netdev') + self.start_networkd() + + self.assertTrue(self.link_exits('dummy98')) + self.assertTrue(self.link_exits('bond199')) + + output = subprocess.check_output(['ip', '-6', 'route', 'list', 'dev', 'bond199']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'abcd::/16') + self.assertRegex(output, 'src') + self.assertRegex(output, '2001:1234:56:8f63::2') + def test_ip_link_mac_address(self): self.copy_unit_to_networkd_unit_path('25-address-link-section.network', '12-dummy.netdev') self.start_networkd() @@ -795,7 +861,67 @@ class NetworkdNetWorkTests(unittest.TestCase, Utilities): output = subprocess.check_output(['ip', 'neigh', 'list']).rstrip().decode('utf-8') print(output) self.assertRegex(output, '192.168.10.1.*00:00:5e:00:02:65.*PERMANENT') - self.assertRegex(output, '2004:da8:1:0::1.*00:00:5e:00:02:66.*PERMANENT') + self.assertRegex(output, '2004:da8:1::1.*00:00:5e:00:02:66.*PERMANENT') + + def test_link_local_addressing(self): + self.copy_unit_to_networkd_unit_path('25-link-local-addressing-yes.network', '11-dummy.netdev', + '25-link-local-addressing-no.network', '12-dummy.netdev') + self.start_networkd() + + self.assertTrue(self.link_exits('test1')) + self.assertTrue(self.link_exits('dummy98')) + + time.sleep(10) + + output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'test1']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'inet .* scope link') + self.assertRegex(output, 'inet6 .* scope link') + + output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'dummy98']).rstrip().decode('utf-8') + print(output) + self.assertNotRegex(output, 'inet6* .* scope link') + + output = subprocess.check_output(['networkctl', 'status', 'test1']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'State: degraded \(configured\)') + + output = subprocess.check_output(['networkctl', 'status', 'dummy98']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, 'State: carrier \(configured\)') + + ''' + Documentation/networking/ip-sysctl.txt + + addr_gen_mode - INTEGER + Defines how link-local and autoconf addresses are generated. + + 0: generate address based on EUI64 (default) + 1: do no generate a link-local address, use EUI64 for addresses generated + from autoconf + 2: generate stable privacy addresses, using the secret from + stable_secret (RFC7217) + 3: generate stable privacy addresses, using a random secret if unset + ''' + + test1_addr_gen_mode = '' + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')): + with open(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'stable_secret')) as f: + try: + f.readline() + except IOError: + # if stable_secret is unset, then EIO is returned + test1_addr_gen_mode = '0' + else: + test1_addr_gen_mode = '2' + else: + test1_addr_gen_mode = '0' + + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'test1'), 'addr_gen_mode')): + self.assertEqual(self.read_ipv6_sysctl_attr('test1', 'addr_gen_mode'), '0') + + if os.path.exists(os.path.join(os.path.join(network_sysctl_ipv6_path, 'dummy98'), 'addr_gen_mode')): + self.assertEqual(self.read_ipv6_sysctl_attr('dummy98', 'addr_gen_mode'), '1') def test_sysctl(self): self.copy_unit_to_networkd_unit_path('25-sysctl.network', '12-dummy.netdev') @@ -954,7 +1080,7 @@ class NetworkdNetworkDHCPServerTests(unittest.TestCase, Utilities): self.assertRegex(output, 'NTP: 192.168.5.1') def test_domain(self): - self.copy_unit_to_networkd_unit_path( '12-dummy.netdev', '24-search-domain.network') + self.copy_unit_to_networkd_unit_path('12-dummy.netdev', '24-search-domain.network') self.start_networkd() self.assertTrue(self.link_exits('dummy98')) @@ -994,8 +1120,10 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): 'dhcp-client-listen-port.network', 'dhcp-client-route-metric.network', 'dhcp-client-route-table.network', + 'dhcp-client.network', 'dhcp-server-veth-peer.network', - 'dhcp-v4-server-veth-peer.network'] + 'dhcp-v4-server-veth-peer.network', + 'static.network'] def setUp(self): self.link_remove(self.links) @@ -1009,7 +1137,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): self.remove_log_file() def test_dhcp_client_ipv6_only(self): - self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv6-only.network') + self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv6-only.network') self.start_networkd() self.assertTrue(self.link_exits('veth99')) @@ -1022,7 +1150,7 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): self.assertNotRegex(output, '192.168.5') def test_dhcp_client_ipv4_only(self): - self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network','dhcp-client-ipv4-only-ipv6-disabled.network') + self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-ipv4-only-ipv6-disabled.network') self.start_networkd() self.assertTrue(self.link_exits('veth99')) @@ -1111,21 +1239,15 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): def test_dhcp_client_listen_port(self): self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client-listen-port.network') - - dh_server = DHCPServer("dhcp_server") - dh_server.start() - self.start_networkd() self.assertTrue(self.link_exits('veth99')) - global port - global ip - - self.assertRegex(str(port), '5555') - self.assertRegex(str(ip), '0.0.0.0') + self.start_dnsmasq('--dhcp-alternate-port=67,5555') - dh_server.join() + output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, '192.168.5.* dynamic') def test_dhcp_route_table_id(self): self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-v4-server-veth-peer.network', 'dhcp-client-route-table.network') @@ -1174,6 +1296,43 @@ class NetworkdNetworkDHCPClientTests(unittest.TestCase, Utilities): print(output) self.assertRegex(output, '192.168.5.*') + def test_dhcp_client_reuse_address_as_static(self): + self.copy_unit_to_networkd_unit_path('25-veth.netdev', 'dhcp-server-veth-peer.network', 'dhcp-client.network') + self.start_networkd() + + self.assertTrue(self.link_exits('veth99')) + + self.start_dnsmasq() + + output = subprocess.check_output(['ip', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, '192.168.5') + self.assertRegex(output, '2600::') + + ipv4_address = re.search('192\.168\.5\.[0-9]*/24', output) + ipv6_address = re.search('2600::[0-9a-f:]*/128', output) + static_network = '\n'.join(['[Match]', 'Name=veth99', '[Network]', 'IPv6AcceptRA=no', 'Address=' + ipv4_address.group(), 'Address=' + ipv6_address.group()]) + print(static_network) + + self.remove_unit_from_networkd_path(['dhcp-client.network']) + + with open(os.path.join(network_unit_file_path, 'static.network'), mode='w') as f: + f.write(static_network) + + self.start_networkd() + + self.assertTrue(self.link_exits('veth99')) + + output = subprocess.check_output(['ip', '-4', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, '192.168.5') + self.assertRegex(output, 'valid_lft forever preferred_lft forever') + + output = subprocess.check_output(['ip', '-6', 'address', 'show', 'dev', 'veth99', 'scope', 'global']).rstrip().decode('utf-8') + print(output) + self.assertRegex(output, '2600::') + self.assertRegex(output, 'valid_lft forever preferred_lft forever') + if __name__ == '__main__': unittest.main(testRunner=unittest.TextTestRunner(stream=sys.stdout, verbosity=3)) |