The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=96c7e70c18a42e8cad9305db2a3b30328d76d84f
commit 96c7e70c18a42e8cad9305db2a3b30328d76d84f Author: Kristof Provost <[email protected]> AuthorDate: 2025-12-29 16:50:08 +0000 Commit: Kristof Provost <[email protected]> CommitDate: 2025-12-30 13:16:53 +0000 pf: convert DIOCRCLRASTATS to netlink Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 78 +++++++++++++++++++++++++++++++++++++----------- sbin/pfctl/pfctl_radix.c | 8 ++++- sys/netpfil/pf/pf_nl.c | 40 +++++++++++++++++++++++++ sys/netpfil/pf/pf_nl.h | 2 ++ 4 files changed, 109 insertions(+), 19 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 6aac9a9c04ae..f8c92a5cd319 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -3757,7 +3757,8 @@ struct nl_astats { struct pfr_astats *a; size_t max; size_t count; - uint64_t total_count; + uint32_t total_count; + uint32_t zeroed; }; #define _OUT(_field) offsetof(struct pfr_astats, _field) @@ -3792,6 +3793,7 @@ snl_attr_get_pfr_astats(struct snl_state *ss, struct nlattr *nla, static struct snl_attr_parser ap_table_get_astats[] = { { .type = PF_TAS_ASTATS, .off = 0, .cb = snl_attr_get_pfr_astats }, { .type = PF_TAS_ASTATS_COUNT, .off = _OUT(total_count), .cb = snl_attr_get_uint32 }, + { .type = PF_TAS_ASTATS_ZEROED, .off = _OUT(zeroed), .cb = snl_attr_get_uint32 }, }; #undef _OUT SNL_DECLARE_PARSER(table_astats_parser, struct genlmsghdr, snl_f_p_empty, ap_table_get_astats); @@ -3844,27 +3846,67 @@ pfctl_get_astats(struct pfctl_handle *h, const struct pfr_table *tbl, return (0); } -int -pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, - struct pfr_addr *addr, int size, int *nzero, int flags) +static int +_pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nzero, int flags) { - struct pfioc_table io; + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + struct nl_astats attrs; + int family_id; - if (size < 0 || !tbl || (size && !addr)) { - errno = EINVAL; - return (-1); + 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_CLEAR_ASTATS); + + 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; } - 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(h->fd, DIOCRCLRASTATS, &io) == -1) - return (-1); if (nzero) - *nzero = io.pfrio_nzero; - return (0); + *nzero = attrs.zeroed; + + return (e.error); +} + +int +pfctl_clr_astats(struct pfctl_handle *h, const struct pfr_table *tbl, + struct pfr_addr *addrs, int size, int *nzero, int flags) +{ + int ret; + int off = 0; + int partial_zeroed; + int chunk_size; + + do { + chunk_size = MIN(size - off, 256); + ret = _pfctl_clr_astats(h, tbl, &addrs[off], chunk_size, + &partial_zeroed, flags); + if (ret != 0) + break; + if (nzero) + *nzero += partial_zeroed; + off += chunk_size; + } while (off < size); + + return (ret); } diff --git a/sbin/pfctl/pfctl_radix.c b/sbin/pfctl/pfctl_radix.c index 4ae301756200..e8d3a1b8dcc3 100644 --- a/sbin/pfctl/pfctl_radix.c +++ b/sbin/pfctl/pfctl_radix.c @@ -201,7 +201,13 @@ int pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, int *nzero, int flags) { - return (pfctl_clr_astats(pfh, tbl, addr, size, nzero, flags)); + int ret; + + ret = pfctl_clr_astats(pfh, tbl, addr, size, nzero, 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 6bd858373bd2..0a8538607ed7 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -2434,6 +2434,39 @@ out: free(pfrastats, M_PF); return (error); } +static int +pf_handle_table_clear_astats(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; + + error = nl_parse_nlmsg(hdr, &table_addr_parser, npt, &attrs); + if (error != 0) + return (error); + + PF_RULES_WLOCK(); + error = pfr_clr_astats(&attrs.table, &attrs.addrs[0], + attrs.addr_count, &attrs.nchange, + attrs.flags | PFR_FLAG_USERIOCTL); + PF_RULES_WUNLOCK(); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_TABLE_CLEAR_ASTATS; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + nlattr_add_u32(nw, PF_TAS_ASTATS_ZEROED, attrs.nchange); + + if (!nlmsg_end(nw)) + return (ENOMEM); + + return (error); +} static const struct nlhdr_parser *all_parsers[] = { &state_parser, @@ -2708,6 +2741,13 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_TABLE_CLEAR_ASTATS, + .cmd_name = "TABLE_CLEAR_ASTATS", + .cmd_cb = pf_handle_table_clear_astats, + .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 5ca14758932a..216f3d13db32 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -72,6 +72,7 @@ enum { PFNL_CMD_TABLE_SET_ADDR = 34, PFNL_CMD_TABLE_GET_ADDR = 35, PFNL_CMD_TABLE_GET_ASTATS = 36, + PFNL_CMD_TABLE_CLEAR_ASTATS = 37, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -504,6 +505,7 @@ enum pf_table_astats_t { PF_TAS_ASTATS = 2, /* nested, pfr_astats_t */ PF_TAS_FLAGS = 3, /* u32 */ PF_TAS_ASTATS_COUNT = 4, /* u32 */ + PF_TAS_ASTATS_ZEROED = 5, /* u32 */ }; #ifdef _KERNEL
