491 * In Delaying Member state, our timer is running (ilm->ilm_timer
492 * < INFINITY). In Idle Member state, our timer is not running
493 * (ilm->ilm_timer == INFINITY).
494 *
495 * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
496 * we have heard a report from another member, or IGMP_IREPORTEDLAST
497 * if I sent the last report.
498 */
499 if ((igmpa->igmpa_code == 0) ||
500 (ipst->ips_igmp_max_version == IGMP_V1_ROUTER)) {
501 /*
502 * Query from an old router.
503 * Remember that the querier on this interface is old,
504 * and set the timer to the value in RFC 1112.
505 */
506 ill->ill_mcast_v1_time = 0;
507 ill->ill_mcast_v1_tset = 1;
508 if (ill->ill_mcast_type != IGMP_V1_ROUTER) {
509 ip1dbg(("Received IGMPv1 Query on %s, switching mode "
510 "to IGMP_V1_ROUTER\n", ill->ill_name));
511 atomic_add_16(&ill->ill_ifptr->illif_mcast_v1, 1);
512 ill->ill_mcast_type = IGMP_V1_ROUTER;
513 }
514
515 timer = SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY);
516
517 if (ipha->ipha_dst != htonl(INADDR_ALLHOSTS_GROUP) ||
518 igmpa->igmpa_group != 0) {
519 ++ipst->ips_igmpstat.igps_rcv_badqueries;
520 rw_exit(&ill->ill_mcast_lock);
521 ill_mcast_timer_start(ill->ill_ipst);
522 return (0);
523 }
524
525 } else {
526 in_addr_t group;
527
528 /*
529 * Query from a new router
530 * Simply do a validity check
531 */
532 group = igmpa->igmpa_group;
533 if (group != 0 && (!CLASSD(group))) {
534 ++ipst->ips_igmpstat.igps_rcv_badqueries;
535 rw_exit(&ill->ill_mcast_lock);
536 ill_mcast_timer_start(ill->ill_ipst);
537 return (0);
538 }
539
540 /*
541 * Switch interface state to v2 on receipt of a v2 query
542 * ONLY IF current state is v3. Let things be if current
543 * state if v1 but do reset the v2-querier-present timer.
544 */
545 if (ill->ill_mcast_type == IGMP_V3_ROUTER) {
546 ip1dbg(("Received IGMPv2 Query on %s, switching mode "
547 "to IGMP_V2_ROUTER", ill->ill_name));
548 atomic_add_16(&ill->ill_ifptr->illif_mcast_v2, 1);
549 ill->ill_mcast_type = IGMP_V2_ROUTER;
550 }
551 ill->ill_mcast_v2_time = 0;
552 ill->ill_mcast_v2_tset = 1;
553
554 timer = DSEC_TO_MSEC((int)igmpa->igmpa_code);
555 }
556
557 if (ip_debug > 1) {
558 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
559 "igmp_input: TIMER = igmp_code %d igmp_type 0x%x",
560 (int)ntohs(igmpa->igmpa_code),
561 (int)ntohs(igmpa->igmpa_type));
562 }
563
564 /*
565 * -Start the timers in all of our membership records
566 * for the physical interface on which the query
567 * arrived, excluding those that belong to the "all
568 * hosts" group (224.0.0.1).
1699 (ill->ill_mcast_v1_time >= OVQP(ill))) {
1700 if ((ill->ill_mcast_v2_tset > 0) ||
1701 (ipst->ips_igmp_max_version ==
1702 IGMP_V2_ROUTER)) {
1703 ip1dbg(("V1 query timer "
1704 "expired on %s; switching "
1705 "mode to IGMP_V2\n",
1706 ill->ill_name));
1707 ill->ill_mcast_type =
1708 IGMP_V2_ROUTER;
1709 } else {
1710 ip1dbg(("V1 query timer "
1711 "expired on %s; switching "
1712 "mode to IGMP_V3\n",
1713 ill->ill_name));
1714 ill->ill_mcast_type =
1715 IGMP_V3_ROUTER;
1716 }
1717 ill->ill_mcast_v1_time = 0;
1718 ill->ill_mcast_v1_tset = 0;
1719 atomic_add_16(&ifp->illif_mcast_v1, -1);
1720 }
1721 if ((ill->ill_mcast_type == IGMP_V2_ROUTER) &&
1722 (ipst->ips_igmp_max_version >= IGMP_V3_ROUTER) &&
1723 (ill->ill_mcast_v2_time >= OVQP(ill))) {
1724 ip1dbg(("V2 query timer expired on "
1725 "%s; switching mode to IGMP_V3\n",
1726 ill->ill_name));
1727 ill->ill_mcast_type = IGMP_V3_ROUTER;
1728 ill->ill_mcast_v2_time = 0;
1729 ill->ill_mcast_v2_tset = 0;
1730 atomic_add_16(&ifp->illif_mcast_v2, -1);
1731 }
1732 rw_exit(&ill->ill_mcast_lock);
1733 ill_refrele(ill);
1734 rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1735 }
1736 }
1737 rw_exit(&ipst->ips_ill_g_lock);
1738 ill_mcast_timer_start(ipst);
1739 mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
1740 ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
1741 MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1742 mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
1743 }
1744
1745 /*
1746 * mld_slowtimo:
1747 * - Resets to newer version if we didn't hear from the older version router
1748 * in MLD_AGE_THRESHOLD seconds.
1749 * - Restarts slowtimeout.
1750 * Check for ips_mld_max_version ensures that we don't revert to a higher
1769
1770 avl_tree = &ifp->illif_avl_by_ppa;
1771 for (ill = avl_first(avl_tree); ill != NULL;
1772 ill = avl_walk(avl_tree, ill, AVL_AFTER)) {
1773 /* Make sure the ill isn't going away. */
1774 if (!ill_check_and_refhold(ill))
1775 continue;
1776 rw_exit(&ipst->ips_ill_g_lock);
1777 rw_enter(&ill->ill_mcast_lock, RW_WRITER);
1778 if (ill->ill_mcast_v1_tset == 1)
1779 ill->ill_mcast_v1_time++;
1780 if ((ill->ill_mcast_type == MLD_V1_ROUTER) &&
1781 (ipst->ips_mld_max_version >= MLD_V2_ROUTER) &&
1782 (ill->ill_mcast_v1_time >= OVQP(ill))) {
1783 ip1dbg(("MLD query timer expired on"
1784 " %s; switching mode to MLD_V2\n",
1785 ill->ill_name));
1786 ill->ill_mcast_type = MLD_V2_ROUTER;
1787 ill->ill_mcast_v1_time = 0;
1788 ill->ill_mcast_v1_tset = 0;
1789 atomic_add_16(&ifp->illif_mcast_v1, -1);
1790 }
1791 rw_exit(&ill->ill_mcast_lock);
1792 ill_refrele(ill);
1793 rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1794 }
1795 }
1796 rw_exit(&ipst->ips_ill_g_lock);
1797 ill_mcast_timer_start(ipst);
1798 mutex_enter(&ipst->ips_mld_slowtimeout_lock);
1799 ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
1800 MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1801 mutex_exit(&ipst->ips_mld_slowtimeout_lock);
1802 }
1803
1804 /*
1805 * igmp_sendpkt:
1806 * This will send to ip_output_simple just like icmp_inbound.
1807 */
1808 static void
1809 igmp_sendpkt(ilm_t *ilm, uchar_t type, ipaddr_t addr)
2199 * INFINITY)
2200 *
2201 * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
2202 * we have heard a report from another member, or IGMP_IREPORTEDLAST
2203 * if I sent the last report.
2204 */
2205 v6group = &mldh->mld_addr;
2206 if (!(IN6_IS_ADDR_UNSPECIFIED(v6group)) &&
2207 ((!IN6_IS_ADDR_MULTICAST(v6group)))) {
2208 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembBadQueries);
2209 return (0);
2210 }
2211
2212 /* Need to do compatibility mode checking */
2213 rw_enter(&ill->ill_mcast_lock, RW_WRITER);
2214 ill->ill_mcast_v1_time = 0;
2215 ill->ill_mcast_v1_tset = 1;
2216 if (ill->ill_mcast_type == MLD_V2_ROUTER) {
2217 ip1dbg(("Received MLDv1 Query on %s, switching mode to "
2218 "MLD_V1_ROUTER\n", ill->ill_name));
2219 atomic_add_16(&ill->ill_ifptr->illif_mcast_v1, 1);
2220 ill->ill_mcast_type = MLD_V1_ROUTER;
2221 }
2222
2223 timer = (int)ntohs(mldh->mld_maxdelay);
2224 if (ip_debug > 1) {
2225 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
2226 "mld_input: TIMER = mld_maxdelay %d mld_type 0x%x",
2227 timer, (int)mldh->mld_type);
2228 }
2229
2230 /*
2231 * -Start the timers in all of our membership records for
2232 * the physical interface on which the query arrived,
2233 * excl:
2234 * 1. those that belong to the "all hosts" group,
2235 * 2. those with 0 scope, or 1 node-local scope.
2236 *
2237 * -Restart any timer that is already running but has a value
2238 * longer that the requested timeout.
2239 * -Use the value specified in the query message as the
|
491 * In Delaying Member state, our timer is running (ilm->ilm_timer
492 * < INFINITY). In Idle Member state, our timer is not running
493 * (ilm->ilm_timer == INFINITY).
494 *
495 * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
496 * we have heard a report from another member, or IGMP_IREPORTEDLAST
497 * if I sent the last report.
498 */
499 if ((igmpa->igmpa_code == 0) ||
500 (ipst->ips_igmp_max_version == IGMP_V1_ROUTER)) {
501 /*
502 * Query from an old router.
503 * Remember that the querier on this interface is old,
504 * and set the timer to the value in RFC 1112.
505 */
506 ill->ill_mcast_v1_time = 0;
507 ill->ill_mcast_v1_tset = 1;
508 if (ill->ill_mcast_type != IGMP_V1_ROUTER) {
509 ip1dbg(("Received IGMPv1 Query on %s, switching mode "
510 "to IGMP_V1_ROUTER\n", ill->ill_name));
511 atomic_inc_16(&ill->ill_ifptr->illif_mcast_v1);
512 ill->ill_mcast_type = IGMP_V1_ROUTER;
513 }
514
515 timer = SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY);
516
517 if (ipha->ipha_dst != htonl(INADDR_ALLHOSTS_GROUP) ||
518 igmpa->igmpa_group != 0) {
519 ++ipst->ips_igmpstat.igps_rcv_badqueries;
520 rw_exit(&ill->ill_mcast_lock);
521 ill_mcast_timer_start(ill->ill_ipst);
522 return (0);
523 }
524
525 } else {
526 in_addr_t group;
527
528 /*
529 * Query from a new router
530 * Simply do a validity check
531 */
532 group = igmpa->igmpa_group;
533 if (group != 0 && (!CLASSD(group))) {
534 ++ipst->ips_igmpstat.igps_rcv_badqueries;
535 rw_exit(&ill->ill_mcast_lock);
536 ill_mcast_timer_start(ill->ill_ipst);
537 return (0);
538 }
539
540 /*
541 * Switch interface state to v2 on receipt of a v2 query
542 * ONLY IF current state is v3. Let things be if current
543 * state if v1 but do reset the v2-querier-present timer.
544 */
545 if (ill->ill_mcast_type == IGMP_V3_ROUTER) {
546 ip1dbg(("Received IGMPv2 Query on %s, switching mode "
547 "to IGMP_V2_ROUTER", ill->ill_name));
548 atomic_inc_16(&ill->ill_ifptr->illif_mcast_v2);
549 ill->ill_mcast_type = IGMP_V2_ROUTER;
550 }
551 ill->ill_mcast_v2_time = 0;
552 ill->ill_mcast_v2_tset = 1;
553
554 timer = DSEC_TO_MSEC((int)igmpa->igmpa_code);
555 }
556
557 if (ip_debug > 1) {
558 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
559 "igmp_input: TIMER = igmp_code %d igmp_type 0x%x",
560 (int)ntohs(igmpa->igmpa_code),
561 (int)ntohs(igmpa->igmpa_type));
562 }
563
564 /*
565 * -Start the timers in all of our membership records
566 * for the physical interface on which the query
567 * arrived, excluding those that belong to the "all
568 * hosts" group (224.0.0.1).
1699 (ill->ill_mcast_v1_time >= OVQP(ill))) {
1700 if ((ill->ill_mcast_v2_tset > 0) ||
1701 (ipst->ips_igmp_max_version ==
1702 IGMP_V2_ROUTER)) {
1703 ip1dbg(("V1 query timer "
1704 "expired on %s; switching "
1705 "mode to IGMP_V2\n",
1706 ill->ill_name));
1707 ill->ill_mcast_type =
1708 IGMP_V2_ROUTER;
1709 } else {
1710 ip1dbg(("V1 query timer "
1711 "expired on %s; switching "
1712 "mode to IGMP_V3\n",
1713 ill->ill_name));
1714 ill->ill_mcast_type =
1715 IGMP_V3_ROUTER;
1716 }
1717 ill->ill_mcast_v1_time = 0;
1718 ill->ill_mcast_v1_tset = 0;
1719 atomic_dec_16(&ifp->illif_mcast_v1);
1720 }
1721 if ((ill->ill_mcast_type == IGMP_V2_ROUTER) &&
1722 (ipst->ips_igmp_max_version >= IGMP_V3_ROUTER) &&
1723 (ill->ill_mcast_v2_time >= OVQP(ill))) {
1724 ip1dbg(("V2 query timer expired on "
1725 "%s; switching mode to IGMP_V3\n",
1726 ill->ill_name));
1727 ill->ill_mcast_type = IGMP_V3_ROUTER;
1728 ill->ill_mcast_v2_time = 0;
1729 ill->ill_mcast_v2_tset = 0;
1730 atomic_dec_16(&ifp->illif_mcast_v2);
1731 }
1732 rw_exit(&ill->ill_mcast_lock);
1733 ill_refrele(ill);
1734 rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1735 }
1736 }
1737 rw_exit(&ipst->ips_ill_g_lock);
1738 ill_mcast_timer_start(ipst);
1739 mutex_enter(&ipst->ips_igmp_slowtimeout_lock);
1740 ipst->ips_igmp_slowtimeout_id = timeout(igmp_slowtimo, (void *)ipst,
1741 MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1742 mutex_exit(&ipst->ips_igmp_slowtimeout_lock);
1743 }
1744
1745 /*
1746 * mld_slowtimo:
1747 * - Resets to newer version if we didn't hear from the older version router
1748 * in MLD_AGE_THRESHOLD seconds.
1749 * - Restarts slowtimeout.
1750 * Check for ips_mld_max_version ensures that we don't revert to a higher
1769
1770 avl_tree = &ifp->illif_avl_by_ppa;
1771 for (ill = avl_first(avl_tree); ill != NULL;
1772 ill = avl_walk(avl_tree, ill, AVL_AFTER)) {
1773 /* Make sure the ill isn't going away. */
1774 if (!ill_check_and_refhold(ill))
1775 continue;
1776 rw_exit(&ipst->ips_ill_g_lock);
1777 rw_enter(&ill->ill_mcast_lock, RW_WRITER);
1778 if (ill->ill_mcast_v1_tset == 1)
1779 ill->ill_mcast_v1_time++;
1780 if ((ill->ill_mcast_type == MLD_V1_ROUTER) &&
1781 (ipst->ips_mld_max_version >= MLD_V2_ROUTER) &&
1782 (ill->ill_mcast_v1_time >= OVQP(ill))) {
1783 ip1dbg(("MLD query timer expired on"
1784 " %s; switching mode to MLD_V2\n",
1785 ill->ill_name));
1786 ill->ill_mcast_type = MLD_V2_ROUTER;
1787 ill->ill_mcast_v1_time = 0;
1788 ill->ill_mcast_v1_tset = 0;
1789 atomic_dec_16(&ifp->illif_mcast_v1);
1790 }
1791 rw_exit(&ill->ill_mcast_lock);
1792 ill_refrele(ill);
1793 rw_enter(&ipst->ips_ill_g_lock, RW_READER);
1794 }
1795 }
1796 rw_exit(&ipst->ips_ill_g_lock);
1797 ill_mcast_timer_start(ipst);
1798 mutex_enter(&ipst->ips_mld_slowtimeout_lock);
1799 ipst->ips_mld_slowtimeout_id = timeout(mld_slowtimo, (void *)ipst,
1800 MSEC_TO_TICK(MCAST_SLOWTIMO_INTERVAL));
1801 mutex_exit(&ipst->ips_mld_slowtimeout_lock);
1802 }
1803
1804 /*
1805 * igmp_sendpkt:
1806 * This will send to ip_output_simple just like icmp_inbound.
1807 */
1808 static void
1809 igmp_sendpkt(ilm_t *ilm, uchar_t type, ipaddr_t addr)
2199 * INFINITY)
2200 *
2201 * The flag is ilm->ilm_state, it is set to IGMP_OTHERMEMBER if
2202 * we have heard a report from another member, or IGMP_IREPORTEDLAST
2203 * if I sent the last report.
2204 */
2205 v6group = &mldh->mld_addr;
2206 if (!(IN6_IS_ADDR_UNSPECIFIED(v6group)) &&
2207 ((!IN6_IS_ADDR_MULTICAST(v6group)))) {
2208 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembBadQueries);
2209 return (0);
2210 }
2211
2212 /* Need to do compatibility mode checking */
2213 rw_enter(&ill->ill_mcast_lock, RW_WRITER);
2214 ill->ill_mcast_v1_time = 0;
2215 ill->ill_mcast_v1_tset = 1;
2216 if (ill->ill_mcast_type == MLD_V2_ROUTER) {
2217 ip1dbg(("Received MLDv1 Query on %s, switching mode to "
2218 "MLD_V1_ROUTER\n", ill->ill_name));
2219 atomic_inc_16(&ill->ill_ifptr->illif_mcast_v1);
2220 ill->ill_mcast_type = MLD_V1_ROUTER;
2221 }
2222
2223 timer = (int)ntohs(mldh->mld_maxdelay);
2224 if (ip_debug > 1) {
2225 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE,
2226 "mld_input: TIMER = mld_maxdelay %d mld_type 0x%x",
2227 timer, (int)mldh->mld_type);
2228 }
2229
2230 /*
2231 * -Start the timers in all of our membership records for
2232 * the physical interface on which the query arrived,
2233 * excl:
2234 * 1. those that belong to the "all hosts" group,
2235 * 2. those with 0 scope, or 1 node-local scope.
2236 *
2237 * -Restart any timer that is already running but has a value
2238 * longer that the requested timeout.
2239 * -Use the value specified in the query message as the
|