diff options
Diffstat (limited to 'net/ipv4')
| -rw-r--r-- | net/ipv4/inet_connection_sock.c | 11 | ||||
| -rw-r--r-- | net/ipv4/netfilter/nf_nat_core.c | 3 | ||||
| -rw-r--r-- | net/ipv4/raw.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp.c | 18 | ||||
| -rw-r--r-- | net/ipv4/tcp_input.c | 45 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 12 | ||||
| -rw-r--r-- | net/ipv4/tcp_minisocks.c | 32 | ||||
| -rw-r--r-- | net/ipv4/tcp_timer.c | 5 | ||||
| -rw-r--r-- | net/ipv4/xfrm4_mode_tunnel.c | 2 |
9 files changed, 34 insertions, 96 deletions
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 828ea211ff21..ec834480abe7 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
| @@ -419,7 +419,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
| 419 | struct inet_connection_sock *icsk = inet_csk(parent); | 419 | struct inet_connection_sock *icsk = inet_csk(parent); |
| 420 | struct request_sock_queue *queue = &icsk->icsk_accept_queue; | 420 | struct request_sock_queue *queue = &icsk->icsk_accept_queue; |
| 421 | struct listen_sock *lopt = queue->listen_opt; | 421 | struct listen_sock *lopt = queue->listen_opt; |
| 422 | int thresh = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; | 422 | int max_retries = icsk->icsk_syn_retries ? : sysctl_tcp_synack_retries; |
| 423 | int thresh = max_retries; | ||
| 423 | unsigned long now = jiffies; | 424 | unsigned long now = jiffies; |
| 424 | struct request_sock **reqp, *req; | 425 | struct request_sock **reqp, *req; |
| 425 | int i, budget; | 426 | int i, budget; |
| @@ -455,6 +456,9 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
| 455 | } | 456 | } |
| 456 | } | 457 | } |
| 457 | 458 | ||
| 459 | if (queue->rskq_defer_accept) | ||
| 460 | max_retries = queue->rskq_defer_accept; | ||
| 461 | |||
| 458 | budget = 2 * (lopt->nr_table_entries / (timeout / interval)); | 462 | budget = 2 * (lopt->nr_table_entries / (timeout / interval)); |
| 459 | i = lopt->clock_hand; | 463 | i = lopt->clock_hand; |
| 460 | 464 | ||
| @@ -462,8 +466,9 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
| 462 | reqp=&lopt->syn_table[i]; | 466 | reqp=&lopt->syn_table[i]; |
| 463 | while ((req = *reqp) != NULL) { | 467 | while ((req = *reqp) != NULL) { |
| 464 | if (time_after_eq(now, req->expires)) { | 468 | if (time_after_eq(now, req->expires)) { |
| 465 | if (req->retrans < thresh && | 469 | if ((req->retrans < thresh || |
| 466 | !req->rsk_ops->rtx_syn_ack(parent, req)) { | 470 | (inet_rsk(req)->acked && req->retrans < max_retries)) |
| 471 | && !req->rsk_ops->rtx_syn_ack(parent, req)) { | ||
| 467 | unsigned long timeo; | 472 | unsigned long timeo; |
| 468 | 473 | ||
| 469 | if (req->retrans++ == 0) | 474 | if (req->retrans++ == 0) |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 04578593e100..d2a887fc8d9b 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
| @@ -556,7 +556,6 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | |||
| 556 | 556 | ||
| 557 | spin_lock_bh(&nf_nat_lock); | 557 | spin_lock_bh(&nf_nat_lock); |
| 558 | hlist_del_rcu(&nat->bysource); | 558 | hlist_del_rcu(&nat->bysource); |
| 559 | nat->ct = NULL; | ||
| 560 | spin_unlock_bh(&nf_nat_lock); | 559 | spin_unlock_bh(&nf_nat_lock); |
| 561 | } | 560 | } |
| 562 | 561 | ||
| @@ -570,8 +569,8 @@ static void nf_nat_move_storage(void *new, void *old) | |||
| 570 | return; | 569 | return; |
| 571 | 570 | ||
| 572 | spin_lock_bh(&nf_nat_lock); | 571 | spin_lock_bh(&nf_nat_lock); |
| 573 | hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); | ||
| 574 | new_nat->ct = ct; | 572 | new_nat->ct = ct; |
| 573 | hlist_replace_rcu(&old_nat->bysource, &new_nat->bysource); | ||
| 575 | spin_unlock_bh(&nf_nat_lock); | 574 | spin_unlock_bh(&nf_nat_lock); |
| 576 | } | 575 | } |
| 577 | 576 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e7e091d365ff..37a1ecd9d600 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
| @@ -934,7 +934,7 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
| 934 | srcp = inet->num; | 934 | srcp = inet->num; |
| 935 | 935 | ||
| 936 | seq_printf(seq, "%4d: %08X:%04X %08X:%04X" | 936 | seq_printf(seq, "%4d: %08X:%04X %08X:%04X" |
| 937 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d", | 937 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %d\n", |
| 938 | i, src, srcp, dest, destp, sp->sk_state, | 938 | i, src, srcp, dest, destp, sp->sk_state, |
| 939 | atomic_read(&sp->sk_wmem_alloc), | 939 | atomic_read(&sp->sk_wmem_alloc), |
| 940 | atomic_read(&sp->sk_rmem_alloc), | 940 | atomic_read(&sp->sk_rmem_alloc), |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index ab66683b8043..fc54a48fde1e 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -2112,12 +2112,15 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
| 2112 | break; | 2112 | break; |
| 2113 | 2113 | ||
| 2114 | case TCP_DEFER_ACCEPT: | 2114 | case TCP_DEFER_ACCEPT: |
| 2115 | if (val < 0) { | 2115 | icsk->icsk_accept_queue.rskq_defer_accept = 0; |
| 2116 | err = -EINVAL; | 2116 | if (val > 0) { |
| 2117 | } else { | 2117 | /* Translate value in seconds to number of |
| 2118 | if (val > MAX_TCP_ACCEPT_DEFERRED) | 2118 | * retransmits */ |
| 2119 | val = MAX_TCP_ACCEPT_DEFERRED; | 2119 | while (icsk->icsk_accept_queue.rskq_defer_accept < 32 && |
| 2120 | icsk->icsk_accept_queue.rskq_defer_accept = val; | 2120 | val > ((TCP_TIMEOUT_INIT / HZ) << |
| 2121 | icsk->icsk_accept_queue.rskq_defer_accept)) | ||
| 2122 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
| 2123 | icsk->icsk_accept_queue.rskq_defer_accept++; | ||
| 2121 | } | 2124 | } |
| 2122 | break; | 2125 | break; |
| 2123 | 2126 | ||
| @@ -2299,7 +2302,8 @@ static int do_tcp_getsockopt(struct sock *sk, int level, | |||
| 2299 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; | 2302 | val = (val ? : sysctl_tcp_fin_timeout) / HZ; |
| 2300 | break; | 2303 | break; |
| 2301 | case TCP_DEFER_ACCEPT: | 2304 | case TCP_DEFER_ACCEPT: |
| 2302 | val = icsk->icsk_accept_queue.rskq_defer_accept; | 2305 | val = !icsk->icsk_accept_queue.rskq_defer_accept ? 0 : |
| 2306 | ((TCP_TIMEOUT_INIT / HZ) << (icsk->icsk_accept_queue.rskq_defer_accept - 1)); | ||
| 2303 | break; | 2307 | break; |
| 2304 | case TCP_WINDOW_CLAMP: | 2308 | case TCP_WINDOW_CLAMP: |
| 2305 | val = tp->window_clamp; | 2309 | val = tp->window_clamp; |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index eba873e9b560..cad73b7dfef0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -4541,49 +4541,6 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, struct tcphdr *th) | |||
| 4541 | } | 4541 | } |
| 4542 | } | 4542 | } |
| 4543 | 4543 | ||
| 4544 | static int tcp_defer_accept_check(struct sock *sk) | ||
| 4545 | { | ||
| 4546 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 4547 | |||
| 4548 | if (tp->defer_tcp_accept.request) { | ||
| 4549 | int queued_data = tp->rcv_nxt - tp->copied_seq; | ||
| 4550 | int hasfin = !skb_queue_empty(&sk->sk_receive_queue) ? | ||
| 4551 | tcp_hdr((struct sk_buff *) | ||
| 4552 | sk->sk_receive_queue.prev)->fin : 0; | ||
| 4553 | |||
| 4554 | if (queued_data && hasfin) | ||
| 4555 | queued_data--; | ||
| 4556 | |||
| 4557 | if (queued_data && | ||
| 4558 | tp->defer_tcp_accept.listen_sk->sk_state == TCP_LISTEN) { | ||
| 4559 | if (sock_flag(sk, SOCK_KEEPOPEN)) { | ||
| 4560 | inet_csk_reset_keepalive_timer(sk, | ||
| 4561 | keepalive_time_when(tp)); | ||
| 4562 | } else { | ||
| 4563 | inet_csk_delete_keepalive_timer(sk); | ||
| 4564 | } | ||
| 4565 | |||
| 4566 | inet_csk_reqsk_queue_add( | ||
| 4567 | tp->defer_tcp_accept.listen_sk, | ||
| 4568 | tp->defer_tcp_accept.request, | ||
| 4569 | sk); | ||
| 4570 | |||
| 4571 | tp->defer_tcp_accept.listen_sk->sk_data_ready( | ||
| 4572 | tp->defer_tcp_accept.listen_sk, 0); | ||
| 4573 | |||
| 4574 | sock_put(tp->defer_tcp_accept.listen_sk); | ||
| 4575 | sock_put(sk); | ||
| 4576 | tp->defer_tcp_accept.listen_sk = NULL; | ||
| 4577 | tp->defer_tcp_accept.request = NULL; | ||
| 4578 | } else if (hasfin || | ||
| 4579 | tp->defer_tcp_accept.listen_sk->sk_state != TCP_LISTEN) { | ||
| 4580 | tcp_reset(sk); | ||
| 4581 | return -1; | ||
| 4582 | } | ||
| 4583 | } | ||
| 4584 | return 0; | ||
| 4585 | } | ||
| 4586 | |||
| 4587 | static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) | 4544 | static int tcp_copy_to_iovec(struct sock *sk, struct sk_buff *skb, int hlen) |
| 4588 | { | 4545 | { |
| 4589 | struct tcp_sock *tp = tcp_sk(sk); | 4546 | struct tcp_sock *tp = tcp_sk(sk); |
| @@ -4944,8 +4901,6 @@ step5: | |||
| 4944 | 4901 | ||
| 4945 | tcp_data_snd_check(sk); | 4902 | tcp_data_snd_check(sk); |
| 4946 | tcp_ack_snd_check(sk); | 4903 | tcp_ack_snd_check(sk); |
| 4947 | |||
| 4948 | tcp_defer_accept_check(sk); | ||
| 4949 | return 0; | 4904 | return 0; |
| 4950 | 4905 | ||
| 4951 | csum_error: | 4906 | csum_error: |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 4f8485c67d1a..12695be2c255 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -85,10 +85,6 @@ | |||
| 85 | int sysctl_tcp_tw_reuse __read_mostly; | 85 | int sysctl_tcp_tw_reuse __read_mostly; |
| 86 | int sysctl_tcp_low_latency __read_mostly; | 86 | int sysctl_tcp_low_latency __read_mostly; |
| 87 | 87 | ||
| 88 | /* Check TCP sequence numbers in ICMP packets. */ | ||
| 89 | #define ICMP_MIN_LENGTH 8 | ||
| 90 | |||
| 91 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb); | ||
| 92 | 88 | ||
| 93 | #ifdef CONFIG_TCP_MD5SIG | 89 | #ifdef CONFIG_TCP_MD5SIG |
| 94 | static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, | 90 | static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, |
| @@ -1918,14 +1914,6 @@ int tcp_v4_destroy_sock(struct sock *sk) | |||
| 1918 | sk->sk_sndmsg_page = NULL; | 1914 | sk->sk_sndmsg_page = NULL; |
| 1919 | } | 1915 | } |
| 1920 | 1916 | ||
| 1921 | if (tp->defer_tcp_accept.request) { | ||
| 1922 | reqsk_free(tp->defer_tcp_accept.request); | ||
| 1923 | sock_put(tp->defer_tcp_accept.listen_sk); | ||
| 1924 | sock_put(sk); | ||
| 1925 | tp->defer_tcp_accept.listen_sk = NULL; | ||
| 1926 | tp->defer_tcp_accept.request = NULL; | ||
| 1927 | } | ||
| 1928 | |||
| 1929 | atomic_dec(&tcp_sockets_allocated); | 1917 | atomic_dec(&tcp_sockets_allocated); |
| 1930 | 1918 | ||
| 1931 | return 0; | 1919 | return 0; |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 019c8c16e5cc..8245247a6ceb 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
| @@ -571,8 +571,10 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
| 571 | does sequence test, SYN is truncated, and thus we consider | 571 | does sequence test, SYN is truncated, and thus we consider |
| 572 | it a bare ACK. | 572 | it a bare ACK. |
| 573 | 573 | ||
| 574 | Both ends (listening sockets) accept the new incoming | 574 | If icsk->icsk_accept_queue.rskq_defer_accept, we silently drop this |
| 575 | connection and try to talk to each other. 8-) | 575 | bare ACK. Otherwise, we create an established connection. Both |
| 576 | ends (listening sockets) accept the new incoming connection and try | ||
| 577 | to talk to each other. 8-) | ||
| 576 | 578 | ||
| 577 | Note: This case is both harmless, and rare. Possibility is about the | 579 | Note: This case is both harmless, and rare. Possibility is about the |
| 578 | same as us discovering intelligent life on another plant tomorrow. | 580 | same as us discovering intelligent life on another plant tomorrow. |
| @@ -640,6 +642,13 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
| 640 | if (!(flg & TCP_FLAG_ACK)) | 642 | if (!(flg & TCP_FLAG_ACK)) |
| 641 | return NULL; | 643 | return NULL; |
| 642 | 644 | ||
| 645 | /* If TCP_DEFER_ACCEPT is set, drop bare ACK. */ | ||
| 646 | if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | ||
| 647 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | ||
| 648 | inet_rsk(req)->acked = 1; | ||
| 649 | return NULL; | ||
| 650 | } | ||
| 651 | |||
| 643 | /* OK, ACK is valid, create big socket and | 652 | /* OK, ACK is valid, create big socket and |
| 644 | * feed this segment to it. It will repeat all | 653 | * feed this segment to it. It will repeat all |
| 645 | * the tests. THIS SEGMENT MUST MOVE SOCKET TO | 654 | * the tests. THIS SEGMENT MUST MOVE SOCKET TO |
| @@ -678,24 +687,7 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, | |||
| 678 | inet_csk_reqsk_queue_unlink(sk, req, prev); | 687 | inet_csk_reqsk_queue_unlink(sk, req, prev); |
| 679 | inet_csk_reqsk_queue_removed(sk, req); | 688 | inet_csk_reqsk_queue_removed(sk, req); |
| 680 | 689 | ||
| 681 | if (inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | 690 | inet_csk_reqsk_queue_add(sk, req, child); |
| 682 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | ||
| 683 | |||
| 684 | /* the accept queue handling is done is est recv slow | ||
| 685 | * path so lets make sure to start there | ||
| 686 | */ | ||
| 687 | tcp_sk(child)->pred_flags = 0; | ||
| 688 | sock_hold(sk); | ||
| 689 | sock_hold(child); | ||
| 690 | tcp_sk(child)->defer_tcp_accept.listen_sk = sk; | ||
| 691 | tcp_sk(child)->defer_tcp_accept.request = req; | ||
| 692 | |||
| 693 | inet_csk_reset_keepalive_timer(child, | ||
| 694 | inet_csk(sk)->icsk_accept_queue.rskq_defer_accept * HZ); | ||
| 695 | } else { | ||
| 696 | inet_csk_reqsk_queue_add(sk, req, child); | ||
| 697 | } | ||
| 698 | |||
| 699 | return child; | 691 | return child; |
| 700 | 692 | ||
| 701 | listen_overflow: | 693 | listen_overflow: |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 4de68cf5f2aa..63ed9d6830e7 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
| @@ -489,11 +489,6 @@ static void tcp_keepalive_timer (unsigned long data) | |||
| 489 | goto death; | 489 | goto death; |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | if (tp->defer_tcp_accept.request && sk->sk_state == TCP_ESTABLISHED) { | ||
| 493 | tcp_send_active_reset(sk, GFP_ATOMIC); | ||
| 494 | goto death; | ||
| 495 | } | ||
| 496 | |||
| 497 | if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) | 492 | if (!sock_flag(sk, SOCK_KEEPOPEN) || sk->sk_state == TCP_CLOSE) |
| 498 | goto out; | 493 | goto out; |
| 499 | 494 | ||
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 584e6d74e3a9..7135279f3f84 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c | |||
| @@ -52,7 +52,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 52 | IP_ECN_clear(top_iph); | 52 | IP_ECN_clear(top_iph); |
| 53 | 53 | ||
| 54 | top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? | 54 | top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? |
| 55 | 0 : XFRM_MODE_SKB_CB(skb)->frag_off; | 55 | 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); |
| 56 | ip_select_ident(top_iph, dst->child, NULL); | 56 | ip_select_ident(top_iph, dst->child, NULL); |
| 57 | 57 | ||
| 58 | top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); | 58 | top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); |
