On Mon, Sep 14, 2020 at 02:09:27PM +0900, YASUOKA Masahiko wrote:
> When pf rule with a "on rdomain n" with nonexisting rdomain n causes
>
> /etc/pf.conf:XXX: rdomain n does not exist
Actually, that should just work regardless of whether the rounting
domain exists at ruleset creation time; just like it is the case with
interface names/groups which may come and go at runtime without
requiring changes to the ruleset.
Rules on nonexistent interfaces won't match, routing domains (and
ultimately routing tables) should behave the same, I think.
Here's a diff that does this for routing domains allowing me to always
use `on rdomain 5' - I've tested it with a few examplatory rulesets and
behaviour is as expected.
It will need more eye balling and I am not pushing such changes before
release, but if that is a general direction we agree, your proposed
`rtable' fix could move along and become just as flexible instead.
Discussed with claudio at k2k20.
Index: /sys/net/pf_ioctl.c
===================================================================
RCS file: /cvs/src/sys/net/pf_ioctl.c,v
retrieving revision 1.356
diff -u -p -r1.356 pf_ioctl.c
--- /sys/net/pf_ioctl.c 24 Aug 2020 15:41:15 -0000 1.356
+++ /sys/net/pf_ioctl.c 14 Sep 2020 22:27:55 -0000
@@ -2820,10 +2820,8 @@ pf_rule_copyin(struct pf_rule *from, str
if (to->rtableid >= 0 && !rtable_exists(to->rtableid))
return (EBUSY);
to->onrdomain = from->onrdomain;
- if (to->onrdomain >= 0 && !rtable_exists(to->onrdomain))
- return (EBUSY);
- if (to->onrdomain >= 0) /* make sure it is a real rdomain */
- to->onrdomain = rtable_l2(to->onrdomain);
+ if (to->rtableid < 0 || to->rtableid > RT_TABLEID_MAX)
+ return (EINVAL);
for (i = 0; i < PFTM_MAX; i++)
to->timeout[i] = from->timeout[i];
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 21:52:54 -0000
@@ -392,7 +392,6 @@ int invalid_redirect(struct node_host *
u_int16_t parseicmpspec(char *, sa_family_t);
int kw_casecmp(const void *, const void *);
int map_tos(char *string, int *);
-int rdomain_exists(u_int);
int filteropts_to_rule(struct pf_rule *, struct filter_opts *);
TAILQ_HEAD(loadanchorshead, loadanchors)
@@ -2475,8 +2474,6 @@ if_item : STRING {
| RDOMAIN NUMBER {
if ($2 < 0 || $2 > RT_TABLEID_MAX)
yyerror("rdomain %lld outside range", $2);
- else if (rdomain_exists($2) != 1)
- yyerror("rdomain %lld does not exist", $2);
$$ = calloc(1, sizeof(struct node_if));
if ($$ == NULL)
@@ -5865,40 +5862,6 @@ map_tos(char *s, int *val)
return (1);
}
return (0);
-}
-
-int
-rdomain_exists(u_int rdomain)
-{
- size_t len;
- struct rt_tableinfo info;
- int mib[6];
- static u_int found[RT_TABLEID_MAX+1];
-
- if (found[rdomain] == 1)
- return 1;
-
- mib[0] = CTL_NET;
- mib[1] = PF_ROUTE;
- mib[2] = 0;
- mib[3] = 0;
- mib[4] = NET_RT_TABLE;
- mib[5] = rdomain;
-
- len = sizeof(info);
- if (sysctl(mib, 6, &info, &len, NULL, 0) == -1) {
- if (errno == ENOENT) {
- /* table nonexistent */
- return 0;
- }
- err(1, "%s", __func__);
- }
- if (info.rti_domainid == rdomain) {
- found[rdomain] = 1;
- return 1;
- }
- /* rdomain is a table, but not an rdomain */
- return 0;
}
int