t_ipsec_misc.sh revision 1.23
1#	$NetBSD: t_ipsec_misc.sh,v 1.23 2019/07/23 04:31:25 ozaki-r 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 -a $preferred = new ]; then
569		skip_if_qemu
570	fi
571
572	if [ $method = delete ]; then
573		shorttime=100
574		longtime=100
575	else
576		shorttime=3
577		longtime=6
578	fi
579
580	rump_server_crypto_start $SOCK_LOCAL netipsec
581	rump_server_crypto_start $SOCK_PEER netipsec
582	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
583	rump_server_add_iface $SOCK_PEER shmif0 $BUS
584
585	export RUMP_SERVER=$SOCK_LOCAL
586	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
587	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
588	if [ $preferred = old ]; then
589		atf_check -s exit:0 rump.sysctl -q -w net.key.prefered_oldsa=1
590	fi
591
592	export RUMP_SERVER=$SOCK_PEER
593	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
594	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer/24
595	if [ $preferred = old ]; then
596		atf_check -s exit:0 rump.sysctl -q -w net.key.prefered_oldsa=1
597	fi
598
599	setup_sasp $proto "$algo_args" $ip_local $ip_peer 100
600
601	extract_new_packets $BUS > $outfile
602
603	export RUMP_SERVER=$SOCK_LOCAL
604	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
605	extract_new_packets $BUS > $outfile
606	check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
607
608	# Add a new SA with a different SPI
609	add_sa $proto "$algo_args" $ip_local $ip_peer $longtime 10010
610
611	export RUMP_SERVER=$SOCK_LOCAL
612	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
613	extract_new_packets $BUS > $outfile
614	if [ $preferred = old ]; then
615		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
616	else
617		# The new SA is preferred
618		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10010
619	fi
620
621	# Add another SA with a different SPI
622	add_sa $proto "$algo_args" $ip_local $ip_peer $shorttime 10020
623
624	export RUMP_SERVER=$SOCK_LOCAL
625	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
626	extract_new_packets $BUS > $outfile
627	if [ $preferred = old ]; then
628		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
629	else
630		# The newest SA is preferred
631		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10020
632	fi
633
634	if [ $method = delete ]; then
635		delete_sa $proto $ip_local $ip_peer 10020
636	else
637		wait_sa_disappeared 10020
638	fi
639
640	export RUMP_SERVER=$SOCK_LOCAL
641	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
642	extract_new_packets $BUS > $outfile
643	if [ $preferred = old ]; then
644		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
645	else
646		# The newest one is removed and the second one is used
647		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10010
648	fi
649
650	if [ $method = delete ]; then
651		delete_sa $proto $ip_local $ip_peer 10010
652	else
653		wait_sa_disappeared 10010
654	fi
655
656	export RUMP_SERVER=$SOCK_LOCAL
657	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
658	extract_new_packets $BUS > $outfile
659	if [ $preferred = old ]; then
660		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
661	else
662		# The second one is removed and the original one is used
663		check_packet_spi $outfile $ip_local $ip_peer $proto_cap 10000
664	fi
665}
666
667add_test_spi()
668{
669	local proto=$1
670	local algo=$2
671	local preferred=$3
672	local method=$4
673	local _algo=$(echo $algo | sed 's/-//g')
674	local name= desc=
675
676	desc="Tests SAs with different SPIs of $proto ($algo) ($preferred SA preferred) ($method)"
677	name="ipsec_spi_${proto}_${_algo}_preferred_${preferred}_${method}"
678
679	atf_test_case ${name} cleanup
680	eval "
681	    ${name}_head() {
682	        atf_set descr \"$desc\"
683	        atf_set require.progs rump_server setkey
684	    }
685	    ${name}_body() {
686	        test_spi $proto $algo $preferred $method
687	        rump_server_destroy_ifaces
688	    }
689	    ${name}_cleanup() {
690	        \$DEBUG && dump
691	        cleanup
692	    }
693	"
694	atf_add_test_case ${name}
695}
696
697setup_sp()
698{
699	local proto=$1
700	local algo_args="$2"
701	local ip_local=$3
702	local ip_peer=$4
703	local tmpfile=./tmp
704
705	export RUMP_SERVER=$SOCK_LOCAL
706	cat > $tmpfile <<-EOF
707	spdadd $ip_local $ip_peer any -P out ipsec $proto/transport//require;
708	spdadd $ip_peer $ip_local any -P in ipsec $proto/transport//require;
709	EOF
710	$DEBUG && cat $tmpfile
711	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
712	check_sp_entries $SOCK_LOCAL $ip_local $ip_peer
713
714	export RUMP_SERVER=$SOCK_PEER
715	cat > $tmpfile <<-EOF
716	spdadd $ip_peer $ip_local any -P out ipsec $proto/transport//require;
717	spdadd $ip_local $ip_peer any -P in ipsec $proto/transport//require;
718	EOF
719	$DEBUG && cat $tmpfile
720	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
721	check_sp_entries $SOCK_PEER $ip_peer $ip_local
722}
723
724test_nosa()
725{
726	local proto=$1
727	local algo=$2
728	local update=$3
729	local ip_local=10.0.0.1
730	local ip_peer=10.0.0.2
731	local algo_args="$(generate_algo_args $proto $algo)"
732	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
733	local outfile=./out
734
735	rump_server_crypto_start $SOCK_LOCAL netipsec
736	rump_server_crypto_start $SOCK_PEER netipsec
737	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
738	rump_server_add_iface $SOCK_PEER shmif0 $BUS
739
740	export RUMP_SERVER=$SOCK_LOCAL
741	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
742	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
743
744	export RUMP_SERVER=$SOCK_PEER
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_peer/24
747
748	setup_sp $proto "$algo_args" $ip_local $ip_peer
749
750	extract_new_packets $BUS > $outfile
751
752	export RUMP_SERVER=$SOCK_LOCAL
753	# It doesn't work because there is no SA
754	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
755}
756
757add_test_nosa()
758{
759	local proto=$1
760	local algo=$2
761	local _algo=$(echo $algo | sed 's/-//g')
762	local name= desc=
763
764	desc="Tests SPs with no relevant SAs with $proto ($algo)"
765	name="ipsec_nosa_${proto}_${_algo}"
766
767	atf_test_case ${name} cleanup
768	eval "
769	    ${name}_head() {
770	        atf_set descr \"$desc\"
771	        atf_set require.progs rump_server setkey
772	    }
773	    ${name}_body() {
774	        test_nosa $proto $algo
775	        rump_server_destroy_ifaces
776	    }
777	    ${name}_cleanup() {
778	        \$DEBUG && dump
779	        cleanup
780	    }
781	"
782	atf_add_test_case ${name}
783}
784
785test_multiple_sa()
786{
787	local proto=$1
788	local algo=$2
789	local update=$3
790	local ip_local=10.0.0.1
791	local ip_peer=10.0.0.2
792	local ip_peer2=10.0.0.3
793	local algo_args="$(generate_algo_args $proto $algo)"
794	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
795	local outfile=./out
796
797	rump_server_crypto_start $SOCK_LOCAL netipsec
798	rump_server_crypto_start $SOCK_PEER netipsec
799	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS
800	rump_server_add_iface $SOCK_PEER shmif0 $BUS
801
802	export RUMP_SERVER=$SOCK_LOCAL
803	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
804	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
805
806	export RUMP_SERVER=$SOCK_PEER
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_peer/24
809	atf_check -s exit:0 rump.ifconfig shmif0 $ip_peer2/24 alias
810
811	setup_sp $proto "$algo_args" "$ip_local" "0.0.0.0/0"
812
813	extract_new_packets $BUS > $outfile
814
815	export RUMP_SERVER=$SOCK_LOCAL
816	# There is no SA, so ping should fail
817	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
818	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
819
820	add_sa $proto "$algo_args" $ip_local $ip_peer 100 10000
821
822	export RUMP_SERVER=$SOCK_LOCAL
823	# There is only an SA for $ip_peer, so ping to $ip_peer2 should fail
824	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
825	atf_check -s not-exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
826
827	add_sa $proto "$algo_args" $ip_local $ip_peer2 100 10010
828
829	export RUMP_SERVER=$SOCK_LOCAL
830	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer
831	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_peer2
832
833	export RUMP_SERVER=$SOCK_LOCAL
834	atf_check -s exit:0 -o match:"$proto/transport//require" \
835	    $HIJACKING setkey -D -P
836	# Check if the policy isn't modified accidentally
837	atf_check -s exit:0 -o not-match:"$proto/transport/.+\-.+/require" \
838	    $HIJACKING setkey -D -P
839	export RUMP_SERVER=$SOCK_PEER
840	atf_check -s exit:0 -o match:"$proto/transport//require" \
841	    $HIJACKING setkey -D -P
842	# Check if the policy isn't modified accidentally
843	atf_check -s exit:0 -o not-match:"$proto/transport/.+\-.+/require" \
844	    $HIJACKING setkey -D -P
845}
846
847add_test_multiple_sa()
848{
849	local proto=$1
850	local algo=$2
851	local _algo=$(echo $algo | sed 's/-//g')
852	local name= desc=
853
854	desc="Tests multiple SAs with $proto ($algo)"
855	name="ipsec_multiple_sa_${proto}_${_algo}"
856
857	atf_test_case ${name} cleanup
858	eval "
859	    ${name}_head() {
860	        atf_set descr \"$desc\"
861	        atf_set require.progs rump_server setkey
862	    }
863	    ${name}_body() {
864	        test_multiple_sa $proto $algo
865	        rump_server_destroy_ifaces
866	    }
867	    ${name}_cleanup() {
868	        \$DEBUG && dump
869	        cleanup
870	    }
871	"
872	atf_add_test_case ${name}
873}
874
875atf_init_test_cases()
876{
877	local algo=
878
879	for algo in $ESP_ENCRYPTION_ALGORITHMS_MINIMUM; do
880		add_test_lifetime ipv4 esp $algo
881		add_test_lifetime ipv6 esp $algo
882		add_test_update esp $algo sa
883		add_test_update esp $algo sp
884		add_test_getspi_update esp $algo
885		add_test_spi esp $algo new delete
886		add_test_spi esp $algo old delete
887		add_test_spi esp $algo new timeout
888		add_test_spi esp $algo old timeout
889		add_test_nosa esp $algo
890		add_test_multiple_sa esp $algo
891	done
892	for algo in $AH_AUTHENTICATION_ALGORITHMS_MINIMUM; do
893		add_test_lifetime ipv4 ah $algo
894		add_test_lifetime ipv6 ah $algo
895		add_test_update ah $algo sa
896		add_test_update ah $algo sp
897		add_test_getspi_update ah $algo
898		add_test_spi ah $algo new delete
899		add_test_spi ah $algo old delete
900		add_test_spi ah $algo new timeout
901		add_test_spi ah $algo old timeout
902		add_test_nosa ah $algo
903		add_test_multiple_sa ah $algo
904	done
905}
906