From nobody Wed Feb 28 22:27:14 2024 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4TlTVq1Bcgz5CXSq; Wed, 28 Feb 2024 22:27:15 +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 4TlTVp6rJfz4nKb; Wed, 28 Feb 2024 22:27:14 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1709159234; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pxqrA8qRDbpVXb3CekJMVqmTbOVOaU2whNdtvVUhuSE=; b=i1sWPDoFNPj3WXJLdWytBDhX1x+J2fAtd7j2BOTZkdzObQY4V+9dJ/MmTDHcXb58sISyY8 iJRns3RKQyBI849s58s3y0U4H3NaP4lDIDHPOtYu36VCG1YaqUHSVgyKU9oI1vdq1GAqyT Bb8Oyf4nbg492u4VDw59sxYQQizxT/QFp/Ulrxju1APKipXx+rbW0C4AaM17D4TBlkl/1C sAGA9Sn95HiLaBJWfxegLBIUbWckzwXmoNPVtpysRk0sK5PeHRqvQng17xmIf4cDA8eI4j zbG/+6clX50GlHEMToVCACuSnq4cqqyZds5FCqZr87hkrd9aaLjZowh0+AwgoA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1709159234; a=rsa-sha256; cv=none; b=j8+oawtgkPYn2xhrfWpgOKNcyFHFGO/LnOlH0jzo43ySK1aJadJFkZTVe4HRMU5Hci/Q8k 1OkDOZVJsK9O3/eKzuqVTJRQysHzU3TayIcOd0m/Pg+FISVP16fF97xx2Oukz5izgcW0f3 KkOsaIejDpZYqaRm6IYzkjmp/aAIHjOjGsuF2Nbb5ab0EQ1lRyc5EWfysgeDjwCRS+rsM1 Z73n2l+YPaYC0aEZ9YN4yITGQzazUxPwoKCUUBJwA22WMzRI9h0vzDPfKqDUJySBGVcPVN kuWkHePyyoHtslt5Qsre2Pq3whV1eIc+0Qxy/5DId8hna7dB/VRx8kKSFfcqmA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1709159234; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=pxqrA8qRDbpVXb3CekJMVqmTbOVOaU2whNdtvVUhuSE=; b=gD809Fks9gskdufgfkRJrGi9Qlhv7m0W7fiJFuwIfgPVXObP+mnlSacXx74HPPCCkkYJbW xI47Jk18H3qcIxnlRACiG3pWtMmXWaLSXQh3/1djzC0If/lOM2GxcjxsA+mbz8xb69XhRW RGBZiwak4OITYImgVo1R4NAs4uAcDE+HW6TTeCu03Tlh5qRgazQa0IYPPiZR09LzXnfoxT Xg0F4+eAhT/0lZKRMA8zp/D5p/PH+7sP87el8Z3x5q/0b8hjQn1PY8WWJtKe9dLatHqpnC 3dl+dC52fZJVzMSnfi3orI9JRa83hXI01BZ2sBJGNxcs2y+od3I41411lbAWCw== 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 4TlTVp50VDzG25; Wed, 28 Feb 2024 22:27:14 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 41SMREeX094375; Wed, 28 Feb 2024 22:27:14 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 41SMREHG094372; Wed, 28 Feb 2024 22:27:14 GMT (envelope-from git) Date: Wed, 28 Feb 2024 22:27:14 GMT Message-Id: <202402282227.41SMREHG094372@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: 706d465dae6a - main - pf: convert kill/clear state to use netlink List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org 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/main X-Git-Reftype: branch X-Git-Commit: 706d465dae6aa3e1b567299b9e80eb574b6c5abf Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=706d465dae6aa3e1b567299b9e80eb574b6c5abf commit 706d465dae6aa3e1b567299b9e80eb574b6c5abf Author: Kristof Provost AuthorDate: 2024-02-26 10:20:29 +0000 Commit: Kristof Provost CommitDate: 2024-02-28 22:26:18 +0000 pf: convert kill/clear state to use netlink Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D44090 --- contrib/pf/authpf/authpf.c | 8 +-- lib/libpfctl/libpfctl.c | 128 ++++++++++++++++++++++++++++++--------------- lib/libpfctl/libpfctl.h | 4 ++ sbin/pfctl/pfctl.c | 12 ++--- sys/net/pfvar.h | 3 ++ sys/netpfil/pf/pf_ioctl.c | 7 +-- sys/netpfil/pf/pf_nl.c | 96 +++++++++++++++++++++++++++++++++- sys/netpfil/pf/pf_nl.h | 19 +++++++ 8 files changed, 221 insertions(+), 56 deletions(-) diff --git a/contrib/pf/authpf/authpf.c b/contrib/pf/authpf/authpf.c index 9858c1c50ced..81dbcb747f5f 100644 --- a/contrib/pf/authpf/authpf.c +++ b/contrib/pf/authpf/authpf.c @@ -57,6 +57,7 @@ static int change_table(int, const char *); static void authpf_kill_states(void); int dev; /* pf device */ +struct pfctl_handle *pfh; char anchorname[PF_ANCHOR_NAME_SIZE] = "authpf"; char rulesetname[MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 2]; char tablename[PF_TABLE_NAME_SIZE] = "authpf_users"; @@ -135,7 +136,8 @@ main(void) } /* open the pf device */ dev = open(PATH_DEVFILE, O_RDWR); - if (dev == -1) { + pfh = pfctl_open(PATH_DEVFILE); + if (dev == -1 || pfh == NULL) { syslog(LOG_ERR, "cannot open packet filter device (%m)"); goto die; } @@ -906,7 +908,7 @@ authpf_kill_states(void) sizeof(kill.src.addr.v.a.addr)); memset(&kill.src.addr.v.a.mask, 0xff, sizeof(kill.src.addr.v.a.mask)); - if (pfctl_kill_states(dev, &kill, NULL)) + if (pfctl_kill_states_h(pfh, &kill, NULL)) syslog(LOG_ERR, "pfctl_kill_states() failed (%m)"); /* Kill all states to ipsrc */ @@ -915,7 +917,7 @@ authpf_kill_states(void) sizeof(kill.dst.addr.v.a.addr)); memset(&kill.dst.addr.v.a.mask, 0xff, sizeof(kill.dst.addr.v.a.mask)); - if (pfctl_kill_states(dev, &kill, NULL)) + if (pfctl_kill_states_h(pfh, &kill, NULL)) syslog(LOG_ERR, "pfctl_kill_states() failed (%m)"); } diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 71546c4709c2..f12e45291fc1 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1630,22 +1630,6 @@ pfctl_get_creatorids(struct pfctl_handle *h, uint32_t *creators, size_t *len) return (error); } -static void -pfctl_nv_add_state_cmp(nvlist_t *nvl, const char *name, - const struct pfctl_state_cmp *cmp) -{ - nvlist_t *nv; - - nv = nvlist_create(0); - - nvlist_add_number(nv, "id", cmp->id); - nvlist_add_number(nv, "creatorid", htonl(cmp->creatorid)); - nvlist_add_number(nv, "direction", cmp->direction); - - nvlist_add_nvlist(nvl, name, nv); - nvlist_destroy(nv); -} - static inline bool snl_attr_get_pfaddr(struct snl_state *ss __unused, struct nlattr *nla, const void *arg __unused, void *target) @@ -1848,48 +1832,110 @@ pfctl_free_states(struct pfctl_states *states) bzero(states, sizeof(*states)); } +struct pfctl_nl_clear_states { + uint32_t killed; +}; +#define _OUT(_field) offsetof(struct pfctl_nl_clear_states, _field) +static struct snl_attr_parser ap_clear_states[] = { + { .type = PF_CS_KILLED, .off = _OUT(killed), .cb = snl_attr_get_uint32 }, +}; +static struct snl_field_parser fp_clear_states[] = {}; +#undef _OUT +SNL_DECLARE_PARSER(clear_states_parser, struct genlmsghdr, fp_clear_states, ap_clear_states); + static int -_pfctl_clear_states(int dev, const struct pfctl_kill *kill, - unsigned int *killed, uint64_t ioctlval) +_pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, + unsigned int *killed, int cmd) { - nvlist_t *nvl; - int ret; + struct snl_writer nw; + struct snl_errmsg_data e = {}; + struct pfctl_nl_clear_states attrs = {}; + struct nlmsghdr *hdr; + uint32_t seq_id; + int family_id; - nvl = nvlist_create(0); + family_id = snl_get_genl_family(&h->ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); - pfctl_nv_add_state_cmp(nvl, "cmp", &kill->cmp); - nvlist_add_number(nvl, "af", kill->af); - nvlist_add_number(nvl, "proto", kill->proto); - pfctl_nv_add_rule_addr(nvl, "src", &kill->src); - pfctl_nv_add_rule_addr(nvl, "dst", &kill->dst); - pfctl_nv_add_rule_addr(nvl, "rt_addr", &kill->rt_addr); - nvlist_add_string(nvl, "ifname", kill->ifname); - nvlist_add_string(nvl, "label", kill->label); - nvlist_add_bool(nvl, "kill_match", kill->kill_match); - nvlist_add_bool(nvl, "nat", kill->nat); - - if ((ret = pfctl_do_ioctl(dev, ioctlval, 1024, &nvl)) != 0) - goto out; + snl_init_writer(&h->ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, cmd); + hdr->nlmsg_flags |= NLM_F_DUMP; + + snl_add_msg_attr_u64(&nw, PF_CS_CMP_ID, kill->cmp.id); + snl_add_msg_attr_u32(&nw, PF_CS_CMP_CREATORID, htonl(kill->cmp.creatorid)); + snl_add_msg_attr_u8(&nw, PF_CS_CMP_DIR, kill->cmp.direction); + snl_add_msg_attr_u8(&nw, PF_CS_AF, kill->af); + snl_add_msg_attr_u8(&nw, PF_CS_PROTO, kill->proto); + snl_add_msg_attr_rule_addr(&nw, PF_CS_SRC, &kill->src); + snl_add_msg_attr_rule_addr(&nw, PF_CS_DST, &kill->dst); + snl_add_msg_attr_rule_addr(&nw, PF_CS_RT_ADDR, &kill->rt_addr); + snl_add_msg_attr_string(&nw, PF_CS_IFNAME, kill->ifname); + snl_add_msg_attr_string(&nw, PF_CS_LABEL, kill->label); + snl_add_msg_attr_bool(&nw, PF_CS_KILL_MATCH, kill->kill_match); + snl_add_msg_attr_bool(&nw, PF_CS_NAT, kill->nat); + + if ((hdr = snl_finalize_msg(&nw)) == NULL) + return (ENXIO); + + seq_id = hdr->nlmsg_seq; + + if (! snl_send_message(&h->ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&h->ss, seq_id, &e)) != NULL) { + if (! snl_parse_nlmsg(&h->ss, hdr, &clear_states_parser, &attrs)) + continue; + } if (killed) - *killed = nvlist_get_number(nvl, "killed"); + *killed = attrs.killed; + + return (e.error); +} + +int +pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, + unsigned int *killed) +{ + return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_CLRSTATES)); +} + +int +pfctl_kill_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, + unsigned int *killed) +{ + return(_pfctl_clear_states_h(h, kill, killed, PFNL_CMD_KILLSTATES)); +} + +static int +_pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, + unsigned int *killed, uint64_t cmd) +{ + struct pfctl_handle *h; + int ret; + + h = pfctl_open(PF_DEVICE); + if (h == NULL) + return (ENODEV); + + ret = _pfctl_clear_states_h(h, kill, killed, cmd); + pfctl_close(h); -out: - nvlist_destroy(nvl); return (ret); } int -pfctl_clear_states(int dev, const struct pfctl_kill *kill, +pfctl_clear_states(int dev __unused, const struct pfctl_kill *kill, unsigned int *killed) { - return (_pfctl_clear_states(dev, kill, killed, DIOCCLRSTATESNV)); + return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_CLRSTATES)); } int -pfctl_kill_states(int dev, const struct pfctl_kill *kill, unsigned int *killed) +pfctl_kill_states(int dev __unused, const struct pfctl_kill *kill, unsigned int *killed) { - return (_pfctl_clear_states(dev, kill, killed, DIOCKILLSTATESNV)); + return (_pfctl_clear_states(dev, kill, killed, PFNL_CMD_KILLSTATES)); } int diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index f05044a9a985..b16caf1f6480 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -446,6 +446,10 @@ int pfctl_clear_states(int dev, const struct pfctl_kill *kill, unsigned int *killed); int pfctl_kill_states(int dev, const struct pfctl_kill *kill, unsigned int *killed); +int pfctl_clear_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, + unsigned int *killed); +int pfctl_kill_states_h(struct pfctl_handle *h, const struct pfctl_kill *kill, + unsigned int *killed); int pfctl_clear_rules(int dev, const char *anchorname); int pfctl_clear_nat(int dev, const char *anchorname); int pfctl_clear_eth_rules(int dev, const char *anchorname); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index c583279750f1..f8ecded066d2 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -545,7 +545,7 @@ pfctl_clear_iface_states(int dev, const char *iface, int opts) if (opts & PF_OPT_KILLMATCH) kill.kill_match = true; - if (pfctl_clear_states(dev, &kill, &killed)) + if (pfctl_clear_states_h(pfh, &kill, &killed)) err(1, "DIOCCLRSTATES"); if ((opts & PF_OPT_QUIET) == 0) fprintf(stderr, "%d states cleared\n", killed); @@ -801,13 +801,13 @@ pfctl_net_kill_states(int dev, const char *iface, int opts) errx(1, "Unknown address family %d", kill.af); - if (pfctl_kill_states(dev, &kill, &newkilled)) + if (pfctl_kill_states_h(pfh, &kill, &newkilled)) err(1, "DIOCKILLSTATES"); killed += newkilled; } freeaddrinfo(res[1]); } else { - if (pfctl_kill_states(dev, &kill, &newkilled)) + if (pfctl_kill_states_h(pfh, &kill, &newkilled)) err(1, "DIOCKILLSTATES"); killed += newkilled; } @@ -873,7 +873,7 @@ pfctl_gateway_kill_states(int dev, const char *iface, int opts) else errx(1, "Unknown address family %d", kill.af); - if (pfctl_kill_states(dev, &kill, &newkilled)) + if (pfctl_kill_states_h(pfh, &kill, &newkilled)) err(1, "DIOCKILLSTATES"); killed += newkilled; } @@ -907,7 +907,7 @@ pfctl_label_kill_states(int dev, const char *iface, int opts) sizeof(kill.label)) errx(1, "label too long: %s", state_kill[1]); - if (pfctl_kill_states(dev, &kill, &killed)) + if (pfctl_kill_states_h(pfh, &kill, &killed)) err(1, "DIOCKILLSTATES"); if ((opts & PF_OPT_QUIET) == 0) @@ -946,7 +946,7 @@ pfctl_id_kill_states(int dev, const char *iface, int opts) usage(); } - if (pfctl_kill_states(dev, &kill, &killed)) + if (pfctl_kill_states_h(pfh, &kill, &killed)) err(1, "DIOCKILLSTATES"); if ((opts & PF_OPT_QUIET) == 0) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index f3a808f8ad26..88fb99ead84e 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2208,6 +2208,9 @@ extern int pf_state_insert(struct pfi_kkif *, struct pf_kstate *); extern struct pf_kstate *pf_alloc_state(int); extern void pf_free_state(struct pf_kstate *); +extern void pf_killstates(struct pf_kstate_kill *, + unsigned int *); +extern unsigned int pf_clear_states(const struct pf_kstate_kill *); static __inline void pf_ref_state(struct pf_kstate *s) diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index d83933cd293f..1b22d49a6255 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -227,9 +227,6 @@ struct cdev *pf_dev; * XXX - These are new and need to be checked when moveing to a new version */ static void pf_clear_all_states(void); -static unsigned int pf_clear_states(const struct pf_kstate_kill *); -static void 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 *); @@ -5944,7 +5941,7 @@ on_error: return (error); } -static unsigned int +unsigned int pf_clear_states(const struct pf_kstate_kill *kill) { struct pf_state_key_cmp match_key; @@ -6013,7 +6010,7 @@ relock_DIOCCLRSTATES: return (killed); } -static void +void pf_killstates(struct pf_kstate_kill *kill, unsigned int *killed) { struct pf_kstate *s; diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index 120ce88f8720..e4558c156aef 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -782,6 +782,7 @@ static const struct nlattr_parser nla_p_getrules[] = { }; static const struct nlfield_parser nlf_p_getrules[] = { }; +#undef _IN #undef _OUT NL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, nlf_p_getrules, nla_p_getrules); @@ -842,6 +843,8 @@ static const struct nlattr_parser nla_p_getrule[] = { }; static const struct nlfield_parser nlf_p_getrule[] = { }; +#undef _IN +#undef _OUT NL_DECLARE_PARSER(getrule_parser, struct genlmsghdr, nlf_p_getrule, nla_p_getrule); static int @@ -1000,10 +1003,87 @@ out: return (error); } +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct pf_kstate_kill, _field) +static const struct nlattr_parser nla_p_clear_states[] = { + { .type = PF_CS_CMP_ID, .off = _OUT(psk_pfcmp.id), .cb = nlattr_get_uint64 }, + { .type = PF_CS_CMP_CREATORID, .off = _OUT(psk_pfcmp.creatorid), .cb = nlattr_get_uint32 }, + { .type = PF_CS_CMP_DIR, .off = _OUT(psk_pfcmp.direction), .cb = nlattr_get_uint8 }, + { .type = PF_CS_AF, .off = _OUT(psk_af), .cb = nlattr_get_uint8 }, + { .type = PF_CS_PROTO, .off = _OUT(psk_proto), .cb = nlattr_get_uint8 }, + { .type = PF_CS_SRC, .off = _OUT(psk_src), .arg = &rule_addr_parser, .cb = nlattr_get_nested }, + { .type = PF_CS_DST, .off = _OUT(psk_dst), .arg = &rule_addr_parser, .cb = nlattr_get_nested }, + { .type = PF_CS_RT_ADDR, .off = _OUT(psk_rt_addr), .arg = &rule_addr_parser, .cb = nlattr_get_nested }, + { .type = PF_CS_IFNAME, .off = _OUT(psk_ifname), .arg = (void *)IFNAMSIZ, .cb = nlattr_get_chara }, + { .type = PF_CS_LABEL, .off = _OUT(psk_label), .arg = (void *)PF_RULE_LABEL_SIZE, .cb = nlattr_get_chara }, + { .type = PF_CS_KILL_MATCH, .off = _OUT(psk_kill_match), .cb = nlattr_get_bool }, + { .type = PF_CS_NAT, .off = _OUT(psk_nat), .cb = nlattr_get_bool }, +}; +static const struct nlfield_parser nlf_p_clear_states[] = {}; +#undef _IN +#undef _OUT +NL_DECLARE_PARSER(clear_states_parser, struct genlmsghdr, nlf_p_clear_states, nla_p_clear_states); + +static int +pf_handle_killclear_states(struct nlmsghdr *hdr, struct nl_pstate *npt, int cmd) +{ + struct pf_kstate_kill kill = {}; + struct epoch_tracker et; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + int error; + unsigned int killed = 0; + + error = nl_parse_nlmsg(hdr, &clear_states_parser, npt, &kill); + if (error != 0) + return (error); + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + return (ENOMEM); + + ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = cmd; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + NET_EPOCH_ENTER(et); + if (cmd == PFNL_CMD_KILLSTATES) + pf_killstates(&kill, &killed); + else + killed = pf_clear_states(&kill); + NET_EPOCH_EXIT(et); + + nlattr_add_u32(nw, PF_CS_KILLED, killed); + + if (! nlmsg_end(nw)) { + error = ENOMEM; + goto out; + } + + return (0); + +out: + nlmsg_abort(nw); + return (error); +} + +static int +pf_handle_clear_states(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + return (pf_handle_killclear_states(hdr, npt, PFNL_CMD_CLRSTATES)); +} + +static int +pf_handle_kill_states(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + return (pf_handle_killclear_states(hdr, npt, PFNL_CMD_KILLSTATES)); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser, &addrule_parser, - &getrules_parser + &getrules_parser, + &clear_states_parser, }; static int family_id; @@ -1058,6 +1138,20 @@ static const struct genl_cmd pf_cmds[] = { .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, .cmd_priv = PRIV_NETINET_PF, }, + { + .cmd_num = PFNL_CMD_CLRSTATES, + .cmd_name = "CLRSTATES", + .cmd_cb = pf_handle_clear_states, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, + { + .cmd_num = PFNL_CMD_KILLSTATES, + .cmd_name = "KILLSTATES", + .cmd_cb = pf_handle_kill_states, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + .cmd_priv = PRIV_NETINET_PF, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index 51df8b7aece9..0ae4a9283072 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -43,6 +43,8 @@ enum { PFNL_CMD_ADDRULE = 5, PFNL_CMD_GETRULES = 6, PFNL_CMD_GETRULE = 7, + PFNL_CMD_CLRSTATES = 8, + PFNL_CMD_KILLSTATES = 9, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -262,6 +264,23 @@ enum pf_getrules_type_t { PF_GR_CLEAR = 5, /* u8 */ }; +enum pf_clear_states_type_t { + PF_CS_UNSPEC, + PF_CS_CMP_ID = 1, /* u64 */ + PF_CS_CMP_CREATORID = 2, /* u32 */ + PF_CS_CMP_DIR = 3, /* u8 */ + PF_CS_AF = 4, /* u8 */ + PF_CS_PROTO = 5, /* u8 */ + PF_CS_SRC = 6, /* nested, pf_addr_wrap */ + PF_CS_DST = 7, /* nested, pf_addr_wrap */ + PF_CS_RT_ADDR = 8, /* nested, pf_addr_wrap */ + PF_CS_IFNAME = 9, /* string */ + PF_CS_LABEL = 10, /* string */ + PF_CS_KILL_MATCH = 11, /* bool */ + PF_CS_NAT = 12, /* bool */ + PF_CS_KILLED = 13, /* u32 */ +}; + #ifdef _KERNEL void pf_nl_register(void);