Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 25 Sep 2025 12:41:33 GMT
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: af922319e813 - main - pf: support one shot rules
Message-ID:  <202509251241.58PCfXlb000781@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=af922319e8136a818bc6c38440d98a574c5df7a9

commit af922319e8136a818bc6c38440d98a574c5df7a9
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-08-27 10:02:51 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-09-25 12:41:07 +0000

    pf: support one shot rules
    
    Add support for one shot rules that remove themselves from an active
    ruleset after match.
    This is an extremely handy technique for firewall proxies.
    
    ok henning, mcbride
    
    Note that the FreeBSD implementation differs significantly from the OpenBSD
    version due to locking differences. We do not remove the rule, but mark it as
    having fired previously so we can skip it.
    
    Obtained from:  OpenBSD, mikeb <mikeb@openbsd.org>, c981122504
    Obtained from:  OpenBSD, sashan <sashan@openbsd.org>, a21b78cad0 (partial)
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf.c | 19 +++++++++++++++++++
 sys/netpfil/pf/pf.h |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index be00aff1f5cb..450e465e926a 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -5633,6 +5633,9 @@ pf_match_rule(struct pf_test_ctx *ctx, struct pf_kruleset *ruleset)
 			*ctx->rm = ctx->pd->related_rule;
 			break;
 		}
+		PF_TEST_ATTRIB(r->rule_flag & PFRULE_EXPIRED,
+		    TAILQ_NEXT(r, entries));
+		/* Don't count expired rule evaluations. */
 		pf_counter_u64_add(&r->evaluations, 1);
 		PF_TEST_ATTRIB(pfi_kkif_match(r->kif, pd->kif) == r->ifnot,
 			r->skip[PF_SKIP_IFP]);
@@ -5736,6 +5739,21 @@ pf_match_rule(struct pf_test_ctx *ctx, struct pf_kruleset *ruleset)
 		if (r->tag)
 			ctx->tag = r->tag;
 		if (r->anchor == NULL) {
+
+			if (r->rule_flag & PFRULE_ONCE) {
+				uint32_t	rule_flag;
+
+				rule_flag = r->rule_flag;
+				if ((rule_flag & PFRULE_EXPIRED) == 0 &&
+				    atomic_cmpset_int(&r->rule_flag, rule_flag,
+				    rule_flag | PFRULE_EXPIRED)) {
+					//r->exptime = gettime();
+				} else {
+					r = TAILQ_NEXT(r, entries);
+					continue;
+				}
+			}
+
 			if (r->action == PF_MATCH) {
 				/*
 				 * Apply translations before increasing counters,
@@ -5813,6 +5831,7 @@ pf_match_rule(struct pf_test_ctx *ctx, struct pf_kruleset *ruleset)
 		r = TAILQ_NEXT(r, entries);
 	}
 
+
 	return (ctx->test_status);
 }
 
diff --git a/sys/netpfil/pf/pf.h b/sys/netpfil/pf/pf.h
index 54ffdbed3de5..bcd66fd17d5d 100644
--- a/sys/netpfil/pf/pf.h
+++ b/sys/netpfil/pf/pf.h
@@ -637,6 +637,8 @@ struct pf_rule {
 #define	PFRULE_PFLOW		0x00040000
 #define	PFRULE_ALLOW_RELATED	0x00080000
 #define	PFRULE_AFTO		0x00200000  /* af-to rule */
+#define	PFRULE_ONCE		0x00400000  /* one shot rule */
+#define	PFRULE_EXPIRED		0x00800000  /* one shot rule hit by pkt */
 
 #ifdef _KERNEL
 #define	PFRULE_REFS		0x0080	/* rule has references */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202509251241.58PCfXlb000781>