1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* Copyright (c) 1990 Mentat Inc. */ 26 27 /* 28 * Internet Group Management Protocol (IGMP) routines. 29 * Multicast Listener Discovery Protocol (MLD) routines. 30 * 31 * Written by Steve Deering, Stanford, May 1988. 32 * Modified by Rosen Sharma, Stanford, Aug 1994. 33 * Modified by Bill Fenner, Xerox PARC, Feb. 1995. 34 * 35 * MULTICAST 3.5.1.1 36 */ 37 38 #include <sys/types.h> 39 #include <sys/stream.h> 40 #include <sys/stropts.h> 41 #include <sys/strlog.h> 42 #include <sys/strsun.h> 43 #include <sys/systm.h> 44 #include <sys/ddi.h> 45 #include <sys/sunddi.h> 46 #include <sys/cmn_err.h> 47 #include <sys/atomic.h> 48 #include <sys/zone.h> 49 #include <sys/callb.h> 50 #include <sys/param.h> 51 #include <sys/socket.h> 52 #include <inet/ipclassifier.h> 53 #include <net/if.h> 54 #include <net/route.h> 55 #include <netinet/in.h> 56 #include <netinet/igmp_var.h> 57 #include <netinet/ip6.h> 58 #include <netinet/icmp6.h> 59 #include <inet/ipsec_impl.h> 60 61 #include <inet/common.h> 62 #include <inet/mi.h> 63 #include <inet/nd.h> 64 #include <inet/ip.h> 65 #include <inet/ip6.h> 66 #include <inet/ip_multi.h> 67 #include <inet/ip_listutils.h> 68 69 #include <netinet/igmp.h> 70 #include <inet/ip_ndp.h> 71 #include <inet/ip_if.h> 72 73 static uint_t igmp_query_in(ipha_t *ipha, igmpa_t *igmpa, ill_t *ill); 74 static uint_t igmpv3_query_in(igmp3qa_t *igmp3qa, ill_t *ill, int igmplen); 75 static uint_t mld_query_in(mld_hdr_t *mldh, ill_t *ill); 76 static uint_t mldv2_query_in(mld2q_t *mld2q, ill_t *ill, int mldlen); 77 static void igmp_sendpkt(ilm_t *ilm, uchar_t type, ipaddr_t addr); 78 static void mld_sendpkt(ilm_t *ilm, uchar_t type, const in6_addr_t *v6addr); 79 static void igmpv3_sendrpt(ill_t *ill, mrec_t *reclist); 80 static void mldv2_sendrpt(ill_t *ill, mrec_t *reclist); 81 static mrec_t *mcast_bldmrec(mcast_record_t type, in6_addr_t *grp, 82 slist_t *srclist, mrec_t *next); 83 static void mcast_init_rtx(ill_t *ill, rtx_state_t *rtxp, 84 mcast_record_t rtype, slist_t *flist); 85 static mrec_t *mcast_merge_rtx(ilm_t *ilm, mrec_t *rp, slist_t *flist); 86 87 /* 88 * Macros used to do timer len conversions. Timer values are always 89 * stored and passed to the timer functions as milliseconds; but the 90 * default values and values from the wire may not be. 91 * 92 * And yes, it's obscure, but decisecond is easier to abbreviate than 93 * "tenths of a second". 94 */ 95 #define DSEC_TO_MSEC(dsec) ((dsec) * 100) 96 #define SEC_TO_MSEC(sec) ((sec) * 1000) 97 98 /* 99 * A running timer (scheduled thru timeout) can be cancelled if another 100 * timer with a shorter timeout value is scheduled before it has timed 101 * out. When the shorter timer expires, the original timer is updated 102 * to account for the time elapsed while the shorter timer ran; but this 103 * does not take into account the amount of time already spent in timeout 104 * state before being preempted by the shorter timer, that is the time 105 * interval between time scheduled to time cancelled. This can cause 106 * delays in sending out multicast membership reports. To resolve this 107 * problem, wallclock time (absolute time) is used instead of deltas 108 * (relative time) to track timers. 109 * 110 * The MACRO below gets the lbolt value, used for proper timer scheduling 111 * and firing. Therefore multicast membership reports are sent on time. 112 * The timer does not exactly fire at the time it was scehduled to fire, 113 * there is a difference of a few milliseconds observed. An offset is used 114 * to take care of the difference. 115 */ 116 117 #define CURRENT_MSTIME ((uint_t)TICK_TO_MSEC(ddi_get_lbolt())) 118 #define CURRENT_OFFSET (999) 119 120 /* 121 * The first multicast join will trigger the igmp timers / mld timers 122 * The unit for next is milliseconds. 123 */ 124 void 125 igmp_start_timers(unsigned next, ip_stack_t *ipst) 126 { 127 int time_left; 128 int ret; 129 timeout_id_t id; 130 131 ASSERT(next != 0 && next != INFINITY); 132 133 mutex_enter(&ipst->ips_igmp_timer_lock); 134 135 if (ipst->ips_igmp_timer_setter_active) { 136 /* 137 * Serialize timer setters, one at a time. If the 138 * timer is currently being set by someone, 139 * just record the next time when it has to be 140 * invoked and return. The current setter will 141 * take care. 142 */ 143 ipst->ips_igmp_time_to_next = 144 MIN(ipst->ips_igmp_time_to_next, next); 145 mutex_exit(&ipst->ips_igmp_timer_lock); 146 return; 147 } else { 148 ipst->ips_igmp_timer_setter_active = B_TRUE; 149 } 150 if (ipst->ips_igmp_timeout_id == 0) { 151 /* 152 * The timer is inactive. We need to start a timer 153 */ 154 ipst->ips_igmp_time_to_next = next; 155 ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler, 156 (void *)ipst, MSEC_TO_TICK(ipst->ips_igmp_time_to_next)); 157 ipst->ips_igmp_timer_scheduled_last = ddi_get_lbolt(); 158 ipst->ips_igmp_timer_setter_active = B_FALSE; 159 mutex_exit(&ipst->ips_igmp_timer_lock); 160 return; 161 } 162 163 /* 164 * The timer was scheduled sometime back for firing in 165 * 'igmp_time_to_next' ms and is active. We need to 166 * reschedule the timeout if the new 'next' will happen 167 * earlier than the currently scheduled timeout 168 */ 169 time_left = ipst->ips_igmp_timer_scheduled_last + 170 MSEC_TO_TICK(ipst->ips_igmp_time_to_next) - ddi_get_lbolt(); 171 if (time_left < MSEC_TO_TICK(next)) { 172 ipst->ips_igmp_timer_setter_active = B_FALSE; 173 mutex_exit(&ipst->ips_igmp_timer_lock); 174 return; 175 } 176 id = ipst->ips_igmp_timeout_id; 177 178 mutex_exit(&ipst->ips_igmp_timer_lock); 179 ret = untimeout(id); 180 mutex_enter(&ipst->ips_igmp_timer_lock); 181 /* 182 * The timeout was cancelled, or the timeout handler 183 * completed, while we were blocked in the untimeout. 184 * No other thread could have set the timer meanwhile 185 * since we serialized all the timer setters. Thus 186 * no timer is currently active nor executing nor will 187 * any timer fire in the future. We start the timer now 188 * if needed. 189 */ 190 if (ret == -1) { 191 ASSERT(ipst->ips_igmp_timeout_id == 0); 192 } else { 193 ASSERT(ipst->ips_igmp_timeout_id != 0); 194 ipst->ips_igmp_timeout_id = 0; 195 } 196 if (ipst->ips_igmp_time_to_next != 0) { 197 ipst->ips_igmp_time_to_next = 198 MIN(ipst->ips_igmp_time_to_next, next); 199 ipst->ips_igmp_timeout_id = timeout(igmp_timeout_handler, 200 (void *)ipst, MSEC_TO_TICK(ipst->ips_igmp_time_to_next)); 201 ipst->ips_igmp_timer_scheduled_last = ddi_get_lbolt(); 202 } 203 ipst->ips_igmp_timer_setter_active = B_FALSE; 204 mutex_exit(&ipst->ips_igmp_timer_lock); 205 } 206 207 /* 208 * mld_start_timers: 209 * The unit for next is milliseconds. 210 */ 211 void 212 mld_start_timers(unsigned next, ip_stack_t *ipst) 213 { 214 int time_left; 215 int ret; 216 timeout_id_t id; 217 218 ASSERT(next != 0 && next != INFINITY); 219 220 mutex_enter(&ipst->ips_mld_timer_lock); 221 if (ipst->ips_mld_timer_setter_active) { 222 /* 223 * Serialize timer setters, one at a time. If the 224 * timer is currently being set by someone, 225 * just record the next time when it has to be 226 * invoked and return. The current setter will 227 * take care. 228 */ 229 ipst->ips_mld_time_to_next = 230 MIN(ipst->ips_mld_time_to_next, next); 231 mutex_exit(&ipst->ips_mld_timer_lock); 232 return; 233 } else { 234 ipst->ips_mld_timer_setter_active = B_TRUE; 235 } 236 if (ipst->ips_mld_timeout_id == 0) { 237 /* 238 * The timer is inactive. We need to start a timer 239 */ 240 ipst->ips_mld_time_to_next = next; 241 ipst->ips_mld_timeout_id = timeout(mld_timeout_handler, 242 (void *)ipst, MSEC_TO_TICK(ipst->ips_mld_time_to_next)); 243 ipst->ips_mld_timer_scheduled_last = ddi_get_lbolt(); 244 ipst->ips_mld_timer_setter_active = B_FALSE; 245 mutex_exit(&ipst->ips_mld_timer_lock); 246 return; 247 } 248 249 /* 250 * The timer was scheduled sometime back for firing in 251 * 'igmp_time_to_next' ms and is active. We need to 252 * reschedule the timeout if the new 'next' will happen 253 * earlier than the currently scheduled timeout 254 */ 255 time_left = ipst->ips_mld_timer_scheduled_last + 256 MSEC_TO_TICK(ipst->ips_mld_time_to_next) - ddi_get_lbolt(); 257 if (time_left < MSEC_TO_TICK(next)) { 258 ipst->ips_mld_timer_setter_active = B_FALSE; 259 mutex_exit(&ipst->ips_mld_timer_lock); 260 return; 261 } 262 id = ipst->ips_mld_timeout_id; 263 264 mutex_exit(&ipst->ips_mld_timer_lock); 265 ret = untimeout(id); 266 mutex_enter(&ipst->ips_mld_timer_lock); 267 /* 268 * The timeout was cancelled, or the timeout handler 269 * completed, while we were blocked in the untimeout. 270 * No other thread could have set the timer meanwhile 271 * since we serialized all the timer setters. Thus 272 * no timer is currently active nor executing nor will 273 * any timer fire in the future. We start the timer now 274 * if needed. 275 */ 276 if (ret == -1) { 277 ASSERT(ipst->ips_mld_timeout_id == 0); 278 } else { 279 ASSERT(ipst->ips_mld_timeout_id != 0); 280 ipst->ips_mld_timeout_id = 0; 281 } 282 if (ipst->ips_mld_time_to_next != 0) { 283 ipst->ips_mld_time_to_next = 284 MIN(ipst->ips_mld_time_to_next, next); 285 ipst->ips_mld_timeout_id = timeout(mld_timeout_handler, 286 (void *)ipst, MSEC_TO_TICK(ipst->ips_mld_time_to_next)); 287 ipst->ips_mld_timer_scheduled_last = ddi_get_lbolt(); 288 } 289 ipst->ips_mld_timer_setter_active = B_FALSE; 290 mutex_exit(&ipst->ips_mld_timer_lock); 291 } 292 293 /* 294 * igmp_input: 295 * Return NULL for a bad packet that is discarded here. 296 * Return mp if the message is OK and should be handed to "raw" receivers. 297 * Callers of igmp_input() may need to reinitialize variables that were copied 298 * from the mblk as this calls pullupmsg(). 299 */ 300 mblk_t * 301 igmp_input(mblk_t *mp, ip_recv_attr_t *ira) 302 { 303 igmpa_t *igmpa; 304 ipha_t *ipha = (ipha_t *)(mp->b_rptr); 305 int iphlen, igmplen, mblklen; 306 ilm_t *ilm; 307 uint32_t src, dst; 308 uint32_t group; 309 in6_addr_t v6group; 310 uint_t next; 311 ipif_t *ipif; 312 ill_t *ill = ira->ira_ill; 313 ip_stack_t *ipst = ill->ill_ipst; 314 315 ASSERT(!ill->ill_isv6); 316 ++ipst->ips_igmpstat.igps_rcv_total; 317 318 mblklen = MBLKL(mp); 319 iphlen = ira->ira_ip_hdr_length; 320 if (mblklen < 1 || mblklen < iphlen) { 321 ++ipst->ips_igmpstat.igps_rcv_tooshort; 322 goto bad_pkt; 323 } 324 igmplen = ira->ira_pktlen - iphlen; 325 /* 326 * Since msg sizes are more variable with v3, just pullup the 327 * whole thing now. 328 */ 329 if (MBLKL(mp) < (igmplen + iphlen)) { 330 mblk_t *mp1; 331 if ((mp1 = msgpullup(mp, -1)) == NULL) { 332 ++ipst->ips_igmpstat.igps_rcv_tooshort; 333 goto bad_pkt; 334 } 335 freemsg(mp); 336 mp = mp1; 337 ipha = (ipha_t *)(mp->b_rptr); 338 } 339 340 /* 341 * Validate lengths 342 */ 343 if (igmplen < IGMP_MINLEN) { 344 ++ipst->ips_igmpstat.igps_rcv_tooshort; 345 goto bad_pkt; 346 } 347 348 igmpa = (igmpa_t *)(&mp->b_rptr[iphlen]); 349 src = ipha->ipha_src; 350 dst = ipha->ipha_dst; 351 if (ip_debug > 1) 352 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE, 353 "igmp_input: src 0x%x, dst 0x%x on %s\n", 354 (int)ntohl(src), (int)ntohl(dst), 355 ill->ill_name); 356 357 switch (igmpa->igmpa_type) { 358 case IGMP_MEMBERSHIP_QUERY: 359 /* 360 * packet length differentiates between v1/v2 and v3 361 * v1/v2 should be exactly 8 octets long; v3 is >= 12 362 */ 363 if ((igmplen == IGMP_MINLEN) || 364 (ipst->ips_igmp_max_version <= IGMP_V2_ROUTER)) { 365 next = igmp_query_in(ipha, igmpa, ill); 366 } else if (igmplen >= IGMP_V3_QUERY_MINLEN) { 367 next = igmpv3_query_in((igmp3qa_t *)igmpa, ill, 368 igmplen); 369 } else { 370 ++ipst->ips_igmpstat.igps_rcv_tooshort; 371 goto bad_pkt; 372 } 373 if (next == 0) 374 goto bad_pkt; 375 376 if (next != INFINITY) 377 igmp_start_timers(next, ipst); 378 379 break; 380 381 case IGMP_V1_MEMBERSHIP_REPORT: 382 case IGMP_V2_MEMBERSHIP_REPORT: 383 /* 384 * For fast leave to work, we have to know that we are the 385 * last person to send a report for this group. Reports 386 * generated by us are looped back since we could potentially 387 * be a multicast router, so discard reports sourced by me. 388 */ 389 mutex_enter(&ill->ill_lock); 390 for (ipif = ill->ill_ipif; ipif != NULL; 391 ipif = ipif->ipif_next) { 392 if (ipif->ipif_lcl_addr == src) { 393 if (ip_debug > 1) { 394 (void) mi_strlog(ill->ill_rq, 395 1, 396 SL_TRACE, 397 "igmp_input: we are only " 398 "member src 0x%x\n", 399 (int)ntohl(src)); 400 } 401 mutex_exit(&ill->ill_lock); 402 return (mp); 403 } 404 } 405 mutex_exit(&ill->ill_lock); 406 407 ++ipst->ips_igmpstat.igps_rcv_reports; 408 group = igmpa->igmpa_group; 409 if (!CLASSD(group)) { 410 ++ipst->ips_igmpstat.igps_rcv_badreports; 411 goto bad_pkt; 412 } 413 414 /* 415 * KLUDGE: if the IP source address of the report has an 416 * unspecified (i.e., zero) subnet number, as is allowed for 417 * a booting host, replace it with the correct subnet number 418 * so that a process-level multicast routing demon can 419 * determine which subnet it arrived from. This is necessary 420 * to compensate for the lack of any way for a process to 421 * determine the arrival interface of an incoming packet. 422 * 423 * Requires that a copy of *this* message it passed up 424 * to the raw interface which is done by our caller. 425 */ 426 if ((src & htonl(0xFF000000U)) == 0) { /* Minimum net mask */ 427 /* Pick the first ipif on this ill */ 428 mutex_enter(&ill->ill_lock); 429 src = ill->ill_ipif->ipif_subnet; 430 mutex_exit(&ill->ill_lock); 431 ip1dbg(("igmp_input: changed src to 0x%x\n", 432 (int)ntohl(src))); 433 ipha->ipha_src = src; 434 } 435 436 /* 437 * If our ill has ILMs that belong to the group being 438 * reported, and we are a 'Delaying Member' in the RFC 439 * terminology, stop our timer for that group and 'clear 440 * flag' i.e. mark as IGMP_OTHERMEMBER. 441 */ 442 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 443 IN6_IPADDR_TO_V4MAPPED(group, &v6group); 444 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 445 if (!IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, &v6group)) 446 continue; 447 448 ++ipst->ips_igmpstat.igps_rcv_ourreports; 449 ilm->ilm_timer = INFINITY; 450 ilm->ilm_state = IGMP_OTHERMEMBER; 451 } /* for */ 452 rw_exit(&ill->ill_mcast_lock); 453 ill_mcast_timer_start(ill->ill_ipst); 454 break; 455 456 case IGMP_V3_MEMBERSHIP_REPORT: 457 /* 458 * Currently nothing to do here; IGMP router is not 459 * implemented in ip, and v3 hosts don't pay attention 460 * to membership reports. 461 */ 462 break; 463 } 464 /* 465 * Pass all valid IGMP packets up to any process(es) listening 466 * on a raw IGMP socket. Do not free the packet. 467 */ 468 return (mp); 469 470 bad_pkt: 471 freemsg(mp); 472 return (NULL); 473 } 474 475 static uint_t 476 igmp_query_in(ipha_t *ipha, igmpa_t *igmpa, ill_t *ill) 477 { 478 ilm_t *ilm; 479 int timer; 480 uint_t next, current; 481 ip_stack_t *ipst; 482 483 ipst = ill->ill_ipst; 484 ++ipst->ips_igmpstat.igps_rcv_queries; 485 486 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 487 /* 488 * In the IGMPv2 specification, there are 3 states and a flag. 489 * 490 * In Non-Member state, we simply don't have a membership record. 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). 569 * 570 * -Restart any timer that is already running but has 571 * a value longer than the requested timeout. 572 * 573 * -Use the value specified in the query message as 574 * the maximum timeout. 575 */ 576 next = (unsigned)INFINITY; 577 578 current = CURRENT_MSTIME; 579 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 580 581 /* 582 * A multicast router joins INADDR_ANY address 583 * to enable promiscuous reception of all 584 * mcasts from the interface. This INADDR_ANY 585 * is stored in the ilm_v6addr as V6 unspec addr 586 */ 587 if (!IN6_IS_ADDR_V4MAPPED(&ilm->ilm_v6addr)) 588 continue; 589 if (ilm->ilm_addr == htonl(INADDR_ANY)) 590 continue; 591 if (ilm->ilm_addr != htonl(INADDR_ALLHOSTS_GROUP) && 592 (igmpa->igmpa_group == 0) || 593 (igmpa->igmpa_group == ilm->ilm_addr)) { 594 if (ilm->ilm_timer > timer) { 595 MCAST_RANDOM_DELAY(ilm->ilm_timer, timer); 596 if (ilm->ilm_timer < next) 597 next = ilm->ilm_timer; 598 ilm->ilm_timer += current; 599 } 600 } 601 } 602 rw_exit(&ill->ill_mcast_lock); 603 /* 604 * No packets have been sent above - no 605 * ill_mcast_send_queued is needed. 606 */ 607 ill_mcast_timer_start(ill->ill_ipst); 608 609 return (next); 610 } 611 612 static uint_t 613 igmpv3_query_in(igmp3qa_t *igmp3qa, ill_t *ill, int igmplen) 614 { 615 uint_t i, next, mrd, qqi, timer, delay, numsrc; 616 uint_t current; 617 ilm_t *ilm; 618 ipaddr_t *src_array; 619 uint8_t qrv; 620 ip_stack_t *ipst; 621 622 ipst = ill->ill_ipst; 623 /* make sure numsrc matches packet size */ 624 numsrc = ntohs(igmp3qa->igmp3qa_numsrc); 625 if (igmplen < IGMP_V3_QUERY_MINLEN + (numsrc * sizeof (ipaddr_t))) { 626 ++ipst->ips_igmpstat.igps_rcv_tooshort; 627 return (0); 628 } 629 src_array = (ipaddr_t *)&igmp3qa[1]; 630 631 ++ipst->ips_igmpstat.igps_rcv_queries; 632 633 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 634 635 if ((mrd = (uint_t)igmp3qa->igmp3qa_mxrc) >= IGMP_V3_MAXRT_FPMIN) { 636 uint_t hdrval, mant, exp; 637 hdrval = (uint_t)igmp3qa->igmp3qa_mxrc; 638 mant = hdrval & IGMP_V3_MAXRT_MANT_MASK; 639 exp = (hdrval & IGMP_V3_MAXRT_EXP_MASK) >> 4; 640 mrd = (mant | 0x10) << (exp + 3); 641 } 642 if (mrd == 0) 643 mrd = MCAST_DEF_QUERY_RESP_INTERVAL; 644 timer = DSEC_TO_MSEC(mrd); 645 MCAST_RANDOM_DELAY(delay, timer); 646 next = (unsigned)INFINITY; 647 current = CURRENT_MSTIME; 648 649 if ((qrv = igmp3qa->igmp3qa_sqrv & IGMP_V3_RV_MASK) == 0) 650 ill->ill_mcast_rv = MCAST_DEF_ROBUSTNESS; 651 else 652 ill->ill_mcast_rv = qrv; 653 654 if ((qqi = (uint_t)igmp3qa->igmp3qa_qqic) >= IGMP_V3_QQI_FPMIN) { 655 uint_t hdrval, mant, exp; 656 hdrval = (uint_t)igmp3qa->igmp3qa_qqic; 657 mant = hdrval & IGMP_V3_QQI_MANT_MASK; 658 exp = (hdrval & IGMP_V3_QQI_EXP_MASK) >> 4; 659 qqi = (mant | 0x10) << (exp + 3); 660 } 661 ill->ill_mcast_qi = (qqi == 0) ? MCAST_DEF_QUERY_INTERVAL : qqi; 662 663 /* 664 * If we have a pending general query response that's scheduled 665 * sooner than the delay we calculated for this response, then 666 * no action is required (RFC3376 section 5.2 rule 1) 667 */ 668 if (ill->ill_global_timer < (current + delay)) { 669 rw_exit(&ill->ill_mcast_lock); 670 ill_mcast_timer_start(ill->ill_ipst); 671 return (next); 672 } 673 674 /* 675 * Now take action depending upon query type: 676 * general, group specific, or group/source specific. 677 */ 678 if ((numsrc == 0) && (igmp3qa->igmp3qa_group == INADDR_ANY)) { 679 /* 680 * general query 681 * We know global timer is either not running or is 682 * greater than our calculated delay, so reset it to 683 * our delay (random value in range [0, response time]). 684 */ 685 ill->ill_global_timer = current + delay; 686 next = delay; 687 } else { 688 /* group or group/source specific query */ 689 for (ilm = ill->ill_ilm; ilm; ilm = ilm->ilm_next) { 690 if (!IN6_IS_ADDR_V4MAPPED(&ilm->ilm_v6addr) || 691 (ilm->ilm_addr == htonl(INADDR_ANY)) || 692 (ilm->ilm_addr == htonl(INADDR_ALLHOSTS_GROUP)) || 693 (igmp3qa->igmp3qa_group != ilm->ilm_addr)) 694 continue; 695 /* 696 * If the query is group specific or we have a 697 * pending group specific query, the response is 698 * group specific (pending sources list should be 699 * empty). Otherwise, need to update the pending 700 * sources list for the group and source specific 701 * response. 702 */ 703 if (numsrc == 0 || (ilm->ilm_timer < INFINITY && 704 SLIST_IS_EMPTY(ilm->ilm_pendsrcs))) { 705 group_query: 706 FREE_SLIST(ilm->ilm_pendsrcs); 707 ilm->ilm_pendsrcs = NULL; 708 } else { 709 boolean_t overflow; 710 slist_t *pktl; 711 if (numsrc > MAX_FILTER_SIZE || 712 (ilm->ilm_pendsrcs == NULL && 713 (ilm->ilm_pendsrcs = l_alloc()) == NULL)) { 714 /* 715 * We've been sent more sources than 716 * we can deal with; or we can't deal 717 * with a source list at all. Revert 718 * to a group specific query. 719 */ 720 goto group_query; 721 } 722 if ((pktl = l_alloc()) == NULL) 723 goto group_query; 724 pktl->sl_numsrc = numsrc; 725 for (i = 0; i < numsrc; i++) 726 IN6_IPADDR_TO_V4MAPPED(src_array[i], 727 &(pktl->sl_addr[i])); 728 l_union_in_a(ilm->ilm_pendsrcs, pktl, 729 &overflow); 730 l_free(pktl); 731 if (overflow) 732 goto group_query; 733 } 734 735 ilm->ilm_timer = (ilm->ilm_timer == INFINITY) ? 736 INFINITY : (ilm->ilm_timer - current); 737 /* choose soonest timer */ 738 ilm->ilm_timer = MIN(ilm->ilm_timer, delay); 739 if (ilm->ilm_timer < next) 740 next = ilm->ilm_timer; 741 ilm->ilm_timer += current; 742 } 743 } 744 rw_exit(&ill->ill_mcast_lock); 745 /* 746 * No packets have been sent above - no 747 * ill_mcast_send_queued is needed. 748 */ 749 ill_mcast_timer_start(ill->ill_ipst); 750 751 return (next); 752 } 753 754 /* 755 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 756 * and it gets sent after the lock is dropped. 757 */ 758 void 759 igmp_joingroup(ilm_t *ilm) 760 { 761 uint_t timer; 762 ill_t *ill; 763 ip_stack_t *ipst = ilm->ilm_ipst; 764 765 ill = ilm->ilm_ill; 766 767 ASSERT(!ill->ill_isv6); 768 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 769 770 if (ilm->ilm_addr == htonl(INADDR_ALLHOSTS_GROUP)) { 771 ilm->ilm_rtx.rtx_timer = INFINITY; 772 ilm->ilm_state = IGMP_OTHERMEMBER; 773 } else { 774 ip1dbg(("Querier mode %d, sending report, group %x\n", 775 ill->ill_mcast_type, htonl(ilm->ilm_addr))); 776 if (ill->ill_mcast_type == IGMP_V1_ROUTER) { 777 igmp_sendpkt(ilm, IGMP_V1_MEMBERSHIP_REPORT, 0); 778 } else if (ill->ill_mcast_type == IGMP_V2_ROUTER) { 779 igmp_sendpkt(ilm, IGMP_V2_MEMBERSHIP_REPORT, 0); 780 } else if (ill->ill_mcast_type == IGMP_V3_ROUTER) { 781 mrec_t *rp; 782 mcast_record_t rtype; 783 /* 784 * The possible state changes we need to handle here: 785 * Old State New State Report 786 * 787 * INCLUDE(0) INCLUDE(X) ALLOW(X),BLOCK(0) 788 * INCLUDE(0) EXCLUDE(X) TO_EX(X) 789 * 790 * No need to send the BLOCK(0) report; ALLOW(X) 791 * is enough. 792 */ 793 rtype = (ilm->ilm_fmode == MODE_IS_INCLUDE) ? 794 ALLOW_NEW_SOURCES : CHANGE_TO_EXCLUDE; 795 rp = mcast_bldmrec(rtype, &ilm->ilm_v6addr, 796 ilm->ilm_filter, NULL); 797 igmpv3_sendrpt(ill, rp); 798 /* 799 * Set up retransmission state. Timer is set below, 800 * for both v3 and older versions. 801 */ 802 mcast_init_rtx(ill, &ilm->ilm_rtx, rtype, 803 ilm->ilm_filter); 804 } 805 806 /* Set the ilm timer value */ 807 ilm->ilm_rtx.rtx_cnt = ill->ill_mcast_rv; 808 MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer, 809 SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY)); 810 timer = ilm->ilm_rtx.rtx_timer; 811 ilm->ilm_rtx.rtx_timer += CURRENT_MSTIME; 812 ilm->ilm_state = IGMP_IREPORTEDLAST; 813 814 /* 815 * We are holding ill_mcast_lock here and the timeout 816 * handler (igmp_timeout_handler_per_ill) acquires that 817 * lock. Hence we can't call igmp_start_timer since it could 818 * deadlock in untimeout(). 819 * Instead the thread which drops ill_mcast_lock will have 820 * to call ill_mcast_timer_start(). 821 */ 822 mutex_enter(&ipst->ips_igmp_timer_lock); 823 ipst->ips_igmp_deferred_next = MIN(timer, 824 ipst->ips_igmp_deferred_next); 825 mutex_exit(&ipst->ips_igmp_timer_lock); 826 } 827 828 if (ip_debug > 1) { 829 (void) mi_strlog(ilm->ilm_ill->ill_rq, 1, SL_TRACE, 830 "igmp_joingroup: multicast_type %d timer %d", 831 (ilm->ilm_ill->ill_mcast_type), 832 (int)ntohl(timer)); 833 } 834 } 835 836 /* 837 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 838 * and it gets sent after the lock is dropped. 839 */ 840 void 841 mld_joingroup(ilm_t *ilm) 842 { 843 uint_t timer; 844 ill_t *ill; 845 ip_stack_t *ipst = ilm->ilm_ipst; 846 847 ill = ilm->ilm_ill; 848 849 ASSERT(ill->ill_isv6); 850 851 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 852 853 if (IN6_ARE_ADDR_EQUAL(&ipv6_all_hosts_mcast, &ilm->ilm_v6addr)) { 854 ilm->ilm_rtx.rtx_timer = INFINITY; 855 ilm->ilm_state = IGMP_OTHERMEMBER; 856 } else { 857 if (ill->ill_mcast_type == MLD_V1_ROUTER) { 858 mld_sendpkt(ilm, MLD_LISTENER_REPORT, NULL); 859 } else { 860 mrec_t *rp; 861 mcast_record_t rtype; 862 /* 863 * The possible state changes we need to handle here: 864 * Old State New State Report 865 * 866 * INCLUDE(0) INCLUDE(X) ALLOW(X),BLOCK(0) 867 * INCLUDE(0) EXCLUDE(X) TO_EX(X) 868 * 869 * No need to send the BLOCK(0) report; ALLOW(X) 870 * is enough 871 */ 872 rtype = (ilm->ilm_fmode == MODE_IS_INCLUDE) ? 873 ALLOW_NEW_SOURCES : CHANGE_TO_EXCLUDE; 874 rp = mcast_bldmrec(rtype, &ilm->ilm_v6addr, 875 ilm->ilm_filter, NULL); 876 mldv2_sendrpt(ill, rp); 877 /* 878 * Set up retransmission state. Timer is set below, 879 * for both v2 and v1. 880 */ 881 mcast_init_rtx(ill, &ilm->ilm_rtx, rtype, 882 ilm->ilm_filter); 883 } 884 885 /* Set the ilm timer value */ 886 ASSERT(ill->ill_mcast_type != MLD_V2_ROUTER || 887 ilm->ilm_rtx.rtx_cnt > 0); 888 889 ilm->ilm_rtx.rtx_cnt = ill->ill_mcast_rv; 890 MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer, 891 SEC_TO_MSEC(ICMP6_MAX_HOST_REPORT_DELAY)); 892 timer = ilm->ilm_rtx.rtx_timer; 893 ilm->ilm_rtx.rtx_timer += CURRENT_MSTIME; 894 ilm->ilm_state = IGMP_IREPORTEDLAST; 895 896 /* 897 * We are holding ill_mcast_lock here and the timeout 898 * handler (mld_timeout_handler_per_ill) acquires that 899 * lock. Hence we can't call mld_start_timer since it could 900 * deadlock in untimeout(). 901 * Instead the thread which drops ill_mcast_lock will have 902 * to call ill_mcast_timer_start(). 903 */ 904 mutex_enter(&ipst->ips_mld_timer_lock); 905 ipst->ips_mld_deferred_next = MIN(timer, 906 ipst->ips_mld_deferred_next); 907 mutex_exit(&ipst->ips_mld_timer_lock); 908 } 909 910 if (ip_debug > 1) { 911 (void) mi_strlog(ilm->ilm_ill->ill_rq, 1, SL_TRACE, 912 "mld_joingroup: multicast_type %d timer %d", 913 (ilm->ilm_ill->ill_mcast_type), 914 (int)ntohl(timer)); 915 } 916 } 917 918 /* 919 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 920 * and it gets sent after the lock is dropped. 921 */ 922 void 923 igmp_leavegroup(ilm_t *ilm) 924 { 925 ill_t *ill = ilm->ilm_ill; 926 927 ASSERT(!ill->ill_isv6); 928 929 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 930 if (ilm->ilm_state == IGMP_IREPORTEDLAST && 931 ill->ill_mcast_type == IGMP_V2_ROUTER && 932 (ilm->ilm_addr != htonl(INADDR_ALLHOSTS_GROUP))) { 933 igmp_sendpkt(ilm, IGMP_V2_LEAVE_GROUP, 934 (htonl(INADDR_ALLRTRS_GROUP))); 935 return; 936 } 937 if ((ill->ill_mcast_type == IGMP_V3_ROUTER) && 938 (ilm->ilm_addr != htonl(INADDR_ALLHOSTS_GROUP))) { 939 mrec_t *rp; 940 /* 941 * The possible state changes we need to handle here: 942 * Old State New State Report 943 * 944 * INCLUDE(X) INCLUDE(0) ALLOW(0),BLOCK(X) 945 * EXCLUDE(X) INCLUDE(0) TO_IN(0) 946 * 947 * No need to send the ALLOW(0) report; BLOCK(X) is enough 948 */ 949 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 950 rp = mcast_bldmrec(BLOCK_OLD_SOURCES, &ilm->ilm_v6addr, 951 ilm->ilm_filter, NULL); 952 } else { 953 rp = mcast_bldmrec(CHANGE_TO_INCLUDE, &ilm->ilm_v6addr, 954 NULL, NULL); 955 } 956 igmpv3_sendrpt(ill, rp); 957 return; 958 } 959 } 960 961 /* 962 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 963 * and it gets sent after the lock is dropped. 964 */ 965 void 966 mld_leavegroup(ilm_t *ilm) 967 { 968 ill_t *ill = ilm->ilm_ill; 969 970 ASSERT(ill->ill_isv6); 971 972 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 973 if (ilm->ilm_state == IGMP_IREPORTEDLAST && 974 ill->ill_mcast_type == MLD_V1_ROUTER && 975 (!IN6_ARE_ADDR_EQUAL(&ipv6_all_hosts_mcast, &ilm->ilm_v6addr))) { 976 mld_sendpkt(ilm, MLD_LISTENER_REDUCTION, &ipv6_all_rtrs_mcast); 977 return; 978 } 979 if ((ill->ill_mcast_type == MLD_V2_ROUTER) && 980 (!IN6_ARE_ADDR_EQUAL(&ipv6_all_hosts_mcast, &ilm->ilm_v6addr))) { 981 mrec_t *rp; 982 /* 983 * The possible state changes we need to handle here: 984 * Old State New State Report 985 * 986 * INCLUDE(X) INCLUDE(0) ALLOW(0),BLOCK(X) 987 * EXCLUDE(X) INCLUDE(0) TO_IN(0) 988 * 989 * No need to send the ALLOW(0) report; BLOCK(X) is enough 990 */ 991 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 992 rp = mcast_bldmrec(BLOCK_OLD_SOURCES, &ilm->ilm_v6addr, 993 ilm->ilm_filter, NULL); 994 } else { 995 rp = mcast_bldmrec(CHANGE_TO_INCLUDE, &ilm->ilm_v6addr, 996 NULL, NULL); 997 } 998 mldv2_sendrpt(ill, rp); 999 return; 1000 } 1001 } 1002 1003 /* 1004 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 1005 * and it gets sent after the lock is dropped. 1006 */ 1007 void 1008 igmp_statechange(ilm_t *ilm, mcast_record_t fmode, slist_t *flist) 1009 { 1010 ill_t *ill; 1011 mrec_t *rp; 1012 ip_stack_t *ipst = ilm->ilm_ipst; 1013 1014 ASSERT(ilm != NULL); 1015 1016 /* state change reports should only be sent if the router is v3 */ 1017 if (ilm->ilm_ill->ill_mcast_type != IGMP_V3_ROUTER) 1018 return; 1019 1020 ill = ilm->ilm_ill; 1021 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1022 1023 /* 1024 * Compare existing(old) state with the new state and prepare 1025 * State Change Report, according to the rules in RFC 3376: 1026 * 1027 * Old State New State State Change Report 1028 * 1029 * INCLUDE(A) INCLUDE(B) ALLOW(B-A),BLOCK(A-B) 1030 * EXCLUDE(A) EXCLUDE(B) ALLOW(A-B),BLOCK(B-A) 1031 * INCLUDE(A) EXCLUDE(B) TO_EX(B) 1032 * EXCLUDE(A) INCLUDE(B) TO_IN(B) 1033 */ 1034 1035 if (ilm->ilm_fmode == fmode) { 1036 slist_t *a_minus_b = NULL, *b_minus_a = NULL; 1037 slist_t *allow, *block; 1038 if (((a_minus_b = l_alloc()) == NULL) || 1039 ((b_minus_a = l_alloc()) == NULL)) { 1040 l_free(a_minus_b); 1041 if (ilm->ilm_fmode == MODE_IS_INCLUDE) 1042 goto send_to_ex; 1043 else 1044 goto send_to_in; 1045 } 1046 l_difference(ilm->ilm_filter, flist, a_minus_b); 1047 l_difference(flist, ilm->ilm_filter, b_minus_a); 1048 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1049 allow = b_minus_a; 1050 block = a_minus_b; 1051 } else { 1052 allow = a_minus_b; 1053 block = b_minus_a; 1054 } 1055 rp = NULL; 1056 if (!SLIST_IS_EMPTY(allow)) 1057 rp = mcast_bldmrec(ALLOW_NEW_SOURCES, &ilm->ilm_v6addr, 1058 allow, rp); 1059 if (!SLIST_IS_EMPTY(block)) 1060 rp = mcast_bldmrec(BLOCK_OLD_SOURCES, &ilm->ilm_v6addr, 1061 block, rp); 1062 l_free(a_minus_b); 1063 l_free(b_minus_a); 1064 } else if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1065 send_to_ex: 1066 rp = mcast_bldmrec(CHANGE_TO_EXCLUDE, &ilm->ilm_v6addr, flist, 1067 NULL); 1068 } else { 1069 send_to_in: 1070 rp = mcast_bldmrec(CHANGE_TO_INCLUDE, &ilm->ilm_v6addr, flist, 1071 NULL); 1072 } 1073 1074 /* 1075 * Need to set up retransmission state; merge the new info with the 1076 * current state (which may be null). If the timer is not currently 1077 * running, the caller will start it when dropping ill_mcast_lock. 1078 */ 1079 rp = mcast_merge_rtx(ilm, rp, flist); 1080 if (ilm->ilm_rtx.rtx_timer == INFINITY) { 1081 ilm->ilm_rtx.rtx_cnt = ill->ill_mcast_rv; 1082 MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer, 1083 SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY)); 1084 mutex_enter(&ipst->ips_igmp_timer_lock); 1085 ipst->ips_igmp_deferred_next = MIN(ipst->ips_igmp_deferred_next, 1086 ilm->ilm_rtx.rtx_timer); 1087 ilm->ilm_rtx.rtx_timer += CURRENT_MSTIME; 1088 mutex_exit(&ipst->ips_igmp_timer_lock); 1089 } 1090 1091 igmpv3_sendrpt(ill, rp); 1092 } 1093 1094 /* 1095 * Caller holds ill_mcast_lock. We queue the packet using ill_mcast_queue 1096 * and it gets sent after the lock is dropped. 1097 */ 1098 void 1099 mld_statechange(ilm_t *ilm, mcast_record_t fmode, slist_t *flist) 1100 { 1101 ill_t *ill; 1102 mrec_t *rp = NULL; 1103 ip_stack_t *ipst = ilm->ilm_ipst; 1104 1105 ASSERT(ilm != NULL); 1106 1107 ill = ilm->ilm_ill; 1108 ASSERT(RW_WRITE_HELD(&ill->ill_mcast_lock)); 1109 1110 /* only need to send if we have an mldv2-capable router */ 1111 if (ill->ill_mcast_type != MLD_V2_ROUTER) { 1112 return; 1113 } 1114 1115 /* 1116 * Compare existing (old) state with the new state passed in 1117 * and send appropriate MLDv2 State Change Report. 1118 * 1119 * Old State New State State Change Report 1120 * 1121 * INCLUDE(A) INCLUDE(B) ALLOW(B-A),BLOCK(A-B) 1122 * EXCLUDE(A) EXCLUDE(B) ALLOW(A-B),BLOCK(B-A) 1123 * INCLUDE(A) EXCLUDE(B) TO_EX(B) 1124 * EXCLUDE(A) INCLUDE(B) TO_IN(B) 1125 */ 1126 if (ilm->ilm_fmode == fmode) { 1127 slist_t *a_minus_b = NULL, *b_minus_a = NULL; 1128 slist_t *allow, *block; 1129 if (((a_minus_b = l_alloc()) == NULL) || 1130 ((b_minus_a = l_alloc()) == NULL)) { 1131 l_free(a_minus_b); 1132 if (ilm->ilm_fmode == MODE_IS_INCLUDE) 1133 goto send_to_ex; 1134 else 1135 goto send_to_in; 1136 } 1137 l_difference(ilm->ilm_filter, flist, a_minus_b); 1138 l_difference(flist, ilm->ilm_filter, b_minus_a); 1139 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1140 allow = b_minus_a; 1141 block = a_minus_b; 1142 } else { 1143 allow = a_minus_b; 1144 block = b_minus_a; 1145 } 1146 if (!SLIST_IS_EMPTY(allow)) 1147 rp = mcast_bldmrec(ALLOW_NEW_SOURCES, &ilm->ilm_v6addr, 1148 allow, rp); 1149 if (!SLIST_IS_EMPTY(block)) 1150 rp = mcast_bldmrec(BLOCK_OLD_SOURCES, &ilm->ilm_v6addr, 1151 block, rp); 1152 l_free(a_minus_b); 1153 l_free(b_minus_a); 1154 } else if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1155 send_to_ex: 1156 rp = mcast_bldmrec(CHANGE_TO_EXCLUDE, &ilm->ilm_v6addr, flist, 1157 NULL); 1158 } else { 1159 send_to_in: 1160 rp = mcast_bldmrec(CHANGE_TO_INCLUDE, &ilm->ilm_v6addr, flist, 1161 NULL); 1162 } 1163 1164 /* 1165 * Need to set up retransmission state; merge the new info with the 1166 * current state (which may be null). If the timer is not currently 1167 * running, the caller will start it when dropping ill_mcast_lock. 1168 */ 1169 rp = mcast_merge_rtx(ilm, rp, flist); 1170 ASSERT(ilm->ilm_rtx.rtx_cnt > 0); 1171 if (ilm->ilm_rtx.rtx_timer == INFINITY) { 1172 ilm->ilm_rtx.rtx_cnt = ill->ill_mcast_rv; 1173 MCAST_RANDOM_DELAY(ilm->ilm_rtx.rtx_timer, 1174 SEC_TO_MSEC(ICMP6_MAX_HOST_REPORT_DELAY)); 1175 mutex_enter(&ipst->ips_mld_timer_lock); 1176 ipst->ips_mld_deferred_next = 1177 MIN(ipst->ips_mld_deferred_next, ilm->ilm_rtx.rtx_timer); 1178 ilm->ilm_rtx.rtx_timer += CURRENT_MSTIME; 1179 mutex_exit(&ipst->ips_mld_timer_lock); 1180 } 1181 1182 mldv2_sendrpt(ill, rp); 1183 } 1184 1185 uint_t 1186 igmp_timeout_handler_per_ill(ill_t *ill) 1187 { 1188 uint_t next = INFINITY, current; 1189 ilm_t *ilm; 1190 mrec_t *rp = NULL; 1191 mrec_t *rtxrp = NULL; 1192 rtx_state_t *rtxp; 1193 mcast_record_t rtype; 1194 1195 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1196 1197 current = CURRENT_MSTIME; 1198 /* First check the global timer on this interface */ 1199 if (ill->ill_global_timer == INFINITY) 1200 goto per_ilm_timer; 1201 if (ill->ill_global_timer <= (current + CURRENT_OFFSET)) { 1202 ill->ill_global_timer = INFINITY; 1203 /* 1204 * Send report for each group on this interface. 1205 * Since we just set the global timer (received a v3 general 1206 * query), need to skip the all hosts addr (224.0.0.1), per 1207 * RFC 3376 section 5. 1208 */ 1209 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 1210 if (ilm->ilm_addr == htonl(INADDR_ALLHOSTS_GROUP)) 1211 continue; 1212 rp = mcast_bldmrec(ilm->ilm_fmode, &ilm->ilm_v6addr, 1213 ilm->ilm_filter, rp); 1214 /* 1215 * Since we're sending a report on this group, okay 1216 * to delete pending group-specific timers. Note 1217 * that group-specific retransmit timers still need 1218 * to be checked in the per_ilm_timer for-loop. 1219 */ 1220 ilm->ilm_timer = INFINITY; 1221 ilm->ilm_state = IGMP_IREPORTEDLAST; 1222 FREE_SLIST(ilm->ilm_pendsrcs); 1223 ilm->ilm_pendsrcs = NULL; 1224 } 1225 igmpv3_sendrpt(ill, rp); 1226 rp = NULL; 1227 } else { 1228 if ((ill->ill_global_timer - current) < next) 1229 next = ill->ill_global_timer - current; 1230 } 1231 1232 per_ilm_timer: 1233 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 1234 if (ilm->ilm_timer == INFINITY) 1235 goto per_ilm_rtxtimer; 1236 1237 if (ilm->ilm_timer > (current + CURRENT_OFFSET)) { 1238 if ((ilm->ilm_timer - current) < next) 1239 next = ilm->ilm_timer - current; 1240 1241 if (ip_debug > 1) { 1242 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE, 1243 "igmp_timo_hlr 2: ilm_timr %d " 1244 "typ %d nxt %d", 1245 (int)ntohl(ilm->ilm_timer - current), 1246 (ill->ill_mcast_type), next); 1247 } 1248 1249 goto per_ilm_rtxtimer; 1250 } 1251 1252 /* the timer has expired, need to take action */ 1253 ilm->ilm_timer = INFINITY; 1254 ilm->ilm_state = IGMP_IREPORTEDLAST; 1255 if (ill->ill_mcast_type == IGMP_V1_ROUTER) { 1256 igmp_sendpkt(ilm, IGMP_V1_MEMBERSHIP_REPORT, 0); 1257 } else if (ill->ill_mcast_type == IGMP_V2_ROUTER) { 1258 igmp_sendpkt(ilm, IGMP_V2_MEMBERSHIP_REPORT, 0); 1259 } else { 1260 slist_t *rsp; 1261 if (!SLIST_IS_EMPTY(ilm->ilm_pendsrcs) && 1262 (rsp = l_alloc()) != NULL) { 1263 /* 1264 * Contents of reply depend on pending 1265 * requested source list. 1266 */ 1267 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1268 l_intersection(ilm->ilm_filter, 1269 ilm->ilm_pendsrcs, rsp); 1270 } else { 1271 l_difference(ilm->ilm_pendsrcs, 1272 ilm->ilm_filter, rsp); 1273 } 1274 FREE_SLIST(ilm->ilm_pendsrcs); 1275 ilm->ilm_pendsrcs = NULL; 1276 if (!SLIST_IS_EMPTY(rsp)) 1277 rp = mcast_bldmrec(MODE_IS_INCLUDE, 1278 &ilm->ilm_v6addr, rsp, rp); 1279 FREE_SLIST(rsp); 1280 } else { 1281 /* 1282 * Either the pending request is just group- 1283 * specific, or we couldn't get the resources 1284 * (rsp) to build a source-specific reply. 1285 */ 1286 rp = mcast_bldmrec(ilm->ilm_fmode, 1287 &ilm->ilm_v6addr, ilm->ilm_filter, rp); 1288 } 1289 igmpv3_sendrpt(ill, rp); 1290 rp = NULL; 1291 } 1292 1293 per_ilm_rtxtimer: 1294 rtxp = &ilm->ilm_rtx; 1295 1296 if (rtxp->rtx_timer == INFINITY) 1297 continue; 1298 if (rtxp->rtx_timer > (current + CURRENT_OFFSET)) { 1299 if ((rtxp->rtx_timer - current) < next) 1300 next = rtxp->rtx_timer - current; 1301 continue; 1302 } 1303 1304 rtxp->rtx_timer = INFINITY; 1305 ilm->ilm_state = IGMP_IREPORTEDLAST; 1306 if (ill->ill_mcast_type == IGMP_V1_ROUTER) { 1307 igmp_sendpkt(ilm, IGMP_V1_MEMBERSHIP_REPORT, 0); 1308 continue; 1309 } 1310 if (ill->ill_mcast_type == IGMP_V2_ROUTER) { 1311 igmp_sendpkt(ilm, IGMP_V2_MEMBERSHIP_REPORT, 0); 1312 continue; 1313 } 1314 1315 /* 1316 * The retransmit timer has popped, and our router is 1317 * IGMPv3. We have to delve into the retransmit state 1318 * stored in the ilm. 1319 * 1320 * Decrement the retransmit count. If the fmode rtx 1321 * count is active, decrement it, and send a filter 1322 * mode change report with the ilm's source list. 1323 * Otherwise, send a source list change report with 1324 * the current retransmit lists. 1325 */ 1326 ASSERT(rtxp->rtx_cnt > 0); 1327 ASSERT(rtxp->rtx_cnt >= rtxp->rtx_fmode_cnt); 1328 rtxp->rtx_cnt--; 1329 if (rtxp->rtx_fmode_cnt > 0) { 1330 rtxp->rtx_fmode_cnt--; 1331 rtype = (ilm->ilm_fmode == MODE_IS_INCLUDE) ? 1332 CHANGE_TO_INCLUDE : CHANGE_TO_EXCLUDE; 1333 rtxrp = mcast_bldmrec(rtype, &ilm->ilm_v6addr, 1334 ilm->ilm_filter, rtxrp); 1335 } else { 1336 rtxrp = mcast_bldmrec(ALLOW_NEW_SOURCES, 1337 &ilm->ilm_v6addr, rtxp->rtx_allow, rtxrp); 1338 rtxrp = mcast_bldmrec(BLOCK_OLD_SOURCES, 1339 &ilm->ilm_v6addr, rtxp->rtx_block, rtxrp); 1340 } 1341 if (rtxp->rtx_cnt > 0) { 1342 MCAST_RANDOM_DELAY(rtxp->rtx_timer, 1343 SEC_TO_MSEC(IGMP_MAX_HOST_REPORT_DELAY)); 1344 if (rtxp->rtx_timer < next) 1345 next = rtxp->rtx_timer; 1346 rtxp->rtx_timer += current; 1347 } else { 1348 ASSERT(rtxp->rtx_timer == INFINITY); 1349 CLEAR_SLIST(rtxp->rtx_allow); 1350 CLEAR_SLIST(rtxp->rtx_block); 1351 } 1352 igmpv3_sendrpt(ill, rtxrp); 1353 rtxrp = NULL; 1354 } 1355 1356 rw_exit(&ill->ill_mcast_lock); 1357 /* Send any deferred/queued IP packets */ 1358 ill_mcast_send_queued(ill); 1359 /* Defer ill_mcast_timer_start() until the caller is done */ 1360 1361 return (next); 1362 } 1363 1364 /* 1365 * igmp_timeout_handler: 1366 * Called when there are timeout events, every next * TMEOUT_INTERVAL (tick). 1367 * Returns number of ticks to next event (or 0 if none). 1368 * 1369 * As part of multicast join and leave igmp we may need to send out an 1370 * igmp request. The igmp related state variables in the ilm are protected 1371 * by ill_mcast_lock. A single global igmp timer is used to track igmp timeouts. 1372 * igmp_timer_lock protects the global igmp_timeout_id. igmp_start_timers 1373 * starts the igmp timer if needed. It serializes multiple threads trying to 1374 * simultaneously start the timer using the igmp_timer_setter_active flag. 1375 * 1376 * igmp_input() receives igmp queries and responds to the queries 1377 * in a delayed fashion by posting a timer i.e. it calls igmp_start_timers(). 1378 * Later the igmp_timer fires, the timeout handler igmp_timerout_handler() 1379 * performs the action exclusively after acquiring ill_mcast_lock. 1380 * 1381 * The igmp_slowtimeo() function is called thru another timer. 1382 * igmp_slowtimeout_lock protects the igmp_slowtimeout_id 1383 */ 1384 void 1385 igmp_timeout_handler(void *arg) 1386 { 1387 ill_t *ill; 1388 uint_t global_next = INFINITY; 1389 uint_t next; 1390 ill_walk_context_t ctx; 1391 ip_stack_t *ipst = arg; 1392 1393 ASSERT(arg != NULL); 1394 mutex_enter(&ipst->ips_igmp_timer_lock); 1395 ASSERT(ipst->ips_igmp_timeout_id != 0); 1396 ipst->ips_igmp_timeout_id = 0; 1397 ipst->ips_igmp_timer_scheduled_last = 0; 1398 ipst->ips_igmp_time_to_next = 0; 1399 mutex_exit(&ipst->ips_igmp_timer_lock); 1400 1401 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1402 ill = ILL_START_WALK_V4(&ctx, ipst); 1403 for (; ill != NULL; ill = ill_next(&ctx, ill)) { 1404 ASSERT(!ill->ill_isv6); 1405 /* Make sure the ill isn't going away. */ 1406 if (!ill_check_and_refhold(ill)) 1407 continue; 1408 rw_exit(&ipst->ips_ill_g_lock); 1409 next = igmp_timeout_handler_per_ill(ill); 1410 if (next < global_next) 1411 global_next = next; 1412 ill_refrele(ill); 1413 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1414 } 1415 rw_exit(&ipst->ips_ill_g_lock); 1416 if (global_next != INFINITY) 1417 igmp_start_timers(global_next, ipst); 1418 } 1419 1420 /* 1421 * mld_timeout_handler: 1422 * Called when there are timeout events, every next (tick). 1423 * Returns number of ticks to next event (or 0 if none). 1424 */ 1425 uint_t 1426 mld_timeout_handler_per_ill(ill_t *ill) 1427 { 1428 ilm_t *ilm; 1429 uint_t next = INFINITY, current; 1430 mrec_t *rp, *rtxrp; 1431 rtx_state_t *rtxp; 1432 mcast_record_t rtype; 1433 1434 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1435 1436 current = CURRENT_MSTIME; 1437 /* 1438 * First check the global timer on this interface; the global timer 1439 * is not used for MLDv1, so if it's set we can assume we're v2. 1440 */ 1441 if (ill->ill_global_timer == INFINITY) 1442 goto per_ilm_timer; 1443 if (ill->ill_global_timer <= (current + CURRENT_OFFSET)) { 1444 ill->ill_global_timer = INFINITY; 1445 /* 1446 * Send report for each group on this interface. 1447 * Since we just set the global timer (received a v2 general 1448 * query), need to skip the all hosts addr (ff02::1), per 1449 * RFC 3810 section 6. 1450 */ 1451 rp = NULL; 1452 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 1453 if (IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, 1454 &ipv6_all_hosts_mcast)) 1455 continue; 1456 rp = mcast_bldmrec(ilm->ilm_fmode, &ilm->ilm_v6addr, 1457 ilm->ilm_filter, rp); 1458 /* 1459 * Since we're sending a report on this group, okay 1460 * to delete pending group-specific timers. Note 1461 * that group-specific retransmit timers still need 1462 * to be checked in the per_ilm_timer for-loop. 1463 */ 1464 ilm->ilm_timer = INFINITY; 1465 ilm->ilm_state = IGMP_IREPORTEDLAST; 1466 FREE_SLIST(ilm->ilm_pendsrcs); 1467 ilm->ilm_pendsrcs = NULL; 1468 } 1469 mldv2_sendrpt(ill, rp); 1470 } else { 1471 if ((ill->ill_global_timer - current) < next) 1472 next = ill->ill_global_timer - current; 1473 } 1474 1475 per_ilm_timer: 1476 rp = rtxrp = NULL; 1477 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 1478 if (ilm->ilm_timer == INFINITY) 1479 goto per_ilm_rtxtimer; 1480 1481 if (ilm->ilm_timer > (current + CURRENT_OFFSET)) { 1482 if ((ilm->ilm_timer - current) < next) 1483 next = ilm->ilm_timer - current; 1484 1485 if (ip_debug > 1) { 1486 (void) mi_strlog(ill->ill_rq, 1, SL_TRACE, 1487 "igmp_timo_hlr 2: ilm_timr" 1488 " %d typ %d nxt %d", 1489 (int)ntohl(ilm->ilm_timer - current), 1490 (ill->ill_mcast_type), next); 1491 } 1492 1493 goto per_ilm_rtxtimer; 1494 } 1495 1496 /* the timer has expired, need to take action */ 1497 ilm->ilm_timer = INFINITY; 1498 ilm->ilm_state = IGMP_IREPORTEDLAST; 1499 if (ill->ill_mcast_type == MLD_V1_ROUTER) { 1500 mld_sendpkt(ilm, MLD_LISTENER_REPORT, NULL); 1501 } else { 1502 slist_t *rsp; 1503 if (!SLIST_IS_EMPTY(ilm->ilm_pendsrcs) && 1504 (rsp = l_alloc()) != NULL) { 1505 /* 1506 * Contents of reply depend on pending 1507 * requested source list. 1508 */ 1509 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 1510 l_intersection(ilm->ilm_filter, 1511 ilm->ilm_pendsrcs, rsp); 1512 } else { 1513 l_difference(ilm->ilm_pendsrcs, 1514 ilm->ilm_filter, rsp); 1515 } 1516 FREE_SLIST(ilm->ilm_pendsrcs); 1517 ilm->ilm_pendsrcs = NULL; 1518 if (!SLIST_IS_EMPTY(rsp)) 1519 rp = mcast_bldmrec(MODE_IS_INCLUDE, 1520 &ilm->ilm_v6addr, rsp, rp); 1521 FREE_SLIST(rsp); 1522 } else { 1523 rp = mcast_bldmrec(ilm->ilm_fmode, 1524 &ilm->ilm_v6addr, ilm->ilm_filter, rp); 1525 } 1526 } 1527 1528 per_ilm_rtxtimer: 1529 rtxp = &ilm->ilm_rtx; 1530 1531 if (rtxp->rtx_timer == INFINITY) 1532 continue; 1533 if (rtxp->rtx_timer > (current + CURRENT_OFFSET)) { 1534 if ((rtxp->rtx_timer - current) < next) 1535 next = rtxp->rtx_timer - current; 1536 continue; 1537 } 1538 1539 rtxp->rtx_timer = INFINITY; 1540 ilm->ilm_state = IGMP_IREPORTEDLAST; 1541 if (ill->ill_mcast_type == MLD_V1_ROUTER) { 1542 mld_sendpkt(ilm, MLD_LISTENER_REPORT, NULL); 1543 continue; 1544 } 1545 1546 /* 1547 * The retransmit timer has popped, and our router is 1548 * MLDv2. We have to delve into the retransmit state 1549 * stored in the ilm. 1550 * 1551 * Decrement the retransmit count. If the fmode rtx 1552 * count is active, decrement it, and send a filter 1553 * mode change report with the ilm's source list. 1554 * Otherwise, send a source list change report with 1555 * the current retransmit lists. 1556 */ 1557 ASSERT(rtxp->rtx_cnt > 0); 1558 ASSERT(rtxp->rtx_cnt >= rtxp->rtx_fmode_cnt); 1559 rtxp->rtx_cnt--; 1560 if (rtxp->rtx_fmode_cnt > 0) { 1561 rtxp->rtx_fmode_cnt--; 1562 rtype = (ilm->ilm_fmode == MODE_IS_INCLUDE) ? 1563 CHANGE_TO_INCLUDE : CHANGE_TO_EXCLUDE; 1564 rtxrp = mcast_bldmrec(rtype, &ilm->ilm_v6addr, 1565 ilm->ilm_filter, rtxrp); 1566 } else { 1567 rtxrp = mcast_bldmrec(ALLOW_NEW_SOURCES, 1568 &ilm->ilm_v6addr, rtxp->rtx_allow, rtxrp); 1569 rtxrp = mcast_bldmrec(BLOCK_OLD_SOURCES, 1570 &ilm->ilm_v6addr, rtxp->rtx_block, rtxrp); 1571 } 1572 if (rtxp->rtx_cnt > 0) { 1573 MCAST_RANDOM_DELAY(rtxp->rtx_timer, 1574 SEC_TO_MSEC(ICMP6_MAX_HOST_REPORT_DELAY)); 1575 if (rtxp->rtx_timer < next) 1576 next = rtxp->rtx_timer; 1577 rtxp->rtx_timer += current; 1578 } else { 1579 ASSERT(rtxp->rtx_timer == INFINITY); 1580 CLEAR_SLIST(rtxp->rtx_allow); 1581 CLEAR_SLIST(rtxp->rtx_block); 1582 } 1583 } 1584 1585 if (ill->ill_mcast_type == MLD_V2_ROUTER) { 1586 mldv2_sendrpt(ill, rp); 1587 mldv2_sendrpt(ill, rtxrp); 1588 } 1589 rw_exit(&ill->ill_mcast_lock); 1590 /* Send any deferred/queued IP packets */ 1591 ill_mcast_send_queued(ill); 1592 /* Defer ill_mcast_timer_start() until the caller is done */ 1593 1594 return (next); 1595 } 1596 1597 /* 1598 * mld_timeout_handler: 1599 * Called when there are timeout events, every next * TMEOUT_INTERVAL (tick). 1600 * Returns number of ticks to next event (or 0 if none). 1601 * MT issues are same as igmp_timeout_handler 1602 */ 1603 void 1604 mld_timeout_handler(void *arg) 1605 { 1606 ill_t *ill; 1607 uint_t global_next = INFINITY; 1608 uint_t next; 1609 ill_walk_context_t ctx; 1610 ip_stack_t *ipst = arg; 1611 1612 ASSERT(arg != NULL); 1613 mutex_enter(&ipst->ips_mld_timer_lock); 1614 ASSERT(ipst->ips_mld_timeout_id != 0); 1615 ipst->ips_mld_timeout_id = 0; 1616 ipst->ips_mld_timer_scheduled_last = 0; 1617 ipst->ips_mld_time_to_next = 0; 1618 mutex_exit(&ipst->ips_mld_timer_lock); 1619 1620 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1621 ill = ILL_START_WALK_V6(&ctx, ipst); 1622 for (; ill != NULL; ill = ill_next(&ctx, ill)) { 1623 ASSERT(ill->ill_isv6); 1624 /* Make sure the ill isn't going away. */ 1625 if (!ill_check_and_refhold(ill)) 1626 continue; 1627 rw_exit(&ipst->ips_ill_g_lock); 1628 next = mld_timeout_handler_per_ill(ill); 1629 if (next < global_next) 1630 global_next = next; 1631 ill_refrele(ill); 1632 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1633 } 1634 rw_exit(&ipst->ips_ill_g_lock); 1635 if (global_next != INFINITY) 1636 mld_start_timers(global_next, ipst); 1637 } 1638 1639 /* 1640 * Calculate the Older Version Querier Present timeout value, in number 1641 * of slowtimo intervals, for the given ill. 1642 */ 1643 #define OVQP(ill) \ 1644 ((1000 * (((ill)->ill_mcast_rv * (ill)->ill_mcast_qi) \ 1645 + MCAST_QUERY_RESP_INTERVAL)) / MCAST_SLOWTIMO_INTERVAL) 1646 1647 /* 1648 * igmp_slowtimo: 1649 * - Resets to new router if we didnt we hear from the router 1650 * in IGMP_AGE_THRESHOLD seconds. 1651 * - Resets slowtimeout. 1652 * Check for ips_igmp_max_version ensures that we don't revert to a higher 1653 * IGMP version than configured. 1654 */ 1655 void 1656 igmp_slowtimo(void *arg) 1657 { 1658 ill_t *ill; 1659 ill_if_t *ifp; 1660 avl_tree_t *avl_tree; 1661 ip_stack_t *ipst = (ip_stack_t *)arg; 1662 1663 ASSERT(arg != NULL); 1664 1665 /* 1666 * The ill_if_t list is circular, hence the odd loop parameters. 1667 * 1668 * We can't use the ILL_START_WALK and ill_next() wrappers for this 1669 * walk, as we need to check the illif_mcast_* fields in the ill_if_t 1670 * structure (allowing us to skip if none of the instances have timers 1671 * running). 1672 */ 1673 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1674 for (ifp = IP_V4_ILL_G_LIST(ipst); 1675 ifp != (ill_if_t *)&IP_V4_ILL_G_LIST(ipst); 1676 ifp = ifp->illif_next) { 1677 /* 1678 * illif_mcast_v[12] are set using atomics. If an ill hears 1679 * a V1 or V2 query now and we miss seeing the count now, 1680 * we will see it the next time igmp_slowtimo is called. 1681 */ 1682 if (ifp->illif_mcast_v1 == 0 && ifp->illif_mcast_v2 == 0) 1683 continue; 1684 1685 avl_tree = &ifp->illif_avl_by_ppa; 1686 for (ill = avl_first(avl_tree); ill != NULL; 1687 ill = avl_walk(avl_tree, ill, AVL_AFTER)) { 1688 /* Make sure the ill isn't going away. */ 1689 if (!ill_check_and_refhold(ill)) 1690 continue; 1691 rw_exit(&ipst->ips_ill_g_lock); 1692 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 1693 if (ill->ill_mcast_v1_tset == 1) 1694 ill->ill_mcast_v1_time++; 1695 if (ill->ill_mcast_v2_tset == 1) 1696 ill->ill_mcast_v2_time++; 1697 if ((ill->ill_mcast_type == IGMP_V1_ROUTER) && 1698 (ipst->ips_igmp_max_version >= IGMP_V2_ROUTER) && 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 1751 * IGMP version than configured. 1752 */ 1753 void 1754 mld_slowtimo(void *arg) 1755 { 1756 ill_t *ill; 1757 ill_if_t *ifp; 1758 avl_tree_t *avl_tree; 1759 ip_stack_t *ipst = (ip_stack_t *)arg; 1760 1761 ASSERT(arg != NULL); 1762 /* See comments in igmp_slowtimo() above... */ 1763 rw_enter(&ipst->ips_ill_g_lock, RW_READER); 1764 for (ifp = IP_V6_ILL_G_LIST(ipst); 1765 ifp != (ill_if_t *)&IP_V6_ILL_G_LIST(ipst); 1766 ifp = ifp->illif_next) { 1767 if (ifp->illif_mcast_v1 == 0) 1768 continue; 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) 1810 { 1811 mblk_t *mp; 1812 igmpa_t *igmpa; 1813 uint8_t *rtralert; 1814 ipha_t *ipha; 1815 int hdrlen = sizeof (ipha_t) + RTRALERT_LEN; 1816 size_t size = hdrlen + sizeof (igmpa_t); 1817 ill_t *ill = ilm->ilm_ill; 1818 ip_stack_t *ipst = ill->ill_ipst; 1819 1820 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1821 1822 mp = allocb(size, BPRI_HI); 1823 if (mp == NULL) { 1824 return; 1825 } 1826 mp->b_wptr = mp->b_rptr + size; 1827 1828 ipha = (ipha_t *)mp->b_rptr; 1829 rtralert = (uint8_t *)&(ipha[1]); 1830 igmpa = (igmpa_t *)&(rtralert[RTRALERT_LEN]); 1831 igmpa->igmpa_type = type; 1832 igmpa->igmpa_code = 0; 1833 igmpa->igmpa_group = ilm->ilm_addr; 1834 igmpa->igmpa_cksum = 0; 1835 igmpa->igmpa_cksum = IP_CSUM(mp, hdrlen, 0); 1836 1837 rtralert[0] = IPOPT_COPY | IPOPT_RTRALERT; 1838 rtralert[1] = RTRALERT_LEN; 1839 rtralert[2] = 0; 1840 rtralert[3] = 0; 1841 1842 ipha->ipha_version_and_hdr_length = (IP_VERSION << 4) 1843 | (IP_SIMPLE_HDR_LENGTH_IN_WORDS + RTRALERT_LEN_IN_WORDS); 1844 ipha->ipha_type_of_service = 0; 1845 ipha->ipha_length = htons(size); 1846 ipha->ipha_ident = 0; 1847 ipha->ipha_fragment_offset_and_flags = 0; 1848 ipha->ipha_ttl = IGMP_TTL; 1849 ipha->ipha_protocol = IPPROTO_IGMP; 1850 ipha->ipha_hdr_checksum = 0; 1851 ipha->ipha_dst = addr ? addr : igmpa->igmpa_group; 1852 ipha->ipha_src = INADDR_ANY; 1853 1854 ill_mcast_queue(ill, mp); 1855 1856 ++ipst->ips_igmpstat.igps_snd_reports; 1857 } 1858 1859 /* 1860 * Sends an IGMP_V3_MEMBERSHIP_REPORT message out the ill. 1861 * The report will contain one group record 1862 * for each element of reclist. If this causes packet length to 1863 * exceed ill->ill_mtu, multiple reports are sent. 1864 * reclist is assumed to be made up of buffers allocated by mcast_bldmrec(), 1865 * and those buffers are freed here. 1866 */ 1867 static void 1868 igmpv3_sendrpt(ill_t *ill, mrec_t *reclist) 1869 { 1870 igmp3ra_t *igmp3ra; 1871 grphdra_t *grphdr; 1872 mblk_t *mp; 1873 ipha_t *ipha; 1874 uint8_t *rtralert; 1875 ipaddr_t *src_array; 1876 int i, j, numrec, more_src_cnt; 1877 size_t hdrsize, size, rsize; 1878 mrec_t *rp, *cur_reclist; 1879 mrec_t *next_reclist = reclist; 1880 boolean_t morepkts; 1881 ip_stack_t *ipst = ill->ill_ipst; 1882 1883 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 1884 1885 /* if there aren't any records, there's nothing to send */ 1886 if (reclist == NULL) 1887 return; 1888 1889 hdrsize = sizeof (ipha_t) + RTRALERT_LEN; 1890 nextpkt: 1891 size = hdrsize + sizeof (igmp3ra_t); 1892 morepkts = B_FALSE; 1893 more_src_cnt = 0; 1894 cur_reclist = next_reclist; 1895 numrec = 0; 1896 for (rp = cur_reclist; rp != NULL; rp = rp->mrec_next) { 1897 rsize = sizeof (grphdra_t) + 1898 (rp->mrec_srcs.sl_numsrc * sizeof (ipaddr_t)); 1899 if (size + rsize > ill->ill_mtu) { 1900 if (rp == cur_reclist) { 1901 /* 1902 * If the first mrec we looked at is too big 1903 * to fit in a single packet (i.e the source 1904 * list is too big), we must either truncate 1905 * the list (if TO_EX or IS_EX), or send 1906 * multiple reports for the same group (all 1907 * other types). 1908 */ 1909 int srcspace, srcsperpkt; 1910 srcspace = ill->ill_mtu - (size + 1911 sizeof (grphdra_t)); 1912 1913 /* 1914 * Skip if there's not even enough room in 1915 * a single packet to send something useful. 1916 */ 1917 if (srcspace <= sizeof (ipaddr_t)) 1918 continue; 1919 1920 srcsperpkt = srcspace / sizeof (ipaddr_t); 1921 /* 1922 * Increment size and numrec, because we will 1923 * be sending a record for the mrec we're 1924 * looking at now. 1925 */ 1926 size += sizeof (grphdra_t) + 1927 (srcsperpkt * sizeof (ipaddr_t)); 1928 numrec++; 1929 if (rp->mrec_type == MODE_IS_EXCLUDE || 1930 rp->mrec_type == CHANGE_TO_EXCLUDE) { 1931 rp->mrec_srcs.sl_numsrc = srcsperpkt; 1932 if (rp->mrec_next == NULL) { 1933 /* no more packets to send */ 1934 break; 1935 } else { 1936 /* 1937 * more packets, but we're 1938 * done with this mrec. 1939 */ 1940 next_reclist = rp->mrec_next; 1941 } 1942 } else { 1943 more_src_cnt = rp->mrec_srcs.sl_numsrc 1944 - srcsperpkt; 1945 rp->mrec_srcs.sl_numsrc = srcsperpkt; 1946 /* 1947 * We'll fix up this mrec (remove the 1948 * srcs we've already sent) before 1949 * returning to nextpkt above. 1950 */ 1951 next_reclist = rp; 1952 } 1953 } else { 1954 next_reclist = rp; 1955 } 1956 morepkts = B_TRUE; 1957 break; 1958 } 1959 size += rsize; 1960 numrec++; 1961 } 1962 1963 mp = allocb(size, BPRI_HI); 1964 if (mp == NULL) { 1965 goto free_reclist; 1966 } 1967 bzero((char *)mp->b_rptr, size); 1968 mp->b_wptr = (uchar_t *)(mp->b_rptr + size); 1969 1970 ipha = (ipha_t *)mp->b_rptr; 1971 rtralert = (uint8_t *)&(ipha[1]); 1972 igmp3ra = (igmp3ra_t *)&(rtralert[RTRALERT_LEN]); 1973 grphdr = (grphdra_t *)&(igmp3ra[1]); 1974 1975 rp = cur_reclist; 1976 for (i = 0; i < numrec; i++) { 1977 grphdr->grphdra_type = rp->mrec_type; 1978 grphdr->grphdra_numsrc = htons(rp->mrec_srcs.sl_numsrc); 1979 grphdr->grphdra_group = V4_PART_OF_V6(rp->mrec_group); 1980 src_array = (ipaddr_t *)&(grphdr[1]); 1981 1982 for (j = 0; j < rp->mrec_srcs.sl_numsrc; j++) 1983 src_array[j] = V4_PART_OF_V6(rp->mrec_srcs.sl_addr[j]); 1984 1985 grphdr = (grphdra_t *)&(src_array[j]); 1986 rp = rp->mrec_next; 1987 } 1988 1989 igmp3ra->igmp3ra_type = IGMP_V3_MEMBERSHIP_REPORT; 1990 igmp3ra->igmp3ra_numrec = htons(numrec); 1991 igmp3ra->igmp3ra_cksum = IP_CSUM(mp, hdrsize, 0); 1992 1993 rtralert[0] = IPOPT_COPY | IPOPT_RTRALERT; 1994 rtralert[1] = RTRALERT_LEN; 1995 rtralert[2] = 0; 1996 rtralert[3] = 0; 1997 1998 ipha->ipha_version_and_hdr_length = IP_VERSION << 4 1999 | (IP_SIMPLE_HDR_LENGTH_IN_WORDS + RTRALERT_LEN_IN_WORDS); 2000 ipha->ipha_type_of_service = IPTOS_PREC_INTERNETCONTROL; 2001 ipha->ipha_length = htons(size); 2002 ipha->ipha_ttl = IGMP_TTL; 2003 ipha->ipha_protocol = IPPROTO_IGMP; 2004 ipha->ipha_dst = htonl(INADDR_ALLRPTS_GROUP); 2005 ipha->ipha_src = INADDR_ANY; 2006 2007 ill_mcast_queue(ill, mp); 2008 2009 ++ipst->ips_igmpstat.igps_snd_reports; 2010 2011 if (morepkts) { 2012 if (more_src_cnt > 0) { 2013 int index, mvsize; 2014 slist_t *sl = &next_reclist->mrec_srcs; 2015 index = sl->sl_numsrc; 2016 mvsize = more_src_cnt * sizeof (in6_addr_t); 2017 (void) memmove(&sl->sl_addr[0], &sl->sl_addr[index], 2018 mvsize); 2019 sl->sl_numsrc = more_src_cnt; 2020 } 2021 goto nextpkt; 2022 } 2023 2024 free_reclist: 2025 while (reclist != NULL) { 2026 rp = reclist->mrec_next; 2027 mi_free(reclist); 2028 reclist = rp; 2029 } 2030 } 2031 2032 /* 2033 * mld_input: 2034 * Return NULL for a bad packet that is discarded here. 2035 * Return mp if the message is OK and should be handed to "raw" receivers. 2036 * Callers of mld_input() may need to reinitialize variables that were copied 2037 * from the mblk as this calls pullupmsg(). 2038 */ 2039 mblk_t * 2040 mld_input(mblk_t *mp, ip_recv_attr_t *ira) 2041 { 2042 ip6_t *ip6h = (ip6_t *)(mp->b_rptr); 2043 mld_hdr_t *mldh; 2044 ilm_t *ilm; 2045 ipif_t *ipif; 2046 uint16_t hdr_length, exthdr_length; 2047 in6_addr_t *v6group_ptr; 2048 uint_t next; 2049 int mldlen; 2050 ill_t *ill = ira->ira_ill; 2051 ip_stack_t *ipst = ill->ill_ipst; 2052 2053 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembTotal); 2054 2055 /* Make sure the src address of the packet is link-local */ 2056 if (!(IN6_IS_ADDR_LINKLOCAL(&ip6h->ip6_src))) { 2057 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 2058 freemsg(mp); 2059 return (NULL); 2060 } 2061 2062 if (ip6h->ip6_hlim != 1) { 2063 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpBadHoplimit); 2064 freemsg(mp); 2065 return (NULL); 2066 } 2067 2068 /* Get to the icmp header part */ 2069 hdr_length = ira->ira_ip_hdr_length; 2070 exthdr_length = hdr_length - IPV6_HDR_LEN; 2071 2072 mldlen = ntohs(ip6h->ip6_plen) - exthdr_length; 2073 2074 /* An MLD packet must at least be 24 octets to be valid */ 2075 if (mldlen < MLD_MINLEN) { 2076 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 2077 freemsg(mp); 2078 return (NULL); 2079 } 2080 2081 mldh = (mld_hdr_t *)(&mp->b_rptr[hdr_length]); 2082 2083 switch (mldh->mld_type) { 2084 case MLD_LISTENER_QUERY: 2085 /* 2086 * packet length differentiates between v1 and v2. v1 2087 * query should be exactly 24 octets long; v2 is >= 28. 2088 */ 2089 if ((mldlen == MLD_MINLEN) || 2090 (ipst->ips_mld_max_version < MLD_V2_ROUTER)) { 2091 next = mld_query_in(mldh, ill); 2092 } else if (mldlen >= MLD_V2_QUERY_MINLEN) { 2093 next = mldv2_query_in((mld2q_t *)mldh, ill, mldlen); 2094 } else { 2095 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 2096 freemsg(mp); 2097 return (NULL); 2098 } 2099 if (next == 0) { 2100 return (mp); 2101 } 2102 2103 if (next != INFINITY) 2104 mld_start_timers(next, ipst); 2105 break; 2106 2107 case MLD_LISTENER_REPORT: 2108 /* 2109 * For fast leave to work, we have to know that we are the 2110 * last person to send a report for this group. Reports 2111 * generated by us are looped back since we could potentially 2112 * be a multicast router, so discard reports sourced by me. 2113 */ 2114 mutex_enter(&ill->ill_lock); 2115 for (ipif = ill->ill_ipif; ipif != NULL; 2116 ipif = ipif->ipif_next) { 2117 if (IN6_ARE_ADDR_EQUAL(&ipif->ipif_v6lcl_addr, 2118 &ip6h->ip6_src)) { 2119 if (ip_debug > 1) { 2120 char buf1[INET6_ADDRSTRLEN]; 2121 2122 (void) mi_strlog(ill->ill_rq, 2123 1, 2124 SL_TRACE, 2125 "mld_input: we are only " 2126 "member src %s\n", 2127 inet_ntop(AF_INET6, &ip6h->ip6_src, 2128 buf1, sizeof (buf1))); 2129 } 2130 mutex_exit(&ill->ill_lock); 2131 return (mp); 2132 } 2133 } 2134 mutex_exit(&ill->ill_lock); 2135 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembResponses); 2136 2137 v6group_ptr = &mldh->mld_addr; 2138 if (!IN6_IS_ADDR_MULTICAST(v6group_ptr)) { 2139 BUMP_MIB(ill->ill_icmp6_mib, 2140 ipv6IfIcmpInGroupMembBadReports); 2141 freemsg(mp); 2142 return (NULL); 2143 } 2144 2145 2146 /* 2147 * If we belong to the group being reported, and we are a 2148 * 'Delaying member' per the RFC terminology, stop our timer 2149 * for that group and 'clear flag' i.e. mark ilm_state as 2150 * IGMP_OTHERMEMBER. With zones, there can be multiple group 2151 * membership entries for the same group address (one per zone) 2152 * so we need to walk the ill_ilm list. 2153 */ 2154 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 2155 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 2156 if (!IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, v6group_ptr)) 2157 continue; 2158 BUMP_MIB(ill->ill_icmp6_mib, 2159 ipv6IfIcmpInGroupMembOurReports); 2160 2161 ilm->ilm_timer = INFINITY; 2162 ilm->ilm_state = IGMP_OTHERMEMBER; 2163 } 2164 rw_exit(&ill->ill_mcast_lock); 2165 /* 2166 * No packets have been sent above - no 2167 * ill_mcast_send_queued is needed. 2168 */ 2169 ill_mcast_timer_start(ill->ill_ipst); 2170 break; 2171 2172 case MLD_LISTENER_REDUCTION: 2173 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembReductions); 2174 break; 2175 } 2176 return (mp); 2177 } 2178 2179 /* 2180 * Handles an MLDv1 Listener Query. Returns 0 on error, or the appropriate 2181 * (non-zero, unsigned) timer value to be set on success. 2182 */ 2183 static uint_t 2184 mld_query_in(mld_hdr_t *mldh, ill_t *ill) 2185 { 2186 ilm_t *ilm; 2187 int timer; 2188 uint_t next, current; 2189 in6_addr_t *v6group; 2190 2191 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembQueries); 2192 2193 /* 2194 * In the MLD specification, there are 3 states and a flag. 2195 * 2196 * In Non-Listener state, we simply don't have a membership record. 2197 * In Delaying state, our timer is running (ilm->ilm_timer < INFINITY) 2198 * In Idle Member state, our timer is not running (ilm->ilm_timer == 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 2240 * maximum timeout. 2241 */ 2242 next = INFINITY; 2243 2244 current = CURRENT_MSTIME; 2245 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 2246 ASSERT(!IN6_IS_ADDR_V4MAPPED(&ilm->ilm_v6addr)); 2247 2248 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr) || 2249 IN6_IS_ADDR_MC_NODELOCAL(&ilm->ilm_v6addr) || 2250 IN6_IS_ADDR_MC_RESERVED(&ilm->ilm_v6addr)) 2251 continue; 2252 if ((!IN6_ARE_ADDR_EQUAL(&ilm->ilm_v6addr, 2253 &ipv6_all_hosts_mcast)) && 2254 (IN6_IS_ADDR_UNSPECIFIED(v6group)) || 2255 (IN6_ARE_ADDR_EQUAL(v6group, &ilm->ilm_v6addr))) { 2256 if (timer == 0) { 2257 /* Respond immediately */ 2258 ilm->ilm_timer = INFINITY; 2259 ilm->ilm_state = IGMP_IREPORTEDLAST; 2260 mld_sendpkt(ilm, MLD_LISTENER_REPORT, NULL); 2261 break; 2262 } 2263 if (ilm->ilm_timer > timer) { 2264 MCAST_RANDOM_DELAY(ilm->ilm_timer, timer); 2265 if (ilm->ilm_timer < next) 2266 next = ilm->ilm_timer; 2267 ilm->ilm_timer += current; 2268 } 2269 break; 2270 } 2271 } 2272 rw_exit(&ill->ill_mcast_lock); 2273 /* Send any deferred/queued IP packets */ 2274 ill_mcast_send_queued(ill); 2275 ill_mcast_timer_start(ill->ill_ipst); 2276 2277 return (next); 2278 } 2279 2280 /* 2281 * Handles an MLDv2 Listener Query. On error, returns 0; on success, 2282 * returns the appropriate (non-zero, unsigned) timer value (which may 2283 * be INFINITY) to be set. 2284 */ 2285 static uint_t 2286 mldv2_query_in(mld2q_t *mld2q, ill_t *ill, int mldlen) 2287 { 2288 ilm_t *ilm; 2289 in6_addr_t *v6group, *src_array; 2290 uint_t next, numsrc, i, mrd, delay, qqi, current; 2291 uint8_t qrv; 2292 2293 v6group = &mld2q->mld2q_addr; 2294 numsrc = ntohs(mld2q->mld2q_numsrc); 2295 2296 /* make sure numsrc matches packet size */ 2297 if (mldlen < MLD_V2_QUERY_MINLEN + (numsrc * sizeof (in6_addr_t))) { 2298 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInErrors); 2299 return (0); 2300 } 2301 src_array = (in6_addr_t *)&mld2q[1]; 2302 2303 BUMP_MIB(ill->ill_icmp6_mib, ipv6IfIcmpInGroupMembQueries); 2304 2305 /* extract Maximum Response Delay from code in header */ 2306 mrd = ntohs(mld2q->mld2q_mxrc); 2307 if (mrd >= MLD_V2_MAXRT_FPMIN) { 2308 uint_t hdrval, mant, exp; 2309 hdrval = mrd; 2310 mant = hdrval & MLD_V2_MAXRT_MANT_MASK; 2311 exp = (hdrval & MLD_V2_MAXRT_EXP_MASK) >> 12; 2312 mrd = (mant | 0x1000) << (exp + 3); 2313 } 2314 if (mrd == 0) 2315 mrd = DSEC_TO_MSEC(MCAST_DEF_QUERY_RESP_INTERVAL); 2316 2317 MCAST_RANDOM_DELAY(delay, mrd); 2318 next = (unsigned)INFINITY; 2319 current = CURRENT_MSTIME; 2320 2321 if ((qrv = mld2q->mld2q_sqrv & MLD_V2_RV_MASK) == 0) 2322 ill->ill_mcast_rv = MCAST_DEF_ROBUSTNESS; 2323 else 2324 ill->ill_mcast_rv = qrv; 2325 2326 if ((qqi = (uint_t)mld2q->mld2q_qqic) >= MLD_V2_QQI_FPMIN) { 2327 uint_t mant, exp; 2328 mant = qqi & MLD_V2_QQI_MANT_MASK; 2329 exp = (qqi & MLD_V2_QQI_EXP_MASK) >> 12; 2330 qqi = (mant | 0x10) << (exp + 3); 2331 } 2332 ill->ill_mcast_qi = (qqi == 0) ? MCAST_DEF_QUERY_INTERVAL : qqi; 2333 2334 /* 2335 * If we have a pending general query response that's scheduled 2336 * sooner than the delay we calculated for this response, then 2337 * no action is required (MLDv2 draft section 6.2 rule 1) 2338 */ 2339 rw_enter(&ill->ill_mcast_lock, RW_WRITER); 2340 if (ill->ill_global_timer < (current + delay)) { 2341 rw_exit(&ill->ill_mcast_lock); 2342 return (next); 2343 } 2344 2345 /* 2346 * Now take action depending on query type: general, 2347 * group specific, or group/source specific. 2348 */ 2349 if ((numsrc == 0) && IN6_IS_ADDR_UNSPECIFIED(v6group)) { 2350 /* 2351 * general query 2352 * We know global timer is either not running or is 2353 * greater than our calculated delay, so reset it to 2354 * our delay (random value in range [0, response time]) 2355 */ 2356 ill->ill_global_timer = current + delay; 2357 next = delay; 2358 } else { 2359 /* group or group/source specific query */ 2360 for (ilm = ill->ill_ilm; ilm != NULL; ilm = ilm->ilm_next) { 2361 if (IN6_IS_ADDR_UNSPECIFIED(&ilm->ilm_v6addr) || 2362 IN6_IS_ADDR_MC_NODELOCAL(&ilm->ilm_v6addr) || 2363 IN6_IS_ADDR_MC_RESERVED(&ilm->ilm_v6addr) || 2364 !IN6_ARE_ADDR_EQUAL(v6group, &ilm->ilm_v6addr)) 2365 continue; 2366 2367 /* 2368 * If the query is group specific or we have a 2369 * pending group specific query, the response is 2370 * group specific (pending sources list should be 2371 * empty). Otherwise, need to update the pending 2372 * sources list for the group and source specific 2373 * response. 2374 */ 2375 if (numsrc == 0 || (ilm->ilm_timer < INFINITY && 2376 SLIST_IS_EMPTY(ilm->ilm_pendsrcs))) { 2377 group_query: 2378 FREE_SLIST(ilm->ilm_pendsrcs); 2379 ilm->ilm_pendsrcs = NULL; 2380 } else { 2381 boolean_t overflow; 2382 slist_t *pktl; 2383 if (numsrc > MAX_FILTER_SIZE || 2384 (ilm->ilm_pendsrcs == NULL && 2385 (ilm->ilm_pendsrcs = l_alloc()) == NULL)) { 2386 /* 2387 * We've been sent more sources than 2388 * we can deal with; or we can't deal 2389 * with a source list at all. Revert 2390 * to a group specific query. 2391 */ 2392 goto group_query; 2393 } 2394 if ((pktl = l_alloc()) == NULL) 2395 goto group_query; 2396 pktl->sl_numsrc = numsrc; 2397 for (i = 0; i < numsrc; i++) 2398 pktl->sl_addr[i] = src_array[i]; 2399 l_union_in_a(ilm->ilm_pendsrcs, pktl, 2400 &overflow); 2401 l_free(pktl); 2402 if (overflow) 2403 goto group_query; 2404 } 2405 ilm->ilm_timer = (ilm->ilm_timer == INFINITY) ? 2406 INFINITY : (ilm->ilm_timer - current); 2407 /* set timer to soonest value */ 2408 ilm->ilm_timer = MIN(ilm->ilm_timer, delay); 2409 if (ilm->ilm_timer < next) 2410 next = ilm->ilm_timer; 2411 ilm->ilm_timer += current; 2412 break; 2413 } 2414 } 2415 rw_exit(&ill->ill_mcast_lock); 2416 /* 2417 * No packets have been sent above - no 2418 * ill_mcast_send_queued is needed. 2419 */ 2420 ill_mcast_timer_start(ill->ill_ipst); 2421 2422 return (next); 2423 } 2424 2425 /* 2426 * Send MLDv1 response packet with hoplimit 1 2427 */ 2428 static void 2429 mld_sendpkt(ilm_t *ilm, uchar_t type, const in6_addr_t *v6addr) 2430 { 2431 mblk_t *mp; 2432 mld_hdr_t *mldh; 2433 ip6_t *ip6h; 2434 ip6_hbh_t *ip6hbh; 2435 struct ip6_opt_router *ip6router; 2436 size_t size = IPV6_HDR_LEN + sizeof (mld_hdr_t); 2437 ill_t *ill = ilm->ilm_ill; 2438 2439 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 2440 2441 /* 2442 * We need to place a router alert option in this packet. The length 2443 * of the options must be a multiple of 8. The hbh option header is 2 2444 * bytes followed by the 4 byte router alert option. That leaves 2445 * 2 bytes of pad for a total of 8 bytes. 2446 */ 2447 const int router_alert_length = 8; 2448 2449 ASSERT(ill->ill_isv6); 2450 2451 size += router_alert_length; 2452 mp = allocb(size, BPRI_HI); 2453 if (mp == NULL) 2454 return; 2455 bzero(mp->b_rptr, size); 2456 mp->b_wptr = mp->b_rptr + size; 2457 2458 ip6h = (ip6_t *)mp->b_rptr; 2459 ip6hbh = (struct ip6_hbh *)&ip6h[1]; 2460 ip6router = (struct ip6_opt_router *)&ip6hbh[1]; 2461 /* 2462 * A zero is a pad option of length 1. The bzero of the whole packet 2463 * above will pad between ip6router and mld. 2464 */ 2465 mldh = (mld_hdr_t *)((uint8_t *)ip6hbh + router_alert_length); 2466 2467 mldh->mld_type = type; 2468 mldh->mld_addr = ilm->ilm_v6addr; 2469 2470 ip6router->ip6or_type = IP6OPT_ROUTER_ALERT; 2471 ip6router->ip6or_len = 2; 2472 ip6router->ip6or_value[0] = 0; 2473 ip6router->ip6or_value[1] = IP6_ALERT_MLD; 2474 2475 ip6hbh->ip6h_nxt = IPPROTO_ICMPV6; 2476 ip6hbh->ip6h_len = 0; 2477 2478 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 2479 ip6h->ip6_plen = htons(sizeof (*mldh) + router_alert_length); 2480 ip6h->ip6_nxt = IPPROTO_HOPOPTS; 2481 ip6h->ip6_hops = MLD_HOP_LIMIT; 2482 if (v6addr == NULL) 2483 ip6h->ip6_dst = ilm->ilm_v6addr; 2484 else 2485 ip6h->ip6_dst = *v6addr; 2486 2487 ip6h->ip6_src = ipv6_all_zeros; 2488 /* 2489 * Prepare for checksum by putting icmp length in the icmp 2490 * checksum field. The checksum is calculated in ip_output. 2491 */ 2492 mldh->mld_cksum = htons(sizeof (*mldh)); 2493 2494 ill_mcast_queue(ill, mp); 2495 } 2496 2497 /* 2498 * Sends an MLD_V2_LISTENER_REPORT message out the passed-in ill. The 2499 * report will contain one multicast address record for each element of 2500 * reclist. If this causes packet length to exceed ill->ill_mtu, 2501 * multiple reports are sent. reclist is assumed to be made up of 2502 * buffers allocated by mcast_bldmrec(), and those buffers are freed here. 2503 */ 2504 static void 2505 mldv2_sendrpt(ill_t *ill, mrec_t *reclist) 2506 { 2507 mblk_t *mp; 2508 mld2r_t *mld2r; 2509 mld2mar_t *mld2mar; 2510 in6_addr_t *srcarray; 2511 ip6_t *ip6h; 2512 ip6_hbh_t *ip6hbh; 2513 struct ip6_opt_router *ip6router; 2514 size_t size, optlen, padlen, icmpsize, rsize; 2515 int i, numrec, more_src_cnt; 2516 mrec_t *rp, *cur_reclist; 2517 mrec_t *next_reclist = reclist; 2518 boolean_t morepkts; 2519 2520 /* If there aren't any records, there's nothing to send */ 2521 if (reclist == NULL) 2522 return; 2523 2524 ASSERT(ill->ill_isv6); 2525 ASSERT(RW_LOCK_HELD(&ill->ill_mcast_lock)); 2526 2527 /* 2528 * Total option length (optlen + padlen) must be a multiple of 2529 * 8 bytes. We assume here that optlen <= 8, so the total option 2530 * length will be 8. Assert this in case anything ever changes. 2531 */ 2532 optlen = sizeof (ip6_hbh_t) + sizeof (struct ip6_opt_router); 2533 ASSERT(optlen <= 8); 2534 padlen = 8 - optlen; 2535 nextpkt: 2536 icmpsize = sizeof (mld2r_t); 2537 size = IPV6_HDR_LEN + optlen + padlen + icmpsize; 2538 morepkts = B_FALSE; 2539 more_src_cnt = 0; 2540 for (rp = cur_reclist = next_reclist, numrec = 0; rp != NULL; 2541 rp = rp->mrec_next, numrec++) { 2542 rsize = sizeof (mld2mar_t) + 2543 (rp->mrec_srcs.sl_numsrc * sizeof (in6_addr_t)); 2544 if (size + rsize > ill->ill_mtu) { 2545 if (rp == cur_reclist) { 2546 /* 2547 * If the first mrec we looked at is too big 2548 * to fit in a single packet (i.e the source 2549 * list is too big), we must either truncate 2550 * the list (if TO_EX or IS_EX), or send 2551 * multiple reports for the same group (all 2552 * other types). 2553 */ 2554 int srcspace, srcsperpkt; 2555 srcspace = ill->ill_mtu - 2556 (size + sizeof (mld2mar_t)); 2557 2558 /* 2559 * Skip if there's not even enough room in 2560 * a single packet to send something useful. 2561 */ 2562 if (srcspace <= sizeof (in6_addr_t)) 2563 continue; 2564 2565 srcsperpkt = srcspace / sizeof (in6_addr_t); 2566 /* 2567 * Increment icmpsize and size, because we will 2568 * be sending a record for the mrec we're 2569 * looking at now. 2570 */ 2571 rsize = sizeof (mld2mar_t) + 2572 (srcsperpkt * sizeof (in6_addr_t)); 2573 icmpsize += rsize; 2574 size += rsize; 2575 if (rp->mrec_type == MODE_IS_EXCLUDE || 2576 rp->mrec_type == CHANGE_TO_EXCLUDE) { 2577 rp->mrec_srcs.sl_numsrc = srcsperpkt; 2578 if (rp->mrec_next == NULL) { 2579 /* no more packets to send */ 2580 break; 2581 } else { 2582 /* 2583 * more packets, but we're 2584 * done with this mrec. 2585 */ 2586 next_reclist = rp->mrec_next; 2587 } 2588 } else { 2589 more_src_cnt = rp->mrec_srcs.sl_numsrc 2590 - srcsperpkt; 2591 rp->mrec_srcs.sl_numsrc = srcsperpkt; 2592 /* 2593 * We'll fix up this mrec (remove the 2594 * srcs we've already sent) before 2595 * returning to nextpkt above. 2596 */ 2597 next_reclist = rp; 2598 } 2599 } else { 2600 next_reclist = rp; 2601 } 2602 morepkts = B_TRUE; 2603 break; 2604 } 2605 icmpsize += rsize; 2606 size += rsize; 2607 } 2608 2609 mp = allocb(size, BPRI_HI); 2610 if (mp == NULL) 2611 goto free_reclist; 2612 bzero(mp->b_rptr, size); 2613 mp->b_wptr = mp->b_rptr + size; 2614 2615 ip6h = (ip6_t *)mp->b_rptr; 2616 ip6hbh = (ip6_hbh_t *)&(ip6h[1]); 2617 ip6router = (struct ip6_opt_router *)&(ip6hbh[1]); 2618 mld2r = (mld2r_t *)((uint8_t *)ip6hbh + optlen + padlen); 2619 mld2mar = (mld2mar_t *)&(mld2r[1]); 2620 2621 ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW; 2622 ip6h->ip6_plen = htons(optlen + padlen + icmpsize); 2623 ip6h->ip6_nxt = IPPROTO_HOPOPTS; 2624 ip6h->ip6_hops = MLD_HOP_LIMIT; 2625 ip6h->ip6_dst = ipv6_all_v2rtrs_mcast; 2626 ip6h->ip6_src = ipv6_all_zeros; 2627 2628 ip6hbh->ip6h_nxt = IPPROTO_ICMPV6; 2629 /* 2630 * ip6h_len is the number of 8-byte words, not including the first 2631 * 8 bytes; we've assumed optlen + padlen == 8 bytes; hence len = 0. 2632 */ 2633 ip6hbh->ip6h_len = 0; 2634 2635 ip6router->ip6or_type = IP6OPT_ROUTER_ALERT; 2636 ip6router->ip6or_len = 2; 2637 ip6router->ip6or_value[0] = 0; 2638 ip6router->ip6or_value[1] = IP6_ALERT_MLD; 2639 2640 mld2r->mld2r_type = MLD_V2_LISTENER_REPORT; 2641 mld2r->mld2r_nummar = htons(numrec); 2642 /* 2643 * Prepare for the checksum by putting icmp length in the icmp 2644 * checksum field. The checksum is calculated in ip_output_simple. 2645 */ 2646 mld2r->mld2r_cksum = htons(icmpsize); 2647 2648 for (rp = cur_reclist; rp != NULL; rp = rp->mrec_next) { 2649 mld2mar->mld2mar_type = rp->mrec_type; 2650 mld2mar->mld2mar_auxlen = 0; 2651 mld2mar->mld2mar_numsrc = htons(rp->mrec_srcs.sl_numsrc); 2652 mld2mar->mld2mar_group = rp->mrec_group; 2653 srcarray = (in6_addr_t *)&(mld2mar[1]); 2654 2655 for (i = 0; i < rp->mrec_srcs.sl_numsrc; i++) 2656 srcarray[i] = rp->mrec_srcs.sl_addr[i]; 2657 2658 mld2mar = (mld2mar_t *)&(srcarray[i]); 2659 } 2660 2661 ill_mcast_queue(ill, mp); 2662 2663 if (morepkts) { 2664 if (more_src_cnt > 0) { 2665 int index, mvsize; 2666 slist_t *sl = &next_reclist->mrec_srcs; 2667 index = sl->sl_numsrc; 2668 mvsize = more_src_cnt * sizeof (in6_addr_t); 2669 (void) memmove(&sl->sl_addr[0], &sl->sl_addr[index], 2670 mvsize); 2671 sl->sl_numsrc = more_src_cnt; 2672 } 2673 goto nextpkt; 2674 } 2675 2676 free_reclist: 2677 while (reclist != NULL) { 2678 rp = reclist->mrec_next; 2679 mi_free(reclist); 2680 reclist = rp; 2681 } 2682 } 2683 2684 static mrec_t * 2685 mcast_bldmrec(mcast_record_t type, in6_addr_t *grp, slist_t *srclist, 2686 mrec_t *next) 2687 { 2688 mrec_t *rp; 2689 int i; 2690 2691 if ((type == ALLOW_NEW_SOURCES || type == BLOCK_OLD_SOURCES) && 2692 SLIST_IS_EMPTY(srclist)) 2693 return (next); 2694 2695 rp = (mrec_t *)mi_alloc(sizeof (mrec_t), BPRI_HI); 2696 if (rp == NULL) 2697 return (next); 2698 2699 rp->mrec_next = next; 2700 rp->mrec_type = type; 2701 rp->mrec_auxlen = 0; 2702 rp->mrec_group = *grp; 2703 if (srclist == NULL) { 2704 rp->mrec_srcs.sl_numsrc = 0; 2705 } else { 2706 rp->mrec_srcs.sl_numsrc = srclist->sl_numsrc; 2707 for (i = 0; i < srclist->sl_numsrc; i++) 2708 rp->mrec_srcs.sl_addr[i] = srclist->sl_addr[i]; 2709 } 2710 2711 return (rp); 2712 } 2713 2714 /* 2715 * Set up initial retransmit state. If memory cannot be allocated for 2716 * the source lists, simply create as much state as is possible; memory 2717 * allocation failures are considered one type of transient error that 2718 * the retransmissions are designed to overcome (and if they aren't 2719 * transient, there are bigger problems than failing to notify the 2720 * router about multicast group membership state changes). 2721 */ 2722 static void 2723 mcast_init_rtx(ill_t *ill, rtx_state_t *rtxp, mcast_record_t rtype, 2724 slist_t *flist) 2725 { 2726 /* 2727 * There are only three possibilities for rtype: 2728 * New join, transition from INCLUDE {} to INCLUDE {flist} 2729 * => rtype is ALLOW_NEW_SOURCES 2730 * New join, transition from INCLUDE {} to EXCLUDE {flist} 2731 * => rtype is CHANGE_TO_EXCLUDE 2732 * State change that involves a filter mode change 2733 * => rtype is either CHANGE_TO_INCLUDE or CHANGE_TO_EXCLUDE 2734 */ 2735 ASSERT(rtype == CHANGE_TO_EXCLUDE || rtype == CHANGE_TO_INCLUDE || 2736 rtype == ALLOW_NEW_SOURCES); 2737 2738 rtxp->rtx_cnt = ill->ill_mcast_rv; 2739 2740 switch (rtype) { 2741 case CHANGE_TO_EXCLUDE: 2742 rtxp->rtx_fmode_cnt = ill->ill_mcast_rv; 2743 CLEAR_SLIST(rtxp->rtx_allow); 2744 COPY_SLIST(flist, rtxp->rtx_block); 2745 break; 2746 case ALLOW_NEW_SOURCES: 2747 case CHANGE_TO_INCLUDE: 2748 rtxp->rtx_fmode_cnt = 2749 rtype == ALLOW_NEW_SOURCES ? 0 : ill->ill_mcast_rv; 2750 CLEAR_SLIST(rtxp->rtx_block); 2751 COPY_SLIST(flist, rtxp->rtx_allow); 2752 break; 2753 } 2754 } 2755 2756 /* 2757 * The basic strategy here, as extrapolated from RFC 3810 section 6.1 and 2758 * RFC 3376 section 5.1, covers three cases: 2759 * * The current state change is a filter mode change 2760 * Set filter mode retransmit counter; set retransmit allow or 2761 * block list to new source list as appropriate, and clear the 2762 * retransmit list that was not set; send TO_IN or TO_EX with 2763 * new source list. 2764 * * The current state change is a source list change, but the filter 2765 * mode retransmit counter is > 0 2766 * Decrement filter mode retransmit counter; set retransmit 2767 * allow or block list to new source list as appropriate, 2768 * and clear the retransmit list that was not set; send TO_IN 2769 * or TO_EX with new source list. 2770 * * The current state change is a source list change, and the filter 2771 * mode retransmit counter is 0. 2772 * Merge existing rtx allow and block lists with new state: 2773 * rtx_allow = (new allow + rtx_allow) - new block 2774 * rtx_block = (new block + rtx_block) - new allow 2775 * Send ALLOW and BLOCK records for new retransmit lists; 2776 * decrement retransmit counter. 2777 * 2778 * As is the case for mcast_init_rtx(), memory allocation failures are 2779 * acceptable; we just create as much state as we can. 2780 */ 2781 static mrec_t * 2782 mcast_merge_rtx(ilm_t *ilm, mrec_t *mreclist, slist_t *flist) 2783 { 2784 ill_t *ill; 2785 rtx_state_t *rtxp = &ilm->ilm_rtx; 2786 mcast_record_t txtype; 2787 mrec_t *rp, *rpnext, *rtnmrec; 2788 boolean_t ovf; 2789 2790 ill = ilm->ilm_ill; 2791 2792 if (mreclist == NULL) 2793 return (mreclist); 2794 2795 /* 2796 * A filter mode change is indicated by a single mrec, which is 2797 * either TO_IN or TO_EX. In this case, we just need to set new 2798 * retransmit state as if this were an initial join. There is 2799 * no change to the mrec list. 2800 */ 2801 if (mreclist->mrec_type == CHANGE_TO_INCLUDE || 2802 mreclist->mrec_type == CHANGE_TO_EXCLUDE) { 2803 mcast_init_rtx(ill, rtxp, mreclist->mrec_type, 2804 &mreclist->mrec_srcs); 2805 return (mreclist); 2806 } 2807 2808 /* 2809 * Only the source list has changed 2810 */ 2811 rtxp->rtx_cnt = ill->ill_mcast_rv; 2812 if (rtxp->rtx_fmode_cnt > 0) { 2813 /* but we're still sending filter mode change reports */ 2814 rtxp->rtx_fmode_cnt--; 2815 if (ilm->ilm_fmode == MODE_IS_INCLUDE) { 2816 CLEAR_SLIST(rtxp->rtx_block); 2817 COPY_SLIST(flist, rtxp->rtx_allow); 2818 txtype = CHANGE_TO_INCLUDE; 2819 } else { 2820 CLEAR_SLIST(rtxp->rtx_allow); 2821 COPY_SLIST(flist, rtxp->rtx_block); 2822 txtype = CHANGE_TO_EXCLUDE; 2823 } 2824 /* overwrite first mrec with new info */ 2825 mreclist->mrec_type = txtype; 2826 l_copy(flist, &mreclist->mrec_srcs); 2827 /* then free any remaining mrecs */ 2828 for (rp = mreclist->mrec_next; rp != NULL; rp = rpnext) { 2829 rpnext = rp->mrec_next; 2830 mi_free(rp); 2831 } 2832 mreclist->mrec_next = NULL; 2833 rtnmrec = mreclist; 2834 } else { 2835 mrec_t *allow_mrec, *block_mrec; 2836 /* 2837 * Just send the source change reports; but we need to 2838 * recalculate the ALLOW and BLOCK lists based on previous 2839 * state and new changes. 2840 */ 2841 rtnmrec = mreclist; 2842 allow_mrec = block_mrec = NULL; 2843 for (rp = mreclist; rp != NULL; rp = rp->mrec_next) { 2844 ASSERT(rp->mrec_type == ALLOW_NEW_SOURCES || 2845 rp->mrec_type == BLOCK_OLD_SOURCES); 2846 if (rp->mrec_type == ALLOW_NEW_SOURCES) 2847 allow_mrec = rp; 2848 else 2849 block_mrec = rp; 2850 } 2851 /* 2852 * Perform calculations: 2853 * new_allow = mrec_allow + (rtx_allow - mrec_block) 2854 * new_block = mrec_block + (rtx_block - mrec_allow) 2855 * 2856 * Each calc requires two steps, for example: 2857 * rtx_allow = rtx_allow - mrec_block; 2858 * new_allow = mrec_allow + rtx_allow; 2859 * 2860 * Store results in mrec lists, and then copy into rtx lists. 2861 * We do it in this order in case the rtx list hasn't been 2862 * alloc'd yet; if it hasn't and our alloc fails, that's okay, 2863 * Overflows are also okay. 2864 */ 2865 if (block_mrec != NULL) { 2866 l_difference_in_a(rtxp->rtx_allow, 2867 &block_mrec->mrec_srcs); 2868 } 2869 if (allow_mrec != NULL) { 2870 l_difference_in_a(rtxp->rtx_block, 2871 &allow_mrec->mrec_srcs); 2872 l_union_in_a(&allow_mrec->mrec_srcs, rtxp->rtx_allow, 2873 &ovf); 2874 } 2875 if (block_mrec != NULL) { 2876 l_union_in_a(&block_mrec->mrec_srcs, rtxp->rtx_block, 2877 &ovf); 2878 COPY_SLIST(&block_mrec->mrec_srcs, rtxp->rtx_block); 2879 } else { 2880 rtnmrec = mcast_bldmrec(BLOCK_OLD_SOURCES, 2881 &ilm->ilm_v6addr, rtxp->rtx_block, allow_mrec); 2882 } 2883 if (allow_mrec != NULL) { 2884 COPY_SLIST(&allow_mrec->mrec_srcs, rtxp->rtx_allow); 2885 } else { 2886 rtnmrec = mcast_bldmrec(ALLOW_NEW_SOURCES, 2887 &ilm->ilm_v6addr, rtxp->rtx_allow, block_mrec); 2888 } 2889 } 2890 2891 return (rtnmrec); 2892 } 2893