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);
                goto out;
        case ICMP_PARAMETERPROB:
                err = EPROTO;
+               harderr = true;
                break;
        case ICMP_DEST_UNREACH:
                if (code > NR_ICMP_UNREACH)
                }
 
                err = icmp_err_convert[code].errno;
+               harderr = icmp_err_convert[code].fatal;
                /* check if this ICMP message allows revert of backoff.
                 * (see RFC 6069)
                 */
 
                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);
 
 
        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,
                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;
        }
 
 
                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) */