[prev in list] [next in list] [prev in thread] [next in thread]
List: openbsd-tech
Subject: Re: pf: route-to IPs, not interfaces
From: Alexander Bluhm <alexander.bluhm () gmx ! net>
Date: 2021-01-28 21:45:54
Message-ID: YBMwkgUz8Jqt+Hvd () t430s ! bluhm ! invalid
[Download RAW message or body]
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);
>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic