1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-11 09:50:12 +00:00

fixed memory leak for IPv6 multicast membership information associated

with interface addresses.

Approved by:	gnn (mentor)
MFC after:	1 week
This commit is contained in:
JINMEI Tatuya 2007-06-02 08:02:36 +00:00
parent 99124467fc
commit 09a52a5532
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=170202
3 changed files with 29 additions and 21 deletions

View File

@ -926,6 +926,7 @@ in6_update_ifa(ifp, ifra, ia, flags)
if (ia == NULL)
return (ENOBUFS);
bzero((caddr_t)ia, sizeof(*ia));
LIST_INIT(&ia->ia6_memberships);
/* Initialize the address and masks, and put time stamp */
IFA_LOCK_INIT(&ia->ia_ifa);
ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
@ -1083,7 +1084,7 @@ in6_update_ifa(ifp, ifra, ia, flags)
(MAX_RTR_SOLICITATION_DELAY * hz);
}
imm = in6_joingroup(ifp, &llsol, &error, delay);
if (error != 0) {
if (imm == NULL) {
nd6log((LOG_WARNING,
"in6_update_ifa: addmulti failed for "
"%s on %s (errno=%d)\n",
@ -1092,6 +1093,8 @@ in6_update_ifa(ifp, ifra, ia, flags)
in6_purgeaddr((struct ifaddr *)ia);
return (error);
}
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
in6m_sol = imm->i6mm_maddr;
bzero(&mltmask, sizeof(mltmask));
@ -1173,6 +1176,7 @@ in6_update_ifa(ifp, ifra, ia, flags)
if_name(ifp), error));
goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
/*
* join node information group address
@ -1198,6 +1202,9 @@ in6_update_ifa(ifp, ifra, ia, flags)
ip6_sprintf(ip6buf, &mltaddr.sin6_addr),
if_name(ifp), error));
/* XXX not very fatal, go on... */
} else {
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
}
}
#undef hostnamelen
@ -1260,6 +1267,7 @@ in6_update_ifa(ifp, ifra, ia, flags)
if_name(ifp), error));
goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain);
#undef MLTMASK_LEN
}
@ -1324,6 +1332,7 @@ in6_purgeaddr(ifa)
struct ifnet *ifp = ifa->ifa_ifp;
struct in6_ifaddr *ia = (struct in6_ifaddr *) ifa;
char ip6buf[INET6_ADDRSTRLEN];
struct in6_multi_mship *imm;
/* stop DAD processing */
nd6_dad_stop(ifa);
@ -1350,24 +1359,12 @@ in6_purgeaddr(ifa)
/* Remove ownaddr's loopback rtentry, if it exists. */
in6_ifremloop(&(ia->ia_ifa));
if (ifp->if_flags & IFF_MULTICAST) {
/*
* delete solicited multicast addr for deleting host id
*/
struct in6_multi *in6m;
struct in6_addr llsol;
bzero(&llsol, sizeof(struct in6_addr));
llsol.s6_addr32[0] = IPV6_ADDR_INT32_MLL;
llsol.s6_addr32[1] = 0;
llsol.s6_addr32[2] = htonl(1);
llsol.s6_addr32[3] =
ia->ia_addr.sin6_addr.s6_addr32[3];
llsol.s6_addr8[12] = 0xff;
(void)in6_setscope(&llsol, ifp, NULL); /* XXX proceed anyway */
IN6_LOOKUP_MULTI(llsol, ifp, in6m);
if (in6m)
in6_delmulti(in6m);
/*
* leave from multicast groups we have joined for the interface
*/
while ((imm = ia->ia6_memberships.lh_first) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
in6_unlink_ifa(ia, ifp);

View File

@ -731,8 +731,8 @@ in6_ifdetach(ifp)
struct rtentry *rt;
short rtflags;
struct sockaddr_in6 sin6;
struct in6_multi *in6m;
struct in6_multi *in6m_next;
struct in6_multi *in6m, *in6m_next;
struct in6_multi_mship *imm;
/* remove neighbor management table */
nd6_purge(ifp);
@ -756,6 +756,14 @@ in6_ifdetach(ifp)
ia = (struct in6_ifaddr *)ifa;
/*
* leave from multicast groups we have joined for the interface
*/
while ((imm = ia->ia6_memberships.lh_first) != NULL) {
LIST_REMOVE(imm, i6mm_chain);
in6_leavegroup(imm);
}
/* remove from the routing table */
if ((ia->ia_flags & IFA_ROUTE) &&
(rt = rtalloc1((struct sockaddr *)&ia->ia_addr, 0, 0UL))) {

View File

@ -115,6 +115,9 @@ struct in6_ifaddr {
/* back pointer to the ND prefix (for autoconfigured addresses only) */
struct nd_prefix *ia6_ndpr;
/* multicast addresses joined from the kernel */
LIST_HEAD(, in6_multi_mship) ia6_memberships;
};
/* control structure to manage address selection policy */