Example #1
0
/*
 * TCP attaches to socket via pru_attach(), reserving space,
 * and an internet control block.  This is likely occuring on
 * cpu0 and may have to move later when we bind/connect.
 */
static void
tcp_usr_attach(netmsg_t msg)
{
	struct socket *so = msg->base.nm_so;
	struct pru_attach_info *ai = msg->attach.nm_ai;
	int error;
	struct inpcb *inp;
	struct tcpcb *tp = 0;
	TCPDEBUG0;

	soreference(so);
	inp = so->so_pcb;
	TCPDEBUG1();
	if (inp) {
		error = EISCONN;
		goto out;
	}

	error = tcp_attach(so, ai);
	if (error)
		goto out;

	if ((so->so_options & SO_LINGER) && so->so_linger == 0)
		so->so_linger = TCP_LINGERTIME;
	tp = sototcpcb(so);
out:
	sofree(so);		/* from ref above */
	TCPDEBUG2(PRU_ATTACH);
	lwkt_replymsg(&msg->lmsg, error);
}
Example #2
0
/*
 * Attach TCP protocol to socket, allocating internet protocol control
 * block, tcp control block, bufer space, and entering LISTEN state
 * if to accept connections.
 */
static int
tcp_attach(struct socket *so, struct pru_attach_info *ai)
{
	struct tcpcb *tp;
	struct inpcb *inp;
	int error;
	int cpu;
#ifdef INET6
	int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != 0;
#endif

	if (so->so_snd.ssb_hiwat == 0 || so->so_rcv.ssb_hiwat == 0) {
		lwkt_gettoken(&so->so_rcv.ssb_token);
		error = soreserve(so, tcp_sendspace, tcp_recvspace,
				  ai->sb_rlimit);
		lwkt_reltoken(&so->so_rcv.ssb_token);
		if (error)
			return (error);
	}
	atomic_set_int(&so->so_rcv.ssb_flags, SSB_AUTOSIZE);
	atomic_set_int(&so->so_snd.ssb_flags, SSB_AUTOSIZE);
	cpu = mycpu->gd_cpuid;

	/*
	 * Set the default port for protocol processing. This will likely
	 * change when we connect.
	 */
	error = in_pcballoc(so, &tcbinfo[cpu]);
	if (error)
		return (error);
	inp = so->so_pcb;
#ifdef INET6
	if (isipv6) {
		inp->inp_vflag |= INP_IPV6;
		inp->in6p_hops = -1;	/* use kernel default */
	}
	else
#endif
	inp->inp_vflag |= INP_IPV4;
	tp = tcp_newtcpcb(inp);
	if (tp == NULL) {
		/*
		 * Make sure the socket is destroyed by the pcbdetach.
		 */
		soreference(so);
#ifdef INET6
		if (isipv6)
			in6_pcbdetach(inp);
		else
#endif
		in_pcbdetach(inp);
		sofree(so);	/* from ref above */
		return (ENOBUFS);
	}
	tp->t_state = TCPS_CLOSED;
	return (0);
}
Example #3
0
void
soabort_oncpu(struct socket *so)
{
	soreference(so);
	so_pru_abort_oncpu(so);
}
Example #4
0
/*
 * Handle the first completed incoming connection, assumed to be already
 * on the socket's so_comp queue.
 */
static void
ng_ksocket_finish_accept(priv_p priv)
{
	struct socket *const head = priv->so;
	struct socket *so;
	struct sockaddr *sa = NULL;
	struct ng_mesg *resp;
	struct ng_ksocket_accept *resp_data;
	node_p node;
	priv_p priv2;
	int len;
	int error;

	lwkt_getpooltoken(head);
	so = TAILQ_FIRST(&head->so_comp);
	if (so == NULL) {	/* Should never happen */
		lwkt_relpooltoken(head);
		return;
	}
	TAILQ_REMOVE(&head->so_comp, so, so_list);
	head->so_qlen--;
	soclrstate(so, SS_COMP);
	so->so_head = NULL;
	soreference(so);
	lwkt_relpooltoken(head);

	/* XXX KNOTE(&head->so_rcv.ssb_sel.si_note, 0); */

	soaccept(so, &sa);

	len = OFFSETOF(struct ng_ksocket_accept, addr);
	if (sa != NULL)
		len += sa->sa_len;

	NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len,
	    M_WAITOK | M_NULLOK);
	if (resp == NULL) {
		soclose(so, FNONBLOCK);
		goto out;
	}
	resp->header.flags |= NGF_RESP;
	resp->header.token = priv->response_token;

	/* Clone a ksocket node to wrap the new socket */
        error = ng_make_node_common(&ng_ksocket_typestruct, &node);
        if (error) {
		kfree(resp, M_NETGRAPH);
		soclose(so, FNONBLOCK);
		goto out;
	}

	if (ng_ksocket_constructor(node) != 0) {
		NG_NODE_UNREF(node);
		kfree(resp, M_NETGRAPH);
		soclose(so, FNONBLOCK);
		goto out;
	}

	priv2 = NG_NODE_PRIVATE(node);
	priv2->so = so;
	priv2->flags |= KSF_CLONED | KSF_EMBRYONIC;

	/*
	 * Insert the cloned node into a list of embryonic children
	 * on the parent node.  When a hook is created on the cloned
	 * node it will be removed from this list.  When the parent
	 * is destroyed it will destroy any embryonic children it has.
	 */
	LIST_INSERT_HEAD(&priv->embryos, priv2, siblings);

	so->so_upcallarg = (caddr_t)node;
	so->so_upcall = ng_ksocket_incoming;
	atomic_set_int(&priv->so->so_rcv.ssb_flags, SSB_UPCALL);
	atomic_set_int(&priv->so->so_snd.ssb_flags, SSB_UPCALL);

	/* Fill in the response data and send it or return it to the caller */
	resp_data = (struct ng_ksocket_accept *)resp->data;
	resp_data->nodeid = NG_NODE_ID(node);
	if (sa != NULL)
		bcopy(sa, &resp_data->addr, sa->sa_len);
	NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0);

out:
	if (sa != NULL)
		kfree(sa, M_SONAME);
}