aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/inet_connection_sock.h1
-rw-r--r--net/dccp/ipv4.c4
-rw-r--r--net/dccp/ipv6.c3
-rw-r--r--net/ipv4/inet_connection_sock.c16
-rw-r--r--net/ipv4/tcp_ipv4.c6
-rw-r--r--net/ipv6/tcp_ipv6.c3
6 files changed, 25 insertions, 8 deletions
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index ba1d3615acbb..183292722f6e 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -318,6 +318,7 @@ extern void inet_csk_reqsk_queue_prune(struct sock *parent,
318 const unsigned long max_rto); 318 const unsigned long max_rto);
319 319
320extern void inet_csk_destroy_sock(struct sock *sk); 320extern void inet_csk_destroy_sock(struct sock *sk);
321extern void inet_csk_prepare_forced_close(struct sock *sk);
321 322
322/* 323/*
323 * LISTEN is a special case for poll.. 324 * LISTEN is a special case for poll..
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index 176ecdba4a22..4f9f5eb478f1 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -439,8 +439,8 @@ exit:
439 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 439 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
440 return NULL; 440 return NULL;
441put_and_exit: 441put_and_exit:
442 bh_unlock_sock(newsk); 442 inet_csk_prepare_forced_close(newsk);
443 sock_put(newsk); 443 dccp_done(newsk);
444 goto exit; 444 goto exit;
445} 445}
446 446
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 56840b249f3b..6e05981f271e 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -585,7 +585,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
585 newinet->inet_rcv_saddr = LOOPBACK4_IPV6; 585 newinet->inet_rcv_saddr = LOOPBACK4_IPV6;
586 586
587 if (__inet_inherit_port(sk, newsk) < 0) { 587 if (__inet_inherit_port(sk, newsk) < 0) {
588 sock_put(newsk); 588 inet_csk_prepare_forced_close(newsk);
589 dccp_done(newsk);
589 goto out; 590 goto out;
590 } 591 }
591 __inet6_hash(newsk, NULL); 592 __inet6_hash(newsk, NULL);
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 2026542d6836..d0670f00d524 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -710,6 +710,22 @@ void inet_csk_destroy_sock(struct sock *sk)
710} 710}
711EXPORT_SYMBOL(inet_csk_destroy_sock); 711EXPORT_SYMBOL(inet_csk_destroy_sock);
712 712
713/* This function allows to force a closure of a socket after the call to
714 * tcp/dccp_create_openreq_child().
715 */
716void inet_csk_prepare_forced_close(struct sock *sk)
717{
718 /* sk_clone_lock locked the socket and set refcnt to 2 */
719 bh_unlock_sock(sk);
720 sock_put(sk);
721
722 /* The below has to be done to allow calling inet_csk_destroy_sock */
723 sock_set_flag(sk, SOCK_DEAD);
724 percpu_counter_inc(sk->sk_prot->orphan_count);
725 inet_sk(sk)->inet_num = 0;
726}
727EXPORT_SYMBOL(inet_csk_prepare_forced_close);
728
713int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) 729int inet_csk_listen_start(struct sock *sk, const int nr_table_entries)
714{ 730{
715 struct inet_sock *inet = inet_sk(sk); 731 struct inet_sock *inet = inet_sk(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1ed230716d51..54139fa514e6 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1767,10 +1767,8 @@ exit:
1767 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 1767 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
1768 return NULL; 1768 return NULL;
1769put_and_exit: 1769put_and_exit:
1770 tcp_clear_xmit_timers(newsk); 1770 inet_csk_prepare_forced_close(newsk);
1771 tcp_cleanup_congestion_control(newsk); 1771 tcp_done(newsk);
1772 bh_unlock_sock(newsk);
1773 sock_put(newsk);
1774 goto exit; 1772 goto exit;
1775} 1773}
1776EXPORT_SYMBOL(tcp_v4_syn_recv_sock); 1774EXPORT_SYMBOL(tcp_v4_syn_recv_sock);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6565cf55eb1e..93825dd3a7c0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1288,7 +1288,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1288#endif 1288#endif
1289 1289
1290 if (__inet_inherit_port(sk, newsk) < 0) { 1290 if (__inet_inherit_port(sk, newsk) < 0) {
1291 sock_put(newsk); 1291 inet_csk_prepare_forced_close(newsk);
1292 tcp_done(newsk);
1292 goto out; 1293 goto out;
1293 } 1294 }
1294 __inet6_hash(newsk, NULL); 1295 __inet6_hash(newsk, NULL);