git: ba2a92078626 - main - pf: convert DIOCBEGINADDRS to netlink

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Sat, 08 Jun 2024 02:47:22 UTC
The branch main has been updated by kp:

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

commit ba2a920786265f364973562abe9262829cf1901b
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-06-07 20:44:40 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-06-08 02:46:43 +0000

    pf: convert DIOCBEGINADDRS to netlink
---
 contrib/pf/ftp-proxy/filter.c  |  2 +-
 contrib/pf/tftp-proxy/filter.c |  2 +-
 lib/libpfctl/libpfctl.c        | 49 ++++++++++++++++++++++++++++++++++++++++++
 lib/libpfctl/libpfctl.h        |  1 +
 sbin/pfctl/pfctl.c             |  2 +-
 sys/net/pfvar.h                |  1 +
 sys/netpfil/pf/pf_ioctl.c      | 16 ++++++++++----
 sys/netpfil/pf/pf_nl.c         | 37 +++++++++++++++++++++++++++++++
 sys/netpfil/pf/pf_nl.h         |  6 ++++++
 9 files changed, 109 insertions(+), 7 deletions(-)

diff --git a/contrib/pf/ftp-proxy/filter.c b/contrib/pf/ftp-proxy/filter.c
index e3276f88489e..7d6d3f1fa348 100644
--- a/contrib/pf/ftp-proxy/filter.c
+++ b/contrib/pf/ftp-proxy/filter.c
@@ -263,7 +263,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 		errno = EINVAL;
 		return (-1);
 	}
-	if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
+	if (pfctl_begin_addrs(pfh, &pfp.ticket))
 		return (-1);
 	pfpool_ticket = pfp.ticket;
 
diff --git a/contrib/pf/tftp-proxy/filter.c b/contrib/pf/tftp-proxy/filter.c
index 3cf2e1fcf3ab..8d5dcc21badc 100644
--- a/contrib/pf/tftp-proxy/filter.c
+++ b/contrib/pf/tftp-proxy/filter.c
@@ -272,7 +272,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 		errno = EINVAL;
 		return (-1);
 	}
-	if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
+	if (pfctl_begin_addrs(pfh, &pfp.ticket))
 		return (-1);
 	pfpool_ticket = pfp.ticket;
 
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index ebe52e7a415f..b9fba232b8ca 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -2688,3 +2688,52 @@ pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit)
 
 	return (e.error);
 }
+
+struct pfctl_nl_begin_addrs {
+	uint32_t ticket;
+};
+#define	_OUT(_field)	offsetof(struct pfctl_nl_begin_addrs, _field)
+static struct snl_attr_parser ap_begin_addrs[] = {
+	{ .type = PF_BA_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 },
+};
+static struct snl_field_parser fp_begin_addrs[] = {};
+#undef _OUT
+SNL_DECLARE_PARSER(begin_addrs_parser, struct genlmsghdr, fp_begin_addrs, ap_begin_addrs);
+
+int
+pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket)
+{
+	struct snl_writer nw;
+	struct pfctl_nl_begin_addrs attrs = {};
+	struct snl_errmsg_data e = {};
+	struct nlmsghdr *hdr;
+	uint32_t seq_id;
+	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_BEGIN_ADDRS);
+	hdr->nlmsg_flags |= NLM_F_DUMP;
+
+	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, &begin_addrs_parser, &attrs))
+			continue;
+	}
+
+	if (ticket != NULL)
+		*ticket = attrs.ticket;
+
+	return (e.error);
+}
+
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 44c7fa47e88d..eebc97c52565 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -497,5 +497,6 @@ int	pfctl_set_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t seconds
 int	pfctl_get_timeout(struct pfctl_handle *h, uint32_t timeout, uint32_t *seconds);
 int	pfctl_set_limit(struct pfctl_handle *h, const int index, const uint limit);
 int	pfctl_get_limit(struct pfctl_handle *h, const int index, uint *limit);
