git: 8bced6260072 - main - pf: Fix pfr_kentry_byaddr() to be used for a rule in an anchor

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Sat, 12 Jul 2025 13:38:55 UTC
The branch main has been updated by kp:

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

commit 8bced626007201293dbbbc217d4a6dd7e8ecc9fc
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2025-07-07 09:26:06 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2025-07-12 09:57:51 +0000

    pf: Fix pfr_kentry_byaddr() to be used for a rule in an anchor
    
    It couldn't find an entry if its table is attached a table on the root. This
    fixes the problem "route-to <TABLE> least-states" doesn't work.
    The problem is found by IIJ.
    
    OK sashan
    
    Obtained from:  OpenBSD, yasuoka <yasuoka@openbsd.org>, a7d8badaea
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
---
 sys/netpfil/pf/pf_table.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/sys/netpfil/pf/pf_table.c b/sys/netpfil/pf/pf_table.c
index 43e4366845a2..4faf328a2315 100644
--- a/sys/netpfil/pf/pf_table.c
+++ b/sys/netpfil/pf/pf_table.c
@@ -2074,11 +2074,11 @@ pfr_lookup_table(struct pfr_table *tbl)
 	    (struct pfr_ktable *)tbl));
 }
 
-int
-pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
+static struct pfr_kentry *
+pfr_kentry_byaddr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
+    int exact)
 {
 	struct pfr_kentry	*ke = NULL;
-	int			 match;
 
 	PF_RULES_RASSERT();
 
@@ -2121,11 +2121,26 @@ pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
 	default:
 		unhandled_af(af);
 	}
+	if (exact && ke && KENTRY_NETWORK(ke))
+		ke = NULL;
+
+	return (ke);
+}
+
+int
+pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
+{
+	struct pfr_kentry	*ke = NULL;
+	int match;
+
+	ke = pfr_kentry_byaddr(kt, a, af, 0);
+
 	match = (ke && !ke->pfrke_not);
 	if (match)
 		pfr_kstate_counter_add(&kt->pfrkt_match, 1);
 	else
 		pfr_kstate_counter_add(&kt->pfrkt_nomatch, 1);
+
 	return (match);
 }