diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-04-02 16:42:51 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-04-02 16:42:51 +0000 |
commit | cce79b77fe6cf41d33a3e78b9094492e51e42513 (patch) | |
tree | ce7ccb5a61bc221536d7be8afa6dd74597aee1f4 /sys/netinet/tcp_usrreq.c | |
parent | b93d36449d6fde60fa737733dba9c068e761cfa4 (diff) | |
download | FreeBSD-src-cce79b77fe6cf41d33a3e78b9094492e51e42513.zip FreeBSD-src-cce79b77fe6cf41d33a3e78b9094492e51e42513.tar.gz |
During reformulation of tcp_usr_detach(), the call to initiate TCP
disconnect for fully connected sockets was dropped, meaning that if
the socket was closed while the connection was alive, it would be
leaked. Structure tcp_usr_detach() so that there are two clear
parts: initiating disconnect, and reclaiming state, and reintroduce
the tcp_disconnect() call in the first part.
MFC after: 3 months
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 29c0da8..daec08e 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -161,10 +161,24 @@ tcp_usr_detach(struct socket *so) INP_LOCK(inp); KASSERT(inp->inp_socket != NULL, ("tcp_usr_detach: inp_socket == NULL")); - TCPDEBUG1(); - tp = intotcpcb(inp); + /* + * First, if we still have full TCP state, and we're not dropped, + * initiate a disconnect. + */ + if (!(inp->inp_vflag & INP_TIMEWAIT) && + !(inp->inp_vflag & INP_DROPPED)) { + tp = intotcpcb(inp); + tcp_disconnect(tp); + } + + /* + * Second, release any protocol state that we can reasonably release. + * Note that the call to tcp_disconnect() may actually have changed + * the TCP state, so we have to re-evaluate INP_TIMEWAIT and + * INP_DROPPED. + */ if (inp->inp_vflag & INP_TIMEWAIT) { if (inp->inp_vflag & INP_DROPPED) { /* @@ -225,10 +239,6 @@ tcp_usr_detach(struct socket *so) } #endif } else { - /* - * Connection state still required, as is socket, so - * mark socket for TCP to free later. - */ SOCK_LOCK(so); so->so_state |= SS_PROTOREF; SOCK_UNLOCK(so); @@ -1450,7 +1460,8 @@ tcp_disconnect(tp) soisdisconnecting(so); sbflush(&so->so_rcv); tcp_usrclosed(tp); - tcp_output(tp); + if (!(inp->inp_vflag & INP_DROPPED)) + tcp_output(tp); } } |