* Hook for ifdetach. * * NOTE: Some finalization tasks need to run before the protocol domain * is detached, but also before the link layer does its cleanup. * Run before link-layer cleanup; cleanup groups, but do not free MLD state. * * SMPng: Caller must hold IN6_MULTI_LOCK(). * Must take IF_ADDR_LOCK() to cover if_multiaddrs iterator. * XXX This routine is also bitten by unlocked ifma_p
| 539 | * XXX This routine is also bitten by unlocked ifma_protospec access. |
| 540 | */ |
| 541 | void |
| 542 | mld_ifdetach(struct ifnet *ifp, struct in6_multi_head *inmh) |
| 543 | { |
| 544 | struct epoch_tracker et; |
| 545 | struct mld_ifsoftc *mli; |
| 546 | struct ifmultiaddr *ifma; |
| 547 | struct in6_multi *inm; |
| 548 | |
| 549 | CTR3(KTR_MLD, "%s: called for ifp %p(%s)", __func__, ifp, |
| 550 | if_name(ifp)); |
| 551 | |
| 552 | IN6_MULTI_LIST_LOCK_ASSERT(); |
| 553 | MLD_LOCK(); |
| 554 | |
| 555 | mli = MLD_IFINFO(ifp); |
| 556 | IF_ADDR_WLOCK(ifp); |
| 557 | /* |
| 558 | * Extract list of in6_multi associated with the detaching ifp |
| 559 | * which the PF_INET6 layer is about to release. |
| 560 | */ |
| 561 | NET_EPOCH_ENTER(et); |
| 562 | CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
| 563 | inm = in6m_ifmultiaddr_get_inm(ifma); |
| 564 | if (inm == NULL) |
| 565 | continue; |
| 566 | in6m_disconnect_locked(inmh, inm); |
| 567 | |
| 568 | if (mli->mli_version == MLD_VERSION_2) { |
| 569 | in6m_clear_recorded(inm); |
| 570 | |
| 571 | /* |
| 572 | * We need to release the final reference held |
| 573 | * for issuing the INCLUDE {}. |
| 574 | */ |
| 575 | if (inm->in6m_state == MLD_LEAVING_MEMBER) { |
| 576 | inm->in6m_state = MLD_NOT_MEMBER; |
| 577 | in6m_rele_locked(inmh, inm); |
| 578 | } |
| 579 | } |
| 580 | } |
| 581 | NET_EPOCH_EXIT(et); |
| 582 | IF_ADDR_WUNLOCK(ifp); |
| 583 | MLD_UNLOCK(); |
| 584 | } |
| 585 | |
| 586 | /* |
| 587 | * Hook for domifdetach. |
no test coverage detected