diff options
Diffstat (limited to 'sys/netinet6/in6_src.c')
-rw-r--r-- | sys/netinet6/in6_src.c | 65 |
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)); } /* |