* 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 IGMP 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. */
| 1412 | * Return 0 if successful, otherwise return an appropriate error code. |
| 1413 | */ |
| 1414 | static int |
| 1415 | inp_block_unblock_source(struct inpcb *inp, struct sockopt *sopt) |
| 1416 | { |
| 1417 | struct group_source_req gsr; |
| 1418 | struct rm_priotracker in_ifa_tracker; |
| 1419 | sockunion_t *gsa, *ssa; |
| 1420 | struct ifnet *ifp; |
| 1421 | struct in_mfilter *imf; |
| 1422 | struct ip_moptions *imo; |
| 1423 | struct in_msource *ims; |
| 1424 | struct in_multi *inm; |
| 1425 | uint16_t fmode; |
| 1426 | int error, doblock; |
| 1427 | |
| 1428 | ifp = NULL; |
| 1429 | error = 0; |
| 1430 | doblock = 0; |
| 1431 | |
| 1432 | memset(&gsr, 0, sizeof(struct group_source_req)); |
| 1433 | gsa = (sockunion_t *)&gsr.gsr_group; |
| 1434 | ssa = (sockunion_t *)&gsr.gsr_source; |
| 1435 | |
| 1436 | switch (sopt->sopt_name) { |
| 1437 | case IP_BLOCK_SOURCE: |
| 1438 | case IP_UNBLOCK_SOURCE: { |
| 1439 | struct ip_mreq_source mreqs; |
| 1440 | |
| 1441 | error = sooptcopyin(sopt, &mreqs, |
| 1442 | sizeof(struct ip_mreq_source), |
| 1443 | sizeof(struct ip_mreq_source)); |
| 1444 | if (error) |
| 1445 | return (error); |
| 1446 | |
| 1447 | gsa->sin.sin_family = AF_INET; |
| 1448 | gsa->sin.sin_len = sizeof(struct sockaddr_in); |
| 1449 | gsa->sin.sin_addr = mreqs.imr_multiaddr; |
| 1450 | |
| 1451 | ssa->sin.sin_family = AF_INET; |
| 1452 | ssa->sin.sin_len = sizeof(struct sockaddr_in); |
| 1453 | ssa->sin.sin_addr = mreqs.imr_sourceaddr; |
| 1454 | |
| 1455 | if (!in_nullhost(mreqs.imr_interface)) { |
| 1456 | IN_IFADDR_RLOCK(&in_ifa_tracker); |
| 1457 | INADDR_TO_IFP(mreqs.imr_interface, ifp); |
| 1458 | IN_IFADDR_RUNLOCK(&in_ifa_tracker); |
| 1459 | } |
| 1460 | if (sopt->sopt_name == IP_BLOCK_SOURCE) |
| 1461 | doblock = 1; |
| 1462 | |
| 1463 | CTR3(KTR_IGMPV3, "%s: imr_interface = 0x%08x, ifp = %p", |
| 1464 | __func__, ntohl(mreqs.imr_interface.s_addr), ifp); |
| 1465 | break; |
| 1466 | } |
| 1467 | |
| 1468 | case MCAST_BLOCK_SOURCE: |
| 1469 | case MCAST_UNBLOCK_SOURCE: |
| 1470 | error = sooptcopyin(sopt, &gsr, |
| 1471 | sizeof(struct group_source_req), |
no test coverage detected