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
This commit is contained in:
Mark Johnston
2026-01-26 17:23:33 +00:00
parent 49ec19f1e1
commit 39878d24a6
+10 -5
View File
@@ -11961,11 +11961,11 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
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 @@ pf_test(sa_family_t af, int dir, int pflags, struct ifnet *ifp, struct mbuf **m0
}
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?! */