aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristof Provost <kp@FreeBSD.org>2021-08-26 15:06:15 +0000
committerKristof Provost <kp@FreeBSD.org>2021-09-06 08:06:33 +0000
commitd1d99d7575dac949030a065c952651514c8bf50f (patch)
treefff1e905c471798b89b9e8211825ef82d25e3b69
parent6f85e21674a15174be96de95275dd36b61a404dc (diff)
downloadsrc-d1d99d7575dac949030a065c952651514c8bf50f.tar.gz
src-d1d99d7575dac949030a065c952651514c8bf50f.zip
libpfctl: Implement DIOCGETSTATUS wrappers
MFC after: 1 week Sponsored by: Modirum MDPay Differential Revision: https://reviews.freebsd.org/D31696 (cherry picked from commit 46fb68b1de49c8d235024374b71c1249af9e62ef)
-rw-r--r--lib/libpfctl/libpfctl.c115
-rw-r--r--lib/libpfctl/libpfctl.h30
2 files changed, 145 insertions, 0 deletions
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
index 7e6bc1b14a2a..3d52502f9ba8 100644
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -122,6 +122,121 @@ pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems,
}
static void
+_pfctl_get_status_counters(const nvlist_t *nvl,
+ struct pfctl_status_counters *counters)
+{
+ const uint64_t *ids, *counts;
+ const char *const *names;
+ size_t id_len, counter_len, names_len;
+
+ ids = nvlist_get_number_array(nvl, "ids", &id_len);
+ counts = nvlist_get_number_array(nvl, "counters", &counter_len);
+ names = nvlist_get_string_array(nvl, "names", &names_len);
+ assert(id_len == counter_len);
+ assert(counter_len == names_len);
+
+ TAILQ_INIT(counters);
+
+ for (size_t i = 0; i < id_len; i++) {
+ struct pfctl_status_counter *c;
+
+ c = malloc(sizeof(*c));
+
+ c->id = ids[i];
+ c->counter = counts[i];
+ c->name = strdup(names[i]);
+
+ TAILQ_INSERT_TAIL(counters, c, entry);
+ }
+}
+
+struct pfctl_status *
+pfctl_get_status(int dev)
+{
+ struct pfioc_nv nv;
+ struct pfctl_status *status;
+ nvlist_t *nvl;
+ size_t len;
+ const void *chksum;
+
+ status = calloc(1, sizeof(*status));
+ if (status == NULL)
+ return (NULL);
+
+ nv.data = malloc(4096);
+ nv.len = nv.size = 4096;
+
+ if (ioctl(dev, DIOCGETSTATUSNV, &nv)) {
+ free(nv.data);
+ free(status);
+ return (NULL);
+ }
+
+ nvl = nvlist_unpack(nv.data, nv.len, 0);
+ free(nv.data);
+ if (nvl == NULL) {
+ free(status);
+ return (NULL);
+ }
+
+ status->running = nvlist_get_bool(nvl, "running");
+ status->since = nvlist_get_number(nvl, "since");
+ status->debug = nvlist_get_number(nvl, "debug");
+ status->hostid = nvlist_get_number(nvl, "hostid");
+ status->states = nvlist_get_number(nvl, "states");
+ status->src_nodes = nvlist_get_number(nvl, "src_nodes");
+
+ strlcpy(status->ifname, nvlist_get_string(nvl, "ifname"),
+ IFNAMSIZ);
+ chksum = nvlist_get_binary(nvl, "chksum", &len);
+ assert(len == PF_MD5_DIGEST_LENGTH);
+ memcpy(status->pf_chksum, chksum, len);
+
+ _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "counters"),
+ &status->counters);
+ _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "lcounters"),
+ &status->lcounters);
+ _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "fcounters"),
+ &status->fcounters);
+ _pfctl_get_status_counters(nvlist_get_nvlist(nvl, "scounters"),
+ &status->scounters);
+
+ pf_nvuint_64_array(nvl, "pcounters", 2 * 2 * 3,
+ (uint64_t *)status->pcounters, NULL);
+ pf_nvuint_64_array(nvl, "bcounters", 2 * 2,
+ (uint64_t *)status->bcounters, NULL);
+
+ nvlist_destroy(nvl);
+
+ return (status);
+}
+
+void
+pfctl_free_status(struct pfctl_status *status)
+{
+ struct pfctl_status_counter *c, *tmp;
+
+ TAILQ_FOREACH_SAFE(c, &status->counters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
+ TAILQ_FOREACH_SAFE(c, &status->lcounters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
+ TAILQ_FOREACH_SAFE(c, &status->fcounters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
+ TAILQ_FOREACH_SAFE(c, &status->scounters, entry, tmp) {
+ free(c->name);
+ free(c);
+ }
+
+ free(status);
+}
+
+static void
pfctl_nv_add_addr(nvlist_t *nvparent, const char *name,
const struct pf_addr *addr)
{
diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
index d57241dd59fd..70de7627f0a6 100644
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -38,6 +38,33 @@
struct pfctl_anchor;
+struct pfctl_status_counter {
+ uint64_t id;
+ uint64_t counter;
+ char *name;
+
+ TAILQ_ENTRY(pfctl_status_counter) entry;
+};
+TAILQ_HEAD(pfctl_status_counters, pfctl_status_counter);
+
+struct pfctl_status {
+ bool running;
+ uint32_t since;
+ uint32_t debug;
+ uint32_t hostid;
+ uint64_t states;
+ uint64_t src_nodes;
+ char ifname[IFNAMSIZ];
+ uint8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
+
+ struct pfctl_status_counters counters;
+ struct pfctl_status_counters lcounters;
+ struct pfctl_status_counters fcounters;
+ struct pfctl_status_counters scounters;
+ uint64_t pcounters[2][2][3];
+ uint64_t bcounters[2][2];
+};
+
struct pfctl_pool {
struct pf_palist list;
struct pf_pooladdr *cur;
@@ -253,6 +280,9 @@ struct pfctl_syncookies {
enum pfctl_syncookies_mode mode;
};
+struct pfctl_status* pfctl_get_status(int dev);
+void pfctl_free_status(struct pfctl_status *status);
+
int pfctl_get_rule(int dev, u_int32_t nr, u_int32_t ticket,
const char *anchor, u_int32_t ruleset, struct pfctl_rule *rule,
char *anchor_call);