git: 0592a4c83d67 - main - pf: Add DIOCGETSTATESNV
Kristof Provost
kp at FreeBSD.org
Thu May 20 11:54:50 UTC 2021
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=0592a4c83d67547644763fb023abd5eb28e57f92
commit 0592a4c83d67547644763fb023abd5eb28e57f92
Author: Kristof Provost <kp at FreeBSD.org>
AuthorDate: 2021-05-05 19:00:16 +0000
Commit: Kristof Provost <kp at FreeBSD.org>
CommitDate: 2021-05-20 10:49:27 +0000
pf: Add DIOCGETSTATESNV
Add DIOCGETSTATESNV, an nvlist-based alternative to DIOCGETSTATES.
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D30243
---
share/man/man4/pf.4 | 71 ++++++++++++++++++++++++++++++++-----------
sys/net/pfvar.h | 1 +
sys/netpfil/pf/pf_ioctl.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 130 insertions(+), 18 deletions(-)
diff --git a/share/man/man4/pf.4 b/share/man/man4/pf.4
index 24843535c924..133e4d300043 100644
--- a/share/man/man4/pf.4
+++ b/share/man/man4/pf.4
@@ -415,30 +415,65 @@ Set the debug level.
enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC,
PF_DEBUG_NOISY };
.Ed
-.It Dv DIOCGETSTATES Fa "struct pfioc_states *ps"
+.It Dv DIOCGETSTATESNV Fa "struct pfioc_nv *nv"
Get state table entries.
.Bd -literal
-struct pfioc_states {
- int ps_len;
- union {
- caddr_t psu_buf;
- struct pf_state *psu_states;
- } ps_u;
-#define ps_buf ps_u.psu_buf
-#define ps_states ps_u.psu_states
+nvlist pf_state_key {
+ nvlist pf_addr addr[2];
+ number port[2];
+ number af;
+ number proto;
+};
+
+nvlist pf_state_scrub {
+ bool timestamp;
+ number ttl;
+ number ts_mod;
+};
+
+nvlist pf_state_peer {
+ nvlist pf_state_scrub scrub;
+ number seqlo;
+ number seqhi;
+ number seqdiff;
+ number max_win;
+ number mss;
+ number state;
+ number wscale;
+};
+
+nvlist pf_state {
+ number id;
+ string ifname;
+ nvlist pf_state_key stack_key;
+ nvlist pf_state_key wire_key;
+ nvlist pf_state_peer src;
+ nvlist pf_state_peer dst;
+ nvlist pf_addr rt_addr;
+ number rule;
+ number anchor;
+ number nat_rule;
+ number expire;
+ number packets[2];
+ number bytes[2];
+ number creatorid;
+ number direction;
+ number log;
+ number state_flags;
+ number timeout;
+ number sync_flags;
+};
+
+nvlist pf_states {
+ number count;
+ nvlist pf_state states[];
};
.Ed
.Pp
If
-.Va ps_len
-is non-zero on entry, as many states as possible that can fit into this
-size will be copied into the supplied buffer
-.Va ps_states .
-On exit,
-.Va ps_len
-is always set to the total size required to hold all state table entries
-(i.e., it is set to
-.Li sizeof(struct pf_state) * nr ) .
+.Va pfioc_nv.size
+is insufficiently large, as many states as possible that can fit into this
+size will be copied into the supplied buffer.
.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
Add or remove the
.Va rule
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 1bd1ebd27449..d9e35dae753a 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1264,6 +1264,7 @@ struct pfioc_iface {
#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t)
#define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states)
+#define DIOCGETSTATESNV _IOWR('D', 25, struct pfioc_nv)
#define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule)
/* XXX cut 26 - 28 */
#define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 1ea7310ebebb..8424e0ce5689 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -209,6 +209,7 @@ static int pf_killstates_row(struct pf_kstate_kill *,
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_getstates(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 *);
@@ -2948,6 +2949,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCNATLOOK:
case DIOCSETDEBUG:
case DIOCGETSTATES:
+ case DIOCGETSTATESNV:
case DIOCGETTIMEOUT:
case DIOCCLRRULECTRS:
case DIOCGETLIMIT:
@@ -3000,6 +3002,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCGETSTATENV:
case DIOCGETSTATUS:
case DIOCGETSTATES:
+ case DIOCGETSTATESNV:
case DIOCGETTIMEOUT:
case DIOCGETLIMIT:
case DIOCGETALTQSV0:
@@ -3709,6 +3712,11 @@ DIOCGETSTATES_full:
break;
}
+ case DIOCGETSTATESNV: {
+ error = pf_getstates((struct pfioc_nv *)addr);
+ break;
+ }
+
case DIOCGETSTATUS: {
struct pf_status *s = (struct pf_status *)addr;
@@ -5916,6 +5924,74 @@ errout:
return (error);
}
+static int
+pf_getstates(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL, *nvls;
+ void *nvlpacked = NULL;
+ struct pf_state *s = NULL;
+ int error = 0;
+ uint64_t count = 0;
+
+#define ERROUT(x) ERROUT_FUNCTION(errout, x)
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ ERROUT(ENOMEM);
+
+ nvlist_add_number(nvl, "count", uma_zone_get_cur(V_pf_state_z));
+
+ for (int i = 0; i < pf_hashmask; i++) {
+ struct pf_idhash *ih = &V_pf_idhash[i];
+
+ PF_HASHROW_LOCK(ih);
+ LIST_FOREACH(s, &ih->states, entry) {
+ if (s->timeout == PFTM_UNLINKED)
+ continue;
+
+ nvls = pf_state_to_nvstate(s);
+ if (nvls == NULL) {
+ PF_HASHROW_UNLOCK(ih);
+ ERROUT(ENOMEM);
+ }
+ if ((nvlist_size(nvl) + nvlist_size(nvls)) > nv->size) {
+ /* We've run out of room for more states. */
+ nvlist_destroy(nvls);
+ PF_HASHROW_UNLOCK(ih);
+ goto DIOCGETSTATESNV_full;
+ }
+ nvlist_append_nvlist_array(nvl, "states", nvls);
+ count++;
+ }
+ PF_HASHROW_UNLOCK(ih);
+ }
+
+ /* We've managed to put them all the available space. Let's make sure
+ * 'count' matches our array (that's racy, because we don't hold a lock
+ * over all states, only over each row individually. */
+ (void)nvlist_take_number(nvl, "count");
+ nvlist_add_number(nvl, "count", count);
+
+DIOCGETSTATESNV_full:
+
+ 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:
+ free(nvlpacked, M_TEMP);
+ nvlist_destroy(nvl);
+ return (error);
+}
+
/*
* XXX - Check for version missmatch!!!
*/
More information about the dev-commits-src-main
mailing list