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 <davem@davemloft.net>
This commit is contained in:
commit
9a1f02f3ef
@ -482,6 +482,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
const int code = icmp_hdr(skb)->code;
|
||||
struct sock *sk;
|
||||
struct request_sock *fastopen;
|
||||
bool harderr = false;
|
||||
u32 seq, snd_una;
|
||||
int err;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
@ -555,6 +556,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
goto out;
|
||||
case ICMP_PARAMETERPROB:
|
||||
err = EPROTO;
|
||||
harderr = true;
|
||||
break;
|
||||
case ICMP_DEST_UNREACH:
|
||||
if (code > NR_ICMP_UNREACH)
|
||||
@ -579,6 +581,7 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
}
|
||||
|
||||
err = icmp_err_convert[code].errno;
|
||||
harderr = icmp_err_convert[code].fatal;
|
||||
/* check if this ICMP message allows revert of backoff.
|
||||
* (see RFC 6069)
|
||||
*/
|
||||
@ -604,6 +607,9 @@ int tcp_v4_err(struct sk_buff *skb, u32 info)
|
||||
|
||||
ip_icmp_error(sk, skb, err, th->dest, info, (u8 *)th);
|
||||
|
||||
if (!harderr)
|
||||
break;
|
||||
|
||||
if (!sock_owned_by_user(sk)) {
|
||||
WRITE_ONCE(sk->sk_err, err);
|
||||
|
||||
|
@ -626,7 +626,6 @@ void tcp_retransmit_timer(struct sock *sk)
|
||||
* implemented ftp to mars will work nicely. We will have to fix
|
||||
* the 120 second clamps though!
|
||||
*/
|
||||
icsk->icsk_backoff++;
|
||||
|
||||
out_reset_timer:
|
||||
/* If stream is thin, use linear timeouts. Since 'icsk_backoff' is
|
||||
@ -647,11 +646,12 @@ out_reset_timer:
|
||||
tcp_rto_min(sk),
|
||||
TCP_RTO_MAX);
|
||||
} else if (sk->sk_state != TCP_SYN_SENT ||
|
||||
icsk->icsk_backoff >
|
||||
tp->total_rto >
|
||||
READ_ONCE(net->ipv4.sysctl_tcp_syn_linear_timeouts)) {
|
||||
/* Use normal (exponential) backoff unless linear timeouts are
|
||||
* activated.
|
||||
*/
|
||||
icsk->icsk_backoff++;
|
||||
icsk->icsk_rto = min(icsk->icsk_rto << 1, TCP_RTO_MAX);
|
||||
}
|
||||
inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
|
||||
|
@ -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) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user