Date: Wed, 16 Oct 2013 09:15:07 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256604 - user/ae/inet6/sys/netinet6 Message-ID: <201310160915.r9G9F7hJ099225@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Wed Oct 16 09:15:07 2013 New Revision: 256604 URL: http://svnweb.freebsd.org/changeset/base/256604 Log: Add handle_nexthop() function to handle IPV6_NEXTHOP advanced socket API option. Modified: user/ae/inet6/sys/netinet6/in6_src.c Modified: user/ae/inet6/sys/netinet6/in6_src.c ============================================================================== --- user/ae/inet6/sys/netinet6/in6_src.c Wed Oct 16 09:12:40 2013 (r256603) +++ user/ae/inet6/sys/netinet6/in6_src.c Wed Oct 16 09:15:07 2013 (r256604) @@ -132,6 +132,8 @@ static int cached_rtlookup(const struct static int check_scopezones(const struct sockaddr_in6 *dst, struct route_in6 *ro, u_int fibnum, const struct ip6_moptions *mopts, const struct in6_addr *src, const struct ifnet *ifp); +static int handle_nexthop(struct ip6po_nhinfo *nh, u_int fibnum, + struct ifnet **ifpp); static int handle_pktinfo(const struct sockaddr_in6 *dst, const struct in6_pktinfo* pi, const struct ip6_moptions *mopts, struct route_in6 *ro, u_int fibnum, struct ifnet **ifpp, @@ -487,6 +489,71 @@ handle_pktinfo(const struct sockaddr_in6 return (0); } +/* + * nh - next hop destination and route; + * fibnum - FIB number. + * ifpp - pointer to outgoing interface. + * + * NOTE: we can keep this route, it will be freed in the socket + * option handling code (see ip6_output.c). + */ +static int +handle_nexthop(struct ip6po_nhinfo *nh, u_int fibnum, struct ifnet **ifpp) +{ + struct sockaddr_in6 *sa; + struct in6_ifaddr *ia; + struct route_in6 *ro; + struct ifnet *ifp, *oifp; + + sa = (struct sockaddr_in6 *)nh->ip6po_nhi_nexthop; + ro = &nh->ip6po_nhi_route; + if (sa->sin6_family != AF_INET6) + return (EAFNOSUPPORT); + /* + * If *ifpp is not NULL, this means that outgoing interface + * was determined in the PKTINFO handling code. + */ + oifp = *ifpp; + + /* + * Check that the next hop address is our own. + */ + ia = in6ifa_ifwithaddr(&sa->sin6_addr, sa->sin6_scope_id); + if (ia != NULL) { + /* Address is our own. */ + ifp = ia->ia_ifp; + ifa_free(&ia->ia_ifa); + } else { + /* + * Address is not our own. + * Determine outgoing interface by zone index. + */ + if (IN6_IS_ADDR_LINKLOCAL(&sa->sin6_addr)) + ifp = in6_getlinkifnet(sa->sin6_scope_id); + else { + if (cached_rtlookup(sa, ro, fibnum) != 0) + return (EHOSTUNREACH); + /* + * The node identified by that address must be a + * neighbor of the sending host. + */ + if (ro->ro_rt->rt_flags & RTF_GATEWAY) + return (EHOSTUNREACH); + ifp = ro->ro_rt->rt_ifp; + } + } + /* + * When the outgoing interface is specified by IPV6_PKTINFO + * as well, the next hop specified by this option must be + * reachable via the specified interface. + */ + if (ifp == NULL || (oifp != NULL && oifp != ifp)) + return (EHOSTUNREACH); + + *ifpp = ifp; + return (0); +} + int in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201310160915.r9G9F7hJ099225>