Home | History | Annotate | Line # | Download | only in ipsec
      1 #	$NetBSD: t_ipsec_misc.sh,v 1.25 2022/01/07 22:59:32 andvar Exp $
      2 #
      3 # Copyright (c) 2017 Internet Initiative Japan Inc.
      4 # All rights reserved.
      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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     16 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     17 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     18 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     19 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     20 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     21 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     22 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     23 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     24 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     25 # POSSIBILITY OF SUCH DAMAGE.
     26 #
     27 
     28 SOCK_LOCAL=unix://ipsec_local
     29 SOCK_PEER=unix://ipsec_peer
     30 BUS=./bus_ipsec
     31 
     32 DEBUG=${DEBUG:-true}
     33 
     34 setup_sasp()
     35 {
     36 	local proto=$1
     37 	local algo_args="$2"
     38 	local ip_local=$3
     39 	local ip_peer=$4
     40 	local lifetime=$5
     41 	local update=$6
     42 	local tmpfile=./tmp
     43 	local saadd=add
     44 	local saadd_algo_args="$algo_args"
     45 	local extra=
     46 
     47 	if [ "$update" = getspi ]; then
     48 		saadd=getspi
     49 		saadd_algo_args=
     50 	fi
     51 
     52 	if [ "$update" = sa -o "$update" = getspi ]; then
     53 		extra="update $ip_local $ip_peer $proto 10000 $algo_args;
     54 		       update $ip_peer $ip_local $proto 10001 $algo_args;"
     55 	elif [ "$update" = sp ]; then
     56 		extra="spdupdate $ip_local $ip_peer any -P out ipsec $proto/transport//require;"
     57 	fi
     58 
     59 	export RUMP_SERVER=$SOCK_LOCAL
     60 	cat > $tmpfile <<-EOF
     61 	$saadd $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $saadd_algo_args;
     62 	$saadd $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $saadd_algo_args;
     63 	spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require;
     64 	$extra
     65 	EOF
     66 	$DEBUG && cat $tmpfile
     67 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
     68 	# XXX it can be expired if $lifetime is very short
     69 	#check_sa_entries $SOCK_LOCAL $ip_local $ip_peer
     70 
     71 	if [ "$update" = sp ]; then
     72 		extra="spdupdate $ip_peer $ip_local any -P out ipsec $proto/transport//require;"
     73 	fi
     74 
     75 	export RUMP_SERVER=$SOCK_PEER
     76 	cat > $tmpfile <<-EOF
     77 	$saadd $ip_local $ip_peer $proto 10000 -lh $lifetime -ls $lifetime $saadd_algo_args;
     78 	$saadd $ip_peer $ip_local $proto 10001 -lh $lifetime -ls $lifetime $saadd_algo_args;
     79 	spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require;
     80 	$extra
     81 	EOF
     82 	$DEBUG && cat $tmpfile
     83 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
     84 	# XXX it can be expired if $lifetime is very short
     85 	#check_sa_entries $SOCK_PEER $ip_local $ip_peer
     86 }
     87 
     88 test_sad_disapper_until()
     89 {
     90 	local time=$1
     91 	local check_dead_sa=$2
     92 	local setkey_opts=
     93 	local n=$time
     94 	local tmpfile=./__tmp
     95 	local sock= ok=
     96 
     97 	if $check_dead_sa; then
     98 		setkey_opts="-D -a"
     99 	else
    100 		setkey_opts="-D"
    101 	fi
    102 
    103 	while [ $n -ne 0 ]; do
    104 		ok=0
    105 		sleep 1
    106 		for sock in $SOCK_LOCAL $SOCK_PEER; do
    107 			export RUMP_SERVER=$sock
    108 			$HIJACKING setkey $setkey_opts > $tmpfile
    109 			$DEBUG && cat $tmpfile
    110 			if grep -q 'No SAD entries.' $tmpfile; then
    111 				ok=$((ok + 1))
    112 			fi
    113 		done
    114 		if [ $ok -eq 2 ]; then
    115 			return
    116 		fi
    117 
    118 		n=$((n - 1))
    119 	done
    120 
    121 	atf_fail "SAs didn't disappear after $time sec."
    122 }
    123 
    124 test_ipsec4_lifetime()
    125 {
    126 	local proto=$1
    127 	local algo=$2
    128 	local ip_local=10.0.0.1
    129 	local ip_peer=10.0.0.2
    130 	local outfile=./out
    131 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    132 	local algo_args="$(generate_algo_args $proto $algo)"
    133 	local lifetime=3
    134 	local buffertime=2
    135 
    136 	rump_server_crypto_start $SOCK_LOCAL netipsec
    137 	rump_server_crypto_start $SOCK_PEER netipsec
    138 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    139 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    140 
    141 	export RUMP_SERVER=$SOCK_LOCAL
    142 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    143 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    144 	#atf_check -s exit:0 -o ignore rump.sysctl -w net.key.debug=0xff
    145 
    146 	export RUMP_SERVER=$SOCK_PEER
    147 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    148 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    149 	#atf_check -s exit:0 -o ignore rump.sysctl -w net.key.debug=0xff
    150 
    151 	extract_new_packets $BUS > $outfile
    152 
    153 	export RUMP_SERVER=$SOCK_LOCAL
    154 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    155 
    156 	extract_new_packets $BUS > $outfile
    157 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: ICMP echo request" \
    158 	    cat $outfile
    159 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: ICMP echo reply" \
    160 	    cat $outfile
    161 
    162 	# Set up SAs with lifetime 1 sec.
    163 	setup_sasp $proto "$algo_args" $ip_local $ip_peer 1
    164 
    165 	# Check the SAs have been expired
    166 	test_sad_disapper_until $((1 + $buffertime)) false
    167 
    168 	# Clean up SPs
    169 	export RUMP_SERVER=$SOCK_LOCAL
    170 	atf_check -s exit:0 -o empty $HIJACKING setkey -F -P
    171 	export RUMP_SERVER=$SOCK_PEER
    172 	atf_check -s exit:0 -o empty $HIJACKING setkey -F -P
    173 
    174 	# Set up SAs with lifetime with $lifetime
    175 	setup_sasp $proto "$algo_args" $ip_local $ip_peer $lifetime
    176 
    177 	# Use the SAs; this will create a reference from an SP to an SA
    178 	export RUMP_SERVER=$SOCK_LOCAL
    179 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    180 
    181 	extract_new_packets $BUS > $outfile
    182 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: $proto_cap" \
    183 	    cat $outfile
    184 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: $proto_cap" \
    185 	    cat $outfile
    186 
    187 	# Check the SAs have been expired
    188 	test_sad_disapper_until $((lifetime + $buffertime)) true
    189 
    190 	export RUMP_SERVER=$SOCK_LOCAL
    191 	atf_check -s not-exit:0 -o match:'0 packets received' \
    192 	    rump.ping -c 1 -n -w 1 $ip_peer
    193 
    194 	test_flush_entries $SOCK_LOCAL
    195 	test_flush_entries $SOCK_PEER
    196 }
    197 
    198 test_ipsec6_lifetime()
    199 {
    200 	local proto=$1
    201 	local algo=$2
    202 	local ip_local=fd00::1
    203 	local ip_peer=fd00::2
    204 	local outfile=./out
    205 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    206 	local algo_args="$(generate_algo_args $proto $algo)"
    207 	local lifetime=3
    208 	local buffertime=2
    209 
    210 	rump_server_crypto_start $SOCK_LOCAL netinet6 netipsec
    211 	rump_server_crypto_start $SOCK_PEER netinet6 netipsec
    212 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    213 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    214 
    215 	export RUMP_SERVER=$SOCK_LOCAL
    216 	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
    217 	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_local
    218 
    219 	export RUMP_SERVER=$SOCK_PEER
    220 	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
    221 	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_peer
    222 
    223 	extract_new_packets $BUS > $outfile
    224 
    225 	export RUMP_SERVER=$SOCK_LOCAL
    226 	atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_peer
    227 
    228 	extract_new_packets $BUS > $outfile
    229 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: ICMP6, echo request" \
    230 	    cat $outfile
    231 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: ICMP6, echo reply" \
    232 	    cat $outfile
    233 
    234 	# Set up SAs with lifetime 1 sec.
    235 	setup_sasp $proto "$algo_args" $ip_local $ip_peer 1
    236 
    237 	# Check the SAs have been expired
    238 	test_sad_disapper_until $((1 + $buffertime)) false
    239 
    240 	# Clean up SPs
    241 	export RUMP_SERVER=$SOCK_LOCAL
    242 	atf_check -s exit:0 -o empty $HIJACKING setkey -F -P
    243 	export RUMP_SERVER=$SOCK_PEER
    244 	atf_check -s exit:0 -o empty $HIJACKING setkey -F -P
    245 
    246 	# Set up SAs with lifetime with $lifetime
    247 	setup_sasp $proto "$algo_args" $ip_local $ip_peer $lifetime
    248 
    249 	# Use the SAs; this will create a reference from an SP to an SA
    250 	export RUMP_SERVER=$SOCK_LOCAL
    251 	atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_peer
    252 
    253 	extract_new_packets $BUS > $outfile
    254 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: $proto_cap" \
    255 	    cat $outfile
    256 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: $proto_cap" \
    257 	    cat $outfile
    258 
    259 	# Check the SAs have been expired
    260 	test_sad_disapper_until $((lifetime + $buffertime)) true
    261 
    262 	export RUMP_SERVER=$SOCK_LOCAL
    263 	atf_check -s not-exit:0 -o match:'0 packets received' \
    264 	    rump.ping6 -c 1 -n -X 1 $ip_peer
    265 
    266 	test_flush_entries $SOCK_LOCAL
    267 	test_flush_entries $SOCK_PEER
    268 }
    269 
    270 test_lifetime_common()
    271 {
    272 	local ipproto=$1
    273 	local proto=$2
    274 	local algo=$3
    275 
    276 	if [ $ipproto = ipv4 ]; then
    277 		test_ipsec4_lifetime $proto $algo
    278 	else
    279 		test_ipsec6_lifetime $proto $algo
    280 	fi
    281 }
    282 
    283 add_test_lifetime()
    284 {
    285 	local ipproto=$1
    286 	local proto=$2
    287 	local algo=$3
    288 	local _algo=$(echo $algo | sed 's/-//g')
    289 	local name= desc=
    290 
    291 	name="ipsec_lifetime_${ipproto}_${proto}_${_algo}"
    292 	desc="Tests of lifetime of IPsec ($ipproto) with $proto ($algo)"
    293 
    294 	atf_test_case ${name} cleanup
    295 	eval "
    296 	    ${name}_head() {
    297 	        atf_set descr \"$desc\"
    298 	        atf_set require.progs rump_server setkey
    299 	    }
    300 	    ${name}_body() {
    301 	        test_lifetime_common $ipproto $proto $algo
    302 	        rump_server_destroy_ifaces
    303 	    }
    304 	    ${name}_cleanup() {
    305 	        \$DEBUG && dump
    306 	        cleanup
    307 	    }
    308 	"
    309 	atf_add_test_case ${name}
    310 }
    311 
    312 test_update()
    313 {
    314 	local proto=$1
    315 	local algo=$2
    316 	local update=$3
    317 	local ip_local=10.0.0.1
    318 	local ip_peer=10.0.0.2
    319 	local algo_args="$(generate_algo_args $proto $algo)"
    320 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    321 	local outfile=./out
    322 
    323 	rump_server_crypto_start $SOCK_LOCAL netipsec
    324 	rump_server_crypto_start $SOCK_PEER netipsec
    325 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    326 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    327 
    328 	export RUMP_SERVER=$SOCK_LOCAL
    329 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    330 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    331 
    332 	export RUMP_SERVER=$SOCK_PEER
    333 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    334 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    335 
    336 	setup_sasp $proto "$algo_args" $ip_local $ip_peer 100 $update
    337 
    338 	extract_new_packets $BUS > $outfile
    339 
    340 	export RUMP_SERVER=$SOCK_LOCAL
    341 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    342 
    343 	extract_new_packets $BUS > $outfile
    344 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: $proto_cap" \
    345 	    cat $outfile
    346 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: $proto_cap" \
    347 	    cat $outfile
    348 }
    349 
    350 add_test_update()
    351 {
    352 	local proto=$1
    353 	local algo=$2
    354 	local update=$3
    355 	local _update=$(echo $update |tr 'a-z' 'A-Z')
    356 	local _algo=$(echo $algo | sed 's/-//g')
    357 	local name= desc=
    358 
    359 	desc="Tests trying to update $_update of $proto ($algo)"
    360 	name="ipsec_update_${update}_${proto}_${_algo}"
    361 
    362 	atf_test_case ${name} cleanup
    363 	eval "
    364 	    ${name}_head() {
    365 	        atf_set descr \"$desc\"
    366 	        atf_set require.progs rump_server setkey
    367 	    }
    368 	    ${name}_body() {
    369 	        test_update $proto $algo $update
    370 	        rump_server_destroy_ifaces
    371 	    }
    372 	    ${name}_cleanup() {
    373 	        \$DEBUG && dump
    374 	        cleanup
    375 	    }
    376 	"
    377 	atf_add_test_case ${name}
    378 }
    379 
    380 test_getspi_update()
    381 {
    382 	local proto=$1
    383 	local algo=$2
    384 	local ip_local=10.0.0.1
    385 	local ip_peer=10.0.0.2
    386 	local algo_args="$(generate_algo_args $proto $algo)"
    387 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    388 	local outfile=./out
    389 
    390 	rump_server_crypto_start $SOCK_LOCAL netipsec
    391 	rump_server_crypto_start $SOCK_PEER netipsec
    392 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    393 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    394 
    395 	export RUMP_SERVER=$SOCK_LOCAL
    396 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    397 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    398 
    399 	export RUMP_SERVER=$SOCK_PEER
    400 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    401 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    402 
    403 	setup_sasp $proto "$algo_args" $ip_local $ip_peer 100 getspi
    404 
    405 	extract_new_packets $BUS > $outfile
    406 
    407 	export RUMP_SERVER=$SOCK_LOCAL
    408 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    409 
    410 	extract_new_packets $BUS > $outfile
    411 	atf_check -s exit:0 -o match:"$ip_local > $ip_peer: $proto_cap" \
    412 	    cat $outfile
    413 	atf_check -s exit:0 -o match:"$ip_peer > $ip_local: $proto_cap" \
    414 	    cat $outfile
    415 }
    416 
    417 add_test_getspi_update()
    418 {
    419 	local proto=$1
    420 	local algo=$2
    421 	local _algo=$(echo $algo | sed 's/-//g')
    422 	local name= desc=
    423 
    424 	desc="Tests trying to getspi and update SA of $proto ($algo)"
    425 	name="ipsec_getspi_update_sa_${proto}_${_algo}"
    426 
    427 	atf_test_case ${name} cleanup
    428 	eval "
    429 	    ${name}_head() {
    430 	        atf_set descr \"$desc\"
    431 	        atf_set require.progs rump_server setkey
    432 	    }
    433 	    ${name}_body() {
    434 	        test_getspi_update $proto $algo
    435 	        rump_server_destroy_ifaces
    436 	    }
    437 	    ${name}_cleanup() {
    438 	        \$DEBUG && dump
    439 	        cleanup
    440 	    }
    441 	"
    442 	atf_add_test_case ${name}
    443 }
    444 
    445 add_sa()
    446 {
    447 	local proto=$1
    448 	local algo_args="$2"
    449 	local ip_local=$3
    450 	local ip_peer=$4
    451 	local lifetime=$5
    452 	local spi=$6
    453 	local tmpfile=./tmp
    454 	local extra=
    455 
    456 	export RUMP_SERVER=$SOCK_LOCAL
    457 	cat > $tmpfile <<-EOF
    458 	add $ip_local $ip_peer $proto $((spi)) -lh $lifetime -ls $lifetime $algo_args;
    459 	add $ip_peer $ip_local $proto $((spi + 1)) -lh $lifetime -ls $lifetime $algo_args;
    460 	$extra
    461 	EOF
    462 	$DEBUG && cat $tmpfile
    463 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    464 	$DEBUG && $HIJACKING setkey -D
    465 	# XXX it can be expired if $lifetime is very short
    466 	#check_sa_entries $SOCK_LOCAL $ip_local $ip_peer
    467 
    468 	export RUMP_SERVER=$SOCK_PEER
    469 	cat > $tmpfile <<-EOF
    470 	add $ip_local $ip_peer $proto $((spi)) -lh $lifetime -ls $lifetime $algo_args;
    471 	add $ip_peer $ip_local $proto $((spi + 1)) -lh $lifetime -ls $lifetime $algo_args;
    472 	$extra
    473 	EOF
    474 	$DEBUG && cat $tmpfile
    475 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    476 	$DEBUG && $HIJACKING setkey -D
    477 	# XXX it can be expired if $lifetime is very short
    478 	#check_sa_entries $SOCK_PEER $ip_local $ip_peer
    479 }
    480 
    481 delete_sa()
    482 {
    483 	local proto=$1
    484 	local ip_local=$2
    485 	local ip_peer=$3
    486 	local spi=$4
    487 	local tmpfile=./tmp
    488 	local extra=
    489 
    490 	export RUMP_SERVER=$SOCK_LOCAL
    491 	cat > $tmpfile <<-EOF
    492 	delete $ip_local $ip_peer $proto $((spi));
    493 	delete $ip_peer $ip_local $proto $((spi + 1));
    494 	EOF
    495 	$DEBUG && cat $tmpfile
    496 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    497 	$DEBUG && $HIJACKING setkey -D
    498 
    499 	export RUMP_SERVER=$SOCK_PEER
    500 	cat > $tmpfile <<-EOF
    501 	delete $ip_local $ip_peer $proto $((spi));
    502 	delete $ip_peer $ip_local $proto $((spi + 1));
    503 	EOF
    504 	$DEBUG && cat $tmpfile
    505 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    506 	$DEBUG && $HIJACKING setkey -D
    507 }
    508 
    509 check_packet_spi()
    510 {
    511 	local outfile=$1
    512 	local ip_local=$2
    513 	local ip_peer=$3
    514 	local proto=$4
    515 	local spi=$5
    516 	local spistr=
    517 
    518 	$DEBUG && cat $outfile
    519 	spistr=$(printf "%08x" $spi)
    520 	atf_check -s exit:0 \
    521 	    -o match:"$ip_local > $ip_peer: $proto_cap\(spi=0x$spistr," \
    522 	    cat $outfile
    523 	spistr=$(printf "%08x" $((spi + 1)))
    524 	atf_check -s exit:0 \
    525 	    -o match:"$ip_peer > $ip_local: $proto_cap\(spi=0x$spistr," \
    526 	    cat $outfile
    527 }
    528 
    529 wait_sa_disappeared()
    530 {
    531 	local spi=$1
    532 	local i=
    533 
    534 	export RUMP_SERVER=$SOCK_LOCAL
    535 	for i in $(seq 1 10); do
    536 		$HIJACKING setkey -D |grep -q "spi=$spi"
    537 		[ $? != 0 ] && break
    538 		sleep 1
    539 	done
    540 	if [ $i -eq 10 ]; then
    541 		atf_fail "SA (spi=$spi) didn't disappear in 10s"
    542 	fi
    543 	export RUMP_SERVER=$SOCK_PEER
    544 	for i in $(seq 1 10); do
    545 		$HIJACKING setkey -D |grep -q "spi=$spi"
    546 		[ $? != 0 ] && break
    547 		sleep 1
    548 	done
    549 	if [ $i -eq 10 ]; then
    550 		atf_fail "SA (spi=$spi) didn't disappear in 10s"
    551 	fi
    552 }
    553 
    554 test_spi()
    555 {
    556 	local proto=$1
    557 	local algo=$2
    558 	local preferred=$3
    559 	local method=$4
    560 	local ip_local=10.0.0.1
    561 	local ip_peer=10.0.0.2
    562 	local algo_args="$(generate_algo_args $proto $algo)"
    563 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    564 	local outfile=./out
    565 	local spistr=
    566 	local longtime= shorttime=
    567 
    568 	if [ $method = timeout ]; then
    569 		atf_skip \
    570 	   "PR 55632: test fails randomly, leaving spurious rump_server around"
    571 	fi
    572 	if [ $method = timeout -a $preferred = new ]; then
    573 		skip_if_qemu
    574 	fi
    575 
    576 	if [ $method = delete ]; then
    577 		shorttime=100
    578 		longtime=100
    579 	else
    580 		shorttime=3
    581 		longtime=6
    582 	fi
    583 
    584 	rump_server_crypto_start $SOCK_LOCAL netipsec
    585 	rump_server_crypto_start $SOCK_PEER netipsec
    586 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    587 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    588 
    589 	export RUMP_SERVER=$SOCK_LOCAL
    590 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    591 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    592 	if [ $preferred = old ]; then
    593 		atf_check -s exit:0 rump.sysctl -q -w net.key.prefered_oldsa=1
    594 	fi
    595 
    596 	export RUMP_SERVER=$SOCK_PEER
    597 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    598 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    599 	if [ $preferred = old ]; then
    600 		atf_check -s exit:0 rump.sysctl -q -w net.key.prefered_oldsa=1
    601 	fi
    602 
    603 	setup_sasp $proto "$algo_args" $ip_local $ip_peer 100
    604 
    605 	extract_new_packets $BUS > $outfile
    606 
    607 	export RUMP_SERVER=$SOCK_LOCAL
    608 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    609 	extract_new_packets $BUS > $outfile
    610 	check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    611 
    612 	# Add a new SA with a different SPI
    613 	add_sa $proto "$algo_args" $ip_local $ip_peer $longtime 10010
    614 
    615 	export RUMP_SERVER=$SOCK_LOCAL
    616 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    617 	extract_new_packets $BUS > $outfile
    618 	if [ $preferred = old ]; then
    619 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    620 	else
    621 		# The new SA is preferred
    622 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10010
    623 	fi
    624 
    625 	# Add another SA with a different SPI
    626 	add_sa $proto "$algo_args" $ip_local $ip_peer $shorttime 10020
    627 
    628 	export RUMP_SERVER=$SOCK_LOCAL
    629 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    630 	extract_new_packets $BUS > $outfile
    631 	if [ $preferred = old ]; then
    632 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    633 	else
    634 		# The newest SA is preferred
    635 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10020
    636 	fi
    637 
    638 	if [ $method = delete ]; then
    639 		delete_sa $proto $ip_local $ip_peer 10020
    640 	else
    641 		wait_sa_disappeared 10020
    642 	fi
    643 
    644 	export RUMP_SERVER=$SOCK_LOCAL
    645 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    646 	extract_new_packets $BUS > $outfile
    647 	if [ $preferred = old ]; then
    648 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    649 	else
    650 		# The newest one is removed and the second one is used
    651 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10010
    652 	fi
    653 
    654 	if [ $method = delete ]; then
    655 		delete_sa $proto $ip_local $ip_peer 10010
    656 	else
    657 		wait_sa_disappeared 10010
    658 	fi
    659 
    660 	export RUMP_SERVER=$SOCK_LOCAL
    661 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    662 	extract_new_packets $BUS > $outfile
    663 	if [ $preferred = old ]; then
    664 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    665 	else
    666 		# The second one is removed and the original one is used
    667 		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
    668 	fi
    669 }
    670 
    671 add_test_spi()
    672 {
    673 	local proto=$1
    674 	local algo=$2
    675 	local preferred=$3
    676 	local method=$4
    677 	local _algo=$(echo $algo | sed 's/-//g')
    678 	local name= desc=
    679 
    680 	desc="Tests SAs with different SPIs of $proto ($algo) ($preferred SA preferred) ($method)"
    681 	name="ipsec_spi_${proto}_${_algo}_preferred_${preferred}_${method}"
    682 
    683 	atf_test_case ${name} cleanup
    684 	eval "
    685 	    ${name}_head() {
    686 	        atf_set descr \"$desc\"
    687 	        atf_set require.progs rump_server setkey
    688 	    }
    689 	    ${name}_body() {
    690 	        test_spi $proto $algo $preferred $method
    691 	        rump_server_destroy_ifaces
    692 	    }
    693 	    ${name}_cleanup() {
    694 	        \$DEBUG && dump
    695 	        cleanup
    696 	    }
    697 	"
    698 	atf_add_test_case ${name}
    699 }
    700 
    701 setup_sp()
    702 {
    703 	local proto=$1
    704 	local algo_args="$2"
    705 	local ip_local=$3
    706 	local ip_peer=$4
    707 	local tmpfile=./tmp
    708 
    709 	export RUMP_SERVER=$SOCK_LOCAL
    710 	cat > $tmpfile <<-EOF
    711 	spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require;
    712 	spdadd $ip_peer $ip_local any -P in ipsec $proto/transport//require;
    713 	EOF
    714 	$DEBUG && cat $tmpfile
    715 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    716 	check_sp_entries $SOCK_LOCAL $ip_local $ip_peer
    717 
    718 	export RUMP_SERVER=$SOCK_PEER
    719 	cat > $tmpfile <<-EOF
    720 	spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require;
    721 	spdadd $ip_local $ip_peer any -P in ipsec $proto/transport//require;
    722 	EOF
    723 	$DEBUG && cat $tmpfile
    724 	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
    725 	check_sp_entries $SOCK_PEER $ip_peer $ip_local
    726 }
    727 
    728 test_nosa()
    729 {
    730 	local proto=$1
    731 	local algo=$2
    732 	local update=$3
    733 	local ip_local=10.0.0.1
    734 	local ip_peer=10.0.0.2
    735 	local algo_args="$(generate_algo_args $proto $algo)"
    736 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    737 	local outfile=./out
    738 
    739 	rump_server_crypto_start $SOCK_LOCAL netipsec
    740 	rump_server_crypto_start $SOCK_PEER netipsec
    741 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    742 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    743 
    744 	export RUMP_SERVER=$SOCK_LOCAL
    745 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    746 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    747 
    748 	export RUMP_SERVER=$SOCK_PEER
    749 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    750 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    751 
    752 	setup_sp $proto "$algo_args" $ip_local $ip_peer
    753 
    754 	extract_new_packets $BUS > $outfile
    755 
    756 	export RUMP_SERVER=$SOCK_LOCAL
    757 	# It doesn't work because there is no SA
    758 	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    759 }
    760 
    761 add_test_nosa()
    762 {
    763 	local proto=$1
    764 	local algo=$2
    765 	local _algo=$(echo $algo | sed 's/-//g')
    766 	local name= desc=
    767 
    768 	desc="Tests SPs with no relevant SAs with $proto ($algo)"
    769 	name="ipsec_nosa_${proto}_${_algo}"
    770 
    771 	atf_test_case ${name} cleanup
    772 	eval "
    773 	    ${name}_head() {
    774 	        atf_set descr \"$desc\"
    775 	        atf_set require.progs rump_server setkey
    776 	    }
    777 	    ${name}_body() {
    778 	        test_nosa $proto $algo
    779 	        rump_server_destroy_ifaces
    780 	    }
    781 	    ${name}_cleanup() {
    782 	        \$DEBUG && dump
    783 	        cleanup
    784 	    }
    785 	"
    786 	atf_add_test_case ${name}
    787 }
    788 
    789 test_multiple_sa()
    790 {
    791 	local proto=$1
    792 	local algo=$2
    793 	local update=$3
    794 	local ip_local=10.0.0.1
    795 	local ip_peer=10.0.0.2
    796 	local ip_peer2=10.0.0.3
    797 	local algo_args="$(generate_algo_args $proto $algo)"
    798 	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
    799 	local outfile=./out
    800 
    801 	rump_server_crypto_start $SOCK_LOCAL netipsec
    802 	rump_server_crypto_start $SOCK_PEER netipsec
    803 	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
    804 	rump_server_add_iface $SOCK_PEER shmif0 $BUS
    805 
    806 	export RUMP_SERVER=$SOCK_LOCAL
    807 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    808 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
    809 
    810 	export RUMP_SERVER=$SOCK_PEER
    811 	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
    812 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
    813 	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer2/24 alias
    814 
    815 	setup_sp $proto "$algo_args" "$ip_local" "0.0.0.0/0"
    816 
    817 	extract_new_packets $BUS > $outfile
    818 
    819 	export RUMP_SERVER=$SOCK_LOCAL
    820 	# There is no SA, so ping should fail
    821 	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    822 	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
    823 
    824 	add_sa $proto "$algo_args" $ip_local $ip_peer 100 10000
    825 
    826 	export RUMP_SERVER=$SOCK_LOCAL
    827 	# There is only an SA for $ip_peer, so ping to $ip_peer2 should fail
    828 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    829 	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
    830 
    831 	add_sa $proto "$algo_args" $ip_local $ip_peer2 100 10010
    832 
    833 	export RUMP_SERVER=$SOCK_LOCAL
    834 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
    835 	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
    836 
    837 	export RUMP_SERVER=$SOCK_LOCAL
    838 	atf_check -s exit:0 -o match:"$proto/transport//require" \
    839 	    $HIJACKING setkey -D -P
    840 	# Check if the policy isn't modified accidentally
    841 	atf_check -s exit:0 -o not-match:"$proto/transport/.+\-.+/require" \
    842 	    $HIJACKING setkey -D -P
    843 	export RUMP_SERVER=$SOCK_PEER
    844 	atf_check -s exit:0 -o match:"$proto/transport//require" \
    845 	    $HIJACKING setkey -D -P
    846 	# Check if the policy isn't modified accidentally
    847 	atf_check -s exit:0 -o not-match:"$proto/transport/.+\-.+/require" \
    848 	    $HIJACKING setkey -D -P
    849 }
    850 
    851 add_test_multiple_sa()
    852 {
    853 	local proto=$1
    854 	local algo=$2
    855 	local _algo=$(echo $algo | sed 's/-//g')
    856 	local name= desc=
    857 
    858 	desc="Tests multiple SAs with $proto ($algo)"
    859 	name="ipsec_multiple_sa_${proto}_${_algo}"
    860 
    861 	atf_test_case ${name} cleanup
    862 	eval "
    863 	    ${name}_head() {
    864 	        atf_set descr \"$desc\"
    865 	        atf_set require.progs rump_server setkey
    866 	    }
    867 	    ${name}_body() {
    868 	        test_multiple_sa $proto $algo
    869 	        rump_server_destroy_ifaces
    870 	    }
    871 	    ${name}_cleanup() {
    872 	        \$DEBUG && dump
    873 	        cleanup
    874 	    }
    875 	"
    876 	atf_add_test_case ${name}
    877 }
    878 
    879 atf_init_test_cases()
    880 {
    881 	local algo=
    882 
    883 	for algo in $ESP_ENCRYPTION_ALGORITHMS_MINIMUM; do
    884 		add_test_lifetime ipv4 esp $algo
    885 		add_test_lifetime ipv6 esp $algo
    886 		add_test_update esp $algo sa
    887 		add_test_update esp $algo sp
    888 		add_test_getspi_update esp $algo
    889 		add_test_spi esp $algo new delete
    890 		add_test_spi esp $algo old delete
    891 		add_test_spi esp $algo new timeout
    892 		add_test_spi esp $algo old timeout
    893 		add_test_nosa esp $algo
    894 		add_test_multiple_sa esp $algo
    895 	done
    896 	for algo in $AH_AUTHENTICATION_ALGORITHMS_MINIMUM; do
    897 		add_test_lifetime ipv4 ah $algo
    898 		add_test_lifetime ipv6 ah $algo
    899 		add_test_update ah $algo sa
    900 		add_test_update ah $algo sp
    901 		add_test_getspi_update ah $algo
    902 		add_test_spi ah $algo new delete
    903 		add_test_spi ah $algo old delete
    904 		add_test_spi ah $algo new timeout
    905 		add_test_spi ah $algo old timeout
    906 		add_test_nosa ah $algo
    907 		add_test_multiple_sa ah $algo
    908 	done
    909 }
    910