1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# L2TPv3 tunnel between 2 hosts
5#
6#            host-1          |   router   |     host-2
7#                            |            |
8#      lo          l2tp      |            |      l2tp           lo
9# 172.16.101.1  172.16.1.1   |            | 172.16.1.2    172.16.101.2
10#  fc00:101::1   fc00:1::1   |            |   fc00:1::2    fc00:101::2
11#                            |            |
12#                  eth0      |            |     eth0
13#                10.1.1.1    |            |   10.1.2.1
14#              2001:db8:1::1 |            | 2001:db8:2::1
15
16VERBOSE=0
17PAUSE_ON_FAIL=no
18
19which ping6 > /dev/null 2>&1 && ping6=$(which ping6) || ping6=$(which ping)
20
21################################################################################
22#
23log_test()
24{
25	local rc=$1
26	local expected=$2
27	local msg="$3"
28
29	if [ ${rc} -eq ${expected} ]; then
30		printf "TEST: %-60s  [ OK ]\n" "${msg}"
31		nsuccess=$((nsuccess+1))
32	else
33		ret=1
34		nfail=$((nfail+1))
35		printf "TEST: %-60s  [FAIL]\n" "${msg}"
36		if [ "${PAUSE_ON_FAIL}" = "yes" ]; then
37			echo
38			echo "hit enter to continue, 'q' to quit"
39			read a
40			[ "$a" = "q" ] && exit 1
41		fi
42	fi
43}
44
45run_cmd()
46{
47	local ns
48	local cmd
49	local out
50	local rc
51
52	ns="$1"
53	shift
54	cmd="$*"
55
56	if [ "$VERBOSE" = "1" ]; then
57		printf "    COMMAND: $cmd\n"
58	fi
59
60	out=$(eval ip netns exec ${ns} ${cmd} 2>&1)
61	rc=$?
62	if [ "$VERBOSE" = "1" -a -n "$out" ]; then
63		echo "    $out"
64	fi
65
66	[ "$VERBOSE" = "1" ] && echo
67
68	return $rc
69}
70
71################################################################################
72# create namespaces and interconnects
73
74create_ns()
75{
76	local ns=$1
77	local addr=$2
78	local addr6=$3
79
80	[ -z "${addr}" ] && addr="-"
81	[ -z "${addr6}" ] && addr6="-"
82
83	ip netns add ${ns}
84
85	ip -netns ${ns} link set lo up
86	if [ "${addr}" != "-" ]; then
87		ip -netns ${ns} addr add dev lo ${addr}
88	fi
89	if [ "${addr6}" != "-" ]; then
90		ip -netns ${ns} -6 addr add dev lo ${addr6}
91	fi
92
93	ip -netns ${ns} ro add unreachable default metric 8192
94	ip -netns ${ns} -6 ro add unreachable default metric 8192
95
96	ip netns exec ${ns} sysctl -qw net.ipv4.ip_forward=1
97	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.keep_addr_on_down=1
98	ip netns exec ${ns} sysctl -qw net.ipv6.conf.all.forwarding=1
99	ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.forwarding=1
100	ip netns exec ${ns} sysctl -qw net.ipv6.conf.default.accept_dad=0
101}
102
103# create veth pair to connect namespaces and apply addresses.
104connect_ns()
105{
106	local ns1=$1
107	local ns1_dev=$2
108	local ns1_addr=$3
109	local ns1_addr6=$4
110	local ns2=$5
111	local ns2_dev=$6
112	local ns2_addr=$7
113	local ns2_addr6=$8
114
115	ip -netns ${ns1} li add ${ns1_dev} type veth peer name tmp
116	ip -netns ${ns1} li set ${ns1_dev} up
117	ip -netns ${ns1} li set tmp netns ${ns2} name ${ns2_dev}
118	ip -netns ${ns2} li set ${ns2_dev} up
119
120	if [ "${ns1_addr}" != "-" ]; then
121		ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr}
122		ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr}
123	fi
124
125	if [ "${ns1_addr6}" != "-" ]; then
126		ip -netns ${ns1} addr add dev ${ns1_dev} ${ns1_addr6}
127		ip -netns ${ns2} addr add dev ${ns2_dev} ${ns2_addr6}
128	fi
129}
130
131################################################################################
132# test setup
133
134cleanup()
135{
136	local ns
137
138	for ns in host-1 host-2 router
139	do
140		ip netns del ${ns} 2>/dev/null
141	done
142}
143
144setup_l2tp_ipv4()
145{
146	#
147	# configure l2tpv3 tunnel on host-1
148	#
149	ip -netns host-1 l2tp add tunnel tunnel_id 1041 peer_tunnel_id 1042 \
150			 encap ip local 10.1.1.1 remote 10.1.2.1
151	ip -netns host-1 l2tp add session name l2tp4 tunnel_id 1041 \
152			 session_id 1041 peer_session_id 1042
153	ip -netns host-1 link set dev l2tp4 up
154	ip -netns host-1 addr add dev l2tp4 172.16.1.1 peer 172.16.1.2
155
156	#
157	# configure l2tpv3 tunnel on host-2
158	#
159	ip -netns host-2 l2tp add tunnel tunnel_id 1042 peer_tunnel_id 1041 \
160			 encap ip local 10.1.2.1 remote 10.1.1.1
161	ip -netns host-2 l2tp add session name l2tp4 tunnel_id 1042 \
162			 session_id 1042 peer_session_id 1041
163	ip -netns host-2 link set dev l2tp4 up
164	ip -netns host-2 addr add dev l2tp4 172.16.1.2 peer 172.16.1.1
165
166	#
167	# add routes to loopback addresses
168	#
169	ip -netns host-1 ro add 172.16.101.2/32 via 172.16.1.2
170	ip -netns host-2 ro add 172.16.101.1/32 via 172.16.1.1
171}
172
173setup_l2tp_ipv6()
174{
175	#
176	# configure l2tpv3 tunnel on host-1
177	#
178	ip -netns host-1 l2tp add tunnel tunnel_id 1061 peer_tunnel_id 1062 \
179			 encap ip local 2001:db8:1::1 remote 2001:db8:2::1
180	ip -netns host-1 l2tp add session name l2tp6 tunnel_id 1061 \
181			 session_id 1061 peer_session_id 1062
182	ip -netns host-1 link set dev l2tp6 up
183	ip -netns host-1 addr add dev l2tp6 fc00:1::1 peer fc00:1::2
184
185	#
186	# configure l2tpv3 tunnel on host-2
187	#
188	ip -netns host-2 l2tp add tunnel tunnel_id 1062 peer_tunnel_id 1061 \
189			 encap ip local 2001:db8:2::1 remote 2001:db8:1::1
190	ip -netns host-2 l2tp add session name l2tp6 tunnel_id 1062 \
191			 session_id 1062 peer_session_id 1061
192	ip -netns host-2 link set dev l2tp6 up
193	ip -netns host-2 addr add dev l2tp6 fc00:1::2 peer fc00:1::1
194
195	#
196	# add routes to loopback addresses
197	#
198	ip -netns host-1 -6 ro add fc00:101::2/128 via fc00:1::2
199	ip -netns host-2 -6 ro add fc00:101::1/128 via fc00:1::1
200}
201
202setup()
203{
204	# start clean
205	cleanup
206
207	set -e
208	create_ns host-1 172.16.101.1/32 fc00:101::1/128
209	create_ns host-2 172.16.101.2/32 fc00:101::2/128
210	create_ns router
211
212	connect_ns host-1 eth0 10.1.1.1/24 2001:db8:1::1/64 \
213	           router eth1 10.1.1.2/24 2001:db8:1::2/64
214
215	connect_ns host-2 eth0 10.1.2.1/24 2001:db8:2::1/64 \
216	           router eth2 10.1.2.2/24 2001:db8:2::2/64
217
218	ip -netns host-1 ro add 10.1.2.0/24 via 10.1.1.2
219	ip -netns host-1 -6 ro add 2001:db8:2::/64 via 2001:db8:1::2
220
221	ip -netns host-2 ro add 10.1.1.0/24 via 10.1.2.2
222	ip -netns host-2 -6 ro add 2001:db8:1::/64 via 2001:db8:2::2
223
224	setup_l2tp_ipv4
225	setup_l2tp_ipv6
226	set +e
227}
228
229setup_ipsec()
230{
231	#
232	# IPv4
233	#
234	run_cmd host-1 ip xfrm policy add \
235		src 10.1.1.1 dst 10.1.2.1 dir out \
236		tmpl proto esp mode transport
237
238	run_cmd host-1 ip xfrm policy add \
239		src 10.1.2.1 dst 10.1.1.1 dir in \
240		tmpl proto esp mode transport
241
242	run_cmd host-2 ip xfrm policy add \
243		src 10.1.1.1 dst 10.1.2.1 dir in \
244		tmpl proto esp mode transport
245
246	run_cmd host-2 ip xfrm policy add \
247		src 10.1.2.1 dst 10.1.1.1 dir out \
248		tmpl proto esp mode transport
249
250	ip -netns host-1 xfrm state add \
251		src 10.1.1.1 dst 10.1.2.1 \
252		spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \
253		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
254
255	ip -netns host-1 xfrm state add \
256		src 10.1.2.1 dst 10.1.1.1 \
257		spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \
258		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
259
260	ip -netns host-2 xfrm state add \
261		src 10.1.1.1 dst 10.1.2.1 \
262		spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \
263		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
264
265	ip -netns host-2 xfrm state add \
266		src 10.1.2.1 dst 10.1.1.1 \
267		spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \
268		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
269
270	#
271	# IPV6
272	#
273	run_cmd host-1 ip -6 xfrm policy add \
274		src 2001:db8:1::1 dst 2001:db8:2::1 dir out \
275		tmpl proto esp mode transport
276
277	run_cmd host-1 ip -6 xfrm policy add \
278		src 2001:db8:2::1 dst 2001:db8:1::1 dir in \
279		tmpl proto esp mode transport
280
281	run_cmd host-2 ip -6 xfrm policy add \
282		src 2001:db8:1::1 dst 2001:db8:2::1 dir in \
283		tmpl proto esp mode transport
284
285	run_cmd host-2 ip -6 xfrm policy add \
286		src 2001:db8:2::1 dst 2001:db8:1::1 dir out \
287		tmpl proto esp mode transport
288
289	ip -netns host-1 -6 xfrm state add \
290		src 2001:db8:1::1 dst 2001:db8:2::1 \
291		spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \
292		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
293
294	ip -netns host-1 -6 xfrm state add \
295		src 2001:db8:2::1 dst 2001:db8:1::1 \
296		spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \
297		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
298
299	ip -netns host-2 -6 xfrm state add \
300		src 2001:db8:1::1 dst 2001:db8:2::1 \
301		spi 0x1000 proto esp aead 'rfc4106(gcm(aes))' \
302		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
303
304	ip -netns host-2 -6 xfrm state add \
305		src 2001:db8:2::1 dst 2001:db8:1::1 \
306		spi 0x1001 proto esp aead 'rfc4106(gcm(aes))' \
307		0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f 128 mode transport
308}
309
310teardown_ipsec()
311{
312	run_cmd host-1 ip xfrm state flush
313	run_cmd host-1 ip xfrm policy flush
314	run_cmd host-2 ip xfrm state flush
315	run_cmd host-2 ip xfrm policy flush
316}
317
318################################################################################
319# generate traffic through tunnel for various cases
320
321run_ping()
322{
323	local desc="$1"
324
325	run_cmd host-1 ping -c1 -w1 172.16.1.2
326	log_test $? 0 "IPv4 basic L2TP tunnel ${desc}"
327
328	run_cmd host-1 ping -c1 -w1 -I 172.16.101.1 172.16.101.2
329	log_test $? 0 "IPv4 route through L2TP tunnel ${desc}"
330
331	run_cmd host-1 ${ping6} -c1 -w1 fc00:1::2
332	log_test $? 0 "IPv6 basic L2TP tunnel ${desc}"
333
334	run_cmd host-1 ${ping6} -c1 -w1 -I fc00:101::1 fc00:101::2
335	log_test $? 0 "IPv6 route through L2TP tunnel ${desc}"
336}
337
338run_tests()
339{
340	local desc
341
342	setup
343	run_ping
344
345	setup_ipsec
346	run_ping "- with IPsec"
347	run_cmd host-1 ping -c1 -w1 172.16.1.2
348	log_test $? 0 "IPv4 basic L2TP tunnel ${desc}"
349
350	run_cmd host-1 ping -c1 -w1 -I 172.16.101.1 172.16.101.2
351	log_test $? 0 "IPv4 route through L2TP tunnel ${desc}"
352
353	run_cmd host-1 ${ping6} -c1 -w1 fc00:1::2
354	log_test $? 0 "IPv6 basic L2TP tunnel - with IPsec"
355
356	run_cmd host-1 ${ping6} -c1 -w1 -I fc00:101::1 fc00:101::2
357	log_test $? 0 "IPv6 route through L2TP tunnel - with IPsec"
358
359	teardown_ipsec
360	run_ping "- after IPsec teardown"
361}
362
363################################################################################
364# main
365
366declare -i nfail=0
367declare -i nsuccess=0
368
369while getopts :pv o
370do
371	case $o in
372		p) PAUSE_ON_FAIL=yes;;
373		v) VERBOSE=$(($VERBOSE + 1));;
374		*) exit 1;;
375	esac
376done
377
378run_tests
379cleanup
380
381printf "\nTests passed: %3d\n" ${nsuccess}
382printf "Tests failed: %3d\n"   ${nfail}
383