diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2019-02-20 00:03:16 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2019-02-20 00:03:16 +0000 |
commit | 0c91eda49c62127a36ca61e2b67e5b576cfbfae1 (patch) | |
tree | a9cc3cf53bb1bc98da72032198ff4e0abd86ea1b /sys/net/if_ethersubr.c | |
parent | 214fed708bee6aa6e7f834f2567cc84a6d98d0fa (diff) |
make ether_output with AF_MPLS use a routes gateway address if available
sending an MPLS frame is weird compared to other address families.
other families figure out and pass the address on the local link
for ether_output to use for resolution, but AF_MPLS basically passes
a dummy sockaddr so ether_output can get the ethernet protocol field
right. ether_output then has to pull the route apart to figure out
which address and family to use for address resolution on the local
net. eg, MPLS tagged routes via ip addresess need to pull the route
apart and get at the AF_INET sockaddr to pass to arpresolve. that
code currently uses the destination address of the route, but if
that destination is not on the local network, we'd end up using it
for arp requests that don't work.
this change uses the rt_gateway sockaddr if RTF_GATEWAY is set.
this solves the problem in my testing and doesn't seem to break
other uses cases ive tried.
reported by adrian close via bugs@
ok deraadt@ claudio@
Diffstat (limited to 'sys/net/if_ethersubr.c')
-rw-r--r-- | sys/net/if_ethersubr.c | 13 |
1 files changed, 5 insertions, 8 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index 4b16785a71f..55ef9d67fec 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.258 2019/02/18 03:41:21 dlg Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.259 2019/02/20 00:03:15 dlg Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -235,19 +235,16 @@ ether_resolve(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, #endif #ifdef MPLS case AF_MPLS: - if (rt) - dst = rt_key(rt); - else + if (rt == NULL) senderr(EHOSTUNREACH); if (!ISSET(ifp->if_xflags, IFXF_MPLS)) senderr(ENETUNREACH); - af = dst->sa_family; - if (af == AF_MPLS) - af = rt->rt_gateway->sa_family; + dst = ISSET(rt->rt_flags, RTF_GATEWAY) ? + rt->rt_gateway : rt_key(rt); - switch (af) { + switch (dst->sa_family) { case AF_LINK: if (satosdl(dst)->sdl_alen < sizeof(eh->ether_dhost)) senderr(EHOSTUNREACH); |