* Block or unblock an ASM multicast source on an inpcb. * This implements the delta-based API described in RFC 3678. * * The delta-based API applies only to exclusive-mode memberships. * An MLD downcall will be performed. * * SMPng: NOTE: Must take Giant as a join may create a new ifma. * * Return 0 if successful, otherwise return an appropriate error code. */
| 1398 | * Return 0 if successful, otherwise return an appropriate error code. |
| 1399 | */ |
| 1400 | static int |
| 1401 | in6p_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) |
| 1402 | { |
| 1403 | struct group_source_req gsr; |
| 1404 | sockunion_t *gsa, *ssa; |
| 1405 | struct ifnet *ifp; |
| 1406 | struct in6_mfilter *imf; |
| 1407 | struct ip6_moptions *imo; |
| 1408 | struct in6_msource *ims; |
| 1409 | struct in6_multi *inm; |
| 1410 | uint16_t fmode; |
| 1411 | int error, doblock; |
| 1412 | #ifdef KTR |
| 1413 | char ip6tbuf[INET6_ADDRSTRLEN]; |
| 1414 | #endif |
| 1415 | |
| 1416 | ifp = NULL; |
| 1417 | error = 0; |
| 1418 | doblock = 0; |
| 1419 | |
| 1420 | memset(&gsr, 0, sizeof(struct group_source_req)); |
| 1421 | gsa = (sockunion_t *)&gsr.gsr_group; |
| 1422 | ssa = (sockunion_t *)&gsr.gsr_source; |
| 1423 | |
| 1424 | switch (sopt->sopt_name) { |
| 1425 | case MCAST_BLOCK_SOURCE: |
| 1426 | case MCAST_UNBLOCK_SOURCE: |
| 1427 | error = sooptcopyin(sopt, &gsr, |
| 1428 | sizeof(struct group_source_req), |
| 1429 | sizeof(struct group_source_req)); |
| 1430 | if (error) |
| 1431 | return (error); |
| 1432 | |
| 1433 | if (gsa->sin6.sin6_family != AF_INET6 || |
| 1434 | gsa->sin6.sin6_len != sizeof(struct sockaddr_in6)) |
| 1435 | return (EINVAL); |
| 1436 | |
| 1437 | if (ssa->sin6.sin6_family != AF_INET6 || |
| 1438 | ssa->sin6.sin6_len != sizeof(struct sockaddr_in6)) |
| 1439 | return (EINVAL); |
| 1440 | |
| 1441 | if (gsr.gsr_interface == 0 || V_if_index < gsr.gsr_interface) |
| 1442 | return (EADDRNOTAVAIL); |
| 1443 | |
| 1444 | ifp = ifnet_byindex(gsr.gsr_interface); |
| 1445 | |
| 1446 | if (sopt->sopt_name == MCAST_BLOCK_SOURCE) |
| 1447 | doblock = 1; |
| 1448 | break; |
| 1449 | |
| 1450 | default: |
| 1451 | CTR2(KTR_MLD, "%s: unknown sopt_name %d", |
| 1452 | __func__, sopt->sopt_name); |
| 1453 | return (EOPNOTSUPP); |
| 1454 | break; |
| 1455 | } |
| 1456 | |
| 1457 | if (!IN6_IS_ADDR_MULTICAST(&gsa->sin6.sin6_addr)) |
no test coverage detected