summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6_src.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet6/in6_src.c')
-rw-r--r--sys/netinet6/in6_src.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/netinet6/in6_src.c b/sys/netinet6/in6_src.c
index ea302a5..49bc715 100644
--- a/sys/netinet6/in6_src.c
+++ b/sys/netinet6/in6_src.c
@@ -122,12 +122,11 @@ static struct sx addrsel_sxlock;
#define ADDRSEL_XUNLOCK() sx_xunlock(&addrsel_sxlock)
#define ADDR_LABEL_NOTAPP (-1)
-
static VNET_DEFINE(struct in6_addrpolicy, defaultaddrpolicy);
-VNET_DEFINE(int, ip6_prefer_tempaddr);
-
#define V_defaultaddrpolicy VNET(defaultaddrpolicy)
+VNET_DEFINE(int, ip6_prefer_tempaddr) = 0;
+
static int selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
struct ip6_moptions *, struct route_in6 *, struct ifnet **,
struct rtentry **, int));
@@ -182,7 +181,7 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
struct ifnet **ifpp, struct in6_addr *srcp)
{
- struct in6_addr dst;
+ struct in6_addr dst, tmp;
struct ifnet *ifp = NULL;
struct in6_ifaddr *ia = NULL, *ia_best = NULL;
struct in6_pktinfo *pi = NULL;
@@ -326,10 +325,9 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
if (!V_ip6_use_deprecated && IFA6_IS_DEPRECATED(ia))
continue;
+ /* If jailed only take addresses of the jail into account. */
if (cred != NULL &&
- prison_local_ip6(cred, &ia->ia_addr.sin6_addr,
- (inp != NULL &&
- (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0)
+ prison_check_ip6(cred, &ia->ia_addr.sin6_addr) != 0)
continue;
/* Rule 1: Prefer same address */
@@ -476,10 +474,26 @@ in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
return (EADDRNOTAVAIL);
}
+ /*
+ * At this point at least one of the addresses belonged to the jail
+ * but it could still be, that we want to further restrict it, e.g.
+ * theoratically IN6_IS_ADDR_LOOPBACK.
+ * It must not be IN6_IS_ADDR_UNSPECIFIED anymore.
+ * prison_local_ip6() will fix an IN6_IS_ADDR_LOOPBACK but should
+ * let all others previously selected pass.
+ * Use tmp to not change ::1 on lo0 to the primary jail address.
+ */
+ tmp = ia->ia_addr.sin6_addr;
+ if (cred != NULL && prison_local_ip6(cred, &tmp, (inp != NULL &&
+ (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0)) != 0) {
+ IN6_IFADDR_RUNLOCK();
+ return (EADDRNOTAVAIL);
+ }
+
if (ifpp)
*ifpp = ifp;
- bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp));
+ bcopy(&tmp, srcp, sizeof(*srcp));
IN6_IFADDR_RUNLOCK();
return (0);
}
@@ -937,8 +951,6 @@ void
addrsel_policy_init(void)
{
- V_ip6_prefer_tempaddr = 0;
-
init_policy_queue();
/* initialize the "last resort" policy */
OpenPOWER on IntegriCloud