version 1.73, 2016/07/20 07:37:51 |
version 1.74, 2016/08/01 03:15:31 |
Line 402 mld_input(struct mbuf *m, int off) |
|
Line 402 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 428 mld_input(struct mbuf *m, int off) |
|
Line 430 mld_input(struct mbuf *m, int off) |
|
*/ |
*/ |
timer = ntohs(mldh->mld_maxdelay); |
timer = ntohs(mldh->mld_maxdelay); |
|
|
ia = in6_get_ia_from_ifp(ifp); |
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 457 mld_input(struct mbuf *m, int off) |
|
Line 463 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 514 mld_sendpkt(struct in6_multi *in6m, int |
|
Line 522 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 522 mld_sendpkt(struct in6_multi *in6m, int |
|
Line 532 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 645 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 666 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 664 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 686 in6_addmulti(struct in6_addr *maddr6, st |
|
callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); |
callout_init(&in6m->in6m_timer_ch, CALLOUT_MPSAFE); |
callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); |
callout_setfunc(&in6m->in6m_timer_ch, mld_timeo, in6m); |
|
|
|
_s = pserialize_read_enter(); |
ia = in6_get_ia_from_ifp(ifp); |
ia = in6_get_ia_from_ifp(ifp); |
if (ia == NULL) { |
if (ia == NULL) { |
|
pserialize_read_exit(_s); |
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 674 in6_addmulti(struct in6_addr *maddr6, st |
|
Line 698 in6_addmulti(struct in6_addr *maddr6, st |
|
} |
} |
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 816 in6_savemkludge(struct in6_ifaddr *oia) |
|
Line 842 in6_savemkludge(struct in6_ifaddr *oia) |
|
{ |
{ |
struct in6_ifaddr *ia; |
struct in6_ifaddr *ia; |
struct in6_multi *in6m; |
struct in6_multi *in6m; |
|
int s; |
|
|
|
s = pserialize_read_enter(); |
ia = in6_get_ia_from_ifp(oia->ia_ifp); |
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); |
Line 825 in6_savemkludge(struct in6_ifaddr *oia) |
|
Line 853 in6_savemkludge(struct in6_ifaddr *oia) |
|
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 844 in6_savemkludge(struct in6_ifaddr *oia) |
|
Line 873 in6_savemkludge(struct in6_ifaddr *oia) |
|
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); |
LIST_INSERT_HEAD(&mk->mk_head, in6m, in6m_entry); |
} |
} |
} |
} |
|
pserialize_read_exit(s); |
} |
} |
|
|
/* |
/* |
Line 986 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1016 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
uint32_t tmp; |
uint32_t tmp; |
int error; |
int error; |
size_t written; |
size_t written; |
struct psref psref; |
struct psref psref, psref_ia; |
int bound; |
int bound, s; |
|
|
if (namelen != 1) |
if (namelen != 1) |
return EINVAL; |
return EINVAL; |
Line 1001 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1031 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
|
|
if (oldp == NULL) { |
if (oldp == NULL) { |
*oldlenp = 0; |
*oldlenp = 0; |
|
s = pserialize_read_enter(); |
IFADDR_READER_FOREACH(ifa, ifp) { |
IFADDR_READER_FOREACH(ifa, ifp) { |
if (ifa->ifa_addr->sa_family != AF_INET6) |
if (ifa->ifa_addr->sa_family != AF_INET6) |
continue; |
continue; |
Line 1010 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1041 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
sizeof(uint32_t); |
sizeof(uint32_t); |
} |
} |
} |
} |
|
pserialize_read_exit(s); |
if_put(ifp, &psref); |
if_put(ifp, &psref); |
curlwp_bindx(bound); |
curlwp_bindx(bound); |
return 0; |
return 0; |
Line 1017 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1049 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
|
|
error = 0; |
error = 0; |
written = 0; |
written = 0; |
|
s = pserialize_read_enter(); |
IFADDR_READER_FOREACH(ifa, ifp) { |
IFADDR_READER_FOREACH(ifa, ifp) { |
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 1044 in6_multicast_sysctl(SYSCTLFN_ARGS) |
|
Line 1081 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); |
if_put(ifp, &psref); |
curlwp_bindx(bound); |
curlwp_bindx(bound); |
*oldlenp = written; |
*oldlenp = written; |