check before joining multicast group. otherwise multiple in6_multi structure

will be kept.  reported by patrick latifi
This commit is contained in:
itojun 2004-06-14 07:54:45 +00:00
parent 3ce67e6c14
commit 4d7b9596f6
1 changed files with 73 additions and 43 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: in6.c,v 1.86 2004/03/28 08:28:06 christos Exp $ */ /* $NetBSD: in6.c,v 1.87 2004/06/14 07:54:45 itojun Exp $ */
/* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */ /* $KAME: in6.c,v 1.198 2001/07/18 09:12:38 itojun Exp $ */
/* /*
@ -62,7 +62,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.86 2004/03/28 08:28:06 christos Exp $"); __KERNEL_RCSID(0, "$NetBSD: in6.c,v 1.87 2004/06/14 07:54:45 itojun Exp $");
#include "opt_inet.h" #include "opt_inet.h"
@ -1079,16 +1079,24 @@ in6_update_ifa(ifp, ifra, ia)
llsol.sin6_addr.s6_addr32[3] = llsol.sin6_addr.s6_addr32[3] =
ifra->ifra_addr.sin6_addr.s6_addr32[3]; ifra->ifra_addr.sin6_addr.s6_addr32[3];
llsol.sin6_addr.s6_addr8[12] = 0xff; llsol.sin6_addr.s6_addr8[12] = 0xff;
imm = in6_joingroup(ifp, &llsol.sin6_addr, &error); LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
if (imm) { if (IN6_ARE_ADDR_EQUAL(&llsol.sin6_addr,
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, &imm->i6mm_maddr->in6m_addr))
i6mm_chain); break;
} else { }
nd6log((LOG_ERR, "in6_update_ifa: addmulti " if (!imm) {
"failed for %s on %s (errno=%d)\n", imm = in6_joingroup(ifp, &llsol.sin6_addr,
ip6_sprintf(&llsol.sin6_addr), &error);
if_name(ifp), error)); if (!imm) {
goto cleanup; nd6log((LOG_ERR,
"in6_update_ifa: addmulti "
"failed for %s on %s (errno=%d)\n",
ip6_sprintf(&llsol.sin6_addr),
if_name(ifp), error));
goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
} }
} }
@ -1147,33 +1155,48 @@ in6_update_ifa(ifp, ifra, ia)
#ifndef SCOPEDROUTING #ifndef SCOPEDROUTING
mltaddr.sin6_scope_id = zoneid; /* XXX */ mltaddr.sin6_scope_id = zoneid; /* XXX */
#endif #endif
imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
if (imm) { if (IN6_ARE_ADDR_EQUAL(&mltaddr.sin6_addr,
&imm->i6mm_maddr->in6m_addr))
break;
}
if (!imm) {
imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error);
if (!imm) {
nd6log((LOG_WARNING,
"in6_update_ifa: addmulti failed for "
"%s on %s (errno=%d)\n",
ip6_sprintf(&mltaddr.sin6_addr),
if_name(ifp), error));
goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, LIST_INSERT_HEAD(&ia->ia6_memberships, imm,
i6mm_chain); i6mm_chain);
} else {
nd6log((LOG_WARNING,
"in6_update_ifa: addmulti failed for "
"%s on %s (errno=%d)\n",
ip6_sprintf(&mltaddr.sin6_addr),
if_name(ifp), error));
goto cleanup;
} }
/* /*
* join node information group address * join node information group address
*/ */
if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) == 0) { if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr) == 0) {
imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
if (imm) { if (IN6_ARE_ADDR_EQUAL(&mltaddr.sin6_addr,
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, &imm->i6mm_maddr->in6m_addr))
i6mm_chain); break;
} else { }
nd6log((LOG_WARNING, "in6_update_ifa: " if (!imm) {
"addmulti failed for %s on %s (errno=%d)\n", imm = in6_joingroup(ifp, &mltaddr.sin6_addr,
ip6_sprintf(&mltaddr.sin6_addr), &error);
if_name(ifp), error)); if (!imm) {
/* XXX not very fatal, go on... */ nd6log((LOG_WARNING, "in6_update_ifa: "
"addmulti failed for %s on %s "
"(errno=%d)\n",
ip6_sprintf(&mltaddr.sin6_addr),
if_name(ifp), error));
/* XXX not very fatal, go on... */
} else {
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
}
} }
} }
@ -1213,17 +1236,24 @@ in6_update_ifa(ifp, ifra, ia)
} else { } else {
RTFREE(rt); RTFREE(rt);
} }
imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error); LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) {
if (imm) { if (IN6_ARE_ADDR_EQUAL(&mltaddr.sin6_addr,
LIST_INSERT_HEAD(&ia->ia6_memberships, imm, &imm->i6mm_maddr->in6m_addr))
i6mm_chain); break;
} else { }
nd6log((LOG_WARNING, "in6_update_ifa: " if (!imm) {
"addmulti failed for %s on %s " imm = in6_joingroup(ifp, &mltaddr.sin6_addr,
"(errno=%d)\n", &error);
ip6_sprintf(&mltaddr.sin6_addr), if (!imm) {
if_name(ifp), error)); nd6log((LOG_WARNING, "in6_update_ifa: "
goto cleanup; "addmulti failed for %s on %s "
"(errno=%d)\n",
ip6_sprintf(&mltaddr.sin6_addr),
if_name(ifp), error));
goto cleanup;
}
LIST_INSERT_HEAD(&ia->ia6_memberships,
imm, i6mm_chain);
} }
} }
} }
@ -1760,7 +1790,7 @@ in6_restoremkludge(ia, ifp)
in6m->in6m_ia = ia; in6m->in6m_ia = ia;
IFAREF(&ia->ia_ifa); IFAREF(&ia->ia_ifa);
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, LIST_INSERT_HEAD(&ia->ia6_multiaddrs,
in6m, in6m_entry); in6m, in6m_entry);
} }
LIST_INIT(&mk->mk_head); LIST_INIT(&mk->mk_head);
break; break;