From owner-svn-src-user@FreeBSD.ORG Wed Oct 16 09:15:07 2013 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id D7887EA1; Wed, 16 Oct 2013 09:15:07 +0000 (UTC) (envelope-from ae@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id B63F52D6C; Wed, 16 Oct 2013 09:15:07 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9G9F7PA099226; Wed, 16 Oct 2013 09:15:07 GMT (envelope-from ae@svn.freebsd.org) Received: (from ae@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9G9F7hJ099225; Wed, 16 Oct 2013 09:15:07 GMT (envelope-from ae@svn.freebsd.org) Message-Id: <201310160915.r9G9F7hJ099225@svn.freebsd.org> From: "Andrey V. Elsukov" Date: Wed, 16 Oct 2013 09:15:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256604 - user/ae/inet6/sys/netinet6 X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 16 Oct 2013 09:15:08 -0000 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,