-/* $OpenBSD: parse.y,v 1.708 2021/01/12 00:10:34 bluhm Exp $ */
+/* $OpenBSD: parse.y,v 1.709 2021/02/01 00:31:04 dlg Exp $ */
/*
* Copyright (c) 2001 Markus Friedl. All rights reserved.
struct redirspec nat;
struct redirspec rdr;
struct redirspec rroute;
+ u_int8_t rt;
/* scrub opts */
int nodf;
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;
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 *,
%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
YYERROR;
}
- if ($9.route.rt) {
+ if ($9.rt) {
yyerror("cannot specify route handling "
"on anchors");
YYERROR;
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))
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;
- }
- | 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;
+ | ROUTETO routespec {
+ filter_opts.rt = PF_ROUTETO;
+ }
+ | REPLYTO routespec {
+ filter_opts.rt = PF_REPLYTO;
+ }
+ | DUPTO routespec {
+ filter_opts.rt = PF_DUPTO;
}
| not RECEIVEDON if_item {
if (filter_opts.rcv) {
}
;
-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");
+routespec : redirspec pool_opts {
+ struct redirection *redir;
+ if (filter_opts.rt != PF_NOPFROUTE) {
+ yyerror("cannot respecify "
+ "route-to/reply-to/dup-to");
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");
- 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
yyerror("keep state is great, but only for pass rules");
problems++;
}
+ if (r->rt && !r->keep_state) {
+ yyerror("route-to, reply-to and dup-to require keep state");
+ problems++;
+ }
if (r->rule_flag & PFRULE_STATESLOPPY &&
(r->keep_state == PF_STATE_MODULATE ||
r->keep_state == PF_STATE_SYNPROXY)) {
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;
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 */
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 */
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);
}
}
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,
"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) {
r->af = af;
if (!naddr) {
yyerror("af mismatch in %s spec",
- allow_if ? "routing" : "translation");
+ routing ? "routing" : "translation");
return (1);
}
if (tbl) {
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);
-/* $OpenBSD: pfctl_parser.c,v 1.345 2021/01/12 00:10:34 bluhm Exp $ */
+/* $OpenBSD: pfctl_parser.c,v 1.346 2021/02/01 00:31:04 dlg Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
{
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) {
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;
-.\" $OpenBSD: pf.conf.5,v 1.585 2020/12/07 08:29:41 sashan Exp $
+.\" $OpenBSD: pf.conf.5,v 1.586 2021/02/01 00:31:04 dlg Exp $
.\"
.\" Copyright (c) 2002, Daniel Hartmeier
.\" Copyright (c) 2003 - 2013 Henning Brauer <henning@openbsd.org>
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd $Mdocdate: December 7 2020 $
+.Dd $Mdocdate: February 1 2021 $
.Dt PF.CONF 5
.Os
.Sh NAME
.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
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 |
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 ) ]
-/* $OpenBSD: if_pfsync.c,v 1.281 2021/01/18 18:29:19 mvs Exp $ */
+/* $OpenBSD: if_pfsync.c,v 1.282 2021/02/01 00:31:05 dlg Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff
/* 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)) {
st->rule.ptr = r;
st->anchor.ptr = NULL;
- st->rt_kif = NULL;
st->pfsync_time = getuptime();
st->sync_state = PFSYNC_S_NONE;
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) {
}
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:
-/* $OpenBSD: pf.c,v 1.1105 2021/01/28 09:37:20 dlg Exp $ */
+/* $OpenBSD: pf.c,v 1.1106 2021/02/01 00:31:05 dlg Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
/* 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);
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);
}
/* 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;
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;
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)
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) {
*/
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;
}
ipstat_inc(ips_fragmented);
done:
+ if_put(ifp);
rtfree(rt);
return;
#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;
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;
}
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);
/*
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;
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 */
}
-/* $OpenBSD: pfvar.h,v 1.498 2021/01/12 00:10:34 bluhm Exp $ */
+/* $OpenBSD: pfvar.h,v 1.499 2021/02/01 00:31:05 dlg Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
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;
u_int16_t if_index_out;
pf_refcnt_t refcnt;
u_int16_t delay;
+ u_int8_t rt;
};
/*
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;
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);