xref: /freebsd/tests/sys/netpfil/pf/nat64.sh (revision f6f116cdbd2a406d2913df5368299ba4cdbf40a1)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2024 Rubicon Communications, LLC (Netgate)
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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26
27. $(atf_get_srcdir)/utils.subr
28
29nat64_setup_base()
30{
31	pft_init
32
33	epair_link=$(vnet_mkepair)
34	epair=$(vnet_mkepair)
35
36	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
37	route -6 add default 2001:db8::1
38
39	vnet_mkjail rtr ${epair}b ${epair_link}a
40	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
41	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
42
43	vnet_mkjail dst ${epair_link}b
44	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
45	jexec dst route add default 192.0.2.1
46
47	# Sanity checks
48	atf_check -s exit:0 -o ignore \
49	    ping6 -c 1 2001:db8::1
50	atf_check -s exit:0 -o ignore \
51	    jexec dst ping -c 1 192.0.2.1
52
53	jexec rtr pfctl -e
54}
55
56nat64_setup_in()
57{
58	nat64_setup_base
59	pft_set_rules rtr \
60	    "set reassemble yes" \
61	    "set state-policy if-bound" \
62	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)"
63}
64
65nat64_setup_out()
66{
67	nat64_setup_base
68	jexec rtr sysctl net.inet6.ip6.forwarding=1
69	# AF translation happens post-routing, traffic must be directed
70	# towards the outbound interface using routes for the original AF.
71	# jexec rtr ifconfig ${epair_link}a inet6 2001:db8:2::1/64 up no_dad
72	jexec rtr route add -inet6 64:ff9b::/96 -iface ${epair_link}a;
73	pft_set_rules rtr \
74	    "set reassemble yes" \
75	    "set state-policy if-bound" \
76	    "pass quick inet6 proto icmp6 icmp6-type { neighbrsol, neighbradv }" \
77	    "pass in  quick on ${epair}b from any to 64:ff9b::/96" \
78	    "pass out quick on ${epair_link}a from any to 64:ff9b::/96 af-to inet from (${epair_link}a)" \
79	    "block"
80}
81
82atf_test_case "icmp_echo_in" "cleanup"
83icmp_echo_in_head()
84{
85	atf_set descr 'Basic NAT64 ICMP echo test on inbound interface'
86	atf_set require.user root
87}
88
89icmp_echo_in_body()
90{
91	nat64_setup_in
92
93	# One ping
94	atf_check -s exit:0 -o ignore \
95	    ping6 -c 1 64:ff9b::192.0.2.2
96
97	# Make sure packets make it even when state is established
98	atf_check -s exit:0 \
99	    -o match:'5 packets transmitted, 5 packets received, 0.0% packet loss' \
100	    ping6 -c 5 64:ff9b::192.0.2.2
101}
102
103icmp_echo_in_cleanup()
104{
105	pft_cleanup
106}
107
108atf_test_case "icmp_echo_out" "cleanup"
109icmp_echo_out_head()
110{
111	atf_set descr 'Basic NAT64 ICMP echo test on outbound interface'
112	atf_set require.user root
113}
114
115icmp_echo_out_body()
116{
117	nat64_setup_out
118
119	# One ping
120	atf_check -s exit:0 -o ignore \
121	    ping6 -c 1 64:ff9b::192.0.2.2
122
123	# Make sure packets make it even when state is established
124	atf_check -s exit:0 \
125	    -o match:'5 packets transmitted, 5 packets received, 0.0% packet loss' \
126	    ping6 -c 5 64:ff9b::192.0.2.2
127}
128
129icmp_echo_out_cleanup()
130{
131	pft_cleanup
132}
133
134atf_test_case "fragmentation_in" "cleanup"
135fragmentation_in_head()
136{
137	atf_set descr 'Test fragmented packets on inbound interface'
138	atf_set require.user root
139}
140
141fragmentation_in_body()
142{
143	nat64_setup_in
144
145	atf_check -s exit:0 -o ignore \
146	    ping6 -c 1 -s 1280 64:ff9b::192.0.2.2
147
148	atf_check -s exit:0 \
149	    -o match:'3 packets transmitted, 3 packets received, 0.0% packet loss' \
150	    ping6 -c 3 -s 2000 64:ff9b::192.0.2.2
151	atf_check -s exit:0 \
152	    -o match:'3 packets transmitted, 3 packets received, 0.0% packet loss' \
153	    ping6 -c 3 -s 10000 -b 20000 64:ff9b::192.0.2.2
154}
155
156fragmentation_in_cleanup()
157{
158	pft_cleanup
159}
160
161atf_test_case "fragmentation_out" "cleanup"
162fragmentation_out_head()
163{
164	atf_set descr 'Test fragmented packets on outbound interface'
165	atf_set require.user root
166}
167
168fragmentation_out_body()
169{
170	nat64_setup_out
171
172	atf_check -s exit:0 -o ignore \
173	    ping6 -c 1 -s 1280 64:ff9b::192.0.2.2
174
175	atf_check -s exit:0 \
176	    -o match:'3 packets transmitted, 3 packets received, 0.0% packet loss' \
177	    ping6 -c 3 -s 2000 64:ff9b::192.0.2.2
178	atf_check -s exit:0 \
179	    -o match:'3 packets transmitted, 3 packets received, 0.0% packet loss' \
180	    ping6 -c 3 -s 10000 -b 20000 64:ff9b::192.0.2.2
181}
182
183fragmentation_out_cleanup()
184{
185	pft_cleanup
186}
187
188atf_test_case "tcp_in" "cleanup"
189tcp_in_head()
190{
191	atf_set descr 'TCP NAT64 test on inbound interface'
192	atf_set require.user root
193}
194
195tcp_in_body()
196{
197	nat64_setup_in
198
199	echo "foo" | jexec dst nc -l 1234 &
200
201	# Sanity check & delay for nc startup
202	atf_check -s exit:0 -o ignore \
203	    ping6 -c 1 64:ff9b::192.0.2.2
204
205	rcv=$(nc -w 3 -6 64:ff9b::c000:202 1234)
206	if [ "${rcv}" != "foo" ];
207	then
208		echo "rcv=${rcv}"
209		atf_fail "Failed to connect to TCP server"
210	fi
211}
212
213tcp_in_cleanup()
214{
215	pft_cleanup
216}
217
218atf_test_case "tcp_out" "cleanup"
219tcp_out_head()
220{
221	atf_set descr 'TCP NAT64 test on outbound interface'
222	atf_set require.user root
223}
224
225tcp_out_body()
226{
227	nat64_setup_out
228
229	echo "foo" | jexec dst nc -l 1234 &
230
231	# Sanity check & delay for nc startup
232	atf_check -s exit:0 -o ignore \
233	    ping6 -c 1 64:ff9b::192.0.2.2
234
235	rcv=$(nc -w 3 -6 64:ff9b::c000:202 1234)
236	if [ "${rcv}" != "foo" ];
237	then
238		echo "rcv=${rcv}"
239		atf_fail "Failed to connect to TCP server"
240	fi
241}
242
243tcp_out_cleanup()
244{
245	pft_cleanup
246}
247
248atf_test_case "udp_in" "cleanup"
249udp_in_head()
250{
251	atf_set descr 'UDP NAT64 test on inbound interface'
252	atf_set require.user root
253}
254
255udp_in_body()
256{
257	nat64_setup_in
258
259	echo "foo" | jexec dst nc -u -l 1234 &
260
261	# Sanity check & delay for nc startup
262	atf_check -s exit:0 -o ignore \
263	    ping6 -c 1 64:ff9b::192.0.2.2
264
265	rcv=$(echo bar | nc -w 3 -6 -u 64:ff9b::c000:202 1234)
266	if [ "${rcv}" != "foo" ];
267	then
268		echo "rcv=${rcv}"
269		atf_fail "Failed to connect to UDP server"
270	fi
271}
272
273udp_in_cleanup()
274{
275	pft_cleanup
276}
277
278atf_test_case "udp_out" "cleanup"
279udp_out_head()
280{
281	atf_set descr 'UDP NAT64 test on outbound interface'
282	atf_set require.user root
283}
284
285udp_out_body()
286{
287	nat64_setup_out
288
289	echo "foo" | jexec dst nc -u -l 1234 &
290
291	# Sanity check & delay for nc startup
292	atf_check -s exit:0 -o ignore \
293	    ping6 -c 1 64:ff9b::192.0.2.2
294
295	rcv=$(echo bar | nc -w 3 -6 -u 64:ff9b::c000:202 1234)
296	if [ "${rcv}" != "foo" ];
297	then
298		echo "rcv=${rcv}"
299		atf_fail "Failed to connect to UDP server"
300	fi
301}
302
303udp_out_cleanup()
304{
305	pft_cleanup
306}
307
308atf_test_case "sctp_in" "cleanup"
309sctp_in_head()
310{
311	atf_set descr 'SCTP NAT64 test on inbound interface'
312	atf_set require.user root
313}
314
315sctp_in_body()
316{
317	nat64_setup_in
318	if ! kldstat -q -m sctp; then
319		atf_skip "This test requires SCTP"
320	fi
321
322	echo "foo" | jexec dst nc --sctp -N -l 1234 &
323
324	# Sanity check & delay for nc startup
325	atf_check -s exit:0 -o ignore \
326	    ping6 -c 1 64:ff9b::192.0.2.2
327
328	rcv=$(echo bar | nc --sctp -w 3 -6 64:ff9b::c000:202 1234)
329	if [ "${rcv}" != "foo" ];
330	then
331		echo "rcv=${rcv}"
332		atf_fail "Failed to connect to SCTP server"
333	fi
334}
335
336sctp_in_cleanup()
337{
338	pft_cleanup
339}
340
341atf_test_case "sctp_out" "cleanup"
342sctp_out_head()
343{
344	atf_set descr 'SCTP NAT64 test on outbound interface'
345	atf_set require.user root
346}
347
348sctp_out_body()
349{
350	nat64_setup_out
351	if ! kldstat -q -m sctp; then
352		atf_skip "This test requires SCTP"
353	fi
354
355	echo "foo" | jexec dst nc --sctp -N -l 1234 &
356
357	# Sanity check & delay for nc startup
358	atf_check -s exit:0 -o ignore \
359	    ping6 -c 1 64:ff9b::192.0.2.2
360
361	rcv=$(echo bar | nc --sctp -w 3 -6 64:ff9b::c000:202 1234)
362	if [ "${rcv}" != "foo" ];
363	then
364		echo "rcv=${rcv}"
365		atf_fail "Failed to connect to SCTP server"
366	fi
367}
368
369sctp_out_cleanup()
370{
371	pft_cleanup
372}
373
374atf_test_case "tos" "cleanup"
375tos_head()
376{
377	atf_set descr 'ToS translation test'
378	atf_set require.user root
379}
380
381tos_body()
382{
383	nat64_setup_in
384
385	# Ensure we can distinguish ToS on the destination
386	jexec dst pfctl -e
387	pft_set_rules dst \
388	    "pass" \
389	    "block in inet tos 8"
390
391	atf_check -s exit:0 -o ignore \
392	    ping6 -c 1 -z 4 64:ff9b::192.0.2.2
393	atf_check -s exit:2 -o ignore \
394	    ping6 -c 1 -z 8 64:ff9b::192.0.2.2
395	atf_check -s exit:0 -o ignore \
396	    ping6 -c 1 -z 16 64:ff9b::192.0.2.2
397
398	jexec dst pfctl -sr -vv
399}
400
401tos_cleanup()
402{
403	pft_cleanup
404}
405
406atf_test_case "no_v4" "cleanup"
407no_v4_head()
408{
409	atf_set descr 'Test error handling when there is no IPv4 address to translate to'
410	atf_set require.user root
411}
412
413no_v4_body()
414{
415	pft_init
416
417	epair_link=$(vnet_mkepair)
418	epair=$(vnet_mkepair)
419
420	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
421	route -6 add default 2001:db8::1
422
423	vnet_mkjail rtr ${epair}b ${epair_link}a
424	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
425
426	vnet_mkjail dst ${epair_link}b
427	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
428	jexec dst route add default 192.0.2.1
429
430	# Sanity check
431	atf_check -s exit:0 -o ignore \
432	    ping6 -c 1 2001:db8::1
433
434	jexec rtr pfctl -e
435	pft_set_rules rtr \
436	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)"
437
438	atf_check -s exit:2 -o ignore \
439	    ping6 -c 3 64:ff9b::192.0.2.2
440}
441
442no_v4_cleanup()
443{
444	pft_cleanup
445}
446
447atf_test_case "range" "cleanup"
448range_head()
449{
450	atf_set descr 'Test using an address range for the IPv4 side'
451	atf_set require.user root
452}
453
454range_body()
455{
456	pft_init
457
458	epair_link=$(vnet_mkepair)
459	epair=$(vnet_mkepair)
460
461	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
462	route -6 add default 2001:db8::1
463
464	vnet_mkjail rtr ${epair}b ${epair_link}a
465	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
466	jexec rtr ifconfig ${epair_link}a 192.0.2.2/24 up
467	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.3/24 up
468
469	vnet_mkjail dst ${epair_link}b
470	jexec dst ifconfig ${epair_link}b 192.0.2.254/24 up
471	jexec dst route add default 192.0.2.2
472
473	# Sanity checks
474	atf_check -s exit:0 -o ignore \
475	    jexec rtr ping -c 1 192.0.2.254
476	atf_check -s exit:0 -o ignore \
477	    ping6 -c 1 2001:db8::1
478	atf_check -s exit:0 -o ignore \
479	    jexec dst ping -c 1 192.0.2.2
480	atf_check -s exit:0 -o ignore \
481	    jexec dst ping -c 1 192.0.2.3
482
483	jexec rtr pfctl -e
484	pft_set_rules rtr \
485	    "set reassemble yes" \
486	    "set state-policy if-bound" \
487	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from 192.0.2.2/31 round-robin"
488
489	# Use pf to count sources
490	jexec dst pfctl -e
491	pft_set_rules dst \
492	    "pass"
493
494	atf_check -s exit:0 -o ignore \
495	    ping6 -c 1 64:ff9b::192.0.2.254
496	atf_check -s exit:0 -o ignore \
497	    ping6 -c 1 64:ff9b::192.0.2.254
498
499	# Verify on dst that we saw different source addresses
500	atf_check -s exit:0 -o match:".*192.0.2.2.*" \
501	    jexec dst pfctl -ss
502	atf_check -s exit:0 -o match:".*192.0.2.3.*" \
503	    jexec dst pfctl -ss
504}
505
506range_cleanup()
507{
508	pft_cleanup
509}
510
511atf_test_case "pool" "cleanup"
512pool_head()
513{
514	atf_set descr 'Use a pool of IPv4 addresses'
515	atf_set require.user root
516}
517
518pool_body()
519{
520	pft_init
521
522	epair_link=$(vnet_mkepair)
523	epair=$(vnet_mkepair)
524
525	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
526	route -6 add default 2001:db8::1
527
528	vnet_mkjail rtr ${epair}b ${epair_link}a
529	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
530	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
531	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.3/24 up
532	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.4/24 up
533
534	vnet_mkjail dst ${epair_link}b
535	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
536	jexec dst route add default 192.0.2.1
537
538	# Sanity checks
539	atf_check -s exit:0 -o ignore \
540	    ping6 -c 1 2001:db8::1
541	atf_check -s exit:0 -o ignore \
542	    jexec dst ping -c 1 192.0.2.1
543
544	jexec rtr pfctl -e
545	pft_set_rules rtr \
546	    "set reassemble yes" \
547	    "set state-policy if-bound" \
548	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from { 192.0.2.1, 192.0.2.3, 192.0.2.4 } round-robin"
549
550	# Use pf to count sources
551	jexec dst pfctl -e
552	pft_set_rules dst \
553	    "pass"
554
555	atf_check -s exit:0 -o ignore \
556	    ping6 -c 1 64:ff9b::192.0.2.2
557	atf_check -s exit:0 -o ignore \
558	    ping6 -c 1 64:ff9b::192.0.2.2
559	atf_check -s exit:0 -o ignore \
560	    ping6 -c 1 64:ff9b::192.0.2.2
561
562	# Verify on dst that we saw different source addresses
563	atf_check -s exit:0 -o match:".*192.0.2.1.*" \
564	    jexec dst pfctl -ss
565	atf_check -s exit:0 -o match:".*192.0.2.3.*" \
566	    jexec dst pfctl -ss
567	atf_check -s exit:0 -o match:".*192.0.2.4.*" \
568	    jexec dst pfctl -ss
569}
570
571pool_cleanup()
572{
573	pft_cleanup
574}
575
576
577atf_test_case "table"
578table_head()
579{
580	atf_set descr 'Check table restrictions'
581	atf_set require.user root
582}
583
584table_body()
585{
586	pft_init
587
588	# Round-robin and random are allowed
589	echo "pass in on epair inet6 from any to 64:ff9b::/96 af-to inet from <wanaddr> round-robin" | \
590	    atf_check -s exit:0 \
591	    pfctl -f -
592	echo "pass in on epair inet6 from any to 64:ff9b::/96 af-to inet from <wanaddr> random" | \
593	    atf_check -s exit:0 \
594	    pfctl -f -
595
596	# bitmask is not
597	echo "pass in on epair inet6 from any to 64:ff9b::/96 af-to inet from <wanaddr> bitmask" | \
598	    atf_check -s exit:1 \
599	    -e match:"tables are not supported by pool type" \
600	    pfctl -f -
601}
602
603table_cleanup()
604{
605	pft_cleanup
606}
607
608atf_test_case "table_range" "cleanup"
609table_range_head()
610{
611	atf_set descr 'Test using an address range within a table for the IPv4 side'
612	atf_set require.user root
613}
614
615table_range_body()
616{
617	pft_init
618
619	epair_link=$(vnet_mkepair)
620	epair=$(vnet_mkepair)
621
622	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
623	route -6 add default 2001:db8::1
624
625	vnet_mkjail rtr ${epair}b ${epair_link}a
626	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
627	jexec rtr ifconfig ${epair_link}a 192.0.2.2/24 up
628	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.3/24 up
629
630	vnet_mkjail dst ${epair_link}b
631	jexec dst ifconfig ${epair_link}b 192.0.2.254/24 up
632	jexec dst route add default 192.0.2.2
633
634	# Sanity checks
635	atf_check -s exit:0 -o ignore \
636	    ping6 -c 1 2001:db8::1
637	atf_check -s exit:0 -o ignore \
638	    jexec dst ping -c 1 192.0.2.2
639
640	jexec rtr pfctl -e
641	pft_set_rules rtr \
642	    "set reassemble yes" \
643	    "set state-policy if-bound" \
644	    "table <wanaddrs> { 192.0.2.2/31 }" \
645	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from <wanaddrs> round-robin"
646
647	# Use pf to count sources
648	jexec dst pfctl -e
649	pft_set_rules dst \
650	    "pass"
651
652	atf_check -s exit:0 -o ignore \
653	    ping6 -c 1 64:ff9b::192.0.2.254
654	atf_check -s exit:0 -o ignore \
655	    ping6 -c 1 64:ff9b::192.0.2.254
656
657	# Verify on dst that we saw different source addresses
658	atf_check -s exit:0 -o match:".*192.0.2.2.*" \
659	    jexec dst pfctl -ss
660	atf_check -s exit:0 -o match:".*192.0.2.3.*" \
661	    jexec dst pfctl -ss
662}
663
664table_range_cleanup()
665{
666	pft_cleanup
667}
668
669table_common_body()
670{
671	pool_type=$1
672
673	pft_init
674
675	epair_link=$(vnet_mkepair)
676	epair=$(vnet_mkepair)
677
678	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
679	route -6 add default 2001:db8::1
680
681	vnet_mkjail rtr ${epair}b ${epair_link}a
682	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
683	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
684	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.3/24 up
685	jexec rtr ifconfig ${epair_link}a inet alias 192.0.2.4/24 up
686
687	vnet_mkjail dst ${epair_link}b
688	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
689	jexec dst route add default 192.0.2.1
690
691	# Sanity checks
692	atf_check -s exit:0 -o ignore \
693	    ping6 -c 1 2001:db8::1
694	atf_check -s exit:0 -o ignore \
695	    jexec dst ping -c 1 192.0.2.1
696
697	jexec rtr pfctl -e
698	pft_set_rules rtr \
699	    "set reassemble yes" \
700	    "set state-policy if-bound" \
701	    "table <wanaddrs> { 192.0.2.1, 192.0.2.3, 192.0.2.4 }" \
702	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 af-to inet from <wanaddrs> ${pool_type}"
703
704	# Use pf to count sources
705	jexec dst pfctl -e
706	pft_set_rules dst \
707	    "pass"
708
709	atf_check -s exit:0 -o ignore \
710	    ping6 -c 1 64:ff9b::192.0.2.2
711	atf_check -s exit:0 -o ignore \
712	    ping6 -c 1 64:ff9b::192.0.2.2
713	atf_check -s exit:0 -o ignore \
714	    ping6 -c 1 64:ff9b::192.0.2.2
715
716	# XXX We can't reasonably check pool type random because it's random. It may end
717	# up choosing the same source IP for all three connections.
718	if [ "${pool_type}" == "round-robin" ];
719	then
720		# Verify on dst that we saw different source addresses
721		atf_check -s exit:0 -o match:".*192.0.2.1.*" \
722		    jexec dst pfctl -ss
723		atf_check -s exit:0 -o match:".*192.0.2.3.*" \
724		    jexec dst pfctl -ss
725		atf_check -s exit:0 -o match:".*192.0.2.4.*" \
726		    jexec dst pfctl -ss
727	fi
728}
729
730atf_test_case "table_round_robin" "cleanup"
731table_round_robin_head()
732{
733	atf_set descr 'Use a table of IPv4 addresses in round-robin mode'
734	atf_set require.user root
735}
736
737table_round_robin_body()
738{
739	table_common_body round-robin
740}
741
742table_round_robin_cleanup()
743{
744	pft_cleanup
745}
746
747atf_test_case "table_random" "cleanup"
748table_random_head()
749{
750	atf_set descr 'Use a table of IPv4 addresses in random mode'
751	atf_set require.user root
752}
753
754table_random_body()
755{
756	table_common_body random
757}
758
759table_random_cleanup()
760{
761	pft_cleanup
762}
763
764atf_test_case "dummynet" "cleanup"
765dummynet_head()
766{
767	atf_set descr 'Test dummynet on af-to rules'
768	atf_set require.user root
769}
770
771dummynet_body()
772{
773	pft_init
774	dummynet_init
775
776	epair_link=$(vnet_mkepair)
777	epair=$(vnet_mkepair)
778
779	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
780	route -6 add default 2001:db8::1
781
782	vnet_mkjail rtr ${epair}b ${epair_link}a
783	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
784	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
785
786	vnet_mkjail dst ${epair_link}b
787	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
788	jexec dst route add default 192.0.2.1
789
790	# Sanity checks
791	atf_check -s exit:0 -o ignore \
792	    ping6 -c 1 2001:db8::1
793	atf_check -s exit:0 -o ignore \
794	    jexec dst ping -c 1 192.0.2.1
795
796	jexec rtr pfctl -e
797	jexec rtr dnctl pipe 1 config delay 600
798	pft_set_rules rtr \
799	    "set reassemble yes" \
800	    "set state-policy if-bound" \
801	    "pass in on ${epair}b inet6 from any to 64:ff9b::/96 dnpipe 1 af-to inet from (${epair_link}a)"
802
803	# The ping request will pass, but take 1.2 seconds (.6 in, .6 out)
804	# So this works:
805	atf_check -s exit:0 -o ignore \
806	    ping6 -c 1 -t 2 64:ff9b::192.0.2.2
807
808	# But this times out:
809	atf_check -s exit:2 -o ignore \
810	    ping6 -c 1 -t 1 64:ff9b::192.0.2.2
811}
812
813dummynet_cleanup()
814{
815	pft_cleanup
816}
817
818atf_test_case "gateway6" "cleanup"
819gateway6_head()
820{
821	atf_set descr 'NAT64 with a routing hop on the v6 side'
822	atf_set require.user root
823}
824
825gateway6_body()
826{
827	pft_init
828
829	epair_lan_link=$(vnet_mkepair)
830	epair_link=$(vnet_mkepair)
831	epair=$(vnet_mkepair)
832
833	ifconfig ${epair}a inet6 2001:db8:1::2/64 up no_dad
834	route -6 add default 2001:db8:1::1
835
836	vnet_mkjail lan_rtr ${epair}b ${epair_lan_link}a
837	jexec lan_rtr ifconfig ${epair}b inet6 2001:db8:1::1/64 up no_dad
838	jexec lan_rtr ifconfig ${epair_lan_link}a inet6 2001:db8::2/64 up no_dad
839	jexec lan_rtr route -6 add default 2001:db8::1
840	jexec lan_rtr sysctl net.inet6.ip6.forwarding=1
841
842	vnet_mkjail rtr ${epair_lan_link}b ${epair_link}a
843	jexec rtr ifconfig ${epair_lan_link}b inet6 2001:db8::1/64 up no_dad
844	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
845	jexec rtr route -6 add default 2001:db8::2
846
847	vnet_mkjail dst ${epair_link}b
848	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
849	jexec dst route add default 192.0.2.1
850
851	# Sanity checks
852	atf_check -s exit:0 -o ignore \
853	    ping6 -c 1 2001:db8:1::1
854	atf_check -s exit:0 -o ignore \
855	    ping6 -c 1 2001:db8::1
856	atf_check -s exit:0 -o ignore \
857	    jexec dst ping -c 1 192.0.2.1
858
859	jexec rtr pfctl -e
860	pft_set_rules rtr \
861	    "set reassemble yes" \
862	    "set state-policy if-bound" \
863	    "pass in on ${epair_lan_link}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)"
864
865	# One ping
866	atf_check -s exit:0 -o ignore \
867	    ping6 -c 1 64:ff9b::192.0.2.2
868
869	# Make sure packets make it even when state is established
870	atf_check -s exit:0 \
871	    -o match:'5 packets transmitted, 5 packets received, 0.0% packet loss' \
872	    ping6 -c 5 64:ff9b::192.0.2.2
873}
874
875gateway6_cleanup()
876{
877	pft_cleanup
878}
879
880atf_test_case "route_to" "cleanup"
881route_to_head()
882{
883	atf_set descr 'Test route-to on af-to rules'
884	atf_set require.user root
885}
886
887route_to_body()
888{
889	pft_init
890
891	epair_link=$(vnet_mkepair)
892	epair_null=$(vnet_mkepair)
893	epair=$(vnet_mkepair)
894
895	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
896	route -6 add default 2001:db8::1
897
898	vnet_mkjail rtr ${epair}b ${epair_link}a ${epair_null}a
899	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
900	jexec rtr ifconfig ${epair_null}a 192.0.2.3/24 up
901	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
902
903	vnet_mkjail dst ${epair_link}b
904	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
905	jexec dst route add default 192.0.2.1
906
907	# Sanity checks
908	atf_check -s exit:0 -o ignore \
909	    ping6 -c 1 2001:db8::1
910
911	jexec rtr pfctl -e
912	pft_set_rules rtr \
913	    "set reassemble yes" \
914	    "set state-policy if-bound" \
915	    "pass in on ${epair}b route-to (${epair_link}a 192.0.2.2) inet6 from any to 64:ff9b::/96 af-to inet from (${epair_link}a)"
916
917	atf_check -s exit:0 -o ignore \
918	    ping6 -c 3 64:ff9b::192.0.2.2
919}
920
921route_to_cleanup()
922{
923	pft_cleanup
924}
925
926atf_test_case "reply_to" "cleanup"
927reply_to_head()
928{
929	atf_set descr 'Test reply-to on af-to rules'
930	atf_set require.user root
931}
932
933reply_to_body()
934{
935	pft_init
936
937	epair_link=$(vnet_mkepair)
938	epair=$(vnet_mkepair)
939
940	ifconfig ${epair}a inet6 2001:db8::2/64 up no_dad
941	route -6 add default 2001:db8::1
942
943	vnet_mkjail rtr ${epair}b ${epair_link}a
944	jexec rtr ifconfig ${epair}b inet6 2001:db8::1/64 up no_dad
945	jexec rtr ifconfig ${epair_link}a 192.0.2.1/24 up
946
947	vnet_mkjail dst ${epair_link}b
948	jexec dst ifconfig ${epair_link}b 192.0.2.2/24 up
949	jexec dst route add default 192.0.2.1
950
951	# Sanity checks
952	atf_check -s exit:0 -o ignore \
953	    ping6 -c 1 2001:db8::1
954
955	jexec rtr pfctl -e
956	pft_set_rules rtr \
957	    "set reassemble yes" \
958	    "set state-policy if-bound" \
959	    "pass in on ${epair}b reply-to (${epair}b 2001:db8::2) inet6 from any to 64:ff9b::/96 af-to inet from 192.0.2.1"
960
961	atf_check -s exit:0 -o ignore \
962	    ping6 -c 3 64:ff9b::192.0.2.2
963}
964
965reply_to_cleanup()
966{
967	pft_cleanup
968}
969
970atf_test_case "v6_gateway" "cleanup"
971v6_gateway_head()
972{
973	atf_set descr 'nat64 when the IPv4 gateway is given by an IPv6 address'
974	atf_set require.user root
975}
976
977v6_gateway_body()
978{
979	pft_init
980
981	epair_wan_two=$(vnet_mkepair)
982	epair_wan_one=$(vnet_mkepair)
983	epair_lan=$(vnet_mkepair)
984
985	ifconfig ${epair_lan}a inet6 2001:db8::2/64 up no_dad
986	route -6 add default 2001:db8::1
987
988	vnet_mkjail rtr ${epair_lan}b ${epair_wan_one}a
989	jexec rtr ifconfig ${epair_lan}b inet6 2001:db8::1/64 up no_dad
990	jexec rtr ifconfig ${epair_wan_one}a 192.0.2.1/24 up
991	jexec rtr ifconfig ${epair_wan_one}a inet6 -ifdisabled
992	jexec rtr route add default -inet6 fe80::1%${epair_wan_one}a
993	#jexec rtr route add default 192.0.2.2
994
995	vnet_mkjail wan_one ${epair_wan_one}b ${epair_wan_two}a
996	jexec wan_one ifconfig ${epair_wan_one}b 192.0.2.2/24 up
997	jexec wan_one ifconfig ${epair_wan_one}b inet6 fe80::1/64
998	jexec wan_one ifconfig ${epair_wan_two}a 198.51.100.2/24 up
999	jexec wan_one route add default 192.0.2.1
1000	jexec wan_one sysctl net.inet.ip.forwarding=1
1001
1002	vnet_mkjail wan_two ${epair_wan_two}b
1003	jexec wan_two ifconfig ${epair_wan_two}b 198.51.100.1/24 up
1004	jexec wan_two route add default 198.51.100.2
1005
1006	# Sanity checks
1007	atf_check -s exit:0 -o ignore \
1008	    ping6 -c 1 2001:db8::1
1009	atf_check -s exit:0 -o ignore \
1010	    jexec rtr ping -c 1 192.0.2.2
1011	atf_check -s exit:0 -o ignore \
1012	    jexec rtr ping -c 1 198.51.100.1
1013
1014	jexec rtr pfctl -e
1015	pft_set_rules rtr \
1016	    "set reassemble yes" \
1017	    "set state-policy if-bound" \
1018	    "pass in on ${epair_lan}b inet6 from any to 64:ff9b::/96 af-to inet from (${epair_wan_one}a)"
1019
1020	atf_check -s exit:0 -o ignore \
1021	    ping6 -c 3 64:ff9b::192.0.2.2
1022	atf_check -s exit:0 -o ignore \
1023	    ping6 -c 3 64:ff9b::198.51.100.1
1024}
1025
1026v6_gateway_cleanup()
1027{
1028	pft_cleanup
1029}
1030
1031atf_init_test_cases()
1032{
1033	atf_add_test_case "icmp_echo_in"
1034	atf_add_test_case "icmp_echo_out"
1035	atf_add_test_case "fragmentation_in"
1036	atf_add_test_case "fragmentation_out"
1037	atf_add_test_case "tcp_in"
1038	atf_add_test_case "tcp_out"
1039	atf_add_test_case "udp_in"
1040	atf_add_test_case "udp_out"
1041	atf_add_test_case "sctp_in"
1042	atf_add_test_case "sctp_out"
1043	atf_add_test_case "tos"
1044	atf_add_test_case "no_v4"
1045	atf_add_test_case "range"
1046	atf_add_test_case "pool"
1047	atf_add_test_case "table"
1048	atf_add_test_case "table_range"
1049	atf_add_test_case "table_round_robin"
1050	atf_add_test_case "table_random"
1051	atf_add_test_case "dummynet"
1052	atf_add_test_case "gateway6"
1053	atf_add_test_case "route_to"
1054	atf_add_test_case "reply_to"
1055	atf_add_test_case "v6_gateway"
1056}
1057