void in6_pcbdetach(struct in6pcb *in6p) { struct socket *so = in6p->in6p_socket; int s; if (in6p->in6p_af != AF_INET6) return; #if defined(IPSEC) || defined(FAST_IPSEC) ipsec6_delete_pcbpolicy(in6p); #endif /* IPSEC */ so->so_pcb = 0; if (in6p->in6p_options) m_freem(in6p->in6p_options); if (in6p->in6p_outputopts != NULL) { ip6_clearpktopts(in6p->in6p_outputopts, -1); free(in6p->in6p_outputopts, M_IP6OPT); } rtcache_free(&in6p->in6p_route); ip6_freemoptions(in6p->in6p_moptions); s = splnet(); in6_pcbstate(in6p, IN6P_ATTACHED); LIST_REMOVE(&in6p->in6p_head, inph_lhash); CIRCLEQ_REMOVE(&in6p->in6p_table->inpt_queue, &in6p->in6p_head, inph_queue); pool_put(&in6pcb_pool, in6p); splx(s); sofree(so); /* drops the socket's lock */ mutex_enter(softnet_lock); /* reacquire it */ }
void in6_pcbdetach( struct inpcb *inp) { struct socket *so = inp->inp_socket; struct inpcbinfo *ipi = inp->inp_pcbinfo; #if IPSEC if (inp->in6p_sp != NULL) { ipsec6_delete_pcbpolicy(inp); } #endif /* IPSEC */ if (in_pcb_checkstate(inp, WNT_STOPUSING, 1) != WNT_STOPUSING) printf("in6_pcbdetach so=%p can't be marked dead ok\n", so); inp->inp_state = INPCB_STATE_DEAD; if ((so->so_flags & SOF_PCBCLEARING) == 0) { struct ip_moptions *imo; struct ip6_moptions *im6o; inp->inp_vflag = 0; so->so_flags |= SOF_PCBCLEARING; inp->inp_gencnt = ++ipi->ipi_gencnt; if (inp->in6p_options) m_freem(inp->in6p_options); ip6_freepcbopts(inp->in6p_outputopts); if (inp->in6p_route.ro_rt) { rtfree(inp->in6p_route.ro_rt); inp->in6p_route.ro_rt = NULL; } /* Check and free IPv4 related resources in case of mapped addr */ if (inp->inp_options) (void)m_free(inp->inp_options); im6o = inp->in6p_moptions; inp->in6p_moptions = NULL; if (im6o != NULL) IM6O_REMREF(im6o); imo = inp->inp_moptions; inp->inp_moptions = NULL; if (imo != NULL) IMO_REMREF(imo); } }