* Join an IPv4 multicast group, possibly with a source. */
| 1969 | * Join an IPv4 multicast group, possibly with a source. |
| 1970 | */ |
| 1971 | static int |
| 1972 | inp_join_group(struct inpcb *inp, struct sockopt *sopt) |
| 1973 | { |
| 1974 | struct group_source_req gsr; |
| 1975 | sockunion_t *gsa, *ssa; |
| 1976 | struct ifnet *ifp; |
| 1977 | struct in_mfilter *imf; |
| 1978 | struct ip_moptions *imo; |
| 1979 | struct in_multi *inm; |
| 1980 | struct in_msource *lims; |
| 1981 | struct epoch_tracker et; |
| 1982 | int error, is_new; |
| 1983 | |
| 1984 | ifp = NULL; |
| 1985 | lims = NULL; |
| 1986 | error = 0; |
| 1987 | |
| 1988 | memset(&gsr, 0, sizeof(struct group_source_req)); |
| 1989 | gsa = (sockunion_t *)&gsr.gsr_group; |
| 1990 | gsa->ss.ss_family = AF_UNSPEC; |
| 1991 | ssa = (sockunion_t *)&gsr.gsr_source; |
| 1992 | ssa->ss.ss_family = AF_UNSPEC; |
| 1993 | |
| 1994 | switch (sopt->sopt_name) { |
| 1995 | case IP_ADD_MEMBERSHIP: { |
| 1996 | struct ip_mreqn mreqn; |
| 1997 | |
| 1998 | if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) |
| 1999 | error = sooptcopyin(sopt, &mreqn, |
| 2000 | sizeof(struct ip_mreqn), sizeof(struct ip_mreqn)); |
| 2001 | else |
| 2002 | error = sooptcopyin(sopt, &mreqn, |
| 2003 | sizeof(struct ip_mreq), sizeof(struct ip_mreq)); |
| 2004 | if (error) |
| 2005 | return (error); |
| 2006 | |
| 2007 | gsa->sin.sin_family = AF_INET; |
| 2008 | gsa->sin.sin_len = sizeof(struct sockaddr_in); |
| 2009 | gsa->sin.sin_addr = mreqn.imr_multiaddr; |
| 2010 | if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr))) |
| 2011 | return (EINVAL); |
| 2012 | |
| 2013 | NET_EPOCH_ENTER(et); |
| 2014 | if (sopt->sopt_valsize == sizeof(struct ip_mreqn) && |
| 2015 | mreqn.imr_ifindex != 0) |
| 2016 | ifp = ifnet_byindex_ref(mreqn.imr_ifindex); |
| 2017 | else |
| 2018 | ifp = inp_lookup_mcast_ifp(inp, &gsa->sin, |
| 2019 | mreqn.imr_address); |
| 2020 | NET_EPOCH_EXIT(et); |
| 2021 | break; |
| 2022 | } |
| 2023 | case IP_ADD_SOURCE_MEMBERSHIP: { |
| 2024 | struct ip_mreq_source mreqs; |
| 2025 | |
| 2026 | error = sooptcopyin(sopt, &mreqs, sizeof(struct ip_mreq_source), |
| 2027 | sizeof(struct ip_mreq_source)); |
| 2028 | if (error) |
no test coverage detected