From owner-dev-commits-src-branches@freebsd.org Fri May 14 13:06:44 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 27E876475B2; Fri, 14 May 2021 13:06:44 +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 4FhTLq6ZMVz3ksM; Fri, 14 May 2021 13:06:43 +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 CFECA12C42; Fri, 14 May 2021 13:06:43 +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 14ED6h3L052236; Fri, 14 May 2021 13:06:43 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 14ED6hIw052234; Fri, 14 May 2021 13:06:43 GMT (envelope-from git) Date: Fri, 14 May 2021 13:06:43 GMT Message-Id: <202105141306.14ED6hIw052234@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: 41bb01e095b1 - stable/13 - pf: Introduce DIOCCLRSTATESNV 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/13 X-Git-Reftype: branch X-Git-Commit: 41bb01e095b198b4d27b3d860c649267ad35c1d9 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: Fri, 14 May 2021 13:06:44 -0000 The branch stable/13 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=41bb01e095b198b4d27b3d860c649267ad35c1d9 commit 41bb01e095b198b4d27b3d860c649267ad35c1d9 Author: Kristof Provost AuthorDate: 2021-04-29 09:07:02 +0000 Commit: Kristof Provost CommitDate: 2021-05-14 08:15:27 +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 (cherry picked from commit 7606a45dcc87cb6b222af929dad37b615cb925cf) --- 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 c6761a5d87f1..dd2f189b948a 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1072,6 +1072,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; @@ -1238,6 +1251,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 d9e313f62683..79da65e0ec98 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 *); @@ -2475,6 +2477,72 @@ relock_DIOCKILLSTATES: return (killed); } +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);