Hi, When pf rule with a "on rdomain n" with nonexisting rdomain n causes
/etc/pf.conf:XXX: rdomain n does not exist error. But with a "rtable n" with nonexisting rtable n will cause pfctl: DIOCADDRULE: Device busy error. It is hard to find the cause by this error message. /etc/pf.conf:XXX: rtable n does not exist is better. ok? Make pfctl check if the rtable really exists when parsing the config. Index: sbin/pfctl/parse.y =================================================================== RCS file: /cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.701 diff -u -p -r1.701 parse.y --- sbin/pfctl/parse.y 28 Jan 2020 15:40:35 -0000 1.701 +++ sbin/pfctl/parse.y 14 Sep 2020 04:54:39 -0000 @@ -393,6 +393,7 @@ u_int16_t parseicmpspec(char *, sa_famil int kw_casecmp(const void *, const void *); int map_tos(char *string, int *); int rdomain_exists(u_int); +int rtable_exists(u_int); int filteropts_to_rule(struct pf_rule *, struct filter_opts *); TAILQ_HEAD(loadanchorshead, loadanchors) @@ -1217,6 +1218,10 @@ antispoof_opt : LABEL label { yyerror("invalid rtable id"); YYERROR; } + else if (rtable_exists($2) != 1) { + yyerror("rtable %lld does not exist", $2); + YYERROR; + } antispoof_opts.rtableid = $2; } ; @@ -2001,6 +2006,10 @@ filter_opt : USER uids { yyerror("invalid rtable id"); YYERROR; } + else if (rtable_exists($2) != 1) { + yyerror("rtable %lld does not exist", $2); + YYERROR; + } filter_opts.rtableid = $2; } | DIVERTTO STRING PORT portplain { @@ -5899,6 +5908,36 @@ rdomain_exists(u_int rdomain) } /* rdomain is a table, but not an rdomain */ return 0; +} + +int +rtable_exists(u_int rtable) +{ + size_t len; + struct rt_tableinfo info; + int mib[6]; + static u_int found[RT_TABLEID_MAX+1]; + + if (found[rtable] == 1) + return 1; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_TABLE; + mib[5] = rtable; + + len = sizeof(info); + if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) { + if (errno == ENOENT) { + /* table nonexistent */ + return 0; + } + err(1, "%s", __func__); + } + found[rtable] = 1; + return 1; } int