summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2016-06-08 12:57:59 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2016-06-08 12:57:59 +0000
commit0e4aa2a0a717cfcc7c36e8a4f3b7450d5cabc143 (patch)
tree63a2cc118b54aeabab9a3f039c83e2e3f3605219
parentd36a5a23b0320264d1da9e01e776af8bea943b6e (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.c6
-rw-r--r--sys/netinet6/nd6.c103
-rw-r--r--sys/netinet6/nd6.h4
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 *);