version 1.57, 2014/06/10 09:38:30 |
version 1.81, 2017/02/07 02:38:08 |
|
|
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#ifdef _KERNEL_OPT |
#include "opt_inet.h" |
#include "opt_inet.h" |
|
#include "opt_net_mpsafe.h" |
|
#endif |
|
|
#include <sys/param.h> |
#include <sys/param.h> |
#include <sys/systm.h> |
#include <sys/systm.h> |
#include <sys/mbuf.h> |
#include <sys/mbuf.h> |
#include <sys/socket.h> |
#include <sys/socket.h> |
#include <sys/socketvar.h> |
#include <sys/socketvar.h> |
#include <sys/protosw.h> |
|
#include <sys/syslog.h> |
#include <sys/syslog.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
#include <sys/kernel.h> |
#include <sys/kernel.h> |
|
|
ip6_opts.ip6po_hbh = hbh; |
ip6_opts.ip6po_hbh = hbh; |
/* We will specify the hoplimit by a multicast option. */ |
/* We will specify the hoplimit by a multicast option. */ |
ip6_opts.ip6po_hlim = -1; |
ip6_opts.ip6po_hlim = -1; |
|
ip6_opts.ip6po_prefer_tempaddr = IP6PO_TEMPADDR_NOTPREFER; |
} |
} |
|
|
static void |
static void |
Line 195 mld_starttimer(struct in6_multi *in6m) |
|
Line 198 mld_starttimer(struct in6_multi *in6m) |
|
{ |
{ |
struct timeval now; |
struct timeval now; |
|
|
|
KASSERT(in6m->in6m_timer != IN6M_TIMER_UNDEF); |
|
|
microtime(&now); |
microtime(&now); |
in6m->in6m_timer_expire.tv_sec = now.tv_sec + in6m->in6m_timer / hz; |
in6m->in6m_timer_expire.tv_sec = now.tv_sec + in6m->in6m_timer / hz; |
in6m->in6m_timer_expire.tv_usec = now.tv_usec + |
in6m->in6m_timer_expire.tv_usec = now.tv_usec + |
Line 224 mld_timeo(void *arg) |
|
Line 229 mld_timeo(void *arg) |
|
{ |
{ |
struct in6_multi *in6m = arg; |
struct in6_multi *in6m = arg; |
|
|
|
/* XXX NOMPSAFE still need softnet_lock */ |
mutex_enter(softnet_lock); |
mutex_enter(softnet_lock); |
KERNEL_LOCK(1, NULL); |
KERNEL_LOCK(1, NULL); |
|
|
|
if (in6m->in6m_timer == IN6M_TIMER_UNDEF) |
|
goto out; |
|
|
in6m->in6m_timer = IN6M_TIMER_UNDEF; |
in6m->in6m_timer = IN6M_TIMER_UNDEF; |
|
|
switch (in6m->in6m_state) { |
switch (in6m->in6m_state) { |
Line 238 mld_timeo(void *arg) |
|
Line 247 mld_timeo(void *arg) |
|
break; |
break; |
} |
} |
|
|
|
out: |
KERNEL_UNLOCK_ONE(NULL); |
KERNEL_UNLOCK_ONE(NULL); |
mutex_exit(softnet_lock); |
mutex_exit(softnet_lock); |
} |
} |
Line 327 mld_input(struct mbuf *m, int off) |
|
Line 337 mld_input(struct mbuf *m, int off) |
|
{ |
{ |
struct ip6_hdr *ip6; |
struct ip6_hdr *ip6; |
struct mld_hdr *mldh; |
struct mld_hdr *mldh; |
struct ifnet *ifp = m->m_pkthdr.rcvif; |
struct ifnet *ifp; |
struct in6_multi *in6m = NULL; |
struct in6_multi *in6m = NULL; |
struct in6_addr mld_addr, all_in6; |
struct in6_addr mld_addr, all_in6; |
struct in6_ifaddr *ia; |
struct in6_ifaddr *ia; |
u_long timer = 0; /* timer value in the MLD query header */ |
u_long timer = 0; /* timer value in the MLD query header */ |
|
int s; |
|
|
|
ifp = m_get_rcvif(m, &s); |
|
if (__predict_false(ifp == NULL)) |
|
goto out; |
IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh)); |
IP6_EXTHDR_GET(mldh, struct mld_hdr *, m, off, sizeof(*mldh)); |
if (mldh == NULL) { |
if (mldh == NULL) { |
ICMP6_STATINC(ICMP6_STAT_TOOSHORT); |
ICMP6_STATINC(ICMP6_STAT_TOOSHORT); |
return; |
goto out_nodrop; |
} |
} |
|
|
/* source address validation */ |
/* source address validation */ |
Line 362 mld_input(struct mbuf *m, int off) |
|
Line 376 mld_input(struct mbuf *m, int off) |
|
* though RFC3590 says "SHOULD log" if the source of a query |
* though RFC3590 says "SHOULD log" if the source of a query |
* is the unspecified address. |
* is the unspecified address. |
*/ |
*/ |
|
char ip6bufs[INET6_ADDRSTRLEN]; |
|
char ip6bufm[INET6_ADDRSTRLEN]; |
log(LOG_INFO, |
log(LOG_INFO, |
"mld_input: src %s is not link-local (grp=%s)\n", |
"mld_input: src %s is not link-local (grp=%s)\n", |
ip6_sprintf(&ip6->ip6_src), ip6_sprintf(&mldh->mld_addr)); |
IN6_PRINT(ip6bufs,&ip6->ip6_src), |
|
IN6_PRINT(ip6bufm, &mldh->mld_addr)); |
#endif |
#endif |
m_freem(m); |
goto out; |
return; |
|
} |
} |
|
|
/* |
/* |
Line 376 mld_input(struct mbuf *m, int off) |
|
Line 392 mld_input(struct mbuf *m, int off) |
|
mld_addr = mldh->mld_addr; |
mld_addr = mldh->mld_addr; |
if (in6_setscope(&mld_addr, ifp, NULL)) { |
if (in6_setscope(&mld_addr, ifp, NULL)) { |
/* XXX: this should not happen! */ |
/* XXX: this should not happen! */ |
m_free(m); |
goto out; |
return; |
|
} |
} |
|
|
/* |
/* |
Line 393 mld_input(struct mbuf *m, int off) |
|
Line 408 mld_input(struct mbuf *m, int off) |
|
* if we sent the last report. |
* if we sent the last report. |
*/ |
*/ |
switch (mldh->mld_type) { |
switch (mldh->mld_type) { |
case MLD_LISTENER_QUERY: |
case MLD_LISTENER_QUERY: { |
|
struct psref psref; |
|
|
if (ifp->if_flags & IFF_LOOPBACK) |
if (ifp->if_flags & IFF_LOOPBACK) |
break; |
break; |
|
|
Line 419 mld_input(struct mbuf *m, int off) |
|
Line 436 mld_input(struct mbuf *m, int off) |
|
*/ |
*/ |
timer = ntohs(mldh->mld_maxdelay); |
timer = ntohs(mldh->mld_maxdelay); |
|
|
IFP_TO_IA6(ifp, ia); |
ia = in6_get_ia_from_ifp_psref(ifp, &psref); |
if (ia == NULL) |
if (ia == NULL) |
break; |
break; |
|
|
|
/* The following operations may sleep */ |
|
m_put_rcvif(ifp, &s); |
|
ifp = NULL; |
|
|
LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) { |
LIST_FOREACH(in6m, &ia->ia6_multiaddrs, in6m_entry) { |
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) || |
if (IN6_ARE_ADDR_EQUAL(&in6m->in6m_addr, &all_in6) || |
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < |
IPV6_ADDR_MC_SCOPE(&in6m->in6m_addr) < |
Line 448 mld_input(struct mbuf *m, int off) |
|
Line 469 mld_input(struct mbuf *m, int off) |
|
mld_starttimer(in6m); |
mld_starttimer(in6m); |
} |
} |
} |
} |
|
ia6_release(ia, &psref); |
break; |
break; |
|
} |
|
|
case MLD_LISTENER_REPORT: |
case MLD_LISTENER_REPORT: |
/* |
/* |
Line 488 mld_input(struct mbuf *m, int off) |
|
Line 511 mld_input(struct mbuf *m, int off) |
|
break; |
break; |
} |
} |
|
|
|
out: |
m_freem(m); |
m_freem(m); |
|
out_nodrop: |
|
m_put_rcvif(ifp, &s); |
} |
} |
|
|
static void |
static void |
Line 502 mld_sendpkt(struct in6_multi *in6m, int |
|
Line 528 mld_sendpkt(struct in6_multi *in6m, int |
|
struct in6_ifaddr *ia = NULL; |
struct in6_ifaddr *ia = NULL; |
struct ifnet *ifp = in6m->in6m_ifp; |
struct ifnet *ifp = in6m->in6m_ifp; |
int ignflags; |
int ignflags; |
|
struct psref psref; |
|
int bound; |
|
|
/* |
/* |
* At first, find a link local address on the outgoing interface |
* At first, find a link local address on the outgoing interface |
Line 510 mld_sendpkt(struct in6_multi *in6m, int |
|
Line 538 mld_sendpkt(struct in6_multi *in6m, int |
|
* the case where we first join a link-local address. |
* the case where we first join a link-local address. |
*/ |
*/ |
ignflags = (IN6_IFF_NOTREADY|IN6_IFF_ANYCAST) & ~IN6_IFF_TENTATIVE; |
ignflags = (IN6_IFF_NOTREADY|IN6_IFF_ANYCAST) & ~IN6_IFF_TENTATIVE; |
if ((ia = in6ifa_ifpforlinklocal(ifp, ignflags)) == NULL) |
bound = curlwp_bind(); |
|
ia = in6ifa_ifpforlinklocal_psref(ifp, ignflags, &psref); |
|
if (ia == NULL) { |
|
curlwp_bindx(bound); |
return; |
return; |
if ((ia->ia6_flags & IN6_IFF_TENTATIVE)) |
} |
|
if ((ia->ia6_flags & IN6_IFF_TENTATIVE)) { |
|
ia6_release(ia, &psref); |
ia = NULL; |
ia = NULL; |
|
} |
|
|
/* Allocate two mbufs to store IPv6 header and MLD header */ |
/* Allocate two mbufs to store IPv6 header and MLD header */ |
mldh = mld_allocbuf(&mh, sizeof(struct mld_hdr), in6m, type); |
mldh = mld_allocbuf(&mh, sizeof(struct mld_hdr), in6m, type); |
if (mldh == NULL) |
if (mldh == NULL) { |
|
ia6_release(ia, &psref); |
|
curlwp_bindx(bound); |
return; |
return; |
|
} |
|
|
/* fill src/dst here */ |
/* fill src/dst here */ |
ip6 = mtod(mh, struct ip6_hdr *); |
ip6 = mtod(mh, struct ip6_hdr *); |
ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any; |
ip6->ip6_src = ia ? ia->ia_addr.sin6_addr : in6addr_any; |
ip6->ip6_dst = dst ? *dst : in6m->in6m_addr; |
ip6->ip6_dst = dst ? *dst : in6m->in6m_addr; |
|
ia6_release(ia, &psref); |
|
curlwp_bindx(bound); |
|
|
mldh->mld_addr = in6m->in6m_addr; |
mldh->mld_addr = in6m->in6m_addr; |
in6_clearscope(&mldh->mld_addr); /* XXX */ |
in6_clearscope(&mldh->mld_addr); /* XXX */ |
Line 532 mld_sendpkt(struct in6_multi *in6m, int |
|
Line 571 mld_sendpkt(struct in6_multi *in6m, int |
|
|
|
/* construct multicast option */ |
/* construct multicast option */ |
memset(&im6o, 0, sizeof(im6o)); |
memset(&im6o, 0, sizeof(im6o)); |
im6o.im6o_multicast_ifp = ifp; |
im6o.im6o_multicast_if_index = if_get_index(ifp); |
im6o.im6o_multicast_hlim = 1; |
im6o.im6o_multicast_hlim = 1; |
|
|
/* |
/* |
Line 585 mld_allocbuf(struct mbuf **mh, int len, |
|
Line 624 mld_allocbuf(struct mbuf **mh, int len, |
|
(*mh)->m_next = md; |
(*mh)->m_next = md; |
md->m_next = NULL; |
md->m_next = NULL; |
|
|
(*mh)->m_pkthdr.rcvif = NULL; |
m_reset_rcvif((*mh)); |
(*mh)->m_pkthdr.len = sizeof(struct ip6_hdr) + len; |
(*mh)->m_pkthdr.len = sizeof(struct ip6_hdr) + len; |
(*mh)->m_len = sizeof(struct ip6_hdr); |
(*mh)->m_len = sizeof(struct ip6_hdr); |
MH_ALIGN(*mh, sizeof(struct ip6_hdr)); |
MH_ALIGN(*mh, sizeof(struct ip6_hdr)); |
Line 633 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 672 in6_addmulti(struct in6_addr *maddr6, st |
|
*/ |
*/ |
in6m->in6m_refcount++; |
in6m->in6m_refcount++; |
} else { |
} else { |
|
int _s; |
/* |
/* |
* New address; allocate a new multicast record |
* New address; allocate a new multicast record |
* and link it into the interface's multicast list. |
* and link it into the interface's multicast list. |
Line 649 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 689 in6_addmulti(struct in6_addr *maddr6, st |
|
in6m->in6m_ifp = ifp; |
in6m->in6m_ifp = ifp; |
in6m->in6m_refcount = 1; |
in6m->in6m_refcount = 1; |
in6m->in6m_timer = IN6M_TIMER_UNDEF; |
in6m->in6m_timer = IN6M_TIMER_UNDEF; |
IFP_TO_IA6(ifp, ia); |
callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); |
|
callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); |
|
|
|
_s = pserialize_read_enter(); |
|
ia = in6_get_ia_from_ifp(ifp); |
if (ia == NULL) { |
if (ia == NULL) { |
|
pserialize_read_exit(_s); |
|
callout_destroy(&in6m->in6m_timer_ch); |
free(in6m, M_IPMADDR); |
free(in6m, M_IPMADDR); |
splx(s); |
splx(s); |
*errorp = EADDRNOTAVAIL; /* appropriate? */ |
*errorp = EADDRNOTAVAIL; /* appropriate? */ |
return (NULL); |
return (NULL); |
} |
} |
in6m->in6m_ia = ia; |
in6m->in6m_ia = ia; |
IFAREF(&ia->ia_ifa); /* gain a reference */ |
ifaref(&ia->ia_ifa); /* gain a reference */ |
|
/* FIXME NOMPSAFE: need to lock */ |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
|
pserialize_read_exit(_s); |
|
|
/* |
/* |
* Ask the network driver to update its multicast reception |
* Ask the network driver to update its multicast reception |
Line 667 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 715 in6_addmulti(struct in6_addr *maddr6, st |
|
sockaddr_in6_init(&sin6, maddr6, 0, 0, 0); |
sockaddr_in6_init(&sin6, maddr6, 0, 0, 0); |
*errorp = if_mcast_op(ifp, SIOCADDMULTI, sin6tosa(&sin6)); |
*errorp = if_mcast_op(ifp, SIOCADDMULTI, sin6tosa(&sin6)); |
if (*errorp) { |
if (*errorp) { |
|
callout_destroy(&in6m->in6m_timer_ch); |
LIST_REMOVE(in6m, in6m_entry); |
LIST_REMOVE(in6m, in6m_entry); |
free(in6m, M_IPMADDR); |
free(in6m, M_IPMADDR); |
IFAFREE(&ia->ia_ifa); |
ifafree(&ia->ia_ifa); |
splx(s); |
splx(s); |
return (NULL); |
return (NULL); |
} |
} |
|
|
callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); |
|
callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); |
|
in6m->in6m_timer = timer; |
in6m->in6m_timer = timer; |
if (in6m->in6m_timer > 0) { |
if (in6m->in6m_timer > 0) { |
in6m->in6m_state = MLD_REPORTPENDING; |
in6m->in6m_state = MLD_REPORTPENDING; |
Line 708 in6_delmulti(struct in6_multi *in6m) |
|
Line 755 in6_delmulti(struct in6_multi *in6m) |
|
mld_stoptimer(in6m); |
mld_stoptimer(in6m); |
|
|
if (--in6m->in6m_refcount == 0) { |
if (--in6m->in6m_refcount == 0) { |
|
int _s; |
|
|
/* |
/* |
* No remaining claims to this record; let MLD6 know |
* No remaining claims to this record; let MLD6 know |
* that we are leaving the multicast group. |
* that we are leaving the multicast group. |
Line 719 in6_delmulti(struct in6_multi *in6m) |
|
Line 768 in6_delmulti(struct in6_multi *in6m) |
|
*/ |
*/ |
LIST_REMOVE(in6m, in6m_entry); |
LIST_REMOVE(in6m, in6m_entry); |
if (in6m->in6m_ia != NULL) { |
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; |
in6m->in6m_ia = NULL; |
} |
} |
|
|
Line 727 in6_delmulti(struct in6_multi *in6m) |
|
Line 776 in6_delmulti(struct in6_multi *in6m) |
|
* Delete all references of this multicasting group from |
* Delete all references of this multicasting group from |
* the membership arrays |
* the membership arrays |
*/ |
*/ |
for (ia = in6_ifaddr; ia; ia = ia->ia_next) { |
_s = pserialize_read_enter(); |
|
IN6_ADDRLIST_READER_FOREACH(ia) { |
struct in6_multi_mship *imm; |
struct in6_multi_mship *imm; |
LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) { |
LIST_FOREACH(imm, &ia->ia6_memberships, i6mm_chain) { |
if (imm->i6mm_maddr == in6m) |
if (imm->i6mm_maddr == in6m) |
imm->i6mm_maddr = NULL; |
imm->i6mm_maddr = NULL; |
} |
} |
} |
} |
|
pserialize_read_exit(_s); |
|
|
/* |
/* |
* Notify the network driver to update its multicast |
* Notify the network driver to update its multicast |
Line 741 in6_delmulti(struct in6_multi *in6m) |
|
Line 792 in6_delmulti(struct in6_multi *in6m) |
|
*/ |
*/ |
sockaddr_in6_init(&sin6, &in6m->in6m_addr, 0, 0, 0); |
sockaddr_in6_init(&sin6, &in6m->in6m_addr, 0, 0, 0); |
if_mcast_op(in6m->in6m_ifp, SIOCDELMULTI, sin6tosa(&sin6)); |
if_mcast_op(in6m->in6m_ifp, SIOCDELMULTI, sin6tosa(&sin6)); |
|
|
|
/* Tell mld_timeo we're halting the timer */ |
|
in6m->in6m_timer = IN6M_TIMER_UNDEF; |
|
if (mutex_owned(softnet_lock)) |
|
callout_halt(&in6m->in6m_timer_ch, softnet_lock); |
|
else |
|
callout_halt(&in6m->in6m_timer_ch, NULL); |
callout_destroy(&in6m->in6m_timer_ch); |
callout_destroy(&in6m->in6m_timer_ch); |
|
|
free(in6m, M_IPMADDR); |
free(in6m, M_IPMADDR); |
} |
} |
splx(s); |
splx(s); |
Line 792 in6_savemkludge(struct in6_ifaddr *oia) |
|
Line 851 in6_savemkludge(struct in6_ifaddr *oia) |
|
{ |
{ |
struct in6_ifaddr *ia; |
struct in6_ifaddr *ia; |
struct in6_multi *in6m; |
struct in6_multi *in6m; |
|
int s; |
|
|
IFP_TO_IA6(oia->ia_ifp, ia); |
s = pserialize_read_enter(); |
|
ia = in6_get_ia_from_ifp(oia->ia_ifp); |
if (ia) { /* there is another address */ |
if (ia) { /* there is another address */ |
KASSERT(ia != oia); |
KASSERT(ia != oia); |
while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { |
while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { |
LIST_REMOVE(in6m, in6m_entry); |
LIST_REMOVE(in6m, in6m_entry); |
IFAREF(&ia->ia_ifa); |
ifaref(&ia->ia_ifa); |
IFAFREE(&in6m->in6m_ia->ia_ifa); |
ifafree(&in6m->in6m_ia->ia_ifa); |
in6m->in6m_ia = ia; |
in6m->in6m_ia = ia; |
|
/* FIXME NOMPSAFE: need to lock */ |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
} |
} |
} else { /* last address on this if deleted, save */ |
} else { /* last address on this if deleted, save */ |
Line 815 in6_savemkludge(struct in6_ifaddr *oia) |
|
Line 877 in6_savemkludge(struct in6_ifaddr *oia) |
|
|
|
while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { |
while ((in6m = LIST_FIRST(&oia->ia6_multiaddrs)) != NULL) { |
LIST_REMOVE(in6m, in6m_entry); |
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; |
in6m->in6m_ia = NULL; |
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); |
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); |
} |
} |
} |
} |
|
pserialize_read_exit(s); |
} |
} |
|
|
/* |
/* |
Line 842 in6_restoremkludge(struct in6_ifaddr *ia |
|
Line 905 in6_restoremkludge(struct in6_ifaddr *ia |
|
while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) { |
while ((in6m = LIST_FIRST(&mk->mk_head)) != NULL) { |
LIST_REMOVE(in6m, in6m_entry); |
LIST_REMOVE(in6m, in6m_entry); |
in6m->in6m_ia = ia; |
in6m->in6m_ia = ia; |
IFAREF(&ia->ia_ifa); |
ifaref(&ia->ia_ifa); |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
LIST_INSERT_HEAD(&ia->ia6_multiaddrs, in6m, in6m_entry); |
} |
} |
} |
} |
Line 962 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1025 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
uint32_t tmp; |
uint32_t tmp; |
int error; |
int error; |
size_t written; |
size_t written; |
|
struct psref psref, psref_ia; |
|
int bound, s; |
|
|
if (namelen != 1) |
if (namelen != 1) |
return EINVAL; |
return EINVAL; |
|
|
ifp = if_byindex(name[0]); |
bound = curlwp_bind(); |
if (ifp == NULL) |
ifp = if_get_byindex(name[0], &psref); |
|
if (ifp == NULL) { |
|
curlwp_bindx(bound); |
return ENODEV; |
return ENODEV; |
|
} |
|
|
if (oldp == NULL) { |
if (oldp == NULL) { |
*oldlenp = 0; |
*oldlenp = 0; |
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { |
s = pserialize_read_enter(); |
if (ifa->ifa_addr == NULL) |
IFADDR_READER_FOREACH(ifa, ifp) { |
continue; |
|
if (ifa->ifa_addr->sa_family != AF_INET6) |
if (ifa->ifa_addr->sa_family != AF_INET6) |
continue; |
continue; |
ifa6 = (struct in6_ifaddr *)ifa; |
ifa6 = (struct in6_ifaddr *)ifa; |
Line 983 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1050 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
sizeof(uint32_t); |
sizeof(uint32_t); |
} |
} |
} |
} |
|
pserialize_read_exit(s); |
|
if_put(ifp, &psref); |
|
curlwp_bindx(bound); |
return 0; |
return 0; |
} |
} |
|
|
error = 0; |
error = 0; |
written = 0; |
written = 0; |
TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { |
s = pserialize_read_enter(); |
if (ifa->ifa_addr == NULL) |
IFADDR_READER_FOREACH(ifa, ifp) { |
continue; |
|
if (ifa->ifa_addr->sa_family != AF_INET6) |
if (ifa->ifa_addr->sa_family != AF_INET6) |
continue; |
continue; |
|
|
|
ifa_acquire(ifa, &psref_ia); |
|
pserialize_read_exit(s); |
|
|
ifa6 = (struct in6_ifaddr *)ifa; |
ifa6 = (struct in6_ifaddr *)ifa; |
LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) { |
LIST_FOREACH(in6m, &ifa6->ia6_multiaddrs, in6m_entry) { |
if (written + 2 * sizeof(struct in6_addr) + |
if (written + 2 * sizeof(struct in6_addr) + |
Line 1017 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1090 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
oldp = (char *)oldp + sizeof(tmp); |
oldp = (char *)oldp + sizeof(tmp); |
written += sizeof(tmp); |
written += sizeof(tmp); |
} |
} |
|
|
|
s = pserialize_read_enter(); |
|
ifa_release(ifa, &psref_ia); |
} |
} |
|
pserialize_read_exit(s); |
done: |
done: |
|
ifa_release(ifa, &psref_ia); |
|
if_put(ifp, &psref); |
|
curlwp_bindx(bound); |
*oldlenp = written; |
*oldlenp = written; |
return error; |
return error; |
} |
} |
|
|
SYSCTL_SETUP(sysctl_in6_mklude_setup, "sysctl net.inet6.multicast_kludge subtree setup") |
void |
|
in6_sysctl_multicast_setup(struct sysctllog **clog) |
{ |
{ |
|
|
sysctl_createv(clog, 0, NULL, NULL, |
sysctl_createv(clog, 0, NULL, NULL, |
CTLFLAG_PERMANENT, |
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", |
CTLTYPE_NODE, "multicast", |
SYSCTL_DESCR("Multicast information"), |
SYSCTL_DESCR("Multicast information"), |
in6_multicast_sysctl, 0, NULL, 0, |
in6_multicast_sysctl, 0, NULL, 0, |