diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-06-08 12:57:59 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2016-06-08 12:57:59 +0000 |
commit | 0e4aa2a0a717cfcc7c36e8a4f3b7450d5cabc143 (patch) | |
tree | 63a2cc118b54aeabab9a3f039c83e2e3f3605219 | |
parent | d36a5a23b0320264d1da9e01e776af8bea943b6e (diff) |
Move ND resoluton logic from nd6_output() to nd6_storelladdr() and
rename it to nd6_resolve().
This allows us to get rid of non-Ethernet hacks by moving Ethernet
specific logic in the appropriate layer.
ok sthen@
-rw-r--r-- | sys/net/if_ethersubr.c | 6 | ||||
-rw-r--r-- | sys/netinet6/nd6.c | 103 | ||||
-rw-r--r-- | sys/netinet6/nd6.h | 4 |
3 files changed, 44 insertions, 69 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index ba1ffbd9d7c..2aef400a555 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_ethersubr.c,v 1.237 2016/05/31 07:48:19 mpi Exp $ */ +/* $OpenBSD: if_ethersubr.c,v 1.238 2016/06/08 12:57:58 mpi Exp $ */ /* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */ /* @@ -225,9 +225,9 @@ ether_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, break; #ifdef INET6 case AF_INET6: - error = nd6_storelladdr(ifp, rt, m, dst, (u_char *)edst); + error = nd6_resolve(ifp, rt, m, dst, edst); if (error) - return (error); + return (error == EAGAIN ? 0 : error); etype = htons(ETHERTYPE_IPV6); break; #endif diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c index 49cace17d2d..82d5a6b9dbc 100644 --- a/sys/netinet6/nd6.c +++ b/sys/netinet6/nd6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.c,v 1.184 2016/06/06 10:16:23 sthen Exp $ */ +/* $OpenBSD: nd6.c,v 1.185 2016/06/08 12:57:58 mpi Exp $ */ /* $KAME: nd6.c,v 1.280 2002/06/08 19:52:07 itojun Exp $ */ /* @@ -1492,16 +1492,22 @@ int nd6_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr_in6 *dst, struct rtentry *rt0) { - struct mbuf *m = m0; - struct rtentry *rt = rt0; - struct llinfo_nd6 *ln = NULL; - int error = 0; + return (ifp->if_output(ifp, m0, sin6tosa(dst), rt0)); +} - if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr)) - goto sendpkt; +int +nd6_resolve(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, + struct sockaddr *dst, u_char *desten) +{ + struct sockaddr_dl *sdl; + struct rtentry *rt; + struct llinfo_nd6 *ln = NULL; + int error; - if (nd6_need_cache(ifp) == 0) - goto sendpkt; + if (m->m_flags & M_MCAST) { + ETHER_MAP_IPV6_MULTICAST(&satosin6(dst)->sin6_addr, desten); + return (0); + } error = rt_checkgate(rt0, &rt); if (error) { @@ -1524,6 +1530,12 @@ nd6_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr_in6 *dst, return (EINVAL); } + if (rt->rt_gateway->sa_family != AF_LINK) { + printf("%s: something odd happens\n", __func__); + m_freem(m); + return (EINVAL); + } + ln = (struct llinfo_nd6 *)rt->rt_llinfo; KASSERT(ln != NULL); @@ -1553,8 +1565,21 @@ nd6_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr_in6 *dst, * (i.e. its link-layer address is already resolved), just * send the packet. */ - if (ln->ln_state > ND6_LLINFO_INCOMPLETE) - goto sendpkt; + if (ln->ln_state > ND6_LLINFO_INCOMPLETE) { + sdl = satosdl(rt->rt_gateway); + if (sdl->sdl_alen != ETHER_ADDR_LEN) { + char addr[INET6_ADDRSTRLEN]; + log(LOG_DEBUG, "%s: %s: incorrect nd6 information\n", + __func__, + inet_ntop(AF_INET6, &satosin6(dst)->sin6_addr, + addr, sizeof(addr))); + m_freem(m); + return (EINVAL); + } + + bcopy(LLADDR(sdl), desten, sdl->sdl_alen); + return (0); + } /* * There is a neighbor cache entry, but no ethernet address @@ -1565,6 +1590,7 @@ nd6_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr_in6 *dst, ln->ln_state = ND6_LLINFO_INCOMPLETE; m_freem(ln->ln_hold); ln->ln_hold = m; + /* * If there has been no NS for the neighbor after entering the * INCOMPLETE state, send the first solicitation. @@ -1572,13 +1598,9 @@ nd6_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr_in6 *dst, if (!ND6_LLINFO_PERMANENT(ln) && ln->ln_asked == 0) { ln->ln_asked++; nd6_llinfo_settimer(ln, ND_IFINFO(ifp)->retrans / 1000); - nd6_ns_output(ifp, NULL, &dst->sin6_addr, ln, 0); + nd6_ns_output(ifp, NULL, &satosin6(dst)->sin6_addr, ln, 0); } - return (0); - - sendpkt: - error = ifp->if_output(ifp, m, sin6tosa(dst), rt); - return (error); + return (EAGAIN); } int @@ -1598,53 +1620,6 @@ nd6_need_cache(struct ifnet *ifp) } } -int -nd6_storelladdr(struct ifnet *ifp, struct rtentry *rt0, struct mbuf *m, - struct sockaddr *dst, u_char *desten) -{ - struct sockaddr_dl *sdl; - struct rtentry *rt; - int error; - - if (m->m_flags & M_MCAST) { - switch (ifp->if_type) { - case IFT_ETHER: - case IFT_CARP: - ETHER_MAP_IPV6_MULTICAST(&satosin6(dst)->sin6_addr, - desten); - return (0); - break; - default: - m_freem(m); - return (EINVAL); - } - } - - error = rt_checkgate(rt0, &rt); - if (error) { - m_freem(m); - return (error); - } - - if (rt->rt_gateway->sa_family != AF_LINK) { - printf("%s: something odd happens\n", __func__); - m_freem(m); - return (EINVAL); - } - sdl = satosdl(rt->rt_gateway); - if (sdl->sdl_alen != ETHER_ADDR_LEN) { - char addr[INET6_ADDRSTRLEN]; - log(LOG_DEBUG, "%s: %s: incorrect nd6 information\n", __func__, - inet_ntop(AF_INET6, &satosin6(dst)->sin6_addr, - addr, sizeof(addr))); - m_freem(m); - return (EINVAL); - } - - bcopy(LLADDR(sdl), desten, sdl->sdl_alen); - return (0); -} - /* * oldp - syscall arg, need copyout * newp - syscall arg, need copyin diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h index 892785d2dff..feaf704d139 100644 --- a/sys/netinet6/nd6.h +++ b/sys/netinet6/nd6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: nd6.h,v 1.60 2016/06/01 23:45:19 dlg Exp $ */ +/* $OpenBSD: nd6.h,v 1.61 2016/06/08 12:57:58 mpi Exp $ */ /* $KAME: nd6.h,v 1.95 2002/06/08 11:31:06 itojun Exp $ */ /* @@ -271,7 +271,7 @@ int nd6_ioctl(u_long, caddr_t, struct ifnet *); void nd6_cache_lladdr(struct ifnet *, struct in6_addr *, char *, int, int, int); int nd6_output(struct ifnet *, struct mbuf *, struct sockaddr_in6 *, struct rtentry *); -int nd6_storelladdr(struct ifnet *, struct rtentry *, struct mbuf *, +int nd6_resolve(struct ifnet *, struct rtentry *, struct mbuf *, struct sockaddr *, u_char *); int nd6_sysctl(int, void *, size_t *, void *, size_t); int nd6_need_cache(struct ifnet *); |