* Leave an IPv6 multicast group on an inpcb, possibly with a source. */
| 2163 | * Leave an IPv6 multicast group on an inpcb, possibly with a source. |
| 2164 | */ |
| 2165 | static int |
| 2166 | in6p_leave_group(struct inpcb *inp, struct sockopt *sopt) |
| 2167 | { |
| 2168 | struct ipv6_mreq mreq; |
| 2169 | struct group_source_req gsr; |
| 2170 | sockunion_t *gsa, *ssa; |
| 2171 | struct ifnet *ifp; |
| 2172 | struct in6_mfilter *imf; |
| 2173 | struct ip6_moptions *imo; |
| 2174 | struct in6_msource *ims; |
| 2175 | struct in6_multi *inm; |
| 2176 | uint32_t ifindex; |
| 2177 | int error; |
| 2178 | bool is_final; |
| 2179 | #ifdef KTR |
| 2180 | char ip6tbuf[INET6_ADDRSTRLEN]; |
| 2181 | #endif |
| 2182 | |
| 2183 | ifp = NULL; |
| 2184 | ifindex = 0; |
| 2185 | error = 0; |
| 2186 | is_final = true; |
| 2187 | |
| 2188 | memset(&gsr, 0, sizeof(struct group_source_req)); |
| 2189 | gsa = (sockunion_t *)&gsr.gsr_group; |
| 2190 | gsa->ss.ss_family = AF_UNSPEC; |
| 2191 | ssa = (sockunion_t *)&gsr.gsr_source; |
| 2192 | ssa->ss.ss_family = AF_UNSPEC; |
| 2193 | |
| 2194 | /* |
| 2195 | * Chew everything passed in up into a struct group_source_req |
| 2196 | * as that is easier to process. |
| 2197 | * Note: Any embedded scope ID in the multicast group passed |
| 2198 | * in by userland is ignored, the interface index is the recommended |
| 2199 | * mechanism to specify an interface; see below. |
| 2200 | */ |
| 2201 | switch (sopt->sopt_name) { |
| 2202 | case IPV6_LEAVE_GROUP: |
| 2203 | error = sooptcopyin(sopt, &mreq, sizeof(struct ipv6_mreq), |
| 2204 | sizeof(struct ipv6_mreq)); |
| 2205 | if (error) |
| 2206 | return (error); |
| 2207 | gsa->sin6.sin6_family = AF_INET6; |
| 2208 | gsa->sin6.sin6_len = sizeof(struct sockaddr_in6); |
| 2209 | gsa->sin6.sin6_addr = mreq.ipv6mr_multiaddr; |
| 2210 | gsa->sin6.sin6_port = 0; |
| 2211 | gsa->sin6.sin6_scope_id = 0; |
| 2212 | ifindex = mreq.ipv6mr_interface; |
| 2213 | break; |
| 2214 | |
| 2215 | case MCAST_LEAVE_GROUP: |
| 2216 | case MCAST_LEAVE_SOURCE_GROUP: |
| 2217 | if (sopt->sopt_name == MCAST_LEAVE_GROUP) { |
| 2218 | error = sooptcopyin(sopt, &gsr, |
| 2219 | sizeof(struct group_req), |
| 2220 | sizeof(struct group_req)); |
| 2221 | } else if (sopt->sopt_name == MCAST_LEAVE_SOURCE_GROUP) { |
| 2222 | error = sooptcopyin(sopt, &gsr, |
no test coverage detected