Skip site navigation (1)Skip section navigation (2)
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>