summaryrefslogtreecommitdiff
path: root/sys/net/if_ethersubr.c
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2019-02-20 00:03:16 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2019-02-20 00:03:16 +0000
commit0c91eda49c62127a36ca61e2b67e5b576cfbfae1 (patch)
treea9cc3cf53bb1bc98da72032198ff4e0abd86ea1b /sys/net/if_ethersubr.c
parent214fed708bee6aa6e7f834f2567cc84a6d98d0fa (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.c13
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);