+/*
+ in6_pcblookup_local_and_cleanup does everything
+ in6_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 function is called, we
+ can safely dispose of this socket like the slow
+ timer would usually do and return NULL. This is
+ great for bind.
+*/
+static struct inpcb*
+in6_pcblookup_local_and_cleanup(
+ struct inpcbinfo *pcbinfo,
+ struct in6_addr *laddr,
+ u_int lport_arg,
+ int wild_okay)
+{
+ struct inpcb *inp;
+
+ /* Perform normal lookup */
+ inp = in6_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;
+}