Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Check xfrm policy resolution. Topology:
5#
6# 1.2 1.1 3.1 3.10 2.1 2.2
7# eth1 eth1 veth0 veth0 eth1 eth1
8# ns1 ---- ns3 ----- ns4 ---- ns2
9#
10# ns3 and ns4 are connected via ipsec tunnel.
11# pings from ns1 to ns2 (and vice versa) are supposed to work like this:
12# ns1: ping 10.0.2.2: passes via ipsec tunnel.
13# ns2: ping 10.0.1.2: passes via ipsec tunnel.
14
15# ns1: ping 10.0.1.253: passes via ipsec tunnel (direct policy)
16# ns2: ping 10.0.2.253: passes via ipsec tunnel (direct policy)
17#
18# ns1: ping 10.0.2.254: does NOT pass via ipsec tunnel (exception)
19# ns2: ping 10.0.1.254: does NOT pass via ipsec tunnel (exception)
20
21# Kselftest framework requirement - SKIP code is 4.
22ksft_skip=4
23ret=0
24policy_checks_ok=1
25
26KEY_SHA=0xdeadbeef1234567890abcdefabcdefabcdefabcd
27KEY_AES=0x0123456789abcdef0123456789012345
28SPI1=0x1
29SPI2=0x2
30
31do_esp_policy() {
32 local ns=$1
33 local me=$2
34 local remote=$3
35 local lnet=$4
36 local rnet=$5
37
38 # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
39 ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
40 # to fwd decrypted packets after esp processing:
41 ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
42}
43
44do_esp() {
45 local ns=$1
46 local me=$2
47 local remote=$3
48 local lnet=$4
49 local rnet=$5
50 local spi_out=$6
51 local spi_in=$7
52
53 ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $rnet dst $lnet
54 ip -net $ns xfrm state add src $me dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
55
56 do_esp_policy $ns $me $remote $lnet $rnet
57}
58
59# add policies with different netmasks, to make sure kernel carries
60# the policies contained within new netmask over when search tree is
61# re-built.
62# peer netns that are supposed to be encapsulated via esp have addresses
63# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.
64#
65# Adding a policy for '10.0.1.0/23' will make it necessary to
66# alter the prefix of 10.0.1.0 subnet.
67# In case new prefix overlaps with existing node, the node and all
68# policies it carries need to be merged with the existing one(s).
69#
70# Do that here.
71do_overlap()
72{
73 local ns=$1
74
75 # adds new nodes to tree (neither network exists yet in policy database).
76 ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
77
78 # adds a new node in the 10.0.0.0/24 tree (dst node exists).
79 ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
80
81 # adds a 10.2.0.0/23 node, but for different dst.
82 ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block
83
84 # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.
85 # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.
86 # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node
87 # also has to be merged too, including source-sorted subtrees.
88 # old:
89 # 10.0.0.0/24 (node 1 in dst tree of the bin)
90 # 10.1.0.0/24 (node in src tree of dst node 1)
91 # 10.2.0.0/24 (node in src tree of dst node 1)
92 # 10.0.1.0/24 (node 2 in dst tree of the bin)
93 # 10.0.2.0/24 (node in src tree of dst node 2)
94 # 10.2.0.0/24 (node in src tree of dst node 2)
95 #
96 # The next 'policy add' adds dst '10.0.0.0/23', which means
97 # that dst node 1 and dst node 2 have to be merged including
98 # the sub-tree. As no duplicates are allowed, policies in
99 # the two '10.0.2.0/24' are also merged.
100 #
101 # after the 'add', internal search tree should look like this:
102 # 10.0.0.0/23 (node in dst tree of bin)
103 # 10.0.2.0/24 (node in src tree of dst node)
104 # 10.1.0.0/24 (node in src tree of dst node)
105 # 10.2.0.0/24 (node in src tree of dst node)
106 #
107 # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
108 ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
109
110 # similar to above: add policies (with partially random address), with shrinking prefixes.
111 for p in 29 28 27;do
112 for k in $(seq 1 32); do
113 ip -net $ns xfrm policy add src 10.253.1.$((RANDOM%255))/$p dst 10.254.1.$((RANDOM%255))/$p dir fwd priority $((200+k)) action block 2>/dev/null
114 done
115 done
116}
117
118do_esp_policy_get_check() {
119 local ns=$1
120 local lnet=$2
121 local rnet=$3
122
123 ip -net $ns xfrm policy get src $lnet dst $rnet dir out > /dev/null
124 if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then
125 policy_checks_ok=0
126 echo "FAIL: ip -net $ns xfrm policy get src $lnet dst $rnet dir out"
127 ret=1
128 fi
129
130 ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd > /dev/null
131 if [ $? -ne 0 ] && [ $policy_checks_ok -eq 1 ] ;then
132 policy_checks_ok=0
133 echo "FAIL: ip -net $ns xfrm policy get src $rnet dst $lnet dir fwd"
134 ret=1
135 fi
136}
137
138do_exception() {
139 local ns=$1
140 local me=$2
141 local remote=$3
142 local encryptip=$4
143 local plain=$5
144
145 # network $plain passes without tunnel
146 ip -net $ns xfrm policy add dst $plain dir out priority 10 action allow
147
148 # direct policy for $encryptip, use tunnel, higher prio takes precedence
149 ip -net $ns xfrm policy add dst $encryptip dir out tmpl src $me dst $remote proto esp mode tunnel priority 1 action allow
150}
151
152# policies that are not supposed to match any packets generated in this test.
153do_dummies4() {
154 local ns=$1
155
156 for i in $(seq 10 16);do
157 # dummy policy with wildcard src/dst.
158 echo netns exec $ns ip xfrm policy add src 0.0.0.0/0 dst 10.$i.99.0/30 dir out action block
159 echo netns exec $ns ip xfrm policy add src 10.$i.99.0/30 dst 0.0.0.0/0 dir out action block
160 for j in $(seq 32 64);do
161 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/30 dst 10.$i.$j.0/30 dir out action block
162 # silly, as it encompasses the one above too, but its allowed:
163 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/29 dst 10.$i.$j.0/29 dir out action block
164 # and yet again, even more broad one.
165 echo netns exec $ns ip xfrm policy add src 10.$i.1.0/24 dst 10.$i.$j.0/24 dir out action block
166 echo netns exec $ns ip xfrm policy add src 10.$i.$j.0/24 dst 10.$i.1.0/24 dir fwd action block
167 done
168 done | ip -batch /dev/stdin
169}
170
171do_dummies6() {
172 local ns=$1
173
174 for i in $(seq 10 16);do
175 for j in $(seq 32 64);do
176 echo netns exec $ns ip xfrm policy add src dead:$i::/64 dst dead:$i:$j::/64 dir out action block
177 echo netns exec $ns ip xfrm policy add src dead:$i:$j::/64 dst dead:$i::/24 dir fwd action block
178 done
179 done | ip -batch /dev/stdin
180}
181
182check_ipt_policy_count()
183{
184 ns=$1
185
186 ip netns exec $ns iptables-save -c |grep policy | ( read c rest
187 ip netns exec $ns iptables -Z
188 if [ x"$c" = x'[0:0]' ]; then
189 exit 0
190 elif [ x"$c" = x ]; then
191 echo "ERROR: No counters"
192 ret=1
193 exit 111
194 else
195 exit 1
196 fi
197 )
198}
199
200check_xfrm() {
201 # 0: iptables -m policy rule count == 0
202 # 1: iptables -m policy rule count != 0
203 rval=$1
204 ip=$2
205 lret=0
206
207 ip netns exec ns1 ping -q -c 1 10.0.2.$ip > /dev/null
208
209 check_ipt_policy_count ns3
210 if [ $? -ne $rval ] ; then
211 lret=1
212 fi
213 check_ipt_policy_count ns4
214 if [ $? -ne $rval ] ; then
215 lret=1
216 fi
217
218 ip netns exec ns2 ping -q -c 1 10.0.1.$ip > /dev/null
219
220 check_ipt_policy_count ns3
221 if [ $? -ne $rval ] ; then
222 lret=1
223 fi
224 check_ipt_policy_count ns4
225 if [ $? -ne $rval ] ; then
226 lret=1
227 fi
228
229 return $lret
230}
231
232check_exceptions()
233{
234 logpostfix="$1"
235 local lret=0
236
237 # ping to .254 should be excluded from the tunnel (exception is in place).
238 check_xfrm 0 254
239 if [ $? -ne 0 ]; then
240 echo "FAIL: expected ping to .254 to fail ($logpostfix)"
241 lret=1
242 else
243 echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"
244 fi
245
246 # ping to .253 should use use ipsec due to direct policy exception.
247 check_xfrm 1 253
248 if [ $? -ne 0 ]; then
249 echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"
250 lret=1
251 else
252 echo "PASS: direct policy matches ($logpostfix)"
253 fi
254
255 # ping to .2 should use ipsec.
256 check_xfrm 1 2
257 if [ $? -ne 0 ]; then
258 echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"
259 lret=1
260 else
261 echo "PASS: policy matches ($logpostfix)"
262 fi
263
264 return $lret
265}
266
267check_hthresh_repeat()
268{
269 local log=$1
270 i=0
271
272 for i in $(seq 1 10);do
273 ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::0014:0000:0001 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
274 ip -net ns1 xfrm policy set hthresh6 0 28 || break
275
276 ip -net ns1 xfrm policy update src e000:0001::0000 dst ff01::01 dir in tmpl src :: dst :: proto esp mode tunnel priority 100 action allow || break
277 ip -net ns1 xfrm policy set hthresh6 0 28 || break
278 done
279
280 if [ $i -ne 10 ] ;then
281 echo "FAIL: $log" 1>&2
282 ret=1
283 return 1
284 fi
285
286 echo "PASS: $log"
287 return 0
288}
289
290#check for needed privileges
291if [ "$(id -u)" -ne 0 ];then
292 echo "SKIP: Need root privileges"
293 exit $ksft_skip
294fi
295
296ip -Version 2>/dev/null >/dev/null
297if [ $? -ne 0 ];then
298 echo "SKIP: Could not run test without the ip tool"
299 exit $ksft_skip
300fi
301
302# needed to check if policy lookup got valid ipsec result
303iptables --version 2>/dev/null >/dev/null
304if [ $? -ne 0 ];then
305 echo "SKIP: Could not run test without iptables tool"
306 exit $ksft_skip
307fi
308
309for i in 1 2 3 4; do
310 ip netns add ns$i
311 ip -net ns$i link set lo up
312done
313
314DEV=veth0
315ip link add $DEV netns ns1 type veth peer name eth1 netns ns3
316ip link add $DEV netns ns2 type veth peer name eth1 netns ns4
317
318ip link add $DEV netns ns3 type veth peer name veth0 netns ns4
319
320DEV=veth0
321for i in 1 2; do
322 ip -net ns$i link set $DEV up
323 ip -net ns$i addr add 10.0.$i.2/24 dev $DEV
324 ip -net ns$i addr add dead:$i::2/64 dev $DEV
325
326 ip -net ns$i addr add 10.0.$i.253 dev $DEV
327 ip -net ns$i addr add 10.0.$i.254 dev $DEV
328 ip -net ns$i addr add dead:$i::fd dev $DEV
329 ip -net ns$i addr add dead:$i::fe dev $DEV
330done
331
332for i in 3 4; do
333ip -net ns$i link set eth1 up
334ip -net ns$i link set veth0 up
335done
336
337ip -net ns1 route add default via 10.0.1.1
338ip -net ns2 route add default via 10.0.2.1
339
340ip -net ns3 addr add 10.0.1.1/24 dev eth1
341ip -net ns3 addr add 10.0.3.1/24 dev veth0
342ip -net ns3 addr add 2001:1::1/64 dev eth1
343ip -net ns3 addr add 2001:3::1/64 dev veth0
344
345ip -net ns3 route add default via 10.0.3.10
346
347ip -net ns4 addr add 10.0.2.1/24 dev eth1
348ip -net ns4 addr add 10.0.3.10/24 dev veth0
349ip -net ns4 addr add 2001:2::1/64 dev eth1
350ip -net ns4 addr add 2001:3::10/64 dev veth0
351ip -net ns4 route add default via 10.0.3.1
352
353for j in 4 6; do
354 for i in 3 4;do
355 ip netns exec ns$i sysctl net.ipv$j.conf.eth1.forwarding=1 > /dev/null
356 ip netns exec ns$i sysctl net.ipv$j.conf.veth0.forwarding=1 > /dev/null
357 done
358done
359
360# abuse iptables rule counter to check if ping matches a policy
361ip netns exec ns3 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
362ip netns exec ns4 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
363if [ $? -ne 0 ];then
364 echo "SKIP: Could not insert iptables rule"
365 for i in 1 2 3 4;do ip netns del ns$i;done
366 exit $ksft_skip
367fi
368
369# localip remoteip localnet remotenet
370do_esp ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
371do_esp ns3 dead:3::1 dead:3::10 dead:1::/64 dead:2::/64 $SPI1 $SPI2
372do_esp ns4 10.0.3.10 10.0.3.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
373do_esp ns4 dead:3::10 dead:3::1 dead:2::/64 dead:1::/64 $SPI2 $SPI1
374
375do_dummies4 ns3
376do_dummies6 ns4
377
378do_esp_policy_get_check ns3 10.0.1.0/24 10.0.2.0/24
379do_esp_policy_get_check ns4 10.0.2.0/24 10.0.1.0/24
380do_esp_policy_get_check ns3 dead:1::/64 dead:2::/64
381do_esp_policy_get_check ns4 dead:2::/64 dead:1::/64
382
383# ping to .254 should use ipsec, exception is not installed.
384check_xfrm 1 254
385if [ $? -ne 0 ]; then
386 echo "FAIL: expected ping to .254 to use ipsec tunnel"
387 ret=1
388else
389 echo "PASS: policy before exception matches"
390fi
391
392# installs exceptions
393# localip remoteip encryptdst plaindst
394do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
395do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
396
397do_exception ns3 dead:3::1 dead:3::10 dead:2::fd dead:2:f0::/96
398do_exception ns4 dead:3::10 dead:3::1 dead:1::fd dead:1:f0::/96
399
400check_exceptions "exceptions"
401if [ $? -ne 0 ]; then
402 ret=1
403fi
404
405# insert block policies with adjacent/overlapping netmasks
406do_overlap ns3
407
408check_exceptions "exceptions and block policies"
409if [ $? -ne 0 ]; then
410 ret=1
411fi
412
413for n in ns3 ns4;do
414 ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
415 sleep $((RANDOM%5))
416done
417
418check_exceptions "exceptions and block policies after hresh changes"
419
420# full flush of policy db, check everything gets freed incl. internal meta data
421ip -net ns3 xfrm policy flush
422
423do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
424do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
425
426# move inexact policies to hash table
427ip -net ns3 xfrm policy set hthresh4 16 16
428
429sleep $((RANDOM%5))
430check_exceptions "exceptions and block policies after hthresh change in ns3"
431
432# restore original hthresh settings -- move policies back to tables
433for n in ns3 ns4;do
434 ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
435 sleep $((RANDOM%5))
436done
437check_exceptions "exceptions and block policies after htresh change to normal"
438
439check_hthresh_repeat "policies with repeated htresh change"
440
441for i in 1 2 3 4;do ip netns del ns$i;done
442
443exit $ret