Page MenuHomeFreeBSD

D33245.id99392.diff
No OneTemporary

D33245.id99392.diff

Index: tests/sys/netpfil/pf/Makefile
===================================================================
--- tests/sys/netpfil/pf/Makefile
+++ tests/sys/netpfil/pf/Makefile
@@ -40,6 +40,7 @@
frag-overindex.py \
frag-overlimit.py \
frag-overreplace.py \
+ pfsync_defer.py \
utils.subr
${PACKAGE}FILESMODE_CVE-2019-5597.py= 0555
@@ -48,5 +49,6 @@
${PACKAGE}FILESMODE_frag-overindex.py= 0555
${PACKAGE}FILESMODE_frag-overlimit.py= 0555
${PACKAGE}FILESMODE_frag-overreplace.py= 0555
+${PACKAGE}FILESMODE_pfsync_defer.py= 0555
.include <bsd.test.mk>
Index: tests/sys/netpfil/pf/pfsync.sh
===================================================================
--- tests/sys/netpfil/pf/pfsync.sh
+++ tests/sys/netpfil/pf/pfsync.sh
@@ -27,6 +27,8 @@
. $(atf_get_srcdir)/utils.subr
+common_dir=$(atf_get_srcdir)/../common
+
atf_test_case "basic" "cleanup"
basic_head()
{
@@ -95,6 +97,23 @@
pfsynct_cleanup
}
+atf_test_case "basic_defer" "cleanup"
+basic_defer_head()
+{
+ atf_set descr 'Basic defer mode pfsync test'
+ atf_set require.user root
+}
+
+basic_defer_body()
+{
+ common_body defer
+}
+
+basic_defer_cleanup()
+{
+ pfsynct_cleanup
+}
+
atf_test_case "defer" "cleanup"
defer_head()
{
@@ -104,7 +123,56 @@
defer_body()
{
- common_body defer
+ pfsynct_init
+
+ epair_sync=$(vnet_mkepair)
+ epair_in=$(vnet_mkepair)
+ epair_out=$(vnet_mkepair)
+
+ vnet_mkjail alcatraz ${epair_sync}a ${epair_in}a ${epair_out}a
+
+ jexec alcatraz ifconfig ${epair_sync}a 192.0.2.1/24 up
+ jexec alcatraz ifconfig ${epair_out}a 198.51.100.1/24 up
+ jexec alcatraz ifconfig ${epair_in}a 203.0.113.1/24 up
+ jexec alcatraz arp -s 203.0.113.2 00:01:02:03:04:05
+ jexec alcatraz sysctl net.inet.ip.forwarding=1
+
+ jexec alcatraz ifconfig pfsync0 \
+ syncdev ${epair_sync}a \
+ maxupd 1 \
+ defer \
+ up
+
+ ifconfig ${epair_sync}b 192.0.2.2/24 up
+ ifconfig ${epair_out}b 198.51.100.2/24 up
+ ifconfig ${epair_in}b up
+ route add -net 203.0.113.0/24 198.51.100.1
+
+ # Enable pf
+ jexec alcatraz pfctl -e
+ pft_set_rules alcatraz \
+ "set skip on ${epair_sync}a" \
+ "pass keep state"
+
+ atf_check -s exit:0 env PYTHONPATH=${common_dir} \
+ $(atf_get_srcdir)/pfsync_defer.py \
+ --syncdev ${epair_sync}b \
+ --indev ${epair_in}b \
+ --outdev ${epair_out}b
+
+ # Now disable defer mode and expect failure.
+ jexec alcatraz ifconfig pfsync0 -defer
+
+ # Flush state
+ pft_set_rules alcatraz \
+ "set skip on ${epair_sync}a" \
+ "pass keep state"
+
+ atf_check -s exit:1 env PYTHONPATH=${common_dir} \
+ $(atf_get_srcdir)/pfsync_defer.py \
+ --syncdev ${epair_sync}b \
+ --indev ${epair_in}b \
+ --outdev ${epair_out}b
}
defer_cleanup()
@@ -182,6 +250,7 @@
atf_init_test_cases()
{
atf_add_test_case "basic"
+ atf_add_test_case "basic_defer"
atf_add_test_case "defer"
atf_add_test_case "bulk"
}
Index: tests/sys/netpfil/pf/pfsync_defer.py
===================================================================
--- /dev/null
+++ tests/sys/netpfil/pf/pfsync_defer.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python3
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Rubicon Communications, LLC (Netgate)
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+import argparse
+import logging
+logging.getLogger("scapy").setLevel(logging.CRITICAL)
+import scapy.all as sp
+import socket
+import sys
+import time
+from sniffer import Sniffer
+
+got_pfsync = False
+got_ping = False
+sent_ping = False
+
+def check_pfsync(args, packet):
+ global got_pfsync
+ global got_ping
+
+ ip = packet.getlayer(sp.IP)
+ if not ip:
+ return False
+
+ if ip.proto != 240:
+ return False
+
+ # Only look at the first packet
+ if got_pfsync:
+ return False
+
+ got_pfsync = time.time()
+
+ return False
+
+def check_reply(args, packet):
+ global got_pfsync
+ global got_ping
+
+ if not packet.getlayer(sp.ICMP):
+ return False
+
+ # Only look at the first packet
+ if got_ping:
+ return False
+
+ got_ping = time.time()
+
+ return False
+
+def ping(intf):
+ global sent_ping
+
+ ether = sp.Ether()
+ ip = sp.IP(dst="203.0.113.2", src="198.51.100.2")
+ icmp = sp.ICMP(type='echo-request')
+ raw = sp.raw(bytes.fromhex('00010203'))
+
+ req = ether / ip / icmp / raw
+ sp.sendp(req, iface=intf, verbose=False)
+ sent_ping = time.time()
+
+def main():
+ global got_pfsync
+ global got_ping
+ global sent_ping
+
+ parser = argparse.ArgumentParser("pfsync_defer.py",
+ description="pfsync defer mode test")
+ parser.add_argument('--syncdev', nargs=1,
+ required=True,
+ help='The pfsync interface')
+ parser.add_argument('--outdev', nargs=1,
+ required=True,
+ help='The interface we will send packets on')
+ parser.add_argument('--indev', nargs=1,
+ required=True,
+ help='The interface we will receive packets on')
+
+ args = parser.parse_args()
+
+ syncmon = Sniffer(args, check_pfsync, args.syncdev[0])
+ datamon = Sniffer(args, check_reply, args.indev[0])
+
+ # Send traffic on datadev, which should create state and produce a pfsync message
+ ping(args.outdev[0])
+
+ syncmon.join()
+ datamon.join()
+
+ if not got_pfsync:
+ sys.exit(1)
+
+ if not got_ping:
+ sys.exit(1)
+
+ if got_pfsync > got_ping:
+ sys.exit(1)
+
+ # Deferred packets are delayed up to 20ms (unless the pfsync peer, which we
+ # don't have here, acks their state update earlier)
+ if (sent_ping + 0.020) > got_ping:
+ sys.exit(1)
+
+if __name__ == '__main__':
+ main()

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 6:08 AM (3 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28545944
Default Alt Text
D33245.id99392.diff (6 KB)

Event Timeline