Skip to content

Commit 4bdc3d6

Browse files
edumazetdavem330
authored andcommitted
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: 079096f ("tcp/dccp: install syn_recv requests into ehash table") Signed-off-by: Eric Dumazet <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bbb300e commit 4bdc3d6

File tree

4 files changed

+26
-18
lines changed

4 files changed

+26
-18
lines changed

net/dccp/ipv4.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -799,15 +799,10 @@ static int dccp_v4_rcv(struct sk_buff *skb)
799799
DCCP_SKB_CB(skb)->dccpd_ack_seq);
800800
}
801801

802-
/* Step 2:
803-
* Look up flow ID in table and get corresponding socket */
802+
lookup:
804803
sk = __inet_lookup_skb(&dccp_hashinfo, skb,
805804
dh->dccph_sport, dh->dccph_dport);
806-
/*
807-
* Step 2:
808-
* If no socket ...
809-
*/
810-
if (sk == NULL) {
805+
if (!sk) {
811806
dccp_pr_debug("failed to look up flow ID in table and "
812807
"get corresponding socket\n");
813808
goto no_dccp_socket;
@@ -830,8 +825,12 @@ static int dccp_v4_rcv(struct sk_buff *skb)
830825
struct sock *nsk = NULL;
831826

832827
sk = req->rsk_listener;
833-
if (sk->sk_state == DCCP_LISTEN)
828+
if (likely(sk->sk_state == DCCP_LISTEN)) {
834829
nsk = dccp_check_req(sk, skb, req);
830+
} else {
831+
inet_csk_reqsk_queue_drop(sk, req);
832+
goto lookup;
833+
}
835834
if (!nsk) {
836835
reqsk_put(req);
837836
goto discard_it;

net/dccp/ipv6.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -656,16 +656,11 @@ static int dccp_v6_rcv(struct sk_buff *skb)
656656
else
657657
DCCP_SKB_CB(skb)->dccpd_ack_seq = dccp_hdr_ack_seq(skb);
658658

659-
/* Step 2:
660-
* Look up flow ID in table and get corresponding socket */
659+
lookup:
661660
sk = __inet6_lookup_skb(&dccp_hashinfo, skb,
662661
dh->dccph_sport, dh->dccph_dport,
663662
inet6_iif(skb));
664-
/*
665-
* Step 2:
666-
* If no socket ...
667-
*/
668-
if (sk == NULL) {
663+
if (!sk) {
669664
dccp_pr_debug("failed to look up flow ID in table and "
670665
"get corresponding socket\n");
671666
goto no_dccp_socket;
@@ -688,8 +683,12 @@ static int dccp_v6_rcv(struct sk_buff *skb)
688683
struct sock *nsk = NULL;
689684

690685
sk = req->rsk_listener;
691-
if (sk->sk_state == DCCP_LISTEN)
686+
if (likely(sk->sk_state == DCCP_LISTEN)) {
692687
nsk = dccp_check_req(sk, skb, req);
688+
} else {
689+
inet_csk_reqsk_queue_drop(sk, req);
690+
goto lookup;
691+
}
693692
if (!nsk) {
694693
reqsk_put(req);
695694
goto discard_it;

net/ipv4/tcp_ipv4.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
15721572
TCP_SKB_CB(skb)->ip_dsfield = ipv4_get_dsfield(iph);
15731573
TCP_SKB_CB(skb)->sacked = 0;
15741574

1575+
lookup:
15751576
sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
15761577
if (!sk)
15771578
goto no_tcp_socket;
@@ -1587,8 +1588,12 @@ int tcp_v4_rcv(struct sk_buff *skb)
15871588
sk = req->rsk_listener;
15881589
if (tcp_v4_inbound_md5_hash(sk, skb))
15891590
goto discard_and_relse;
1590-
if (sk->sk_state == TCP_LISTEN)
1591+
if (likely(sk->sk_state == TCP_LISTEN)) {
15911592
nsk = tcp_check_req(sk, skb, req, false);
1593+
} else {
1594+
inet_csk_reqsk_queue_drop(sk, req);
1595+
goto lookup;
1596+
}
15921597
if (!nsk) {
15931598
reqsk_put(req);
15941599
goto discard_it;

net/ipv6/tcp_ipv6.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,7 @@ static int tcp_v6_rcv(struct sk_buff *skb)
13631363
th = tcp_hdr(skb);
13641364
hdr = ipv6_hdr(skb);
13651365

1366+
lookup:
13661367
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
13671368
inet6_iif(skb));
13681369
if (!sk)
@@ -1382,8 +1383,12 @@ static int tcp_v6_rcv(struct sk_buff *skb)
13821383
reqsk_put(req);
13831384
goto discard_it;
13841385
}
1385-
if (sk->sk_state == TCP_LISTEN)
1386+
if (likely(sk->sk_state == TCP_LISTEN)) {
13861387
nsk = tcp_check_req(sk, skb, req, false);
1388+
} else {
1389+
inet_csk_reqsk_queue_drop(sk, req);
1390+
goto lookup;
1391+
}
13871392
if (!nsk) {
13881393
reqsk_put(req);
13891394
goto discard_it;

0 commit comments

Comments
 (0)