git: 044243fcc9b4 - main - libpfctl: allow access to the fd

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Mon, 29 Apr 2024 14:36:49 UTC
The branch main has been updated by kp:

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

commit 044243fcc9b4c639cf5655e37b98478bcb312590
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-04-24 06:40:05 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-04-29 14:32:23 +0000

    libpfctl: allow access to the fd
    
    pfctl_open() opens both /dev/pf and a netlink socket. Allow access to the /dev/
    pf fd via pfctl_fd().
    This means that libpfctl users no longer have to open /dev/pf themselves for any
    calls that are not yet available in libpfctl.
    
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    MFC after:      2 weeks
---
 contrib/pf/authpf/authpf.c     | 20 +++++++++-----------
 contrib/pf/ftp-proxy/filter.c  | 23 ++++++++++-------------
 contrib/pf/tftp-proxy/filter.c | 25 ++++++++++---------------
 lib/libpfctl/libpfctl.c        |  6 ++++++
 lib/libpfctl/libpfctl.h        |  1 +
 5 files changed, 36 insertions(+), 39 deletions(-)

diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c
index 81dbcb747f5f..fcf9812cdcca 100644
--- a/contrib/pf/authpf/authpf.c
+++ b/contrib/pf/authpf/authpf.c
@@ -56,7 +56,6 @@ static int	change_filter(int, const char *, const char *);
 static int	change_table(int, const char *);
 static void	authpf_kill_states(void);
 
-int	dev;			/* pf device */
 struct pfctl_handle	 *pfh;
 char	anchorname[PF_ANCHOR_NAME_SIZE] = "authpf";
 char	rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2];
@@ -135,9 +134,8 @@ main(void)
 		exit(1);
 	}
 	/* open the pf device */
-	dev = open(PATH_DEVFILE, O_RDWR);
 	pfh = pfctl_open(PATH_DEVFILE);
