svn commit: r202914 - in stable/7/sys: netinet netinet6
Bjoern A. Zeeb
bz at FreeBSD.org
Sun Jan 24 10:08:55 UTC 2010
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) {
More information about the svn-src-all
mailing list