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