summaryrefslogtreecommitdiffstats
path: root/sys/netinet6/in6.c
diff options
context:
space:
mode:
authorjinmei <jinmei@FreeBSD.org>2007-06-02 08:02:36 +0000
committerjinmei <jinmei@FreeBSD.org>2007-06-02 08:02:36 +0000
commit6d89652bc0f7d0aaa4494c739108f5adc374a1bc (patch)
tree9374c84240bd596492283f33131f2a6e2b672d38 /sys/netinet6/in6.c
parentac701ac964be6305982bbc81a67581b4fc708ec2 (diff)
downloadFreeBSD-src-6d89652bc0f7d0aaa4494c739108f5adc374a1bc.zip
FreeBSD-src-6d89652bc0f7d0aaa4494c739108f5adc374a1bc.tar.gz
fixed memory leak for IPv6 multicast membership information associated
with interface addresses. Approved by: gnn (mentor) MFC after: 1 week
Diffstat (limited to 'sys/netinet6/in6.c')
-rw-r--r--sys/netinet6/in6.c35
1 files changed, 16 insertions, 19 deletions
diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index bf3f3e7..8edc2e2 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -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);
OpenPOWER on IntegriCloud