From owner-dev-commits-src-branches@freebsd.org Thu May 27 10:20:24 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A39116383C3; Thu, 27 May 2021 10:20:24 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4FrP2v6kdVz4rkF; Thu, 27 May 2021 10:20:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BA9732258E; Thu, 27 May 2021 10:20:23 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 14RAKNtb055125; Thu, 27 May 2021 10:20:23 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14RAKN7E055124; Thu, 27 May 2021 10:20:23 GMT (envelope-from git) Date: Thu, 27 May 2021 10:20:23 GMT Message-Id: <202105271020.14RAKN7E055124@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: f8b887607cb5 - stable/12 - pf: Add DIOCGETSTATESNV MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: f8b887607cb5c0458aa0cdbafce3f9966f43c9ed Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 May 2021 10:20:24 -0000 The branch stable/12 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=f8b887607cb5c0458aa0cdbafce3f9966f43c9ed commit f8b887607cb5c0458aa0cdbafce3f9966f43c9ed Author: Kristof Provost AuthorDate: 2021-05-05 19:00:16 +0000 Commit: Kristof Provost CommitDate: 2021-05-27 07:05:53 +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 (cherry picked from commit 0592a4c83d67547644763fb023abd5eb28e57f92) --- 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 5acefd631e3d..41aba842e480 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1263,6 +1263,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 431032f6c6e0..53423fb75202 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 *); @@ -2949,6 +2950,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: @@ -3001,6 +3003,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: @@ -3722,6 +3725,11 @@ DIOCGETSTATES_full: break; } + case DIOCGETSTATESNV: { + error = pf_getstates((struct pfioc_nv *)addr); + break; + } + case DIOCGETSTATUS: { struct pf_status *s = (struct pf_status *)addr; @@ -5931,6 +5939,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!!! */