On Thu, Jan 28, 2021 at 10:54:30PM +1000, David Gwynne wrote: > this is the diff from the "pf route-to issues" thread, but on it's own.
I think we should make progress and commit something. > the caveat is that route-to becomes tied to pass rules that create > state, like rdr-to and nat-to. Maybe we should mention that in the man page. But let's discuss that separately. > that's a separate change for broader discussion. Yes. No more topics on top of uncomitted diffs. > ok? OK bluhm@ > Index: sbin/pfctl/parse.y > =================================================================== > RCS file: /cvs/src/sbin/pfctl/parse.y,v > retrieving revision 1.708 > diff -u -p -r1.708 parse.y > --- sbin/pfctl/parse.y 12 Jan 2021 00:10:34 -0000 1.708 > +++ sbin/pfctl/parse.y 28 Jan 2021 11:45:58 -0000 > @@ -276,6 +276,7 @@ struct filter_opts { > struct redirspec nat; > struct redirspec rdr; > struct redirspec rroute; > + u_int8_t rt; > > /* scrub opts */ > int nodf; > @@ -284,15 +285,6 @@ struct filter_opts { > int randomid; > int max_mss; > > - /* route opts */ > - struct { > - struct node_host *host; > - u_int8_t rt; > - u_int8_t pool_opts; > - sa_family_t af; > - struct pf_poolhashkey *key; > - } route; > - > struct { > u_int32_t limit; > u_int32_t seconds; > @@ -372,7 +364,7 @@ void expand_label(char *, size_t, cons > struct node_port *, u_int8_t); > int expand_divertspec(struct pf_rule *, struct divertspec *); > int collapse_redirspec(struct pf_pool *, struct pf_rule *, > - struct redirspec *rs, u_int8_t); > + struct redirspec *rs, int); > int apply_redirspec(struct pf_pool *, struct pf_rule *, > struct redirspec *, int, struct node_port *); > void expand_rule(struct pf_rule *, int, struct node_if *, > @@ -518,7 +510,6 @@ int parseport(char *, struct range *r, i > %type <v.host> ipspec xhost host dynaddr host_list > %type <v.host> table_host_list tablespec > %type <v.host> redir_host_list redirspec > -%type <v.host> route_host route_host_list routespec > %type <v.os> os xos os_list > %type <v.port> portspec port_list port_item > %type <v.uid> uids uid_list uid_item > @@ -975,7 +966,7 @@ anchorrule : ANCHOR anchorname dir quick > YYERROR; > } > > - if ($9.route.rt) { > + if ($9.rt) { > yyerror("cannot specify route handling " > "on anchors"); > YYERROR; > @@ -1843,37 +1834,13 @@ pfrule : action dir logquick interface > decide_address_family($7.src.host, &r.af); > decide_address_family($7.dst.host, &r.af); > > - if ($8.route.rt) { > - if (!r.direction) { > + if ($8.rt) { > + if ($8.rt != PF_DUPTO && !r.direction) { > yyerror("direction must be explicit " > "with rules that specify routing"); > YYERROR; > } > - r.rt = $8.route.rt; > - r.route.opts = $8.route.pool_opts; > - if ($8.route.key != NULL) > - memcpy(&r.route.key, $8.route.key, > - sizeof(struct pf_poolhashkey)); > - } > - if (r.rt) { > - decide_address_family($8.route.host, &r.af); > - if ((r.route.opts & PF_POOL_TYPEMASK) == > - PF_POOL_NONE && ($8.route.host->next != > NULL || > - $8.route.host->addr.type == PF_ADDR_TABLE || > - DYNIF_MULTIADDR($8.route.host->addr))) > - r.route.opts |= PF_POOL_ROUNDROBIN; > - if ($8.route.host->next != NULL) { > - if (!PF_POOL_DYNTYPE(r.route.opts)) { > - yyerror("address pool option " > - "not supported by type"); > - YYERROR; > - } > - } > - /* fake redirspec */ > - if (($8.rroute.rdr = calloc(1, > - sizeof(*$8.rroute.rdr))) == NULL) > - err(1, "$8.rroute.rdr"); > - $8.rroute.rdr->host = $8.route.host; > + r.rt = $8.rt; > } > > if (expand_divertspec(&r, &$8.divert)) > @@ -2137,30 +2104,14 @@ filter_opt : USER uids { > sizeof(filter_opts.nat.pool_opts)); > filter_opts.nat.pool_opts.staticport = 1; > } > - | ROUTETO routespec pool_opts { > - filter_opts.route.host = $2; > - filter_opts.route.rt = PF_ROUTETO; > - filter_opts.route.pool_opts = $3.type | $3.opts; > - memcpy(&filter_opts.rroute.pool_opts, &$3, > - sizeof(filter_opts.rroute.pool_opts)); > - if ($3.key != NULL) > - filter_opts.route.key = $3.key; > + | ROUTETO routespec { > + filter_opts.rt = PF_ROUTETO; > } > - | REPLYTO routespec pool_opts { > - filter_opts.route.host = $2; > - filter_opts.route.rt = PF_REPLYTO; > - filter_opts.route.pool_opts = $3.type | $3.opts; > - if ($3.key != NULL) > - filter_opts.route.key = $3.key; > - } > - | DUPTO routespec pool_opts { > - filter_opts.route.host = $2; > - filter_opts.route.rt = PF_DUPTO; > - filter_opts.route.pool_opts = $3.type | $3.opts; > - memcpy(&filter_opts.rroute.pool_opts, &$3, > - sizeof(filter_opts.rroute.pool_opts)); > - if ($3.key != NULL) > - filter_opts.route.key = $3.key; > + | REPLYTO routespec { > + filter_opts.rt = PF_REPLYTO; > + } > + | DUPTO routespec { > + filter_opts.rt = PF_DUPTO; > } > | not RECEIVEDON if_item { > if (filter_opts.rcv) { > @@ -3743,122 +3694,21 @@ 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; > - } > - 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 = $$; > - } > - } > - | STRING '/' STRING { > - char *buf; > - > - if (asprintf(&buf, "%s/%s", $1, $3) == -1) > - err(1, "host: asprintf"); > - free($1); > - if (($$ = host(buf, pf->opts)) == NULL) { > - /* error. "any" is handled elsewhere */ > - free(buf); > - yyerror("could not parse host specification"); > - YYERROR; > - } > - free(buf); > - } > - | '<' STRING '>' { > - if (strlen($2) >= PF_TABLE_NAME_SIZE) { > - yyerror("table name '%s' too long", $2); > - free($2); > - YYERROR; > - } > - $$ = calloc(1, sizeof(struct node_host)); > - if ($$ == NULL) > - err(1, "host: calloc"); > - $$->addr.type = PF_ADDR_TABLE; > - if (strlcpy($$->addr.v.tblname, $2, > - sizeof($$->addr.v.tblname)) >= > - sizeof($$->addr.v.tblname)) > - errx(1, "host: strlcpy"); > - free($2); > - $$->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 { > - if ($2 > 0) { > - struct node_host *n; > - for (n = $1; n != NULL; n = n->next) > - n->weight = $2; > - } > - $$ = $1; > - } > - | route_host_list comma route_host optweight optnl { > - if ($1->af == 0) > - $1->af = $3->af; > - if ($1->af != $3->af) { > - yyerror("all pool addresses must be in the " > - "same address family"); > +routespec : redirspec pool_opts { > + struct redirection *redir; > + if (filter_opts.rt != PF_NOPFROUTE) { > + yyerror("cannot respecify " > + "route-to/reply-to/dup-to"); > YYERROR; > } > - $1->tail->next = $3; > - $1->tail = $3->tail; > - if ($4 > 0) { > - struct node_host *n; > - for (n = $3; n != NULL; n = n->next) > - n->weight = $4; > - } > - $$ = $1; > - } > - ; > - > -routespec : route_host optweight { > - if ($2 > 0) { > - struct node_host *n; > - for (n = $1; n != NULL; n = n->next) > - n->weight = $2; > - } > - $$ = $1; > + redir = calloc(1, sizeof(*redir)); > + if (redir == NULL) > + err(1, "routespec calloc"); > + redir->host = $1; > + filter_opts.rroute.rdr = redir; > + memcpy(&filter_opts.rroute.pool_opts, &$2, > + sizeof(filter_opts.rroute.pool_opts)); > } > - | '{' optnl route_host_list '}' { $$ = $3; } > ; > > timeout_spec : STRING NUMBER > @@ -4478,7 +4328,7 @@ expand_divertspec(struct pf_rule *r, str > > int > collapse_redirspec(struct pf_pool *rpool, struct pf_rule *r, > - struct redirspec *rs, u_int8_t allow_if) > + struct redirspec *rs, int routing) > { > struct pf_opt_tbl *tbl = NULL; > struct node_host *h, *hprev = NULL; > @@ -4494,6 +4344,15 @@ collapse_redirspec(struct pf_pool *rpool > r->naf = rs->af; > > for (h = rs->rdr->host; h != NULL; h = h->next) { > + if (routing) { > + if (h->addr.type == PF_ADDR_DYNIFTL && > + h->addr.iflags != PFI_AFLAG_PEER) { > + yyerror("route spec requires :peer with " > + "dynamic interface addresses"); > + return (1); > + } > + } > + > /* set rule address family if redirect spec has one */ > if (rs->af && !r->af && !af) { > /* swap address families for af-to */ > @@ -4515,7 +4374,7 @@ collapse_redirspec(struct pf_pool *rpool > if (!r->af && af && af != h->af) { > yyerror("%s spec contains addresses with " > "different address families", > - allow_if ? "routing" : "translation"); > + routing ? "routing" : "translation"); > return (1); > } > } else if (h->af) { /* af-to case */ > @@ -4526,7 +4385,7 @@ collapse_redirspec(struct pf_pool *rpool > if (rs->af && rs->af != h->af) { > yyerror("%s spec contains addresses that " > "don't match target address family", > - allow_if ? "routing" : "translation"); > + routing ? "routing" : "translation"); > return (1); > } > } > @@ -4541,8 +4400,9 @@ collapse_redirspec(struct pf_pool *rpool > > if (naddr == 0) { /* the first host */ > rpool->addr = h->addr; > - if (!allow_if && h->ifname) { > - yyerror("@if not permitted for translation"); > + if (h->ifname) { > + yyerror("@if not permitted for %s", > + routing ? "routing" : "translation"); > return (1); > } > if (h->ifname && strlcpy(rpool->ifname, h->ifname, > @@ -4564,8 +4424,9 @@ collapse_redirspec(struct pf_pool *rpool > "not supported for translation or routing"); > return (1); > } > - if (!allow_if && h->ifname) { > - yyerror("@if not permitted for translation"); > + if (h->ifname) { > + yyerror("@if not permitted for %s", > + routing ? "routing" : "translation"); > return (1); > } > if (hprev) { > @@ -4596,7 +4457,7 @@ collapse_redirspec(struct pf_pool *rpool > r->af = af; > if (!naddr) { > yyerror("af mismatch in %s spec", > - allow_if ? "routing" : "translation"); > + routing ? "routing" : "translation"); > return (1); > } > if (tbl) { > @@ -5992,7 +5853,7 @@ filteropts_to_rule(struct pf_rule *r, st > yyerror("af-to can only be used with direction in"); > return (1); > } > - if ((opts->marker & FOM_AFTO) && opts->route.rt) { > + if ((opts->marker & FOM_AFTO) && opts->rt) { > yyerror("af-to cannot be used together with " > "route-to, reply-to, dup-to"); > return (1); > Index: sbin/pfctl/pfctl_parser.c > =================================================================== > RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v > retrieving revision 1.345 > diff -u -p -r1.345 pfctl_parser.c > --- sbin/pfctl/pfctl_parser.c 12 Jan 2021 00:10:34 -0000 1.345 > +++ sbin/pfctl/pfctl_parser.c 28 Jan 2021 11:45:58 -0000 > @@ -1615,17 +1615,12 @@ 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 ((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 +1637,6 @@ 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; > Index: share/man/man5/pf.conf.5 > =================================================================== > RCS file: /cvs/src/share/man/man5/pf.conf.5,v > retrieving revision 1.585 > diff -u -p -r1.585 pf.conf.5 > --- share/man/man5/pf.conf.5 7 Dec 2020 08:29:41 -0000 1.585 > +++ share/man/man5/pf.conf.5 28 Jan 2021 11:45:58 -0000 > @@ -1113,8 +1113,8 @@ the incoming connection arrived through > .It Cm route-to > The > .Cm route-to > -option routes the packet to the specified interface with an optional address > -for the next hop. > +option routes the packet to the specified destination address instead > +of the destination address in the packet header. > When a > .Cm route-to > rule creates state, only packets that pass in the same direction as the > @@ -2858,8 +2858,7 @@ ifspec = ( [ "!" ] ( interface-n > interface-list = [ "!" ] ( interface-name | interface-group ) > [ [ "," ] interface-list ] > route = ( "route-to" | "reply-to" | "dup-to" ) > - ( routehost | "{" routehost-list "}" ) > - [ pooltype ] > + ( redirhost | "{" redirhost-list "}" ) > af = "inet" | "inet6" > > protospec = "proto" ( proto-name | proto-number | > @@ -2878,14 +2877,11 @@ host = [ "!" ] ( address [ "we > address [ "/" mask-bits ] [ "weight" number ] | > "<" string ">" ) > redirhost = address [ "/" mask-bits ] > -routehost = host | host "@" interface-name | > - "(" interface-name [ address [ "/" mask-bits ] ] ")" > address = ( interface-name | interface-group | > "(" ( interface-name | interface-group ) ")" | > hostname | ipv4-dotted-quad | ipv6-coloned-hex ) > host-list = host [ [ "," ] host-list ] > redirhost-list = redirhost [ [ "," ] redirhost-list ] > -routehost-list = routehost [ [ "," ] routehost-list ] > > port = "port" ( unary-op | binary-op | "{" op-list "}" ) > portspec = "port" ( number | name ) [ ":" ( "*" | number | name ) ] > Index: sys/net/if_pfsync.c > =================================================================== > RCS file: /cvs/src/sys/net/if_pfsync.c,v > retrieving revision 1.281 > diff -u -p -r1.281 if_pfsync.c > --- sys/net/if_pfsync.c 18 Jan 2021 18:29:19 -0000 1.281 > +++ sys/net/if_pfsync.c 28 Jan 2021 11:45:58 -0000 > @@ -613,6 +613,7 @@ pfsync_state_import(struct pfsync_state > > /* copy to state */ > st->rt_addr = sp->rt_addr; > + st->rt = sp->rt; > st->creation = getuptime() - ntohl(sp->creation); > st->expire = getuptime(); > if (ntohl(sp->expire)) { > @@ -643,7 +644,6 @@ pfsync_state_import(struct pfsync_state > > st->rule.ptr = r; > st->anchor.ptr = NULL; > - st->rt_kif = NULL; > > st->pfsync_time = getuptime(); > st->sync_state = PFSYNC_S_NONE; > @@ -1860,7 +1860,7 @@ pfsync_undefer(struct pfsync_deferral *p > if (drop) > m_freem(pd->pd_m); > else { > - if (st->rule.ptr->rt == PF_ROUTETO) { > + if (st->rt == PF_ROUTETO) { > if (pf_setup_pdesc(&pdesc, st->key[PF_SK_WIRE]->af, > st->direction, st->kif, pd->pd_m, NULL) != > PF_PASS) { > @@ -1869,11 +1869,11 @@ pfsync_undefer(struct pfsync_deferral *p > } > switch (st->key[PF_SK_WIRE]->af) { > case AF_INET: > - pf_route(&pdesc, st->rule.ptr, st); > + pf_route(&pdesc, st); > break; > #ifdef INET6 > case AF_INET6: > - pf_route6(&pdesc, st->rule.ptr, st); > + pf_route6(&pdesc, st); > break; > #endif /* INET6 */ > default: > Index: sys/net/pf.c > =================================================================== > RCS file: /cvs/src/sys/net/pf.c,v > retrieving revision 1.1105 > diff -u -p -r1.1105 pf.c > --- sys/net/pf.c 28 Jan 2021 09:37:20 -0000 1.1105 > +++ sys/net/pf.c 28 Jan 2021 11:45:58 -0000 > @@ -1180,6 +1180,7 @@ pf_state_export(struct pfsync_state *sp, > > /* copy from state */ > strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); > + sp->rt = st->rt; > sp->rt_addr = st->rt_addr; > sp->creation = htonl(getuptime() - st->creation); > expire = pf_state_expires(st); > @@ -3430,16 +3431,13 @@ pf_set_rt_ifp(struct pf_state *s, struct > struct pf_rule *r = s->rule.ptr; > int rv; > > - s->rt_kif = NULL; > if (!r->rt) > return (0); > > rv = pf_map_addr(af, r, saddr, &s->rt_addr, NULL, sns, > &r->route, PF_SN_ROUTE); > - if (rv == 0) { > - s->rt_kif = r->route.kif; > - s->natrule.ptr = r; > - } > + if (rv == 0) > + s->rt = r->rt; > > return (rv); > } > @@ -5963,15 +5961,13 @@ pf_rtlabel_match(struct pf_addr *addr, s > > /* pf_route() may change pd->m, adjust local copies after calling */ > void > -pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) > +pf_route(struct pf_pdesc *pd, struct pf_state *s) > { > struct mbuf *m0, *m1; > struct sockaddr_in *dst, sin; > struct rtentry *rt = NULL; > struct ip *ip; > struct ifnet *ifp = NULL; > - struct pf_addr naddr; > - struct pf_src_node *sns[PF_SN_MAX]; > int error = 0; > unsigned int rtableid; > > @@ -5981,11 +5977,11 @@ pf_route(struct pf_pdesc *pd, struct pf_ > return; > } > > - if (r->rt == PF_DUPTO) { > + if (s->rt == PF_DUPTO) { > if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) > return; > } else { > - if ((r->rt == PF_REPLYTO) == (r->direction == pd->dir)) > + if ((s->rt == PF_REPLYTO) == (s->direction == pd->dir)) > return; > m0 = pd->m; > pd->m = NULL; > @@ -5999,48 +5995,45 @@ pf_route(struct pf_pdesc *pd, struct pf_ > > ip = mtod(m0, struct ip *); > > - memset(&sin, 0, sizeof(sin)); > - dst = &sin; > - dst->sin_family = AF_INET; > - dst->sin_len = sizeof(*dst); > - dst->sin_addr = ip->ip_dst; > - rtableid = m0->m_pkthdr.ph_rtableid; > - > if (pd->dir == PF_IN) { > if (ip->ip_ttl <= IPTTLDEC) { > - if (r->rt != PF_DUPTO) > + if (s->rt != PF_DUPTO) { > pf_send_icmp(m0, ICMP_TIMXCEED, > ICMP_TIMXCEED_INTRANS, 0, > - pd->af, r, pd->rdomain); > + pd->af, s->rule.ptr, pd->rdomain); > + } > goto bad; > } > ip->ip_ttl -= IPTTLDEC; > } > > - if (s == NULL) { > - memset(sns, 0, sizeof(sns)); > - if (pf_map_addr(AF_INET, r, > - (struct pf_addr *)&ip->ip_src, > - &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) { > - DPFPRINTF(LOG_ERR, > - "%s: pf_map_addr() failed", __func__); > - goto bad; > - } > + memset(&sin, 0, sizeof(sin)); > + dst = &sin; > + dst->sin_family = AF_INET; > + dst->sin_len = sizeof(*dst); > + dst->sin_addr = s->rt_addr.v4; > + rtableid = m0->m_pkthdr.ph_rtableid; > > - if (!PF_AZERO(&naddr, AF_INET)) > - dst->sin_addr.s_addr = naddr.v4.s_addr; > - ifp = r->route.kif ? > - r->route.kif->pfik_ifp : NULL; > - } else { > - if (!PF_AZERO(&s->rt_addr, AF_INET)) > - dst->sin_addr.s_addr = > - s->rt_addr.v4.s_addr; > - ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; > + rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); > + if (!rtisvalid(rt)) { > + if (s->rt != PF_DUPTO) { > + pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST, > + 0, pd->af, s->rule.ptr, pd->rdomain); > + } > + ipstat_inc(ips_noroute); > + goto bad; > } > + > + ifp = if_get(rt->rt_ifidx); > if (ifp == NULL) > goto bad; > > - if (r->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { > + /* A locally generated packet may have invalid source address. */ > + if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET && > + (ifp->if_flags & IFF_LOOPBACK) == 0) > + ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr; > + > + if (s->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { > if (pf_test(AF_INET, PF_OUT, ifp, &m0) != PF_PASS) > goto bad; > else if (m0 == NULL) > @@ -6053,20 +6046,6 @@ pf_route(struct pf_pdesc *pd, struct pf_ > ip = mtod(m0, struct ip *); > } > > - rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); > - if (!rtisvalid(rt)) { > - if (r->rt != PF_DUPTO) { > - pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST, > - 0, pd->af, s->rule.ptr, pd->rdomain); > - } > - ipstat_inc(ips_noroute); > - goto bad; > - } > - /* A locally generated packet may have invalid source address. */ > - if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET && > - (ifp->if_flags & IFF_LOOPBACK) == 0) > - ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr; > - > in_proto_cksum_out(m0, ifp); > > if (ntohs(ip->ip_len) <= ifp->if_mtu) { > @@ -6087,9 +6066,9 @@ pf_route(struct pf_pdesc *pd, struct pf_ > */ > if (ip->ip_off & htons(IP_DF)) { > ipstat_inc(ips_cantfrag); > - if (r->rt != PF_DUPTO) > + if (s->rt != PF_DUPTO) > pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, > - ifp->if_mtu, pd->af, r, pd->rdomain); > + ifp->if_mtu, pd->af, s->rule.ptr, pd->rdomain); > goto bad; > } > > @@ -6113,6 +6092,7 @@ pf_route(struct pf_pdesc *pd, struct pf_ > ipstat_inc(ips_fragmented); > > done: > + if_put(ifp); > rtfree(rt); > return; > > @@ -6124,15 +6104,13 @@ bad: > #ifdef INET6 > /* pf_route6() may change pd->m, adjust local copies after calling */ > void > -pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) > +pf_route6(struct pf_pdesc *pd, struct pf_state *s) > { > struct mbuf *m0; > struct sockaddr_in6 *dst, sin6; > struct rtentry *rt = NULL; > struct ip6_hdr *ip6; > struct ifnet *ifp = NULL; > - struct pf_addr naddr; > - struct pf_src_node *sns[PF_SN_MAX]; > struct m_tag *mtag; > unsigned int rtableid; > > @@ -6142,11 +6120,11 @@ pf_route6(struct pf_pdesc *pd, struct pf > return; > } > > - if (r->rt == PF_DUPTO) { > + if (s->rt == PF_DUPTO) { > if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) > return; > } else { > - if ((r->rt == PF_REPLYTO) == (r->direction == pd->dir)) > + if ((s->rt == PF_REPLYTO) == (s->direction == pd->dir)) > return; > m0 = pd->m; > pd->m = NULL; > @@ -6159,74 +6137,59 @@ pf_route6(struct pf_pdesc *pd, struct pf > } > ip6 = mtod(m0, struct ip6_hdr *); > > - memset(&sin6, 0, sizeof(sin6)); > - dst = &sin6; > - dst->sin6_family = AF_INET6; > - dst->sin6_len = sizeof(*dst); > - dst->sin6_addr = ip6->ip6_dst; > - rtableid = m0->m_pkthdr.ph_rtableid; > - > if (pd->dir == PF_IN) { > if (ip6->ip6_hlim <= IPV6_HLIMDEC) { > - if (r->rt != PF_DUPTO) > + if (s->rt != PF_DUPTO) { > pf_send_icmp(m0, ICMP6_TIME_EXCEEDED, > ICMP6_TIME_EXCEED_TRANSIT, 0, > - pd->af, r, pd->rdomain); > + pd->af, s->rule.ptr, pd->rdomain); > + } > goto bad; > } > ip6->ip6_hlim -= IPV6_HLIMDEC; > } > > - if (s == NULL) { > - memset(sns, 0, sizeof(sns)); > - if (pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src, > - &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) { > - DPFPRINTF(LOG_ERR, > - "%s: pf_map_addr() failed", __func__); > - goto bad; > - } > - if (!PF_AZERO(&naddr, AF_INET6)) > - pf_addrcpy((struct pf_addr *)&dst->sin6_addr, > - &naddr, AF_INET6); > - ifp = r->route.kif ? r->route.kif->pfik_ifp : NULL; > - } else { > - if (!PF_AZERO(&s->rt_addr, AF_INET6)) > - pf_addrcpy((struct pf_addr *)&dst->sin6_addr, > - &s->rt_addr, AF_INET6); > - ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; > - } > - if (ifp == NULL) > - goto bad; > - > - if (r->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { > - if (pf_test(AF_INET6, PF_OUT, ifp, &m0) != PF_PASS) > - goto bad; > - else if (m0 == NULL) > - goto done; > - if (m0->m_len < sizeof(struct ip6_hdr)) { > - DPFPRINTF(LOG_ERR, > - "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); > - goto bad; > - } > - } > + memset(&sin6, 0, sizeof(sin6)); > + dst = &sin6; > + dst->sin6_family = AF_INET6; > + dst->sin6_len = sizeof(*dst); > + dst->sin6_addr = s->rt_addr.v6; > + rtableid = m0->m_pkthdr.ph_rtableid; > > if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr)) > dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index); > rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid); > if (!rtisvalid(rt)) { > - if (r->rt != PF_DUPTO) { > + if (s->rt != PF_DUPTO) { > pf_send_icmp(m0, ICMP6_DST_UNREACH, > ICMP6_DST_UNREACH_NOROUTE, 0, > pd->af, s->rule.ptr, pd->rdomain); > - } > + } > ip6stat_inc(ip6s_noroute); > goto bad; > } > + > + ifp = if_get(rt->rt_ifidx); > + if (ifp == NULL) > + goto bad; > + > /* A locally generated packet may have invalid source address. */ > if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) && > (ifp->if_flags & IFF_LOOPBACK) == 0) > ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; > > + if (s->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { > + if (pf_test(AF_INET6, PF_OUT, ifp, &m0) != PF_PASS) > + goto bad; > + else if (m0 == NULL) > + goto done; > + if (m0->m_len < sizeof(struct ip6_hdr)) { > + DPFPRINTF(LOG_ERR, > + "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); > + goto bad; > + } > + } > + > in6_proto_cksum_out(m0, ifp); > > /* > @@ -6239,13 +6202,14 @@ pf_route6(struct pf_pdesc *pd, struct pf > ifp->if_output(ifp, m0, sin6tosa(dst), rt); > } else { > ip6stat_inc(ip6s_cantfrag); > - if (r->rt != PF_DUPTO) > + if (s->rt != PF_DUPTO) > pf_send_icmp(m0, ICMP6_PACKET_TOO_BIG, 0, > - ifp->if_mtu, pd->af, r, pd->rdomain); > + ifp->if_mtu, pd->af, s->rule.ptr, pd->rdomain); > goto bad; > } > > done: > + if_put(ifp); > rtfree(rt); > return; > > @@ -7286,14 +7250,14 @@ done: > pd.m = NULL; > break; > default: > - if (r->rt) { > + if (s && s->rt) { > switch (pd.af) { > case AF_INET: > - pf_route(&pd, r, s); > + pf_route(&pd, s); > break; > #ifdef INET6 > case AF_INET6: > - pf_route6(&pd, r, s); > + pf_route6(&pd, s); > break; > #endif /* INET6 */ > } > Index: sys/net/pfvar.h > =================================================================== > RCS file: /cvs/src/sys/net/pfvar.h,v > retrieving revision 1.498 > diff -u -p -r1.498 pfvar.h > --- sys/net/pfvar.h 12 Jan 2021 00:10:34 -0000 1.498 > +++ sys/net/pfvar.h 28 Jan 2021 11:45:58 -0000 > @@ -762,7 +762,6 @@ struct pf_state { > struct pf_sn_head src_nodes; > struct pf_state_key *key[2]; /* addresses stack and wire */ > struct pfi_kif *kif; > - struct pfi_kif *rt_kif; > u_int64_t packets[2]; > u_int64_t bytes[2]; > int32_t creation; > @@ -797,6 +796,7 @@ struct pf_state { > u_int16_t if_index_out; > pf_refcnt_t refcnt; > u_int16_t delay; > + u_int8_t rt; > }; > > /* > @@ -852,7 +852,7 @@ struct pfsync_state { > u_int8_t proto; > u_int8_t direction; > u_int8_t log; > - u_int8_t pad0; > + u_int8_t rt; > u_int8_t timeout; > u_int8_t sync_flags; > u_int8_t updates; > @@ -1798,8 +1798,8 @@ int pf_state_key_attach(struct pf_state_ > int pf_translate(struct pf_pdesc *, struct pf_addr *, u_int16_t, > struct pf_addr *, u_int16_t, u_int16_t, int); > int pf_translate_af(struct pf_pdesc *); > -void pf_route(struct pf_pdesc *, struct pf_rule *, struct pf_state *); > -void pf_route6(struct pf_pdesc *, struct pf_rule *, struct pf_state *); > +void pf_route(struct pf_pdesc *, struct pf_state *); > +void pf_route6(struct pf_pdesc *, struct pf_state *); > void pf_init_threshold(struct pf_threshold *, u_int32_t, u_int32_t); > int pf_delay_pkt(struct mbuf *, u_int); >