From nobody Mon Nov 27 20:37:11 2023 X-Original-To: dev-commits-src-main@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 4SfHSl3PpCz52ljf; Mon, 27 Nov 2023 20:37:11 +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 4SfHSl2DVZz4K7l; Mon, 27 Nov 2023 20:37:11 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701117431; 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=cySsdPrlZcxp1CcYZpSV1eMpAxhTgxx9qcgKpfK9Vh0=; b=MbvdtviLpyMcHaP8/a6W9HdojkcA8LPEMPZi5gPl7db0qRb4vhRdvsD6BabtOg2EhfF4uz 11oTuLF8KQMvvACLjAKocYHh4E0A5OUe4b2wogHvoHIZKHuVx+fYXKeoEWoaIGp8JLCGwH se7g0Ya1GPQwjmGW00Y9v6F9o8E+7CE23QsFk/T3M0JP9uWPtzLRjj1rHb6/ovl0Gr7knK Ll7sgWqpSe+js/hKQnfkIft3jeIoPE9U2dgo4wa6kUDLUCn5fXuoGeN1zn/RNgtbR22jPs d9Ugyn/gQULHDvDPmVc3yM4dbfYneLu8WHiXWBT2IJscIyORyXt9Bxh5yb6KDQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1701117431; 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=cySsdPrlZcxp1CcYZpSV1eMpAxhTgxx9qcgKpfK9Vh0=; b=GlqizXIdePnjXDbbf1hWAmcF0DCn6FD+OoVSGwVeOUpcw8YaAxm4jHkVwAnlgWJ8L04Uf6 TdkpjcXteGHUtLGCPJySMgm5Cn0b5G2cE2KI/jX/4ftdnxOmOmSt9bLVW/cT2OPrlSWTq2 jMd1f3NLabsqsuouvYlDJrDLmGy22nzGoLvK2Z3HSq7Un83vnbhTcJtlxpGcLI9zGA83S+ c06AGnASSlqrItqaiwokCf+5TCgiactHEQvZcniXWR8Gav89MNe5XyPCG+NeZH0lLXOLod kiDYM+gp6M2nJFjjq+IKViAKmWcJXwdJsjsG2hup0tuWP8GkNI4vrCjGjGgf4A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1701117431; a=rsa-sha256; cv=none; b=M+tHRd3evgaxSiLUg/TsPVBzqlxM5SONgY5iOVum7tkUy8CP6wJ1d5hL0hh2dNWvEPI/wm Sh+ZtZVHLeaHBMLku6FnpleYpZrWoaJe196avoEYOisK2acI5ePZneYVeFSToIy+E5xhri Q6wGyPvr3PwdHHvNEMDNRXwRNIZqsnwTDXGLvppeXRvxyJNdnw0dvFlLFjcw2DQqwb/0jH csAABopAXsQIj1xaWPYPfxa2H029dOL9Z/PyLONqTYSPXFvDVqqkTBv2WYOLmv8PfxluB2 Na3e6mqWmwr83y+vnR0gB91wNJwlUM6kj97HRiPrRgjnQhDArggfckWSPWdIsA== 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 4SfHSl1GjYzt64; Mon, 27 Nov 2023 20:37:11 +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 3ARKbBLp019779; Mon, 27 Nov 2023 20:37:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 3ARKbBKa019776; Mon, 27 Nov 2023 20:37:11 GMT (envelope-from git) Date: Mon, 27 Nov 2023 20:37:11 GMT Message-Id: <202311272037.3ARKbBKa019776@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: 44f323ecdec0 - main - pf: implement DIOCGETRULES via netlink List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: 44f323ecdec02dc947c34d08c34b881fe2da1ba6 Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=44f323ecdec02dc947c34d08c34b881fe2da1ba6 commit 44f323ecdec02dc947c34d08c34b881fe2da1ba6 Author: Kristof Provost AuthorDate: 2023-11-24 23:42:44 +0000 Commit: Kristof Provost CommitDate: 2023-11-27 20:36:49 +0000 pf: implement DIOCGETRULES via netlink Sponsored by: Rubicon Communications, LLC ("Netgate") --- lib/libpfctl/libpfctl.c | 57 ++++++++++++++++++++++++++++++---------- sys/net/pfvar.h | 1 + sys/netpfil/pf/pf_ioctl.c | 56 +++++++++++++++++++++++----------------- sys/netpfil/pf/pf_nl.c | 66 +++++++++++++++++++++++++++++++++++++++++++++-- sys/netpfil/pf/pf_nl.h | 9 +++++++ 5 files changed, 149 insertions(+), 40 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index a600031ec0a9..513d2d0f01be 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1119,26 +1119,55 @@ pfctl_add_rule(int dev __unused, const struct pfctl_rule *r, const char *anchor, return (e.error); } +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct pfctl_rules_info, _field) +static struct snl_attr_parser ap_getrules[] = { + { .type = PF_GR_NR, .off = _OUT(nr), .cb = snl_attr_get_uint32 }, + { .type = PF_GR_TICKET, .off = _OUT(ticket), .cb = snl_attr_get_uint32 }, +}; +static struct snl_field_parser fp_getrules[] = { +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, fp_getrules, ap_getrules); + int -pfctl_get_rules_info(int dev, struct pfctl_rules_info *rules, uint32_t ruleset, +pfctl_get_rules_info(int dev __unused, struct pfctl_rules_info *rules, uint32_t ruleset, const char *path) { - struct pfioc_rule pr; - int ret; + struct snl_state ss = {}; + struct snl_errmsg_data e = {}; + struct nlmsghdr *hdr; + struct snl_writer nw; + uint32_t seq_id; + int family_id; - bzero(&pr, sizeof(pr)); - if (strlcpy(pr.anchor, path, sizeof(pr.anchor)) >= sizeof(pr.anchor)) - return (E2BIG); + snl_init(&ss, NETLINK_GENERIC); + family_id = snl_get_genl_family(&ss, PFNL_FAMILY_NAME); + if (family_id == 0) + return (ENOTSUP); - pr.rule.action = ruleset; - ret = ioctl(dev, DIOCGETRULES, &pr); - if (ret != 0) - return (ret); + snl_init_writer(&ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETRULES); + hdr->nlmsg_flags |= NLM_F_DUMP; - rules->nr = pr.nr; - rules->ticket = pr.ticket; + snl_add_msg_attr_string(&nw, PF_GR_ANCHOR, path); + snl_add_msg_attr_u8(&nw, PF_GR_ACTION, ruleset); - return (0); + hdr = snl_finalize_msg(&nw); + if (hdr == NULL) + return (ENOMEM); + + seq_id = hdr->nlmsg_seq; + if (! snl_send_message(&ss, hdr)) + return (ENXIO); + + while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { + if (! snl_parse_nlmsg(&ss, hdr, &getrules_parser, rules)) + continue; + } + + return (e.error); } int @@ -1368,7 +1397,7 @@ SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, fp_state, ap_state); static const struct snl_hdr_parser *all_parsers[] = { &state_parser, &skey_parser, &speer_parser, - &creator_parser, + &creator_parser, &getrules_parser }; static int diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index 4b10190bf9ea..48162b786a86 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2473,6 +2473,7 @@ int pf_keth_anchor_nvcopyout( struct pf_keth_ruleset *pf_find_or_create_keth_ruleset(const char *); void pf_keth_anchor_remove(struct pf_keth_rule *); +int pf_ioctl_getrules(struct pfioc_rule *); int pf_ioctl_addrule(struct pf_krule *, uint32_t, uint32_t, const char *, const char *, uid_t uid, pid_t); diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 1598939c2375..ec55d43d3800 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2021,6 +2021,36 @@ pf_rule_to_krule(const struct pf_rule *rule, struct pf_krule *krule) return (0); } +int +pf_ioctl_getrules(struct pfioc_rule *pr) +{ + struct pf_kruleset *ruleset; + struct pf_krule *tail; + int rs_num; + + PF_RULES_WLOCK(); + ruleset = pf_find_kruleset(pr->anchor); + if (ruleset == NULL) { + PF_RULES_WUNLOCK(); + return (EINVAL); + } + rs_num = pf_get_ruleset_number(pr->rule.action); + if (rs_num >= PF_RULESET_MAX) { + PF_RULES_WUNLOCK(); + return (EINVAL); + } + tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, + pf_krulequeue); + if (tail) + pr->nr = tail->nr + 1; + else + pr->nr = 0; + pr->ticket = ruleset->rules[rs_num].active.ticket; + PF_RULES_WUNLOCK(); + + return (0); +} + int pf_ioctl_addrule(struct pf_krule *rule, uint32_t ticket, uint32_t pool_ticket, const char *anchor, const char *anchor_call, @@ -3117,33 +3147,11 @@ DIOCADDRULENV_error: case DIOCGETRULES: { struct pfioc_rule *pr = (struct pfioc_rule *)addr; - struct pf_kruleset *ruleset; - struct pf_krule *tail; - int rs_num; pr->anchor[sizeof(pr->anchor) - 1] = 0; - PF_RULES_WLOCK(); - ruleset = pf_find_kruleset(pr->anchor); - if (ruleset == NULL) { - PF_RULES_WUNLOCK(); - error = EINVAL; - break; - } - rs_num = pf_get_ruleset_number(pr->rule.action); - if (rs_num >= PF_RULESET_MAX) { - PF_RULES_WUNLOCK(); - error = EINVAL; - break; - } - tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr, - pf_krulequeue); - if (tail) - pr->nr = tail->nr + 1; - else - pr->nr = 0; - pr->ticket = ruleset->rules[rs_num].active.ticket; - PF_RULES_WUNLOCK(); + error = pf_ioctl_getrules(pr); + break; } diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index fe5ded0e86a4..86cc5ba9cc91 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -635,7 +635,64 @@ pf_handle_addrule(struct nlmsghdr *hdr, struct nl_pstate *npt) return (error); } -static const struct nlhdr_parser *all_parsers[] = { &state_parser, &addrule_parser }; +struct nl_parsed_getrules { + char *anchor; + uint8_t action; +}; +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct pfioc_rule, _field) +static const struct nlattr_parser nla_p_getrules[] = { + { .type = PF_GR_ANCHOR, .off = _OUT(anchor), .arg = (void *)MAXPATHLEN, .cb = nlattr_get_chara }, + { .type = PF_GR_ACTION, .off = _OUT(rule.action), .cb = nlattr_get_uint8 }, +}; +static const struct nlfield_parser nlf_p_getrules[] = { +}; +NL_DECLARE_PARSER(getrules_parser, struct genlmsghdr, nlf_p_getrules, nla_p_getrules); + +static int +pf_handle_getrules(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + struct pfioc_rule attrs = {}; + int error; + struct nl_writer *nw = npt->nw; + struct genlmsghdr *ghdr_new; + + error = nl_parse_nlmsg(hdr, &getrules_parser, npt, &attrs); + 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 = PFNL_CMD_GETRULES; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + error = pf_ioctl_getrules(&attrs); + if (error != 0) + goto out; + + nlattr_add_u32(nw, PF_GR_NR, attrs.nr); + nlattr_add_u32(nw, PF_GR_TICKET, attrs.ticket); + + if (!nlmsg_end(nw)) { + error = ENOMEM; + goto out; + } + + return (0); + +out: + nlmsg_abort(nw); + return (error); +} + +static const struct nlhdr_parser *all_parsers[] = { + &state_parser, + &addrule_parser, + &getrules_parser +}; static int family_id; @@ -670,7 +727,12 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_addrule, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, }, - + { + .cmd_num = PFNL_CMD_GETRULES, + .cmd_name = "GETRULES", + .cmd_cb = pf_handle_getrules, + .cmd_flags = GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index 8265ae1d1bfa..3ae77ffd3790 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -41,6 +41,7 @@ enum { PFNL_CMD_START = 3, PFNL_CMD_STOP = 4, PFNL_CMD_ADDRULE = 5, + PFNL_CMD_GETRULES = 6, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) @@ -232,6 +233,14 @@ enum pf_addrule_type_t { PF_ART_RULE = 5, /* nested, pfrule_type_t */ }; +enum pf_getrules_type_t { + PF_GR_UNSPEC, + PF_GR_ANCHOR = 1, /* string */ + PF_GR_ACTION = 2, /* u8 */ + PF_GR_NR = 3, /* u32 */ + PF_GR_TICKET = 4, /* u32 */ +}; + #ifdef _KERNEL void pf_nl_register(void);