1#!/bin/bash
2#
3# This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
4#
5
6# Kselftest framework requirement - SKIP code is 4.
7ksft_skip=4
8ret=0
9test_inet_nat=true
10
11cleanup()
12{
13	for i in 0 1 2; do ip netns del ns$i;done
14}
15
16nft --version > /dev/null 2>&1
17if [ $? -ne 0 ];then
18	echo "SKIP: Could not run test without nft tool"
19	exit $ksft_skip
20fi
21
22ip -Version > /dev/null 2>&1
23if [ $? -ne 0 ];then
24	echo "SKIP: Could not run test without ip tool"
25	exit $ksft_skip
26fi
27
28ip netns add ns0
29if [ $? -ne 0 ];then
30	echo "SKIP: Could not create net namespace"
31	exit $ksft_skip
32fi
33
34trap cleanup EXIT
35
36ip netns add ns1
37ip netns add ns2
38
39ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1
40if [ $? -ne 0 ];then
41    echo "SKIP: No virtual ethernet pair device support in kernel"
42    exit $ksft_skip
43fi
44ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
45
46ip -net ns0 link set lo up
47ip -net ns0 link set veth0 up
48ip -net ns0 addr add 10.0.1.1/24 dev veth0
49ip -net ns0 addr add dead:1::1/64 dev veth0
50
51ip -net ns0 link set veth1 up
52ip -net ns0 addr add 10.0.2.1/24 dev veth1
53ip -net ns0 addr add dead:2::1/64 dev veth1
54
55for i in 1 2; do
56  ip -net ns$i link set lo up
57  ip -net ns$i link set eth0 up
58  ip -net ns$i addr add 10.0.$i.99/24 dev eth0
59  ip -net ns$i route add default via 10.0.$i.1
60  ip -net ns$i addr add dead:$i::99/64 dev eth0
61  ip -net ns$i route add default via dead:$i::1
62done
63
64bad_counter()
65{
66	local ns=$1
67	local counter=$2
68	local expect=$3
69
70	echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
71	ip netns exec $ns nft list counter inet filter $counter 1>&2
72}
73
74check_counters()
75{
76	ns=$1
77	local lret=0
78
79	cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
80	if [ $? -ne 0 ]; then
81		bad_counter $ns ns0in "packets 1 bytes 84"
82		lret=1
83	fi
84	cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
85	if [ $? -ne 0 ]; then
86		bad_counter $ns ns0out "packets 1 bytes 84"
87		lret=1
88	fi
89
90	expect="packets 1 bytes 104"
91	cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
92	if [ $? -ne 0 ]; then
93		bad_counter $ns ns0in6 "$expect"
94		lret=1
95	fi
96	cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
97	if [ $? -ne 0 ]; then
98		bad_counter $ns ns0out6 "$expect"
99		lret=1
100	fi
101
102	return $lret
103}
104
105check_ns0_counters()
106{
107	local ns=$1
108	local lret=0
109
110	cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
111	if [ $? -ne 0 ]; then
112		bad_counter ns0 ns0in "packets 0 bytes 0"
113		lret=1
114	fi
115
116	cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
117	if [ $? -ne 0 ]; then
118		bad_counter ns0 ns0in6 "packets 0 bytes 0"
119		lret=1
120	fi
121
122	cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
123	if [ $? -ne 0 ]; then
124		bad_counter ns0 ns0out "packets 0 bytes 0"
125		lret=1
126	fi
127	cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
128	if [ $? -ne 0 ]; then
129		bad_counter ns0 ns0out6 "packets 0 bytes 0"
130		lret=1
131	fi
132
133	for dir in "in" "out" ; do
134		expect="packets 1 bytes 84"
135		cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
136		if [ $? -ne 0 ]; then
137			bad_counter ns0 $ns$dir "$expect"
138			lret=1
139		fi
140
141		expect="packets 1 bytes 104"
142		cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
143		if [ $? -ne 0 ]; then
144			bad_counter ns0 $ns$dir6 "$expect"
145			lret=1
146		fi
147	done
148
149	return $lret
150}
151
152reset_counters()
153{
154	for i in 0 1 2;do
155		ip netns exec ns$i nft reset counters inet > /dev/null
156	done
157}
158
159test_local_dnat6()
160{
161	local family=$1
162	local lret=0
163	local IPF=""
164
165	if [ $family = "inet" ];then
166		IPF="ip6"
167	fi
168
169ip netns exec ns0 nft -f - <<EOF
170table $family nat {
171	chain output {
172		type nat hook output priority 0; policy accept;
173		ip6 daddr dead:1::99 dnat $IPF to dead:2::99
174	}
175}
176EOF
177	if [ $? -ne 0 ]; then
178		echo "SKIP: Could not add add $family dnat hook"
179		return $ksft_skip
180	fi
181
182	# ping netns1, expect rewrite to netns2
183	ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
184	if [ $? -ne 0 ]; then
185		lret=1
186		echo "ERROR: ping6 failed"
187		return $lret
188	fi
189
190	expect="packets 0 bytes 0"
191	for dir in "in6" "out6" ; do
192		cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
193		if [ $? -ne 0 ]; then
194			bad_counter ns0 ns1$dir "$expect"
195			lret=1
196		fi
197	done
198
199	expect="packets 1 bytes 104"
200	for dir in "in6" "out6" ; do
201		cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
202		if [ $? -ne 0 ]; then
203			bad_counter ns0 ns2$dir "$expect"
204			lret=1
205		fi
206	done
207
208	# expect 0 count in ns1
209	expect="packets 0 bytes 0"
210	for dir in "in6" "out6" ; do
211		cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
212		if [ $? -ne 0 ]; then
213			bad_counter ns1 ns0$dir "$expect"
214			lret=1
215		fi
216	done
217
218	# expect 1 packet in ns2
219	expect="packets 1 bytes 104"
220	for dir in "in6" "out6" ; do
221		cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
222		if [ $? -ne 0 ]; then
223			bad_counter ns2 ns0$dir "$expect"
224			lret=1
225		fi
226	done
227
228	test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was $family NATted to ns2"
229	ip netns exec ns0 nft flush chain ip6 nat output
230
231	return $lret
232}
233
234test_local_dnat()
235{
236	local family=$1
237	local lret=0
238	local IPF=""
239
240	if [ $family = "inet" ];then
241		IPF="ip"
242	fi
243
244ip netns exec ns0 nft -f - <<EOF 2>/dev/null
245table $family nat {
246	chain output {
247		type nat hook output priority 0; policy accept;
248		ip daddr 10.0.1.99 dnat $IPF to 10.0.2.99
249	}
250}
251EOF
252	if [ $? -ne 0 ]; then
253		if [ $family = "inet" ];then
254			echo "SKIP: inet nat tests"
255			test_inet_nat=false
256			return $ksft_skip
257		fi
258		echo "SKIP: Could not add add $family dnat hook"
259		return $ksft_skip
260	fi
261
262	# ping netns1, expect rewrite to netns2
263	ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
264	if [ $? -ne 0 ]; then
265		lret=1
266		echo "ERROR: ping failed"
267		return $lret
268	fi
269
270	expect="packets 0 bytes 0"
271	for dir in "in" "out" ; do
272		cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
273		if [ $? -ne 0 ]; then
274			bad_counter ns0 ns1$dir "$expect"
275			lret=1
276		fi
277	done
278
279	expect="packets 1 bytes 84"
280	for dir in "in" "out" ; do
281		cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
282		if [ $? -ne 0 ]; then
283			bad_counter ns0 ns2$dir "$expect"
284			lret=1
285		fi
286	done
287
288	# expect 0 count in ns1
289	expect="packets 0 bytes 0"
290	for dir in "in" "out" ; do
291		cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
292		if [ $? -ne 0 ]; then
293			bad_counter ns1 ns0$dir "$expect"
294			lret=1
295		fi
296	done
297
298	# expect 1 packet in ns2
299	expect="packets 1 bytes 84"
300	for dir in "in" "out" ; do
301		cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
302		if [ $? -ne 0 ]; then
303			bad_counter ns2 ns0$dir "$expect"
304			lret=1
305		fi
306	done
307
308	test $lret -eq 0 && echo "PASS: ping to ns1 was $family NATted to ns2"
309
310	ip netns exec ns0 nft flush chain $family nat output
311
312	reset_counters
313	ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
314	if [ $? -ne 0 ]; then
315		lret=1
316		echo "ERROR: ping failed"
317		return $lret
318	fi
319
320	expect="packets 1 bytes 84"
321	for dir in "in" "out" ; do
322		cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
323		if [ $? -ne 0 ]; then
324			bad_counter ns1 ns1$dir "$expect"
325			lret=1
326		fi
327	done
328	expect="packets 0 bytes 0"
329	for dir in "in" "out" ; do
330		cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
331		if [ $? -ne 0 ]; then
332			bad_counter ns0 ns2$dir "$expect"
333			lret=1
334		fi
335	done
336
337	# expect 1 count in ns1
338	expect="packets 1 bytes 84"
339	for dir in "in" "out" ; do
340		cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
341		if [ $? -ne 0 ]; then
342			bad_counter ns0 ns0$dir "$expect"
343			lret=1
344		fi
345	done
346
347	# expect 0 packet in ns2
348	expect="packets 0 bytes 0"
349	for dir in "in" "out" ; do
350		cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
351		if [ $? -ne 0 ]; then
352			bad_counter ns2 ns2$dir "$expect"
353			lret=1
354		fi
355	done
356
357	test $lret -eq 0 && echo "PASS: ping to ns1 OK after $family nat output chain flush"
358
359	return $lret
360}
361
362
363test_masquerade6()
364{
365	local family=$1
366	local natflags=$2
367	local lret=0
368
369	ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
370
371	ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
372	if [ $? -ne 0 ] ; then
373		echo "ERROR: cannot ping ns1 from ns2 via ipv6"
374		return 1
375		lret=1
376	fi
377
378	expect="packets 1 bytes 104"
379	for dir in "in6" "out6" ; do
380		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
381		if [ $? -ne 0 ]; then
382			bad_counter ns1 ns2$dir "$expect"
383			lret=1
384		fi
385
386		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
387		if [ $? -ne 0 ]; then
388			bad_counter ns2 ns1$dir "$expect"
389			lret=1
390		fi
391	done
392
393	reset_counters
394
395# add masquerading rule
396ip netns exec ns0 nft -f - <<EOF
397table $family nat {
398	chain postrouting {
399		type nat hook postrouting priority 0; policy accept;
400		meta oif veth0 masquerade $natflags
401	}
402}
403EOF
404	if [ $? -ne 0 ]; then
405		echo "SKIP: Could not add add $family masquerade hook"
406		return $ksft_skip
407	fi
408
409	ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
410	if [ $? -ne 0 ] ; then
411		echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
412		lret=1
413	fi
414
415	# ns1 should have seen packets from ns0, due to masquerade
416	expect="packets 1 bytes 104"
417	for dir in "in6" "out6" ; do
418		cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
419		if [ $? -ne 0 ]; then
420			bad_counter ns1 ns0$dir "$expect"
421			lret=1
422		fi
423
424		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
425		if [ $? -ne 0 ]; then
426			bad_counter ns2 ns1$dir "$expect"
427			lret=1
428		fi
429	done
430
431	# ns1 should not have seen packets from ns2, due to masquerade
432	expect="packets 0 bytes 0"
433	for dir in "in6" "out6" ; do
434		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
435		if [ $? -ne 0 ]; then
436			bad_counter ns1 ns0$dir "$expect"
437			lret=1
438		fi
439
440		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
441		if [ $? -ne 0 ]; then
442			bad_counter ns2 ns1$dir "$expect"
443			lret=1
444		fi
445	done
446
447	ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
448	if [ $? -ne 0 ] ; then
449		echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)"
450		lret=1
451	fi
452
453	ip netns exec ns0 nft flush chain $family nat postrouting
454	if [ $? -ne 0 ]; then
455		echo "ERROR: Could not flush $family nat postrouting" 1>&2
456		lret=1
457	fi
458
459	test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for ns2"
460
461	return $lret
462}
463
464test_masquerade()
465{
466	local family=$1
467	local natflags=$2
468	local lret=0
469
470	ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
471	ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
472
473	ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
474	if [ $? -ne 0 ] ; then
475		echo "ERROR: cannot ping ns1 from ns2 $natflags"
476		lret=1
477	fi
478
479	expect="packets 1 bytes 84"
480	for dir in "in" "out" ; do
481		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
482		if [ $? -ne 0 ]; then
483			bad_counter ns1 ns2$dir "$expect"
484			lret=1
485		fi
486
487		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
488		if [ $? -ne 0 ]; then
489			bad_counter ns2 ns1$dir "$expect"
490			lret=1
491		fi
492	done
493
494	reset_counters
495
496# add masquerading rule
497ip netns exec ns0 nft -f - <<EOF
498table $family nat {
499	chain postrouting {
500		type nat hook postrouting priority 0; policy accept;
501		meta oif veth0 masquerade $natflags
502	}
503}
504EOF
505	if [ $? -ne 0 ]; then
506		echo "SKIP: Could not add add $family masquerade hook"
507		return $ksft_skip
508	fi
509
510	ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
511	if [ $? -ne 0 ] ; then
512		echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
513		lret=1
514	fi
515
516	# ns1 should have seen packets from ns0, due to masquerade
517	expect="packets 1 bytes 84"
518	for dir in "in" "out" ; do
519		cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
520		if [ $? -ne 0 ]; then
521			bad_counter ns1 ns0$dir "$expect"
522			lret=1
523		fi
524
525		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
526		if [ $? -ne 0 ]; then
527			bad_counter ns2 ns1$dir "$expect"
528			lret=1
529		fi
530	done
531
532	# ns1 should not have seen packets from ns2, due to masquerade
533	expect="packets 0 bytes 0"
534	for dir in "in" "out" ; do
535		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
536		if [ $? -ne 0 ]; then
537			bad_counter ns1 ns0$dir "$expect"
538			lret=1
539		fi
540
541		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
542		if [ $? -ne 0 ]; then
543			bad_counter ns2 ns1$dir "$expect"
544			lret=1
545		fi
546	done
547
548	ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
549	if [ $? -ne 0 ] ; then
550		echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)"
551		lret=1
552	fi
553
554	ip netns exec ns0 nft flush chain $family nat postrouting
555	if [ $? -ne 0 ]; then
556		echo "ERROR: Could not flush $family nat postrouting" 1>&2
557		lret=1
558	fi
559
560	test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for ns2"
561
562	return $lret
563}
564
565test_redirect6()
566{
567	local family=$1
568	local lret=0
569
570	ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
571
572	ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
573	if [ $? -ne 0 ] ; then
574		echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
575		lret=1
576	fi
577
578	expect="packets 1 bytes 104"
579	for dir in "in6" "out6" ; do
580		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
581		if [ $? -ne 0 ]; then
582			bad_counter ns1 ns2$dir "$expect"
583			lret=1
584		fi
585
586		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
587		if [ $? -ne 0 ]; then
588			bad_counter ns2 ns1$dir "$expect"
589			lret=1
590		fi
591	done
592
593	reset_counters
594
595# add redirect rule
596ip netns exec ns0 nft -f - <<EOF
597table $family nat {
598	chain prerouting {
599		type nat hook prerouting priority 0; policy accept;
600		meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
601	}
602}
603EOF
604	if [ $? -ne 0 ]; then
605		echo "SKIP: Could not add add $family redirect hook"
606		return $ksft_skip
607	fi
608
609	ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
610	if [ $? -ne 0 ] ; then
611		echo "ERROR: cannot ping ns1 from ns2 via ipv6 with active $family redirect"
612		lret=1
613	fi
614
615	# ns1 should have seen no packets from ns2, due to redirection
616	expect="packets 0 bytes 0"
617	for dir in "in6" "out6" ; do
618		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
619		if [ $? -ne 0 ]; then
620			bad_counter ns1 ns0$dir "$expect"
621			lret=1
622		fi
623	done
624
625	# ns0 should have seen packets from ns2, due to masquerade
626	expect="packets 1 bytes 104"
627	for dir in "in6" "out6" ; do
628		cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
629		if [ $? -ne 0 ]; then
630			bad_counter ns1 ns0$dir "$expect"
631			lret=1
632		fi
633	done
634
635	ip netns exec ns0 nft delete table $family nat
636	if [ $? -ne 0 ]; then
637		echo "ERROR: Could not delete $family nat table" 1>&2
638		lret=1
639	fi
640
641	test $lret -eq 0 && echo "PASS: $family IPv6 redirection for ns2"
642
643	return $lret
644}
645
646test_redirect()
647{
648	local family=$1
649	local lret=0
650
651	ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
652	ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
653
654	ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
655	if [ $? -ne 0 ] ; then
656		echo "ERROR: cannot ping ns1 from ns2"
657		lret=1
658	fi
659
660	expect="packets 1 bytes 84"
661	for dir in "in" "out" ; do
662		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
663		if [ $? -ne 0 ]; then
664			bad_counter ns1 ns2$dir "$expect"
665			lret=1
666		fi
667
668		cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
669		if [ $? -ne 0 ]; then
670			bad_counter ns2 ns1$dir "$expect"
671			lret=1
672		fi
673	done
674
675	reset_counters
676
677# add redirect rule
678ip netns exec ns0 nft -f - <<EOF
679table $family nat {
680	chain prerouting {
681		type nat hook prerouting priority 0; policy accept;
682		meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
683	}
684}
685EOF
686	if [ $? -ne 0 ]; then
687		echo "SKIP: Could not add add $family redirect hook"
688		return $ksft_skip
689	fi
690
691	ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
692	if [ $? -ne 0 ] ; then
693		echo "ERROR: cannot ping ns1 from ns2 with active $family ip redirect"
694		lret=1
695	fi
696
697	# ns1 should have seen no packets from ns2, due to redirection
698	expect="packets 0 bytes 0"
699	for dir in "in" "out" ; do
700
701		cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
702		if [ $? -ne 0 ]; then
703			bad_counter ns1 ns0$dir "$expect"
704			lret=1
705		fi
706	done
707
708	# ns0 should have seen packets from ns2, due to masquerade
709	expect="packets 1 bytes 84"
710	for dir in "in" "out" ; do
711		cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
712		if [ $? -ne 0 ]; then
713			bad_counter ns1 ns0$dir "$expect"
714			lret=1
715		fi
716	done
717
718	ip netns exec ns0 nft delete table $family nat
719	if [ $? -ne 0 ]; then
720		echo "ERROR: Could not delete $family nat table" 1>&2
721		lret=1
722	fi
723
724	test $lret -eq 0 && echo "PASS: $family IP redirection for ns2"
725
726	return $lret
727}
728
729
730# ip netns exec ns0 ping -c 1 -q 10.0.$i.99
731for i in 0 1 2; do
732ip netns exec ns$i nft -f - <<EOF
733table inet filter {
734	counter ns0in {}
735	counter ns1in {}
736	counter ns2in {}
737
738	counter ns0out {}
739	counter ns1out {}
740	counter ns2out {}
741
742	counter ns0in6 {}
743	counter ns1in6 {}
744	counter ns2in6 {}
745
746	counter ns0out6 {}
747	counter ns1out6 {}
748	counter ns2out6 {}
749
750	map nsincounter {
751		type ipv4_addr : counter
752		elements = { 10.0.1.1 : "ns0in",
753			     10.0.2.1 : "ns0in",
754			     10.0.1.99 : "ns1in",
755			     10.0.2.99 : "ns2in" }
756	}
757
758	map nsincounter6 {
759		type ipv6_addr : counter
760		elements = { dead:1::1 : "ns0in6",
761			     dead:2::1 : "ns0in6",
762			     dead:1::99 : "ns1in6",
763			     dead:2::99 : "ns2in6" }
764	}
765
766	map nsoutcounter {
767		type ipv4_addr : counter
768		elements = { 10.0.1.1 : "ns0out",
769			     10.0.2.1 : "ns0out",
770			     10.0.1.99: "ns1out",
771			     10.0.2.99: "ns2out" }
772	}
773
774	map nsoutcounter6 {
775		type ipv6_addr : counter
776		elements = { dead:1::1 : "ns0out6",
777			     dead:2::1 : "ns0out6",
778			     dead:1::99 : "ns1out6",
779			     dead:2::99 : "ns2out6" }
780	}
781
782	chain input {
783		type filter hook input priority 0; policy accept;
784		counter name ip saddr map @nsincounter
785		icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
786	}
787	chain output {
788		type filter hook output priority 0; policy accept;
789		counter name ip daddr map @nsoutcounter
790		icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
791	}
792}
793EOF
794done
795
796sleep 3
797# test basic connectivity
798for i in 1 2; do
799  ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
800  if [ $? -ne 0 ];then
801  	echo "ERROR: Could not reach other namespace(s)" 1>&2
802	ret=1
803  fi
804
805  ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
806  if [ $? -ne 0 ];then
807	echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
808	ret=1
809  fi
810  check_counters ns$i
811  if [ $? -ne 0 ]; then
812	ret=1
813  fi
814
815  check_ns0_counters ns$i
816  if [ $? -ne 0 ]; then
817	ret=1
818  fi
819  reset_counters
820done
821
822if [ $ret -eq 0 ];then
823	echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
824fi
825
826reset_counters
827test_local_dnat ip
828test_local_dnat6 ip6
829reset_counters
830$test_inet_nat && test_local_dnat inet
831$test_inet_nat && test_local_dnat6 inet
832
833for flags in "" "fully-random"; do
834reset_counters
835test_masquerade ip $flags
836test_masquerade6 ip6 $flags
837reset_counters
838$test_inet_nat && test_masquerade inet $flags
839$test_inet_nat && test_masquerade6 inet $flags
840done
841
842reset_counters
843test_redirect ip
844test_redirect6 ip6
845reset_counters
846$test_inet_nat && test_redirect inet
847$test_inet_nat && test_redirect6 inet
848
849exit $ret
850