summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/mld6.c
diff options
context:
space:
mode:
authorrwatson <rwatson@FreeBSD.org>2009-06-23 20:19:09 +0000
committerrwatson <rwatson@FreeBSD.org>2009-06-23 20:19:09 +0000
commitc9ef486fe1d7da6a2212a337eacc5ed5b40f85d9 (patch)
tree5ce1a7dad67026f119a839b3325454ebafa72c51 /sys/netinet6/mld6.c
parentf75c2385c686d82292982283b5f0a9c9988beda8 (diff)
downloadFreeBSD-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.c21
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);
}
OpenPOWER on IntegriCloud