/* * 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); }
/* * 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); }
void soabort_oncpu(struct socket *so) { soreference(so); so_pru_abort_oncpu(so); }
/* * 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); }