Tables under different anchors may have the same name, but pfctl warns about such scenarios upon table creation to avoid mixups. Unique and descriptive names are highly recommended (for sanity).
# pfctl -T replace -t t1 1 table created. no changes. # pfctl -T replace -t t1 -a a1 pfctl: warning: namespace collision with <t1> global table. 1 table created. no changes. Adding a table to yet another anchor will only ever warn about the one in the main anchor: # pfctl -T replace -t t1 -a a2 pfctl: warning: namespace collision with <t1> global table. 1 table created. no changes. Adding equally named tables in non-main anchors only will never produce warnings: # pfctl -T add -t t2 -a a1 1 table created. 0/0 addresses added. # pfctl -T add -t t2 -a a2 1 table created. 0/0 addresses added. Things to improve: - spot all collisions - warn on dry runs (`-n') as well - name offending anchors For this the anchor name must be passed in, but this is impossible to do from pfctl's main() upon processing `-f file', where it's done now since the file may contain table definitions. This diff moves the call to process_tabledefs() inside the parser where it's only called when tables actually occur. This way both table and anchor name is known and warn_namespace_collision()'s `filter == NULL' semantic can be dropped to further simplify the function. Besides new warnings on standard error, there's no functional change as ruleset production/manipulation is not effected; regress passes. # ./obj/pfctl -T replace -t t3 1 table created. no changes. # ./obj/pfctl -T replace -t t3 -a a1 pfctl: warning: table <t3> already defined in anchor "/" 1 table created. no changes. # ./obj/pfctl -T replace -t t3 -a a2 -n pfctl: warning: table <t3> already defined in anchor "/" pfctl: warning: table <t3> already defined in anchor "a1" 1 table created (dummy). The main anchor is denoted as "/" as it keeps the logic around warnx(3) simple while still allowing to copy/paste it as is. Since it's not just about collisions with the "global" tables (those in the main anchor), I renamed the function to warn_duplicate_tables() at no cost/blame churn since signature and callers are touched anyway. Feedback? Objections? OK? Index: pfctl.h =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl.h,v retrieving revision 1.57 diff -u -p -r1.57 pfctl.h --- pfctl.h 6 Sep 2018 15:07:33 -0000 1.57 +++ pfctl.h 29 Dec 2018 15:59:11 -0000 @@ -79,7 +79,7 @@ void pfctl_clear_tables(const char *, i void pfctl_show_tables(const char *, int); int pfctl_command_tables(int, char *[], char *, const char *, char *, const char *, int); -void warn_namespace_collision(const char *); +void warn_duplicate_tables(const char *, const char *); void pfctl_show_ifaces(const char *, int); FILE *pfctl_fopen(const char *, const char *); Index: pfctl.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl.c,v retrieving revision 1.361 diff -u -p -r1.361 pfctl.c --- pfctl.c 27 Dec 2018 16:33:44 -0000 1.361 +++ pfctl.c 29 Dec 2018 15:59:11 -0000 @@ -2690,8 +2690,6 @@ main(int argc, char *argv[]) if (pfctl_rules(dev, rulesopt, opts, optimize, anchorname, NULL)) error = 1; - else if (!(opts & PF_OPT_NOACTION)) - warn_namespace_collision(NULL); } if (opts & PF_OPT_ENABLE) Index: parse.y =================================================================== RCS file: /cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.688 diff -u -p -r1.688 parse.y --- parse.y 15 Nov 2018 03:22:01 -0000 1.688 +++ parse.y 29 Dec 2018 15:59:28 -0000 @@ -4075,6 +4075,7 @@ process_tabledef(char *name, struct tabl if (pf->opts & PF_OPT_VERBOSE) print_tabledef(name, opts->flags, opts->init_addr, &opts->init_nodes); + warn_duplicate_tables(name, pf->anchor->path); if (!(pf->opts & PF_OPT_NOACTION) && pfctl_define_table(name, opts->flags, opts->init_addr, pf->anchor->path, &ab, pf->anchor->ruleset.tticket)) { Index: pfctl_table.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_table.c,v retrieving revision 1.78 diff -u -p -r1.78 pfctl_table.c --- pfctl_table.c 15 Oct 2018 21:15:35 -0000 1.78 +++ pfctl_table.c 29 Dec 2018 15:59:21 -0000 @@ -94,7 +94,8 @@ static const char *istats_text[2][2][2] goto _error; \ } \ if (nadd) { \ - warn_namespace_collision(table.pfrt_name); \ + warn_duplicate_tables(table.pfrt_name, \ + table.pfrt_anchor); \ xprintf(opts, "%d table created", nadd); \ if (opts & PF_OPT_NOACTION) \ return (0); \ @@ -537,12 +538,10 @@ pfctl_define_table(char *name, int flags } void -warn_namespace_collision(const char *filter) +warn_duplicate_tables(const char *tablename, const char *anchorname) { struct pfr_buffer b; struct pfr_table *t; - const char *name = NULL, *lastcoll; - int coll = 0; bzero(&b, sizeof(b)); b.pfrb_type = PFRB_TABLES; @@ -558,22 +557,13 @@ warn_namespace_collision(const char *fil PFRB_FOREACH(t, &b) { if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE)) continue; - if (filter != NULL && strcmp(filter, t->pfrt_name)) + if (!strcmp(anchorname, t->pfrt_anchor)) continue; - if (!t->pfrt_anchor[0]) - name = t->pfrt_name; - else if (name != NULL && !strcmp(name, t->pfrt_name)) { - coll++; - lastcoll = name; - name = NULL; - } + if (!strcmp(tablename, t->pfrt_name)) + warnx("warning: table <%s> already defined" + " in anchor \"%s\"", tablename, + t->pfrt_anchor[0] ? t->pfrt_anchor : "/"); } - if (coll == 1) - warnx("warning: namespace collision with <%s> global table.", - lastcoll); - else if (coll > 1) - warnx("warning: namespace collisions with %d global tables.", - coll); pfr_buf_clear(&b); } =================================================================== Stats: --- 21 lines 671 chars Stats: +++ 10 lines 470 chars Stats: -11 lines Stats: -201 chars