* 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. * * SMPNG: igmp_ifdetach() needs to take IF_ADDR_LOCK(). * XXX This is also bitten by unlocked ifma_protospec access. */
| 671 | * XXX This is also bitten by unlocked ifma_protospec access. |
| 672 | */ |
| 673 | void |
| 674 | igmp_ifdetach(struct ifnet *ifp) |
| 675 | { |
| 676 | struct igmp_ifsoftc *igi; |
| 677 | struct ifmultiaddr *ifma, *next; |
| 678 | struct in_multi *inm; |
| 679 | struct in_multi_head inm_free_tmp; |
| 680 | CTR3(KTR_IGMPV3, "%s: called for ifp %p(%s)", __func__, ifp, |
| 681 | ifp->if_xname); |
| 682 | |
| 683 | SLIST_INIT(&inm_free_tmp); |
| 684 | IGMP_LOCK(); |
| 685 | |
| 686 | igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; |
| 687 | if (igi->igi_version == IGMP_VERSION_3) { |
| 688 | IF_ADDR_WLOCK(ifp); |
| 689 | restart: |
| 690 | CK_STAILQ_FOREACH_SAFE(ifma, &ifp->if_multiaddrs, ifma_link, next) { |
| 691 | if (ifma->ifma_addr->sa_family != AF_INET || |
| 692 | ifma->ifma_protospec == NULL) |
| 693 | continue; |
| 694 | inm = (struct in_multi *)ifma->ifma_protospec; |
| 695 | if (inm->inm_state == IGMP_LEAVING_MEMBER) |
| 696 | inm_rele_locked(&inm_free_tmp, inm); |
| 697 | inm_clear_recorded(inm); |
| 698 | if (__predict_false(ifma_restart)) { |
| 699 | ifma_restart = false; |
| 700 | goto restart; |
| 701 | } |
| 702 | } |
| 703 | IF_ADDR_WUNLOCK(ifp); |
| 704 | inm_release_list_deferred(&inm_free_tmp); |
| 705 | } |
| 706 | IGMP_UNLOCK(); |
| 707 | |
| 708 | } |
| 709 | |
| 710 | /* |
| 711 | * Hook for domifdetach. |
no test coverage detected