/*
- * Copyright (c) 2010-2013 Apple Inc. All rights reserved.
+ * Copyright (c) 2010-2016 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
IGMP_PRINTF(("%s: unknown sopt_name %d\n",
__func__, sopt->sopt_name));
return (EOPNOTSUPP);
- break;
}
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
if (error)
return (error);
/* we never use msfr.msfr_srcs; */
- memcpy(&msfr, &msfr64, sizeof(msfr));
+ memcpy(&msfr, &msfr64, sizeof(msfr64));
} else {
error = sooptcopyin(sopt, &msfr32,
sizeof(struct __msfilterreq32),
if (error)
return (error);
/* we never use msfr.msfr_srcs; */
- memcpy(&msfr, &msfr32, sizeof(msfr));
+ memcpy(&msfr, &msfr32, sizeof(msfr32));
}
ifnet_head_lock_shared();
IMO_UNLOCK(imo);
return (ENOBUFS);
}
- bzero(tss, (size_t) msfr.msfr_nsrcs * sizeof(*tss));
}
/*
msfr32.msfr_ifindex = msfr.msfr_ifindex;
msfr32.msfr_fmode = msfr.msfr_fmode;
msfr32.msfr_nsrcs = msfr.msfr_nsrcs;
- memcpy(&msfr64.msfr_group, &msfr.msfr_group,
+ memcpy(&msfr32.msfr_group, &msfr.msfr_group,
sizeof(struct sockaddr_storage));
error = sooptcopyout(sopt, &msfr32,
sizeof(struct __msfilterreq32));
error = 0;
switch (sopt->sopt_name) {
-#ifdef MROUTING
- case IP_MULTICAST_VIF:
- if (imo != NULL) {
- IMO_LOCK(imo);
- optval = imo->imo_multicast_vif;
- IMO_UNLOCK(imo);
- } else
- optval = -1;
- error = sooptcopyout(sopt, &optval, sizeof(int));
- break;
-#endif /* MROUTING */
-
case IP_MULTICAST_IF:
memset(&mreqn, 0, sizeof(struct ip_mreqn));
if (imo != NULL) {
IGMP_PRINTF(("%s: unknown sopt_name %d\n",
__func__, sopt->sopt_name));
return (EOPNOTSUPP);
- break;
}
if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0)
/*
* Begin state merge transaction at IGMP layer.
*/
-
if (is_new) {
+ /*
+ * Unlock socket as we may end up calling ifnet_ioctl() to join (or leave)
+ * the multicast group and we run the risk of a lock ordering issue
+ * if the ifnet thread calls into the socket layer to acquire the pcb list
+ * lock while the input thread delivers multicast packets
+ */
+ IMO_ADDREF_LOCKED(imo);
+ IMO_UNLOCK(imo);
+ socket_unlock(inp->inp_socket, 0);
+
VERIFY(inm == NULL);
error = in_joingroup(ifp, &gsa->sin.sin_addr, imf, &inm);
+
+ socket_lock(inp->inp_socket, 0);
+ IMO_REMREF(imo);
+ IMO_LOCK(imo);
+
VERIFY(inm != NULL || error != 0);
if (error)
goto out_imo_free;
IGMP_PRINTF(("%s: unknown sopt_name %d\n",
__func__, sopt->sopt_name));
return (EOPNOTSUPP);
- break;
}
if (!IN_MULTICAST(ntohl(gsa->sin.sin_addr.s_addr)))
* Begin state merge transaction at IGMP layer.
*/
+
if (is_final) {
/*
* Give up the multicast address record to which
imf_reap(imf);
if (is_final) {
- /* Remove the gap in the membership and filter array. */
+ /* Remove the gap in the membership array. */
VERIFY(inm == imo->imo_membership[idx]);
imo->imo_membership[idx] = NULL;
+
+ /*
+ * See inp_join_group() for why we need to unlock
+ */
+ IMO_ADDREF_LOCKED(imo);
+ IMO_UNLOCK(imo);
+ socket_unlock(inp->inp_socket, 0);
+
INM_REMREF(inm);
+
+ socket_lock(inp->inp_socket, 0);
+ IMO_REMREF(imo);
+ IMO_LOCK(imo);
+
for (++idx; idx < imo->imo_num_memberships; ++idx) {
imo->imo_membership[idx-1] = imo->imo_membership[idx];
imo->imo_mfilters[idx-1] = imo->imo_mfilters[idx];
if (error)
return (error);
/* we never use msfr.msfr_srcs; */
- memcpy(&msfr, &msfr64, sizeof(msfr));
+ memcpy(&msfr, &msfr64, sizeof(msfr64));
} else {
error = sooptcopyin(sopt, &msfr32,
sizeof(struct __msfilterreq32),
if (error)
return (error);
/* we never use msfr.msfr_srcs; */
- memcpy(&msfr, &msfr32, sizeof(msfr));
+ memcpy(&msfr, &msfr32, sizeof(msfr32));
}
if ((size_t) msfr.msfr_nsrcs >
* it is not possible to merge the duplicate code, because the idempotence
* of the IPv4 multicast part of the BSD Sockets API must be preserved;
* the effects of these options must be treated as separate and distinct.
- *
- * FUTURE: The IP_MULTICAST_VIF option may be eliminated if MROUTING
- * is refactored to no longer use vifs.
*/
int
inp_setmoptions(struct inpcb *inp, struct sockopt *sopt)
return (EOPNOTSUPP);
switch (sopt->sopt_name) {
-#if MROUTING
- case IP_MULTICAST_VIF: {
- int vifi;
- /*
- * Select a multicast VIF for transmission.
- * Only useful if multicast forwarding is active.
- */
- if (legal_vif_num == NULL) {
- error = EOPNOTSUPP;
- break;
- }
- error = sooptcopyin(sopt, &vifi, sizeof(int), sizeof(int));
- if (error)
- break;
- if (!legal_vif_num(vifi) && (vifi != -1)) {
- error = EINVAL;
- break;
- }
- imo = inp_findmoptions(inp);
- if (imo == NULL) {
- error = ENOMEM;
- break;
- }
- IMO_LOCK(imo);
- imo->imo_multicast_vif = vifi;
- IMO_UNLOCK(imo);
- IMO_REMREF(imo); /* from inp_findmoptions() */
- break;
- }
-#endif
case IP_MULTICAST_IF:
error = inp_set_multicast_if(inp, sopt);
break;