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/netinet/igmp.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/netinet/igmp.c')
-rw-r--r-- | sys/netinet/igmp.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/sys/netinet/igmp.c b/sys/netinet/igmp.c index 2761590..be102d4 100644 --- a/sys/netinet/igmp.c +++ b/sys/netinet/igmp.c @@ -1233,8 +1233,10 @@ igmp_input_v1_report(struct ifnet *ifp, /*const*/ struct ip *ip, */ if (V_igmp_recvifkludge && in_nullhost(ip->ip_src)) { IFP_TO_IA(ifp, ia); - if (ia != NULL) + if (ia != NULL) { ip->ip_src.s_addr = htonl(ia->ia_subnet); + ifa_free(&ia->ia_ifa); + } } CTR3(KTR_IGMPV3, "process v1 report %s on ifp %p(%s)", @@ -1326,16 +1328,23 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, * group. */ IFP_TO_IA(ifp, ia); - if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) + if (ia != NULL && in_hosteq(ip->ip_src, IA_SIN(ia)->sin_addr)) { + ifa_free(&ia->ia_ifa); return (0); + } IGMPSTAT_INC(igps_rcv_reports); - if (ifp->if_flags & IFF_LOOPBACK) + if (ifp->if_flags & IFF_LOOPBACK) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); return (0); + } if (!IN_MULTICAST(ntohl(igmp->igmp_group.s_addr)) || !in_hosteq(igmp->igmp_group, ip->ip_dst)) { + if (ia != NULL) + ifa_free(&ia->ia_ifa); IGMPSTAT_INC(igps_rcv_badreports); return (EINVAL); } @@ -1351,6 +1360,8 @@ igmp_input_v2_report(struct ifnet *ifp, /*const*/ struct ip *ip, if (ia != NULL) ip->ip_src.s_addr = htonl(ia->ia_subnet); } + if (ia != NULL) + ifa_free(&ia->ia_ifa); CTR3(KTR_IGMPV3, "process v2 report %s on ifp %p(%s)", inet_ntoa(igmp->igmp_group), ifp, ifp->if_xname); @@ -3534,8 +3545,10 @@ igmp_v3_encap_report(struct ifnet *ifp, struct mbuf *m) struct in_ifaddr *ia; IFP_TO_IA(ifp, ia); - if (ia != NULL) + if (ia != NULL) { ip->ip_src = ia->ia_addr.sin_addr; + ifa_free(&ia->ia_ifa); + } } ip->ip_dst.s_addr = htonl(INADDR_ALLRPTS_GROUP); |