xref: /freebsd/tests/sys/netpfil/pf/ether.sh (revision 271171e0)
1# $FreeBSD$
2#
3# SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4#
5# Copyright © 2021. Rubicon Communications, LLC (Netgate). All Rights Reserved.
6#
7# Redistribution and use in source and binary forms, with or without
8# modification, are permitted provided that the following conditions
9# are met:
10# 1. Redistributions of source code must retain the above copyright
11#    notice, this list of conditions and the following disclaimer.
12# 2. Redistributions in binary form must reproduce the above copyright
13#    notice, this list of conditions and the following disclaimer in the
14#    documentation and/or other materials provided with the distribution.
15#
16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26# SUCH DAMAGE.
27
28. $(atf_get_srcdir)/utils.subr
29
30atf_test_case "mac" "cleanup"
31mac_head()
32{
33	atf_set descr 'Test MAC address filtering'
34	atf_set require.user root
35}
36
37mac_body()
38{
39	pft_init
40
41	epair=$(vnet_mkepair)
42	epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }')
43
44	ifconfig ${epair}a 192.0.2.1/24 up
45
46	vnet_mkjail alcatraz ${epair}b
47	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
48
49	pft_set_rules alcatraz \
50		"ether block from ${epair_a_mac}"
51
52	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
53
54	# Now enable. Ping should fail.
55	jexec alcatraz pfctl -e
56
57	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
58
59	# Should still fail for 'to'
60	pft_set_rules alcatraz \
61		"ether block to ${epair_a_mac}"
62	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
63
64	# Succeeds if we block a different MAC address
65	pft_set_rules alcatraz \
66		"ether block to 00:01:02:03:04:05"
67	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
68
69	# Should still fail for 'to', even if it's in a list
70	pft_set_rules alcatraz \
71		"ether block to { ${epair_a_mac}, 00:01:02:0:04:05 }"
72	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
73
74	# Now try this with an interface specified
75	pft_set_rules alcatraz \
76		"ether block on ${epair}b from ${epair_a_mac}"
77	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
78
79	# Wrong interface should not match
80	pft_set_rules alcatraz \
81		"ether block on ${epair}a from ${epair_a_mac}"
82	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
83
84	# Test negation
85	pft_set_rules alcatraz \
86		"ether block in on ${epair}b from ! ${epair_a_mac}"
87	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
88
89	pft_set_rules alcatraz \
90		"ether block out on ${epair}b to ! ${epair_a_mac}"
91	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
92
93	# Block everything not us
94	pft_set_rules alcatraz \
95		"ether block out on ${epair}b to { ! ${epair_a_mac} }"
96	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
97
98	# Block us now
99	pft_set_rules alcatraz \
100		"ether block out on ${epair}b to { ! 00:01:02:03:04:05 }"
101	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
102
103	# Block with a masked address
104	pft_set_rules alcatraz \
105		"ether block out on ${epair}b to { ! 00:01:02:03:00:00/32 }"
106	jexec alcatraz pfctl -se
107	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
108
109	epair_prefix=$(echo $epair_a_mac | cut -c-8)
110	pft_set_rules alcatraz \
111		"ether block out on ${epair}b to { ${epair_prefix}:00:00:00/24 }"
112	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
113
114	pft_set_rules alcatraz \
115		"ether block out on ${epair}b to { ${epair_prefix}:00:00:00&ff:ff:ff:00:00:00 }"
116	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
117
118	# Check '-F ethernet' works
119	jexec alcatraz pfctl -F ethernet
120	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
121}
122
123mac_cleanup()
124{
125	pft_cleanup
126}
127
128atf_test_case "proto" "cleanup"
129proto_head()
130{
131	atf_set descr 'Test EtherType filtering'
132	atf_set require.user root
133}
134
135proto_body()
136{
137	pft_init
138
139	epair=$(vnet_mkepair)
140	epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }')
141
142	ifconfig ${epair}a 192.0.2.1/24 up
143
144	vnet_mkjail alcatraz ${epair}b
145	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
146
147	pft_set_rules alcatraz \
148		"ether block proto 0x0810"
149	jexec alcatraz pfctl -e
150
151	atf_check -s exit:0 -o ignore ping -c 1 -t 1 192.0.2.2
152
153	# Block IP
154	pft_set_rules alcatraz \
155		"ether block proto 0x0800"
156	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
157
158	# Block ARP
159	pft_set_rules alcatraz \
160		"ether block proto 0x0806"
161	arp -d 192.0.2.2
162	atf_check -s exit:2 -o ignore ping -c 1 -t 1 192.0.2.2
163}
164
165proto_cleanup()
166{
167	pft_cleanup
168}
169
170atf_test_case "direction" "cleanup"
171direction_head()
172{
173	atf_set descr 'Test directionality of ether rules'
174	atf_set require.user root
175	atf_set require.progs jq
176}
177
178direction_body()
179{
180	pft_init
181
182	epair=$(vnet_mkepair)
183	epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }')
184	epair_b_mac=$(ifconfig ${epair}b ether | awk '/ether/ { print $2; }')
185
186	ifconfig ${epair}a 192.0.2.1/24 up
187
188	vnet_mkjail alcatraz ${epair}b
189	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
190
191	pft_set_rules alcatraz \
192		"ether block in proto 0x0806"
193	jexec alcatraz pfctl -e
194
195	arp -d 192.0.2.2
196	jexec alcatraz arp -d 192.0.2.1
197
198	# We don't allow the jail to receive ARP requests, so if we try to ping
199	# from host to jail the host can't resolve the MAC address
200	ping -c 1 -t 1 192.0.2.2
201
202	mac=$(arp -an --libxo json \
203	    | jq '."arp"."arp-cache"[] |
204	    select(."ip-address"=="192.0.2.2")."mac-address"')
205	atf_check_not_equal "$mac" "$epair_b_mac"
206
207	# Clear ARP table again
208	arp -d 192.0.2.2
209	jexec alcatraz arp -d 192.0.2.1
210
211	# However, we allow outbound ARP, so the host will learn our MAC if the
212	# jail tries to ping
213	jexec alcatraz ping -c 1 -t 1 192.0.2.1
214
215	mac=$(arp -an --libxo json \
216	    | jq '."arp"."arp-cache"[] |
217	    select(."ip-address"=="192.0.2.2")."mac-address"')
218	atf_check_equal "$mac" "$epair_b_mac"
219
220	# Now do the same, but with outbound ARP blocking
221	pft_set_rules alcatraz \
222		"ether block out proto 0x0806"
223
224	# Clear ARP table again
225	arp -d 192.0.2.2
226	jexec alcatraz arp -d 192.0.2.1
227
228	# The jail can't send ARP requests to us, so we'll never learn our MAC
229	# address
230	jexec alcatraz ping -c 1 -t 1 192.0.2.1
231
232	mac=$(jexec alcatraz arp -an --libxo json \
233	    | jq '."arp"."arp-cache"[] |
234	    select(."ip-address"=="192.0.2.1")."mac-address"')
235	atf_check_not_equal "$mac" "$epair_a_mac"
236}
237
238direction_cleanup()
239{
240	pft_cleanup
241}
242
243atf_test_case "captive" "cleanup"
244captive_head()
245{
246	atf_set descr 'Test a basic captive portal-like setup'
247	atf_set require.user root
248}
249
250captive_body()
251{
252	# Host is client, jail 'gw' is the captive portal gateway, jail 'srv'
253	# is a random (web)server. We use the echo protocol rather than http
254	# for the test, because that's easier.
255	pft_init
256
257	epair_gw=$(vnet_mkepair)
258	epair_srv=$(vnet_mkepair)
259	epair_gw_a_mac=$(ifconfig ${epair_gw}a ether | awk '/ether/ { print $2; }')
260
261	vnet_mkjail gw ${epair_gw}b ${epair_srv}a
262	vnet_mkjail srv ${epair_srv}b
263
264	ifconfig ${epair_gw}a 192.0.2.2/24 up
265	route add -net 198.51.100.0/24 192.0.2.1
266	jexec gw ifconfig ${epair_gw}b 192.0.2.1/24 up
267	jexec gw ifconfig lo0 127.0.0.1/8 up
268	jexec gw sysctl net.inet.ip.forwarding=1
269
270	jexec gw ifconfig ${epair_srv}a 198.51.100.1/24 up
271	jexec srv ifconfig ${epair_srv}b 198.51.100.2/24 up
272	jexec srv route add -net 192.0.2.0/24 198.51.100.1
273
274	# Sanity check
275	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.2
276
277	pft_set_rules gw \
278		"ether pass quick proto 0x0806" \
279		"ether pass tag captive" \
280		"rdr on ${epair_gw}b proto tcp to port echo tagged captive -> 127.0.0.1 port echo"
281	jexec gw pfctl -e
282
283	# ICMP should still work, because we don't redirect it.
284	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.2
285
286	# Run the echo server only on the gw, so we know we've redirectly
287	# correctly if we get an echo message.
288	jexec gw /usr/sbin/inetd $(atf_get_srcdir)/echo_inetd.conf
289
290	# Confirm that we're getting redirected
291	atf_check -s exit:0 -o match:"^foo$" -x "echo foo | nc -N 198.51.100.2 7"
292
293	jexec gw killall inetd
294
295	# Now pretend we've authenticated, so add the client's MAC address
296	pft_set_rules gw \
297		"ether pass quick proto 0x0806" \
298		"ether pass quick from ${epair_gw_a_mac}" \
299		"ether pass tag captive" \
300		"rdr on ${epair_gw}b proto tcp to port echo tagged captive -> 127.0.0.1 port echo"
301
302	# No redirect, so failure.
303	atf_check -s exit:1 -x "echo foo | nc -N 198.51.100.2 7"
304
305	# Start a server in srv
306	jexec srv /usr/sbin/inetd $(atf_get_srcdir)/echo_inetd.conf
307
308	# And now we can talk to that one.
309	atf_check -s exit:0 -o match:"^foo$" -x "echo foo | nc -N 198.51.100.2 7"
310}
311
312captive_cleanup()
313{
314	pft_cleanup
315}
316
317atf_test_case "captive_long" "cleanup"
318captive_long_head()
319{
320	atf_set descr 'More complex captive portal setup'
321	atf_set require.user root
322}
323
324captive_long_body()
325{
326	# Host is client, jail 'gw' is the captive portal gateway, jail 'srv'
327	# is a random (web)server. We use the echo protocol rather than http
328	# for the test, because that's easier.
329	dummynet_init
330
331	epair_gw=$(vnet_mkepair)
332	epair_srv=$(vnet_mkepair)
333	epair_gw_a_mac=$(ifconfig ${epair_gw}a ether | awk '/ether/ { print $2; }')
334
335	vnet_mkjail gw ${epair_gw}b ${epair_srv}a
336	vnet_mkjail srv ${epair_srv}b
337
338	ifconfig ${epair_gw}a 192.0.2.2/24 up
339	route add -net 198.51.100.0/24 192.0.2.1
340	jexec gw ifconfig ${epair_gw}b 192.0.2.1/24 up
341	jexec gw ifconfig lo0 127.0.0.1/8 up
342	jexec gw sysctl net.inet.ip.forwarding=1
343
344	jexec gw ifconfig ${epair_srv}a 198.51.100.1/24 up
345	jexec srv ifconfig ${epair_srv}b 198.51.100.2/24 up
346	jexec srv route add -net 192.0.2.0/24 198.51.100.1
347
348	jexec gw dnctl pipe 1 config bw 300KByte/s
349
350	# Sanity check
351	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.2
352
353	pft_set_rules gw \
354		"ether anchor \"captiveportal\" on { ${epair_gw}b } {" \
355			"ether pass quick proto { 0x0806, 0x8035, 0x888e, 0x88c7, 0x8863, 0x8864 }" \
356			"ether pass tag \"captive\"" \
357		"}" \
358		"rdr on ${epair_gw}b proto tcp to port daytime tagged captive -> 127.0.0.1 port echo"
359	jexec gw pfctl -e
360
361	# ICMP should still work, because we don't redirect it.
362	atf_check -s exit:0 -o ignore ping -c 1 -t 1 198.51.100.2
363
364	jexec gw /usr/sbin/inetd -p gw.pid $(atf_get_srcdir)/echo_inetd.conf
365	jexec srv /usr/sbin/inetd -p srv.pid $(atf_get_srcdir)/daytime_inetd.conf
366
367	echo foo | nc -N 198.51.100.2 13
368
369	# Confirm that we're getting redirected
370	atf_check -s exit:0 -o match:"^foo$" -x "echo foo | nc -N 198.51.100.2 13"
371
372	# Now update the rules to allow our client to pass without redirect
373	pft_set_rules gw \
374		"ether anchor \"captiveportal\" on { ${epair_gw}b } {" \
375			"ether pass quick proto { 0x0806, 0x8035, 0x888e, 0x88c7, 0x8863, 0x8864 }" \
376			"ether pass quick from { ${epair_gw_a_mac} } dnpipe 1" \
377			"ether pass tag \"captive\"" \
378		"}" \
379		"rdr on ${epair_gw}b proto tcp to port daytime tagged captive -> 127.0.0.1 port echo"
380
381	# We're not being redirected and get datime information now
382	atf_check -s exit:0 -o match:"^(Mon|Tue|Wed|Thu|Fri|Sat|Sun)" -x "echo foo | nc -N 198.51.100.2 13"
383
384	jexec gw killall inetd
385	jexec srv killall inetd
386}
387
388captive_long_cleanup()
389{
390	pft_cleanup
391}
392
393atf_test_case "dummynet" "cleanup"
394dummynet_head()
395{
396	atf_set descr 'Test dummynet for L2 traffic'
397	atf_set require.user root
398}
399
400dummynet_body()
401{
402	pft_init
403
404	if ! kldstat -q -m dummynet; then
405		atf_skip "This test requires dummynet"
406	fi
407
408	epair=$(vnet_mkepair)
409	vnet_mkjail alcatraz ${epair}b
410
411	ifconfig ${epair}a 192.0.2.1/24 up
412	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
413
414	# Sanity check
415	atf_check -s exit:0 -o ignore ping -i .1 -c 3 -s 1200 192.0.2.2
416
417	jexec alcatraz dnctl pipe 1 config bw 30Byte/s
418	jexec alcatraz pfctl -e
419	pft_set_rules alcatraz \
420		"ether pass in dnpipe 1"
421
422	# Ensure things don't break if non-IP(v4/v6) traffic hits dummynet
423	arp -d 192.0.2.2
424
425	# single ping succeeds just fine
426	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
427
428	# Saturate the link
429	ping -i .1 -c 5 -s 1200 192.0.2.2
430
431	# We should now be hitting the limits and get this packet dropped.
432	atf_check -s exit:2 -o ignore ping -c 1 -s 1200 192.0.2.2
433
434	# We can now also dummynet outbound traffic!
435	pft_set_rules alcatraz \
436		"ether pass out dnpipe 1"
437
438	# We should still be hitting the limits and get this packet dropped.
439	atf_check -s exit:2 -o ignore ping -c 1 -s 1200 192.0.2.2
440}
441
442dummynet_cleanup()
443{
444	pft_cleanup
445}
446
447atf_test_case "anchor" "cleanup"
448anchor_head()
449{
450	atf_set descr 'Test ether anchors'
451	atf_set require.user root
452}
453
454anchor_body()
455{
456	pft_init
457
458	epair=$(vnet_mkepair)
459	epair_a_mac=$(ifconfig ${epair}a ether | awk '/ether/ { print $2; }')
460
461	vnet_mkjail alcatraz ${epair}b
462
463	ifconfig ${epair}a 192.0.2.1/24 up
464	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
465
466	# Sanity check
467	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
468
469	jexec alcatraz pfctl -e
470	pft_set_rules alcatraz \
471		"ether anchor \"foo\" in on lo0 {" \
472			"ether block" \
473		"}"
474
475	# That only filters on lo0, so we should still be able to pass traffic
476	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
477
478	pft_set_rules alcatraz \
479		"ether block in" \
480		"ether anchor \"foo\" in on ${epair}b {" \
481			"ether pass" \
482		"}"
483	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
484
485	pft_set_rules alcatraz \
486		"ether pass" \
487		"ether anchor \"bar\" in on ${epair}b {" \
488			"ether block" \
489		"}"
490	atf_check -s exit:2 -o ignore ping -c 1 -t 2 192.0.2.2
491
492	pft_set_rules alcatraz \
493		"ether block in" \
494		"ether anchor \"baz\" on ${epair}b {" \
495			"ether pass in from 01:02:03:04:05:06" \
496		"}" \
497		"ether pass in from ${epair_a_mac}"
498	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
499
500	atf_check -s exit:0 -o match:'baz' jexec alcatraz pfctl -sA
501}
502
503anchor_cleanup()
504{
505	pft_cleanup
506}
507
508atf_test_case "ip" "cleanup"
509ip_head()
510{
511	atf_set descr 'Test filtering based on IP source/destination'
512	atf_set require.user root
513}
514
515ip_body()
516{
517	pft_init
518
519	epair=$(vnet_mkepair)
520
521	vnet_mkjail alcatraz ${epair}b
522
523	ifconfig ${epair}a 192.0.2.1/24 up
524	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
525
526	# Sanity check
527	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
528
529	jexec alcatraz pfctl -e
530	pft_set_rules alcatraz \
531		"ether pass" \
532		"ether block in l3 from 192.0.2.1"
533
534	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
535
536	# Change IP address and we can ping again
537	ifconfig ${epair}a 192.0.2.3/24 up
538	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
539
540	# Test the 'to' keyword too
541	pft_set_rules alcatraz \
542		"ether pass" \
543		"ether block out l3 to 192.0.2.3"
544	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
545
546	# Test table
547	pft_set_rules alcatraz \
548		"table <tbl> { 192.0.2.3 }" \
549		"ether pass" \
550		"ether block out l3 to <tbl>"
551	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
552}
553
554ip_cleanup()
555{
556	pft_cleanup
557}
558
559atf_test_case "tag" "cleanup"
560tag_head()
561{
562	atf_set descr 'Test setting tags'
563	atf_set require.user root
564}
565
566tag_body()
567{
568	pft_init
569
570	epair=$(vnet_mkepair)
571
572	vnet_mkjail alcatraz ${epair}b
573	ifconfig ${epair}a 192.0.2.1/24 up
574	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
575
576	# Sanity check
577	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
578
579	jexec alcatraz pfctl -e
580	pft_set_rules alcatraz \
581		"ether pass in tag foo" \
582		"block in tagged foo"
583
584	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
585
586	pft_set_rules alcatraz \
587		"ether pass in tag bar" \
588		"block in tagged foo"
589
590	# Still passes when tagged differently
591	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
592}
593
594tag_cleanup()
595{
596	pft_cleanup
597}
598
599atf_test_case "match_tag" "cleanup"
600match_tag_head()
601{
602	atf_set descr 'Test matching tags'
603	atf_set require.user root
604}
605
606match_tag_body()
607{
608	pft_init
609
610	epair=$(vnet_mkepair)
611
612	vnet_mkjail alcatraz ${epair}b
613
614	ifconfig ${epair}a 192.0.2.1/24 up
615	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
616
617	# Sanity check
618	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
619
620	jexec alcatraz pfctl -e
621	pft_set_rules alcatraz \
622		"ether block out tagged foo" \
623		"pass in proto icmp tag foo"
624
625	atf_check -s exit:2 -o ignore ping -c 1 192.0.2.2
626
627	pft_set_rules alcatraz \
628		"ether block out tagged bar" \
629		"pass in proto icmp tag foo"
630
631	# Still passes when tagged differently
632	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
633}
634
635match_tag_cleanup()
636{
637	pft_cleanup
638}
639
640atf_test_case "short_pkt" "cleanup"
641short_pkt_head()
642{
643	atf_set descr 'Test overly short Ethernet packets'
644	atf_set require.user root
645}
646
647short_pkt_body()
648{
649	pft_init
650
651	epair=$(vnet_mkepair)
652	ifconfig ${epair}a 192.0.2.1/24 up
653
654	vnet_mkjail alcatraz ${epair}b
655	jexec alcatraz ifconfig ${epair}b 192.0.2.2/24 up
656
657	jexec alcatraz pfctl -e
658	pft_set_rules alcatraz \
659		"ether pass in" \
660		"ether pass out" \
661		"ether pass in l3 from 192.0.2.1"
662
663	# Sanity check
664	atf_check -s exit:0 -o ignore ping -c 1 192.0.2.2
665
666	jexec alcatraz pfctl -se -v
667
668	# Try sending ever shorter ping requests
669	# BPF won't let us send anything shorter than an Ethernet header, but
670	# that's good enough for this test
671	$(atf_get_srcdir)/pft_ether.py \
672	    --sendif ${epair}a \
673	    --to 192.0.2.2 \
674	    --len 14-64
675}
676
677short_pkt_cleanup()
678{
679	pft_cleanup
680}
681
682atf_init_test_cases()
683{
684	atf_add_test_case "mac"
685	atf_add_test_case "proto"
686	atf_add_test_case "direction"
687	atf_add_test_case "captive"
688	atf_add_test_case "captive_long"
689	atf_add_test_case "dummynet"
690	atf_add_test_case "anchor"
691	atf_add_test_case "ip"
692	atf_add_test_case "tag"
693	atf_add_test_case "match_tag"
694	atf_add_test_case "short_pkt"
695}
696