1# SPDX-License-Identifier: ISC 2# 3# Copyright (c) 2025 Lexi Winter 4# 5# Permission to use, copy, modify, and distribute this software for any 6# purpose with or without fee is hereby granted, provided that the above 7# copyright notice and this permission notice appear in all copies. 8# 9# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 17# We are missing tests for the following flags: 18# 19# -a (turn on ASN lookups) 20# -A (specify ASN lookup server) 21# -d (enable SO_DEBUG) 22# -D (print the diff between our packet and the quote in the ICMP error) 23# -E (detect ECN bleaching) 24# -n (or rather, we enable -n by default and don't test without it) 25# -S (print per-hop packet loss) 26# -v (verbose output) 27# -w (how long to wait for an error response) 28# -x (toggle IP checksums) 29# -z (how long to wait between each probe) 30 31. $(atf_get_srcdir)/../../sys/common/vnet.subr 32 33# These are the default flags we use for most test cases: 34# - only send a single probe packet to reduce the risk of kernel ICMP 35# rate-limiting breaking the test. 36# - only trace up to 5 hops and only wait 1 second for a response so the test 37# fails quicker if something goes wrong. 38# - disable DNS resolution as we don't usually care about this. 39TR_FLAGS="-w 1 -q 1 -m 5 -n" 40 41# The prefix our test networks are in. 42TEST_PREFIX="192.0.2.0/24" 43 44# The IPv4 addresses of the first link net between trsrc and trrtr. 45LINK_TRSRC_TRSRC="192.0.2.5" 46LINK_TRSRC_TRRTR="192.0.2.6" 47LINK_TRSRC_PREFIXLEN="30" 48 49# The IPv4 addresses of the second link net between trsrc and trrtr. 50LINK_TRSRC2_TRSRC="192.0.2.13" 51LINK_TRSRC2_TRRTR="192.0.2.14" 52LINK_TRSRC2_PREFIXLEN="30" 53 54# The IPv4 addresses of the link net between trdst and trrtr. 55LINK_TRDST_TRDST="192.0.2.9" 56LINK_TRDST_TRRTR="192.0.2.10" 57LINK_TRDST_PREFIXLEN="30" 58 59# This is an address inside $TEST_PREFIX which is not routed anywhere. 60UNREACHABLE_ADDR="192.0.2.255" 61 62setup_network() 63{ 64 # Create 3 jails: one to be the source host, one to be the router, 65 # and one to be the destination host. 66 67 vnet_init 68 69 # src jail 70 epsrc=$(vnet_mkepair) 71 epsrc2=$(vnet_mkepair) 72 vnet_mkjail trsrc ${epsrc}a ${epsrc2}a 73 74 # dst jail 75 epdst=$(vnet_mkepair) 76 vnet_mkjail trdst ${epdst}a 77 78 # router jail 79 vnet_mkjail trrtr ${epsrc}b ${epsrc2}b ${epdst}b 80 81 # Configure IPv4 addresses and routes on each jail. 82 83 # trsrc 84 jexec trsrc ifconfig ${epsrc}a inet \ 85 ${LINK_TRSRC_TRSRC}/${LINK_TRSRC_PREFIXLEN} 86 jexec trrtr ifconfig ${epsrc}b inet \ 87 ${LINK_TRSRC_TRRTR}/${LINK_TRSRC_PREFIXLEN} 88 jexec trsrc route add -inet ${TEST_PREFIX} ${LINK_TRSRC_TRRTR} 89 90 # trsrc2 91 jexec trsrc ifconfig ${epsrc2}a inet \ 92 ${LINK_TRSRC2_TRSRC}/${LINK_TRSRC2_PREFIXLEN} 93 jexec trrtr ifconfig ${epsrc2}b inet \ 94 ${LINK_TRSRC2_TRRTR}/${LINK_TRSRC2_PREFIXLEN} 95 96 # trdst 97 jexec trdst ifconfig ${epdst}a inet \ 98 ${LINK_TRDST_TRDST}/${LINK_TRDST_PREFIXLEN} 99 jexec trrtr ifconfig ${epdst}b inet \ 100 ${LINK_TRDST_TRRTR}/${LINK_TRDST_PREFIXLEN} 101 jexec trdst route add -inet ${TEST_PREFIX} ${LINK_TRDST_TRRTR} 102 103 # The router jail (only) needs IP forwarding enabled. 104 jexec trrtr sysctl net.inet.ip.forwarding=1 105} 106 107## 108# 109# start_tcpdump, stop_tcpdump: used to capture packets during the test so we 110# can verify we actually sent the expected packets. 111 112start_tcpdump() 113{ 114 # Run tcpdump on trrtr, either on the given interface or on 115 # ${epsrc}b, which is trsrc's default route interface. 116 117 interface="$1" 118 if [ -z "$interface" ]; then 119 interface="${epsrc}b" 120 fi 121 122 rm -f "${PWD}/traceroute.pcap" 123 124 jexec trrtr daemon -p "${PWD}/tcpdump.pid" \ 125 tcpdump --immediate-mode -w "${PWD}/traceroute.pcap" -nv \ 126 -i $interface 127 128 # Give tcpdump time to start 129 sleep 1 130} 131 132stop_tcpdump() 133{ 134 # Sleep to give tcpdump a chance to finish flushing 135 jexec trrtr kill -USR2 $(cat "${PWD}/tcpdump.pid") 136 sleep 1 137 jexec trrtr kill $(cat "${PWD}/tcpdump.pid") 138 139 # Format the packet capture and merge continued lines (starting with 140 # whitespace) into a single line; this makes it easier to match in 141 # atf_check. Append a blank line since the N command exits on EOF. 142 (tcpdump -nv -r "${PWD}/traceroute.pcap"; echo) | \ 143 sed -E -e :a -e N -e 's/\n +/ /' -e ta -e P -e D \ 144 > tcpdump.output 145} 146 147## 148# test: ipv4_basic 149# 150 151atf_test_case "ipv4_basic" "cleanup" 152ipv4_basic_head() 153{ 154 atf_set descr "Basic IPv4 traceroute across a router" 155 atf_set require.user root 156} 157 158ipv4_basic_body() 159{ 160 setup_network 161 162 # Use a more detailed set of regexp here than the rest of the tests to 163 # make sure the basic output format is correct. 164 atf_check -s exit:0 \ 165 -e match:"^traceroute to ${LINK_TRDST_TRDST} \\(${LINK_TRDST_TRDST}\\), 5 hops max, 40 byte packets$" \ 166 -o match:"^ 1 ${LINK_TRSRC_TRRTR} [0-9.]+ ms$" \ 167 -o match:"^ 2 ${LINK_TRDST_TRDST} [0-9.]+ ms$" \ 168 -o not-match:"^ 3" \ 169 jexec trsrc traceroute $TR_FLAGS ${LINK_TRDST_TRDST} 170} 171 172ipv4_basic_cleanup() 173{ 174 vnet_cleanup 175} 176 177## 178# test: ipv4_icmp 179# 180 181atf_test_case "ipv4_icmp" "cleanup" 182ipv4_icmp_head() 183{ 184 atf_set descr "Basic IPv4 ICMP traceroute across a router" 185 atf_set require.user root 186} 187 188ipv4_icmp_body() 189{ 190 setup_network 191 192 # -I and -Picmp should mean the same thing, so test both. 193 194 for icmp_flag in -Picmp -I; do 195 start_tcpdump 196 197 atf_check -s exit:0 \ 198 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 199 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 200 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 201 -o not-match:"^ 3" \ 202 jexec trsrc traceroute $TR_FLAGS $icmp_flag \ 203 ${LINK_TRDST_TRDST} 204 205 stop_tcpdump 206 207 atf_check -s exit:0 -e ignore \ 208 -o match:"IP \\(tos 0x0, ttl 1, .*, proto ICMP.*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ICMP echo request" \ 209 -o match:"IP \\(tos 0x0, ttl 2, .*, proto ICMP.*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ICMP echo request" \ 210 cat tcpdump.output 211 done 212} 213 214ipv4_icmp_cleanup() 215{ 216 vnet_cleanup 217} 218 219## 220# test: ipv4_udp 221# 222 223atf_test_case "ipv4_udp" "cleanup" 224ipv4_udp_head() 225{ 226 atf_set descr "IPv4 UDP traceroute" 227 atf_set require.user root 228} 229 230ipv4_udp_body() 231{ 232 setup_network 233 234 start_tcpdump 235 236 atf_check -s exit:0 \ 237 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 238 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 239 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 240 -o not-match:"^ 3" \ 241 jexec trsrc traceroute $TR_FLAGS -Pudp ${LINK_TRDST_TRDST} 242 243 stop_tcpdump 244 245 atf_check -s exit:0 -e ignore \ 246 -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ 247 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ 248 cat tcpdump.output 249 250 # Test with -e, the destination port should not increment. 251 252 start_tcpdump 253 254 atf_check -s exit:0 \ 255 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 256 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 257 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 258 -o not-match:"^ 3" \ 259 jexec trsrc traceroute $TR_FLAGS -Pudp -e -p 40000 ${LINK_TRDST_TRDST} 260 261 stop_tcpdump 262 263 atf_check -s exit:0 -e ignore \ 264 -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: UDP" \ 265 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: UDP" \ 266 cat tcpdump.output 267} 268 269ipv4_udp_cleanup() 270{ 271 vnet_cleanup 272} 273 274## 275# test: ipv4_sctp 276# 277 278atf_test_case "ipv4_sctp" "cleanup" 279ipv4_sctp_head() 280{ 281 atf_set descr "IPv4 SCTP traceroute" 282 atf_set require.user root 283} 284 285ipv4_sctp_body() 286{ 287 setup_network 288 289 # For the default packet size, we should sent a SHUTDOWN ACK packet. 290 291 start_tcpdump 292 293 atf_check -s exit:0 \ 294 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 295 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 296 jexec trsrc traceroute $TR_FLAGS -Psctp ${LINK_TRDST_TRDST} 297 298 stop_tcpdump 299 atf_check -s exit:0 -e ignore \ 300 -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: sctp \(1\) \[SHUTDOWN ACK\]" \ 301 -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: sctp \(1\) \[SHUTDOWN ACK\]" \ 302 cat tcpdump.output 303 304 # For a larger packet size we should send INIT packets. 305 306 start_tcpdump 307 308 atf_check -s exit:0 \ 309 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 310 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 311 jexec trsrc traceroute $TR_FLAGS -Psctp ${LINK_TRDST_TRDST} 128 312 313 stop_tcpdump 314 atf_check -s exit:0 -e ignore \ 315 -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: sctp \(1\) \[INIT\]" \ 316 -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: sctp \(1\) \[INIT\]" \ 317 cat tcpdump.output 318 319 # Test with -e, the destination port should not increment. 320 321 start_tcpdump 322 323 atf_check -s exit:0 \ 324 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 325 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 326 jexec trsrc traceroute $TR_FLAGS -Psctp -e -p 40000 ${LINK_TRDST_TRDST} 327 328 stop_tcpdump 329 atf_check -s exit:0 -e ignore \ 330 -o match:"IP \\(tos 0x0, ttl 1, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: sctp \(1\) \[SHUTDOWN ACK\]" \ 331 -o match:"IP \\(tos 0x0, ttl 2, .*, proto SCTP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: sctp \(1\) \[SHUTDOWN ACK\]" \ 332 cat tcpdump.output 333} 334 335ipv4_sctp_cleanup() 336{ 337 vnet_cleanup 338} 339 340## 341# test: ipv4_tcp 342# 343 344atf_test_case "ipv4_tcp" "cleanup" 345ipv4_tcp_head() 346{ 347 atf_set descr "IPv4 TCP traceroute" 348 atf_set require.user root 349} 350 351ipv4_tcp_body() 352{ 353 setup_network 354 355 start_tcpdump 356 357 # We expect the second hop to be a failure since traceroute doesn't 358 # know how to capture the RST packet. 359 atf_check -s exit:0 \ 360 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 361 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 362 -o match:"^ 2 \\*" \ 363 jexec trsrc traceroute $TR_FLAGS -Ptcp ${LINK_TRDST_TRDST} 364 365 stop_tcpdump 366 atf_check -s exit:0 -e ignore \ 367 -o match:"IP \\(tos 0x0, ttl 1, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: Flags \[S\]" \ 368 -o match:"IP \\(tos 0x0, ttl 2, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: Flags \[S\]" \ 369 cat tcpdump.output 370 371 # Test with -e, the destination port should not increment. 372 start_tcpdump 373 374 atf_check -s exit:0 \ 375 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 376 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 377 -o match:"^ 2 \\*" \ 378 jexec trsrc traceroute $TR_FLAGS -Ptcp -e -p 40000 ${LINK_TRDST_TRDST} 379 380 stop_tcpdump 381 atf_check -s exit:0 -e ignore \ 382 -o match:"IP \\(tos 0x0, ttl 1, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: Flags \[S\]" \ 383 -o match:"IP \\(tos 0x0, ttl 2, .*, proto TCP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40000: Flags \[S\]" \ 384 cat tcpdump.output 385} 386 387ipv4_tcp_cleanup() 388{ 389 vnet_cleanup 390} 391 392## 393# test: ipv4_srcaddr 394# 395 396atf_test_case "ipv4_srcaddr" "cleanup" 397ipv4_srcaddr_head() 398{ 399 atf_set descr "IPv4 traceroute with explicit source address" 400 atf_set require.user root 401} 402 403ipv4_srcaddr_body() 404{ 405 setup_network 406 407 start_tcpdump 408 409 atf_check -s exit:0 \ 410 -e match:"^traceroute to ${LINK_TRDST_TRDST} \\($LINK_TRDST_TRDST\\) from ${LINK_TRSRC2_TRSRC}" \ 411 -o match:"^ 1 ${LINK_TRSRC2_TRRTR}" \ 412 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 413 -o not-match:"^ 3" \ 414 jexec trsrc traceroute $TR_FLAGS \ 415 -s ${LINK_TRSRC2_TRSRC} ${LINK_TRDST_TRDST} 416 417 stop_tcpdump 418 atf_check -s exit:0 -e ignore \ 419 -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ 420 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ 421 cat tcpdump.output 422} 423 424ipv4_srcaddr_cleanup() 425{ 426 vnet_cleanup 427} 428 429## 430# test: ipv4_srcinterface 431# 432 433atf_test_case "ipv4_srcinterface" "cleanup" 434ipv4_srcinterface_head() 435{ 436 atf_set descr "IPv4 traceroute with explicit source interface" 437 atf_set require.user root 438} 439 440ipv4_srcinterface_body() 441{ 442 setup_network 443 444 start_tcpdump 445 446 # Unlike -s, traceroute doesn't print 'from ...' when using -i. 447 atf_check -s exit:0 \ 448 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 449 -o match:"^ 1 ${LINK_TRSRC2_TRRTR}" \ 450 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 451 -o not-match:"^ 3" \ 452 jexec trsrc traceroute $TR_FLAGS \ 453 -i ${epsrc2}a ${LINK_TRDST_TRDST} 454 455 stop_tcpdump 456 atf_check -s exit:0 -e ignore \ 457 -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ 458 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC2_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ 459 cat tcpdump.output 460} 461 462ipv4_srcinterface_cleanup() 463{ 464 vnet_cleanup 465} 466 467## 468# test: ipv4_maxhops 469# 470 471atf_test_case "ipv4_maxhops" "cleanup" 472ipv4_maxhops_head() 473{ 474 atf_set descr "IPv4 traceroute with -m" 475 atf_set require.user root 476} 477 478ipv4_maxhops_body() 479{ 480 setup_network 481 482 atf_check -s exit:0 \ 483 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 484 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 485 -o not-match:"^ 2" \ 486 jexec trsrc traceroute -w1 -q1 -m1 ${LINK_TRDST_TRDST} 487} 488 489ipv4_maxhops_cleanup() 490{ 491 vnet_cleanup 492} 493 494## 495# test: ipv4_unreachable 496# 497 498atf_test_case "ipv4_unreachable" "cleanup" 499ipv4_unreachable_head() 500{ 501 atf_set descr "IPv4 traceroute to an unreachable destination" 502 atf_set require.user root 503} 504 505ipv4_unreachable_body() 506{ 507 setup_network 508 509 atf_check -s exit:0 \ 510 -e match:"^traceroute to ${UNREACHABLE_ADDR}" \ 511 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 512 -o match:"^ 2 ${LINK_TRSRC_TRRTR} [0-9.]+ ms !H" \ 513 -o not-match:"^ 3" \ 514 jexec trsrc traceroute $TR_FLAGS $UNREACHABLE_ADDR 515} 516 517ipv4_unreachable_cleanup() 518{ 519 vnet_cleanup 520} 521 522## 523# test: ipv4_hugepacket 524# 525 526atf_test_case "ipv4_hugepacket" "cleanup" 527ipv4_hugepacket_head() 528{ 529 atf_set descr "IPv4 traceroute with a huge packet" 530 atf_set require.user root 531} 532 533ipv4_hugepacket_body() 534{ 535 setup_network 536 537 # We expect this to fail since we specified -F (don't fragment) and the 538 # 2000-byte packet is too large to fit through our tiny epair. Make 539 # sure traceroute reports the error. 540 atf_check -s exit:0 \ 541 -e match:"^traceroute to ${LINK_TRDST_TRDST} \\(${LINK_TRDST_TRDST}\\), 5 hops max, 2000 byte packets$" \ 542 -o match:"^ 1 traceroute: wrote ${LINK_TRDST_TRDST} 2000 chars, ret=-1" \ 543 -e match:"^traceroute: sendto: Message too long" \ 544 jexec trsrc traceroute -F $TR_FLAGS ${LINK_TRDST_TRDST} 2000 545} 546 547ipv4_hugepacket_cleanup() 548{ 549 vnet_cleanup 550} 551 552## 553# test: ipv4_firsthop 554# 555 556atf_test_case "ipv4_firsthop" "cleanup" 557ipv4_firsthop_head() 558{ 559 atf_set descr "IPv4 traceroute with one hop skipped" 560 atf_set require.user root 561} 562 563ipv4_firsthop_body() 564{ 565 setup_network 566 567 # -f 2 means we skip the first hop. For backward compatibility, -M is 568 # the same as -f, so test that too. 569 570 for flag in -f2 -M2; do 571 start_tcpdump 572 573 atf_check -s exit:0 \ 574 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 575 -o not-match:"^ 1" \ 576 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 577 -o not-match:"^ 3" \ 578 jexec trsrc traceroute $flag $TR_FLAGS ${LINK_TRDST_TRDST} 579 580 stop_tcpdump 581 atf_check -s exit:0 -e ignore \ 582 -o not-match:"^..:..:..\....... IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\)" \ 583 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ 584 cat tcpdump.output 585 done 586} 587 588ipv4_firsthop_cleanup() 589{ 590 vnet_cleanup 591} 592 593## 594# test: ipv4_nprobes 595# 596 597atf_test_case "ipv4_nprobes" "cleanup" 598ipv4_nprobes_head() 599{ 600 atf_set descr "IPv4 traceroute with varying number of probes" 601 atf_set require.user root 602} 603 604ipv4_nprobes_body() 605{ 606 setup_network 607 608 # By default we should send 3 probes. 609 atf_check -s exit:0 -e ignore \ 610 -o match:"^ 1 ${LINK_TRSRC_TRRTR} \(${LINK_TRSRC_TRRTR}\)( [0-9.]+ ms){3}$" \ 611 jexec trsrc traceroute -w1 -m1 ${LINK_TRDST_TRDST} 612 613 # Also test 1 and 2 (below the default) and 5 (above the default) 614 for nprobes in 1 2 5; do 615 atf_check -s exit:0 -e ignore \ 616 -o match:"^ 1 ${LINK_TRSRC_TRRTR} \(${LINK_TRSRC_TRRTR}\)( [0-9.]+ ms){$nprobes}$" \ 617 jexec trsrc traceroute -q$nprobes -w1 -m1 ${LINK_TRDST_TRDST} 618 done 619} 620 621ipv4_nprobes_cleanup() 622{ 623 vnet_cleanup 624} 625 626## 627# test: ipv4_baseport 628# 629 630atf_test_case "ipv4_baseport" "cleanup" 631ipv4_baseport_head() 632{ 633 atf_set descr "IPv4 traceroute with non-default base port" 634 atf_set require.user root 635} 636 637ipv4_baseport_body() 638{ 639 setup_network 640 641 start_tcpdump 642 643 atf_check -s exit:0 \ 644 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 645 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 646 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 647 -o not-match:"^ 3" \ 648 jexec trsrc traceroute $TR_FLAGS -p 40000 \ 649 ${LINK_TRDST_TRDST} 650 651 stop_tcpdump 652 653 atf_check -s exit:0 -e ignore \ 654 -o match:"IP \\(tos 0x0, ttl 1, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40001: UDP" \ 655 -o match:"IP \\(tos 0x0, ttl 2, .*, proto UDP.*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.40002: UDP" \ 656 cat tcpdump.output 657} 658 659ipv4_baseport_cleanup() 660{ 661 vnet_cleanup 662} 663 664## 665# test: ipv4_gre 666# 667 668atf_test_case "ipv4_gre" "cleanup" 669ipv4_gre_head() 670{ 671 atf_set descr "IPv4 GRE traceroute" 672 atf_set require.user root 673} 674 675ipv4_gre_body() 676{ 677 setup_network 678 679 start_tcpdump 680 681 # We expect the second hop to be a failure since the remote host will 682 # ignore the GRE packet. 683 atf_check -s exit:0 \ 684 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 685 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 686 -o match:"^ 2 \\*" \ 687 jexec trsrc traceroute $TR_FLAGS -Pgre ${LINK_TRDST_TRDST} 688 689 stop_tcpdump 690 atf_check -s exit:0 -e ignore \ 691 -o match:"IP \\(tos 0x0, ttl 1, .*, proto GRE .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: GREv1" \ 692 -o match:"IP \\(tos 0x0, ttl 2, .*, proto GRE .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: GREv1" \ 693 cat tcpdump.output 694} 695 696ipv4_gre_cleanup() 697{ 698 vnet_cleanup 699} 700 701## 702# test: ipv4_udplite 703# 704 705atf_test_case "ipv4_udplite" "cleanup" 706ipv4_udplite_head() 707{ 708 atf_set descr "IPv4 UDP-Lite traceroute" 709 atf_set require.user root 710} 711 712ipv4_udplite_body() 713{ 714 setup_network 715 716 start_tcpdump 717 718 atf_check -s exit:0 \ 719 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 720 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 721 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 722 -o not-match:"^ 3" \ 723 jexec trsrc traceroute $TR_FLAGS -Pudplite ${LINK_TRDST_TRDST} 724 725 stop_tcpdump 726 atf_check -s exit:0 -e ignore \ 727 -o match:"IP \\(tos 0x0, ttl 1, .*, proto unknown \(136\), .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ip-proto-136" \ 728 -o match:"IP \\(tos 0x0, ttl 2, .*, proto unknown \(136\), .*\\).* ${LINK_TRSRC_TRSRC} > ${LINK_TRDST_TRDST}: ip-proto-136" \ 729 cat tcpdump.output 730} 731 732ipv4_udplite_cleanup() 733{ 734 vnet_cleanup 735} 736 737## 738# test: ipv4_iptos 739# 740 741atf_test_case "ipv4_iptos" "cleanup" 742ipv4_iptos_head() 743{ 744 atf_set descr "IPv4 traceroute with explicit ToS" 745 atf_set require.user root 746} 747 748ipv4_iptos_body() 749{ 750 setup_network 751 752 start_tcpdump 753 754 atf_check -s exit:0 \ 755 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 756 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 757 -o match:"^ 2 ${LINK_TRDST_TRDST}" \ 758 -o not-match:"^ 3" \ 759 jexec trsrc traceroute $TR_FLAGS -t 4 ${LINK_TRDST_TRDST} 760 761 stop_tcpdump 762 atf_check -s exit:0 -e ignore \ 763 -o match:"IP \\(tos 0x4, ttl 1, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33435: UDP" \ 764 -o match:"IP \\(tos 0x4, ttl 2, .*, proto UDP .*\\).* ${LINK_TRSRC_TRSRC}.[0-9]+ > ${LINK_TRDST_TRDST}.33436: UDP" \ 765 cat tcpdump.output 766} 767 768ipv4_iptos_cleanup() 769{ 770 vnet_cleanup 771} 772 773## 774# test: ipv4_srcroute 775# 776 777atf_test_case "ipv4_srcroute" "cleanup" 778ipv4_srcroute_head() 779{ 780 atf_set descr "IPv4 traceroute with explicit source routing" 781 atf_set require.user root 782} 783 784ipv4_srcroute_body() 785{ 786 setup_network 787 jexec trsrc sysctl net.inet.ip.sourceroute=1 788 jexec trsrc sysctl net.inet.ip.accept_sourceroute=1 789 jexec trrtr sysctl net.inet.ip.sourceroute=1 790 791 start_tcpdump 792 793 # As we don't enable source routing on trdst, we should get an ICMP 794 # source routing failed error (!S). 795 atf_check -s exit:0 \ 796 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 797 -o match:"^ 1 ${LINK_TRSRC_TRRTR}" \ 798 -o match:"^ 2 ${LINK_TRDST_TRDST} [0-9.]+ ms !S" \ 799 -o not-match:"^ 3" \ 800 jexec trsrc traceroute $TR_FLAGS \ 801 -g ${LINK_TRSRC_TRRTR} ${LINK_TRDST_TRDST} 802 803 stop_tcpdump 804 atf_check -s exit:0 -e ignore \ 805 -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" \ 806 -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" \ 807 cat tcpdump.output 808} 809 810ipv4_srcroute_cleanup() 811{ 812 vnet_cleanup 813} 814 815## 816# test: ipv4_dontroute 817# 818 819atf_test_case "ipv4_dontroute" "cleanup" 820ipv4_dontroute_head() 821{ 822 atf_set descr "IPv4 traceroute with -r" 823 atf_set require.user root 824} 825 826ipv4_dontroute_body() 827{ 828 setup_network 829 830 # This one should work as trrtr is directly connected. 831 832 atf_check -s exit:0 \ 833 -e match:"^traceroute to ${LINK_TRSRC_TRRTR}" \ 834 -o match:"^ 1 ${LINK_TRSRC_TRRTR} [0-9.]+ ms$" \ 835 -o not-match:"^ 2" \ 836 jexec trsrc traceroute -r $TR_FLAGS ${LINK_TRSRC_TRRTR} 837 838 # This one should fail. 839 840 atf_check -s exit:0 \ 841 -e match:"^traceroute to ${LINK_TRDST_TRDST}" \ 842 -o match:"^ 1 traceroute: wrote ${LINK_TRDST_TRDST} 40 chars, ret=-1" \ 843 jexec trsrc traceroute -r $TR_FLAGS ${LINK_TRDST_TRDST} 844} 845 846ipv4_dontroute_cleanup() 847{ 848 vnet_cleanup 849} 850 851## 852# test case declarations 853 854atf_init_test_cases() 855{ 856 atf_add_test_case ipv4_basic 857 atf_add_test_case ipv4_udp 858 atf_add_test_case ipv4_icmp 859 atf_add_test_case ipv4_tcp 860 atf_add_test_case ipv4_sctp 861 atf_add_test_case ipv4_gre 862 atf_add_test_case ipv4_udplite 863 atf_add_test_case ipv4_srcaddr 864 atf_add_test_case ipv4_srcinterface 865 atf_add_test_case ipv4_maxhops 866 atf_add_test_case ipv4_unreachable 867 atf_add_test_case ipv4_hugepacket 868 atf_add_test_case ipv4_firsthop 869 atf_add_test_case ipv4_nprobes 870 atf_add_test_case ipv4_baseport 871 atf_add_test_case ipv4_iptos 872 atf_add_test_case ipv4_srcroute 873 atf_add_test_case ipv4_dontroute 874} 875