/*
- * Copyright (c) 1998-2015 Apple Inc. All rights reserved.
+ * Copyright (c) 1998-2017 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
void
soisconnecting(struct socket *so)
{
-
so->so_state &= ~(SS_ISCONNECTED|SS_ISDISCONNECTING);
so->so_state |= SS_ISCONNECTING;
void
soisconnected(struct socket *so)
{
- struct socket *head = so->so_head;
-
so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
so->so_state |= SS_ISCONNECTED;
sflt_notify(so, sock_evt_connected, NULL);
- if (head && (so->so_state & SS_INCOMP)) {
- so->so_state &= ~SS_INCOMP;
- so->so_state |= SS_COMP;
+ if (so->so_head != NULL && (so->so_state & SS_INCOMP)) {
+ struct socket *head = so->so_head;
+ int locked = 0;
+
+ /*
+ * Enforce lock order when the protocol has per socket locks
+ */
if (head->so_proto->pr_getlock != NULL) {
- socket_unlock(so, 0);
socket_lock(head, 1);
+ so_acquire_accept_list(head, so);
+ locked = 1;
}
- postevent(head, 0, EV_RCONN);
- TAILQ_REMOVE(&head->so_incomp, so, so_list);
- head->so_incqlen--;
- TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
- sorwakeup(head);
- wakeup_one((caddr_t)&head->so_timeo);
- if (head->so_proto->pr_getlock != NULL) {
+ if (so->so_head == head && (so->so_state & SS_INCOMP)) {
+ so->so_state &= ~SS_INCOMP;
+ so->so_state |= SS_COMP;
+ TAILQ_REMOVE(&head->so_incomp, so, so_list);
+ TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
+ head->so_incqlen--;
+
+ /*
+ * We have to release the accept list in
+ * case a socket callback calls sock_accept()
+ */
+ if (locked != 0) {
+ so_release_accept_list(head);
+ socket_unlock(so, 0);
+ }
+ postevent(head, 0, EV_RCONN);
+ sorwakeup(head);
+ wakeup_one((caddr_t)&head->so_timeo);
+
+ if (locked != 0) {
+ socket_unlock(head, 1);
+ socket_lock(so, 0);
+ }
+ } else if (locked != 0) {
+ so_release_accept_list(head);
socket_unlock(head, 1);
- socket_lock(so, 0);
}
} else {
postevent(so, 0, EV_WCONN);
return ((so->so_state & SS_ISCONNECTED) ||
!(so->so_proto->pr_flags & PR_CONNREQUIRED) ||
(so->so_flags1 & SOF1_PRECONNECT_DATA));
-
}
void
atomic_add_32(&so->so_proto->pr_domain->dom_refs, 1);
/* Insert in head appropriate lists */
+ so_acquire_accept_list(head, NULL);
+
so->so_head = head;
/*
}
head->so_qlen++;
+ so_release_accept_list(head);
+
/* Attach socket filters for this protocol */
sflt_initsock(so);
int
soreserve(struct socket *so, u_int32_t sndcc, u_int32_t rcvcc)
{
-
if (sbreserve(&so->so_snd, sndcc) == 0)
goto bad;
else
}
int
-pru_connectx_notsupp(struct socket *so, struct sockaddr_list **src_sl,
- struct sockaddr_list **dst_sl, struct proc *p, uint32_t ifscope,
+pru_connectx_notsupp(struct socket *so, struct sockaddr *src,
+ struct sockaddr *dst, struct proc *p, uint32_t ifscope,
sae_associd_t aid, sae_connid_t *pcid, uint32_t flags, void *arg,
uint32_t arglen, struct uio *uio, user_ssize_t *bytes_written)
{
-#pragma unused(so, src_sl, dst_sl, p, ifscope, aid, pcid, flags, arg, arglen, uio, bytes_written)
+#pragma unused(so, src, dst, p, ifscope, aid, pcid, flags, arg, arglen, uio, bytes_written)
return (EOPNOTSUPP);
}
lck_mtx_assert(mutex_held, LCK_MTX_ASSERT_OWNED);
- VERIFY(so->so_usecount != 0);
+ VERIFY(so->so_usecount > 0);
so->so_usecount--;
so->unlock_lr[so->next_unlock_lr] = lr_saved;
so->next_unlock_lr = (so->next_unlock_lr + 1) % SO_LCKDBG_MAX;