aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/tcp_input.c')
-rw-r--r--net/ipv4/tcp_input.c46
1 files changed, 46 insertions, 0 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 9cf446427cc2..6e46b4c0f28c 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4451,6 +4451,49 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th)
4451 } 4451 }
4452} 4452}
4453 4453
4454static int tcp_defer_accept_check(struct sock *sk)
4455{
4456 struct tcp_sock *tp = tcp_sk(sk);
4457
4458 if (tp->defer_tcp_accept.request) {
4459 int queued_data = tp->rcv_nxt - tp->copied_seq;
4460 int hasfin = !skb_queue_empty(&sk->sk_receive_queue) ?
4461 tcp_hdr((struct sk_buff *)
4462 sk->sk_receive_queue.prev)->fin : 0;
4463
4464 if (queued_data && hasfin)
4465 queued_data--;
4466
4467 if (queued_data &&
4468 tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) {
4469 if (sock_flag(sk, SOCK_KEEPOPEN)) {
4470 inet_csk_reset_keepalive_timer(sk,
4471 keepalive_time_when(tp));
4472 } else {
4473 inet_csk_delete_keepalive_timer(sk);
4474 }
4475
4476 inet_csk_reqsk_queue_add(
4477 tp->defer_tcp_accept.listen_sk,
4478 tp->defer_tcp_accept.request,
4479 sk);
4480
4481 tp->defer_tcp_accept.listen_sk->sk_data_ready(
4482 tp->defer_tcp_accept.listen_sk, 0);
4483
4484 sock_put(tp->defer_tcp_accept.listen_sk);
4485 sock_put(sk);
4486 tp->defer_tcp_accept.listen_sk = NULL;
4487 tp->defer_tcp_accept.request = NULL;
4488 } else if (hasfin ||
4489 tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) {
4490 tcp_reset(sk);
4491 return -1;
4492 }
4493 }
4494 return 0;
4495}
4496
4454static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) 4497static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen)
4455{ 4498{
4456 struct tcp_sock *tp = tcp_sk(sk); 4499 struct tcp_sock *tp = tcp_sk(sk);
@@ -4811,6 +4854,9 @@ step5:
4811 4854
4812 tcp_data_snd_check(sk); 4855 tcp_data_snd_check(sk);
4813 tcp_ack_snd_check(sk); 4856 tcp_ack_snd_check(sk);
4857
4858 if (tcp_defer_accept_check(sk))
4859 return -1;
4814 return 0; 4860 return 0;
4815 4861
4816csum_error: 4862csum_error: