* Perform the initial join for an IGMP group. * * When joining a group: * If the group should have its IGMP traffic suppressed, do nothing. * IGMPv1 starts sending IGMPv1 host membership reports. * IGMPv2 starts sending IGMPv2 host membership reports. * IGMPv3 will schedule an IGMPv3 state-change report containing the * initial state of the membership. */
| 2379 | * initial state of the membership. |
| 2380 | */ |
| 2381 | static int |
| 2382 | igmp_initial_join(struct in_multi *inm, struct igmp_ifsoftc *igi) |
| 2383 | { |
| 2384 | struct ifnet *ifp; |
| 2385 | struct mbufq *mq; |
| 2386 | int error, retval, syncstates; |
| 2387 | |
| 2388 | CTR4(KTR_IGMPV3, "%s: initial join 0x%08x on ifp %p(%s)", __func__, |
| 2389 | ntohl(inm->inm_addr.s_addr), inm->inm_ifp, inm->inm_ifp->if_xname); |
| 2390 | |
| 2391 | error = 0; |
| 2392 | syncstates = 1; |
| 2393 | |
| 2394 | ifp = inm->inm_ifp; |
| 2395 | |
| 2396 | IN_MULTI_LOCK_ASSERT(); |
| 2397 | IGMP_LOCK_ASSERT(); |
| 2398 | |
| 2399 | KASSERT(igi && igi->igi_ifp == ifp, ("%s: inconsistent ifp", __func__)); |
| 2400 | |
| 2401 | /* |
| 2402 | * Groups joined on loopback or marked as 'not reported', |
| 2403 | * e.g. 224.0.0.1, enter the IGMP_SILENT_MEMBER state and |
| 2404 | * are never reported in any IGMP protocol exchanges. |
| 2405 | * All other groups enter the appropriate IGMP state machine |
| 2406 | * for the version in use on this link. |
| 2407 | * A link marked as IGIF_SILENT causes IGMP to be completely |
| 2408 | * disabled for the link. |
| 2409 | */ |
| 2410 | if ((ifp->if_flags & IFF_LOOPBACK) || |
| 2411 | (igi->igi_flags & IGIF_SILENT) || |
| 2412 | !igmp_isgroupreported(inm->inm_addr)) { |
| 2413 | CTR1(KTR_IGMPV3, |
| 2414 | "%s: not kicking state machine for silent group", __func__); |
| 2415 | inm->inm_state = IGMP_SILENT_MEMBER; |
| 2416 | inm->inm_timer = 0; |
| 2417 | } else { |
| 2418 | /* |
| 2419 | * Deal with overlapping in_multi lifecycle. |
| 2420 | * If this group was LEAVING, then make sure |
| 2421 | * we drop the reference we picked up to keep the |
| 2422 | * group around for the final INCLUDE {} enqueue. |
| 2423 | */ |
| 2424 | if (igi->igi_version == IGMP_VERSION_3 && |
| 2425 | inm->inm_state == IGMP_LEAVING_MEMBER) { |
| 2426 | MPASS(inm->inm_refcount > 1); |
| 2427 | inm_rele_locked(NULL, inm); |
| 2428 | } |
| 2429 | inm->inm_state = IGMP_REPORTING_MEMBER; |
| 2430 | |
| 2431 | switch (igi->igi_version) { |
| 2432 | case IGMP_VERSION_1: |
| 2433 | case IGMP_VERSION_2: |
| 2434 | inm->inm_state = IGMP_IDLE_MEMBER; |
| 2435 | error = igmp_v1v2_queue_report(inm, |
| 2436 | (igi->igi_version == IGMP_VERSION_2) ? |
| 2437 | IGMP_v2_HOST_MEMBERSHIP_REPORT : |
| 2438 | IGMP_v1_HOST_MEMBERSHIP_REPORT); |
no test coverage detected