summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6_src.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/in6_src.c')
-rw-r--r--sys/netinet6/in6_src.c65
1 files changed, 45 insertions, 20 deletions
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index 4d7723a..c343634 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -87,6 +87,7 @@ __FBSDID("$FreeBSD$");
#include <net/if.h>
#include <net/route.h>
+#include <net/if_llatbl.h>
#ifdef RADIX_MPATH
#include <net/radix_mpath.h>
#endif
@@ -131,7 +132,7 @@ int ip6_prefer_tempaddr;
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
- struct rtentry **, int, int));
+ struct rtentry **, int));
static int in6_selectif __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *ro, struct ifnet **));
@@ -479,8 +480,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
static int
selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone,
- int norouteok)
+ struct ifnet **retifp, struct rtentry **retrt, int norouteok)
{
INIT_VNET_INET6(curvnet);
int error = 0;
@@ -536,9 +536,10 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*/
if (opts && opts->ip6po_nexthop) {
struct route_in6 *ron;
-
+ struct llentry *la;
+
sin6_next = satosin6(opts->ip6po_nexthop);
-
+
/* at this moment, we only support AF_INET6 next hops */
if (sin6_next->sin6_family != AF_INET6) {
error = EAFNOSUPPORT; /* or should we proceed? */
@@ -550,6 +551,36 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
* by that address must be a neighbor of the sending host.
*/
ron = &opts->ip6po_nextroute;
+ /*
+ * XXX what do we do here?
+ * PLZ to be fixing
+ */
+
+
+ if (ron->ro_rt == NULL) {
+ rtalloc((struct route *)ron); /* multi path case? */
+ if (ron->ro_rt == NULL) {
+ if (ron->ro_rt) {
+ RTFREE(ron->ro_rt);
+ ron->ro_rt = NULL;
+ }
+ error = EHOSTUNREACH;
+ goto done;
+ }
+ }
+
+ rt = ron->ro_rt;
+ ifp = rt->rt_ifp;
+ IF_AFDATA_LOCK(ifp);
+ la = lla_lookup(LLTABLE6(ifp), 0, (struct sockaddr *)&sin6_next->sin6_addr);
+ IF_AFDATA_UNLOCK(ifp);
+ if (la)
+ LLE_RUNLOCK(la);
+ else {
+ error = EHOSTUNREACH;
+ goto done;
+ }
+#if 0
if ((ron->ro_rt &&
(ron->ro_rt->rt_flags & (RTF_UP | RTF_LLINFO)) !=
(RTF_UP | RTF_LLINFO)) ||
@@ -573,16 +604,14 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
goto done;
}
}
- rt = ron->ro_rt;
- ifp = rt->rt_ifp;
+#endif
/*
* When cloning is required, try to allocate a route to the
* destination so that the caller can store path MTU
* information.
*/
- if (!clone)
- goto done;
+ goto done;
}
/*
@@ -608,21 +637,17 @@ selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
*sa6 = *dstsock;
sa6->sin6_scope_id = 0;
- if (clone) {
#ifdef RADIX_MPATH
rtalloc_mpath((struct route *)ro,
ntohl(sa6->sin6_addr.s6_addr32[3]));
-#else
- rtalloc((struct route *)ro);
-#endif
- } else {
+#else
ro->ro_rt = rtalloc1(&((struct route *)ro)
- ->ro_dst, 0, 0UL);
+ ->ro_dst, 0, 0UL);
if (ro->ro_rt)
RT_UNLOCK(ro->ro_rt);
- }
+#endif
}
-
+
/*
* do not care about the result if we have the nexthop
* explicitly specified.
@@ -693,7 +718,7 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
}
if ((error = selectroute(dstsock, opts, mopts, ro, retifp,
- &rt, 0, 1)) != 0) {
+ &rt, 1)) != 0) {
if (ro == &sro && rt && rt == sro.ro_rt)
RTFREE(rt);
return (error);
@@ -745,11 +770,11 @@ in6_selectif(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
int
in6_selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct ip6_moptions *mopts, struct route_in6 *ro,
- struct ifnet **retifp, struct rtentry **retrt, int clone)
+ struct ifnet **retifp, struct rtentry **retrt)
{
return (selectroute(dstsock, opts, mopts, ro, retifp,
- retrt, clone, 0));
+ retrt, 0));
}
/*
OpenPOWER on IntegriCloud