Re: git: cfa1a1308709 - main - pfctl: fix recrusive printing of ethernet anchors
Date: Mon, 03 Oct 2022 17:13:43 UTC
I think there's still a problem here.
pfctl -a '*' -sr works
pfctl -a 'name/*' -sr does not.
On 9/6/2022 4:19 AM, Kristof Provost wrote:
> The branch main has been updated by kp:
>
> URL: https://cgit.FreeBSD.org/src/commit/?id=cfa1a13087096fe93d7a2976015ccda243476a64
>
> commit cfa1a13087096fe93d7a2976015ccda243476a64
> Author: Kristof Provost <kp@FreeBSD.org>
> AuthorDate: 2022-09-01 09:45:19 +0000
> Commit: Kristof Provost <kp@FreeBSD.org>
> CommitDate: 2022-09-06 11:19:10 +0000
>
> pfctl: fix recrusive printing of ethernet anchors
>
> Similar to the preceding fix for layer three rules, ensure that we
> recursively list wildcard anchors for ethernet rules.
>
> MFC after: 3 weeks
> Sponsored by: Rubicon Communications, LLC ("Netgate")
> Differential Revision: https://reviews.freebsd.org/D36417
> ---
> sbin/pfctl/parse.y | 9 ++++++-
> sbin/pfctl/pfctl.c | 79 +++++++++++++++++++++++++++++++++++++++++++++---------
> 2 files changed, 75 insertions(+), 13 deletions(-)
>
> diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
> index 5d0320e909fb..eea9f89782be 100644
> --- a/sbin/pfctl/parse.y
> +++ b/sbin/pfctl/parse.y
> @@ -1276,7 +1276,14 @@ etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfr
>
> memset(&r, 0, sizeof(r));
> if (pf->eastack[pf->asd + 1]) {
> - /* move inline rules into relative location */
> + if ($3 && strchr($3, '/') != NULL) {
> + free($3);
> + yyerror("anchor paths containing '/' "
> + "cannot be used for inline anchors.");
> + YYERROR;
> + }
> +
> + /* Move inline rules into relative location. */
> pfctl_eth_anchor_setup(pf, &r,
> &pf->eastack[pf->asd]->ruleset,
> $3 ? $3 : pf->ealast->name);
> diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
> index 0445fdd32ea7..bc6f14e1c197 100644
> --- a/sbin/pfctl/pfctl.c
> +++ b/sbin/pfctl/pfctl.c
> @@ -99,7 +99,7 @@ int pfctl_get_pool(int, struct pfctl_pool *, u_int32_t, u_int32_t, int,
> char *);
> void pfctl_print_eth_rule_counters(struct pfctl_eth_rule *, int);
> void pfctl_print_rule_counters(struct pfctl_rule *, int);
> -int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int);
> +int pfctl_show_eth_rules(int, char *, int, enum pfctl_show, char *, int, int);
> int pfctl_show_rules(int, char *, int, enum pfctl_show, char *, int, int);
> int pfctl_show_nat(int, char *, int, char *, int);
> int pfctl_show_src_nodes(int, int);
> @@ -1091,20 +1091,73 @@ pfctl_print_title(char *title)
>
> int
> pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
> - char *anchorname, int depth)
> + char *anchorname, int depth, int wildcard)
> {
> char anchor_call[MAXPATHLEN];
> struct pfctl_eth_rules_info info;
> struct pfctl_eth_rule rule;
> + int brace;
> int dotitle = opts & PF_OPT_SHOWALL;
> int len = strlen(path);
> - int brace;
> - char *p;
> + char *npath, *p;
>
> - if (path[0])
> - snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
> - else
> - snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
> + /*
> + * Truncate a trailing / and * on an anchorname before searching for
> + * the ruleset, this is syntactic sugar that doesn't actually make it
> + * to the kernel.
> + */
> + if ((p = strrchr(anchorname, '/')) != NULL &&
> + p[1] == '*' && p[2] == '\0') {
> + p[0] = '\0';
> + }
> +
> + if (anchorname[0] == '/') {
> + if ((npath = calloc(1, MAXPATHLEN)) == NULL)
> + errx(1, "pfctl_rules: calloc");
> + snprintf(npath, MAXPATHLEN, "%s", anchorname);
> + } else {
> + if (path[0])
> + snprintf(&path[len], MAXPATHLEN - len, "/%s", anchorname);
> + else
> + snprintf(&path[len], MAXPATHLEN - len, "%s", anchorname);
> + npath = path;
> + }
> +
> + /*
> + * If this anchor was called with a wildcard path, go through
> + * the rulesets in the anchor rather than the rules.
> + */
> + if (wildcard && (opts & PF_OPT_RECURSE)) {
> + struct pfctl_eth_rulesets_info ri;
> + u_int32_t mnr, nr;
> +
> + if (pfctl_get_eth_rulesets_info(dev, &ri, npath)) {
> + if (errno == EINVAL) {
> + fprintf(stderr, "Anchor '%s' "
> + "not found.\n", anchorname);
> + } else {
> + warn("DIOCGETETHRULESETS");
> + return (-1);
> + }
> + }
> + mnr = ri.nr;
> +
> + pfctl_print_eth_rule_counters(&rule, opts);
> + for (nr = 0; nr < mnr; ++nr) {
> + struct pfctl_eth_ruleset_info rs;
> +
> + if (pfctl_get_eth_ruleset(dev, npath, nr, &rs))
> + err(1, "DIOCGETETHRULESET");
> + INDENT(depth, !(opts & PF_OPT_VERBOSE));
> + printf("anchor \"%s\" all {\n", rs.name);
> + pfctl_show_eth_rules(dev, npath, opts,
> + format, rs.name, depth + 1, 0);
> + INDENT(depth, !(opts & PF_OPT_VERBOSE));
> + printf("}\n");
> + }
> + path[len] = '\0';
> + return (0);
> + }
>
> if (pfctl_get_eth_rules_info(dev, &info, path)) {
> warn("DIOCGETETHRULES");
> @@ -1141,7 +1194,7 @@ pfctl_show_eth_rules(int dev, char *path, int opts, enum pfctl_show format,
> pfctl_print_eth_rule_counters(&rule, opts);
> if (brace) {
> pfctl_show_eth_rules(dev, path, opts, format,
> - p, depth + 1);
> + p, depth + 1, rule.anchor_wildcard);
> INDENT(depth, !(opts & PF_OPT_VERBOSE));
> printf("}\n");
> }
> @@ -2988,13 +3041,15 @@ main(int argc, char *argv[])
> pfctl_show_limits(dev, opts);
> break;
> case 'e':
> - pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0);
> + pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
> + 0);
> break;
> case 'a':
> opts |= PF_OPT_SHOWALL;
> pfctl_load_fingerprints(dev, opts);
>
> - pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0);
> + pfctl_show_eth_rules(dev, path, opts, 0, anchorname, 0,
> + 0);
>
> pfctl_show_nat(dev, path, opts, anchorname, 0);
> pfctl_show_rules(dev, path, opts, 0, anchorname, 0, 0);
> @@ -3023,7 +3078,7 @@ main(int argc, char *argv[])
>
> if ((opts & PF_OPT_CLRRULECTRS) && showopt == NULL) {
> pfctl_show_eth_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
> - anchorname, 0);
> + anchorname, 0, 0);
> pfctl_show_rules(dev, path, opts, PFCTL_SHOW_NOTHING,
> anchorname, 0, 0);
> }
--
Bryan Drewery