-	if (dev == -1 || pfh == NULL) {
+	if (pfh == NULL) {
 		syslog(LOG_ERR, "cannot open packet filter device (%m)");
 		goto die;
 	}
@@ -648,7 +646,7 @@ remove_stale_rulesets(void)
 
 	memset(&prs, 0, sizeof(prs));
 	strlcpy(prs.path, anchorname, sizeof(prs.path));
-	if (ioctl(dev, DIOCGETRULESETS, &prs)) {
+	if (ioctl(pfctl_fd(pfh), DIOCGETRULESETS, &prs)) {
 		if (errno == EINVAL)
 			return (0);
 		else
@@ -661,7 +659,7 @@ remove_stale_rulesets(void)
 		pid_t	 pid;
 
 		prs.nr = nr - 1;
-		if (ioctl(dev, DIOCGETRULESET, &prs))
+		if (ioctl(pfctl_fd(pfh), DIOCGETRULESET, &prs))
 			return (1);
 		errno = 0;
 		if ((t = strchr(prs.name, '(')) == NULL)
@@ -705,8 +703,8 @@ recursive_ruleset_purge(char *an, char *rs)
 		snprintf(t_e[i].anchor, sizeof(t_e[i].anchor), "%s/%s", an, rs);
 	}
 	t_e[PF_RULESET_MAX].rs_num = PF_RULESET_TABLE;
-	if ((ioctl(dev, DIOCXBEGIN, t) ||
-	    ioctl(dev, DIOCXCOMMIT, t)) &&
+	if ((ioctl(pfctl_fd(pfh), DIOCXBEGIN, t) ||
+	    ioctl(pfctl_fd(pfh), DIOCXCOMMIT, t)) &&
 	    errno != EINVAL)
 		goto cleanup;
 
@@ -714,7 +712,7 @@ recursive_ruleset_purge(char *an, char *rs)
 	if ((prs = calloc(1, sizeof(struct pfioc_ruleset))) == NULL)
 		goto no_mem;
 	snprintf(prs->path, sizeof(prs->path), "%s/%s", an, rs);
-	if (ioctl(dev, DIOCGETRULESETS, prs)) {
+	if (ioctl(pfctl_fd(pfh), DIOCGETRULESETS, prs)) {
 		if (errno != EINVAL)
 			goto cleanup;
 		errno = 0;
@@ -723,7 +721,7 @@ recursive_ruleset_purge(char *an, char *rs)
 
 		while (nr) {
 			prs->nr = 0;
-			if (ioctl(dev, DIOCGETRULESET, prs))
+			if (ioctl(pfctl_fd(pfh), DIOCGETRULESET, prs))
 				goto cleanup;
 
 			if (recursive_ruleset_purge(prs->path, prs->name))
@@ -769,7 +767,7 @@ change_filter(int add, const char *l_user, const char *ip_src)
 
 		if (asprintf(&rsn, "%s/%s", anchorname, rulesetname) == -1)
 			goto no_mem;
-		if (asprintf(&fdpath, "/dev/fd/%d", dev) == -1)
+		if (asprintf(&fdpath, "/dev/fd/%d", pfctl_fd(pfh)) == -1)
 			goto no_mem;
 		if (asprintf(&ipstr, "user_ip=%s", ip_src) == -1)
 			goto no_mem;
@@ -868,7 +866,7 @@ change_table(int add, const char *ip_src)
 		return (-1);
 	}
 
-	if (ioctl(dev, add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
+	if (ioctl(pfctl_fd(pfh), add ? DIOCRADDADDRS : DIOCRDELADDRS, &io) &&
 	    errno != ESRCH) {
 		syslog(LOG_ERR, "cannot %s %s from table %s: %s",
 		    add ? "add" : "remove", ip_src, tablename,
diff --git a/contrib/pf/ftp-proxy/filter.c b/contrib/pf/ftp-proxy/filter.c
index 612e35c4ac6e..3bad5feb4be4 100644
--- a/contrib/pf/ftp-proxy/filter.c
+++ b/contrib/pf/ftp-proxy/filter.c
@@ -57,7 +57,7 @@ static uint32_t			pfticket;
 static uint32_t			pfpool_ticket;
 static struct pfioc_trans	pft;
 static struct pfioc_trans_e	pfte[TRANS_SIZE];
-static int dev, rule_log;
+static int rule_log;
 static struct pfctl_handle *pfh = NULL;
 static const char *qname, *tagname;
 
@@ -104,7 +104,7 @@ add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 		    &satosin6(nat)->sin6_addr.s6_addr, 16);
 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
 	}
-	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCADDADDR, &pfp) == -1)
 		return (-1);
 
 	pfrule.rpool.proxy_port[0] = nat_range_low;
@@ -138,7 +138,7 @@ add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 		    &satosin6(rdr)->sin6_addr.s6_addr, 16);
 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
 	}
-	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCADDADDR, &pfp) == -1)
 		return (-1);
 
 	pfrule.rpool.proxy_port[0] = rdr_port;
@@ -152,7 +152,7 @@ add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 int
 do_commit(void)
 {
-	if (ioctl(dev, DIOCXCOMMIT, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXCOMMIT, &pft) == -1)
 		return (-1);
 
 	return (0);
@@ -161,7 +161,7 @@ do_commit(void)
 int
 do_rollback(void)
 {
-	if (ioctl(dev, DIOCXROLLBACK, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXROLLBACK, &pft) == -1)
 		return (-1);
 	
 	return (0);
@@ -180,13 +180,10 @@ init_filter(const char *opt_qname, const char *opt_tagname, int opt_verbose)
 	else if (opt_verbose == 2)
 		rule_log = PF_LOG_ALL;
 
-	dev = open("/dev/pf", O_RDWR);	
-	if (dev == -1)
-		err(1, "open /dev/pf");
 	pfh = pfctl_open(PF_DEVICE);
 	if (pfh == NULL)
 		err(1, "pfctl_open");
-	status = pfctl_get_status(dev);
+	status = pfctl_get_status(pfctl_fd(pfh));
 	if (status == NULL)
 		err(1, "DIOCGETSTATUS");
 	if (!status->running)
@@ -227,7 +224,7 @@ prepare_commit(u_int32_t id)
 		}
 	}
 
-	if (ioctl(dev, DIOCXBEGIN, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXBEGIN, &pft) == -1)
 		return (-1);
 
 	return (0);
@@ -266,7 +263,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 		errno = EINVAL;
 		return (-1);
 	}
-	if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
 		return (-1);
 	pfpool_ticket = pfp.ticket;
 
@@ -366,7 +363,7 @@ server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
 	pnl.sport = client->sin_port;
 	pnl.dport = proxy->sin_port;
 	
-	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCNATLOOK, &pnl) == -1)
 		return (-1);
 
 	memset(server, 0, sizeof(struct sockaddr_in));
@@ -394,7 +391,7 @@ server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy,
 	pnl.sport = client->sin6_port;
 	pnl.dport = proxy->sin6_port;
 	
-	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCNATLOOK, &pnl) == -1)
 		return (-1);
 
 	memset(server, 0, sizeof(struct sockaddr_in6));
