From 0a8de364ff7a14558e9676f424283148110384d6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 14 Nov 2023 17:23:41 +0000 Subject: tcp: no longer abort SYN_SENT when receiving some ICMP Currently, non fatal ICMP messages received on behalf of SYN_SENT sockets do call tcp_ld_RTO_revert() to implement RFC 6069, but immediately call tcp_done(), thus aborting the connect() attempt. This violates RFC 1122 following requirement: 4.2.3.9 ICMP Messages ... o Destination Unreachable -- codes 0, 1, 5 Since these Unreachable messages indicate soft error conditions, TCP MUST NOT abort the connection, and it SHOULD make the information available to the application. This patch makes sure non 'fatal' ICMP[v6] messages do not abort the connection attempt. It enables RFC 6069 for SYN_SENT sockets as a result. Signed-off-by: Eric Dumazet Cc: David Morley Cc: Neal Cardwell Cc: Yuchung Cheng Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'net/ipv6') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 937a02c2e534..43deda49cc52 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -381,7 +381,7 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct tcp_sock *tp; __u32 seq, snd_una; struct sock *sk; - bool fatal; + bool harderr; int err; 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, return 0; } seq = ntohl(th->seq); - fatal = icmpv6_err_convert(type, code, &err); + harderr = icmpv6_err_convert(type, code, &err); if (sk->sk_state == TCP_NEW_SYN_RECV) { - tcp_req_err(sk, seq, fatal); + tcp_req_err(sk, seq, harderr); return 0; } @@ -489,6 +489,9 @@ static int tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ipv6_icmp_error(sk, skb, err, th->dest, ntohl(info), (u8 *)th); + if (!harderr) + break; + if (!sock_owned_by_user(sk)) { WRITE_ONCE(sk->sk_err, err); sk_error_report(sk); /* Wake people up to see the error (see connect in sock.c) */ -- cgit