Skip to content

Commit 9a1f02f

Browse files
committed
Merge branch 'tcp-change-reaction-to-ICMP'
Eric Dumazet says: ==================== tcp: change reaction to ICMP messages ICMP[v6] messages received for a socket in TCP_SYN_SENT currently abort the connection attempt, in violation of standards. This series changes our stack to adhere to RFC 6069 and RFC 1122 (4.2.3.9) ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents c6e9dba + 0a8de36 commit 9a1f02f

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

net/ipv4/tcp_ipv4.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
482482
const int code = icmp_hdr(skb)->code;
483483
struct sock *sk;
484484
struct request_sock *fastopen;
485+
bool harderr = false;
485486
u32 seq, snd_una;
486487
int err;
487488
struct net *net = dev_net(skb->dev);
@@ -555,6 +556,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
555556
goto out;
556557
case ICMP_PARAMETERPROB:
557558
err = EPROTO;
559+
harderr = true;
558560
break;
559561
case ICMP_DEST_UNREACH:
560562
if (code > NR_ICMP_UNREACH)
@@ -579,6 +581,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
579581
}
580582

581583
err = icmp_err_convert[code].errno;
584+
harderr = icmp_err_convert[code].fatal;
582585
/* check if this ICMP message allows revert of backoff.
583586
* (see RFC 6069)
584587
*/
@@ -604,6 +607,9 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
604607

605608
ip_icmp_error(sk, skb, err, th->dest, info, (u8 *)th);
606609

610+
if (!harderr)
611+
break;
612+
607613
if (!sock_owned_by_user(sk)) {
608614
WRITE_ONCE(sk->sk_err, err);
609615

net/ipv4/tcp_timer.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,6 @@ void tcp_retransmit_timer(struct sock *sk)
626626
* implemented ftp to mars will work nicely. We will have to fix
627627
* the 120 second clamps though!
628628
*/
629-
icsk->icsk_backoff++;
630629

631630
out_reset_timer:
632631
/* If stream is thin, use linear timeouts. Since 'icsk_backoff' is
@@ -647,11 +646,12 @@ void tcp_retransmit_timer(struct sock *sk)
647646
tcp_rto_min(sk),
648647
TCP_RTO_MAX);
649648
} else if (sk->sk_state != TCP_SYN_SENT ||
650-
icsk->icsk_backoff >
649+
tp->total_rto >
651650
READ_ONCE(net->ipv4.sysctl_tcp_syn_linear_timeouts)) {
652651
/* Use normal (exponential) backoff unless linear timeouts are
653652
* activated.
654653
*/
654+
icsk->icsk_backoff++;
655655
icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
656656
}
657657
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,

net/ipv6/tcp_ipv6.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
381381
struct tcp_sock *tp;
382382
__u32 seq, snd_una;
383383
struct sock *sk;
384-
bool fatal;
384+
bool harderr;
385385
int err;
386386

387387
sk = __inet6_lookup_established(net, net->ipv4.tcp_death_row.hashinfo,
@@ -402,9 +402,9 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
402402
return 0;
403403
}
404404
seq = ntohl(th->seq);
405-
fatal = icmpv6_err_convert(type, code, &err);
405+
harderr = icmpv6_err_convert(type, code, &err);
406406
if (sk->sk_state == TCP_NEW_SYN_RECV) {
407-
tcp_req_err(sk, seq, fatal);
407+
tcp_req_err(sk, seq, harderr);
408408
return 0;
409409
}
410410

@@ -489,6 +489,9 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
489489

490490
ipv6_icmp_error(sk, skb, err, th->dest, ntohl(info), (u8 *)th);
491491

492+
if (!harderr)
493+
break;
494+
492495
if (!sock_owned_by_user(sk)) {
493496
WRITE_ONCE(sk->sk_err, err);
494497
sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */

0 commit comments

Comments
 (0)