Date: Thu, 27 May 2021 10:20:22 GMT From: Kristof Provost <kp@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: bc6cf5a56207 - stable/12 - pf: Add DIOCGETSTATENV Message-ID: <202105271020.14RAKM1P055103@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=bc6cf5a56207a4ea929846d97a374a2ebf1703e5 commit bc6cf5a56207a4ea929846d97a374a2ebf1703e5 Author: Kristof Provost <kp@FreeBSD.org> AuthorDate: 2021-05-05 12:33:55 +0000 Commit: Kristof Provost <kp@FreeBSD.org> CommitDate: 2021-05-27 07:05:35 +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 (cherry picked from commit 1732afaa0dae9d844e341f2c1d6ed4b79c403bfb) --- 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 fda0cc57681d..5acefd631e3d 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1256,6 +1256,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 d676bc7ec9c1..431032f6c6e0 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 *); @@ -2609,6 +2610,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, @@ -2790,6 +2942,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: @@ -2845,6 +2998,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: @@ -3516,6 +3670,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; @@ -5699,12 +5858,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!!! */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202105271020.14RAKM1P055103>