Lines 243-248
Link Here
|
243 |
SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RWTUN, |
243 |
SYSCTL_INT(_net_inet6_mld, OID_AUTO, v1enable, CTLFLAG_RWTUN, |
244 |
&mld_v1enable, 0, "Enable fallback to MLDv1"); |
244 |
&mld_v1enable, 0, "Enable fallback to MLDv1"); |
245 |
|
245 |
|
|
|
246 |
static int mld_v2enable = 1; |
247 |
SYSCTL_INT(_net_inet6_mld, OID_AUTO, v2enable, CTLFLAG_RWTUN, |
248 |
&mld_v2enable, 0, "Enable MLDv2"); |
249 |
|
246 |
static int mld_use_allow = 1; |
250 |
static int mld_use_allow = 1; |
247 |
SYSCTL_INT(_net_inet6_mld, OID_AUTO, use_allow, CTLFLAG_RWTUN, |
251 |
SYSCTL_INT(_net_inet6_mld, OID_AUTO, use_allow, CTLFLAG_RWTUN, |
248 |
&mld_use_allow, 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves"); |
252 |
&mld_use_allow, 0, "Use ALLOW/BLOCK for RFC 4604 SSM joins/leaves"); |
Lines 533-577
Link Here
|
533 |
* XXX This routine is also bitten by unlocked ifma_protospec access. |
537 |
* XXX This routine is also bitten by unlocked ifma_protospec access. |
534 |
*/ |
538 |
*/ |
535 |
void |
539 |
void |
536 |
mld_ifdetach(struct ifnet *ifp) |
540 |
mld_ifdetach(struct ifnet *ifp, struct in6_multi_head *inmh) |
537 |
{ |
541 |
{ |
|
|
542 |
struct epoch_tracker et; |
538 |
struct mld_ifsoftc *mli; |
543 |
struct mld_ifsoftc *mli; |
539 |
struct ifmultiaddr *ifma, *next; |
544 |
struct ifmultiaddr *ifma; |
540 |
struct in6_multi *inm; |
545 |
struct in6_multi *inm; |
541 |
struct in6_multi_head inmh; |
|
|
542 |
|
546 |
|
543 |
CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp, |
547 |
CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp, |
544 |
if_name(ifp)); |
548 |
if_name(ifp)); |
545 |
|
549 |
|
546 |
SLIST_INIT(&inmh); |
|
|
547 |
IN6_MULTI_LIST_LOCK_ASSERT(); |
550 |
IN6_MULTI_LIST_LOCK_ASSERT(); |
548 |
MLD_LOCK(); |
551 |
MLD_LOCK(); |
549 |
|
552 |
|
550 |
mli = MLD_IFINFO(ifp); |
553 |
mli = MLD_IFINFO(ifp); |
551 |
if (mli->mli_version == MLD_VERSION_2) { |
554 |
IF_ADDR_WLOCK(ifp); |
552 |
IF_ADDR_WLOCK(ifp); |
555 |
/* |
553 |
restart: |
556 |
* Extract list of in6_multi associated with the detaching ifp |
554 |
CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) { |
557 |
* which the PF_INET6 layer is about to release. |
555 |
if (ifma->ifma_addr->sa_family != AF_INET6 || |
558 |
*/ |
556 |
ifma->ifma_protospec == NULL) |
559 |
NET_EPOCH_ENTER(et); |
557 |
continue; |
560 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
558 |
inm = (struct in6_multi *)ifma->ifma_protospec; |
561 |
inm = in6m_ifmultiaddr_get_inm(ifma); |
|
|
562 |
if (inm == NULL) |
563 |
continue; |
564 |
in6m_disconnect_locked(inmh, inm); |
565 |
|
566 |
if (mli->mli_version == MLD_VERSION_2) { |
567 |
in6m_clear_recorded(inm); |
568 |
|
569 |
/* |
570 |
* We need to release the final reference held |
571 |
* for issuing the INCLUDE {}. |
572 |
*/ |
559 |
if (inm->in6m_state == MLD_LEAVING_MEMBER) { |
573 |
if (inm->in6m_state == MLD_LEAVING_MEMBER) { |
560 |
in6m_disconnect(inm); |
574 |
inm->in6m_state = MLD_NOT_MEMBER; |
561 |
in6m_rele_locked(&inmh, inm); |
575 |
in6m_rele_locked(inmh, inm); |
562 |
ifma->ifma_protospec = NULL; |
|
|
563 |
} |
576 |
} |
564 |
in6m_clear_recorded(inm); |
|
|
565 |
if (__predict_false(ifma6_restart)) { |
566 |
ifma6_restart = false; |
567 |
goto restart; |
568 |
} |
569 |
} |
577 |
} |
570 |
IF_ADDR_WUNLOCK(ifp); |
|
|
571 |
} |
578 |
} |
572 |
|
579 |
NET_EPOCH_EXIT(et); |
|
|
580 |
IF_ADDR_WUNLOCK(ifp); |
573 |
MLD_UNLOCK(); |
581 |
MLD_UNLOCK(); |
574 |
in6m_release_list_deferred(&inmh); |
|
|
575 |
} |
582 |
} |
576 |
|
583 |
|
577 |
/* |
584 |
/* |
Lines 705-714
Link Here
|
705 |
CTR2(KTR_MLD, "process v1 general query on ifp %p(%s)", |
712 |
CTR2(KTR_MLD, "process v1 general query on ifp %p(%s)", |
706 |
ifp, if_name(ifp)); |
713 |
ifp, if_name(ifp)); |
707 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
714 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
708 |
if (ifma->ifma_addr->sa_family != AF_INET6 || |
715 |
inm = in6m_ifmultiaddr_get_inm(ifma); |
709 |
ifma->ifma_protospec == NULL) |
716 |
if (inm == NULL) |
710 |
continue; |
717 |
continue; |
711 |
inm = (struct in6_multi *)ifma->ifma_protospec; |
|
|
712 |
mld_v1_update_group(inm, timer); |
718 |
mld_v1_update_group(inm, timer); |
713 |
} |
719 |
} |
714 |
} else { |
720 |
} else { |
Lines 819-824
Link Here
|
819 |
|
825 |
|
820 |
is_general_query = 0; |
826 |
is_general_query = 0; |
821 |
|
827 |
|
|
|
828 |
if (!mld_v2enable) { |
829 |
CTR3(KTR_MLD, "ignore v2 query %s on ifp %p(%s)", |
830 |
ip6_sprintf(ip6tbuf, &mld->mld_addr), |
831 |
ifp, if_name(ifp)); |
832 |
return (0); |
833 |
} |
834 |
|
822 |
/* |
835 |
/* |
823 |
* RFC3810 Section 6.2: MLD queries must originate from |
836 |
* RFC3810 Section 6.2: MLD queries must originate from |
824 |
* a router's link-local address. |
837 |
* a router's link-local address. |
Lines 1332-1346
Link Here
|
1332 |
static void |
1345 |
static void |
1333 |
mld_fasttimo_vnet(void) |
1346 |
mld_fasttimo_vnet(void) |
1334 |
{ |
1347 |
{ |
|
|
1348 |
struct in6_multi_head inmh; |
1349 |
struct epoch_tracker et; |
1335 |
struct mbufq scq; /* State-change packets */ |
1350 |
struct mbufq scq; /* State-change packets */ |
1336 |
struct mbufq qrq; /* Query response packets */ |
1351 |
struct mbufq qrq; /* Query response packets */ |
1337 |
struct ifnet *ifp; |
1352 |
struct ifnet *ifp; |
1338 |
struct mld_ifsoftc *mli; |
1353 |
struct mld_ifsoftc *mli; |
1339 |
struct ifmultiaddr *ifma, *next; |
1354 |
struct ifmultiaddr *ifma; |
1340 |
struct in6_multi *inm, *tinm; |
1355 |
struct in6_multi *inm, *tinm; |
1341 |
struct in6_multi_head inmh; |
|
|
1342 |
int uri_fasthz; |
1356 |
int uri_fasthz; |
1343 |
|
1357 |
|
|
|
1358 |
SLIST_INIT(&inmh); |
1344 |
uri_fasthz = 0; |
1359 |
uri_fasthz = 0; |
1345 |
|
1360 |
|
1346 |
/* |
1361 |
/* |
Lines 1353-1359
Link Here
|
1353 |
!V_state_change_timers_running6) |
1368 |
!V_state_change_timers_running6) |
1354 |
return; |
1369 |
return; |
1355 |
|
1370 |
|
1356 |
SLIST_INIT(&inmh); |
|
|
1357 |
IN6_MULTI_LIST_LOCK(); |
1371 |
IN6_MULTI_LIST_LOCK(); |
1358 |
MLD_LOCK(); |
1372 |
MLD_LOCK(); |
1359 |
|
1373 |
|
Lines 1399-1410
Link Here
|
1399 |
} |
1413 |
} |
1400 |
|
1414 |
|
1401 |
IF_ADDR_WLOCK(ifp); |
1415 |
IF_ADDR_WLOCK(ifp); |
1402 |
restart: |
1416 |
NET_EPOCH_ENTER(et); |
1403 |
CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) { |
1417 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
1404 |
if (ifma->ifma_addr->sa_family != AF_INET6 || |
1418 |
inm = in6m_ifmultiaddr_get_inm(ifma); |
1405 |
ifma->ifma_protospec == NULL) |
1419 |
if (inm == NULL) |
1406 |
continue; |
1420 |
continue; |
1407 |
inm = (struct in6_multi *)ifma->ifma_protospec; |
|
|
1408 |
switch (mli->mli_version) { |
1421 |
switch (mli->mli_version) { |
1409 |
case MLD_VERSION_1: |
1422 |
case MLD_VERSION_1: |
1410 |
mld_v1_process_group_timer(&inmh, inm); |
1423 |
mld_v1_process_group_timer(&inmh, inm); |
Lines 1414-1424
Link Here
|
1414 |
&scq, inm, uri_fasthz); |
1427 |
&scq, inm, uri_fasthz); |
1415 |
break; |
1428 |
break; |
1416 |
} |
1429 |
} |
1417 |
if (__predict_false(ifma6_restart)) { |
|
|
1418 |
ifma6_restart = false; |
1419 |
goto restart; |
1420 |
} |
1421 |
} |
1430 |
} |
|
|
1431 |
NET_EPOCH_EXIT(et); |
1422 |
IF_ADDR_WUNLOCK(ifp); |
1432 |
IF_ADDR_WUNLOCK(ifp); |
1423 |
|
1433 |
|
1424 |
switch (mli->mli_version) { |
1434 |
switch (mli->mli_version) { |
Lines 1488-1495
Link Here
|
1488 |
case MLD_REPORTING_MEMBER: |
1498 |
case MLD_REPORTING_MEMBER: |
1489 |
if (report_timer_expired) { |
1499 |
if (report_timer_expired) { |
1490 |
inm->in6m_state = MLD_IDLE_MEMBER; |
1500 |
inm->in6m_state = MLD_IDLE_MEMBER; |
1491 |
in6m_disconnect(inm); |
1501 |
in6m_disconnect_locked(inmh, inm); |
1492 |
in6m_rele_locked(inmh, inm); |
|
|
1493 |
} |
1502 |
} |
1494 |
break; |
1503 |
break; |
1495 |
case MLD_G_QUERY_PENDING_MEMBER: |
1504 |
case MLD_G_QUERY_PENDING_MEMBER: |
Lines 1613-1619
Link Here
|
1613 |
if (inm->in6m_state == MLD_LEAVING_MEMBER && |
1622 |
if (inm->in6m_state == MLD_LEAVING_MEMBER && |
1614 |
inm->in6m_scrv == 0) { |
1623 |
inm->in6m_scrv == 0) { |
1615 |
inm->in6m_state = MLD_NOT_MEMBER; |
1624 |
inm->in6m_state = MLD_NOT_MEMBER; |
1616 |
in6m_disconnect(inm); |
1625 |
in6m_disconnect_locked(inmh, inm); |
1617 |
in6m_rele_locked(inmh, inm); |
1626 |
in6m_rele_locked(inmh, inm); |
1618 |
} |
1627 |
} |
1619 |
} |
1628 |
} |
Lines 1658-1667
Link Here
|
1658 |
static void |
1667 |
static void |
1659 |
mld_v2_cancel_link_timers(struct mld_ifsoftc *mli) |
1668 |
mld_v2_cancel_link_timers(struct mld_ifsoftc *mli) |
1660 |
{ |
1669 |
{ |
1661 |
struct ifmultiaddr *ifma, *next; |
1670 |
struct epoch_tracker et; |
|
|
1671 |
struct in6_multi_head inmh; |
1672 |
struct ifmultiaddr *ifma; |
1662 |
struct ifnet *ifp; |
1673 |
struct ifnet *ifp; |
1663 |
struct in6_multi *inm; |
1674 |
struct in6_multi *inm; |
1664 |
struct in6_multi_head inmh; |
|
|
1665 |
|
1675 |
|
1666 |
CTR3(KTR_MLD, "%s: cancel v2 timers on ifp %p(%s)", __func__, |
1676 |
CTR3(KTR_MLD, "%s: cancel v2 timers on ifp %p(%s)", __func__, |
1667 |
mli->mli_ifp, if_name(mli->mli_ifp)); |
1677 |
mli->mli_ifp, if_name(mli->mli_ifp)); |
Lines 1684-1695
Link Here
|
1684 |
ifp = mli->mli_ifp; |
1694 |
ifp = mli->mli_ifp; |
1685 |
|
1695 |
|
1686 |
IF_ADDR_WLOCK(ifp); |
1696 |
IF_ADDR_WLOCK(ifp); |
1687 |
restart: |
1697 |
NET_EPOCH_ENTER(et); |
1688 |
CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) { |
1698 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
1689 |
if (ifma->ifma_addr->sa_family != AF_INET6 || |
1699 |
inm = in6m_ifmultiaddr_get_inm(ifma); |
1690 |
ifma->ifma_protospec == NULL) |
1700 |
if (inm == NULL) |
1691 |
continue; |
1701 |
continue; |
1692 |
inm = (struct in6_multi *)ifma->ifma_protospec; |
|
|
1693 |
switch (inm->in6m_state) { |
1702 |
switch (inm->in6m_state) { |
1694 |
case MLD_NOT_MEMBER: |
1703 |
case MLD_NOT_MEMBER: |
1695 |
case MLD_SILENT_MEMBER: |
1704 |
case MLD_SILENT_MEMBER: |
Lines 1704-1712
Link Here
|
1704 |
* version, we need to release the final |
1713 |
* version, we need to release the final |
1705 |
* reference held for issuing the INCLUDE {}. |
1714 |
* reference held for issuing the INCLUDE {}. |
1706 |
*/ |
1715 |
*/ |
1707 |
in6m_disconnect(inm); |
|
|
1708 |
in6m_rele_locked(&inmh, inm); |
1716 |
in6m_rele_locked(&inmh, inm); |
1709 |
ifma->ifma_protospec = NULL; |
|
|
1710 |
/* FALLTHROUGH */ |
1717 |
/* FALLTHROUGH */ |
1711 |
case MLD_G_QUERY_PENDING_MEMBER: |
1718 |
case MLD_G_QUERY_PENDING_MEMBER: |
1712 |
case MLD_SG_QUERY_PENDING_MEMBER: |
1719 |
case MLD_SG_QUERY_PENDING_MEMBER: |
Lines 1722-1732
Link Here
|
1722 |
mbufq_drain(&inm->in6m_scq); |
1729 |
mbufq_drain(&inm->in6m_scq); |
1723 |
break; |
1730 |
break; |
1724 |
} |
1731 |
} |
1725 |
if (__predict_false(ifma6_restart)) { |
|
|
1726 |
ifma6_restart = false; |
1727 |
goto restart; |
1728 |
} |
1729 |
} |
1732 |
} |
|
|
1733 |
NET_EPOCH_EXIT(et); |
1730 |
IF_ADDR_WUNLOCK(ifp); |
1734 |
IF_ADDR_WUNLOCK(ifp); |
1731 |
in6m_release_list_deferred(&inmh); |
1735 |
in6m_release_list_deferred(&inmh); |
1732 |
} |
1736 |
} |
Lines 1899-1904
Link Here
|
1899 |
error = 0; |
1903 |
error = 0; |
1900 |
|
1904 |
|
1901 |
/* |
1905 |
/* |
|
|
1906 |
* Check if the in6_multi has already been disconnected. |
1907 |
*/ |
1908 |
if (inm->in6m_ifp == NULL) { |
1909 |
CTR1(KTR_MLD, "%s: inm is disconnected", __func__); |
1910 |
return (0); |
1911 |
} |
1912 |
|
1913 |
/* |
1902 |
* Try to detect if the upper layer just asked us to change state |
1914 |
* Try to detect if the upper layer just asked us to change state |
1903 |
* for an interface which has now gone away. |
1915 |
* for an interface which has now gone away. |
1904 |
*/ |
1916 |
*/ |
Lines 2007-2013
Link Here
|
2007 |
*/ |
2019 |
*/ |
2008 |
if (mli->mli_version == MLD_VERSION_2 && |
2020 |
if (mli->mli_version == MLD_VERSION_2 && |
2009 |
inm->in6m_state == MLD_LEAVING_MEMBER) { |
2021 |
inm->in6m_state == MLD_LEAVING_MEMBER) { |
|
|
2022 |
in6m_trace("pre leaving member", inm); |
2010 |
inm->in6m_refcount--; |
2023 |
inm->in6m_refcount--; |
|
|
2024 |
MPASS(inm->in6m_refcount > 0); |
2011 |
} |
2025 |
} |
2012 |
inm->in6m_state = MLD_REPORTING_MEMBER; |
2026 |
inm->in6m_state = MLD_REPORTING_MEMBER; |
2013 |
|
2027 |
|
Lines 3012-3022
Link Here
|
3012 |
|
3026 |
|
3013 |
NET_EPOCH_ENTER(et); |
3027 |
NET_EPOCH_ENTER(et); |
3014 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
3028 |
CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
3015 |
if (ifma->ifma_addr->sa_family != AF_INET6 || |
3029 |
inm = in6m_ifmultiaddr_get_inm(ifma); |
3016 |
ifma->ifma_protospec == NULL) |
3030 |
if (inm == NULL) |
3017 |
continue; |
3031 |
continue; |
3018 |
|
|
|
3019 |
inm = (struct in6_multi *)ifma->ifma_protospec; |
3020 |
KASSERT(ifp == inm->in6m_ifp, |
3032 |
KASSERT(ifp == inm->in6m_ifp, |
3021 |
("%s: inconsistent ifp", __func__)); |
3033 |
("%s: inconsistent ifp", __func__)); |
3022 |
|
3034 |
|