Merge tag 'docs-5.12-2' of git://git.lwn.net/linux
[linux-2.6-microblaze.git] / tools / testing / selftests / net / xfrm_policy.sh
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.
22 ksft_skip=4
23 ret=0
24 policy_checks_ok=1
25
26 KEY_SHA=0xdeadbeef1234567890abcdefabcdefabcdefabcd
27 KEY_AES=0x0123456789abcdef0123456789012345
28 SPI1=0x1
29 SPI2=0x2
30
31 do_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
44 do_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.
71 do_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
118 do_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
138 do_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.
153 do_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
171 do_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
182 check_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
200 check_xfrm() {
201         # 0: iptables -m policy rule count == 0
202         # 1: iptables -m policy rule count != 0
203         rval=$1
204         ip=$2
205         local 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
232 check_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
267 check_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 # insert non-overlapping policies in a random order and check that
291 # all of them can be fetched using the traffic selectors.
292 check_random_order()
293 {
294         local ns=$1
295         local log=$2
296
297         for i in $(seq 100); do
298                 ip -net $ns xfrm policy flush
299                 for j in $(seq 0 16 255 | sort -R); do
300                         ip -net $ns xfrm policy add dst $j.0.0.0/24 dir out priority 10 action allow
301                 done
302                 for j in $(seq 0 16 255); do
303                         if ! ip -net $ns xfrm policy get dst $j.0.0.0/24 dir out > /dev/null; then
304                                 echo "FAIL: $log" 1>&2
305                                 return 1
306                         fi
307                 done
308         done
309
310         for i in $(seq 100); do
311                 ip -net $ns xfrm policy flush
312                 for j in $(seq 0 16 255 | sort -R); do
313                         local addr=$(printf "e000:0000:%02x00::/56" $j)
314                         ip -net $ns xfrm policy add dst $addr dir out priority 10 action allow
315                 done
316                 for j in $(seq 0 16 255); do
317                         local addr=$(printf "e000:0000:%02x00::/56" $j)
318                         if ! ip -net $ns xfrm policy get dst $addr dir out > /dev/null; then
319                                 echo "FAIL: $log" 1>&2
320                                 return 1
321                         fi
322                 done
323         done
324
325         ip -net $ns xfrm policy flush
326
327         echo "PASS: $log"
328         return 0
329 }
330
331 #check for needed privileges
332 if [ "$(id -u)" -ne 0 ];then
333         echo "SKIP: Need root privileges"
334         exit $ksft_skip
335 fi
336
337 ip -Version 2>/dev/null >/dev/null
338 if [ $? -ne 0 ];then
339         echo "SKIP: Could not run test without the ip tool"
340         exit $ksft_skip
341 fi
342
343 # needed to check if policy lookup got valid ipsec result
344 iptables --version 2>/dev/null >/dev/null
345 if [ $? -ne 0 ];then
346         echo "SKIP: Could not run test without iptables tool"
347         exit $ksft_skip
348 fi
349
350 for i in 1 2 3 4; do
351     ip netns add ns$i
352     ip -net ns$i link set lo up
353 done
354
355 DEV=veth0
356 ip link add $DEV netns ns1 type veth peer name eth1 netns ns3
357 ip link add $DEV netns ns2 type veth peer name eth1 netns ns4
358
359 ip link add $DEV netns ns3 type veth peer name veth0 netns ns4
360
361 DEV=veth0
362 for i in 1 2; do
363     ip -net ns$i link set $DEV up
364     ip -net ns$i addr add 10.0.$i.2/24 dev $DEV
365     ip -net ns$i addr add dead:$i::2/64 dev $DEV
366
367     ip -net ns$i addr add 10.0.$i.253 dev $DEV
368     ip -net ns$i addr add 10.0.$i.254 dev $DEV
369     ip -net ns$i addr add dead:$i::fd dev $DEV
370     ip -net ns$i addr add dead:$i::fe dev $DEV
371 done
372
373 for i in 3 4; do
374 ip -net ns$i link set eth1 up
375 ip -net ns$i link set veth0 up
376 done
377
378 ip -net ns1 route add default via 10.0.1.1
379 ip -net ns2 route add default via 10.0.2.1
380
381 ip -net ns3 addr add 10.0.1.1/24 dev eth1
382 ip -net ns3 addr add 10.0.3.1/24 dev veth0
383 ip -net ns3 addr add 2001:1::1/64 dev eth1
384 ip -net ns3 addr add 2001:3::1/64 dev veth0
385
386 ip -net ns3 route add default via 10.0.3.10
387
388 ip -net ns4 addr add 10.0.2.1/24 dev eth1
389 ip -net ns4 addr add 10.0.3.10/24 dev veth0
390 ip -net ns4 addr add 2001:2::1/64 dev eth1
391 ip -net ns4 addr add 2001:3::10/64 dev veth0
392 ip -net ns4 route add default via 10.0.3.1
393
394 for j in 4 6; do
395         for i in 3 4;do
396                 ip netns exec ns$i sysctl net.ipv$j.conf.eth1.forwarding=1 > /dev/null
397                 ip netns exec ns$i sysctl net.ipv$j.conf.veth0.forwarding=1 > /dev/null
398         done
399 done
400
401 # abuse iptables rule counter to check if ping matches a policy
402 ip netns exec ns3 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
403 ip netns exec ns4 iptables -p icmp -A FORWARD -m policy --dir out --pol ipsec
404 if [ $? -ne 0 ];then
405         echo "SKIP: Could not insert iptables rule"
406         for i in 1 2 3 4;do ip netns del ns$i;done
407         exit $ksft_skip
408 fi
409
410 #          localip  remoteip  localnet    remotenet
411 do_esp ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24 $SPI1 $SPI2
412 do_esp ns3 dead:3::1 dead:3::10 dead:1::/64 dead:2::/64 $SPI1 $SPI2
413 do_esp ns4 10.0.3.10 10.0.3.1 10.0.2.0/24 10.0.1.0/24 $SPI2 $SPI1
414 do_esp ns4 dead:3::10 dead:3::1 dead:2::/64 dead:1::/64 $SPI2 $SPI1
415
416 do_dummies4 ns3
417 do_dummies6 ns4
418
419 do_esp_policy_get_check ns3 10.0.1.0/24 10.0.2.0/24
420 do_esp_policy_get_check ns4 10.0.2.0/24 10.0.1.0/24
421 do_esp_policy_get_check ns3 dead:1::/64 dead:2::/64
422 do_esp_policy_get_check ns4 dead:2::/64 dead:1::/64
423
424 # ping to .254 should use ipsec, exception is not installed.
425 check_xfrm 1 254
426 if [ $? -ne 0 ]; then
427         echo "FAIL: expected ping to .254 to use ipsec tunnel"
428         ret=1
429 else
430         echo "PASS: policy before exception matches"
431 fi
432
433 # installs exceptions
434 #                localip  remoteip   encryptdst  plaindst
435 do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
436 do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
437
438 do_exception ns3 dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96
439 do_exception ns4 dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96
440
441 check_exceptions "exceptions"
442 if [ $? -ne 0 ]; then
443         ret=1
444 fi
445
446 # insert block policies with adjacent/overlapping netmasks
447 do_overlap ns3
448
449 check_exceptions "exceptions and block policies"
450 if [ $? -ne 0 ]; then
451         ret=1
452 fi
453
454 for n in ns3 ns4;do
455         ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
456         sleep $((RANDOM%5))
457 done
458
459 check_exceptions "exceptions and block policies after hresh changes"
460
461 # full flush of policy db, check everything gets freed incl. internal meta data
462 ip -net ns3 xfrm policy flush
463
464 do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
465 do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
466
467 # move inexact policies to hash table
468 ip -net ns3 xfrm policy set hthresh4 16 16
469
470 sleep $((RANDOM%5))
471 check_exceptions "exceptions and block policies after hthresh change in ns3"
472
473 # restore original hthresh settings -- move policies back to tables
474 for n in ns3 ns4;do
475         ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
476         sleep $((RANDOM%5))
477 done
478 check_exceptions "exceptions and block policies after htresh change to normal"
479
480 check_hthresh_repeat "policies with repeated htresh change"
481
482 check_random_order ns3 "policies inserted in random order"
483
484 for i in 1 2 3 4;do ip netns del ns$i;done
485
486 exit $ret