Exemple #1
0
/*
 * Destroy a disconnected socket.  This routine is a NOP if entities
 * still have a reference on the socket:
 *
 *	so_pcb -	The protocol stack still has a reference
 *	SS_NOFDREF -	There is no longer a file pointer reference
 */
void
sofree(struct socket *so)
{
	struct socket *head;

	/*
	 * This is a bit hackish at the moment.  We need to interlock
	 * any accept queue we are on before we potentially lose the
	 * last reference to avoid races against a re-reference from
	 * someone operating on the queue.
	 */
	while ((head = so->so_head) != NULL) {
		lwkt_getpooltoken(head);
		if (so->so_head == head)
			break;
		lwkt_relpooltoken(head);
	}

	/*
	 * Arbitrage the last free.
	 */
	KKASSERT(so->so_refs > 0);
	if (atomic_fetchadd_int(&so->so_refs, -1) != 1) {
		if (head)
			lwkt_relpooltoken(head);
		return;
	}

	KKASSERT(so->so_pcb == NULL && (so->so_state & SS_NOFDREF));
	KKASSERT((so->so_state & SS_ASSERTINPROG) == 0);

	/*
	 * We're done, remove ourselves from the accept queue we are
	 * on, if we are on one.
	 */
	if (head != NULL) {
		if (so->so_state & SS_INCOMP) {
			TAILQ_REMOVE(&head->so_incomp, so, so_list);
			head->so_incqlen--;
		} else if (so->so_state & SS_COMP) {
			/*
			 * We must not decommission a socket that's
			 * on the accept(2) queue.  If we do, then
			 * accept(2) may hang after select(2) indicated
			 * that the listening socket was ready.
			 */
			lwkt_relpooltoken(head);
			return;
		} else {
			panic("sofree: not queued");
		}
		soclrstate(so, SS_INCOMP);
		so->so_head = NULL;
		lwkt_relpooltoken(head);
	}
	ssb_release(&so->so_snd, so);
	sorflush(so);
	sodealloc(so);
}
Exemple #2
0
/* FUNCTION: soshutdown()
 *
 * PARAM1: struct socket *    socket structure
 * PARAM2: int                shutdown action
 *                               0 = shutdown read half of connection
 *                               1 = shutdown write half of connection
 *                               2 = shutdown both halves of connection
 *
 * RETURNS: int               0 if successful, else error code
 */
int
soshutdown(struct socket *so, int how)
{
   how++;   /* convert 0,1,2 into 1,2,3 */
   if (how & 1)   /* caller wanted READ or BOTH */
      sorflush(so);

   if (how & 2)   /* caller wanted WRITE or BOTH */
   {
      sbflush(&so->so_snd); /* flush the socket send queue */
      so->so_req = PRU_SHUTDOWN;
      return ((*so->so_proto->pr_usrreq)(so, (struct mbuf *)0, (struct mbuf *)0));
   }

   return 0;
}
Exemple #3
0
void
sofree(struct socket * so)
{
   INET_TRACE (INETM_SOCKET|INETM_CLOSE,
    ("INET: sofree, so %lx so_pcb %lx so_state %x so_head %lx\n",
    so, so->so_pcb, so->so_state, so->so_head));

   if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
      return;
   if (so->so_head) 
   {
      if (!soqremque(so, 0) && !soqremque(so, 1))
         panic("sofree");
      so->so_head = 0;
   }
   sbrelease(&so->so_snd);
   sorflush(so);
#ifdef SAVE_SOCK_ENDPOINTS
   if (so->so_endpoint)
      _socket_free_entry (so);
#endif   /* SAVE_SOCK_ENDPOINTS */

#ifdef IP_MULTICAST
   /* multicast opts? */
   if (so->inp_moptions)
	   ip_freemoptions(so->inp_moptions);
#endif   /* IP_MULTICAST */

   /* IP_TOS opts? */
   if (so->so_optsPack)
      SOCOPT_FREE(so->so_optsPack);
	   
   qdel(&soq, so);   /* Delete the socket entry from the queue */
   
   if (so_evtmap)  
      (*so_evtmap_delete) (so);
   
   SOC_FREE(so);
}