xref: /freebsd/tests/sys/netpfil/pf/killstate.sh (revision 9978553d0199e7ec0bdd1c44fc7f6c7b0c11e43b)
1#
2# SPDX-License-Identifier: BSD-2-Clause
3#
4# Copyright (c) 2021 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
29common_dir=$(atf_get_srcdir)/../common
30
31find_state()
32{
33	jail=${1:-alcatraz}
34	ip=${2:-192.0.2.2}
35
36	jexec ${jail} pfctl -ss | grep icmp | grep ${ip}
37}
38
39find_state_v6()
40{
41	jexec alcatraz pfctl -ss | grep icmp | grep 2001:db8::2
42}
43
44
45atf_test_case "v4" "cleanup"
46v4_head()
47{
48	atf_set descr 'Test killing states by IPv4 address'
49	atf_set require.user root
50	atf_set require.progs python3 scapy
51}
52
53v4_body()
54{
55	pft_init
56
57	epair=$(vnet_mkepair)
58	ifconfig ${epair}a 192.0.2.1/24 up
59
60	vnet_mkjail alcatraz ${epair}b
61	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
62	jexec alcatraz pfctl -e
63
64	pft_set_rules alcatraz "block all" \
65		"pass in proto icmp" \
66		"set skip on lo"
67
68	# Sanity check & establish state
69	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
70		--sendif ${epair}a \
71		--to 192.0.2.2 \
72		--replyif ${epair}a
73
74	# Change rules to now deny the ICMP traffic
75	pft_set_rules noflush alcatraz "block all"
76	if ! find_state;
77	then
78		atf_fail "Setting new rules removed the state."
79	fi
80
81	# Killing with the wrong IP doesn't affect our state
82	jexec alcatraz pfctl -k 192.0.2.3
83	if ! find_state;
84	then
85		atf_fail "Killing with the wrong IP removed our state."
86	fi
87
88	# Killing with one correct address and one incorrect doesn't kill the state
89	jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.3
90	if ! find_state;
91	then
92		atf_fail "Killing with one wrong IP removed our state."
93	fi
94
95	# Killing with correct address does remove the state
96	jexec alcatraz pfctl -k 192.0.2.1
97	if find_state;
98	then
99		atf_fail "Killing with the correct IP did not remove our state."
100	fi
101}
102
103v4_cleanup()
104{
105	pft_cleanup
106}
107
108atf_test_case "src_dst" "cleanup"
109src_dst_head()
110{
111	atf_set descr 'Test killing a state with source and destination specified'
112	atf_set require.user root
113}
114
115src_dst_body()
116{
117	pft_init
118
119	epair=$(vnet_mkepair)
120	ifconfig ${epair}a 192.0.2.1/24 up
121
122	vnet_mkjail alcatraz ${epair}b
123	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
124	jexec alcatraz pfctl -e
125
126	pft_set_rules alcatraz "block all" \
127		"pass in proto icmp" \
128		"set skip on lo"
129
130	# Sanity check & establish state
131	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
132		--sendif ${epair}a \
133		--to 192.0.2.2 \
134		--replyif ${epair}a
135
136	# Change rules to now deny the ICMP traffic
137	pft_set_rules noflush alcatraz "block all"
138	if ! find_state;
139	then
140		atf_fail "Setting new rules removed the state."
141	fi
142
143	# Killing with the wrong source IP doesn't affect our state
144	jexec alcatraz pfctl -k 192.0.2.3 -k 192.0.2.2
145	if ! find_state;
146	then
147		atf_fail "Killing with the wrong source IP removed our state."
148	fi
149
150	# Killing with the wrong destination IP doesn't affect our state
151	jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.3
152	if ! find_state;
153	then
154		atf_fail "Killing with the wrong destination IP removed our state."
155	fi
156
157	# But it does with the correct one
158	jexec alcatraz pfctl -k 192.0.2.1 -k 192.0.2.2
159	if find_state;
160	then
161		atf_fail "Killing with the correct IPs did not remove our state."
162	fi
163}
164
165src_dst_cleanup()
166{
167	pft_cleanup
168}
169
170atf_test_case "v6" "cleanup"
171v6_head()
172{
173	atf_set descr 'Test killing states by IPv6 address'
174	atf_set require.user root
175	atf_set require.progs python3 scapy
176}
177
178v6_body()
179{
180	pft_init
181
182	epair=$(vnet_mkepair)
183	ifconfig ${epair}a inet6 2001:db8::1/64 up no_dad
184
185	vnet_mkjail alcatraz ${epair}b
186	jexec alcatraz ifconfig ${epair}b inet6 2001:db8::2/64 up no_dad
187	jexec alcatraz pfctl -e
188
189	pft_set_rules alcatraz "block all" \
190		"pass quick inet6 proto ipv6-icmp all icmp6-type { neighbrsol, neighbradv } no state" \
191		"pass in proto icmp6" \
192		"set skip on lo"
193
194	# Sanity check & establish state
195	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
196		--sendif ${epair}a \
197		--fromaddr 2001:db8::1 \
198		--to 2001:db8::2 \
199		--replyif ${epair}a
200
201	# Change rules to now deny the ICMP traffic
202	pft_set_rules noflush alcatraz "block all"
203	if ! find_state_v6;
204	then
205		atf_fail "Setting new rules removed the state."
206	fi
207
208	# Killing with the wrong IP doesn't affect our state
209	jexec alcatraz pfctl -k 2001:db8::3
210	if ! find_state_v6;
211	then
212		atf_fail "Killing with the wrong IP removed our state."
213	fi
214
215	# Killing with one correct address and one incorrect doesn't kill the state
216	jexec alcatraz pfctl -k 2001:db8::1 -k 2001:db8::3
217	if ! find_state_v6;
218	then
219		atf_fail "Killing with one wrong IP removed our state."
220	fi
221
222	# Killing with correct address does remove the state
223	jexec alcatraz pfctl -k 2001:db8::1
224	if find_state_v6;
225	then
226		atf_fail "Killing with the correct IP did not remove our state."
227	fi
228}
229
230v6_cleanup()
231{
232	pft_cleanup
233}
234
235atf_test_case "label" "cleanup"
236label_head()
237{
238	atf_set descr 'Test killing states by label'
239	atf_set require.user root
240	atf_set require.progs python3 scapy
241}
242
243label_body()
244{
245	pft_init
246
247	epair=$(vnet_mkepair)
248	ifconfig ${epair}a 192.0.2.1/24 up
249
250	vnet_mkjail alcatraz ${epair}b
251	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
252	jexec alcatraz pfctl -e
253
254	pft_set_rules alcatraz "block all" \
255		"pass in proto tcp label bar" \
256		"pass in proto icmp label foo" \
257		"set skip on lo"
258
259	# Sanity check & establish state
260	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
261		--sendif ${epair}a \
262		--to 192.0.2.2 \
263		--replyif ${epair}a
264
265	# Change rules to now deny the ICMP traffic
266	pft_set_rules noflush alcatraz "block all"
267	if ! find_state;
268	then
269		atf_fail "Setting new rules removed the state."
270	fi
271
272	# Killing a label on a different rules keeps the state
273	jexec alcatraz pfctl -k label -k bar
274	if ! find_state;
275	then
276		atf_fail "Killing a different label removed the state."
277	fi
278
279	# Killing a non-existing label keeps the state
280	jexec alcatraz pfctl -k label -k baz
281	if ! find_state;
282	then
283		atf_fail "Killing a non-existing label removed the state."
284	fi
285
286	# Killing the correct label kills the state
287	jexec alcatraz pfctl -k label -k foo
288	if find_state;
289	then
290		atf_fail "Killing the state did not remove it."
291	fi
292}
293
294label_cleanup()
295{
296	pft_cleanup
297}
298
299atf_test_case "multilabel" "cleanup"
300multilabel_head()
301{
302	atf_set descr 'Test killing states with multiple labels by label'
303	atf_set require.user root
304	atf_set require.progs python3 scapy
305}
306
307multilabel_body()
308{
309	pft_init
310
311	epair=$(vnet_mkepair)
312	ifconfig ${epair}a 192.0.2.1/24 up
313
314	vnet_mkjail alcatraz ${epair}b
315	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
316	jexec alcatraz pfctl -e
317
318	pft_set_rules alcatraz "block all" \
319		"pass in proto icmp label foo label bar" \
320		"set skip on lo"
321
322	# Sanity check & establish state
323	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
324		--sendif ${epair}a \
325		--to 192.0.2.2 \
326		--replyif ${epair}a
327
328	# Change rules to now deny the ICMP traffic
329	pft_set_rules noflush alcatraz "block all"
330	if ! find_state;
331	then
332		atf_fail "Setting new rules removed the state."
333	fi
334
335	# Killing a label on a different rules keeps the state
336	jexec alcatraz pfctl -k label -k baz
337	if ! find_state;
338	then
339		atf_fail "Killing a different label removed the state."
340	fi
341
342	# Killing the state with the last label works
343	jexec alcatraz pfctl -k label -k bar
344	if find_state;
345	then
346		atf_fail "Killing with the last label did not remove the state."
347	fi
348
349	pft_set_rules alcatraz "block all" \
350		"pass in proto icmp label foo label bar" \
351		"set skip on lo"
352
353	# Reestablish state
354	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
355		--sendif ${epair}a \
356		--to 192.0.2.2 \
357		--replyif ${epair}a
358
359	# Change rules to now deny the ICMP traffic
360	pft_set_rules noflush alcatraz "block all"
361	if ! find_state;
362	then
363		atf_fail "Setting new rules removed the state."
364	fi
365
366	# Killing with the first label works too
367	jexec alcatraz pfctl -k label -k foo
368	if find_state;
369	then
370		atf_fail "Killing with the first label did not remove the state."
371	fi
372}
373
374multilabel_cleanup()
375{
376	pft_cleanup
377}
378
379atf_test_case "gateway" "cleanup"
380gateway_head()
381{
382	atf_set descr 'Test killing states by route-to/reply-to address'
383	atf_set require.user root
384	atf_set require.progs python3 scapy
385}
386
387gateway_body()
388{
389	pft_init
390
391	epair=$(vnet_mkepair)
392	ifconfig ${epair}a 192.0.2.1/24 up
393
394	vnet_mkjail alcatraz ${epair}b
395	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
396	jexec alcatraz pfctl -e
397
398	pft_set_rules alcatraz "block all" \
399		"pass in reply-to (${epair}b 192.0.2.1) proto icmp" \
400		"set skip on lo"
401
402	# Sanity check & establish state
403	# Note: use pft_ping so we always use the same ID, so pf considers all
404	# echo requests part of the same flow.
405	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
406		--sendif ${epair}a \
407		--to 192.0.2.2 \
408		--replyif ${epair}a
409
410	# Change rules to now deny the ICMP traffic
411	pft_set_rules noflush alcatraz "block all"
412	if ! find_state;
413	then
414		atf_fail "Setting new rules removed the state."
415	fi
416
417	# Killing with a different gateway does not affect our state
418	jexec alcatraz pfctl -k gateway -k 192.0.2.2
419	if ! find_state;
420	then
421		atf_fail "Killing with a different gateway removed the state."
422	fi
423
424	# Killing states with the relevant gateway does terminate our state
425	jexec alcatraz pfctl -k gateway -k 192.0.2.1
426	if find_state;
427	then
428		atf_fail "Killing with the gateway did not remove the state."
429	fi
430}
431
432gateway_cleanup()
433{
434	pft_cleanup
435}
436
437atf_test_case "match" "cleanup"
438match_head()
439{
440	atf_set descr 'Test killing matching states'
441	atf_set require.user root
442}
443
444wait_for_state()
445{
446	jail=$1
447	addr=$2
448
449	while ! jexec $jail pfctl -s s | grep $addr >/dev/null;
450	do
451		sleep .1
452	done
453}
454
455match_body()
456{
457	pft_init
458
459	epair_one=$(vnet_mkepair)
460	ifconfig ${epair_one}a 192.0.2.1/24 up
461
462	epair_two=$(vnet_mkepair)
463
464	vnet_mkjail alcatraz ${epair_one}b ${epair_two}a
465	jexec alcatraz ifconfig ${epair_one}b 192.0.2.2/24 up
466	jexec alcatraz ifconfig ${epair_two}a 198.51.100.1/24 up
467	jexec alcatraz sysctl net.inet.ip.forwarding=1
468	jexec alcatraz pfctl -e
469
470	vnet_mkjail singsing ${epair_two}b
471	jexec singsing ifconfig ${epair_two}b 198.51.100.2/24 up
472	jexec singsing route add default 198.51.100.1
473	jexec singsing /usr/sbin/inetd -p ${PWD}/inetd-echo.pid \
474	    $(atf_get_srcdir)/echo_inetd.conf
475
476	route add 198.51.100.0/24 192.0.2.2
477
478	pft_set_rules alcatraz \
479		"nat on ${epair_two}a from 192.0.2.0/24 -> (${epair_two}a)" \
480		"pass all"
481
482	nc 198.51.100.2 7 &
483	wait_for_state alcatraz 192.0.2.1
484
485	# Expect two states
486	states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l)
487	if [ $states -ne 2 ] ;
488	then
489		atf_fail "Expected two states, found $states"
490	fi
491
492	# If we don't kill the matching NAT state one should be left
493	jexec alcatraz pfctl -k 192.0.2.1
494	states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l)
495	if [ $states -ne 1 ] ;
496	then
497		atf_fail "Expected one states, found $states"
498	fi
499
500	# Flush
501	jexec alcatraz pfctl -F states
502
503	nc 198.51.100.2 7 &
504	wait_for_state alcatraz 192.0.2.1
505
506	# Kill matching states, expect all of them to be gone
507	jexec alcatraz pfctl -M -k 192.0.2.1
508	states=$(jexec alcatraz pfctl -s s | grep 192.0.2.1 | wc -l)
509	if [ $states -ne 0 ] ;
510	then
511		atf_fail "Expected zero states, found $states"
512	fi
513}
514
515match_cleanup()
516{
517	pft_cleanup
518}
519
520atf_test_case "interface" "cleanup"
521interface_head()
522{
523	atf_set descr 'Test killing states based on interface'
524	atf_set require.user root
525	atf_set require.progs python3 scapy
526}
527
528interface_body()
529{
530	pft_init
531
532	epair=$(vnet_mkepair)
533	ifconfig ${epair}a 192.0.2.1/24 up
534
535	vnet_mkjail alcatraz ${epair}b
536	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
537	jexec alcatraz pfctl -e
538
539	pft_set_rules alcatraz "block all" \
540		"pass in proto icmp" \
541		"set skip on lo"
542
543	# Sanity check & establish state
544	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
545		--sendif ${epair}a \
546		--to 192.0.2.2 \
547		--replyif ${epair}a
548
549	# Change rules to now deny the ICMP traffic
550	pft_set_rules noflush alcatraz "block all"
551	if ! find_state;
552	then
553		atf_fail "Setting new rules removed the state."
554	fi
555
556	# Flushing states on a different interface doesn't affect our state
557	jexec alcatraz pfctl -i ${epair}a -Fs
558	if ! find_state;
559	then
560		atf_fail "Flushing on a different interface removed the state."
561	fi
562
563	# Flushing on the correct interface does (even with floating states)
564	jexec alcatraz pfctl -i ${epair}b -Fs
565	if find_state;
566	then
567		atf_fail "Flushing on a the interface did not remove the state."
568	fi
569}
570
571interface_cleanup()
572{
573	pft_cleanup
574}
575
576atf_test_case "id" "cleanup"
577id_head()
578{
579	atf_set descr 'Test killing states by id'
580	atf_set require.user root
581	atf_set require.progs python3 scapy
582}
583
584id_body()
585{
586	pft_init
587
588	epair=$(vnet_mkepair)
589	ifconfig ${epair}a 192.0.2.1/24 up
590
591	vnet_mkjail alcatraz ${epair}b
592	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
593	jexec alcatraz pfctl -e
594
595	pft_set_rules alcatraz "block all" \
596		"pass in proto tcp" \
597		"pass in proto icmp" \
598		"set skip on lo"
599
600	# Sanity check & establish state
601	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
602		--sendif ${epair}a \
603		--to 192.0.2.2 \
604		--replyif ${epair}a
605
606	# Change rules to now deny the ICMP traffic
607	pft_set_rules noflush alcatraz "block all"
608	if ! find_state;
609	then
610		atf_fail "Setting new rules removed the state."
611	fi
612
613	# Get the state ID
614	id=$(jexec alcatraz pfctl -ss -vvv | grep -A 3 icmp |
615	    grep -A 3 192.0.2.2 | awk '/id:/ { printf("%s/%s", $2, $4); }')
616
617	# Kill the wrong ID
618	jexec alcatraz pfctl -k id -k 1
619	if ! find_state;
620	then
621		atf_fail "Killing a different ID removed the state."
622	fi
623
624	# Kill the correct ID
625	jexec alcatraz pfctl -k id -k ${id}
626	if find_state;
627	then
628		atf_fail "Killing the state did not remove it."
629	fi
630}
631
632id_cleanup()
633{
634	pft_cleanup
635}
636
637atf_test_case "key" "cleanup"
638key_head()
639{
640	atf_set descr 'Test killing states by their key'
641	atf_set require.user root
642	atf_set require.progs python3 scapy
643}
644
645key_body()
646{
647	pft_init
648
649	epair=$(vnet_mkepair)
650	ifconfig ${epair}a 192.0.2.1/24 up
651
652	vnet_mkjail alcatraz ${epair}b
653	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
654	jexec alcatraz pfctl -e
655
656	pft_set_rules alcatraz \
657		"block all" \
658		"pass in proto tcp" \
659		"pass in proto icmp"
660
661	# Sanity check & establish state
662	atf_check -s exit:0 -o ignore ${common_dir}/pft_ping.py \
663		--sendif ${epair}a \
664		--to 192.0.2.2 \
665		--replyif ${epair}a
666
667	# Get the state key
668	key=$(jexec alcatraz pfctl -ss -vvv | awk '/icmp/ { print($2 " " $3 " " $4 " " $5); }')
669	bad_key=$(echo ${key} | sed 's/icmp/tcp/')
670
671	# Kill the wrong key
672	atf_check -s exit:0 -e "match:killed 0 states" \
673	    jexec alcatraz pfctl -k key -k "${bad_key}"
674	if ! find_state;
675	then
676		atf_fail "Killing a different ID removed the state."
677	fi
678
679	# Kill the correct key
680	atf_check -s exit:0 -e "match:killed 1 states" \
681	    jexec alcatraz pfctl -k key -k "${key}"
682	if find_state;
683	then
684		atf_fail "Killing the state did not remove it."
685	fi
686}
687
688key_cleanup()
689{
690	pft_cleanup
691}
692
693atf_test_case "nat" "cleanup"
694nat_head()
695{
696	atf_set descr 'Test killing states by their NAT-ed IP address'
697	atf_set require.user root
698	atf_set require.progs python3 scapy
699}
700
701nat_body()
702{
703	pft_init
704	j="killstate:nat"
705
706	epair_c=$(vnet_mkepair)
707	epair_srv=$(vnet_mkepair)
708
709	vnet_mkjail ${j}c ${epair_c}a
710	ifconfig -j ${j}c ${epair_c}a inet 192.0.2.2/24 up
711	jexec ${j}c route add default 192.0.2.1
712
713	vnet_mkjail ${j}srv ${epair_srv}a
714	ifconfig -j ${j}srv ${epair_srv}a inet 198.51.100.2/24 up
715
716	vnet_mkjail ${j}r ${epair_c}b ${epair_srv}b
717	ifconfig -j ${j}r ${epair_c}b inet 192.0.2.1/24 up
718	ifconfig -j ${j}r ${epair_srv}b inet 198.51.100.1/24 up
719	jexec ${j}r sysctl net.inet.ip.forwarding=1
720
721	jexec ${j}r pfctl -e
722	pft_set_rules ${j}r \
723		"nat on ${epair_srv}b inet from 192.0.2.0/24 to any -> (${epair_srv}b)"
724
725	# Sanity check
726	atf_check -s exit:0 -o ignore \
727	    jexec ${j}c ping -c 1 192.0.2.1
728	atf_check -s exit:0 -o ignore \
729	    jexec ${j}srv ping -c 1 198.51.100.1
730	atf_check -s exit:0 -o ignore \
731	    jexec ${j}c ping -c 1 198.51.100.2
732
733	# Establish state
734	# Note: use pft_ping so we always use the same ID, so pf considers all
735	# echo requests part of the same flow.
736	atf_check -s exit:0 -o ignore jexec ${j}c ${common_dir}/pft_ping.py \
737		--sendif ${epair_c}a \
738		--to 198.51.100.1 \
739		--replyif ${epair_c}a
740
741	# There's NAT here, so the source IP will be 198.51.100.1
742	if ! find_state ${j}r 198.51.100.1;
743	then
744		atf_fail "Expected state not found"
745	fi
746
747	# By NAT-ed address?
748	jexec ${j}r pfctl -k nat -k 192.0.2.2
749
750	if find_state ${j}r 198.51.100.1;
751	then
752		jexec ${j}r pfctl -ss -v
753		atf_fail "Failed to remove state"
754	fi
755}
756
757nat_cleanup()
758{
759	pft_cleanup
760}
761
762atf_init_test_cases()
763{
764	atf_add_test_case "v4"
765	atf_add_test_case "src_dst"
766	atf_add_test_case "v6"
767	atf_add_test_case "label"
768	atf_add_test_case "multilabel"
769	atf_add_test_case "gateway"
770	atf_add_test_case "match"
771	atf_add_test_case "interface"
772	atf_add_test_case "id"
773	atf_add_test_case "key"
774	atf_add_test_case "nat"
775}
776