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