diff options
author | Eric Dumazet <edumazet@google.com> | 2015-10-13 20:12:54 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-10-13 21:26:34 -0400 |
commit | 4bdc3d66147b3a623b32216a45431d0cff005f50 (patch) | |
tree | 2e3f5a76b0e11c05cd1e9e88f5ab0c5cc1efe344 /net/dccp/ipv4.c | |
parent | bbb300eb976b613a8e4e666d3af39f5ab1031d22 (diff) |
tcp/dccp: fix behavior of stale SYN_RECV request sockets
When a TCP/DCCP listener is closed, its pending SYN_RECV request sockets
become stale, meaning 3WHS can not complete.
But current behavior is wrong :
incoming packets finding such stale sockets are dropped.
We need instead to cleanup the request socket and perform another
lookup :
- Incoming ACK will give a RST answer,
- SYN rtx might find another listener if available.
- We expedite cleanup of request sockets and old listener socket.
Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r-- | net/dccp/ipv4.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index 8e99681c8189..0dcf1963b323 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c | |||
@@ -799,15 +799,10 @@ static int dccp_v4_rcv(struct sk_buff *skb) | |||
799 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 799 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
800 | } | 800 | } |
801 | 801 | ||
802 | /* Step 2: | 802 | lookup: |
803 | * Look up flow ID in table and get corresponding socket */ | ||
804 | sk = __inet_lookup_skb(&dccp_hashinfo, skb, | 803 | sk = __inet_lookup_skb(&dccp_hashinfo, skb, |
805 | dh->dccph_sport, dh->dccph_dport); | 804 | dh->dccph_sport, dh->dccph_dport); |
806 | /* | 805 | if (!sk) { |
807 | * Step 2: | ||
808 | * If no socket ... | ||
809 | */ | ||
810 | if (sk == NULL) { | ||
811 | dccp_pr_debug("failed to look up flow ID in table and " | 806 | dccp_pr_debug("failed to look up flow ID in table and " |
812 | "get corresponding socket\n"); | 807 | "get corresponding socket\n"); |
813 | goto no_dccp_socket; | 808 | goto no_dccp_socket; |
@@ -830,8 +825,12 @@ static int dccp_v4_rcv(struct sk_buff *skb) | |||
830 | struct sock *nsk = NULL; | 825 | struct sock *nsk = NULL; |
831 | 826 | ||
832 | sk = req->rsk_listener; | 827 | sk = req->rsk_listener; |
833 | if (sk->sk_state == DCCP_LISTEN) | 828 | if (likely(sk->sk_state == DCCP_LISTEN)) { |
834 | nsk = dccp_check_req(sk, skb, req); | 829 | nsk = dccp_check_req(sk, skb, req); |
830 | } else { | ||
831 | inet_csk_reqsk_queue_drop(sk, req); | ||
832 | goto lookup; | ||
833 | } | ||
835 | if (!nsk) { | 834 | if (!nsk) { |
836 | reqsk_put(req); | 835 | reqsk_put(req); |
837 | goto discard_it; | 836 | goto discard_it; |