On Tue, Jan 12, 2021 at 08:45:22PM +0100, Alexandr Nedvedicky wrote:
> I think bluhm@ and dlg@ have committed part of that change already.

I have only commited a refactoring change.  Next step in kernel
would be to remove the check in pf_find_state() and see what happens.

I was waiting for dlg@ to do it, but maybe he waited for me.

Index: net/pf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/pf.c,v
retrieving revision 1.1098
diff -u -p -r1.1098 pf.c
--- net/pf.c    14 Jan 2021 09:44:33 -0000      1.1098
+++ net/pf.c    15 Jan 2021 16:46:42 -0000
@@ -1122,12 +1122,6 @@ pf_find_state(struct pf_pdesc *pd, struc
        }
 
        *state = s;
-       if (pd->dir == PF_OUT && s->rt_kif != NULL && s->rt_kif != pd->kif &&
-           ((s->rule.ptr->rt == PF_ROUTETO &&
-           s->rule.ptr->direction == PF_OUT) ||
-           (s->rule.ptr->rt == PF_REPLYTO &&
-           s->rule.ptr->direction == PF_IN)))
-               return (PF_PASS);
 
        return (PF_MATCH);
 }

> the proposed diff updates pfctl(8) so parser will do 'a right thing',

Does it work without the kernel changes from dlg@ ?

> the diff also breaks existing regression tests. We can update
> them once, we will agree on proposed diff.

I have adapted my regress pf.conf and regress/sys/net/pf_forward
fails in the route-to test.  It worked with dlg@'s diff.  So your
standalone pfctl change does not seem to be sufficient.

bluhm

