+
+/*
+ in_pcblookup_local_and_cleanup does everything
+ in_pcblookup_local does but it checks for a socket
+ that's going away. Since we know that the lock is
+ held read+write when this funciton is called, we
+ can safely dispose of this socket like the slow
+ timer would usually do and return NULL. This is
+ great for bind.
+*/
+struct inpcb*
+in_pcblookup_local_and_cleanup(
+ struct inpcbinfo *pcbinfo,
+ struct in_addr laddr,
+ u_int lport_arg,
+ int wild_okay)
+{
+ struct inpcb *inp;
+
+ /* Perform normal lookup */
+ inp = in_pcblookup_local(pcbinfo, laddr, lport_arg, wild_okay);
+
+ /* Check if we found a match but it's waiting to be disposed */
+ if (inp && inp->inp_wantcnt == WNT_STOPUSING) {
+ struct socket *so = inp->inp_socket;
+
+ lck_mtx_lock(inp->inpcb_mtx);
+
+ if (so->so_usecount == 0) {
+ in_pcbdispose(inp);
+ inp = NULL;
+ }
+ else {
+ lck_mtx_unlock(inp->inpcb_mtx);
+ }
+ }
+
+ return inp;
+}
+
+#ifdef __APPLE_API_PRIVATE
+static void
+in_pcb_conflict_post_msg(u_int16_t port)
+{
+ /*
+ * Radar 5523020 send a kernel event notification if a non-participating socket tries to bind
+ * the port a socket who has set SOF_NOTIFYCONFLICT owns.
+ */
+ struct kev_msg ev_msg;
+ struct kev_in_portinuse in_portinuse;
+
+ in_portinuse.port = ntohs(port); /* port in host order */
+ in_portinuse.req_pid = proc_selfpid();
+ ev_msg.vendor_code = KEV_VENDOR_APPLE;
+ ev_msg.kev_class = KEV_NETWORK_CLASS;
+ ev_msg.kev_subclass = KEV_INET_SUBCLASS;
+ ev_msg.event_code = KEV_INET_PORTINUSE;
+ ev_msg.dv[0].data_ptr = &in_portinuse;
+ ev_msg.dv[0].data_length = sizeof(struct kev_in_portinuse);
+ ev_msg.dv[1].data_length = 0;
+ kev_post_msg(&ev_msg);
+}
+#endif
+/*
+ * Returns: 0 Success
+ * EADDRNOTAVAIL Address not available.
+ * EINVAL Invalid argument
+ * EAFNOSUPPORT Address family not supported [notdef]
+ * EACCES Permission denied
+ * EADDRINUSE Address in use
+ * EAGAIN Resource unavailable, try again
+ * proc_suser:EPERM Operation not permitted
+ */