+int	pfctl_begin_addrs(struct pfctl_handle *h, uint32_t *ticket);
 
 #endif
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index ec718f6b0a99..450c64785b9c 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1719,7 +1719,7 @@ pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af)
 	struct pf_pooladdr *pa;
 
 	if ((pf->opts & PF_OPT_NOACTION) == 0) {
-		if (ioctl(pf->dev, DIOCBEGINADDRS, &pf->paddr))
+		if (pfctl_begin_addrs(pf->h, &pf->paddr.ticket))
 			err(1, "DIOCBEGINADDRS");
 	}
 
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index eb36c0aee4d1..d6d01c9b5970 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -2507,6 +2507,7 @@ int			 pf_ioctl_get_timeout(int, int *);
 int			 pf_ioctl_set_timeout(int, int, int *);
 int			 pf_ioctl_get_limit(int, unsigned int *);
 int			 pf_ioctl_set_limit(int, unsigned int, unsigned int *);
+int			 pf_ioctl_begin_addrs(uint32_t *);
 
 void			 pf_krule_free(struct pf_krule *);
 void			 pf_krule_clear_counters(struct pf_krule *);
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index af3f914982ec..f801afd9da80 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -2517,6 +2517,17 @@ pf_ioctl_get_limit(int index, unsigned int *limit)
 	return (0);
 }
 
+int
+pf_ioctl_begin_addrs(uint32_t *ticket)
+{
+	PF_RULES_WLOCK();
+	pf_empty_kpool(&V_pf_pabuf);
+	*ticket = ++V_ticket_pabuf;
+	PF_RULES_WUNLOCK();
+
+	return (0);
+}
+
 static int
 pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
 {
@@ -4182,10 +4193,7 @@ DIOCGETSTATESV2_full:
 	case DIOCBEGINADDRS: {
 		struct pfioc_pooladdr	*pp = (struct pfioc_pooladdr *)addr;
 
-		PF_RULES_WLOCK();
-		pf_empty_kpool(&V_pf_pabuf);
-		pp->ticket = ++V_ticket_pabuf;
-		PF_RULES_WUNLOCK();
+		error = pf_ioctl_begin_addrs(&pp->ticket);
 		break;
 	}
 
diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c
index 57b1a4a6b5b3..615a9229b3f3 100644
--- a/sys/netpfil/pf/pf_nl.c
+++ b/sys/netpfil/pf/pf_nl.c
@@ -1471,6 +1471,36 @@ pf_handle_get_limit(struct nlmsghdr *hdr, struct nl_pstate *npt)
 	return (0);
 }
 
+static int
+pf_handle_begin_addrs(struct nlmsghdr *hdr, struct nl_pstate *npt)
+{
+	struct nl_writer *nw = npt->nw;
+	struct genlmsghdr *ghdr_new;
+	uint32_t ticket;
+	int error;
+
+	error = pf_ioctl_begin_addrs(&ticket);
+	if (error != 0)
+		return (error);
+
+	if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr)))
+		return (ENOMEM);
+
+	ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr);
+	ghdr_new->cmd = PFNL_CMD_BEGIN_ADDRS;
+	ghdr_new->version = 0;
+	ghdr_new->reserved = 0;
+
+	nlattr_add_u32(nw, PF_BA_TICKET, ticket);
+
+	if (!nlmsg_end(nw)) {
+		nlmsg_abort(nw);
+		return (ENOMEM);
+	}
+
+	return (0);
+}
+
 static const struct nlhdr_parser *all_parsers[] = {
 	&state_parser,
 	&addrule_parser,
@@ -1612,6 +1642,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_BEGIN_ADDRS,
+		.cmd_name = "BEGIN_ADDRS",
+		.cmd_cb = pf_handle_begin_addrs,
+		.cmd_flags = GENL_CMD_CAP_DO | 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 437cc6482dbb..d50b5a1e9d43 100644
--- a/sys/netpfil/pf/pf_nl.h
+++ b/sys/netpfil/pf/pf_nl.h
@@ -54,6 +54,7 @@ enum {
 	PFNL_CMD_GET_TIMEOUT = 16,
 	PFNL_CMD_SET_LIMIT = 17,
 	PFNL_CMD_GET_LIMIT = 18,
+	PFNL_CMD_BEGIN_ADDRS = 19,
 	__PFNL_CMD_MAX,
 };
 #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1)
@@ -350,6 +351,11 @@ enum pf_limit_types_t {
 	PF_LI_LIMIT		= 2, /* u32 */
 };
 
+enum pf_begin_addrs_types_t {
+	PF_BA_UNSPEC,
+	PF_BA_TICKET		= 1, /* u32 */
+};
+
 #ifdef _KERNEL
 
 void	pf_nl_register(void);