* TCP attaches to socket via pru_attach(), reserving space, * and an internet control block. */
| 161 | * and an internet control block. |
| 162 | */ |
| 163 | static int |
| 164 | tcp_usr_attach(struct socket *so, int proto, struct thread *td) |
| 165 | { |
| 166 | struct inpcb *inp; |
| 167 | struct tcpcb *tp = NULL; |
| 168 | int error; |
| 169 | TCPDEBUG0; |
| 170 | |
| 171 | inp = sotoinpcb(so); |
| 172 | KASSERT(inp == NULL, ("tcp_usr_attach: inp != NULL")); |
| 173 | TCPDEBUG1(); |
| 174 | |
| 175 | if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { |
| 176 | error = soreserve(so, V_tcp_sendspace, V_tcp_recvspace); |
| 177 | if (error) |
| 178 | goto out; |
| 179 | } |
| 180 | |
| 181 | so->so_rcv.sb_flags |= SB_AUTOSIZE; |
| 182 | so->so_snd.sb_flags |= SB_AUTOSIZE; |
| 183 | error = in_pcballoc(so, &V_tcbinfo); |
| 184 | if (error) |
| 185 | goto out; |
| 186 | inp = sotoinpcb(so); |
| 187 | #ifdef INET6 |
| 188 | if (inp->inp_vflag & INP_IPV6PROTO) { |
| 189 | inp->inp_vflag |= INP_IPV6; |
| 190 | if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) |
| 191 | inp->inp_vflag |= INP_IPV4; |
| 192 | inp->in6p_hops = -1; /* use kernel default */ |
| 193 | } |
| 194 | else |
| 195 | #endif |
| 196 | inp->inp_vflag |= INP_IPV4; |
| 197 | tp = tcp_newtcpcb(inp); |
| 198 | if (tp == NULL) { |
| 199 | error = ENOBUFS; |
| 200 | in_pcbdetach(inp); |
| 201 | in_pcbfree(inp); |
| 202 | goto out; |
| 203 | } |
| 204 | tp->t_state = TCPS_CLOSED; |
| 205 | INP_WUNLOCK(inp); |
| 206 | TCPSTATES_INC(TCPS_CLOSED); |
| 207 | if ((so->so_options & SO_LINGER) && so->so_linger == 0) |
| 208 | so->so_linger = TCP_LINGERTIME; |
| 209 | out: |
| 210 | TCPDEBUG2(PRU_ATTACH); |
| 211 | TCP_PROBE2(debug__user, tp, PRU_ATTACH); |
| 212 | return (error); |
| 213 | } |
| 214 | |
| 215 | /* |
| 216 | * tcp_usr_detach is called when the socket layer loses its final reference |
nothing calls this directly
no test coverage detected