git: 39878d24a690 - main - pf: Rationalize the ip_divert_ptr test

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 26 Jan 2026 17:24:54 UTC
The branch main has been updated by markj:

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

commit 39878d24a690feb4da3fc223649c6a5fd166d09d
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-01-26 17:23:33 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-01-26 17:23:33 +0000

    pf: Rationalize the ip_divert_ptr test
    
    If a rule has a divert port set, then we can reasonably predict that
    ipdivert.ko is loaded, and in particular that ip_divert_ptr is set.
    
    Moreover, in this case, if ipdivert.ko is not loaded we should just drop
    the packet instead of ignoring the divert rule.
    
    Reviewed by:    igoro, kp, glebius
    MFC after:      2 weeks
    Sponsored by:   OPNsense
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D54845
---
 sys/netpfil/pf/pf.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
index bec6911795bd..c01b32e5a8b5 100644
--- a/sys/netpfil/pf/pf.c
+++ b/sys/netpfil/pf/pf.c
@@ -11961,11 +11961,11 @@ done:
 	    pf_is_loopback(af, pd.dst))
 		pd.m->m_flags |= M_SKIP_FIREWALL;
 
-	if (af == AF_INET && __predict_false(ip_divert_ptr != NULL) &&
-	    action == PF_PASS && r->divert.port && !PACKET_LOOPED(&pd)) {
+	if (af == AF_INET && action == PF_PASS && r->divert.port &&
+	    !PACKET_LOOPED(&pd)) {
 		mtag = m_tag_alloc(MTAG_PF_DIVERT, 0,
 		    sizeof(struct pf_divert_mtag), M_NOWAIT | M_ZERO);
-		if (mtag != NULL) {
+		if (__predict_true(mtag != NULL && ip_divert_ptr != NULL)) {
 			((struct pf_divert_mtag *)(mtag+1))->port =
 			    ntohs(r->divert.port);
 			((struct pf_divert_mtag *)(mtag+1))->idir =
@@ -11994,15 +11994,20 @@ done:
 			}
 			ip_divert_ptr(*m0, dir == PF_IN);
 			*m0 = NULL;
-
 			return (action);
-		} else {
+		} else if (mtag == NULL) {
 			/* XXX: ipfw has the same behaviour! */
 			action = PF_DROP;
 			REASON_SET(&reason, PFRES_MEMORY);
 			pd.act.log = PF_LOG_FORCE;
 			DPFPRINTF(PF_DEBUG_MISC,
 			    "pf: failed to allocate divert tag");
+		} else {
+			action = PF_DROP;
+			REASON_SET(&reason, PFRES_MATCH);
+			pd.act.log = PF_LOG_FORCE;
+			DPFPRINTF(PF_DEBUG_MISC,
+			    "pf: divert(4) is not loaded");
 		}
 	}
 	/* XXX: Anybody working on it?! */