diff --git a/contrib/pf/tftp-proxy/filter.c b/contrib/pf/tftp-proxy/filter.c
index f372ddd0aeae..b69247caf04f 100644
--- a/contrib/pf/tftp-proxy/filter.c
+++ b/contrib/pf/tftp-proxy/filter.c
@@ -61,7 +61,7 @@ static char			pfanchor[PF_ANCHOR_NAME_SIZE];
 static char			pfanchor_call[PF_ANCHOR_NAME_SIZE];
 static struct pfioc_trans	pft;
 static struct pfioc_trans_e	pfte[TRANS_SIZE];
-static int dev, rule_log;
+static int rule_log;
 static struct pfctl_handle *pfh = NULL;
 static char *qname;
 
@@ -108,7 +108,7 @@ add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 		    &satosin6(nat)->sin6_addr.s6_addr, 16);
 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
 	}
-	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCADDADDR, &pfp) == -1)
 		return (-1);
 
 	pfrule.rpool.proxy_port[0] = nat_range_low;
@@ -142,7 +142,7 @@ add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 		    &satosin6(rdr)->sin6_addr.s6_addr, 16);
 		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
 	}
-	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCADDADDR, &pfp) == -1)
 		return (-1);
 
 	pfrule.rpool.proxy_port[0] = rdr_port;
@@ -156,7 +156,7 @@ add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
 int
 do_commit(void)
 {
-	if (ioctl(dev, DIOCXCOMMIT, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXCOMMIT, &pft) == -1)
 		return (-1);
 
 	return (0);
@@ -165,7 +165,7 @@ do_commit(void)
 int
 do_rollback(void)
 {
-	if (ioctl(dev, DIOCXROLLBACK, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXROLLBACK, &pft) == -1)
 		return (-1);
 	
 	return (0);
@@ -183,17 +183,12 @@ init_filter(char *opt_qname, int opt_verbose)
 	else if (opt_verbose == 2)
 		rule_log = PF_LOG_ALL;
 
-	dev = open("/dev/pf", O_RDWR);	
-	if (dev == -1) {
-		syslog(LOG_ERR, "can't open /dev/pf");
-		exit(1);
-	}
 	pfh = pfctl_open(PF_DEVICE);
 	if (pfh == NULL) {
 		syslog(LOG_ERR, "can't pfctl_open()");
 		exit(1);
 	}
-	status = pfctl_get_status(dev);
+	status = pfctl_get_status(pfctl_fd(pfh));
 	if (status == NULL) {
 		syslog(LOG_ERR, "DIOCGETSTATUS");
 		exit(1);
@@ -238,7 +233,7 @@ prepare_commit(u_int32_t id)
 		}
 	}
 
-	if (ioctl(dev, DIOCXBEGIN, &pft) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCXBEGIN, &pft) == -1)
 		return (-1);
 
 	return (0);
@@ -277,7 +272,7 @@ prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
 		errno = EINVAL;
 		return (-1);
 	}
-	if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCBEGINADDRS, &pfp) == -1)
 		return (-1);
 	pfpool_ticket = pfp.ticket;
 
@@ -379,7 +374,7 @@ server_lookup4(struct sockaddr_in *client, struct sockaddr_in *proxy,
 	pnl.sport = client->sin_port;
 	pnl.dport = proxy->sin_port;
 
-	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCNATLOOK, &pnl) == -1)
 		return (-1);
 
 	memset(server, 0, sizeof(struct sockaddr_in));
@@ -407,7 +402,7 @@ server_lookup6(struct sockaddr_in6 *client, struct sockaddr_in6 *proxy,
 	pnl.sport = client->sin6_port;
 	pnl.dport = proxy->sin6_port;
 	
-	if (ioctl(dev, DIOCNATLOOK, &pnl) == -1)
+	if (ioctl(pfctl_fd(pfh), DIOCNATLOOK, &pnl) == -1)
 		return (-1);
 
 	memset(server, 0, sizeof(struct sockaddr_in6));
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index b42afc542273..5b9500980996 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -102,6 +102,12 @@ pfctl_close(struct pfctl_handle *h)
 	free(h);
 }
 
+int
+pfctl_fd(struct pfctl_handle *h)
+{
+	return (h->fd);
+}
+
 static int
 pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl)
 {
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index bdb4bfae4be1..a290fa45501a 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -390,6 +390,7 @@ struct pfctl_syncookies {
 struct pfctl_handle;
 struct pfctl_handle	*pfctl_open(const char *pf_device);
 void	pfctl_close(struct pfctl_handle *);
+int	pfctl_fd(struct pfctl_handle *);
 
 int	pfctl_startstop(struct pfctl_handle *h, int start);
 struct pfctl_status* pfctl_get_status(int dev);