aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/sys/netpfil/pf/Makefile8
-rwxr-xr-xtests/sys/netpfil/pf/forward.sh67
-rw-r--r--tests/sys/netpfil/pf/pft_ping.py83
-rw-r--r--tests/sys/netpfil/pf/utils.subr10
4 files changed, 164 insertions, 4 deletions
diff --git a/tests/sys/netpfil/pf/Makefile b/tests/sys/netpfil/pf/Makefile
index 72e373db3310..fe0080d76c5d 100644
--- a/tests/sys/netpfil/pf/Makefile
+++ b/tests/sys/netpfil/pf/Makefile
@@ -4,8 +4,12 @@ PACKAGE= tests
TESTSDIR= ${TESTSBASE}/sys/netpfil/pf
-ATF_TESTS_SH+= pass_block
+ATF_TESTS_SH+= pass_block \
+ forward
-${PACKAGE}FILES+= utils.subr
+${PACKAGE}FILES+= utils.subr \
+ pft_ping.py
+
+${PACKAGE}FILESMODE_pft_ping.py= 0555
.include <bsd.test.mk>
diff --git a/tests/sys/netpfil/pf/forward.sh b/tests/sys/netpfil/pf/forward.sh
new file mode 100755
index 000000000000..62ef97b09dc1
--- /dev/null
+++ b/tests/sys/netpfil/pf/forward.sh
@@ -0,0 +1,67 @@
+# $FreeBSD$
+
+. $(atf_get_srcdir)/utils.subr
+
+atf_test_case "v4" "cleanup"
+v4_head()
+{
+ atf_set descr 'Basic forwarding test'
+ atf_set require.user root
+
+ # We need scapy to be installed for out test scripts to work
+ atf_set require.progs scapy
+}
+
+v4_body()
+{
+ pft_init
+
+ epair_send=$(pft_mkepair)
+ ifconfig ${epair_send}a 192.0.2.1/24 up
+
+ epair_recv=$(pft_mkepair)
+ ifconfig ${epair_recv}a up
+
+ pft_mkjail alcatraz ${epair_send}b ${epair_recv}b
+ jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up
+ jexec alcatraz ifconfig ${epair_recv}b 198.51.100.2/24 up
+ jexec alcatraz sysctl net.inet.ip.forwarding=1
+ jexec alcatraz arp -s 198.51.100.3 00:01:02:03:04:05
+ route add -net 198.51.100.0/24 192.0.2.2
+
+ # Sanity check, can we forward ICMP echo requests without pf?
+ atf_check -s exit:0 $(atf_get_srcdir)/pft_ping.py \
+ --sendif ${epair_send}a \
+ --to 198.51.100.3 \
+ --recvif ${epair_recv}a
+
+ # Forward with pf enabled
+ printf "block in\n" | jexec alcatraz pfctl -ef -
+ atf_check -s exit:1 $(atf_get_srcdir)/pft_ping.py \
+ --sendif ${epair_send}a \
+ --to 198.51.100.3 \
+ --recvif ${epair_recv}a
+
+ printf "block out\n" | jexec alcatraz pfctl -f -
+ atf_check -s exit:1 $(atf_get_srcdir)/pft_ping.py \
+ --sendif ${epair_send}a \
+ --to 198.51.100.3 \
+ --recv ${epair_recv}a
+
+ # Allow ICMP
+ printf "block in\npass in proto icmp\n" | jexec alcatraz pfctl -f -
+ atf_check -s exit:0 $(atf_get_srcdir)/pft_ping.py \
+ --sendif ${epair_send}a \
+ --to 198.51.100.3 \
+ --recvif ${epair_recv}a
+}
+
+v4_cleanup()
+{
+ pft_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case "v4"
+}
diff --git a/tests/sys/netpfil/pf/pft_ping.py b/tests/sys/netpfil/pf/pft_ping.py
new file mode 100644
index 000000000000..a07cfd82b6e8
--- /dev/null
+++ b/tests/sys/netpfil/pf/pft_ping.py
@@ -0,0 +1,83 @@
+#!/usr/local/bin/python2.7
+
+import argparse
+import scapy.all as sp
+import sys
+import threading
+
+PAYLOAD_MAGIC = 0x42c0ffee
+
+class Sniffer(threading.Thread):
+ def __init__(self, recvif):
+ threading.Thread.__init__(self)
+
+ self._recvif = recvif
+
+ self.start()
+
+ def run(self):
+ self.packets = sp.sniff(iface=self._recvif, timeout=3)
+
+def check_ping_request(packet, dst_ip):
+ """
+ Verify that the packet matches what we'd have sent
+ """
+ ip = packet.getlayer(sp.IP)
+ if not ip:
+ return False
+ if ip.dst != dst_ip:
+ return False
+
+ icmp = packet.getlayer(sp.ICMP)
+ if not icmp:
+ return False
+ if sp.icmptypes[icmp.type] != 'echo-request':
+ return False
+
+ raw = packet.getlayer(sp.Raw)
+ if not raw:
+ return False
+ if raw.load != str(PAYLOAD_MAGIC):
+ return False
+
+ return True
+
+def ping(send_if, dst_ip):
+ req = sp.Ether() \
+ / sp.IP(dst=dst_ip) \
+ / sp.ICMP(type='echo-request') \
+ / sp.Raw(PAYLOAD_MAGIC)
+ sp.sendp(req, iface=send_if, verbose=False)
+
+def main():
+ parser = argparse.ArgumentParser("pft_ping.py",
+ description="Ping test tool")
+ parser.add_argument('--sendif', nargs=1,
+ required=True,
+ help='The interface through which the packet(s) will be sent')
+ parser.add_argument('--recvif', nargs=1,
+ help='The interface on which to expect the ICMP echo response')
+ parser.add_argument('--to', nargs=1,
+ required=True,
+ help='The destination IP address for the ICMP echo request')
+
+ args = parser.parse_args()
+
+ sniffer = None
+ if not args.recvif is None:
+ sniffer = Sniffer(args.recvif[0])
+
+ ping(args.sendif[0], args.to[0])
+
+ if sniffer:
+ sniffer.join()
+
+ for packet in sniffer.packets:
+ if check_ping_request(packet, args.to[0]):
+ sys.exit(0)
+
+ # We did not get the packet we expected
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()
diff --git a/tests/sys/netpfil/pf/utils.subr b/tests/sys/netpfil/pf/utils.subr
index 822dd741e204..9d2f2bee95e4 100644
--- a/tests/sys/netpfil/pf/utils.subr
+++ b/tests/sys/netpfil/pf/utils.subr
@@ -23,8 +23,14 @@ pft_mkepair()
pft_mkjail()
{
jailname=$1
- ifname=$2
- jail -c name=${jailname} persist vnet vnet.interface=${ifname}
+ shift
+
+ vnet_interfaces=
+ for ifname in $@
+ do
+ vnet_interfaces="${vnet_interfaces} vnet.interface=${ifname}"
+ done
+ jail -c name=${jailname} persist vnet ${vnet_interfaces}
echo $jailname >> created_jails.lst
}