aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
authorWei Wang <weiwan@google.com>2016-02-17 13:58:22 -0800
committerDavid S. Miller <davem@davemloft.net>2016-02-19 15:46:24 -0500
commite0d8c1b7381133240f0c69eaf740f64975b6058e (patch)
treee4db7477d4deaf5a5b922ddeb89f6327fe7d8483 /net/ipv6/udp.c
parentbe2net: Fix pcie error recovery in case of NIC+RoCE adapters (diff)
downloadlinux-dev-e0d8c1b7381133240f0c69eaf740f64975b6058e.tar.xz
linux-dev-e0d8c1b7381133240f0c69eaf740f64975b6058e.zip
ipv6: pass up EMSGSIZE msg for UDP socket in Ipv6
In ipv4, when the machine receives a ICMP_FRAG_NEEDED message, the connected UDP socket will get EMSGSIZE message on its next read from the socket. However, this is not the case for ipv6. This fix modifies the udp err handler in Ipv6 for ICMP6_PKT_TOOBIG to make it similar to ipv4 behavior. That is when the machine gets an ICMP6_PKT_TOOBIG message, the connected UDP socket will get EMSGSIZE message on its next read from the socket. Signed-off-by: Wei Wang <weiwan@google.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index ac4e7e03dded..0711f8fe4d44 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -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);