> --------8<---------------8<---------------8<------------------8<--------
> diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
> index 2b3e62b1a7e..536aec3286b 100644
> --- a/sbin/pfctl/parse.y
> +++ b/sbin/pfctl/parse.y
> @@ -3745,23 +3745,13 @@ pool_opt      : BITMASK       {
>               ;
>  
>  route_host   : STRING                        {
> -                     /* try to find @if0 address specs */
> -                     if (strrchr($1, '@') != NULL) {
> -                             if (($$ = host($1, pf->opts)) == NULL)  {
> -                                     yyerror("invalid host for route spec");
> -                                     YYERROR;
> -                             }
> +                     if (($$ = next_hop($1, pf->opts)) == NULL)      {
> +                             /* error. "any" is handled elsewhere */
>                               free($1);
> -                     } else {
> -                             $$ = calloc(1, sizeof(struct node_host));
> -                             if ($$ == NULL)
> -                                     err(1, "route_host: calloc");
> -                             $$->ifname = $1;
> -                             $$->addr.type = PF_ADDR_NONE;
> -                             set_ipmask($$, 128);
> -                             $$->next = NULL;
> -                             $$->tail = $$;
> +                             yyerror("could not parse host specification");
> +                             YYERROR;
>                       }
> +                     free($1);
>               }
>               | STRING '/' STRING             {
>                       char    *buf;
> @@ -3769,7 +3759,7 @@ route_host      : STRING                        {
>                       if (asprintf(&buf, "%s/%s", $1, $3) == -1)
>                               err(1, "host: asprintf");
>                       free($1);
> -                     if (($$ = host(buf, pf->opts)) == NULL) {
> +                     if (($$ = next_hop(buf, pf->opts)) == NULL)     {
>                               /* error. "any" is handled elsewhere */
>                               free(buf);
>                               yyerror("could not parse host specification");
> @@ -3795,33 +3785,6 @@ route_host     : STRING                        {
>                       $$->next = NULL;
>                       $$->tail = $$;
>               }
> -             | dynaddr '/' NUMBER            {
> -                     struct node_host        *n;
> -
> -                     if ($3 < 0 || $3 > 128) {
> -                             yyerror("bit number too big");
> -                             YYERROR;
> -                     }
> -                     $$ = $1;
> -                     for (n = $1; n != NULL; n = n->next)
> -                             set_ipmask(n, $3);
> -             }
> -             | '(' STRING host ')'           {
> -                     struct node_host        *n;
> -
> -                     $$ = $3;
> -                     /* XXX check masks, only full mask should be allowed */
> -                     for (n = $3; n != NULL; n = n->next) {
> -                             if ($$->ifname) {
> -                                     yyerror("cannot specify interface twice 
> "
> -                                         "in route spec");
> -                                     YYERROR;
> -                             }
> -                             if (($$->ifname = strdup($2)) == NULL)
> -                                     errx(1, "host: strdup");
> -                     }
> -                     free($2);
> -             }
>               ;
>  
>  route_host_list      : route_host optweight optnl            { 
> diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
> index 03317844e91..534b53b1198 100644
> --- a/sbin/pfctl/pfctl_parser.c
> +++ b/sbin/pfctl/pfctl_parser.c
> @@ -1615,17 +1615,16 @@ host(const char *s, int opts)
>  {
>       struct node_host        *h = NULL, *n;
>       int                      mask = -1;
> -     char                    *p, *ps, *if_name;
> +     char                    *p, *ps;
>       const char              *errstr;
>  
> +     if (strchr(s, '@') != NULL)
> +             err(1, "%s: '@' not expected in host spec. (%s)\n",
> +                 __func__, s);
> +
>       if ((ps = strdup(s)) == NULL)
>               err(1, "%s: strdup", __func__);
>  
> -     if ((if_name = strrchr(ps, '@')) != NULL) {
> -             if_name[0] = '\0';
> -             if_name++;
> -     }
> -
>       if ((p = strchr(ps, '/')) != NULL) {
>               mask = strtonum(p+1, 0, 128, &errstr);
>               if (errstr) {
> @@ -1642,10 +1641,46 @@ host(const char *s, int opts)
>               goto error;
>       }
>  
> -     if (if_name && if_name[0])
> -             for (n = h; n != NULL; n = n->next)
> -                     if ((n->ifname = strdup(if_name)) == NULL)
> -                             err(1, "%s: strdup", __func__);
> +     for (n = h; n != NULL; n = n->next) {
> +             n->addr.type = PF_ADDR_ADDRMASK;
> +             n->weight = 0;
> +     }       
> +
> +error:
> +     free(ps);
> +     return (h);
> +}
> +
> +struct node_host *
> +next_hop(const char *s, int opts)
> +{
> +     struct node_host        *h = NULL, *n;
> +     int                      mask = -1;
> +     char                    *p, *ps;
> +     const char              *errstr;
> +
> +     if (strchr(s, '@') != NULL)
> +             err(1, "%s: '@' not expected in next-hop spec. (%s)\n",
> +                 __func__, s);
> +
> +     if ((ps = strdup(s)) == NULL)
> +             err(1, "%s: strdup", __func__);
> +
> +     if ((p = strchr(ps, '/')) != NULL) {
> +             mask = strtonum(p+1, 0, 128, &errstr);
> +             if (errstr) {
> +                     fprintf(stderr, "netmask is %s: %s\n", errstr, p);
> +                     goto error;
> +             }
> +             p[0] = '\0';
> +     }
> +
> +     if ((h = host_ip(ps, mask)) == NULL &&
> +         (h = host_dns(ps, mask, (opts & PF_OPT_NODNS))) == NULL) {
> +             fprintf(stderr, "no IP address found for %s\n", s);
> +             goto error;
> +     }
> +
>       for (n = h; n != NULL; n = n->next) {
>               n->addr.type = PF_ADDR_ADDRMASK;
>               n->weight = 0;
> diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
> index a82854a0fea..c7ab3f967b6 100644
> --- a/sbin/pfctl/pfctl_parser.h
> +++ b/sbin/pfctl/pfctl_parser.h
> @@ -292,6 +292,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     *next_hop(const char *, int);
>  
>  int                   append_addr(struct pfr_buffer *, char *, int, int);
>  int                   append_addr_host(struct pfr_buffer *,

Reply via email to