t_ipsec_misc.sh revision 1.24
1#	$NetBSD: t_ipsec_misc.sh,v 1.24 2020/08/31 14:03:56 martin 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
28SOCK_LOCAL=unix://ipsec_local
29SOCK_PEER=unix://ipsec_peer
30BUS=./bus_ipsec
31
32DEBUG=${DEBUG:-true}
33
34setup_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
88test_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
124test_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
198test_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
270test_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
283add_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
312test_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
350add_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 udpate $_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
380test_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
417add_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 udpate 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
445add_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
481delete_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
509check_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
529wait_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
554test_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
671add_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
701setup_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
728test_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
761add_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
789test_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
851add_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
879atf_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