From patchwork Mon Mar 14 20:59:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wei Wang X-Patchwork-Id: 597257 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3qP9BL2H1Gz9s6n for ; Tue, 15 Mar 2016 08:00:26 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b=i8Kpd5ur; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933493AbcCNVAY (ORCPT ); Mon, 14 Mar 2016 17:00:24 -0400 Received: from mail-pa0-f45.google.com ([209.85.220.45]:35135 "EHLO mail-pa0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933307AbcCNVAW (ORCPT ); Mon, 14 Mar 2016 17:00:22 -0400 Received: by mail-pa0-f45.google.com with SMTP id td3so137624768pab.2 for ; Mon, 14 Mar 2016 14:00:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=3G4GN8qW498jHr+T87UVSwTMXwXsf43u1s1ncQBpakg=; b=i8Kpd5uro3kJMOegln0axXuBPraIDLdbD0m+88YhWoeS9wzWmvn1/gDIZzECrrjy5M Q9PHLox8jGBU47MBgEeItscQgwad52OxaXqUY3U2grTKaUEJCWWSnoWTU/KqRNIgVfpw F5zylKW8Ndp/bals88iiQlblnWp755fD9IHPirzKY3gGAACk0zBifiaX0sKXZMam1CY3 4FG58JWUTpCZn/tmubOqSzY5gqfvTRUV2vvpe6MikkxV0ETbpJZC6E+R6SKzDAOVmBzP lsIeMS9mgiU2dYkGFoFq6PxKYQjzSGX8Uh0GGHjU6JlSAAzUm4dHYQOpW9PYr09NajRq XZ9A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=3G4GN8qW498jHr+T87UVSwTMXwXsf43u1s1ncQBpakg=; b=Ww7A2MHMeRdppDUHzbRNx2lCg4kq0TsDxwdHwyx9e9v7kBvQ5IuXNfijtYsyVZ2pN0 AYQHunTVSNUY4GyLg/0TE/tUSLKYs17h3RCBBVjx0r6jsr2gwn682FA/LmqKcmgO8pxK lz7KSCAfxFWw6wlKSK2heZyDi2A1Q/XhSaFWoSOsQ0WI46h3cVISM1cfkEyv28LE3L19 YeFr7WsvXc55XGh/bYVVC/Q4d09O/DGhix5vJrCwcPeo5ddTCLp0Z8iy6Hgx0B/Ns/aj bdAN7TmdI0V+6kd7RMystI/zaEfNQsVH+uc//Z59DbVxwcpgS1mS1RpE9zVpxKyuHeuY UXaQ== X-Gm-Message-State: AD7BkJIwqVWI5V6BFNzEzuSi8pB5jTiKP6fn+wHVDewtvtcEO75gEP/8vUYuTX3fY5y6uEMd X-Received: by 10.66.66.198 with SMTP id h6mr40335641pat.112.1457989220801; Mon, 14 Mar 2016 14:00:20 -0700 (PDT) Received: from localhost ([2620:0:1000:3002:2867:4449:c0f5:e33e]) by smtp.gmail.com with ESMTPSA id fw9sm19628522pac.21.2016.03.14.14.00.20 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 14 Mar 2016 14:00:20 -0700 (PDT) From: Wei Wang X-Google-Original-From: Wei Wang To: "David S . Miller" Cc: Eric Dumazet , netdev@vger.kernel.org, Wei Wang Subject: [PATCH] ipv6: Fix the pmtu path for connected UDP socket Date: Mon, 14 Mar 2016 13:59:47 -0700 Message-Id: <1457989187-92851-1-git-send-email-tracywwnj@gmail.com> X-Mailer: git-send-email 2.7.0.rc3.207.g0ac5344 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Wei Wang When ICMPV6_PKT_TOOBIG message is received by a connected UDP socket, the new mtu value is not properly updated in the dst_entry associated with the socket. This leads to the issue that the mtu value returned by getsockopt(sockfd, IPPROTO_IPV6, IPV6_MTU, ...) is wrong. The fix is to update sk->sk_dst_cache and other corresponding fields when a new routing cache is allocated for the new pmtu in UDP connected socket case. Signed-off-by: Wei Wang --- include/net/ip6_route.h | 4 ++-- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/icmp.c | 2 +- net/ipv6/ip6_vti.c | 2 +- net/ipv6/ipcomp6.c | 2 +- net/ipv6/route.c | 21 +++++++++------------ 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 295d291..2b147a8 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -115,8 +115,8 @@ void rt6_purge_dflt_routers(struct net *net); int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, const struct in6_addr *gwaddr); -void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, int oif, - u32 mark); +void ip6_update_pmtu(struct net *net, struct sock *sk, struct sk_buff *skb, + __be32 mtu, int oif, u32 mark); void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu); void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 0630a4d5..2c926ec 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -664,7 +664,7 @@ static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type == NDISC_REDIRECT) ip6_redirect(skb, net, skb->dev->ifindex, 0); else - ip6_update_pmtu(skb, net, info, 0, 0); + ip6_update_pmtu(net, NULL, skb, info, 0, 0); xfrm_state_put(x); return 0; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 060a60b..b74847a 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -476,7 +476,7 @@ static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type == NDISC_REDIRECT) ip6_redirect(skb, net, skb->dev->ifindex, 0); else - ip6_update_pmtu(skb, net, info, 0, 0); + ip6_update_pmtu(net, NULL, skb, info, 0, 0); xfrm_state_put(x); return 0; diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 0a37ddc..03816f5 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -92,7 +92,7 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct net *net = dev_net(skb->dev); if (type == ICMPV6_PKT_TOOBIG) - ip6_update_pmtu(skb, net, info, 0, 0); + ip6_update_pmtu(net, NULL, skb, info, 0, 0); else if (type == NDISC_REDIRECT) ip6_redirect(skb, net, skb->dev->ifindex, 0); diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index d90a11f..fa873ca 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -599,7 +599,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type == NDISC_REDIRECT) ip6_redirect(skb, net, skb->dev->ifindex, 0); else - ip6_update_pmtu(skb, net, info, 0, 0); + ip6_update_pmtu(net, NULL, skb, info, 0, 0); xfrm_state_put(x); return 0; diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 1b9316e..c07a5ac 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -76,7 +76,7 @@ static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type == NDISC_REDIRECT) ip6_redirect(skb, net, skb->dev->ifindex, 0); else - ip6_update_pmtu(skb, net, info, 0, 0); + ip6_update_pmtu(net, NULL, skb, info, 0, 0); xfrm_state_put(x); return 0; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ed44663..8f6a5f1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -1346,7 +1346,7 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt) (rt->rt6i_flags & RTF_PCPU || rt->rt6i_node); } -static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, +static void __ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, const struct ipv6hdr *iph, u32 mtu) { struct rt6_info *rt6 = (struct rt6_info *)dst; @@ -1377,12 +1377,8 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk, nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr); if (nrt6) { rt6_do_update_pmtu(nrt6, mtu); - - /* ip6_ins_rt(nrt6) will bump the - * rt6->rt6i_node->fn_sernum - * which will fail the next rt6_check() and - * invalidate the sk->sk_dst_cache. - */ + if (sk) + ip6_dst_store(sk, &nrt6->dst, daddr, saddr); ip6_ins_rt(nrt6); } } @@ -1394,8 +1390,8 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu); } -void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, - int oif, u32 mark) +void ip6_update_pmtu(struct net *net, struct sock *sk, + struct sk_buff *skb, __be32 mtu, int oif, u32 mark) { const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data; struct dst_entry *dst; @@ -1410,15 +1406,16 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, dst = ip6_route_output(net, NULL, &fl6); if (!dst->error) - __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu)); + __ip6_rt_update_pmtu(dst, sk, iph, ntohl(mtu)); dst_release(dst); } EXPORT_SYMBOL_GPL(ip6_update_pmtu); void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu) { - ip6_update_pmtu(skb, sock_net(sk), mtu, - sk->sk_bound_dev_if, sk->sk_mark); + ip6_update_pmtu(sock_net(sk), + (sk->sk_state != TCP_ESTABLISHED) ? NULL : sk, + skb, mtu, sk->sk_bound_dev_if, sk->sk_mark); } EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);