return (EINVAL);
if (!(so->so_options & (SO_REUSEADDR|SO_REUSEPORT)))
wild = 1;
- socket_unlock(so, 0); /* keep reference on socket */
- lck_rw_lock_exclusive(pcbinfo->ipi_lock);
bzero(&laddr, sizeof(laddr));
+ socket_unlock(so, 0); /* keep reference on socket */
+ lck_rw_lock_exclusive(pcbinfo->ipi_lock);
+
if (nam != NULL) {
if (nam->sa_len != sizeof (struct sockaddr_in)) {
}
}
socket_lock(so, 0);
+
+ /*
+ * We unlocked socket's protocol lock for a long time.
+ * The socket might have been dropped/defuncted.
+ * Checking if world has changed since.
+ */
+ if (inp->inp_state == INPCB_STATE_DEAD) {
+ lck_rw_done(pcbinfo->ipi_lock);
+ return (ECONNABORTED);
+ }
+
if (inp->inp_lport != 0 || inp->inp_laddr.s_addr != INADDR_ANY) {
lck_rw_done(pcbinfo->ipi_lock);
return (EINVAL);
}
/*
- * Insert PCB onto various hash lists.
+ * @brief Insert PCB onto various hash lists.
+ *
+ * @param inp Pointer to internet protocol control block
+ * @param locked Implies if ipi_lock (protecting pcb list)
+ * is already locked or not.
+ *
+ * @return int error on failure and 0 on success
*/
int
in_pcbinshash(struct inpcb *inp, int locked)
socket_unlock(inp->inp_socket, 0);
lck_rw_lock_exclusive(pcbinfo->ipi_lock);
socket_lock(inp->inp_socket, 0);
- if (inp->inp_state == INPCB_STATE_DEAD) {
- /*
- * The socket got dropped when
- * it was unlocked
- */
- lck_rw_done(pcbinfo->ipi_lock);
- return (ECONNABORTED);
- }
}
}
+ /*
+ * This routine or its caller may have given up
+ * socket's protocol lock briefly.
+ * During that time the socket may have been dropped.
+ * Safe-guarding against that.
+ */
+ if (inp->inp_state == INPCB_STATE_DEAD) {
+ if (!locked) {
+ lck_rw_done(pcbinfo->ipi_lock);
+ }
+ return (ECONNABORTED);
+ }
+
+
#if INET6
if (inp->inp_vflag & INP_IPV6)
hashkey_faddr = inp->in6p_faddr.s6_addr32[3] /* XXX */;
break;
}
- VERIFY(inp->inp_state != INPCB_STATE_DEAD);
-
/*
* If none exists, malloc one and tack it on.
*/