Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 Jan 2010 10:08:54 +0000 (UTC)
From:      "Bjoern A. Zeeb" <bz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r202914 - in stable/7/sys: netinet netinet6
Message-ID:  <201001241008.o0OA8sZ0092388@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: bz
Date: Sun Jan 24 10:08:54 2010
New Revision: 202914
URL: http://svn.freebsd.org/changeset/base/202914

Log:
  MFC r194777:
  
    Make callers to in6_selectsrc() and in6_pcbladdr() pass in memory
    to save the selected source address rather than returning an
    unreferenced copy to a pointer that might long be gone by the
    time we use the pointer for anything meaningful.
  
    Asked for by:	rwatson
    Reviewed by:		rwatson
  
  Approved by:	re (kensmith)

Modified:
  stable/7/sys/netinet/tcp_usrreq.c
  stable/7/sys/netinet6/icmp6.c
  stable/7/sys/netinet6/in6_pcb.c
  stable/7/sys/netinet6/in6_pcb.h
  stable/7/sys/netinet6/in6_src.c
  stable/7/sys/netinet6/ip6_var.h
  stable/7/sys/netinet6/nd6_nbr.c
  stable/7/sys/netinet6/raw_ip6.c
  stable/7/sys/netinet6/udp6_usrreq.c
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/netinet/tcp_usrreq.c
==============================================================================
--- stable/7/sys/netinet/tcp_usrreq.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet/tcp_usrreq.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -1111,7 +1111,7 @@ tcp6_connect(struct tcpcb *tp, struct so
 	struct inpcb *inp = tp->t_inpcb, *oinp;
 	struct socket *so = inp->inp_socket;
 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
-	struct in6_addr *addr6;
+	struct in6_addr addr6;
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(&tcbinfo);
@@ -1135,13 +1135,13 @@ tcp6_connect(struct tcpcb *tp, struct so
 	oinp = in6_pcblookup_hash(inp->inp_pcbinfo,
 				  &sin6->sin6_addr, sin6->sin6_port,
 				  IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
-				  ? addr6
+				  ? &addr6
 				  : &inp->in6p_laddr,
 				  inp->inp_lport,  0, NULL);
 	if (oinp)
 		return EADDRINUSE;
 	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
-		inp->in6p_laddr = *addr6;
+		inp->in6p_laddr = addr6;
 	inp->in6p_faddr = sin6->sin6_addr;
 	inp->inp_fport = sin6->sin6_port;
 	/* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */

Modified: stable/7/sys/netinet6/icmp6.c
==============================================================================
--- stable/7/sys/netinet6/icmp6.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/icmp6.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -2032,7 +2032,7 @@ icmp6_reflect(struct mbuf *m, size_t off
 	int plen;
 	int type, code;
 	struct ifnet *outif = NULL;
-	struct in6_addr origdst, *src = NULL;
+	struct in6_addr origdst, src, *srcp = NULL;
 
 	/* too short to reflect */
 	if (off < sizeof(struct ip6_hdr)) {
@@ -2100,7 +2100,7 @@ icmp6_reflect(struct mbuf *m, size_t off
 		if ((ia = ip6_getdstifaddr(m))) {
 			if (!(ia->ia6_flags &
 			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY)))
-				src = &ia->ia_addr.sin6_addr;
+				srcp = &ia->ia_addr.sin6_addr;
 		} else {
 			struct sockaddr_in6 d;
 
@@ -2113,12 +2113,12 @@ icmp6_reflect(struct mbuf *m, size_t off
 			if (ia &&
 			    !(ia->ia6_flags &
 			    (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY))) {
-				src = &ia->ia_addr.sin6_addr;
+				srcp = &ia->ia_addr.sin6_addr;
 			}
 		}
 	}
 
-	if (src == NULL) {
+	if (srcp == NULL) {
 		int e;
 		struct sockaddr_in6 sin6;
 		struct route_in6 ro;
@@ -2134,10 +2134,10 @@ icmp6_reflect(struct mbuf *m, size_t off
 		sin6.sin6_addr = ip6->ip6_dst; /* zone ID should be embedded */
 
 		bzero(&ro, sizeof(ro));
-		src = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &e);
+		e = in6_selectsrc(&sin6, NULL, NULL, &ro, NULL, &outif, &src);
 		if (ro.ro_rt)
 			RTFREE(ro.ro_rt); /* XXX: we could use this */
-		if (src == NULL) {
+		if (e) {
 			char ip6buf[INET6_ADDRSTRLEN];
 			nd6log((LOG_DEBUG,
 			    "icmp6_reflect: source can't be determined: "
@@ -2145,9 +2145,10 @@ icmp6_reflect(struct mbuf *m, size_t off
 			    ip6_sprintf(ip6buf, &sin6.sin6_addr), e));
 			goto bad;
 		}
+		srcp = &src;
 	}
 
-	ip6->ip6_src = *src;
+	ip6->ip6_src = *srcp;
 	ip6->ip6_flow = 0;
 	ip6->ip6_vfc &= ~IPV6_VERSION_MASK;
 	ip6->ip6_vfc |= IPV6_VERSION;

Modified: stable/7/sys/netinet6/in6_pcb.c
==============================================================================
--- stable/7/sys/netinet6/in6_pcb.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/in6_pcb.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -278,12 +278,13 @@ in6_pcbbind(register struct inpcb *inp, 
  */
 int
 in6_pcbladdr(register struct inpcb *inp, struct sockaddr *nam,
-    struct in6_addr **plocal_addr6)
+    struct in6_addr *plocal_addr6)
 {
 	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
 	int error = 0;
 	struct ifnet *ifp = NULL;
 	int scope_ambiguous = 0;
+	struct in6_addr in6a;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
 	INP_WLOCK_ASSERT(inp);
@@ -311,25 +312,25 @@ in6_pcbladdr(register struct inpcb *inp,
 	if ((error = prison_remote_ip6(inp->inp_cred, &sin6->sin6_addr)) != 0)
 		return (error);
 
-	/*
-	 * XXX: in6_selectsrc might replace the bound local address
-	 * with the address specified by setsockopt(IPV6_PKTINFO).
-	 * Is it the intended behavior?
-	 */
-	*plocal_addr6 = in6_selectsrc(sin6, inp->in6p_outputopts,
-				      inp, NULL,
-				      inp->inp_cred,
-				      &ifp, &error);
+	error = in6_selectsrc(sin6, inp->in6p_outputopts,
+	    inp, NULL, inp->inp_cred, &ifp, &in6a);
+	if (error)
+		return (error);
+
 	if (ifp && scope_ambiguous &&
 	    (error = in6_setscope(&sin6->sin6_addr, ifp, NULL)) != 0) {
 		return(error);
 	}
 
-	if (*plocal_addr6 == NULL) {
-		if (error == 0)
-			error = EADDRNOTAVAIL;
-		return (error);
-	}
+	/*
+	 * Do not update this earlier, in case we return with an error.
+	 *
+	 * XXX: this in6_selectsrc result might replace the bound local
+	 * aaddress with the address specified by setsockopt(IPV6_PKTINFO).
+	 * Is it the intended behavior?
+	 */
+	*plocal_addr6 = in6a;
+
 	/*
 	 * Don't do pcblookup call here; return interface in
 	 * plocal_addr6
@@ -350,8 +351,8 @@ int
 in6_pcbconnect(register struct inpcb *inp, struct sockaddr *nam,
     struct ucred *cred)
 {
-	struct in6_addr *addr6;
 	register struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
+	struct in6_addr addr6;
 	int error;
 
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
@@ -367,7 +368,7 @@ in6_pcbconnect(register struct inpcb *in
 	if (in6_pcblookup_hash(inp->inp_pcbinfo, &sin6->sin6_addr,
 			       sin6->sin6_port,
 			      IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
-			      ? addr6 : &inp->in6p_laddr,
+			      ? &addr6 : &inp->in6p_laddr,
 			      inp->inp_lport, 0, NULL) != NULL) {
 		return (EADDRINUSE);
 	}
@@ -377,7 +378,7 @@ in6_pcbconnect(register struct inpcb *in
 			if (error)
 				return (error);
 		}
-		inp->in6p_laddr = *addr6;
+		inp->in6p_laddr = addr6;
 	}
 	inp->in6p_faddr = sin6->sin6_addr;
 	inp->inp_fport = sin6->sin6_port;

Modified: stable/7/sys/netinet6/in6_pcb.h
==============================================================================
--- stable/7/sys/netinet6/in6_pcb.h	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/in6_pcb.h	Sun Jan 24 10:08:54 2010	(r202914)
@@ -74,8 +74,7 @@ void	in6_losing __P((struct inpcb *));
 int	in6_pcbbind __P((struct inpcb *, struct sockaddr *, struct ucred *));
 int	in6_pcbconnect __P((struct inpcb *, struct sockaddr *, struct ucred *));
 void	in6_pcbdisconnect __P((struct inpcb *));
-int	in6_pcbladdr __P((struct inpcb *, struct sockaddr *,
-			  struct in6_addr **));
+int	in6_pcbladdr(struct inpcb *, struct sockaddr *, struct in6_addr *);
 struct	inpcb *
 	in6_pcblookup_local __P((struct inpcbinfo *,
 				 struct in6_addr *, u_short, int,

Modified: stable/7/sys/netinet6/in6_src.c
==============================================================================
--- stable/7/sys/netinet6/in6_src.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/in6_src.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -168,10 +168,10 @@ static struct in6_addrpolicy *match_addr
 	goto out;		/* XXX: we can't use 'break' here */ \
 } while(0)
 
-struct in6_addr *
+int
 in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts,
     struct inpcb *inp, struct route_in6 *ro, struct ucred *cred,
-    struct ifnet **ifpp, int *errorp)
+    struct ifnet **ifpp, struct in6_addr *srcp)
 {
 	struct in6_addr dst;
 	struct ifnet *ifp = NULL;
@@ -181,10 +181,12 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 	struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL;
 	u_int32_t odstzone;
 	int prefer_tempaddr;
+	int error;
 	struct ip6_moptions *mopts;
 
+	KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__));
+
 	dst = dstsock->sin6_addr; /* make a copy for local operation */
-	*errorp = 0;
 	if (ifpp)
 		*ifpp = NULL;
 
@@ -207,10 +209,8 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 		struct in6_ifaddr *ia6;
 
 		/* get the outgoing interface */
-		if ((*errorp = in6_selectif(dstsock, opts, mopts, ro, &ifp))
-		    != 0) {
-			return (NULL);
-		}
+		if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0)
+			return (error);
 
 		/*
 		 * determine the appropriate zone id of the source based on
@@ -224,25 +224,25 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 		srcsock.sin6_len = sizeof(srcsock);
 		srcsock.sin6_addr = pi->ipi6_addr;
 		if (ifp) {
-			*errorp = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
-			if (*errorp != 0)
-				return (NULL);
+			error = in6_setscope(&srcsock.sin6_addr, ifp, NULL);
+			if (error)
+				return (error);
 		}
-		if (cred != NULL && (*errorp = prison_local_ip6(cred,
+		if (cred != NULL && (error = prison_local_ip6(cred,
 		    &srcsock.sin6_addr, (inp != NULL &&
 		    (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
-			return (NULL);
+			return (error);
 
 		ia6 = (struct in6_ifaddr *)ifa_ifwithaddr((struct sockaddr *)(&srcsock));
 		if (ia6 == NULL ||
 		    (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) {
-			*errorp = EADDRNOTAVAIL;
-			return (NULL);
+			return (EADDRNOTAVAIL);
 		}
 		pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */
 		if (ifpp)
 			*ifpp = ifp;
-		return (&ia6->ia_addr.sin6_addr);
+		bcopy(&ia6->ia_addr.sin6_addr, srcp, sizeof(*srcp));
+		return (0);
 	}
 
 	/*
@@ -250,10 +250,11 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 	 */
 	if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) {
 		if (cred != NULL &&
-		    (*errorp = prison_local_ip6(cred, &inp->in6p_laddr,
+		    (error = prison_local_ip6(cred, &inp->in6p_laddr,
 		    ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0)
-			return (NULL);
-		return (&inp->in6p_laddr);
+			return (error);
+		bcopy(&inp->in6p_laddr, srcp, sizeof(*srcp));
+		return (0);
 	}
 
 	/*
@@ -261,16 +262,16 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 	 * the outgoing interface and the destination address.
 	 */
 	/* get the outgoing interface */
-	if ((*errorp = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0)
-		return (NULL);
+	if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0)
+		return (error);
 
 #ifdef DIAGNOSTIC
 	if (ifp == NULL)	/* this should not happen */
 		panic("in6_selectsrc: NULL ifp");
 #endif
-	*errorp = in6_setscope(&dst, ifp, &odstzone);
-	if (*errorp != 0)
-		return (NULL);
+	error = in6_setscope(&dst, ifp, &odstzone);
+	if (error)
+		return (error);
 
 	for (ia = in6_ifaddr; ia; ia = ia->ia_next) {
 		int new_scope = -1, new_matchlen = -1;
@@ -449,15 +450,14 @@ in6_selectsrc(struct sockaddr_in6 *dstso
 		break;
 	}
 
-	if ((ia = ia_best) == NULL) {
-		*errorp = EADDRNOTAVAIL;
-		return (NULL);
-	}
+	if ((ia = ia_best) == NULL)
+		return (EADDRNOTAVAIL);
 
 	if (ifpp)
 		*ifpp = ifp;
 
-	return (&ia->ia_addr.sin6_addr);
+	bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp));
+	return (0);
 }
 
 /*

Modified: stable/7/sys/netinet6/ip6_var.h
==============================================================================
--- stable/7/sys/netinet6/ip6_var.h	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/ip6_var.h	Sun Jan 24 10:08:54 2010	(r202914)
@@ -389,9 +389,9 @@ int	rip6_usrreq __P((struct socket *,
 int	dest6_input __P((struct mbuf **, int *, int));
 int	none_input __P((struct mbuf **, int *, int));
 
-struct in6_addr *in6_selectsrc __P((struct sockaddr_in6 *, struct ip6_pktopts *,
+int	in6_selectsrc(struct sockaddr_in6 *, struct ip6_pktopts *,
 	struct inpcb *inp, struct route_in6 *, struct ucred *cred,
-	struct ifnet **, int *));
+	struct ifnet **, struct in6_addr *);
 int in6_selectroute __P((struct sockaddr_in6 *, struct ip6_pktopts *,
 	struct ip6_moptions *, struct route_in6 *, struct ifnet **,
 	struct rtentry **, int));

Modified: stable/7/sys/netinet6/nd6_nbr.c
==============================================================================
--- stable/7/sys/netinet6/nd6_nbr.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/nd6_nbr.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -473,9 +473,9 @@ nd6_ns_output(struct ifnet *ifp, const s
 			dst_sa.sin6_len = sizeof(dst_sa);
 			dst_sa.sin6_addr = ip6->ip6_dst;
 
-			src = in6_selectsrc(&dst_sa, NULL,
-			    NULL, &ro, NULL, NULL, &error);
-			if (src == NULL) {
+			error = in6_selectsrc(&dst_sa, NULL,
+			    NULL, &ro, NULL, NULL, &src_in);
+			if (error) {
 				char ip6buf[INET6_ADDRSTRLEN];
 				nd6log((LOG_DEBUG,
 				    "nd6_ns_output: source can't be "
@@ -484,6 +484,7 @@ nd6_ns_output(struct ifnet *ifp, const s
 				    error));
 				goto bad;
 			}
+			src = &src_in;
 		}
 	} else {
 		/*
@@ -883,7 +884,7 @@ nd6_na_output(struct ifnet *ifp, const s
 	struct ip6_hdr *ip6;
 	struct nd_neighbor_advert *nd_na;
 	struct ip6_moptions im6o;
-	struct in6_addr *src, daddr6;
+	struct in6_addr src, daddr6;
 	struct sockaddr_in6 dst_sa;
 	int icmp6len, maxlen, error;
 	caddr_t mac = NULL;
@@ -956,15 +957,15 @@ nd6_na_output(struct ifnet *ifp, const s
 	 * Select a source whose scope is the same as that of the dest.
 	 */
 	bcopy(&dst_sa, &ro.ro_dst, sizeof(dst_sa));
-	src = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, NULL, &error);
-	if (src == NULL) {
+	error = in6_selectsrc(&dst_sa, NULL, NULL, &ro, NULL, NULL, &src);
+	if (error) {
 		char ip6buf[INET6_ADDRSTRLEN];
 		nd6log((LOG_DEBUG, "nd6_na_output: source can't be "
 		    "determined: dst=%s, error=%d\n",
 		    ip6_sprintf(ip6buf, &dst_sa.sin6_addr), error));
 		goto bad;
 	}
-	ip6->ip6_src = *src;
+	ip6->ip6_src = src;
 	nd_na = (struct nd_neighbor_advert *)(ip6 + 1);
 	nd_na->nd_na_type = ND_NEIGHBOR_ADVERT;
 	nd_na->nd_na_code = 0;

Modified: stable/7/sys/netinet6/raw_ip6.c
==============================================================================
--- stable/7/sys/netinet6/raw_ip6.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/raw_ip6.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -328,7 +328,7 @@ rip6_output(m, va_alist)
 	struct ifnet *oifp = NULL;
 	int type = 0, code = 0;		/* for ICMPv6 output statistics only */
 	int scope_ambiguous = 0;
-	struct in6_addr *in6a;
+	struct in6_addr in6a;
 	va_list ap;
 
 	va_start(ap, m);
@@ -389,16 +389,14 @@ rip6_output(m, va_alist)
 	/*
 	 * Source address selection.
 	 */
-	if ((in6a = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
-	    &oifp, &error)) == NULL) {
-		if (error == 0)
-			error = EADDRNOTAVAIL;
+	error = in6_selectsrc(dstsock, optp, in6p, NULL, so->so_cred,
+	    &oifp, &in6a);
+	if (error)
 		goto bad;
-	}
-	error = prison_get_ip6(in6p->inp_cred, in6a);
+	error = prison_get_ip6(in6p->inp_cred, &in6a);
 	if (error != 0)
 		goto bad;
-	ip6->ip6_src = *in6a;
+	ip6->ip6_src = in6a;
 
 	if (oifp && scope_ambiguous) {
 		/*
@@ -685,7 +683,7 @@ rip6_connect(struct socket *so, struct s
 {
 	struct inpcb *inp;
 	struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam;
-	struct in6_addr *in6a = NULL;
+	struct in6_addr in6a;
 	struct ifnet *ifp = NULL;
 	int error = 0, scope_ambiguous = 0;
 
@@ -715,13 +713,12 @@ rip6_connect(struct socket *so, struct s
 	INP_INFO_WLOCK(&ripcbinfo);
 	INP_WLOCK(inp);
 	/* Source address selection. XXX: need pcblookup? */
-	in6a = in6_selectsrc(addr, inp->in6p_outputopts,
-			     inp, NULL, so->so_cred,
-			     &ifp, &error);
-	if (in6a == NULL) {
+	error = in6_selectsrc(addr, inp->in6p_outputopts,
+	    inp, NULL, so->so_cred, &ifp, &in6a);
+	if (error) {
 		INP_WUNLOCK(inp);
 		INP_INFO_WUNLOCK(&ripcbinfo);
-		return (error ? error : EADDRNOTAVAIL);
+		return (error);
 	}
 
 	/* XXX: see above */
@@ -732,7 +729,7 @@ rip6_connect(struct socket *so, struct s
 		return (error);
 	}
 	inp->in6p_faddr = addr->sin6_addr;
-	inp->in6p_laddr = *in6a;
+	inp->in6p_laddr = in6a;
 	soisconnected(so);
 	INP_WUNLOCK(inp);
 	INP_INFO_WUNLOCK(&ripcbinfo);

Modified: stable/7/sys/netinet6/udp6_usrreq.c
==============================================================================
--- stable/7/sys/netinet6/udp6_usrreq.c	Sun Jan 24 09:05:43 2010	(r202913)
+++ stable/7/sys/netinet6/udp6_usrreq.c	Sun Jan 24 10:08:54 2010	(r202914)
@@ -481,7 +481,7 @@ udp6_output(struct inpcb *inp, struct mb
 	u_int32_t plen = sizeof(struct udphdr) + ulen;
 	struct ip6_hdr *ip6;
 	struct udphdr *udp6;
-	struct in6_addr *laddr, *faddr;
+	struct in6_addr *laddr, *faddr, in6a;
 	struct sockaddr_in6 *sin6 = NULL;
 	struct ifnet *oifp = NULL;
 	int scope_ambiguous = 0;
@@ -579,13 +579,16 @@ udp6_output(struct inpcb *inp, struct mb
 		}
 
 		if (!IN6_IS_ADDR_V4MAPPED(faddr)) {
-			laddr = in6_selectsrc(sin6, optp, inp, NULL,
-			    td->td_ucred, &oifp, &error);
+			error = in6_selectsrc(sin6, optp, inp, NULL,
+			    td->td_ucred, &oifp, &in6a);
+			if (error)
+				goto release;
 			if (oifp && scope_ambiguous &&
 			    (error = in6_setscope(&sin6->sin6_addr,
 			    oifp, NULL))) {
 				goto release;
 			}
+			laddr = &in6a;
 		} else
 			laddr = &inp->in6p_laddr;	/* XXX */
 		if (laddr == NULL) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001241008.o0OA8sZ0092388>