1# 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2021 Rubicon Communications, LLC (Netgate) 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25# SUCH DAMAGE. 26 27. $(atf_get_srcdir)/utils.subr 28 29common_dir=$(atf_get_srcdir)/../common 30 31find_state() 32{ 33 jail=${1:-alcatraz} 34 ip=${2:-192.0.2.2} 35 36 jexec ${jail} pfctl -ss | grep icmp | grep ${ip} 37} 38 39find_state_v6() 40{ 41 jexec alcatraz pfctl -ss | grep icmp | grep 2001:db8::2 42} 43 44 45atf_test_case "v4" "cleanup" 46v4_head() 47{ 48 atf_set descr 'Test killing states by IPv4 address' 49 atf_set require.user root 50 atf_set require.progs python3 scapy 51} 52 53v4_body() 54{ 55 pft_init 56 57 epair=$(vnet_mkepair) 58 ifconfig ${epair}a 192.0.2.1/24 up 59 60 vnet_mkjail alcatraz ${epair}b 61 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 62 jexec alcatraz pfctl -e 63 64 pft_set_rules alcatraz "block all" \ 65 "pass in proto icmp" \ 66 "set skip on lo" 67 68 # Sanity check & establish state 69 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 70 --sendif ${epair}a \ 71 --to 192.0.2.2 \ 72 --replyif ${epair}a 73 74 # Change rules to now deny the ICMP traffic 75 pft_set_rules noflush alcatraz "block all" 76 if ! find_state; 77 then 78 atf_fail "Setting new rules removed the state." 79 fi 80 81 # Killing with the wrong IP doesn't affect our state 82 jexec alcatraz pfctl -k 192.0.2.3 83 if ! find_state; 84 then 85 atf_fail "Killing with the wrong IP removed our state." 86 fi 87 88 # Killing with one correct address and one incorrect doesn't kill the state 89 jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.3 90 if ! find_state; 91 then 92 atf_fail "Killing with one wrong IP removed our state." 93 fi 94 95 # Killing with correct address does remove the state 96 jexec alcatraz pfctl -k 192.0.2.1 97 if find_state; 98 then 99 atf_fail "Killing with the correct IP did not remove our state." 100 fi 101} 102 103v4_cleanup() 104{ 105 pft_cleanup 106} 107 108atf_test_case "src_dst" "cleanup" 109src_dst_head() 110{ 111 atf_set descr 'Test killing a state with source and destination specified' 112 atf_set require.user root 113} 114 115src_dst_body() 116{ 117 pft_init 118 119 epair=$(vnet_mkepair) 120 ifconfig ${epair}a 192.0.2.1/24 up 121 122 vnet_mkjail alcatraz ${epair}b 123 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 124 jexec alcatraz pfctl -e 125 126 pft_set_rules alcatraz "block all" \ 127 "pass in proto icmp" \ 128 "set skip on lo" 129 130 # Sanity check & establish state 131 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 132 --sendif ${epair}a \ 133 --to 192.0.2.2 \ 134 --replyif ${epair}a 135 136 # Change rules to now deny the ICMP traffic 137 pft_set_rules noflush alcatraz "block all" 138 if ! find_state; 139 then 140 atf_fail "Setting new rules removed the state." 141 fi 142 143 # Killing with the wrong source IP doesn't affect our state 144 jexec alcatraz pfctl -k 192.0.2.3 -k 192.0.2.2 145 if ! find_state; 146 then 147 atf_fail "Killing with the wrong source IP removed our state." 148 fi 149 150 # Killing with the wrong destination IP doesn't affect our state 151 jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.3 152 if ! find_state; 153 then 154 atf_fail "Killing with the wrong destination IP removed our state." 155 fi 156 157 # But it does with the correct one 158 jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.2 159 if find_state; 160 then 161 atf_fail "Killing with the correct IPs did not remove our state." 162 fi 163} 164 165src_dst_cleanup() 166{ 167 pft_cleanup 168} 169 170atf_test_case "v6" "cleanup" 171v6_head() 172{ 173 atf_set descr 'Test killing states by IPv6 address' 174 atf_set require.user root 175 atf_set require.progs python3 scapy 176} 177 178v6_body() 179{ 180 pft_init 181 182 epair=$(vnet_mkepair) 183 ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad 184 185 vnet_mkjail alcatraz ${epair}b 186 jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad 187 jexec alcatraz pfctl -e 188 189 pft_set_rules alcatraz "block all" \ 190 "pass quick inet6 proto ipv6-icmp all icmp6-type { neighbrsol, neighbradv } no state" \ 191 "pass in proto icmp6" \ 192 "set skip on lo" 193 194 # Sanity check & establish state 195 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 196 --sendif ${epair}a \ 197 --fromaddr 2001:db8::1 \ 198 --to 2001:db8::2 \ 199 --replyif ${epair}a 200 201 # Change rules to now deny the ICMP traffic 202 pft_set_rules noflush alcatraz "block all" 203 if ! find_state_v6; 204 then 205 atf_fail "Setting new rules removed the state." 206 fi 207 208 # Killing with the wrong IP doesn't affect our state 209 jexec alcatraz pfctl -k 2001:db8::3 210 if ! find_state_v6; 211 then 212 atf_fail "Killing with the wrong IP removed our state." 213 fi 214 215 # Killing with one correct address and one incorrect doesn't kill the state 216 jexec alcatraz pfctl -k 2001:db8::1 -k 2001:db8::3 217 if ! find_state_v6; 218 then 219 atf_fail "Killing with one wrong IP removed our state." 220 fi 221 222 # Killing with correct address does remove the state 223 jexec alcatraz pfctl -k 2001:db8::1 224 if find_state_v6; 225 then 226 atf_fail "Killing with the correct IP did not remove our state." 227 fi 228} 229 230v6_cleanup() 231{ 232 pft_cleanup 233} 234 235atf_test_case "label" "cleanup" 236label_head() 237{ 238 atf_set descr 'Test killing states by label' 239 atf_set require.user root 240 atf_set require.progs python3 scapy 241} 242 243label_body() 244{ 245 pft_init 246 247 epair=$(vnet_mkepair) 248 ifconfig ${epair}a 192.0.2.1/24 up 249 250 vnet_mkjail alcatraz ${epair}b 251 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 252 jexec alcatraz pfctl -e 253 254 pft_set_rules alcatraz "block all" \ 255 "pass in proto tcp label bar" \ 256 "pass in proto icmp label foo" \ 257 "set skip on lo" 258 259 # Sanity check & establish state 260 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 261 --sendif ${epair}a \ 262 --to 192.0.2.2 \ 263 --replyif ${epair}a 264 265 # Change rules to now deny the ICMP traffic 266 pft_set_rules noflush alcatraz "block all" 267 if ! find_state; 268 then 269 atf_fail "Setting new rules removed the state." 270 fi 271 272 # Killing a label on a different rules keeps the state 273 jexec alcatraz pfctl -k label -k bar 274 if ! find_state; 275 then 276 atf_fail "Killing a different label removed the state." 277 fi 278 279 # Killing a non-existing label keeps the state 280 jexec alcatraz pfctl -k label -k baz 281 if ! find_state; 282 then 283 atf_fail "Killing a non-existing label removed the state." 284 fi 285 286 # Killing the correct label kills the state 287 jexec alcatraz pfctl -k label -k foo 288 if find_state; 289 then 290 atf_fail "Killing the state did not remove it." 291 fi 292} 293 294label_cleanup() 295{ 296 pft_cleanup 297} 298 299atf_test_case "multilabel" "cleanup" 300multilabel_head() 301{ 302 atf_set descr 'Test killing states with multiple labels by label' 303 atf_set require.user root 304 atf_set require.progs python3 scapy 305} 306 307multilabel_body() 308{ 309 pft_init 310 311 epair=$(vnet_mkepair) 312 ifconfig ${epair}a 192.0.2.1/24 up 313 314 vnet_mkjail alcatraz ${epair}b 315 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 316 jexec alcatraz pfctl -e 317 318 pft_set_rules alcatraz "block all" \ 319 "pass in proto icmp label foo label bar" \ 320 "set skip on lo" 321 322 # Sanity check & establish state 323 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 324 --sendif ${epair}a \ 325 --to 192.0.2.2 \ 326 --replyif ${epair}a 327 328 # Change rules to now deny the ICMP traffic 329 pft_set_rules noflush alcatraz "block all" 330 if ! find_state; 331 then 332 atf_fail "Setting new rules removed the state." 333 fi 334 335 # Killing a label on a different rules keeps the state 336 jexec alcatraz pfctl -k label -k baz 337 if ! find_state; 338 then 339 atf_fail "Killing a different label removed the state." 340 fi 341 342 # Killing the state with the last label works 343 jexec alcatraz pfctl -k label -k bar 344 if find_state; 345 then 346 atf_fail "Killing with the last label did not remove the state." 347 fi 348 349 pft_set_rules alcatraz "block all" \ 350 "pass in proto icmp label foo label bar" \ 351 "set skip on lo" 352 353 # Reestablish state 354 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 355 --sendif ${epair}a \ 356 --to 192.0.2.2 \ 357 --replyif ${epair}a 358 359 # Change rules to now deny the ICMP traffic 360 pft_set_rules noflush alcatraz "block all" 361 if ! find_state; 362 then 363 atf_fail "Setting new rules removed the state." 364 fi 365 366 # Killing with the first label works too 367 jexec alcatraz pfctl -k label -k foo 368 if find_state; 369 then 370 atf_fail "Killing with the first label did not remove the state." 371 fi 372} 373 374multilabel_cleanup() 375{ 376 pft_cleanup 377} 378 379atf_test_case "gateway" "cleanup" 380gateway_head() 381{ 382 atf_set descr 'Test killing states by route-to/reply-to address' 383 atf_set require.user root 384 atf_set require.progs python3 scapy 385} 386 387gateway_body() 388{ 389 pft_init 390 391 epair=$(vnet_mkepair) 392 ifconfig ${epair}a 192.0.2.1/24 up 393 394 vnet_mkjail alcatraz ${epair}b 395 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 396 jexec alcatraz pfctl -e 397 398 pft_set_rules alcatraz "block all" \ 399 "pass in reply-to (${epair}b 192.0.2.1) proto icmp" \ 400 "set skip on lo" 401 402 # Sanity check & establish state 403 # Note: use pft_ping so we always use the same ID, so pf considers all 404 # echo requests part of the same flow. 405 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 406 --sendif ${epair}a \ 407 --to 192.0.2.2 \ 408 --replyif ${epair}a 409 410 # Change rules to now deny the ICMP traffic 411 pft_set_rules noflush alcatraz "block all" 412 if ! find_state; 413 then 414 atf_fail "Setting new rules removed the state." 415 fi 416 417 # Killing with a different gateway does not affect our state 418 jexec alcatraz pfctl -k gateway -k 192.0.2.2 419 if ! find_state; 420 then 421 atf_fail "Killing with a different gateway removed the state." 422 fi 423 424 # Killing states with the relevant gateway does terminate our state 425 jexec alcatraz pfctl -k gateway -k 192.0.2.1 426 if find_state; 427 then 428 atf_fail "Killing with the gateway did not remove the state." 429 fi 430} 431 432gateway_cleanup() 433{ 434 pft_cleanup 435} 436 437atf_test_case "match" "cleanup" 438match_head() 439{ 440 atf_set descr 'Test killing matching states' 441 atf_set require.user root 442} 443 444wait_for_state() 445{ 446 jail=$1 447 addr=$2 448 449 while ! jexec $jail pfctl -s s | grep $addr >/dev/null; 450 do 451 sleep .1 452 done 453} 454 455match_body() 456{ 457 pft_init 458 459 epair_one=$(vnet_mkepair) 460 ifconfig ${epair_one}a 192.0.2.1/24 up 461 462 epair_two=$(vnet_mkepair) 463 464 vnet_mkjail alcatraz ${epair_one}b ${epair_two}a 465 jexec alcatraz ifconfig ${epair_one}b 192.0.2.2/24 up 466 jexec alcatraz ifconfig ${epair_two}a 198.51.100.1/24 up 467 jexec alcatraz sysctl net.inet.ip.forwarding=1 468 jexec alcatraz pfctl -e 469 470 vnet_mkjail singsing ${epair_two}b 471 jexec singsing ifconfig ${epair_two}b 198.51.100.2/24 up 472 jexec singsing route add default 198.51.100.1 473 jexec singsing /usr/sbin/inetd -p ${PWD}/inetd-echo.pid \ 474 $(atf_get_srcdir)/echo_inetd.conf 475 476 route add 198.51.100.0/24 192.0.2.2 477 478 pft_set_rules alcatraz \ 479 "nat on ${epair_two}a from 192.0.2.0/24 -> (${epair_two}a)" \ 480 "pass all" 481 482 nc 198.51.100.2 7 & 483 wait_for_state alcatraz 192.0.2.1 484 485 # Expect two states 486 states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l) 487 if [ $states -ne 2 ] ; 488 then 489 atf_fail "Expected two states, found $states" 490 fi 491 492 # If we don't kill the matching NAT state one should be left 493 jexec alcatraz pfctl -k 192.0.2.1 494 states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l) 495 if [ $states -ne 1 ] ; 496 then 497 atf_fail "Expected one states, found $states" 498 fi 499 500 # Flush 501 jexec alcatraz pfctl -F states 502 503 nc 198.51.100.2 7 & 504 wait_for_state alcatraz 192.0.2.1 505 506 # Kill matching states, expect all of them to be gone 507 jexec alcatraz pfctl -M -k 192.0.2.1 508 states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l) 509 if [ $states -ne 0 ] ; 510 then 511 atf_fail "Expected zero states, found $states" 512 fi 513} 514 515match_cleanup() 516{ 517 pft_cleanup 518} 519 520atf_test_case "interface" "cleanup" 521interface_head() 522{ 523 atf_set descr 'Test killing states based on interface' 524 atf_set require.user root 525 atf_set require.progs python3 scapy 526} 527 528interface_body() 529{ 530 pft_init 531 532 epair=$(vnet_mkepair) 533 ifconfig ${epair}a 192.0.2.1/24 up 534 535 vnet_mkjail alcatraz ${epair}b 536 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 537 jexec alcatraz pfctl -e 538 539 pft_set_rules alcatraz "block all" \ 540 "pass in proto icmp" \ 541 "set skip on lo" 542 543 # Sanity check & establish state 544 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 545 --sendif ${epair}a \ 546 --to 192.0.2.2 \ 547 --replyif ${epair}a 548 549 # Change rules to now deny the ICMP traffic 550 pft_set_rules noflush alcatraz "block all" 551 if ! find_state; 552 then 553 atf_fail "Setting new rules removed the state." 554 fi 555 556 # Flushing states on a different interface doesn't affect our state 557 jexec alcatraz pfctl -i ${epair}a -Fs 558 if ! find_state; 559 then 560 atf_fail "Flushing on a different interface removed the state." 561 fi 562 563 # Flushing on the correct interface does (even with floating states) 564 jexec alcatraz pfctl -i ${epair}b -Fs 565 if find_state; 566 then 567 atf_fail "Flushing on a the interface did not remove the state." 568 fi 569} 570 571interface_cleanup() 572{ 573 pft_cleanup 574} 575 576atf_test_case "id" "cleanup" 577id_head() 578{ 579 atf_set descr 'Test killing states by id' 580 atf_set require.user root 581 atf_set require.progs python3 scapy 582} 583 584id_body() 585{ 586 pft_init 587 588 epair=$(vnet_mkepair) 589 ifconfig ${epair}a 192.0.2.1/24 up 590 591 vnet_mkjail alcatraz ${epair}b 592 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 593 jexec alcatraz pfctl -e 594 595 pft_set_rules alcatraz "block all" \ 596 "pass in proto tcp" \ 597 "pass in proto icmp" \ 598 "set skip on lo" 599 600 # Sanity check & establish state 601 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 602 --sendif ${epair}a \ 603 --to 192.0.2.2 \ 604 --replyif ${epair}a 605 606 # Change rules to now deny the ICMP traffic 607 pft_set_rules noflush alcatraz "block all" 608 if ! find_state; 609 then 610 atf_fail "Setting new rules removed the state." 611 fi 612 613 # Get the state ID 614 id=$(jexec alcatraz pfctl -ss -vvv | grep -A 3 icmp | 615 grep -A 3 192.0.2.2 | awk '/id:/ { printf("%s/%s", $2, $4); }') 616 617 # Kill the wrong ID 618 jexec alcatraz pfctl -k id -k 1 619 if ! find_state; 620 then 621 atf_fail "Killing a different ID removed the state." 622 fi 623 624 # Kill the correct ID 625 jexec alcatraz pfctl -k id -k ${id} 626 if find_state; 627 then 628 atf_fail "Killing the state did not remove it." 629 fi 630} 631 632id_cleanup() 633{ 634 pft_cleanup 635} 636 637atf_test_case "key" "cleanup" 638key_head() 639{ 640 atf_set descr 'Test killing states by their key' 641 atf_set require.user root 642 atf_set require.progs python3 scapy 643} 644 645key_body() 646{ 647 pft_init 648 649 epair=$(vnet_mkepair) 650 ifconfig ${epair}a 192.0.2.1/24 up 651 652 vnet_mkjail alcatraz ${epair}b 653 jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up 654 jexec alcatraz pfctl -e 655 656 pft_set_rules alcatraz \ 657 "block all" \ 658 "pass in proto tcp" \ 659 "pass in proto icmp" 660 661 # Sanity check & establish state 662 atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \ 663 --sendif ${epair}a \ 664 --to 192.0.2.2 \ 665 --replyif ${epair}a 666 667 # Get the state key 668 key=$(jexec alcatraz pfctl -ss -vvv | awk '/icmp/ { print($2 " " $3 " " $4 " " $5); }') 669 bad_key=$(echo ${key} | sed 's/icmp/tcp/') 670 671 # Kill the wrong key 672 atf_check -s exit:0 -e "match:killed 0 states" \ 673 jexec alcatraz pfctl -k key -k "${bad_key}" 674 if ! find_state; 675 then 676 atf_fail "Killing a different ID removed the state." 677 fi 678 679 # Kill the correct key 680 atf_check -s exit:0 -e "match:killed 1 states" \ 681 jexec alcatraz pfctl -k key -k "${key}" 682 if find_state; 683 then 684 atf_fail "Killing the state did not remove it." 685 fi 686} 687 688key_cleanup() 689{ 690 pft_cleanup 691} 692 693atf_test_case "nat" "cleanup" 694nat_head() 695{ 696 atf_set descr 'Test killing states by their NAT-ed IP address' 697 atf_set require.user root 698 atf_set require.progs python3 scapy 699} 700 701nat_body() 702{ 703 pft_init 704 j="killstate:nat" 705 706 epair_c=$(vnet_mkepair) 707 epair_srv=$(vnet_mkepair) 708 709 vnet_mkjail ${j}c ${epair_c}a 710 ifconfig -j ${j}c ${epair_c}a inet 192.0.2.2/24 up 711 jexec ${j}c route add default 192.0.2.1 712 713 vnet_mkjail ${j}srv ${epair_srv}a 714 ifconfig -j ${j}srv ${epair_srv}a inet 198.51.100.2/24 up 715 716 vnet_mkjail ${j}r ${epair_c}b ${epair_srv}b 717 ifconfig -j ${j}r ${epair_c}b inet 192.0.2.1/24 up 718 ifconfig -j ${j}r ${epair_srv}b inet 198.51.100.1/24 up 719 jexec ${j}r sysctl net.inet.ip.forwarding=1 720 721 jexec ${j}r pfctl -e 722 pft_set_rules ${j}r \ 723 "nat on ${epair_srv}b inet from 192.0.2.0/24 to any -> (${epair_srv}b)" 724 725 # Sanity check 726 atf_check -s exit:0 -o ignore \ 727 jexec ${j}c ping -c 1 192.0.2.1 728 atf_check -s exit:0 -o ignore \ 729 jexec ${j}srv ping -c 1 198.51.100.1 730 atf_check -s exit:0 -o ignore \ 731 jexec ${j}c ping -c 1 198.51.100.2 732 733 # Establish state 734 # Note: use pft_ping so we always use the same ID, so pf considers all 735 # echo requests part of the same flow. 736 atf_check -s exit:0 -o ignore jexec ${j}c ${common_dir}/pft_ping.py \ 737 --sendif ${epair_c}a \ 738 --to 198.51.100.1 \ 739 --replyif ${epair_c}a 740 741 # There's NAT here, so the source IP will be 198.51.100.1 742 if ! find_state ${j}r 198.51.100.1; 743 then 744 atf_fail "Expected state not found" 745 fi 746 747 # By NAT-ed address? 748 jexec ${j}r pfctl -k nat -k 192.0.2.2 749 750 if find_state ${j}r 198.51.100.1; 751 then 752 jexec ${j}r pfctl -ss -v 753 atf_fail "Failed to remove state" 754 fi 755} 756 757nat_cleanup() 758{ 759 pft_cleanup 760} 761 762atf_init_test_cases() 763{ 764 atf_add_test_case "v4" 765 atf_add_test_case "src_dst" 766 atf_add_test_case "v6" 767 atf_add_test_case "label" 768 atf_add_test_case "multilabel" 769 atf_add_test_case "gateway" 770 atf_add_test_case "match" 771 atf_add_test_case "interface" 772 atf_add_test_case "id" 773 atf_add_test_case "key" 774 atf_add_test_case "nat" 775} 776