Index | Thread | Search

From:
Alexandr Nedvedicky <sashan@fastmail.net>
Subject:
Re: tell pfctl(8) route-to no longer expects network interface
To:
tech@openbsd.org
Date:
Sun, 3 May 2026 00:06:53 +0200

Download raw body.

Thread
Hello,

diff below is better, but still breaks regress test pfail57.in:

    pass in inet af-to inet6 from 2001:db8::1
    pass in inet af-to inet6 from 2001:db8::1 route-to lo0
    pass in inet af-to inet6 from 2001:db8::1 reply-to lo0
    pass in inet af-to inet6 from 2001:db8::1 dup-to lo0
    pass in inet6 af-to inet from 192.0.2.1
    pass in inet6 af-to inet from 192.0.2.1 route-to lo0
    pass in inet6 af-to inet from 192.0.2.1 reply-to lo0
    pass in inet6 af-to inet from 192.0.2.1 dup-to lo0

The diff is minimalistic change which refuses interface name
as route-to/reply-to/dup-to parameter. If we agree
it is not desired to pass interface name, then test needs
to be adjusted too.

The diff below refuses rules like;
    pass in inet6 af-to inet from 192.0.2.1 dup-to lo0
or
    pass in inet6 af-to inet from 192.0.2.1 dup-to (lo0)

The diff itself is hack. We just remember the parser
input and re-check it when we know the context where
the parsed value is being used.

Also the change does not address the case as follows:
    pass in inet6 af-to inet from 192.0.2.1 route-to lo0 - re0
rule above is still accepted. And route-to parameter
is interpreted as address range defined by addresses
bound to lo0 and re0.

thanks and
regards
sashan

--------8<---------------8<-----------------8<--------
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
index 92764edcf3b..be3c6348f2c 100644
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -3147,8 +3147,7 @@ host		: STRING			{
 				yyerror("could not parse host specification");
 				YYERROR;
 			}
-			free($1);
-
+			$$->parser_input = $1;
 		}
 		| STRING '-' STRING		{
 			struct node_host *b, *e;
@@ -3326,7 +3325,7 @@ dynaddr		: '(' STRING ')'		{
 				yyerror("interface name too long");
 				YYERROR;
 			}
-			free(op);
+			$$->parser_input = op;
 			$$->next = NULL;
 			$$->tail = $$;
 		}
@@ -4212,6 +4211,16 @@ routespec	: redirspec pool_opts {
 			if (redir == NULL)
 				err(1, "routespec calloc");
 			redir->host = $1;
+			if (redir->host->parser_input != NULL) {
+				struct node_host *chk_if;
+
+				chk_if = host_if(redir->host->parser_input, 0);
+				if (chk_if != NULL) {
+					yyerror("route-to/reply-to/dup-to: "
+					    "network interface not expected");
+					YYERROR;
+				}
+			}
 			filter_opts.rroute.rdr = redir;
 			memcpy(&filter_opts.rroute.pool_opts, &$2,
 			    sizeof(filter_opts.rroute.pool_opts));
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
index c65a805ad90..b85a10c0391 100644
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -150,6 +150,7 @@ struct node_host {
 	u_int32_t		 ifindex;	/* link-local IPv6 addrs */
 	u_int16_t		 weight;	/* load balancing weight */
 	char			*ifname;
+	char			*parser_input;
 	u_int			 ifa_flags;
 	struct node_host	*next;
 	struct node_host	*tail;
@@ -332,6 +333,7 @@ char			*ifa_indextoname(unsigned int, char *);
 struct node_host	*ifa_exists(const char *);
 struct node_host	*ifa_lookup(const char *, int);
 struct node_host	*host(const char *, int);
+struct node_host	*host_if(const char *, int);
 
 int			 append_addr(struct pfr_buffer *, char *, int, int);
 int			 append_addr_host(struct pfr_buffer *,