The branch main has been updated by kp:

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

commit e989530a09b6e9f77b89c950ecf32f1b4fa709da
Author:     Kristof Provost <[email protected]>
AuthorDate: 2021-04-29 15:20:36 +0000
Commit:     Kristof Provost <[email protected]>
CommitDate: 2021-05-07 20:13:30 +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
---
 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 5e36c4bad624..6c044fa8b449 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1270,6 +1270,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 77918414df9b..1340d9eec008 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 *);
@@ -2636,7 +2641,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)
 {
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to