* Leave a multicast group; real entry point. * All source filters will be expunged. * * Only preserves atomicity at inm level. * * Holding the write lock for the INP which contains imf * is highly advisable. We can't assert for it as imf does not * contain a back-pointer to the owning inp. * * Note: This is not the same as inm_release(*) as this function also * makes a state change downc
| 1322 | * makes a state change downcall into IGMP. |
| 1323 | */ |
| 1324 | int |
| 1325 | in_leavegroup_locked(struct in_multi *inm, /*const*/ struct in_mfilter *imf) |
| 1326 | { |
| 1327 | struct in_mfilter timf; |
| 1328 | int error; |
| 1329 | |
| 1330 | IN_MULTI_LOCK_ASSERT(); |
| 1331 | IN_MULTI_LIST_UNLOCK_ASSERT(); |
| 1332 | |
| 1333 | error = 0; |
| 1334 | |
| 1335 | CTR5(KTR_IGMPV3, "%s: leave inm %p, 0x%08x/%s, imf %p", __func__, |
| 1336 | inm, ntohl(inm->inm_addr.s_addr), |
| 1337 | (inm_is_ifp_detached(inm) ? "null" : inm->inm_ifp->if_xname), |
| 1338 | imf); |
| 1339 | |
| 1340 | /* |
| 1341 | * If no imf was specified (i.e. kernel consumer), |
| 1342 | * fake one up and assume it is an ASM join. |
| 1343 | */ |
| 1344 | if (imf == NULL) { |
| 1345 | imf_init(&timf, MCAST_EXCLUDE, MCAST_UNDEFINED); |
| 1346 | imf = &timf; |
| 1347 | } |
| 1348 | |
| 1349 | /* |
| 1350 | * Begin state merge transaction at IGMP layer. |
| 1351 | * |
| 1352 | * As this particular invocation should not cause any memory |
| 1353 | * to be allocated, and there is no opportunity to roll back |
| 1354 | * the transaction, it MUST NOT fail. |
| 1355 | */ |
| 1356 | CTR1(KTR_IGMPV3, "%s: merge inm state", __func__); |
| 1357 | IN_MULTI_LIST_LOCK(); |
| 1358 | error = inm_merge(inm, imf); |
| 1359 | KASSERT(error == 0, ("%s: failed to merge inm state", __func__)); |
| 1360 | |
| 1361 | CTR1(KTR_IGMPV3, "%s: doing igmp downcall", __func__); |
| 1362 | CURVNET_SET(inm->inm_ifp->if_vnet); |
| 1363 | error = igmp_change_state(inm); |
| 1364 | IF_ADDR_WLOCK(inm->inm_ifp); |
| 1365 | inm_release_deferred(inm); |
| 1366 | IF_ADDR_WUNLOCK(inm->inm_ifp); |
| 1367 | IN_MULTI_LIST_UNLOCK(); |
| 1368 | CURVNET_RESTORE(); |
| 1369 | if (error) |
| 1370 | CTR1(KTR_IGMPV3, "%s: failed igmp downcall", __func__); |
| 1371 | |
| 1372 | CTR2(KTR_IGMPV3, "%s: dropping ref on %p", __func__, inm); |
| 1373 | |
| 1374 | return (error); |
| 1375 | } |
| 1376 | |
| 1377 | /*#ifndef BURN_BRIDGES*/ |
| 1378 | /* |
no test coverage detected