git: e25df666069d - stable/13 - pf: Introduce DIOCKILLSTATESNV

Kristof Provost kp at FreeBSD.org
Fri May 14 13:06:45 UTC 2021


The branch stable/13 has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=e25df666069d89d7224640d526fe42cb2a3c224e

commit e25df666069d89d7224640d526fe42cb2a3c224e
Author:     Kristof Provost <kp at FreeBSD.org>
AuthorDate: 2021-04-29 15:20:36 +0000
Commit:     Kristof Provost <kp at FreeBSD.org>
CommitDate: 2021-05-14 08:17:17 +0000

    pf: Introduce DIOCKILLSTATESNV
    
    Introduce an nvlist based alternative to DIOCKILLSTATES.
    
    MFC after:      1 week
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D30054
    
    (cherry picked from commit e989530a09b6e9f77b89c950ecf32f1b4fa709da)
---
 sys/net/pfvar.h           |   1 +
 sys/netpfil/pf/pf_ioctl.c | 110 +++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 96 insertions(+), 15 deletions(-)

diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index dd2f189b948a..7b18ef7d3b0c 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1268,6 +1268,7 @@ struct pfioc_iface {
 #define DIOCGETLIMIT	_IOWR('D', 39, struct pfioc_limit)
 #define DIOCSETLIMIT	_IOWR('D', 40, struct pfioc_limit)
 #define DIOCKILLSTATES	_IOWR('D', 41, struct pfioc_state_kill)
+#define DIOCKILLSTATESNV	_IOWR('D', 41, struct pfioc_nv)
 #define DIOCSTARTALTQ	_IO  ('D', 42)
 #define DIOCSTOPALTQ	_IO  ('D', 43)
 #define DIOCADDALTQV0	_IOWR('D', 45, struct pfioc_altq_v0)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 79da65e0ec98..897a5ff512a6 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -202,6 +202,11 @@ struct cdev *pf_dev;
  */
 static void		 pf_clear_all_states(void);
 static unsigned int	 pf_clear_states(const struct pf_kstate_kill *);
+static int		 pf_killstates(struct pf_kstate_kill *,
+			    unsigned int *);
+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_clear_tables(void);
 static void		 pf_clear_srcnodes(struct pf_ksrc_node *);
@@ -2412,7 +2417,7 @@ pf_label_match(const struct pf_krule *rule, const char *label)
 }
 
 static int
-pf_killstates_row(struct pfioc_state_kill *psk, struct pf_idhash *ih)
+pf_killstates_row(struct pf_kstate_kill *psk, struct pf_idhash *ih)
 {
 	struct pf_state		*s;
 	struct pf_state_key	*sk;
@@ -3390,25 +3395,20 @@ DIOCCHANGERULE_error:
 	}
 
 	case DIOCKILLSTATES: {
-		struct pf_state		*s;
 		struct pfioc_state_kill	*psk = (struct pfioc_state_kill *)addr;
-		u_int			 i, killed = 0;
+		struct pf_kstate_kill	 kill;
 
-		if (psk->psk_pfcmp.id) {
-			if (psk->psk_pfcmp.creatorid == 0)
-				psk->psk_pfcmp.creatorid = V_pf_status.hostid;
-			if ((s = pf_find_state_byid(psk->psk_pfcmp.id,
-			    psk->psk_pfcmp.creatorid))) {
-				pf_unlink_state(s, PF_ENTER_LOCKED);
-				psk->psk_killed = 1;
-			}
+		error = pf_state_kill_to_kstate_kill(psk, &kill);
+		if (error)
 			break;
-		}
 
-		for (i = 0; i <= pf_hashmask; i++)
-			killed += pf_killstates_row(psk, &V_pf_idhash[i]);
+		psk->psk_killed = 0;
+		error = pf_killstates(&kill, &psk->psk_killed);
+		break;
+	}
 
-		psk->psk_killed = killed;
+	case DIOCKILLSTATESNV: {
+		error = pf_killstates_nv((struct pfioc_nv *)addr);
 		break;
 	}
 
@@ -5462,6 +5462,86 @@ relock_DIOCCLRSTATES:
 	return (killed);
 }
 
+static int
+pf_killstates(struct pf_kstate_kill *kill, unsigned int *killed)
+{
+	struct pf_state		*s;
+
+	if (kill->psk_pfcmp.id) {
+		if (kill->psk_pfcmp.creatorid == 0)
+			kill->psk_pfcmp.creatorid = V_pf_status.hostid;
+		if ((s = pf_find_state_byid(kill->psk_pfcmp.id,
+		    kill->psk_pfcmp.creatorid))) {
+			pf_unlink_state(s, PF_ENTER_LOCKED);
+			*killed = 1;
+		}
+		return (0);
+	}
+
+	for (unsigned int i = 0; i <= pf_hashmask; i++)
+		*killed += pf_killstates_row(kill, &V_pf_idhash[i]);
+
+	return (0);
+}
+
+static int
+pf_killstates_nv(struct pfioc_nv *nv)
+{
+	struct pf_kstate_kill	 kill;
+	nvlist_t		*nvl = NULL;
+	void			*nvlpacked = NULL;
+	int			 error = 0;
+	unsigned int		 killed = 0;
+
+#define ERROUT(x)	ERROUT_FUNCTION(on_error, 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);
+
+	error = pf_nvstate_kill_to_kstate_kill(nvl, &kill);
+	if (error)
+		ERROUT(error);
+
+	error = pf_killstates(&kill, &killed);
+
+	free(nvlpacked, M_TEMP);
+	nvlpacked = NULL;
+	nvlist_destroy(nvl);
+	nvl = nvlist_create(0);
+	if (nvl == NULL)
+		ERROUT(ENOMEM);
+
+	nvlist_add_number(nvl, "killed", killed);
+
+	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);
+
+on_error:
+	nvlist_destroy(nvl);
+	free(nvlpacked, M_TEMP);
+	return (error);
+}
+
 static int
 pf_clearstates_nv(struct pfioc_nv *nv)
 {


More information about the dev-commits-src-all mailing list