From mboxrd@z Thu Jan 1 00:00:00 1970 From: Xin Long Subject: [PATCH net] ipv6: use rt6_info members when dst is set in rt6_fill_node Date: Sat, 8 Sep 2018 17:24:01 +0800 Message-ID: <840f0c017c670ae9cc8fd8330ca24fcca1207918.1536398641.git.lucien.xin@gmail.com> Cc: davem@davemloft.net, David Ahern , Roopa Prabhu To: network dev Return-path: Received: from mail-pf1-f196.google.com ([209.85.210.196]:41171 "EHLO mail-pf1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726343AbeIHOJP (ORCPT ); Sat, 8 Sep 2018 10:09:15 -0400 Received: by mail-pf1-f196.google.com with SMTP id h79-v6so8135918pfk.8 for ; Sat, 08 Sep 2018 02:24:10 -0700 (PDT) Sender: netdev-owner@vger.kernel.org List-ID: In inet6_rtm_getroute, since Commit 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes"), it has used rt->from to dump route info instead of rt. However for some route like cache, its information is not the same as that of the 'from' one. It caused 'ip -6 route get' to dump the wrong route information. In Jianlin's testing, the output information even lost the expiration time for a pmtu route cache due to the wrong fib6_flags. So change to use rt6_info members when it tries to dump a route entry without fibmatch set. Note that we will fix the gw/nh dump in another patch. Fixes: 93531c674315 ("net/ipv6: separate handling of FIB entries from dst based routes") Reported-by: Jianlin Shi Signed-off-by: Xin Long --- net/ipv6/route.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 18e00ce..e554922 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -4670,20 +4670,33 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, int iif, int type, u32 portid, u32 seq, unsigned int flags) { - struct rtmsg *rtm; + struct rt6key *fib6_prefsrc, *fib6_dst, *fib6_src; + struct rt6_info *rt6 = (struct rt6_info *)dst; + u32 *pmetrics, table, fib6_flags; struct nlmsghdr *nlh; + struct rtmsg *rtm; long expires = 0; - u32 *pmetrics; - u32 table; nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags); if (!nlh) return -EMSGSIZE; + if (rt6) { + fib6_dst = &rt6->rt6i_dst; + fib6_src = &rt6->rt6i_src; + fib6_flags = rt6->rt6i_flags; + fib6_prefsrc = &rt6->rt6i_prefsrc; + } else { + fib6_dst = &rt->fib6_dst; + fib6_src = &rt->fib6_src; + fib6_flags = rt->fib6_flags; + fib6_prefsrc = &rt->fib6_prefsrc; + } + rtm = nlmsg_data(nlh); rtm->rtm_family = AF_INET6; - rtm->rtm_dst_len = rt->fib6_dst.plen; - rtm->rtm_src_len = rt->fib6_src.plen; + rtm->rtm_dst_len = fib6_dst->plen; + rtm->rtm_src_len = fib6_src->plen; rtm->rtm_tos = 0; if (rt->fib6_table) table = rt->fib6_table->tb6_id; @@ -4698,7 +4711,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, rtm->rtm_scope = RT_SCOPE_UNIVERSE; rtm->rtm_protocol = rt->fib6_protocol; - if (rt->fib6_flags & RTF_CACHE) + if (fib6_flags & RTF_CACHE) rtm->rtm_flags |= RTM_F_CLONED; if (dest) { @@ -4706,7 +4719,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, goto nla_put_failure; rtm->rtm_dst_len = 128; } else if (rtm->rtm_dst_len) - if (nla_put_in6_addr(skb, RTA_DST, &rt->fib6_dst.addr)) + if (nla_put_in6_addr(skb, RTA_DST, &fib6_dst->addr)) goto nla_put_failure; #ifdef CONFIG_IPV6_SUBTREES if (src) { @@ -4714,12 +4727,12 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, goto nla_put_failure; rtm->rtm_src_len = 128; } else if (rtm->rtm_src_len && - nla_put_in6_addr(skb, RTA_SRC, &rt->fib6_src.addr)) + nla_put_in6_addr(skb, RTA_SRC, &fib6_src->addr)) goto nla_put_failure; #endif if (iif) { #ifdef CONFIG_IPV6_MROUTE - if (ipv6_addr_is_multicast(&rt->fib6_dst.addr)) { + if (ipv6_addr_is_multicast(&fib6_dst->addr)) { int err = ip6mr_get_route(net, skb, rtm, portid); if (err == 0) @@ -4737,9 +4750,9 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, goto nla_put_failure; } - if (rt->fib6_prefsrc.plen) { + if (fib6_prefsrc->plen) { struct in6_addr saddr_buf; - saddr_buf = rt->fib6_prefsrc.addr; + saddr_buf = fib6_prefsrc->addr; if (nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf)) goto nla_put_failure; } @@ -4777,7 +4790,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, goto nla_put_failure; } - if (rt->fib6_flags & RTF_EXPIRES) { + if (fib6_flags & RTF_EXPIRES) { expires = dst ? dst->expires : rt->expires; expires -= jiffies; } @@ -4785,7 +4798,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, if (rtnl_put_cacheinfo(skb, dst, 0, expires, dst ? dst->error : 0) < 0) goto nla_put_failure; - if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->fib6_flags))) + if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(fib6_flags))) goto nla_put_failure; -- 2.1.0