|
@@ -548,6 +548,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|
|
const struct in6_addr *daddr = &hdr->daddr;
|
|
|
struct udphdr *uh = (struct udphdr *)(skb->data+offset);
|
|
|
struct sock *sk;
|
|
|
+ int harderr;
|
|
|
int err;
|
|
|
struct net *net = dev_net(skb->dev);
|
|
|
|
|
@@ -559,26 +560,27 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ harderr = icmpv6_err_convert(type, code, &err);
|
|
|
+ np = inet6_sk(sk);
|
|
|
+
|
|
|
if (type == ICMPV6_PKT_TOOBIG) {
|
|
|
if (!ip6_sk_accept_pmtu(sk))
|
|
|
goto out;
|
|
|
ip6_sk_update_pmtu(skb, sk, info);
|
|
|
+ if (np->pmtudisc != IPV6_PMTUDISC_DONT)
|
|
|
+ harderr = 1;
|
|
|
}
|
|
|
if (type == NDISC_REDIRECT) {
|
|
|
ip6_sk_redirect(skb, sk);
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- np = inet6_sk(sk);
|
|
|
-
|
|
|
- if (!icmpv6_err_convert(type, code, &err) && !np->recverr)
|
|
|
- goto out;
|
|
|
-
|
|
|
- if (sk->sk_state != TCP_ESTABLISHED && !np->recverr)
|
|
|
- goto out;
|
|
|
-
|
|
|
- if (np->recverr)
|
|
|
+ if (!np->recverr) {
|
|
|
+ if (!harderr || sk->sk_state != TCP_ESTABLISHED)
|
|
|
+ goto out;
|
|
|
+ } else {
|
|
|
ipv6_icmp_error(sk, skb, err, uh->dest, ntohl(info), (u8 *)(uh+1));
|
|
|
+ }
|
|
|
|
|
|
sk->sk_err = err;
|
|
|
sk->sk_error_report(sk);
|