diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist index 2159b24978c0..a909ea3714d3 100644 --- a/etc/mtree/BSD.tests.dist +++ b/etc/mtree/BSD.tests.dist @@ -1,1223 +1,1225 @@ # # Please see the file src/etc/mtree/README before making changes to this file. # /set type=dir uname=root gname=wheel mode=0755 tags=package=tests . bin cat .. chflags .. chmod .. cp .. date .. dd .. echo .. expr .. hostname .. ln .. ls .. mkdir .. mv .. pax .. pkill .. pwait .. rm .. rmdir .. sh builtins .. errors .. execution .. expansion .. invocation .. parameters .. parser .. set-e .. .. sleep .. test .. timeout .. .. cddl lib .. sbin .. usr.bin ctfconvert .. ztest .. .. usr.sbin dtrace common aggs .. arithmetic .. arrays .. assocs .. begin .. bitfields .. buffering .. builtinvar .. cg .. clauses .. cpc .. decls .. drops .. dtraceUtil .. end .. env .. enum .. error .. exit .. fbtprovider .. funcs .. grammar .. include .. inline .. io .. ip .. java_api .. json .. kinst .. lexer .. llquantize .. mdb .. mib .. misc .. multiaggs .. offsetof .. oformat .. operators .. pid .. plockstat .. pointers .. pragma .. predicates .. preprocessor .. print .. printa .. printf .. privs .. probes .. proc .. profile-n .. providers .. raise .. rates .. safety .. scalars .. sched .. scripting .. sdt .. sizeof .. speculation .. stability .. stack .. stackdepth .. stop .. strlen .. strtoll .. struct .. sugar .. syscall .. sysevent .. tick-n .. trace .. tracemem .. translators .. typedef .. types .. uctf .. union .. usdt .. ustack .. vars .. version .. .. i386 arrays .. funcs .. pid .. ustack .. .. amd64 arrays .. .. .. zfsd .. .. .. etc rc.d .. .. examples .. games .. gnu lib .. usr.bin diff .. .. .. include .. lib atf libatf-c detail .. .. libatf-c++ detail .. .. test-programs .. .. csu dynamic .. dynamiclib .. static .. .. googletest gmock .. gmock_main .. gtest .. gtest_main .. .. libarchive .. libbe .. libc c063 .. db .. gen execve .. posix_spawn .. .. hash data .. .. iconv .. inet .. locale .. net getaddrinfo data .. .. .. nss .. regex data .. .. resolv .. rpc .. ssp .. setjmp .. stdio .. stdlib .. stdtime .. string .. sys .. time .. tls dso .. .. termios .. ttyio .. .. libcam .. libcasper services cap_dns .. cap_grp .. cap_pwd .. cap_sysctl .. .. .. libcrypt .. libdevdctl .. libexecinfo .. libkvm .. libmp .. libnv .. libproc .. libregex data .. .. librt .. libsbuf .. libsysdecode .. libthr dlopen .. .. libutil .. libxo .. msun .. .. libexec atf atf-check .. atf-pytest-wrapper .. atf-sh .. .. nuageinit .. rc .. rtld-elf rtld_deepbind .. .. tftpd .. .. sbin bectl .. dhclient .. devd .. growfs .. ifconfig .. ipfw .. md5 .. mdconfig .. newfs_msdos .. nvmecontrol .. pfctl files .. .. ping .. route .. savecore .. sysctl .. .. secure lib .. libexec .. usr.bin .. usr.sbin .. .. share examples tests atf .. googletest .. plain .. tap .. .. .. zoneinfo .. .. sys acl .. aio .. audit .. auditpipe .. cam ctl .. .. capsicum .. cddl zfs bin .. include .. tests acl cifs .. nontrivial .. trivial .. .. atime .. bootfs .. cache .. cachefile .. clean_mirror .. cli_root zfs_upgrade .. zfs_promote .. zfs_clone .. zfs_property .. zfs_destroy .. zpool_create .. zpool_history .. zpool_expand .. zpool_remove .. zfs_mount .. zfs_unshare .. zdb .. zpool_online .. zpool_get .. zpool_export .. zfs_copies .. zfs_get .. zfs .. zpool_clear .. zpool_import blockfiles .. .. zpool .. zpool_offline .. zpool_replace .. zfs_rollback .. zpool_set .. zfs_send .. zfs_set .. zpool_detach .. zfs_diff .. zpool_scrub .. zfs_inherit .. zfs_snapshot .. zfs_share .. zpool_destroy .. zpool_status .. zfs_unmount .. zfs_receive .. zfs_create .. zpool_upgrade blockfiles .. .. zpool_add .. zfs_rename .. zpool_attach .. zfs_reservation .. .. cli_user misc .. zfs_list .. zpool_iostat .. zpool_list .. .. compression .. ctime .. delegate .. devices .. exec .. grow_pool .. grow_replicas .. history .. hotplug .. hotspare .. inheritance .. interop .. inuse .. iscsi .. large_files .. largest_pool .. link_count .. migration .. mmap .. mount .. mv_files .. nestedfs .. no_space .. online_offline .. pool_names .. poolversion .. quota .. redundancy .. refquota .. refreserv .. rename_dirs .. replacement .. reservation .. rootpool .. rsend .. scrub_mirror .. slog .. snapshot .. snapused .. sparse .. threadsappend .. truncate .. txg_integrity .. userquota .. utils_test .. write_dirs .. xattr .. zfsd .. zil .. zinject .. zones .. zvol zvol_ENOSPC .. zvol_cli .. zvol_misc .. zvol_swap .. .. zvol_thrash .. .. .. .. compat32 .. devrandom .. dtrace .. fifo .. file .. fs fusefs .. tarfs .. tmpfs .. .. geom class concat .. eli .. gate .. gpt .. mirror .. multipath .. nop .. part .. raid3 .. shsec .. stripe .. uzip etalon .. .. .. .. kern acct .. execve .. pipe .. .. kqueue libkqueue .. .. mac bsdextended .. ipacl .. portacl .. .. mqueue .. net if_ovpn .. routing .. .. netgraph .. netinet .. netinet6 frag6 .. .. netipsec tunnel .. .. netlink .. netmap .. netpfil common .. ipfw .. pf ioctl .. .. .. opencrypto .. pjdfstest chflags .. chmod .. chown .. ftruncate .. granular .. link .. mkdir .. mkfifo .. mknod .. open .. rename .. rmdir .. symlink .. truncate .. unlink .. utimensat .. .. posixshm .. sound .. sys .. vfs .. vm stack .. .. vmm .. .. usr.bin apply .. asa .. awk bugs-fixed .. netbsd .. .. basename .. bintrans .. bmake archives fmt_44bsd .. fmt_44bsd_mod .. fmt_oldbsd .. .. basic t0 .. t1 .. t2 .. t3 .. .. execution ellipsis .. empty .. joberr .. plus .. .. shell builtin .. meta .. path .. path_select .. replace .. select .. .. suffixes basic .. src_wild1 .. src_wild2 .. .. syntax directive-t0 .. enl .. funny-targets .. semi .. .. sysmk t0 2 1 .. .. mk .. .. t1 2 1 .. .. mk .. .. t2 2 1 .. .. mk .. .. .. variables modifier_M .. modifier_t .. opt_V .. t0 .. .. .. bsdcat .. calendar .. cmp .. column .. compress .. cpio .. col .. comm .. csplit .. cut .. dc .. diff .. diff3 .. dirname .. du .. env .. factor .. file2c .. file .. find .. fold .. getconf .. gh-bc .. grep .. gzip .. head .. hexdump .. ident .. indent .. join .. jot .. lastcomm .. limits .. locale .. lockf .. lorder .. m4 .. mkimg .. mktemp .. ncal .. opensm .. patch .. pr .. printf .. procstat .. renice .. rs .. sdiff .. sed regress.multitest.out .. .. seq .. soelim .. sort .. split .. stat .. tail .. tar .. tee .. tftp .. touch .. tr .. truncate .. tsort .. units .. unifdef .. uniq .. unzip .. vmstat .. wc .. xargs .. xinstall .. xo .. yacc yacc .. .. .. usr.sbin chown .. ctladm .. daemon .. etcupdate .. extattr .. fstyp .. jail .. makefs .. mixer .. newsyslog .. nmtree .. praudit .. pw .. rpcbind .. sa .. syslogd .. + traceroute + .. .. .. # vim: set expandtab ts=4 sw=4: diff --git a/usr.sbin/traceroute/Makefile b/usr.sbin/traceroute/Makefile index 45a80174f5ab..b47e0e2bd55f 100644 --- a/usr.sbin/traceroute/Makefile +++ b/usr.sbin/traceroute/Makefile @@ -1,31 +1,34 @@ .include PACKAGE= runtime PROG= traceroute MAN= traceroute.8 SRCS= as.c traceroute.c ifaddrlist.c findsaddr-udp.c BINOWN= root BINMODE=4555 +HAS_TESTS= +SUBDIR.${MK_TESTS}+= tests + .if !defined(TRACEROUTE_NO_IPSEC) CFLAGS+= -DIPSEC .endif # RTT Jitter on the internet these days means printing 3 decimal places on # > 1000ms times is plain useless. Uncomment this to enable variable precision # reporting, ie: print a variable precision from 0.001ms through 1000ms # CFLAGS+= -DSANE_PRECISION .if !defined(TRACEROUTE_NO_IPSEC) LIBADD+= ipsec .endif .if ${MK_CASPER} != "no" LIBADD+= casper LIBADD+= cap_dns CFLAGS+=-DWITH_CASPER .endif WARNS?= 3 .include diff --git a/usr.sbin/traceroute/tests/Makefile b/usr.sbin/traceroute/tests/Makefile new file mode 100644 index 000000000000..7c3d6f777582 --- /dev/null +++ b/usr.sbin/traceroute/tests/Makefile @@ -0,0 +1,7 @@ +ATF_TESTS_SH+= traceroute_test + +# Allow tests to run in parallel in their own jails +TEST_METADATA+= execenv="jail" +TEST_METADATA+= execenv_jail_params="vnet allow.raw_sockets" + +.include diff --git a/usr.sbin/traceroute/tests/traceroute_test.sh b/usr.sbin/traceroute/tests/traceroute_test.sh new file mode 100755 index 000000000000..268e0bd58b5b --- /dev/null +++ b/usr.sbin/traceroute/tests/traceroute_test.sh @@ -0,0 +1,874 @@ +# SPDX-License-Identifier: ISC +# +# Copyright (c) 2025 Lexi Winter +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +# We are missing tests for the following flags: +# +# -a (turn on ASN lookups) +# -A (specify ASN lookup server) +# -d (enable SO_DEBUG) +# -D (print the diff between our packet and the quote in the ICMP error) +# -E (detect ECN bleaching) +# -n (or rather, we enable -n by default and don't test without it) +# -S (print per-hop packet loss) +# -v (verbose output) +# -w (how long to wait for an error response) +# -x (toggle IP checksums) +# -z (how long to wait between each probe) + +. $(atf_get_srcdir)/../../sys/common/vnet.subr + +# These are the default flags we use for most test cases: +# - only send a single probe packet to reduce the risk of kernel ICMP +# rate-limiting breaking the test. +# - only trace up to 5 hops and only wait 1 second for a response so the test +# fails quicker if something goes wrong. +# - disable DNS resolution as we don't usually care about this. +TR_FLAGS="-w 1 -q 1 -m 5 -n" + +# The prefix our test networks are in. +TEST_PREFIX="192.0.2.0/24" + +# The IPv4 addresses of the first link net between trsrc and trrtr. +LINK_TRSRC_TRSRC="192.0.2.5" +LINK_TRSRC_TRRTR="192.0.2.6" +LINK_TRSRC_PREFIXLEN="30" + +# The IPv4 addresses of the second link net between trsrc and trrtr. +LINK_TRSRC2_TRSRC="192.0.2.13" +LINK_TRSRC2_TRRTR="192.0.2.14" +LINK_TRSRC2_PREFIXLEN="30" + +# The IPv4 addresses of the link net between trdst and trrtr. +LINK_TRDST_TRDST="192.0.2.9" +LINK_TRDST_TRRTR="192.0.2.10" +LINK_TRDST_PREFIXLEN="30" + +# This is an address inside $TEST_PREFIX which is not routed anywhere. +UNREACHABLE_ADDR="192.0.2.255" + +setup_network() +{ + # Create 3 jails: one to be the source host, one to be the router, + # and one to be the destination host. + + vnet_init + + # src jail + epsrc=$(vnet_mkepair) + epsrc2=$(vnet_mkepair) + vnet_mkjail trsrc ${epsrc}a ${epsrc2}a + + # dst jail + epdst=$(vnet_mkepair) + vnet_mkjail trdst ${epdst}a + + # router jail + vnet_mkjail trrtr ${epsrc}b ${epsrc2}b ${epdst}b + + # Configure IPv4 addresses and routes on each jail. + + # trsrc + jexec trsrc ifconfig ${epsrc}a inet \ + ${LINK_TRSRC_TRSRC}/${LINK_TRSRC_PREFIXLEN} + jexec trrtr ifconfig ${epsrc}b inet \ + ${LINK_TRSRC_TRRTR}/${LINK_TRSRC_PREFIXLEN} + jexec trsrc route add -inet ${TEST_PREFIX} ${LINK_TRSRC_TRRTR} + + # trsrc2 + jexec trsrc ifconfig ${epsrc2}a inet \ + ${LINK_TRSRC2_TRSRC}/${LINK_TRSRC2_PREFIXLEN} + jexec trrtr ifconfig ${epsrc2}b inet \ + ${LINK_TRSRC2_TRRTR}/${LINK_TRSRC2_PREFIXLEN} + + # trdst + jexec trdst ifconfig ${epdst}a inet \ + ${LINK_TRDST_TRDST}/${LINK_TRDST_PREFIXLEN} + jexec trrtr ifconfig ${epdst}b inet \ + ${LINK_TRDST_TRRTR}/${LINK_TRDST_PREFIXLEN} + jexec trdst route add -inet ${TEST_PREFIX} ${LINK_TRDST_TRRTR} + + # The router jail (only) needs IP forwarding enabled. + jexec trrtr sysctl net.inet.ip.forwarding=1 +} + +## +# +# start_tcpdump, stop_tcpdump: used to capture packets during the test so we +# can verify we actually sent the expected packets. + +start_tcpdump() +{ + # Run tcpdump on trrtr, either on the given interface or on + # ${epsrc}b, which is trsrc's default route interface. + + interface="$1" + if [ -z "$interface" ]; then + interface="${epsrc}b" + fi + + rm -f "${PWD}/traceroute.pcap" + + jexec trrtr daemon -p "${PWD}/tcpdump.pid" \ + tcpdump --immediate-mode -w "${PWD}/traceroute.pcap" -nv \ + -i $interface + + # Give tcpdump time to start + sleep 1 +} + +stop_tcpdump() +{ + # Sleep to give tcpdump a chance to finish flushing + jexec trrtr kill -USR2 $(cat "${PWD}/tcpdump.pid") + sleep 1 + jexec trrtr kill $(cat "${PWD}/tcpdump.pid") + + # Format the packet capture and merge continued lines (starting with + # whitespace) into a single line; this makes it easier to match in + # atf_check. Append a blank line since the N command exits on EOF. + (tcpdump -nv -r "${PWD}/traceroute.pcap"; echo) | \ + sed -E -e :a -e N -e 's/\n +/ /' -e ta -e P -e D \ + > tcpdump.output +} + +## +# test: ipv4_basic +# + +atf_test_case "ipv4_basic" "cleanup" +ipv4_basic_head() +{ + atf_set descr "Basic IPv4 traceroute across a router" + atf_set require.user root +} + +ipv4_basic_body() +{ + setup_network + + # Use a more detailed set of regexp here than the rest of the tests to + # make sure the basic output format is correct. + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST} \\(${LINK_TRDST_TRDST}\\), 5 hops max, 40 byte packets$" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR} [0-9.]+ ms$" \ + -o match:"^ 2 ${LINK_TRDST_TRDST} [0-9.]+ ms$" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS ${LINK_TRDST_TRDST} +} + +ipv4_basic_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_icmp +# + +atf_test_case "ipv4_icmp" "cleanup" +ipv4_icmp_head() +{ + atf_set descr "Basic IPv4 ICMP traceroute across a router" + atf_set require.user root +} + +ipv4_icmp_body() +{ + setup_network + + # -I and -Picmp should mean the same thing, so test both. + + for icmp_flag in -Picmp -I; do + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS $icmp_flag \ + ${LINK_TRDST_TRDST} + + stop_tcpdump + + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto ICMP.*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ICMP echo request" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto ICMP.*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ICMP echo request" \ + cat tcpdump.output + done +} + +ipv4_icmp_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_udp +# + +atf_test_case "ipv4_udp" "cleanup" +ipv4_udp_head() +{ + atf_set descr "IPv4 UDP traceroute" + atf_set require.user root +} + +ipv4_udp_body() +{ + setup_network + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS -Pudp ${LINK_TRDST_TRDST} + + stop_tcpdump + + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ + cat tcpdump.output + + # Test with -e, the destination port should not increment. + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS -Pudp -e -p 40000 ${LINK_TRDST_TRDST} + + stop_tcpdump + + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: UDP" \ + cat tcpdump.output +} + +ipv4_udp_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_sctp +# + +atf_test_case "ipv4_sctp" "cleanup" +ipv4_sctp_head() +{ + atf_set descr "IPv4 SCTP traceroute" + atf_set require.user root +} + +ipv4_sctp_body() +{ + setup_network + + # For the default packet size, we should sent a SHUTDOWN ACK packet. + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + jexec trsrc traceroute $TR_FLAGS -Psctp ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: sctp \(1\) \[SHUTDOWN ACK\]" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: sctp \(1\) \[SHUTDOWN ACK\]" \ + cat tcpdump.output + + # For a larger packet size we should send INIT packets. + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + jexec trsrc traceroute $TR_FLAGS -Psctp ${LINK_TRDST_TRDST} 128 + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: sctp \(1\) \[INIT\]" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: sctp \(1\) \[INIT\]" \ + cat tcpdump.output + + # Test with -e, the destination port should not increment. + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + jexec trsrc traceroute $TR_FLAGS -Psctp -e -p 40000 ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: sctp \(1\) \[SHUTDOWN ACK\]" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: sctp \(1\) \[SHUTDOWN ACK\]" \ + cat tcpdump.output +} + +ipv4_sctp_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_tcp +# + +atf_test_case "ipv4_tcp" "cleanup" +ipv4_tcp_head() +{ + atf_set descr "IPv4 TCP traceroute" + atf_set require.user root +} + +ipv4_tcp_body() +{ + setup_network + + start_tcpdump + + # We expect the second hop to be a failure since traceroute doesn't + # know how to capture the RST packet. + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 \\*" \ + jexec trsrc traceroute $TR_FLAGS -Ptcp ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: Flags \[S\]" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: Flags \[S\]" \ + cat tcpdump.output + + # Test with -e, the destination port should not increment. + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 \\*" \ + jexec trsrc traceroute $TR_FLAGS -Ptcp -e -p 40000 ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: Flags \[S\]" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: Flags \[S\]" \ + cat tcpdump.output +} + +ipv4_tcp_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_srcaddr +# + +atf_test_case "ipv4_srcaddr" "cleanup" +ipv4_srcaddr_head() +{ + atf_set descr "IPv4 traceroute with explicit source address" + atf_set require.user root +} + +ipv4_srcaddr_body() +{ + setup_network + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST} \\($LINK_TRDST_TRDST\\) from ${LINK_TRSRC2_TRSRC}" \ + -o match:"^ 1 ${LINK_TRSRC2_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS \ + -s ${LINK_TRSRC2_TRSRC} ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ + cat tcpdump.output +} + +ipv4_srcaddr_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_srcinterface +# + +atf_test_case "ipv4_srcinterface" "cleanup" +ipv4_srcinterface_head() +{ + atf_set descr "IPv4 traceroute with explicit source interface" + atf_set require.user root +} + +ipv4_srcinterface_body() +{ + setup_network + + start_tcpdump + + # Unlike -s, traceroute doesn't print 'from ...' when using -i. + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC2_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS \ + -i ${epsrc2}a ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ + cat tcpdump.output +} + +ipv4_srcinterface_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_maxhops +# + +atf_test_case "ipv4_maxhops" "cleanup" +ipv4_maxhops_head() +{ + atf_set descr "IPv4 traceroute with -m" + atf_set require.user root +} + +ipv4_maxhops_body() +{ + setup_network + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o not-match:"^ 2" \ + jexec trsrc traceroute -w1 -q1 -m1 ${LINK_TRDST_TRDST} +} + +ipv4_maxhops_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_unreachable +# + +atf_test_case "ipv4_unreachable" "cleanup" +ipv4_unreachable_head() +{ + atf_set descr "IPv4 traceroute to an unreachable destination" + atf_set require.user root +} + +ipv4_unreachable_body() +{ + setup_network + + atf_check -s exit:0 \ + -e match:"^traceroute to ${UNREACHABLE_ADDR}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRSRC_TRRTR} [0-9.]+ ms !H" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS $UNREACHABLE_ADDR +} + +ipv4_unreachable_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_hugepacket +# + +atf_test_case "ipv4_hugepacket" "cleanup" +ipv4_hugepacket_head() +{ + atf_set descr "IPv4 traceroute with a huge packet" + atf_set require.user root +} + +ipv4_hugepacket_body() +{ + setup_network + + # We expect this to fail since we specified -F (don't fragment) and the + # 2000-byte packet is too large to fit through our tiny epair. Make + # sure traceroute reports the error. + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST} \\(${LINK_TRDST_TRDST}\\), 5 hops max, 2000 byte packets$" \ + -o match:"^ 1 traceroute: wrote ${LINK_TRDST_TRDST} 2000 chars, ret=-1" \ + -e match:"^traceroute: sendto: Message too long" \ + jexec trsrc traceroute -F $TR_FLAGS ${LINK_TRDST_TRDST} 2000 +} + +ipv4_hugepacket_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_firsthop +# + +atf_test_case "ipv4_firsthop" "cleanup" +ipv4_firsthop_head() +{ + atf_set descr "IPv4 traceroute with one hop skipped" + atf_set require.user root +} + +ipv4_firsthop_body() +{ + setup_network + + # -f 2 means we skip the first hop. For backward compatibility, -M is + # the same as -f, so test that too. + + for flag in -f2 -M2; do + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 1" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $flag $TR_FLAGS ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o not-match:"^..:..:..\....... IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\)" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ + cat tcpdump.output + done +} + +ipv4_firsthop_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_nprobes +# + +atf_test_case "ipv4_nprobes" "cleanup" +ipv4_nprobes_head() +{ + atf_set descr "IPv4 traceroute with varying number of probes" + atf_set require.user root +} + +ipv4_nprobes_body() +{ + setup_network + + # By default we should send 3 probes. + atf_check -s exit:0 -e ignore \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR} \(${LINK_TRSRC_TRRTR}\)( [0-9.]+ ms){3}$" \ + jexec trsrc traceroute -w1 -m1 ${LINK_TRDST_TRDST} + + # Also test 1 and 2 (below the default) and 5 (above the default) + for nprobes in 1 2 5; do + atf_check -s exit:0 -e ignore \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR} \(${LINK_TRSRC_TRRTR}\)( [0-9.]+ ms){$nprobes}$" \ + jexec trsrc traceroute -q$nprobes -w1 -m1 ${LINK_TRDST_TRDST} + done +} + +ipv4_nprobes_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_baseport +# + +atf_test_case "ipv4_baseport" "cleanup" +ipv4_baseport_head() +{ + atf_set descr "IPv4 traceroute with non-default base port" + atf_set require.user root +} + +ipv4_baseport_body() +{ + setup_network + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS -p 40000 \ + ${LINK_TRDST_TRDST} + + stop_tcpdump + + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40001: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40002: UDP" \ + cat tcpdump.output +} + +ipv4_baseport_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_gre +# + +atf_test_case "ipv4_gre" "cleanup" +ipv4_gre_head() +{ + atf_set descr "IPv4 GRE traceroute" + atf_set require.user root +} + +ipv4_gre_body() +{ + setup_network + + start_tcpdump + + # We expect the second hop to be a failure since the remote host will + # ignore the GRE packet. + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 \\*" \ + jexec trsrc traceroute $TR_FLAGS -Pgre ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto GRE .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: GREv1" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto GRE .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: GREv1" \ + cat tcpdump.output +} + +ipv4_gre_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_udplite +# + +atf_test_case "ipv4_udplite" "cleanup" +ipv4_udplite_head() +{ + atf_set descr "IPv4 UDP-Lite traceroute" + atf_set require.user root +} + +ipv4_udplite_body() +{ + setup_network + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS -Pudplite ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto unknown \(136\), .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ip-proto-136" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto unknown \(136\), .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ip-proto-136" \ + cat tcpdump.output +} + +ipv4_udplite_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_iptos +# + +atf_test_case "ipv4_iptos" "cleanup" +ipv4_iptos_head() +{ + atf_set descr "IPv4 traceroute with explicit ToS" + atf_set require.user root +} + +ipv4_iptos_body() +{ + setup_network + + start_tcpdump + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST}" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS -t 4 ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x4, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ + -o match:"IP \\(tos 0x4, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ + cat tcpdump.output +} + +ipv4_iptos_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_srcroute +# + +atf_test_case "ipv4_srcroute" "cleanup" +ipv4_srcroute_head() +{ + atf_set descr "IPv4 traceroute with explicit source routing" + atf_set require.user root +} + +ipv4_srcroute_body() +{ + setup_network + jexec trsrc sysctl net.inet.ip.sourceroute=1 + jexec trsrc sysctl net.inet.ip.accept_sourceroute=1 + jexec trrtr sysctl net.inet.ip.sourceroute=1 + + start_tcpdump + + # As we don't enable source routing on trdst, we should get an ICMP + # source routing failed error (!S). + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 2 ${LINK_TRDST_TRDST} [0-9.]+ ms !S" \ + -o not-match:"^ 3" \ + jexec trsrc traceroute $TR_FLAGS \ + -g ${LINK_TRSRC_TRRTR} ${LINK_TRDST_TRDST} + + stop_tcpdump + atf_check -s exit:0 -e ignore \ + -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP .*, options \\(NOP,LSRR ${LINK_TRDST_TRDST}\\)\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRSRC_TRRTR}.33435: UDP" \ + -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP .*, options \\(NOP,LSRR ${LINK_TRDST_TRDST}\\)\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRSRC_TRRTR}.33436: UDP" \ + cat tcpdump.output +} + +ipv4_srcroute_cleanup() +{ + vnet_cleanup +} + +## +# test: ipv4_dontroute +# + +atf_test_case "ipv4_dontroute" "cleanup" +ipv4_dontroute_head() +{ + atf_set descr "IPv4 traceroute with -r" + atf_set require.user root +} + +ipv4_dontroute_body() +{ + setup_network + + # This one should work as trrtr is directly connected. + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRSRC_TRRTR}" \ + -o match:"^ 1 ${LINK_TRSRC_TRRTR} [0-9.]+ ms$" \ + -o not-match:"^ 2" \ + jexec trsrc traceroute -r $TR_FLAGS ${LINK_TRSRC_TRRTR} + + # This one should fail. + + atf_check -s exit:0 \ + -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ + -o match:"^ 1 traceroute: wrote ${LINK_TRDST_TRDST} 40 chars, ret=-1" \ + jexec trsrc traceroute -r $TR_FLAGS ${LINK_TRDST_TRDST} +} + +ipv4_dontroute_cleanup() +{ + vnet_cleanup +} + +## +# test case declarations + +atf_init_test_cases() +{ + atf_add_test_case ipv4_basic + atf_add_test_case ipv4_udp + atf_add_test_case ipv4_icmp + atf_add_test_case ipv4_tcp + atf_add_test_case ipv4_sctp + atf_add_test_case ipv4_gre + atf_add_test_case ipv4_udplite + atf_add_test_case ipv4_srcaddr + atf_add_test_case ipv4_srcinterface + atf_add_test_case ipv4_maxhops + atf_add_test_case ipv4_unreachable + atf_add_test_case ipv4_hugepacket + atf_add_test_case ipv4_firsthop + atf_add_test_case ipv4_nprobes + atf_add_test_case ipv4_baseport + atf_add_test_case ipv4_iptos + atf_add_test_case ipv4_srcroute + atf_add_test_case ipv4_dontroute +}