diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-06-23 20:19:09 +0000 |
commit | c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9 (patch) | |
tree | 5ce1a7dad67026f119a839b3325454ebafa72c51 /sys/netinet6/mld6.c | |
parent | f75c2385c686d82292982283b5f0a9c9988beda8 (diff) | |
download | FreeBSD-src-c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9.zip FreeBSD-src-c9ef486fe1d7da6a2212a337eacc5ed5b40f85d9.tar.gz |
Modify most routines returning 'struct ifaddr *' to return references
rather than pointers, requiring callers to properly dispose of those
references. The following routines now return references:
ifaddr_byindex
ifa_ifwithaddr
ifa_ifwithbroadaddr
ifa_ifwithdstaddr
ifa_ifwithnet
ifaof_ifpforaddr
ifa_ifwithroute
ifa_ifwithroute_fib
rt_getifa
rt_getifa_fib
IFP_TO_IA
ip_rtaddr
in6_ifawithifp
in6ifa_ifpforlinklocal
in6ifa_ifpwithaddr
in6_ifadd
carp_iamatch6
ip6_getdstifaddr
Remove unused macro which didn't have required referencing:
IFP_TO_IA6
This closes many small races in which changes to interface
or address lists while an ifaddr was in use could lead to use of freed
memory (etc). In a few cases, add missing if_addr_list locking
required to safely acquire references.
Because of a lack of deep copying support, we accept a race in which
an in6_ifaddr pointed to by mbuf tags and extracted with
ip6_getdstifaddr() doesn't hold a reference while in transmit. Once
we have mbuf tag deep copy support, this can be fixed.
Reviewed by: bz
Obtained from: Apple, Inc. (portions)
MFC after: 6 weeks (portions)
Diffstat (limited to 'sys/netinet6/mld6.c')
-rw-r--r-- | sys/netinet6/mld6.c | 21 |
1 files changed, 18 insertions, 3 deletions
diff --git a/sys/netinet6/mld6.c b/sys/netinet6/mld6.c index 012c672..61fff11 100644 --- a/sys/netinet6/mld6.c +++ b/sys/netinet6/mld6.c @@ -1152,8 +1152,13 @@ mld_v1_input_report(struct ifnet *ifp, const struct ip6_hdr *ip6, */ ia = in6ifa_ifpforlinklocal(ifp, IN6_IFF_NOTREADY|IN6_IFF_ANYCAST); if ((ia && IN6_ARE_ADDR_EQUAL(&ip6->ip6_src, IA6_IN6(ia))) || - (ia == NULL && IN6_IS_ADDR_UNSPECIFIED(&src))) + (ia == NULL && IN6_IS_ADDR_UNSPECIFIED(&src))) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); return (0); + } + if (ia != NULL) + ifa_free(&ia->ia_ifa); CTR3(KTR_MLD, "process v1 report %s on ifp %p(%s)", ip6_sprintf(ip6tbuf, &mld->mld_addr), ifp, ifp->if_xname); @@ -1796,11 +1801,16 @@ mld_v1_transmit_report(struct in6_multi *in6m, const int type) /* ia may be NULL if link-local address is tentative. */ MGETHDR(mh, M_DONTWAIT, MT_HEADER); - if (mh == NULL) + if (mh == NULL) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); return (ENOMEM); + } MGET(md, M_DONTWAIT, MT_DATA); if (md == NULL) { m_free(mh); + if (ia != NULL) + ifa_free(&ia->ia_ifa); return (ENOMEM); } mh->m_next = md; @@ -1839,6 +1849,8 @@ mld_v1_transmit_report(struct in6_multi *in6m, const int type) mld_dispatch_packet(mh); + if (ia != NULL) + ifa_free(&ia->ia_ifa); return (0); } @@ -3136,6 +3148,8 @@ mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m) MGETHDR(mh, M_DONTWAIT, MT_HEADER); if (mh == NULL) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); m_freem(m); return (NULL); } @@ -3154,6 +3168,8 @@ mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m) ip6->ip6_vfc |= IPV6_VERSION; ip6->ip6_nxt = IPPROTO_ICMPV6; ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any; + if (ia != NULL) + ifa_free(&ia->ia_ifa); ip6->ip6_dst = in6addr_linklocal_allv2routers; /* scope ID will be set in netisr */ @@ -3168,7 +3184,6 @@ mld_v2_encap_report(struct ifnet *ifp, struct mbuf *m) mh->m_next = m; mld->mld_cksum = in6_cksum(mh, IPPROTO_ICMPV6, sizeof(struct ip6_hdr), sizeof(struct mldv2_report) + mldreclen); - return (mh); } |