diff options
| author | Bjoern A. Zeeb <bz@FreeBSD.org> | 2009-02-07 13:19:08 +0000 |
|---|---|---|
| committer | Bjoern A. Zeeb <bz@FreeBSD.org> | 2009-02-07 13:19:08 +0000 |
| commit | da0bebf915b0494f2279c47f43f36c94f7d2fff5 (patch) | |
| tree | 13c112004187522aaadada0f39d777757c44b187 /sys/netinet6/in6_src.c | |
| parent | 75b76418f23497322f5811ce92d1ca971abb80f9 (diff) | |
Notes
Diffstat (limited to 'sys/netinet6/in6_src.c')
| -rw-r--r-- | sys/netinet6/in6_src.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c index ec813402a359..e0358b0a4010 100644 --- a/sys/netinet6/in6_src.c +++ b/sys/netinet6/in6_src.c @@ -79,6 +79,7 @@ __FBSDID("$FreeBSD$"); #include <sys/sysctl.h> #include <sys/errno.h> #include <sys/time.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/sx.h> @@ -224,6 +225,11 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (*errorp != 0) return (NULL); } + if (cred != NULL && prison_local_ip6(cred, &srcsock.sin6_addr, + (inp != NULL && (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { + *errorp = EADDRNOTAVAIL; + return (NULL); + } ia6 = (struct in6_ifaddr *)ifa_ifwithaddr((struct sockaddr *)(&srcsock)); if (ia6 == NULL || @@ -241,6 +247,11 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, * Otherwise, if the socket has already bound the source, just use it. */ if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { + if (cred != NULL && prison_local_ip6(cred, &inp->in6p_laddr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) { + *errorp = EADDRNOTAVAIL; + return (NULL); + } return (&inp->in6p_laddr); } @@ -292,6 +303,12 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, if (!ip6_use_deprecated && IFA6_IS_DEPRECATED(ia)) continue; + if (cred != NULL && + prison_local_ip6(cred, &ia->ia_addr.sin6_addr, + (inp != NULL && + (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) + continue; + /* Rule 1: Prefer same address */ if (IN6_ARE_ADDR_EQUAL(&dst, &ia->ia_addr.sin6_addr)) { ia_best = ia; @@ -765,6 +782,10 @@ in6_pcbsetport(struct in6_addr *laddr, struct inpcb *inp, struct ucred *cred) INP_INFO_WLOCK_ASSERT(pcbinfo); INP_WLOCK_ASSERT(inp); + if (prison_local_ip6(cred, laddr, + ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) + return(EINVAL); + /* XXX: this is redundant when called from in6_pcbbind */ if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0) wild = INPLOOKUP_WILDCARD; |
