* Leave an IPv4 multicast group on an inpcb, possibly with a source. */
| 2295 | * Leave an IPv4 multicast group on an inpcb, possibly with a source. |
| 2296 | */ |
| 2297 | static int |
| 2298 | inp_leave_group(struct inpcb *inp, struct sockopt *sopt) |
| 2299 | { |
| 2300 | struct group_source_req gsr; |
| 2301 | struct ip_mreq_source mreqs; |
| 2302 | struct rm_priotracker in_ifa_tracker; |
| 2303 | sockunion_t *gsa, *ssa; |
| 2304 | struct ifnet *ifp; |
| 2305 | struct in_mfilter *imf; |
| 2306 | struct ip_moptions *imo; |
| 2307 | struct in_msource *ims; |
| 2308 | struct in_multi *inm; |
| 2309 | int error; |
| 2310 | bool is_final; |
| 2311 | |
| 2312 | ifp = NULL; |
| 2313 | error = 0; |
| 2314 | is_final = true; |
| 2315 | |
| 2316 | memset(&gsr, 0, sizeof(struct group_source_req)); |
| 2317 | gsa = (sockunion_t *)&gsr.gsr_group; |
| 2318 | gsa->ss.ss_family = AF_UNSPEC; |
| 2319 | ssa = (sockunion_t *)&gsr.gsr_source; |
| 2320 | ssa->ss.ss_family = AF_UNSPEC; |
| 2321 | |
| 2322 | switch (sopt->sopt_name) { |
| 2323 | case IP_DROP_MEMBERSHIP: |
| 2324 | case IP_DROP_SOURCE_MEMBERSHIP: |
| 2325 | if (sopt->sopt_name == IP_DROP_MEMBERSHIP) { |
| 2326 | error = sooptcopyin(sopt, &mreqs, |
| 2327 | sizeof(struct ip_mreq), |
| 2328 | sizeof(struct ip_mreq)); |
| 2329 | /* |
| 2330 | * Swap interface and sourceaddr arguments, |
| 2331 | * as ip_mreq and ip_mreq_source are laid |
| 2332 | * out differently. |
| 2333 | */ |
| 2334 | mreqs.imr_interface = mreqs.imr_sourceaddr; |
| 2335 | mreqs.imr_sourceaddr.s_addr = INADDR_ANY; |
| 2336 | } else if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { |
| 2337 | error = sooptcopyin(sopt, &mreqs, |
| 2338 | sizeof(struct ip_mreq_source), |
| 2339 | sizeof(struct ip_mreq_source)); |
| 2340 | } |
| 2341 | if (error) |
| 2342 | return (error); |
| 2343 | |
| 2344 | gsa->sin.sin_family = AF_INET; |
| 2345 | gsa->sin.sin_len = sizeof(struct sockaddr_in); |
| 2346 | gsa->sin.sin_addr = mreqs.imr_multiaddr; |
| 2347 | |
| 2348 | if (sopt->sopt_name == IP_DROP_SOURCE_MEMBERSHIP) { |
| 2349 | ssa->sin.sin_family = AF_INET; |
| 2350 | ssa->sin.sin_len = sizeof(struct sockaddr_in); |
| 2351 | ssa->sin.sin_addr = mreqs.imr_sourceaddr; |
| 2352 | } |
| 2353 | |
| 2354 | /* |
no test coverage detected