[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