Date: Wed, 16 Oct 2013 09:02:11 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r256600 - user/ae/inet6/sys/netinet6 Message-ID: <201310160902.r9G92BnT092776@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Wed Oct 16 09:02:11 2013 New Revision: 256600 URL: http://svnweb.freebsd.org/changeset/base/256600 Log: Add check_scopezones() function to check that source address doesn't break destination scope zone. 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 08:58:58 2013 (r256599) +++ user/ae/inet6/sys/netinet6/in6_src.c Wed Oct 16 09:02:11 2013 (r256600) @@ -129,6 +129,9 @@ VNET_DEFINE(int, ip6_prefer_tempaddr) = static int cached_rtlookup(const struct sockaddr_in6 *dst, struct route_in6 *ro, u_int fibnum); +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 selectroute(struct sockaddr_in6 *, struct ip6_pktopts *, struct ip6_moptions *, struct route_in6 *, struct ifnet **, @@ -324,6 +327,38 @@ cached_rtlookup(const struct sockaddr_in return (0); } +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) +{ + struct ifnet *oifp; + + oifp = NULL; + /* Determine zone index of destination address. */ + if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr) || + IN6_IS_ADDR_MC_INTFACELOCAL(&dst->sin6_addr)) { + if (dst->sin6_scope_id == 0) + return (EHOSTUNREACH); + oifp = in6_getlinkifnet(dst->sin6_scope_id); + } else if (IN6_IS_ADDR_MULTICAST(&dst->sin6_addr) && + mopts != NULL && mopts->im6o_multicast_ifp != NULL) { + oifp = mopts->im6o_multicast_ifp; + } else { + if (cached_rtlookup(dst, ro, fibnum) == 0) + oifp = ro->ro_rt->rt_ifp; + } + if (oifp == NULL) + return (EHOSTUNREACH); + + if (oifp != ifp && + in6_getscopezone(ifp, in6_srcaddrscope(src)) != + in6_getscopezone(oifp, in6_srcaddrscope(&dst->sin6_addr))) + return (EHOSTUNREACH); + + 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?201310160902.r9G92BnT092776>