git: 66cacc141d37 - main - libpfctl: introduce pfctl_handle
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 04 Jan 2024 22:11:11 UTC
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=66cacc141d372fdfa624a380bac6880ecf809994
commit 66cacc141d372fdfa624a380bac6880ecf809994
Author: Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2024-01-04 09:50:14 +0000
Commit: Kristof Provost <kp@FreeBSD.org>
CommitDate: 2024-01-04 22:10:24 +0000
libpfctl: introduce pfctl_handle
Consumers of libpfctl can (and in future, should) open a handle. This
handle is an opaque object which contains the /dev/pf file descriptor
and a netlink handle. This means that libpfctl users can open the handle
as root, then drop privileges and still access pf.
Already add the handle to pfctl_startstop() and pfctl_get_creatorids()
as these are new in main, and not present on stable branches. Other
calls will have handle-enabled alternatives implemented in subsequent
commits.
Sponsored by: Rubicon Communications, LLC ("Netgate")
---
lib/libpfctl/libpfctl.c | 58 ++++++++++++++++++++++++++++++++++++++-----------
lib/libpfctl/libpfctl.h | 10 +++++++--
sbin/pfctl/pfctl.c | 12 ++++++----
3 files changed, 61 insertions(+), 19 deletions(-)
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index f915072c4ea1..94949a5a7337 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -50,11 +50,17 @@
#include <assert.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include "libpfctl.h"
+struct pfctl_handle {
+ int fd;
+ struct snl_state ss;
+};
+
const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = {
"never",
"always",
@@ -64,6 +70,38 @@ const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = {
static int _pfctl_clear_states(int , const struct pfctl_kill *,
unsigned int *, uint64_t);
+struct pfctl_handle *
+pfctl_open(const char *pf_device)
+{
+ struct pfctl_handle *h;
+
+ h = calloc(1, sizeof(struct pfctl_handle));
+ h->fd = -1;
+
+ h->fd = open(pf_device, O_RDWR);
+ if (h->fd < 0)
+ goto error;
+
+ if (!snl_init(&h->ss, NETLINK_GENERIC))
+ goto error;
+
+ return (h);
+error:
+ close(h->fd);
+ snl_free(&h->ss);
+ free(h);
+
+ return (NULL);
+}
+
+void
+pfctl_close(struct pfctl_handle *h)
+{
+ close(h->fd);
+ snl_free(&h->ss);
+ free(h);
+}
+
static int
pfctl_do_ioctl(int dev, uint cmd, size_t size, nvlist_t **nvl)
{
@@ -183,21 +221,19 @@ pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems,
}
int
-pfctl_startstop(int start)
+pfctl_startstop(struct pfctl_handle *h, int start)
{
- struct snl_state ss = {};
struct snl_errmsg_data e = {};
struct snl_writer nw;
struct nlmsghdr *hdr;
uint32_t seq_id;
int family_id;
- snl_init(&ss, NETLINK_GENERIC);
- family_id = snl_get_genl_family(&ss, PFNL_FAMILY_NAME);
+ family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME);
if (family_id == 0)
return (ENOTSUP);
- snl_init_writer(&ss, &nw);
+ snl_init_writer(&h->ss, &nw);
hdr = snl_create_genl_msg_request(&nw, family_id,
start ? PFNL_CMD_START : PFNL_CMD_STOP);
@@ -206,9 +242,9 @@ pfctl_startstop(int start)
return (ENOMEM);
seq_id = hdr->nlmsg_seq;
- snl_send_message(&ss, hdr);
+ snl_send_message(&h->ss, hdr);
- while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) {
+ while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) {
}
return (e.error);
@@ -1288,17 +1324,13 @@ pfctl_get_creators_nl(struct snl_state *ss, uint32_t *creators, size_t *len)
}
int
-pfctl_get_creatorids(uint32_t *creators, size_t *len)
+pfctl_get_creatorids(struct pfctl_handle *h, uint32_t *creators, size_t *len)
{
- struct snl_state ss = {};
int error;
- snl_init(&ss, NETLINK_GENERIC);
- error = pfctl_get_creators_nl(&ss, creators, len);
- snl_free(&ss);
+ error = pfctl_get_creators_nl(&h->ss, creators, len);
return (error);
-
}
static void
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index 7f3b1b600db7..f128e5340891 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -385,7 +385,13 @@ struct pfctl_syncookies {
uint32_t halfopen_states;
};
-int pfctl_startstop(int start);
+#define PF_DEVICE "/dev/pf"
+
+struct pfctl_handle;
+struct pfctl_handle *pfctl_open(const char *pf_device);
+void pfctl_close(struct pfctl_handle *);
+
+int pfctl_startstop(struct pfctl_handle *h, int start);
struct pfctl_status* pfctl_get_status(int dev);
uint64_t pfctl_status_counter(struct pfctl_status *status, int id);
uint64_t pfctl_status_lcounter(struct pfctl_status *status, int id);
@@ -416,7 +422,7 @@ int pfctl_add_rule(int dev, const struct pfctl_rule *r,
const char *anchor, const char *anchor_call, uint32_t ticket,
uint32_t pool_ticket);
int pfctl_set_keepcounters(int dev, bool keep);
-int pfctl_get_creatorids(uint32_t *creators, size_t *len);
+int pfctl_get_creatorids(struct pfctl_handle *h, uint32_t *creators, size_t *len);
struct pfctl_state_filter {
char ifname[IFNAMSIZ];
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
index 2702c701f9cc..217bf31b3301 100644
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -132,7 +132,7 @@ static const char *showopt;
static const char *debugopt;
static char *anchoropt;
static const char *optiopt = NULL;
-static const char *pf_device = "/dev/pf";
+static const char *pf_device = PF_DEVICE;
static char *ifaceopt;
static char *tableopt;
static const char *tblcmdopt;
@@ -144,6 +144,7 @@ int loadopt;
int altqsupport;
int dev = -1;
+struct pfctl_handle *pfh = NULL;
static int first_title = 1;
static int labels = 0;
@@ -312,7 +313,7 @@ pfctl_enable(int dev, int opts)
{
int ret;
- if ((ret = pfctl_startstop(1)) != 0) {
+ if ((ret = pfctl_startstop(pfh, 1)) != 0) {
if (ret == EEXIST)
errx(1, "pf already enabled");
else if (ret == ESRCH)
@@ -335,7 +336,7 @@ pfctl_disable(int dev, int opts)
{
int ret;
- if ((ret = pfctl_startstop(0)) != 0) {
+ if ((ret = pfctl_startstop(pfh, 0)) != 0) {
if (ret == ENOENT)
errx(1, "pf not enabled");
else
@@ -1665,7 +1666,7 @@ pfctl_show_creators(int opts)
uint32_t creators[16];
size_t count = nitems(creators);
- ret = pfctl_get_creatorids(creators, &count);
+ ret = pfctl_get_creatorids(pfh, creators, &count);
if (ret != 0)
errx(ret, "Failed to retrieve creators");
@@ -3079,6 +3080,9 @@ main(int argc, char *argv[])
altqsupport = 1;
#endif
}
+ pfh = pfctl_open(pf_device);
+ if (pfh == NULL)
+ err(1, "Failed to open netlink");
if (opts & PF_OPT_DISABLE)
if (pfctl_disable(dev, opts))