The RTN_ type for IPv6 FIB entries is currently embedded in rt6i_flags
and dst.error. Since dst is going to be removed, it can no longer be
relied on for FIB dumps so save the route type as fib6_type.

Signed-off-by: David Ahern <dsah...@gmail.com>
---
 include/net/ip6_fib.h |  1 +
 net/ipv6/addrconf.c   |  2 ++
 net/ipv6/route.c      | 46 ++++++++++++++++++++--------------------------
 3 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index f0aaf1c8f1a8..0165820bbafb 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -174,6 +174,7 @@ struct rt6_info {
        int                             rt6i_nh_weight;
        unsigned short                  rt6i_nfheader_len;
        u8                              rt6i_protocol;
+       u8                              fib6_type;
        u8                              exception_bucket_flushed:1,
                                        should_flush:1,
                                        unused:6;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 7d455d4df7ef..34d6aa65bf34 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -2331,6 +2331,7 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, 
struct net_device *dev,
                .fc_flags = RTF_UP | flags,
                .fc_nlinfo.nl_net = dev_net(dev),
                .fc_protocol = RTPROT_KERNEL,
+               .fc_type = RTN_UNICAST,
        };
 
        cfg.fc_dst = *pfx;
@@ -2394,6 +2395,7 @@ static void addrconf_add_mroute(struct net_device *dev)
                .fc_ifindex = dev->ifindex,
                .fc_dst_len = 8,
                .fc_flags = RTF_UP,
+               .fc_type = RTN_UNICAST,
                .fc_nlinfo.nl_net = dev_net(dev),
        };
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 1d2b6b1c5dae..177c85e7aa4d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -307,6 +307,7 @@ static const struct rt6_info ip6_null_entry_template = {
        .rt6i_protocol  = RTPROT_KERNEL,
        .rt6i_metric    = ~(u32) 0,
        .rt6i_ref       = ATOMIC_INIT(1),
+       .fib6_type      = RTN_UNREACHABLE,
 };
 
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -324,6 +325,7 @@ static const struct rt6_info ip6_prohibit_entry_template = {
        .rt6i_protocol  = RTPROT_KERNEL,
        .rt6i_metric    = ~(u32) 0,
        .rt6i_ref       = ATOMIC_INIT(1),
+       .fib6_type      = RTN_PROHIBIT,
 };
 
 static const struct rt6_info ip6_blk_hole_entry_template = {
@@ -339,6 +341,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = {
        .rt6i_protocol  = RTPROT_KERNEL,
        .rt6i_metric    = ~(u32) 0,
        .rt6i_ref       = ATOMIC_INIT(1),
+       .fib6_type      = RTN_BLACKHOLE,
 };
 
 #endif
@@ -2802,6 +2805,11 @@ static struct rt6_info *ip6_route_info_create(struct 
fib6_config *cfg,
                goto out;
        }
 
+       if (cfg->fc_type > RTN_MAX) {
+               NL_SET_ERR_MSG(extack, "Invalid route type");
+               goto out;
+       }
+
        if (cfg->fc_dst_len > 128) {
                NL_SET_ERR_MSG(extack, "Invalid prefix length");
                goto out;
@@ -2914,6 +2922,8 @@ static struct rt6_info *ip6_route_info_create(struct 
fib6_config *cfg,
        rt->rt6i_metric = cfg->fc_metric;
        rt->rt6i_nh_weight = 1;
 
+       rt->fib6_type = cfg->fc_type;
+
        /* We cannot add true routes via loopback here,
           they would result in kernel looping; promote them to reject routes
         */
@@ -3354,6 +3364,7 @@ static struct rt6_info *rt6_add_route_info(struct net 
*net,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
                                  RTF_UP | RTF_PREF(pref),
                .fc_protocol = RTPROT_RA,
+               .fc_type = RTN_UNICAST,
                .fc_nlinfo.portid = 0,
                .fc_nlinfo.nlh = NULL,
                .fc_nlinfo.nl_net = net,
@@ -3410,6 +3421,7 @@ struct rt6_info *rt6_add_dflt_router(struct net *net,
                .fc_flags       = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
                                  RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
                .fc_protocol = RTPROT_RA,
+               .fc_type = RTN_UNICAST,
                .fc_nlinfo.portid = 0,
                .fc_nlinfo.nlh = NULL,
                .fc_nlinfo.nl_net = net,
@@ -3485,6 +3497,7 @@ static void rtmsg_to_fib6_config(struct net *net,
        cfg->fc_dst_len = rtmsg->rtmsg_dst_len;
        cfg->fc_src_len = rtmsg->rtmsg_src_len;
        cfg->fc_flags = rtmsg->rtmsg_flags;
+       cfg->fc_type = rtmsg->rtmsg_type;
 
        cfg->fc_nlinfo.nl_net = net;
 
@@ -3605,10 +3618,13 @@ struct rt6_info *addrconf_dst_alloc(struct net *net,
 
        rt->rt6i_protocol = RTPROT_KERNEL;
        rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
-       if (anycast)
+       if (anycast) {
+               rt->fib6_type = RTN_ANYCAST;
                rt->rt6i_flags |= RTF_ANYCAST;
-       else
+       } else {
+               rt->fib6_type = RTN_LOCAL;
                rt->rt6i_flags |= RTF_LOCAL;
+       }
 
        rt->rt6i_gateway  = *addr;
        rt->rt6i_dst.addr = *addr;
@@ -4508,30 +4524,8 @@ static int rt6_fill_node(struct net *net,
        rtm->rtm_table = table;
        if (nla_put_u32(skb, RTA_TABLE, table))
                goto nla_put_failure;
-       if (rt->rt6i_flags & RTF_REJECT) {
-               switch (rt->dst.error) {
-               case -EINVAL:
-                       rtm->rtm_type = RTN_BLACKHOLE;
-                       break;
-               case -EACCES:
-                       rtm->rtm_type = RTN_PROHIBIT;
-                       break;
-               case -EAGAIN:
-                       rtm->rtm_type = RTN_THROW;
-                       break;
-               default:
-                       rtm->rtm_type = RTN_UNREACHABLE;
-                       break;
-               }
-       }
-       else if (rt->rt6i_flags & RTF_LOCAL)
-               rtm->rtm_type = RTN_LOCAL;
-       else if (rt->rt6i_flags & RTF_ANYCAST)
-               rtm->rtm_type = RTN_ANYCAST;
-       else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
-               rtm->rtm_type = RTN_LOCAL;
-       else
-               rtm->rtm_type = RTN_UNICAST;
+
+       rtm->rtm_type = rt->fib6_type;
        rtm->rtm_flags = 0;
        rtm->rtm_scope = RT_SCOPE_UNIVERSE;
        rtm->rtm_protocol = rt->rt6i_protocol;
-- 
2.11.0

Reply via email to