git: 806adba81f3d - main - libpfctl: decode PFR_A_AF into a u8

From: R. Christian McDonald <rcm_at_FreeBSD.org>
Date: Tue, 29 Sep 2026 11:03:24 UTC
The branch main has been updated by rcm:

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

commit 806adba81f3d808994b0cec955c38ef1a089e739
Author:     R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-29 01:21:56 +0000
Commit:     R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-09-29 11:00:50 +0000

    libpfctl: decode PFR_A_AF into a u8
    
    The kernel sends PFR_A_AF as a u32, although it is documented and
    parsed as a u8, and libpfctl decoded it with snl_attr_get_uint32()
    straight into the u8 pfra_af.  That overwrote pfra_net, pfra_not and
    pfra_fback, and left pfra_af zero on big-endian hosts.
    
    Decode it via a temporary, and accept a u8 as well, so that the
    kernel can be corrected later without breaking libpfctl.
    
    Reviewed by:            kp
    Approved by:            kp (mentor)
    Fixes:                  f27e44e2e3b5 ("pf: convert DIOCRGETADDRS to netlink")
    Sponsored by:           Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D60110
---
 lib/libpfctl/libpfctl.c | 18 +++++++++++++++++-
 sys/netpfil/pf/pf_nl.h  |  2 +-
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 26fcb6f50045..6578cff5e45a 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -2777,9 +2777,25 @@ struct nl_addrs {
 	size_t total_count;
 };
 
+/* pfra_af is a u8, but the kernel sends PFR_A_AF as a u32.  Accept both. */
+static bool
+snl_attr_get_pfra_af(struct snl_state *ss, struct nlattr *nla,
+    const void *arg __unused, void *target)
+{
+	uint32_t af;
+
+	if (snl_attr_get_uint8(ss, nla, NULL, target))
+		return (true);
+	if (! snl_attr_get_uint32(ss, nla, NULL, &af))
+		return (false);
+	*(uint8_t *)target = af;
+
+	return (true);
+}
+
 #define _OUT(_field)	offsetof(struct pfr_addr, _field)
 static const struct snl_attr_parser ap_pfr_addr[] = {
-	{ .type = PFR_A_AF, .off = _OUT(pfra_af), .cb = snl_attr_get_uint32 },
+	{ .type = PFR_A_AF, .off = _OUT(pfra_af), .cb = snl_attr_get_pfra_af },
 	{ .type = PFR_A_NET, .off = _OUT(pfra_net), .cb = snl_attr_get_uint8 },
 	{ .type = PFR_A_NOT, .off = _OUT(pfra_not), .cb = snl_attr_get_bool },
 	{ .type = PFR_A_ADDR, .off = _OUT(pfra_ip6addr), .cb = snl_attr_get_in6_addr },
diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h
index 2b6785b6ffca..220ef8ea9cd8 100644
--- a/sys/netpfil/pf/pf_nl.h
+++ b/sys/netpfil/pf/pf_nl.h
@@ -494,7 +494,7 @@ enum pf_tstats_t {
 
 enum pfr_addr_t {
 	PFR_A_UNSPEC,
-	PFR_A_AF		= 1, /* uint8_t */
+	PFR_A_AF		= 1, /* uint8_t, uint32_t in replies */
 	PFR_A_NET		= 2, /* uint8_t */
 	PFR_A_NOT		= 3, /* bool */
 	PFR_A_ADDR		= 4, /* in6_addr */