* Initiate disconnect from peer. * If connection never passed embryonic stage, just drop; * else if don't need to let data drain, then can just drop anyways, * else have to begin TCP shutdown process: mark socket disconnecting, * drain unread data, state switch to reflect user close, and * send segment (e.g. FIN) to peer. Socket will be really disconnected * when peer sends FIN and acks our
| 769 | * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. |
| 770 | */ |
| 771 | static int |
| 772 | tcp_usr_disconnect(struct socket *so) |
| 773 | { |
| 774 | struct inpcb *inp; |
| 775 | struct tcpcb *tp = NULL; |
| 776 | struct epoch_tracker et; |
| 777 | int error = 0; |
| 778 | |
| 779 | TCPDEBUG0; |
| 780 | NET_EPOCH_ENTER(et); |
| 781 | inp = sotoinpcb(so); |
| 782 | KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL")); |
| 783 | INP_WLOCK(inp); |
| 784 | if (inp->inp_flags & INP_TIMEWAIT) |
| 785 | goto out; |
| 786 | if (inp->inp_flags & INP_DROPPED) { |
| 787 | error = ECONNRESET; |
| 788 | goto out; |
| 789 | } |
| 790 | tp = intotcpcb(inp); |
| 791 | TCPDEBUG1(); |
| 792 | tcp_disconnect(tp); |
| 793 | out: |
| 794 | TCPDEBUG2(PRU_DISCONNECT); |
| 795 | TCP_PROBE2(debug__user, tp, PRU_DISCONNECT); |
| 796 | INP_WUNLOCK(inp); |
| 797 | NET_EPOCH_EXIT(et); |
| 798 | return (error); |
| 799 | } |
| 800 | |
| 801 | #ifdef INET |
| 802 | /* |
nothing calls this directly
no test coverage detected