From nobody Thu Apr 03 17:00:17 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4ZT7Jx3WvNz5s9LH; Thu, 03 Apr 2025 17:00:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R10" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4ZT7Jx3598z4Lp6; Thu, 03 Apr 2025 17:00:17 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1743699617; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5rUFxBjh2Tgd5hedv1Y6SVR8Veo/gJt6QZAD+mdFqbM=; b=oZv26jBHppoq69RKT8xeSF/mgtABBD4RZlYSFiy0jtagSTNe+IVetPjiQCjRUSWoMAmgO/ 0ZfPmacRgV3sMG30F8HDbpjdRAdEb9dolGgRAMJVChO0W/CsefjGShmvt3GJJam8bYvdFA KnPMkZITat+P+kP/8Yg3bUX22gqKb+8fJaVKNHkLONfYya0VhxtjBGFnNLDQQoUVyq03AX cxIFo7u6iH5N/5dOBtXfhagh2z0Z8SliBFHx5ov3VYdzcmn/B6t3JaAGkmU7BYNWAk0frj 8LYU+ZiSfcpgtN2VhsAQp6xQ2XunEVW9M12jm7wnvuu01X7D8fHYw7oW5/J2GA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1743699617; a=rsa-sha256; cv=none; b=t86Lg56/je8WGp4oOxhuKgPUrWXMTS3wXqDYBkem+ZuO1XDiITIFMEvtFS6H4JUM00Xx9f pGuX7J8NEFmq+xzdOminmV5XZgCxDz6vxT5d1HYkUkMPZn4jOfdf3YQktkXKYvtjWTWfmP unMQTVcLc+9LSki4PEyvv9iMPxXK6VRylE8NHRofZuus7uSQ7rSEkVL9U8OAxfOEHSO5cY 8vKX6XUQcXwz/0p4SX+Tkh/UFcQn1q3G+3FlEBqoDJ8xbP15JzSm4XTle9PsErvX9YgZNm 8w41pe3y69ikCClHS+NB8IZp6zedxtjOPLjj5du6Rab05hubenGQmIeWp1asgQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1743699617; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=5rUFxBjh2Tgd5hedv1Y6SVR8Veo/gJt6QZAD+mdFqbM=; b=KVbq/O+8wKAvO3LRB1B5MXNdga9F3bhqgHVYK7bB9BviXShL+s7B57DTUZjdiVIcvxKtt2 dpC2ODA5LGx2W9Y0EEHhuqUrppovVBs7A0aqQkwBB3X8b86ki6MyaeLxPggD62DndpgGcg lASe5e9K3/9CoC1ned6Sr1fRbVCKf2jiuy4aYr+WEsObgXtfTXmDWq5FaHDc7nX/Ly2KYV V5H8mAyAbe3Ij9MJrAW3l1pIePsyDQgGhf082Ca0lbr6Yl/gv8wpQatmwlMRVT+RVDZ/xt jfp6KbmChf/lV43BJte5Yyy4oNCltXwYC2Mn+phlLZcW3ZnwVRmDoa+7ylNyvg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4ZT7Jx2dklz18S8; Thu, 03 Apr 2025 17:00:17 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 533H0HDm052489; Thu, 3 Apr 2025 17:00:17 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 533H0HXR052468; Thu, 3 Apr 2025 17:00:17 GMT (envelope-from git) Date: Thu, 3 Apr 2025 17:00:17 GMT Message-Id: <202504031700.533H0HXR052468@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 7e70d94acd68 - main - pf: allow 'allow-opts' to be used on match rules List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 7e70d94acd68b3ac6b45f49d4ab7a0f7867c3ea7 Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=7e70d94acd68b3ac6b45f49d4ab7a0f7867c3ea7 commit 7e70d94acd68b3ac6b45f49d4ab7a0f7867c3ea7 Author: Kristof Provost AuthorDate: 2025-04-03 12:58:21 +0000 Commit: Kristof Provost CommitDate: 2025-04-03 16:29:38 +0000 pf: allow 'allow-opts' to be used on match rules Allow the 'allow-opts' setting to be set on match rules. The intended use case is to simplify dealing with traffic where IP options are expected (e.g. IGMP), without allowing them on other traffic, or making the ruleset more complex. Add a test case confirming this works as expected. Sponsored by: Rubicon Communications, LLC ("Netgate") --- sbin/pfctl/parse.y | 5 ++-- sys/net/pfvar.h | 1 + sys/netpfil/pf/pf.c | 6 ++-- tests/sys/netpfil/pf/match.sh | 66 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 4 deletions(-) diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y index ea81efd7fd94..1362ae43428c 100644 --- a/sbin/pfctl/parse.y +++ b/sbin/pfctl/parse.y @@ -5325,8 +5325,9 @@ filter_consistent(struct pfctl_rule *r, int anchor_call) r->af == AF_INET ? "inet" : "inet6"); problems++; } - if (r->allow_opts && r->action != PF_PASS) { - yyerror("allow-opts can only be specified for pass rules"); + if (r->allow_opts && r->action != PF_PASS && r->action != PF_MATCH) { + yyerror("allow-opts can only be specified for pass or " + "match rules"); problems++; } if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 82967dc10d03..c511d61d6cc1 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -696,6 +696,7 @@ struct pf_rule_actions { uint8_t min_ttl; uint8_t set_prio[2]; uint8_t rt; + uint8_t allow_opts; }; union pf_keth_rule_ptr { diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c index 775bd016c656..c343512b20dd 100644 --- a/sys/netpfil/pf/pf.c +++ b/sys/netpfil/pf/pf.c @@ -4890,6 +4890,8 @@ pf_rule_to_actions(struct pf_krule *r, struct pf_rule_actions *a) a->set_prio[0] = r->set_prio[0]; a->set_prio[1] = r->set_prio[1]; } + if (r->allow_opts) + a->allow_opts = r->allow_opts; } int @@ -6102,7 +6104,7 @@ pf_create_state(struct pf_krule *r, struct pf_krule *nr, struct pf_krule *a, memcpy(&s->match_rules, match_rules, sizeof(s->match_rules)); memcpy(&s->act, &pd->act, sizeof(struct pf_rule_actions)); - if (r->allow_opts) + if (pd->act.allow_opts) s->state_flags |= PFSTATE_ALLOWOPTS; if (r->rule_flag & PFRULE_STATESLOPPY) s->state_flags |= PFSTATE_SLOPPY; @@ -10473,7 +10475,7 @@ done: goto eat_pkt; if (action == PF_PASS && pd.badopts && - !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) { + !((s && s->state_flags & PFSTATE_ALLOWOPTS) || pd.act.allow_opts)) { action = PF_DROP; REASON_SET(&reason, PFRES_IPOPTIONS); pd.act.log = PF_LOG_FORCE; diff --git a/tests/sys/netpfil/pf/match.sh b/tests/sys/netpfil/pf/match.sh index 93b908e62f2d..58c1e021310a 100644 --- a/tests/sys/netpfil/pf/match.sh +++ b/tests/sys/netpfil/pf/match.sh @@ -26,6 +26,8 @@ . $(atf_get_srcdir)/utils.subr +common_dir=$(atf_get_srcdir)/../common + atf_test_case "dummynet" "cleanup" dummynet_head() { @@ -112,8 +114,72 @@ quick_cleanup() pft_cleanup } +atf_test_case "allow_opts" "cleanup" +allow_opts_head() +{ + atf_set descr 'Test allowing IP options via match' + atf_set require.user root + atf_set require.progs python3 scapy +} + +allow_opts_body() +{ + pft_init + + epair=$(vnet_mkepair) + + ifconfig ${epair}b 192.0.2.2/24 up + + vnet_mkjail alcatraz ${epair}a + jexec alcatraz ifconfig ${epair}a 192.0.2.1/24 up + + jexec alcatraz pfctl -e + jexec alcatraz pfctl -x loud + pft_set_rules alcatraz \ + "match proto icmp allow-opts" \ + "pass" + + # Sanity check + atf_check -s exit:0 -o ignore \ + ping -c 1 192.0.2.1 + + atf_check -s exit:0 -o ignore \ + ${common_dir}/pft_ping.py \ + --sendif ${epair}b \ + --to 192.0.2.1 \ + --send-nop \ + --replyif ${epair}b + + # This doesn't work without 'allow-opts' + pft_set_rules alcatraz \ + "match proto icmp" \ + "pass" + atf_check -s exit:1 -o ignore \ + ${common_dir}/pft_ping.py \ + --sendif ${epair}b \ + --to 192.0.2.1 \ + --send-nop \ + --replyif ${epair}b + + # Setting it on a pass rule still works. + pft_set_rules alcatraz \ + "pass allow-opts" + atf_check -s exit:0 -o ignore \ + ${common_dir}/pft_ping.py \ + --sendif ${epair}b \ + --to 192.0.2.1 \ + --send-nop \ + --replyif ${epair}b +} + +allow_opts_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "dummynet" atf_add_test_case "quick" + atf_add_test_case "allow_opts" }