git: 1732afaa0dae - main - pf: Add DIOCGETSTATENV
Kristof Provost
kp at FreeBSD.org
Thu May 20 11:54:49 UTC 2021
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=1732afaa0dae9d844e341f2c1d6ed4b79c403bfb
commit 1732afaa0dae9d844e341f2c1d6ed4b79c403bfb
Author: Kristof Provost <kp at FreeBSD.org>
AuthorDate: 2021-05-05 12:33:55 +0000
Commit: Kristof Provost <kp at FreeBSD.org>
CommitDate: 2021-05-20 10:49:26 +0000
pf: Add DIOCGETSTATENV
Add DIOCGETSTATENV, an nvlist-based alternative to DIOCGETSTATE.
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D30242
---
share/man/man4/pf.4 | 4 +-
sys/net/pfvar.h | 1 +
sys/netpfil/pf/pf_ioctl.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 229 insertions(+), 2 deletions(-)
diff --git a/share/man/man4/pf.4 b/share/man/man4/pf.4
index 2fb132203908..24843535c924 100644
--- a/share/man/man4/pf.4
+++ b/share/man/man4/pf.4
@@ -326,14 +326,14 @@ struct pfioc_state {
struct pfsync_state state;
};
.Ed
-.It Dv DIOCGETSTATE Fa "struct pfioc_state *ps"
+.It Dv DIOCGETSTATENV Fa "struct pfioc_nv *nv"
Extract the entry identified by the
.Va id
and
.Va creatorid
fields of the
.Va state
-structure from the state table.
+nvlist from the state table.
.It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk"
Remove matching entries from the state table.
This ioctl returns the number of killed states in
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 51c51a82b36d..1bd1ebd27449 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1257,6 +1257,7 @@ struct pfioc_iface {
#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill)
#define DIOCCLRSTATESNV _IOWR('D', 18, struct pfioc_nv)
#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state)
+#define DIOCGETSTATENV _IOWR('D', 19, struct pfioc_nv)
#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
#define DIOCCLRSTATUS _IO ('D', 22)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 2d13ddf1ac61..1ea7310ebebb 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -208,6 +208,7 @@ static int pf_killstates_row(struct pf_kstate_kill *,
struct pf_idhash *);
static int pf_killstates_nv(struct pfioc_nv *);
static int pf_clearstates_nv(struct pfioc_nv *);
+static int pf_getstate(struct pfioc_nv *);
static int pf_clear_tables(void);
static void pf_clear_srcnodes(struct pf_ksrc_node *);
static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
@@ -2474,6 +2475,157 @@ errout:
return (error);
}
+static nvlist_t *
+pf_state_key_to_nvstate_key(const struct pf_state_key *key)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ for (int i = 0; i < 2; i++) {
+ tmp = pf_addr_to_nvaddr(&key->addr[i]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_append_nvlist_array(nvl, "addr", tmp);
+ nvlist_append_number_array(nvl, "port", key->port[i]);
+ }
+ nvlist_add_number(nvl, "af", key->af);
+ nvlist_add_number(nvl, "proto", key->proto);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+static nvlist_t *
+pf_state_scrub_to_nvstate_scrub(const struct pf_state_scrub *scrub)
+{
+ nvlist_t *nvl;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_bool(nvl, "timestamp", scrub->pfss_flags & PFSS_TIMESTAMP);
+ nvlist_add_number(nvl, "ttl", scrub->pfss_ttl);
+ nvlist_add_number(nvl, "ts_mod", scrub->pfss_ts_mod);
+
+ return (nvl);
+}
+
+static nvlist_t *
+pf_state_peer_to_nvstate_peer(const struct pf_state_peer *peer)
+{
+ nvlist_t *nvl, *tmp;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ if (peer->scrub) {
+ tmp = pf_state_scrub_to_nvstate_scrub(peer->scrub);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "scrub", tmp);
+ }
+
+ nvlist_add_number(nvl, "seqlo", peer->seqlo);
+ nvlist_add_number(nvl, "seqhi", peer->seqhi);
+ nvlist_add_number(nvl, "seqdiff", peer->seqdiff);
+ nvlist_add_number(nvl, "max_win", peer->max_win);
+ nvlist_add_number(nvl, "mss", peer->mss);
+ nvlist_add_number(nvl, "state", peer->state);
+ nvlist_add_number(nvl, "wscale", peer->wscale);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
+
+static nvlist_t *
+pf_state_to_nvstate(const struct pf_state *s)
+{
+ nvlist_t *nvl, *tmp;
+ uint32_t expire, flags = 0;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (NULL);
+
+ nvlist_add_number(nvl, "id", s->id);
+ nvlist_add_string(nvl, "ifname", s->kif->pfik_name);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_STACK]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "stack_key", tmp);
+
+ tmp = pf_state_key_to_nvstate_key(s->key[PF_SK_WIRE]);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "wire_key", tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->src);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "src", tmp);
+
+ tmp = pf_state_peer_to_nvstate_peer(&s->dst);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "dst", tmp);
+
+ tmp = pf_addr_to_nvaddr(&s->rt_addr);
+ if (tmp == NULL)
+ goto errout;
+ nvlist_add_nvlist(nvl, "rt_addr", tmp);
+
+ nvlist_add_number(nvl, "rule", s->rule.ptr ? s->rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "anchor",
+ s->anchor.ptr ? s->anchor.ptr->nr : -1);
+ nvlist_add_number(nvl, "nat_rule",
+ s->nat_rule.ptr ? s->nat_rule.ptr->nr : -1);
+ nvlist_add_number(nvl, "creation", s->creation);
+
+ expire = pf_state_expires(s);
+ if (expire <= time_uptime)
+ expire = 0;
+ else
+ expire = expire - time_uptime;
+ nvlist_add_number(nvl, "expire", expire);
+
+ for (int i = 0; i < 2; i++) {
+ nvlist_append_number_array(nvl, "packets",
+ counter_u64_fetch(s->packets[i]));
+ nvlist_append_number_array(nvl, "bytes",
+ counter_u64_fetch(s->bytes[i]));
+ }
+
+ nvlist_add_number(nvl, "creatorid", s->creatorid);
+ nvlist_add_number(nvl, "direction", s->direction);
+ nvlist_add_number(nvl, "log", s->log);
+ nvlist_add_number(nvl, "state_flags", s->state_flags);
+ nvlist_add_number(nvl, "timeout", s->timeout);
+ if (s->src_node)
+ flags |= PFSYNC_FLAG_SRCNODE;
+ if (s->nat_src_node)
+ flags |= PFSYNC_FLAG_NATSRCNODE;
+ nvlist_add_number(nvl, "sync_flags", flags);
+
+ return (nvl);
+
+errout:
+ nvlist_destroy(nvl);
+ return (NULL);
+}
+
static int
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
@@ -2789,6 +2941,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETADDRS:
case DIOCGETADDR:
case DIOCGETSTATE:
+ case DIOCGETSTATENV:
case DIOCSETSTATUSIF:
case DIOCGETSTATUS:
case DIOCCLRSTATUS:
@@ -2844,6 +2997,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETADDRS:
case DIOCGETADDR:
case DIOCGETSTATE:
+ case DIOCGETSTATENV:
case DIOCGETSTATUS:
case DIOCGETSTATES:
case DIOCGETTIMEOUT:
@@ -3504,6 +3658,11 @@ DIOCCHANGERULE_error:
break;
}
+ case DIOCGETSTATENV: {
+ error = pf_getstate((struct pfioc_nv *)addr);
+ break;
+ }
+
case DIOCGETSTATES: {
struct pfioc_states *ps = (struct pfioc_states *)addr;
struct pf_state *s;
@@ -5684,12 +5843,79 @@ pf_clearstates_nv(struct pfioc_nv *nv)
error = copyout(nvlpacked, nv->data, nv->len);
+#undef ERROUT
on_error:
nvlist_destroy(nvl);
free(nvlpacked, M_TEMP);
return (error);
}
+static int
+pf_getstate(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL, *nvls;
+ void *nvlpacked = NULL;
+ struct pf_state *s = NULL;
+ int error = 0;
+ uint64_t id, creatorid;
+
+#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+
+ if (nv->len > pf_ioctl_maxcount)
+ ERROUT(ENOMEM);
+
+ nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ error = copyin(nv->data, nvlpacked, nv->len);
+ if (error)
+ ERROUT(error);
+
+ nvl = nvlist_unpack(nvlpacked, nv->len, 0);
+ if (nvl == NULL)
+ ERROUT(EBADMSG);
+
+ PFNV_CHK(pf_nvuint64(nvl, "id", &id));
+ PFNV_CHK(pf_nvuint64(nvl, "creatorid", &creatorid));
+
+ s = pf_find_state_byid(id, creatorid);
+ if (s == NULL)
+ ERROUT(ENOENT);
+
+ free(nvlpacked, M_TEMP);
+ nvlpacked = NULL;
+ nvlist_destroy(nvl);
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ ERROUT(ENOMEM);
+
+ nvls = pf_state_to_nvstate(s);
+ if (nvls == NULL)
+ ERROUT(ENOMEM);
+
+ nvlist_add_nvlist(nvl, "state", nvls);
+
+ nvlpacked = nvlist_pack(nvl, &nv->len);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ if (nv->size == 0)
+ ERROUT(0);
+ else if (nv->size < nv->len)
+ ERROUT(ENOSPC);
+
+ error = copyout(nvlpacked, nv->data, nv->len);
+
+#undef ERROUT
+errout:
+ if (s != NULL)
+ PF_STATE_UNLOCK(s);
+ free(nvlpacked, M_TEMP);
+ nvlist_destroy(nvl);
+ return (error);
+}
+
/*
* XXX - Check for version missmatch!!!
*/
More information about the dev-commits-src-main
mailing list