git: 7606a45dcc87 - main - pf: Introduce DIOCCLRSTATESNV
Kristof Provost
kp at FreeBSD.org
Fri May 7 20:13:55 UTC 2021
The branch main has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=7606a45dcc87cb6b222af929dad37b615cb925cf
commit 7606a45dcc87cb6b222af929dad37b615cb925cf
Author: Kristof Provost <kp at FreeBSD.org>
AuthorDate: 2021-04-29 09:07:02 +0000
Commit: Kristof Provost <kp at FreeBSD.org>
CommitDate: 2021-05-07 20:13:30 +0000
pf: Introduce DIOCCLRSTATESNV
Introduce an nvlist variant of DIOCCLRSTATES.
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D30052
---
sys/net/pfvar.h | 14 ++++
sys/netpfil/pf/pf_ioctl.c | 199 +++++++++++++++++++++++++++++++++++++++-------
sys/netpfil/pf/pf_nv.c | 1 +
sys/netpfil/pf/pf_nv.h | 5 ++
4 files changed, 192 insertions(+), 27 deletions(-)
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 5261bfe3bfb1..5e36c4bad624 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1074,6 +1074,19 @@ struct pfioc_src_node_kill {
u_int psnk_killed;
};
+#ifdef _KERNEL
+struct pf_kstate_kill {
+ struct pf_state_cmp psk_pfcmp;
+ sa_family_t psk_af;
+ int psk_proto;
+ struct pf_rule_addr psk_src;
+ struct pf_rule_addr psk_dst;
+ char psk_ifname[IFNAMSIZ];
+ char psk_label[PF_RULE_LABEL_SIZE];
+ u_int psk_killed;
+};
+#endif
+
struct pfioc_state_kill {
struct pf_state_cmp psk_pfcmp;
sa_family_t psk_af;
@@ -1240,6 +1253,7 @@ struct pfioc_iface {
#define DIOCGETRULENV _IOWR('D', 7, struct pfioc_nv)
/* XXX cut 8 - 17 */
#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 DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 4e4f726a5614..77918414df9b 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -200,7 +200,9 @@ struct cdev *pf_dev;
/*
* XXX - These are new and need to be checked when moveing to a new version
*/
-static void pf_clear_states(void);
+static void pf_clear_all_states(void);
+static unsigned int pf_clear_states(const struct pf_kstate_kill *);
+static int pf_clearstates_nv(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 *);
@@ -2395,6 +2397,72 @@ pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule)
return (0);
}
+static int
+pf_state_kill_to_kstate_kill(const struct pfioc_state_kill *psk,
+ struct pf_kstate_kill *kill)
+{
+ bzero(kill, sizeof(*kill));
+
+ bcopy(&psk->psk_pfcmp, &kill->psk_pfcmp, sizeof(kill->psk_pfcmp));
+ kill->psk_af = psk->psk_af;
+ kill->psk_proto = psk->psk_proto;
+ bcopy(&psk->psk_src, &kill->psk_src, sizeof(kill->psk_src));
+ bcopy(&psk->psk_dst, &kill->psk_dst, sizeof(kill->psk_dst));
+ strlcpy(kill->psk_ifname, psk->psk_ifname, sizeof(kill->psk_ifname));
+ strlcpy(kill->psk_label, psk->psk_label, sizeof(kill->psk_label));
+
+ return (0);
+}
+
+static int
+pf_nvstate_cmp_to_state_cmp(const nvlist_t *nvl, struct pf_state_cmp *cmp)
+{
+ int error = 0;
+
+ bzero(cmp, sizeof(*cmp));
+
+ PFNV_CHK(pf_nvuint64(nvl, "id", &cmp->id));
+ PFNV_CHK(pf_nvuint32(nvl, "creatorid", &cmp->creatorid));
+ PFNV_CHK(pf_nvuint8(nvl, "direction", &cmp->direction));
+
+errout:
+ return (error);
+}
+
+static int
+pf_nvstate_kill_to_kstate_kill(const nvlist_t *nvl,
+ struct pf_kstate_kill *kill)
+{
+ int error = 0;
+
+ bzero(kill, sizeof(*kill));
+
+ if (! nvlist_exists_nvlist(nvl, "cmp"))
+ return (EINVAL);
+
+ PFNV_CHK(pf_nvstate_cmp_to_state_cmp(nvlist_get_nvlist(nvl, "cmp"),
+ &kill->psk_pfcmp));
+ PFNV_CHK(pf_nvuint8(nvl, "af", &kill->psk_af));
+ PFNV_CHK(pf_nvint(nvl, "proto", &kill->psk_proto));
+
+ if (! nvlist_exists_nvlist(nvl, "src"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "src"),
+ &kill->psk_src));
+ if (! nvlist_exists_nvlist(nvl, "dst"))
+ return (EINVAL);
+ PFNV_CHK(pf_nvrule_addr_to_rule_addr(nvlist_get_nvlist(nvl, "dst"),
+ &kill->psk_dst));
+
+ PFNV_CHK(pf_nvstring(nvl, "ifname", kill->psk_ifname,
+ sizeof(kill->psk_ifname)));
+ PFNV_CHK(pf_nvstring(nvl, "label", kill->psk_label,
+ sizeof(kill->psk_label)));
+
+errout:
+ return (error);
+}
+
static int
pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket,
uint32_t pool_ticket, const char *anchor, const char *anchor_call,
@@ -3305,33 +3373,19 @@ DIOCCHANGERULE_error:
}
case DIOCCLRSTATES: {
- struct pf_state *s;
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
- u_int i, killed = 0;
+ struct pf_kstate_kill kill;
- for (i = 0; i <= pf_hashmask; i++) {
- struct pf_idhash *ih = &V_pf_idhash[i];
+ error = pf_state_kill_to_kstate_kill(psk, &kill);
+ if (error)
+ break;
-relock_DIOCCLRSTATES:
- PF_HASHROW_LOCK(ih);
- LIST_FOREACH(s, &ih->states, entry)
- if (!psk->psk_ifname[0] ||
- !strcmp(psk->psk_ifname,
- s->kif->pfik_name)) {
- /*
- * Don't send out individual
- * delete messages.
- */
- s->state_flags |= PFSTATE_NOSYNC;
- pf_unlink_state(s, PF_ENTER_LOCKED);
- killed++;
- goto relock_DIOCCLRSTATES;
- }
- PF_HASHROW_UNLOCK(ih);
- }
- psk->psk_killed = killed;
- if (V_pfsync_clear_states_ptr != NULL)
- V_pfsync_clear_states_ptr(V_pf_status.hostid, psk->psk_ifname);
+ psk->psk_killed = pf_clear_states(&kill);
+ break;
+ }
+
+ case DIOCCLRSTATESNV: {
+ error = pf_clearstates_nv((struct pfioc_nv *)addr);
break;
}
@@ -5224,7 +5278,7 @@ pf_tbladdr_copyout(struct pf_addr_wrap *aw)
* XXX - Check for version missmatch!!!
*/
static void
-pf_clear_states(void)
+pf_clear_all_states(void)
{
struct pf_state *s;
u_int i;
@@ -5375,6 +5429,97 @@ on_error:
return (error);
}
+static unsigned int
+pf_clear_states(const struct pf_kstate_kill *kill)
+{
+ struct pf_state *s;
+ unsigned int killed = 0;
+
+ for (unsigned int i = 0; i <= pf_hashmask; i++) {
+ struct pf_idhash *ih = &V_pf_idhash[i];
+
+relock_DIOCCLRSTATES:
+ PF_HASHROW_LOCK(ih);
+ LIST_FOREACH(s, &ih->states, entry)
+ if (!kill->psk_ifname[0] ||
+ !strcmp(kill->psk_ifname,
+ s->kif->pfik_name)) {
+ /*
+ * Don't send out individual
+ * delete messages.
+ */
+ s->state_flags |= PFSTATE_NOSYNC;
+ pf_unlink_state(s, PF_ENTER_LOCKED);
+ killed++;
+ goto relock_DIOCCLRSTATES;
+ }
+ PF_HASHROW_UNLOCK(ih);
+ }
+
+ if (V_pfsync_clear_states_ptr != NULL)
+ V_pfsync_clear_states_ptr(V_pf_status.hostid, kill->psk_ifname);
+
+ return (killed);
+}
+
+static int
+pf_clearstates_nv(struct pfioc_nv *nv)
+{
+ struct pf_kstate_kill kill;
+ nvlist_t *nvl = NULL;
+ void *nvlpacked = NULL;
+ int error = 0;
+ unsigned int killed;
+
+#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);
+
+ killed = pf_clear_states(&kill);
+
+ 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);
+}
+
/*
* XXX - Check for version missmatch!!!
*/
@@ -5434,7 +5579,7 @@ shutdown_pf(void)
pf_commit_altq(t[0]);
#endif
- pf_clear_states();
+ pf_clear_all_states();
pf_clear_srcnodes(NULL);
diff --git a/sys/netpfil/pf/pf_nv.c b/sys/netpfil/pf/pf_nv.c
index 8a2082d3e0bb..1fdb52e5fad0 100644
--- a/sys/netpfil/pf/pf_nv.c
+++ b/sys/netpfil/pf/pf_nv.c
@@ -104,6 +104,7 @@ pf_nvbinary(const nvlist_t *nvl, const char *name, void *data,
PF_NV_IMPL_UINT(uint8, uint8_t, UINT8_MAX);
PF_NV_IMPL_UINT(uint16, uint16_t, UINT16_MAX);
PF_NV_IMPL_UINT(uint32, uint32_t, UINT32_MAX);
+PF_NV_IMPL_UINT(uint64, uint64_t, UINT64_MAX);
int
pf_nvint(const nvlist_t *nvl, const char *name, int *val)
diff --git a/sys/netpfil/pf/pf_nv.h b/sys/netpfil/pf/pf_nv.h
index d50f46a1f5cd..589a1972fa43 100644
--- a/sys/netpfil/pf/pf_nv.h
+++ b/sys/netpfil/pf/pf_nv.h
@@ -48,6 +48,11 @@ int pf_nvuint32_array(const nvlist_t *, const char *, uint32_t *,
size_t, size_t *);
void pf_uint32_array_nv(nvlist_t *, const char *, const uint32_t *,
size_t);
+int pf_nvuint64(const nvlist_t *, const char *, uint64_t *);
+int pf_nvuint64_array(const nvlist_t *, const char *, uint64_t *,
+ size_t, size_t *);
+void pf_uint64_array_nv(nvlist_t *, const char *, const uint64_t *,
+ size_t);
int pf_nvstring(const nvlist_t *, const char *, char *, size_t);
More information about the dev-commits-src-main
mailing list