1#	$NetBSD: t_ipsec_tunnel.sh,v 1.11 2023/06/19 08:28:09 knakahara 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_TUNNEL_LOCAL=unix://ipsec_tunel_local
30SOCK_TUNNEL_REMOTE=unix://ipsec_tunnel_remote
31SOCK_REMOTE=unix://ipsec_remote
32BUS_LOCAL=./bus_ipsec_local
33BUS_TUNNEL=./bus_ipsec_tunnel
34BUS_REMOTE=./bus_ipsec_remote
35
36DEBUG=${DEBUG:-false}
37
38setup_servers()
39{
40
41	# See https://www.netbsd.org/docs/network/ipsec/#sample_vpn
42	rump_server_crypto_start $SOCK_LOCAL netinet6
43	rump_server_crypto_start $SOCK_TUNNEL_LOCAL netipsec netinet6
44	rump_server_crypto_start $SOCK_TUNNEL_REMOTE netipsec netinet6
45	rump_server_crypto_start $SOCK_REMOTE netinet6
46	rump_server_add_iface $SOCK_LOCAL shmif0 $BUS_LOCAL
47	rump_server_add_iface $SOCK_TUNNEL_LOCAL shmif0 $BUS_LOCAL
48	rump_server_add_iface $SOCK_TUNNEL_LOCAL shmif1 $BUS_TUNNEL
49	rump_server_add_iface $SOCK_TUNNEL_REMOTE shmif0 $BUS_REMOTE
50	rump_server_add_iface $SOCK_TUNNEL_REMOTE shmif1 $BUS_TUNNEL
51	rump_server_add_iface $SOCK_REMOTE shmif0 $BUS_REMOTE
52}
53
54check_tunnel_packets()
55{
56	local outfile=$1
57	local src=$2
58	local dst=$3
59	local proto=$4
60
61	atf_check -s exit:0 -o match:"$src > $dst: $proto" cat $outfile
62	atf_check -s exit:0 -o match:"$dst > $src: $proto" cat $outfile
63}
64
65test_ipsec4_tunnel()
66{
67	local proto=$1
68	local algo=$2
69	local ip_local=10.0.1.2
70	local ip_gw_local=10.0.1.1
71	local ip_gw_local_tunnel=20.0.0.1
72	local ip_gw_remote_tunnel=20.0.0.2
73	local ip_gw_remote=10.0.2.1
74	local ip_remote=10.0.2.2
75	local subnet_local=10.0.1.0
76	local subnet_remote=10.0.2.0
77	local tmpfile=./tmp
78	local outfile=./out
79	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
80	local algo_args="$(generate_algo_args $proto $algo)"
81
82	setup_servers
83
84	export RUMP_SERVER=$SOCK_LOCAL
85	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
86	atf_check -s exit:0 rump.ifconfig shmif0 $ip_local/24
87	atf_check -s exit:0 -o ignore \
88	    rump.route -n add -net $subnet_remote $ip_gw_local
89
90	export RUMP_SERVER=$SOCK_TUNNEL_LOCAL
91	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
92	atf_check -s exit:0 rump.ifconfig shmif0 $ip_gw_local/24
93	atf_check -s exit:0 rump.ifconfig shmif1 $ip_gw_local_tunnel/24
94	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1
95	atf_check -s exit:0 -o ignore \
96	    rump.route -n add -net $subnet_remote $ip_gw_remote_tunnel
97
98	export RUMP_SERVER=$SOCK_TUNNEL_REMOTE
99	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
100	atf_check -s exit:0 rump.ifconfig shmif0 $ip_gw_remote/24
101	atf_check -s exit:0 rump.ifconfig shmif1 $ip_gw_remote_tunnel/24
102	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.forwarding=1
103	atf_check -s exit:0 -o ignore \
104	    rump.route -n add -net $subnet_local $ip_gw_local_tunnel
105
106	export RUMP_SERVER=$SOCK_REMOTE
107	atf_check -s exit:0 rump.sysctl -q -w net.inet.ip.dad_count=0
108	atf_check -s exit:0 rump.ifconfig shmif0 $ip_remote/24
109	atf_check -s exit:0 -o ignore \
110	    rump.route -n add -net $subnet_local $ip_gw_remote
111
112	extract_new_packets $BUS_TUNNEL > $outfile
113
114	export RUMP_SERVER=$SOCK_LOCAL
115	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote
116
117	extract_new_packets $BUS_TUNNEL > $outfile
118	atf_check -s exit:0 \
119	    -o match:"$ip_local > $ip_remote: ICMP echo request" \
120	    cat $outfile
121	atf_check -s exit:0 \
122	    -o match:"$ip_remote > $ip_local: ICMP echo reply" \
123	    cat $outfile
124
125	export RUMP_SERVER=$SOCK_TUNNEL_LOCAL
126	# from https://www.netbsd.org/docs/network/ipsec/
127	cat > $tmpfile <<-EOF
128	add $ip_gw_local_tunnel $ip_gw_remote_tunnel $proto 10000 $algo_args;
129	add $ip_gw_remote_tunnel $ip_gw_local_tunnel $proto 10001 $algo_args;
130	spdadd $subnet_local/24 $subnet_remote/24 any -P out ipsec
131	    $proto/tunnel/$ip_gw_local_tunnel-$ip_gw_remote_tunnel/require;
132	spdadd $subnet_remote/24 $subnet_local/24 any -P in ipsec
133	    $proto/tunnel/$ip_gw_remote_tunnel-$ip_gw_local_tunnel/require;
134	EOF
135	$DEBUG && cat $tmpfile
136	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
137	check_sa_entries $SOCK_TUNNEL_LOCAL $ip_gw_local_tunnel \
138	    $ip_gw_remote_tunnel
139
140	export RUMP_SERVER=$SOCK_TUNNEL_REMOTE
141	cat > $tmpfile <<-EOF
142	add $ip_gw_local_tunnel $ip_gw_remote_tunnel $proto 10000 $algo_args;
143	add $ip_gw_remote_tunnel $ip_gw_local_tunnel $proto 10001 $algo_args;
144	spdadd $subnet_remote/24 $subnet_local/24 any -P out ipsec
145	    $proto/tunnel/$ip_gw_remote_tunnel-$ip_gw_local_tunnel/require;
146	spdadd $subnet_local/24 $subnet_remote/24 any -P in ipsec
147	    $proto/tunnel/$ip_gw_local_tunnel-$ip_gw_remote_tunnel/require;
148	EOF
149	$DEBUG && cat $tmpfile
150	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
151	check_sa_entries $SOCK_TUNNEL_REMOTE $ip_gw_local_tunnel \
152	    $ip_gw_remote_tunnel
153
154	export RUMP_SERVER=$SOCK_LOCAL
155	atf_check -s exit:0 -o ignore rump.ping -c 1 -n -w 3 $ip_remote
156
157	extract_new_packets $BUS_TUNNEL > $outfile
158	check_tunnel_packets $outfile $ip_gw_local_tunnel $ip_gw_remote_tunnel \
159	    $proto_cap
160
161	test_flush_entries $SOCK_TUNNEL_LOCAL
162	test_flush_entries $SOCK_TUNNEL_REMOTE
163}
164
165test_ipsec6_tunnel()
166{
167	local proto=$1
168	local algo=$2
169	local ip_local=fd00:1::2
170	local ip_gw_local=fd00:1::1
171	local ip_gw_local_tunnel=fc00::1
172	local ip_gw_remote_tunnel=fc00::2
173	local ip_gw_remote=fd00:2::1
174	local ip_remote=fd00:2::2
175	local subnet_local=fd00:1::
176	local subnet_remote=fd00:2::
177	local tmpfile=./tmp
178	local outfile=./out
179	local proto_cap=$(echo $proto | tr 'a-z' 'A-Z')
180	local algo_args="$(generate_algo_args $proto $algo)"
181
182	setup_servers
183
184	export RUMP_SERVER=$SOCK_LOCAL
185	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
186	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_local/64
187	atf_check -s exit:0 -o ignore \
188	    rump.route -n add -inet6 -net $subnet_remote/64 $ip_gw_local
189
190	export RUMP_SERVER=$SOCK_TUNNEL_LOCAL
191	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
192	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_gw_local/64
193	atf_check -s exit:0 rump.ifconfig shmif1 inet6 $ip_gw_local_tunnel/64
194	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.forwarding=1
195	atf_check -s exit:0 -o ignore \
196	    rump.route -n add -inet6 -net $subnet_remote/64 $ip_gw_remote_tunnel
197
198	export RUMP_SERVER=$SOCK_TUNNEL_REMOTE
199	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
200	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_gw_remote/64
201	atf_check -s exit:0 rump.ifconfig shmif1 inet6 $ip_gw_remote_tunnel/64
202	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.forwarding=1
203	atf_check -s exit:0 -o ignore \
204	    rump.route -n add -inet6 -net $subnet_local/64 $ip_gw_local_tunnel
205
206	export RUMP_SERVER=$SOCK_REMOTE
207	atf_check -s exit:0 rump.sysctl -q -w net.inet6.ip6.dad_count=0
208	atf_check -s exit:0 rump.ifconfig shmif0 inet6 $ip_remote
209	atf_check -s exit:0 -o ignore \
210	    rump.route -n add -inet6 -net $subnet_local/64 $ip_gw_remote
211
212	extract_new_packets $BUS_TUNNEL > $outfile
213
214	export RUMP_SERVER=$SOCK_LOCAL
215	atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_remote
216
217	extract_new_packets $BUS_TUNNEL > $outfile
218	atf_check -s exit:0 \
219	    -o match:"$ip_local > $ip_remote: ICMP6, echo request" \
220	    cat $outfile
221	atf_check -s exit:0 \
222	    -o match:"$ip_remote > $ip_local: ICMP6, echo reply" \
223	    cat $outfile
224
225	export RUMP_SERVER=$SOCK_TUNNEL_LOCAL
226	# from https://www.netbsd.org/docs/network/ipsec/
227	cat > $tmpfile <<-EOF
228	add $ip_gw_local_tunnel $ip_gw_remote_tunnel $proto 10000 $algo_args;
229	add $ip_gw_remote_tunnel $ip_gw_local_tunnel $proto 10001 $algo_args;
230	spdadd $subnet_local/64 $subnet_remote/64 any -P out ipsec
231	    $proto/tunnel/$ip_gw_local_tunnel-$ip_gw_remote_tunnel/require;
232	spdadd $subnet_remote/64 $subnet_local/64 any -P in ipsec
233	    $proto/tunnel/$ip_gw_remote_tunnel-$ip_gw_local_tunnel/require;
234	EOF
235	$DEBUG && cat $tmpfile
236	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
237	check_sa_entries $SOCK_TUNNEL_LOCAL $ip_gw_local_tunnel \
238	    $ip_gw_remote_tunnel
239
240	export RUMP_SERVER=$SOCK_TUNNEL_REMOTE
241	cat > $tmpfile <<-EOF
242	add $ip_gw_local_tunnel $ip_gw_remote_tunnel $proto 10000 $algo_args;
243	add $ip_gw_remote_tunnel $ip_gw_local_tunnel $proto 10001 $algo_args;
244	spdadd $subnet_remote/64 $subnet_local/64 any -P out ipsec
245	    $proto/tunnel/$ip_gw_remote_tunnel-$ip_gw_local_tunnel/require;
246	spdadd $subnet_local/64 $subnet_remote/64 any -P in ipsec
247	    $proto/tunnel/$ip_gw_local_tunnel-$ip_gw_remote_tunnel/require;
248	EOF
249	$DEBUG && cat $tmpfile
250	atf_check -s exit:0 -o empty $HIJACKING setkey -c < $tmpfile
251	check_sa_entries $SOCK_TUNNEL_REMOTE $ip_gw_local_tunnel \
252	    $ip_gw_remote_tunnel
253
254	export RUMP_SERVER=$SOCK_LOCAL
255	atf_check -s exit:0 -o ignore rump.ping6 -c 1 -n -X 3 $ip_remote
256
257	extract_new_packets $BUS_TUNNEL > $outfile
258	check_tunnel_packets $outfile $ip_gw_local_tunnel $ip_gw_remote_tunnel \
259	    $proto_cap
260
261	test_flush_entries $SOCK_TUNNEL_LOCAL
262	test_flush_entries $SOCK_TUNNEL_REMOTE
263}
264
265test_tunnel_common()
266{
267	local ipproto=$1
268	local proto=$2
269	local algo=$3
270
271	if [ $ipproto = ipv4 ]; then
272		test_ipsec4_tunnel $proto $algo
273	else
274		test_ipsec6_tunnel $proto $algo
275	fi
276}
277
278add_test_tunnel_mode()
279{
280	local ipproto=$1
281	local proto=$2
282	local algo=$3
283	local _algo=$(echo $algo | sed 's/-//g')
284	local name= desc=
285
286	name="ipsec_tunnel_${ipproto}_${proto}_${_algo}"
287	desc="Tests of IPsec ($ipproto) tunnel mode with $proto ($algo)"
288
289	atf_test_case ${name} cleanup
290	eval "
291	    ${name}_head() {
292	        atf_set descr \"$desc\"
293	        atf_set require.progs rump_server setkey
294	    }
295	    ${name}_body() {
296	        test_tunnel_common $ipproto $proto $algo
297	        rump_server_destroy_ifaces
298	    }
299	    ${name}_cleanup() {
300	        \$DEBUG && dump
301	        cleanup
302	    }
303	"
304	atf_add_test_case ${name}
305}
306
307atf_init_test_cases()
308{
309	local algo=
310
311	for algo in $ESP_ENCRYPTION_ALGORITHMS; do
312		add_test_tunnel_mode ipv4 esp $algo
313		add_test_tunnel_mode ipv6 esp $algo
314	done
315
316	for algo in $AH_AUTHENTICATION_ALGORITHMS; do
317		add_test_tunnel_mode ipv4 ah $algo
318		add_test_tunnel_mode ipv6 ah $algo
319	done
320}
321