diff options
author | Eric Dumazet <edumazet@google.com> | 2022-06-27 15:10:38 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2022-06-29 07:26:56 +0300 |
commit | af9784d007d8382e71fb841c06ab5ef6aa2540fc (patch) | |
tree | d009369882a53d0882a5b08bba87a6b8081fadb8 /net/ipv4/tcp.c | |
parent | f03c8a1e33ce5f28851b8077a5a417a2d0600c2f (diff) | |
download | linux-af9784d007d8382e71fb841c06ab5ef6aa2540fc.tar.xz |
tcp: diag: add support for TIME_WAIT sockets to tcp_abort()
Currently, "ss -K -ta ..." does not support TIME_WAIT sockets.
Issue has been raised at least two times in the past [1] [2]
it is time to fix it.
[1] https://lore.kernel.org/netdev/ba65f579-4e69-ae0d-4770-bc6234beb428@gmail.com/
[2] https://lore.kernel.org/netdev/CANn89i+R9RgmD=AQ4vX1Vb_SQAj4c3fi7-ZtQz-inYY4Sq4CMQ@mail.gmail.com/T/
While we are at it, use inet_sk_state_load() while tcp_abort()
does not hold a lock on the socket.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Tested-by: Muhammad Usama Anjum <usama.anjum@collabora.com>
Link: https://lore.kernel.org/r/20220627121038.226500-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index f7309452bdce..d2ca56aa18eb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -4531,16 +4531,24 @@ EXPORT_SYMBOL_GPL(tcp_done); int tcp_abort(struct sock *sk, int err) { - if (!sk_fullsock(sk)) { - if (sk->sk_state == TCP_NEW_SYN_RECV) { - struct request_sock *req = inet_reqsk(sk); + int state = inet_sk_state_load(sk); - local_bh_disable(); - inet_csk_reqsk_queue_drop(req->rsk_listener, req); - local_bh_enable(); - return 0; - } - return -EOPNOTSUPP; + if (state == TCP_NEW_SYN_RECV) { + struct request_sock *req = inet_reqsk(sk); + + local_bh_disable(); + inet_csk_reqsk_queue_drop(req->rsk_listener, req); + local_bh_enable(); + return 0; + } + if (state == TCP_TIME_WAIT) { + struct inet_timewait_sock *tw = inet_twsk(sk); + + refcount_inc(&tw->tw_refcnt); + local_bh_disable(); + inet_twsk_deschedule_put(tw); + local_bh_enable(); + return 0; } /* Don't race with userspace socket closes such as tcp_close. */ |