diff options
author | Lorenzo Colitti <lorenzo@google.com> | 2015-12-15 22:30:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-12-15 23:26:52 -0500 |
commit | c1e64e298b8cad309091b95d8436a0255c84f54a (patch) | |
tree | c9ddd8cb837aabafdea04d5c04b74902e5da1a21 /net/ipv4/tcp.c | |
parent | 6eb5d2e08f071c05ecbe135369c9ad418826cab2 (diff) |
net: diag: Support destroying TCP sockets.
This implements SOCK_DESTROY for TCP sockets. It causes all
blocking calls on the socket to fail fast with ECONNABORTED and
causes a protocol close of the socket. It informs the other end
of the connection by sending a RST, i.e., initiating a TCP ABORT
as per RFC 793. ECONNABORTED was chosen for consistency with
FreeBSD.
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r-- | net/ipv4/tcp.c | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 92b3e61b847d..2c0e340518d2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -3080,6 +3080,38 @@ void tcp_done(struct sock *sk) | |||
3080 | } | 3080 | } |
3081 | EXPORT_SYMBOL_GPL(tcp_done); | 3081 | EXPORT_SYMBOL_GPL(tcp_done); |
3082 | 3082 | ||
3083 | int tcp_abort(struct sock *sk, int err) | ||
3084 | { | ||
3085 | if (!sk_fullsock(sk)) { | ||
3086 | sock_gen_put(sk); | ||
3087 | return -EOPNOTSUPP; | ||
3088 | } | ||
3089 | |||
3090 | /* Don't race with userspace socket closes such as tcp_close. */ | ||
3091 | lock_sock(sk); | ||
3092 | |||
3093 | /* Don't race with BH socket closes such as inet_csk_listen_stop. */ | ||
3094 | local_bh_disable(); | ||
3095 | bh_lock_sock(sk); | ||
3096 | |||
3097 | if (!sock_flag(sk, SOCK_DEAD)) { | ||
3098 | sk->sk_err = err; | ||
3099 | /* This barrier is coupled with smp_rmb() in tcp_poll() */ | ||
3100 | smp_wmb(); | ||
3101 | sk->sk_error_report(sk); | ||
3102 | if (tcp_need_reset(sk->sk_state)) | ||
3103 | tcp_send_active_reset(sk, GFP_ATOMIC); | ||
3104 | tcp_done(sk); | ||
3105 | } | ||
3106 | |||
3107 | bh_unlock_sock(sk); | ||
3108 | local_bh_enable(); | ||
3109 | release_sock(sk); | ||
3110 | sock_put(sk); | ||
3111 | return 0; | ||
3112 | } | ||
3113 | EXPORT_SYMBOL_GPL(tcp_abort); | ||
3114 | |||
3083 | extern struct tcp_congestion_ops tcp_reno; | 3115 | extern struct tcp_congestion_ops tcp_reno; |
3084 | 3116 | ||
3085 | static __initdata unsigned long thash_entries; | 3117 | static __initdata unsigned long thash_entries; |