Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet6/mld6.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet6/mld6.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.57 retrieving revision 1.61.2.3 diff -u -p -r1.57 -r1.61.2.3 --- src/sys/netinet6/mld6.c 2014/06/10 09:38:30 1.57 +++ src/sys/netinet6/mld6.c 2015/12/27 12:10:07 1.61.2.3 @@ -1,4 +1,4 @@ -/* $NetBSD: mld6.c,v 1.57 2014/06/10 09:38:30 joerg Exp $ */ +/* $NetBSD: mld6.c,v 1.61.2.3 2015/12/27 12:10:07 skrll Exp $ */ /* $KAME: mld6.c,v 1.25 2001/01/16 14:14:18 itojun Exp $ */ /* @@ -102,9 +102,11 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.57 2014/06/10 09:38:30 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mld6.c,v 1.61.2.3 2015/12/27 12:10:07 skrll Exp $"); +#ifdef _KERNEL_OPT #include "opt_inet.h" +#endif #include #include @@ -188,6 +190,7 @@ mld_init(void) ip6_opts.ip6po_hbh = hbh; /* We will specify the hoplimit by a multicast option. */ ip6_opts.ip6po_hlim = -1; + ip6_opts.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER; } static void @@ -195,6 +198,8 @@ mld_starttimer(struct in6_multi *in6m) { struct timeval now; + KASSERT(in6m->in6m_timer != IN6M_TIMER_UNDEF); + microtime(&now); in6m->in6m_timer_expire.tv_sec = now.tv_sec + in6m->in6m_timer / hz; in6m->in6m_timer_expire.tv_usec = now.tv_usec + @@ -227,6 +232,9 @@ mld_timeo(void *arg) mutex_enter(softnet_lock); KERNEL_LOCK(1, NULL); + if (in6m->in6m_timer == IN6M_TIMER_UNDEF) + goto out; + in6m->in6m_timer = IN6M_TIMER_UNDEF; switch (in6m->in6m_state) { @@ -238,6 +246,7 @@ mld_timeo(void *arg) break; } +out: KERNEL_UNLOCK_ONE(NULL); mutex_exit(softnet_lock); } @@ -385,7 +394,7 @@ mld_input(struct mbuf *m, int off) * * In Non-Listener state, we simply don't have a membership record. * In Delaying Listener state, our timer is running (in6m->in6m_timer) - * In Idle Listener state, our timer is not running + * In Idle Listener state, our timer is not running * (in6m->in6m_timer==IN6M_TIMER_UNDEF) * * The flag is in6m->in6m_state, it is set to MLD_OTHERLISTENER if @@ -492,7 +501,7 @@ mld_input(struct mbuf *m, int off) } static void -mld_sendpkt(struct in6_multi *in6m, int type, +mld_sendpkt(struct in6_multi *in6m, int type, const struct in6_addr *dst) { struct mbuf *mh; @@ -613,7 +622,7 @@ mld_allocbuf(struct mbuf **mh, int len, * Add an address to the list of IP6 multicast addresses for a given interface. */ struct in6_multi * -in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, +in6_addmulti(struct in6_addr *maddr6, struct ifnet *ifp, int *errorp, int timer) { struct in6_ifaddr *ia; @@ -649,15 +658,19 @@ in6_addmulti(struct in6_addr *maddr6, st in6m->in6m_ifp = ifp; in6m->in6m_refcount = 1; in6m->in6m_timer = IN6M_TIMER_UNDEF; + callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); + callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); + IFP_TO_IA6(ifp, ia); if (ia == NULL) { + callout_destroy(&in6m->in6m_timer_ch); free(in6m, M_IPMADDR); splx(s); *errorp = EADDRNOTAVAIL; /* appropriate? */ return (NULL); } in6m->in6m_ia = ia; - IFAREF(&ia->ia_ifa); /* gain a reference */ + ifaref(&ia->ia_ifa); /* gain a reference */ LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); /* @@ -667,15 +680,14 @@ in6_addmulti(struct in6_addr *maddr6, st sockaddr_in6_init(&sin6, maddr6, 0, 0, 0); *errorp = if_mcast_op(ifp, SIOCADDMULTI, sin6tosa(&sin6)); if (*errorp) { + callout_destroy(&in6m->in6m_timer_ch); LIST_REMOVE(in6m, in6m_entry); free(in6m, M_IPMADDR); - IFAFREE(&ia->ia_ifa); + ifafree(&ia->ia_ifa); splx(s); return (NULL); } - callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); - callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); in6m->in6m_timer = timer; if (in6m->in6m_timer > 0) { in6m->in6m_state = MLD_REPORTPENDING; @@ -719,7 +731,7 @@ in6_delmulti(struct in6_multi *in6m) */ LIST_REMOVE(in6m, in6m_entry); if (in6m->in6m_ia != NULL) { - IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */ + ifafree(&in6m->in6m_ia->ia_ifa); /* release reference */ in6m->in6m_ia = NULL; } @@ -741,7 +753,12 @@ in6_delmulti(struct in6_multi *in6m) */ sockaddr_in6_init(&sin6, &in6m->in6m_addr, 0, 0, 0); if_mcast_op(in6m->in6m_ifp, SIOCDELMULTI, sin6tosa(&sin6)); + + /* Tell mld_timeo we're halting the timer */ + in6m->in6m_timer = IN6M_TIMER_UNDEF; + callout_halt(&in6m->in6m_timer_ch, softnet_lock); callout_destroy(&in6m->in6m_timer_ch); + free(in6m, M_IPMADDR); } splx(s); @@ -749,7 +766,7 @@ in6_delmulti(struct in6_multi *in6m) struct in6_multi_mship * -in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, +in6_joingroup(struct ifnet *ifp, struct in6_addr *addr, int *errorp, int timer) { struct in6_multi_mship *imm; @@ -798,8 +815,8 @@ in6_savemkludge(struct in6_ifaddr *oia) KASSERT(ia != oia); while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { LIST_REMOVE(in6m, in6m_entry); - IFAREF(&ia->ia_ifa); - IFAFREE(&in6m->in6m_ia->ia_ifa); + ifaref(&ia->ia_ifa); + ifafree(&in6m->in6m_ia->ia_ifa); in6m->in6m_ia = ia; LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); } @@ -815,7 +832,7 @@ in6_savemkludge(struct in6_ifaddr *oia) while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { LIST_REMOVE(in6m, in6m_entry); - IFAFREE(&in6m->in6m_ia->ia_ifa); /* release reference */ + ifafree(&in6m->in6m_ia->ia_ifa); /* release reference */ in6m->in6m_ia = NULL; LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); } @@ -842,7 +859,7 @@ in6_restoremkludge(struct in6_ifaddr *ia while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) { LIST_REMOVE(in6m, in6m_entry); in6m->in6m_ia = ia; - IFAREF(&ia->ia_ifa); + ifaref(&ia->ia_ifa); LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); } } @@ -972,7 +989,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS) if (oldp == NULL) { *oldlenp = 0; - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family != AF_INET6) @@ -988,7 +1005,7 @@ in6_multicast_sysctl(SYSCTLFN_ARGS) error = 0; written = 0; - TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { + IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family != AF_INET6) @@ -1028,6 +1045,12 @@ SYSCTL_SETUP(sysctl_in6_mklude_setup, "s sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT, + CTLTYPE_NODE, "inet6", NULL, + NULL, 0, NULL, 0, + CTL_NET, PF_INET6, CTL_EOL); + + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, CTLTYPE_NODE, "multicast", SYSCTL_DESCR("Multicast information"), in6_multicast_sysctl, 0, NULL, 0,