* Drop a reference to an in6_multi record. * * If the refcount drops to 0, free the in6_multi record and * delete the underlying link-layer membership. */
| 476 | * delete the underlying link-layer membership. |
| 477 | */ |
| 478 | static void |
| 479 | in6m_release(struct in6_multi *inm) |
| 480 | { |
| 481 | struct ifmultiaddr *ifma; |
| 482 | struct ifnet *ifp; |
| 483 | |
| 484 | CTR2(KTR_MLD, "%s: refcount is %d", __func__, inm->in6m_refcount); |
| 485 | |
| 486 | MPASS(inm->in6m_refcount == 0); |
| 487 | CTR2(KTR_MLD, "%s: freeing inm %p", __func__, inm); |
| 488 | |
| 489 | ifma = inm->in6m_ifma; |
| 490 | ifp = inm->in6m_ifp; |
| 491 | MPASS(ifma->ifma_llifma == NULL); |
| 492 | |
| 493 | /* XXX this access is not covered by IF_ADDR_LOCK */ |
| 494 | CTR2(KTR_MLD, "%s: purging ifma %p", __func__, ifma); |
| 495 | KASSERT(ifma->ifma_protospec == NULL, |
| 496 | ("%s: ifma_protospec != NULL", __func__)); |
| 497 | if (ifp == NULL) |
| 498 | ifp = ifma->ifma_ifp; |
| 499 | |
| 500 | if (ifp != NULL) { |
| 501 | CURVNET_SET(ifp->if_vnet); |
| 502 | in6m_purge(inm); |
| 503 | free(inm, M_IP6MADDR); |
| 504 | if_delmulti_ifma_flags(ifma, 1); |
| 505 | CURVNET_RESTORE(); |
| 506 | if_rele(ifp); |
| 507 | } else { |
| 508 | in6m_purge(inm); |
| 509 | free(inm, M_IP6MADDR); |
| 510 | if_delmulti_ifma_flags(ifma, 1); |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | /* |
| 515 | * Interface detach can happen in a taskqueue thread context, so we must use a |
no test coverage detected