From nobody Mon Feb 16 12:47:06 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fF2bb2rgHz6RjRn for ; Mon, 16 Feb 2026 12:47:07 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fF2bb0nv6z42ph for ; Mon, 16 Feb 2026 12:47:07 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1771246027; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qD8midF8tCn1uE0zY05U4vQgQaQ6GzdQziZqgt28Xcw=; b=Hx7GqkCCu4LiWKDPXi1G4maQokCo8Hs1MDVPnqj8HWhONOjOvyz1xMN2be2EoivJLEueiv DxAh8+U6jhwMh4MdasqOzisqH4NvnQP3UN/JwkzmJKxpLpEAqlq7oKDOCm0Zz+JuAfkjmg Cl0EMUxEnynLOufyCAog5Nfge7qBFq/kdqyoUKpBbSgnIw74SIpP9YIbF4C31COb1O7PfM 75qClbcOAKoCAUJcsL8uncO09/5SqZvunZabCrlpY/r+Hn+4MvouRLl6930AjMj5W+S+CC Pidp92jsUy6OnyN+Lk+NU9qSkQBAmiDOeafqggqQ7WnZJwYUsg+DdW3qLfo7BQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1771246027; a=rsa-sha256; cv=none; b=fJ/N66QqBPACkHNaULwfvCLeZ5b6nQ7c2Xd2a2GcWSctBrzyZtWwYObx5pLkXBvg69tcWn mn3iXnQtBuQfVdJzYYvIkIHsftJ2wkI6S3PfLAKTNZUj3Ldooa6RHkaNJt8zu0rUUQ0OuW kWiT/s0d+ajJ0QCWQFUnOkhrknBii9sBGXIeQOjiVarp9JaD64AwWWeBAUDLZmydNZWKpj C5y1WaiHnkrhKKSIZsIaLrcepzuCS2Z1VOecer2dMrwCL0MXyMdLdzUzYFGLUxTQerkFyY s/CTvG0GxlP+XW+3Jy3lsEvsobs6kGR+713Z6jvzlQtne9UZFGKdqQbbdFt8dA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1771246027; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qD8midF8tCn1uE0zY05U4vQgQaQ6GzdQziZqgt28Xcw=; b=QvySdzRle2Q8Bgao84W8sFtxJtZRCXDUfjfPCD5yhBvh9sf9nYEP4MRCa0hDUUa7ZVMK0w EBwig9jdp98i0EXB8s1b/SmErQfxpLQ2q5fjZvEFlmHKMkliKY7LpvBYu1ZcR3Pw7XR0x+ 5n1X0Ai14eeyWjv3Tl2QP83Utxp4r5yB6X+n1+IWAveTZbdV8Vuj4cXtqL7XIfxQlljvR0 fIfywvcxxO3LpWyRmAF86AQ1cV55OpH64l6K88F07hGzn0G9UjWZQAcnUQjOg1Vhgu+aVL QGV7R1M0b5Q2c8FD4Hu5m53/jl8zPg5D8RFzcsh6L7h9wyTCfWSCjbUdqkeY9A== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fF2bZ6qktz7xN for ; Mon, 16 Feb 2026 12:47:06 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3cf0a by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 16 Feb 2026 12:47:06 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 281282e9357b - main - pf: convert DIOCRTSTADDRS to netlink List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 281282e9357b95b679d36ca6d8561e96c1263937 Auto-Submitted: auto-generated Date: Mon, 16 Feb 2026 12:47:06 +0000 Message-Id: <699311ca.3cf0a.35dca8f0@gitrepo.freebsd.org> The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=281282e9357b95b679d36ca6d8561e96c1263937 commit 281282e9357b95b679d36ca6d8561e96c1263937 Author: Kristof Provost AuthorDate: 2026-02-13 16:21:33 +0000 Commit: Kristof Provost CommitDate: 2026-02-16 12:42:50 +0000 pf: convert DIOCRTSTADDRS to netlink Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 67 +++++++++++++++++++++++++++++++++++++++++++ lib/libpfctl/libpfctl.h | 2 ++ sbin/pfctl/pfctl_radix.c | 21 +++++--------- sys/netpfil/pf/pf_nl.c | 41 ++++++++++++++++++++++++++ sys/netpfil/pf/pf_nl.h | 1 + tests/sys/netpfil/pf/table.sh | 38 ++++++++++++++++++++++++ 6 files changed, 156 insertions(+), 14 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 9025b94249ce..cd484949e4da 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -3916,6 +3916,73 @@ pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, return (ret); } +static int +_pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nmatch, int flags) +{ + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + struct nl_astats attrs; + int family_id; + + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); + + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_TABLE_TEST_ADDRS); + + snl_add_msg_attr_table(&nw, PF_TA_TABLE, tbl); + snl_add_msg_attr_u32(&nw, PF_TA_FLAGS, flags); + for (int i = 0; i < size; i++) + snl_add_msg_attr_pfr_addr(&nw, PF_TA_ADDR, &addrs[i]); + + if ((hdr = snl_finalize_msg(&nw)) == NULL) + return (ENXIO); + seq_id = hdr->nlmsg_seq; + + if (! snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (! snl_parse_nlmsg(&h->ss, hdr, &table_astats_parser, &attrs)) + continue; + } + + if (nmatch) + *nmatch = attrs.total_count; + + return (e.error); +} + +int +pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nmatch, int flags) +{ + int ret; + int off = 0; + int partial_match; + int chunk_size; + + if (nmatch) + *nmatch = 0; + + do { + chunk_size = MIN(size - off, 256); + ret = _pfctl_test_addrs(h, tbl, &addrs[off], chunk_size, + &partial_match, flags); + if (ret != 0) + break; + if (nmatch) + *nmatch += partial_match; + off += chunk_size; + } while (off < size); + + return (ret); +} + static void snl_add_msg_attr_limit_rate(struct snl_writer *nw, uint32_t type, const struct pfctl_limit_rate *rate) diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index d55267e56b4c..1012be53db65 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -597,6 +597,8 @@ int pfctl_get_astats(struct pfctl_handle *h, const struct pfr_table *tbl, struct pfr_astats *addr, int *size, int flags); int pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, struct pfr_addr *addr, int size, int *nzero, int flags); +int pfctl_test_addrs(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addr, int size, int *nmatch, int flags); struct pfctl_limit_rate { unsigned int limit; diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index e8d3a1b8dcc3..608c22141ae8 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -214,25 +214,18 @@ int pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, int *nmatch, int flags) { - struct pfioc_table io; + int ret; if (tbl == NULL || size < 0 || (size && addr == NULL)) { errno = EINVAL; return (-1); } - bzero(&io, sizeof io); - io.pfrio_flags = flags; - io.pfrio_table = *tbl; - io.pfrio_buffer = addr; - io.pfrio_esize = sizeof(*addr); - io.pfrio_size = size; - if (ioctl(dev, DIOCRTSTADDRS, &io)) { - pfr_report_error(tbl, &io, "test addresses in"); - return (-1); - } - if (nmatch) - *nmatch = io.pfrio_nmatch; - return (0); + + ret = pfctl_test_addrs(pfh, tbl, addr, size, nmatch, flags); + if (ret != 0) + errno = ret; + + return (ret); } int diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index 7a7655d7d9c8..c2ea65f4b043 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -2467,6 +2467,40 @@ pf_handle_table_clear_astats(struct nlmsghdr *hdr, struct nl_pstate *npt) return (error); } +static int +pf_handle_table_test_addrs(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct nl_parsed_table_addrs attrs = { 0 }; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + int error; + + PF_RULES_RLOCK_TRACKER; + + error = nl_parse_nlmsg(hdr, &table_addr_parser, npt, &attrs); + if (error != 0) + return (error); + + PF_RULES_RLOCK(); + error = pfr_tst_addrs(&attrs.table, &attrs.addrs[0], + attrs.addr_count, &attrs.nchange, + attrs.flags | PFR_FLAG_USERIOCTL); + PF_RULES_RUNLOCK(); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_TABLE_TEST_ADDRS; + + nlattr_add_u32(nw, PF_TAS_ASTATS_COUNT, attrs.nchange); + + if (!nlmsg_end(nw)) + return (ENOMEM); + + return (error); +} + static const struct nlattr_parser nla_p_rate[] = { { .type = PF_LR_LIMIT, .off = 0, .cb = nlattr_get_uint32 }, { .type = PF_LR_SECONDS, .off = sizeof(unsigned int), .cb = nlattr_get_uint32 }, @@ -3154,6 +3188,13 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_TABLE_TEST_ADDRS, + .cmd_name = "TABLE_TEST_ADDRS", + .cmd_cb = pf_handle_table_test_addrs, + .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index 84e9d3a97303..6591c707d9a4 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -82,6 +82,7 @@ enum { PFNL_CMD_SOURCE_GET = 44, PFNL_CMD_SOURCE_NGET = 45, PFNL_CMD_SOURCE_CLEAR = 46, + PFNL_CMD_TABLE_TEST_ADDRS = 47, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) diff --git a/tests/sys/netpfil/pf/table.sh b/tests/sys/netpfil/pf/table.sh index cd83ac90e559..743bfe08557d 100644 --- a/tests/sys/netpfil/pf/table.sh +++ b/tests/sys/netpfil/pf/table.sh @@ -846,6 +846,43 @@ load_cleanup() pft_cleanup } +atf_test_case "test" "cleanup" +test_head() +{ + atf_set descr 'Test pfctl -T test functionality' + atf_set require.user root +} + +test_body() +{ + pft_init + + epair_send=$(vnet_mkepair) + ifconfig ${epair_send}a 192.0.2.1/24 up + + vnet_mkjail alcatraz ${epair_send}b + jexec alcatraz ifconfig ${epair_send}b 192.0.2.2/24 up + jexec alcatraz pfctl -e + + pft_set_rules alcatraz \ + "table counters { 192.0.2.1 }" \ + "pass all" \ + "match in from to any" \ + "match out from any to " + + atf_check -s exit:0 -o ignore ping -c 3 192.0.2.2 + + atf_check -s exit:2 -e match:"0/1 addresses match." \ + jexec alcatraz pfctl -t foo -T test 1.2.3.4 + atf_check -s exit:0 -e match:"1/1 addresses match." \ + jexec alcatraz pfctl -t foo -T test 192.0.2.1 +} + +test_cleanup() +{ + pft_cleanup +} + atf_init_test_cases() { atf_add_test_case "v4_counters" @@ -866,4 +903,5 @@ atf_init_test_cases() atf_add_test_case "in_anchor" atf_add_test_case "replace" atf_add_test_case "load" + atf_add_test_case "test" }