LCOV - code coverage report
Current view: top level - net/ipv4 - fib_semantics.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 408 942 43.3 %
Date: 2021-04-22 12:43:58 Functions: 27 41 65.9 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * INET         An implementation of the TCP/IP protocol suite for the LINUX
       4             :  *              operating system.  INET is implemented using the  BSD Socket
       5             :  *              interface as the means of communication with the user level.
       6             :  *
       7             :  *              IPv4 Forwarding Information Base: semantics.
       8             :  *
       9             :  * Authors:     Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
      10             :  */
      11             : 
      12             : #include <linux/uaccess.h>
      13             : #include <linux/bitops.h>
      14             : #include <linux/types.h>
      15             : #include <linux/kernel.h>
      16             : #include <linux/jiffies.h>
      17             : #include <linux/mm.h>
      18             : #include <linux/string.h>
      19             : #include <linux/socket.h>
      20             : #include <linux/sockios.h>
      21             : #include <linux/errno.h>
      22             : #include <linux/in.h>
      23             : #include <linux/inet.h>
      24             : #include <linux/inetdevice.h>
      25             : #include <linux/netdevice.h>
      26             : #include <linux/if_arp.h>
      27             : #include <linux/proc_fs.h>
      28             : #include <linux/skbuff.h>
      29             : #include <linux/init.h>
      30             : #include <linux/slab.h>
      31             : #include <linux/netlink.h>
      32             : 
      33             : #include <net/arp.h>
      34             : #include <net/ip.h>
      35             : #include <net/protocol.h>
      36             : #include <net/route.h>
      37             : #include <net/tcp.h>
      38             : #include <net/sock.h>
      39             : #include <net/ip_fib.h>
      40             : #include <net/ip6_fib.h>
      41             : #include <net/nexthop.h>
      42             : #include <net/netlink.h>
      43             : #include <net/rtnh.h>
      44             : #include <net/lwtunnel.h>
      45             : #include <net/fib_notifier.h>
      46             : #include <net/addrconf.h>
      47             : 
      48             : #include "fib_lookup.h"
      49             : 
      50             : static DEFINE_SPINLOCK(fib_info_lock);
      51             : static struct hlist_head *fib_info_hash;
      52             : static struct hlist_head *fib_info_laddrhash;
      53             : static unsigned int fib_info_hash_size;
      54             : static unsigned int fib_info_cnt;
      55             : 
      56             : #define DEVINDEX_HASHBITS 8
      57             : #define DEVINDEX_HASHSIZE (1U << DEVINDEX_HASHBITS)
      58             : static struct hlist_head fib_info_devhash[DEVINDEX_HASHSIZE];
      59             : 
      60             : /* for_nexthops and change_nexthops only used when nexthop object
      61             :  * is not set in a fib_info. The logic within can reference fib_nh.
      62             :  */
      63             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
      64             : 
      65             : #define for_nexthops(fi) {                                              \
      66             :         int nhsel; const struct fib_nh *nh;                             \
      67             :         for (nhsel = 0, nh = (fi)->fib_nh;                           \
      68             :              nhsel < fib_info_num_path((fi));                                \
      69             :              nh++, nhsel++)
      70             : 
      71             : #define change_nexthops(fi) {                                           \
      72             :         int nhsel; struct fib_nh *nexthop_nh;                           \
      73             :         for (nhsel = 0, nexthop_nh = (struct fib_nh *)((fi)->fib_nh);        \
      74             :              nhsel < fib_info_num_path((fi));                                \
      75             :              nexthop_nh++, nhsel++)
      76             : 
      77             : #else /* CONFIG_IP_ROUTE_MULTIPATH */
      78             : 
      79             : /* Hope, that gcc will optimize it to get rid of dummy loop */
      80             : 
      81             : #define for_nexthops(fi) {                                              \
      82             :         int nhsel; const struct fib_nh *nh = (fi)->fib_nh;           \
      83             :         for (nhsel = 0; nhsel < 1; nhsel++)
      84             : 
      85             : #define change_nexthops(fi) {                                           \
      86             :         int nhsel;                                                      \
      87             :         struct fib_nh *nexthop_nh = (struct fib_nh *)((fi)->fib_nh); \
      88             :         for (nhsel = 0; nhsel < 1; nhsel++)
      89             : 
      90             : #endif /* CONFIG_IP_ROUTE_MULTIPATH */
      91             : 
      92             : #define endfor_nexthops(fi) }
      93             : 
      94             : 
      95             : const struct fib_prop fib_props[RTN_MAX + 1] = {
      96             :         [RTN_UNSPEC] = {
      97             :                 .error  = 0,
      98             :                 .scope  = RT_SCOPE_NOWHERE,
      99             :         },
     100             :         [RTN_UNICAST] = {
     101             :                 .error  = 0,
     102             :                 .scope  = RT_SCOPE_UNIVERSE,
     103             :         },
     104             :         [RTN_LOCAL] = {
     105             :                 .error  = 0,
     106             :                 .scope  = RT_SCOPE_HOST,
     107             :         },
     108             :         [RTN_BROADCAST] = {
     109             :                 .error  = 0,
     110             :                 .scope  = RT_SCOPE_LINK,
     111             :         },
     112             :         [RTN_ANYCAST] = {
     113             :                 .error  = 0,
     114             :                 .scope  = RT_SCOPE_LINK,
     115             :         },
     116             :         [RTN_MULTICAST] = {
     117             :                 .error  = 0,
     118             :                 .scope  = RT_SCOPE_UNIVERSE,
     119             :         },
     120             :         [RTN_BLACKHOLE] = {
     121             :                 .error  = -EINVAL,
     122             :                 .scope  = RT_SCOPE_UNIVERSE,
     123             :         },
     124             :         [RTN_UNREACHABLE] = {
     125             :                 .error  = -EHOSTUNREACH,
     126             :                 .scope  = RT_SCOPE_UNIVERSE,
     127             :         },
     128             :         [RTN_PROHIBIT] = {
     129             :                 .error  = -EACCES,
     130             :                 .scope  = RT_SCOPE_UNIVERSE,
     131             :         },
     132             :         [RTN_THROW] = {
     133             :                 .error  = -EAGAIN,
     134             :                 .scope  = RT_SCOPE_UNIVERSE,
     135             :         },
     136             :         [RTN_NAT] = {
     137             :                 .error  = -EINVAL,
     138             :                 .scope  = RT_SCOPE_NOWHERE,
     139             :         },
     140             :         [RTN_XRESOLVE] = {
     141             :                 .error  = -EINVAL,
     142             :                 .scope  = RT_SCOPE_NOWHERE,
     143             :         },
     144             : };
     145             : 
     146           5 : static void rt_fibinfo_free(struct rtable __rcu **rtp)
     147             : {
     148           5 :         struct rtable *rt = rcu_dereference_protected(*rtp, 1);
     149             : 
     150           5 :         if (!rt)
     151             :                 return;
     152             : 
     153             :         /* Not even needed : RCU_INIT_POINTER(*rtp, NULL);
     154             :          * because we waited an RCU grace period before calling
     155             :          * free_fib_info_rcu()
     156             :          */
     157             : 
     158           0 :         dst_dev_put(&rt->dst);
     159           0 :         dst_release_immediate(&rt->dst);
     160             : }
     161             : 
     162           5 : static void free_nh_exceptions(struct fib_nh_common *nhc)
     163             : {
     164           5 :         struct fnhe_hash_bucket *hash;
     165           5 :         int i;
     166             : 
     167           5 :         hash = rcu_dereference_protected(nhc->nhc_exceptions, 1);
     168           5 :         if (!hash)
     169             :                 return;
     170           0 :         for (i = 0; i < FNHE_HASH_SIZE; i++) {
     171           0 :                 struct fib_nh_exception *fnhe;
     172             : 
     173           0 :                 fnhe = rcu_dereference_protected(hash[i].chain, 1);
     174           0 :                 while (fnhe) {
     175           0 :                         struct fib_nh_exception *next;
     176             : 
     177           0 :                         next = rcu_dereference_protected(fnhe->fnhe_next, 1);
     178             : 
     179           0 :                         rt_fibinfo_free(&fnhe->fnhe_rth_input);
     180           0 :                         rt_fibinfo_free(&fnhe->fnhe_rth_output);
     181             : 
     182           0 :                         kfree(fnhe);
     183             : 
     184           0 :                         fnhe = next;
     185             :                 }
     186             :         }
     187           0 :         kfree(hash);
     188             : }
     189             : 
     190           5 : static void rt_fibinfo_free_cpus(struct rtable __rcu * __percpu *rtp)
     191             : {
     192           5 :         int cpu;
     193             : 
     194           5 :         if (!rtp)
     195             :                 return;
     196             : 
     197          25 :         for_each_possible_cpu(cpu) {
     198          20 :                 struct rtable *rt;
     199             : 
     200          20 :                 rt = rcu_dereference_protected(*per_cpu_ptr(rtp, cpu), 1);
     201          20 :                 if (rt) {
     202           0 :                         dst_dev_put(&rt->dst);
     203           0 :                         dst_release_immediate(&rt->dst);
     204             :                 }
     205             :         }
     206           5 :         free_percpu(rtp);
     207             : }
     208             : 
     209           5 : void fib_nh_common_release(struct fib_nh_common *nhc)
     210             : {
     211           5 :         if (nhc->nhc_dev)
     212           5 :                 dev_put(nhc->nhc_dev);
     213             : 
     214           5 :         lwtstate_put(nhc->nhc_lwtstate);
     215           5 :         rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
     216           5 :         rt_fibinfo_free(&nhc->nhc_rth_input);
     217           5 :         free_nh_exceptions(nhc);
     218           5 : }
     219             : EXPORT_SYMBOL_GPL(fib_nh_common_release);
     220             : 
     221           5 : void fib_nh_release(struct net *net, struct fib_nh *fib_nh)
     222             : {
     223             : #ifdef CONFIG_IP_ROUTE_CLASSID
     224             :         if (fib_nh->nh_tclassid)
     225             :                 net->ipv4.fib_num_tclassid_users--;
     226             : #endif
     227           0 :         fib_nh_common_release(&fib_nh->nh_common);
     228           0 : }
     229             : 
     230             : /* Release a nexthop info record */
     231           5 : static void free_fib_info_rcu(struct rcu_head *head)
     232             : {
     233           5 :         struct fib_info *fi = container_of(head, struct fib_info, rcu);
     234             : 
     235           5 :         if (fi->nh) {
     236           0 :                 nexthop_put(fi->nh);
     237             :         } else {
     238          10 :                 change_nexthops(fi) {
     239           5 :                         fib_nh_release(fi->fib_net, nexthop_nh);
     240           5 :                 } endfor_nexthops(fi);
     241             :         }
     242             : 
     243           5 :         ip_fib_metrics_put(fi->fib_metrics);
     244             : 
     245           5 :         kfree(fi);
     246           5 : }
     247             : 
     248           5 : void free_fib_info(struct fib_info *fi)
     249             : {
     250           5 :         if (fi->fib_dead == 0) {
     251           0 :                 pr_warn("Freeing alive fib_info %p\n", fi);
     252           0 :                 return;
     253             :         }
     254           5 :         fib_info_cnt--;
     255             : 
     256           5 :         call_rcu(&fi->rcu, free_fib_info_rcu);
     257             : }
     258             : EXPORT_SYMBOL_GPL(free_fib_info);
     259             : 
     260           2 : void fib_release_info(struct fib_info *fi)
     261             : {
     262           2 :         spin_lock_bh(&fib_info_lock);
     263           2 :         if (fi && --fi->fib_treeref == 0) {
     264           0 :                 hlist_del(&fi->fib_hash);
     265           0 :                 if (fi->fib_prefsrc)
     266           0 :                         hlist_del(&fi->fib_lhash);
     267           0 :                 if (fi->nh) {
     268           0 :                         list_del(&fi->nh_list);
     269             :                 } else {
     270           0 :                         change_nexthops(fi) {
     271           0 :                                 if (!nexthop_nh->fib_nh_dev)
     272           0 :                                         continue;
     273           0 :                                 hlist_del(&nexthop_nh->nh_hash);
     274             :                         } endfor_nexthops(fi)
     275             :                 }
     276           0 :                 fi->fib_dead = 1;
     277           0 :                 fib_info_put(fi);
     278             :         }
     279           2 :         spin_unlock_bh(&fib_info_lock);
     280           2 : }
     281             : 
     282           5 : static inline int nh_comp(struct fib_info *fi, struct fib_info *ofi)
     283             : {
     284           5 :         const struct fib_nh *onh;
     285             : 
     286           5 :         if (fi->nh || ofi->nh)
     287           0 :                 return nexthop_cmp(fi->nh, ofi->nh) ? 0 : -1;
     288             : 
     289           5 :         if (ofi->fib_nhs == 0)
     290             :                 return 0;
     291             : 
     292          10 :         for_nexthops(fi) {
     293           5 :                 onh = fib_info_nh(ofi, nhsel);
     294             : 
     295           5 :                 if (nh->fib_nh_oif != onh->fib_nh_oif ||
     296           5 :                     nh->fib_nh_gw_family != onh->fib_nh_gw_family ||
     297             :                     nh->fib_nh_scope != onh->fib_nh_scope ||
     298             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
     299             :                     nh->fib_nh_weight != onh->fib_nh_weight ||
     300             : #endif
     301             : #ifdef CONFIG_IP_ROUTE_CLASSID
     302             :                     nh->nh_tclassid != onh->nh_tclassid ||
     303             : #endif
     304           5 :                     lwtunnel_cmp_encap(nh->fib_nh_lws, onh->fib_nh_lws) ||
     305           5 :                     ((nh->fib_nh_flags ^ onh->fib_nh_flags) & ~RTNH_COMPARE_MASK))
     306             :                         return -1;
     307             : 
     308           5 :                 if (nh->fib_nh_gw_family == AF_INET &&
     309           0 :                     nh->fib_nh_gw4 != onh->fib_nh_gw4)
     310             :                         return -1;
     311             : 
     312           5 :                 if (nh->fib_nh_gw_family == AF_INET6 &&
     313           0 :                     ipv6_addr_cmp(&nh->fib_nh_gw6, &onh->fib_nh_gw6))
     314             :                         return -1;
     315             :         } endfor_nexthops(fi);
     316             :         return 0;
     317             : }
     318             : 
     319          26 : static inline unsigned int fib_devindex_hashfn(unsigned int val)
     320             : {
     321          26 :         unsigned int mask = DEVINDEX_HASHSIZE - 1;
     322             : 
     323          26 :         return (val ^
     324          26 :                 (val >> DEVINDEX_HASHBITS) ^
     325          26 :                 (val >> (DEVINDEX_HASHBITS * 2))) & mask;
     326             : }
     327             : 
     328          19 : static unsigned int fib_info_hashfn_1(int init_val, u8 protocol, u8 scope,
     329             :                                       u32 prefsrc, u32 priority)
     330             : {
     331          19 :         unsigned int val = init_val;
     332             : 
     333          19 :         val ^= (protocol << 8) | scope;
     334          19 :         val ^= prefsrc;
     335          19 :         val ^= priority;
     336             : 
     337          19 :         return val;
     338             : }
     339             : 
     340          19 : static unsigned int fib_info_hashfn_result(unsigned int val)
     341             : {
     342          19 :         unsigned int mask = (fib_info_hash_size - 1);
     343             : 
     344          19 :         return (val ^ (val >> 7) ^ (val >> 12)) & mask;
     345             : }
     346             : 
     347          19 : static inline unsigned int fib_info_hashfn(struct fib_info *fi)
     348             : {
     349          19 :         unsigned int val;
     350             : 
     351          19 :         val = fib_info_hashfn_1(fi->fib_nhs, fi->fib_protocol,
     352          19 :                                 fi->fib_scope, (__force u32)fi->fib_prefsrc,
     353             :                                 fi->fib_priority);
     354             : 
     355          19 :         if (fi->nh) {
     356           0 :                 val ^= fib_devindex_hashfn(fi->nh->id);
     357             :         } else {
     358          38 :                 for_nexthops(fi) {
     359          19 :                         val ^= fib_devindex_hashfn(nh->fib_nh_oif);
     360             :                 } endfor_nexthops(fi)
     361             :         }
     362             : 
     363          19 :         return fib_info_hashfn_result(val);
     364             : }
     365             : 
     366             : /* no metrics, only nexthop id */
     367           0 : static struct fib_info *fib_find_info_nh(struct net *net,
     368             :                                          const struct fib_config *cfg)
     369             : {
     370           0 :         struct hlist_head *head;
     371           0 :         struct fib_info *fi;
     372           0 :         unsigned int hash;
     373             : 
     374           0 :         hash = fib_info_hashfn_1(fib_devindex_hashfn(cfg->fc_nh_id),
     375           0 :                                  cfg->fc_protocol, cfg->fc_scope,
     376           0 :                                  (__force u32)cfg->fc_prefsrc,
     377             :                                  cfg->fc_priority);
     378           0 :         hash = fib_info_hashfn_result(hash);
     379           0 :         head = &fib_info_hash[hash];
     380             : 
     381           0 :         hlist_for_each_entry(fi, head, fib_hash) {
     382           0 :                 if (!net_eq(fi->fib_net, net))
     383             :                         continue;
     384           0 :                 if (!fi->nh || fi->nh->id != cfg->fc_nh_id)
     385           0 :                         continue;
     386           0 :                 if (cfg->fc_protocol == fi->fib_protocol &&
     387           0 :                     cfg->fc_scope == fi->fib_scope &&
     388           0 :                     cfg->fc_prefsrc == fi->fib_prefsrc &&
     389           0 :                     cfg->fc_priority == fi->fib_priority &&
     390           0 :                     cfg->fc_type == fi->fib_type &&
     391           0 :                     cfg->fc_table == fi->fib_tb_id &&
     392           0 :                     !((cfg->fc_flags ^ fi->fib_flags) & ~RTNH_COMPARE_MASK))
     393           0 :                         return fi;
     394             :         }
     395             : 
     396             :         return NULL;
     397             : }
     398             : 
     399          12 : static struct fib_info *fib_find_info(struct fib_info *nfi)
     400             : {
     401          12 :         struct hlist_head *head;
     402          12 :         struct fib_info *fi;
     403          12 :         unsigned int hash;
     404             : 
     405          12 :         hash = fib_info_hashfn(nfi);
     406          12 :         head = &fib_info_hash[hash];
     407             : 
     408          27 :         hlist_for_each_entry(fi, head, fib_hash) {
     409           8 :                 if (!net_eq(fi->fib_net, nfi->fib_net))
     410             :                         continue;
     411           8 :                 if (fi->fib_nhs != nfi->fib_nhs)
     412           0 :                         continue;
     413           8 :                 if (nfi->fib_protocol == fi->fib_protocol &&
     414           8 :                     nfi->fib_scope == fi->fib_scope &&
     415           8 :                     nfi->fib_prefsrc == fi->fib_prefsrc &&
     416           8 :                     nfi->fib_priority == fi->fib_priority &&
     417           8 :                     nfi->fib_type == fi->fib_type &&
     418           5 :                     memcmp(nfi->fib_metrics, fi->fib_metrics,
     419           5 :                            sizeof(u32) * RTAX_MAX) == 0 &&
     420          10 :                     !((nfi->fib_flags ^ fi->fib_flags) & ~RTNH_COMPARE_MASK) &&
     421           5 :                     nh_comp(fi, nfi) == 0)
     422           5 :                         return fi;
     423             :         }
     424             : 
     425             :         return NULL;
     426             : }
     427             : 
     428             : /* Check, that the gateway is already configured.
     429             :  * Used only by redirect accept routine.
     430             :  */
     431           0 : int ip_fib_check_default(__be32 gw, struct net_device *dev)
     432             : {
     433           0 :         struct hlist_head *head;
     434           0 :         struct fib_nh *nh;
     435           0 :         unsigned int hash;
     436             : 
     437           0 :         spin_lock(&fib_info_lock);
     438             : 
     439           0 :         hash = fib_devindex_hashfn(dev->ifindex);
     440           0 :         head = &fib_info_devhash[hash];
     441           0 :         hlist_for_each_entry(nh, head, nh_hash) {
     442           0 :                 if (nh->fib_nh_dev == dev &&
     443           0 :                     nh->fib_nh_gw4 == gw &&
     444           0 :                     !(nh->fib_nh_flags & RTNH_F_DEAD)) {
     445           0 :                         spin_unlock(&fib_info_lock);
     446           0 :                         return 0;
     447             :                 }
     448             :         }
     449             : 
     450           0 :         spin_unlock(&fib_info_lock);
     451             : 
     452           0 :         return -1;
     453             : }
     454             : 
     455          10 : size_t fib_nlmsg_size(struct fib_info *fi)
     456             : {
     457          10 :         size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
     458          10 :                          + nla_total_size(4) /* RTA_TABLE */
     459          10 :                          + nla_total_size(4) /* RTA_DST */
     460          10 :                          + nla_total_size(4) /* RTA_PRIORITY */
     461          10 :                          + nla_total_size(4) /* RTA_PREFSRC */
     462          10 :                          + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
     463          10 :         unsigned int nhs = fib_info_num_path(fi);
     464             : 
     465             :         /* space for nested metrics */
     466          10 :         payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
     467             : 
     468          10 :         if (fi->nh)
     469           0 :                 payload += nla_total_size(4); /* RTA_NH_ID */
     470             : 
     471          10 :         if (nhs) {
     472             :                 size_t nh_encapsize = 0;
     473             :                 /* Also handles the special case nhs == 1 */
     474             : 
     475             :                 /* each nexthop is packed in an attribute */
     476          20 :                 size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
     477             :                 unsigned int i;
     478             : 
     479             :                 /* may contain flow and gateway attribute */
     480          20 :                 nhsize += 2 * nla_total_size(4);
     481             : 
     482             :                 /* grab encap info */
     483          40 :                 for (i = 0; i < fib_info_num_path(fi); i++) {
     484          10 :                         struct fib_nh_common *nhc = fib_info_nhc(fi, i);
     485             : 
     486          10 :                         if (nhc->nhc_lwtstate) {
     487             :                                 /* RTA_ENCAP_TYPE */
     488           0 :                                 nh_encapsize += lwtunnel_get_encap_size(
     489             :                                                 nhc->nhc_lwtstate);
     490             :                                 /* RTA_ENCAP */
     491           0 :                                 nh_encapsize +=  nla_total_size(2);
     492             :                         }
     493             :                 }
     494             : 
     495             :                 /* all nexthops are packed in a nested attribute */
     496          10 :                 payload += nla_total_size((nhs * nhsize) + nh_encapsize);
     497             : 
     498             :         }
     499             : 
     500          10 :         return payload;
     501             : }
     502             : 
     503          10 : void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
     504             :                int dst_len, u32 tb_id, const struct nl_info *info,
     505             :                unsigned int nlm_flags)
     506             : {
     507          10 :         struct fib_rt_info fri;
     508          10 :         struct sk_buff *skb;
     509          10 :         u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
     510          10 :         int err = -ENOBUFS;
     511             : 
     512          10 :         skb = nlmsg_new(fib_nlmsg_size(fa->fa_info), GFP_KERNEL);
     513          10 :         if (!skb)
     514           0 :                 goto errout;
     515             : 
     516          10 :         fri.fi = fa->fa_info;
     517          10 :         fri.tb_id = tb_id;
     518          10 :         fri.dst = key;
     519          10 :         fri.dst_len = dst_len;
     520          10 :         fri.tos = fa->fa_tos;
     521          10 :         fri.type = fa->fa_type;
     522          10 :         fri.offload = fa->offload;
     523          10 :         fri.trap = fa->trap;
     524          10 :         fri.offload_failed = fa->offload_failed;
     525          10 :         err = fib_dump_info(skb, info->portid, seq, event, &fri, nlm_flags);
     526          10 :         if (err < 0) {
     527             :                 /* -EMSGSIZE implies BUG in fib_nlmsg_size() */
     528           0 :                 WARN_ON(err == -EMSGSIZE);
     529           0 :                 kfree_skb(skb);
     530           0 :                 goto errout;
     531             :         }
     532          10 :         rtnl_notify(skb, info->nl_net, info->portid, RTNLGRP_IPV4_ROUTE,
     533             :                     info->nlh, GFP_KERNEL);
     534          10 :         return;
     535           0 : errout:
     536           0 :         if (err < 0)
     537           0 :                 rtnl_set_sk_err(info->nl_net, RTNLGRP_IPV4_ROUTE, err);
     538             : }
     539             : 
     540           0 : static int fib_detect_death(struct fib_info *fi, int order,
     541             :                             struct fib_info **last_resort, int *last_idx,
     542             :                             int dflt)
     543             : {
     544           0 :         const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
     545           0 :         struct neighbour *n;
     546           0 :         int state = NUD_NONE;
     547             : 
     548           0 :         if (likely(nhc->nhc_gw_family == AF_INET))
     549           0 :                 n = neigh_lookup(&arp_tbl, &nhc->nhc_gw.ipv4, nhc->nhc_dev);
     550           0 :         else if (nhc->nhc_gw_family == AF_INET6)
     551           0 :                 n = neigh_lookup(ipv6_stub->nd_tbl, &nhc->nhc_gw.ipv6,
     552             :                                  nhc->nhc_dev);
     553             :         else
     554             :                 n = NULL;
     555             : 
     556           0 :         if (n) {
     557           0 :                 state = n->nud_state;
     558           0 :                 neigh_release(n);
     559             :         } else {
     560           0 :                 return 0;
     561             :         }
     562           0 :         if (state == NUD_REACHABLE)
     563             :                 return 0;
     564           0 :         if ((state & NUD_VALID) && order != dflt)
     565             :                 return 0;
     566           0 :         if ((state & NUD_VALID) ||
     567           0 :             (*last_idx < 0 && order > dflt && state != NUD_INCOMPLETE)) {
     568           0 :                 *last_resort = fi;
     569           0 :                 *last_idx = order;
     570             :         }
     571             :         return 1;
     572             : }
     573             : 
     574          12 : int fib_nh_common_init(struct net *net, struct fib_nh_common *nhc,
     575             :                        struct nlattr *encap, u16 encap_type,
     576             :                        void *cfg, gfp_t gfp_flags,
     577             :                        struct netlink_ext_ack *extack)
     578             : {
     579          12 :         int err;
     580             : 
     581          12 :         nhc->nhc_pcpu_rth_output = alloc_percpu_gfp(struct rtable __rcu *,
     582             :                                                     gfp_flags);
     583          12 :         if (!nhc->nhc_pcpu_rth_output)
     584             :                 return -ENOMEM;
     585             : 
     586          12 :         if (encap) {
     587           0 :                 struct lwtunnel_state *lwtstate;
     588             : 
     589           0 :                 if (encap_type == LWTUNNEL_ENCAP_NONE) {
     590           0 :                         NL_SET_ERR_MSG(extack, "LWT encap type not specified");
     591           0 :                         err = -EINVAL;
     592           0 :                         goto lwt_failure;
     593             :                 }
     594           0 :                 err = lwtunnel_build_state(net, encap_type, encap,
     595           0 :                                            nhc->nhc_family, cfg, &lwtstate,
     596             :                                            extack);
     597           0 :                 if (err)
     598           0 :                         goto lwt_failure;
     599             : 
     600             :                 nhc->nhc_lwtstate = lwtstate_get(lwtstate);
     601             :         }
     602             : 
     603             :         return 0;
     604             : 
     605           0 : lwt_failure:
     606           0 :         rt_fibinfo_free_cpus(nhc->nhc_pcpu_rth_output);
     607           0 :         nhc->nhc_pcpu_rth_output = NULL;
     608           0 :         return err;
     609             : }
     610             : EXPORT_SYMBOL_GPL(fib_nh_common_init);
     611             : 
     612          12 : int fib_nh_init(struct net *net, struct fib_nh *nh,
     613             :                 struct fib_config *cfg, int nh_weight,
     614             :                 struct netlink_ext_ack *extack)
     615             : {
     616          12 :         int err;
     617             : 
     618          12 :         nh->fib_nh_family = AF_INET;
     619             : 
     620          24 :         err = fib_nh_common_init(net, &nh->nh_common, cfg->fc_encap,
     621          12 :                                  cfg->fc_encap_type, cfg, GFP_KERNEL, extack);
     622          12 :         if (err)
     623             :                 return err;
     624             : 
     625          12 :         nh->fib_nh_oif = cfg->fc_oif;
     626          12 :         nh->fib_nh_gw_family = cfg->fc_gw_family;
     627          12 :         if (cfg->fc_gw_family == AF_INET)
     628           1 :                 nh->fib_nh_gw4 = cfg->fc_gw4;
     629          11 :         else if (cfg->fc_gw_family == AF_INET6)
     630           0 :                 nh->fib_nh_gw6 = cfg->fc_gw6;
     631             : 
     632          12 :         nh->fib_nh_flags = cfg->fc_flags;
     633             : 
     634             : #ifdef CONFIG_IP_ROUTE_CLASSID
     635             :         nh->nh_tclassid = cfg->fc_flow;
     636             :         if (nh->nh_tclassid)
     637             :                 net->ipv4.fib_num_tclassid_users++;
     638             : #endif
     639             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
     640             :         nh->fib_nh_weight = nh_weight;
     641             : #endif
     642          12 :         return 0;
     643             : }
     644             : 
     645             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
     646             : 
     647             : static int fib_count_nexthops(struct rtnexthop *rtnh, int remaining,
     648             :                               struct netlink_ext_ack *extack)
     649             : {
     650             :         int nhs = 0;
     651             : 
     652             :         while (rtnh_ok(rtnh, remaining)) {
     653             :                 nhs++;
     654             :                 rtnh = rtnh_next(rtnh, &remaining);
     655             :         }
     656             : 
     657             :         /* leftover implies invalid nexthop configuration, discard it */
     658             :         if (remaining > 0) {
     659             :                 NL_SET_ERR_MSG(extack,
     660             :                                "Invalid nexthop configuration - extra data after nexthops");
     661             :                 nhs = 0;
     662             :         }
     663             : 
     664             :         return nhs;
     665             : }
     666             : 
     667             : /* only called when fib_nh is integrated into fib_info */
     668             : static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
     669             :                        int remaining, struct fib_config *cfg,
     670             :                        struct netlink_ext_ack *extack)
     671             : {
     672             :         struct net *net = fi->fib_net;
     673             :         struct fib_config fib_cfg;
     674             :         struct fib_nh *nh;
     675             :         int ret;
     676             : 
     677             :         change_nexthops(fi) {
     678             :                 int attrlen;
     679             : 
     680             :                 memset(&fib_cfg, 0, sizeof(fib_cfg));
     681             : 
     682             :                 if (!rtnh_ok(rtnh, remaining)) {
     683             :                         NL_SET_ERR_MSG(extack,
     684             :                                        "Invalid nexthop configuration - extra data after nexthop");
     685             :                         return -EINVAL;
     686             :                 }
     687             : 
     688             :                 if (rtnh->rtnh_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) {
     689             :                         NL_SET_ERR_MSG(extack,
     690             :                                        "Invalid flags for nexthop - can not contain DEAD or LINKDOWN");
     691             :                         return -EINVAL;
     692             :                 }
     693             : 
     694             :                 fib_cfg.fc_flags = (cfg->fc_flags & ~0xFF) | rtnh->rtnh_flags;
     695             :                 fib_cfg.fc_oif = rtnh->rtnh_ifindex;
     696             : 
     697             :                 attrlen = rtnh_attrlen(rtnh);
     698             :                 if (attrlen > 0) {
     699             :                         struct nlattr *nla, *nlav, *attrs = rtnh_attrs(rtnh);
     700             : 
     701             :                         nla = nla_find(attrs, attrlen, RTA_GATEWAY);
     702             :                         nlav = nla_find(attrs, attrlen, RTA_VIA);
     703             :                         if (nla && nlav) {
     704             :                                 NL_SET_ERR_MSG(extack,
     705             :                                                "Nexthop configuration can not contain both GATEWAY and VIA");
     706             :                                 return -EINVAL;
     707             :                         }
     708             :                         if (nla) {
     709             :                                 fib_cfg.fc_gw4 = nla_get_in_addr(nla);
     710             :                                 if (fib_cfg.fc_gw4)
     711             :                                         fib_cfg.fc_gw_family = AF_INET;
     712             :                         } else if (nlav) {
     713             :                                 ret = fib_gw_from_via(&fib_cfg, nlav, extack);
     714             :                                 if (ret)
     715             :                                         goto errout;
     716             :                         }
     717             : 
     718             :                         nla = nla_find(attrs, attrlen, RTA_FLOW);
     719             :                         if (nla)
     720             :                                 fib_cfg.fc_flow = nla_get_u32(nla);
     721             : 
     722             :                         fib_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
     723             :                         nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
     724             :                         if (nla)
     725             :                                 fib_cfg.fc_encap_type = nla_get_u16(nla);
     726             :                 }
     727             : 
     728             :                 ret = fib_nh_init(net, nexthop_nh, &fib_cfg,
     729             :                                   rtnh->rtnh_hops + 1, extack);
     730             :                 if (ret)
     731             :                         goto errout;
     732             : 
     733             :                 rtnh = rtnh_next(rtnh, &remaining);
     734             :         } endfor_nexthops(fi);
     735             : 
     736             :         ret = -EINVAL;
     737             :         nh = fib_info_nh(fi, 0);
     738             :         if (cfg->fc_oif && nh->fib_nh_oif != cfg->fc_oif) {
     739             :                 NL_SET_ERR_MSG(extack,
     740             :                                "Nexthop device index does not match RTA_OIF");
     741             :                 goto errout;
     742             :         }
     743             :         if (cfg->fc_gw_family) {
     744             :                 if (cfg->fc_gw_family != nh->fib_nh_gw_family ||
     745             :                     (cfg->fc_gw_family == AF_INET &&
     746             :                      nh->fib_nh_gw4 != cfg->fc_gw4) ||
     747             :                     (cfg->fc_gw_family == AF_INET6 &&
     748             :                      ipv6_addr_cmp(&nh->fib_nh_gw6, &cfg->fc_gw6))) {
     749             :                         NL_SET_ERR_MSG(extack,
     750             :                                        "Nexthop gateway does not match RTA_GATEWAY or RTA_VIA");
     751             :                         goto errout;
     752             :                 }
     753             :         }
     754             : #ifdef CONFIG_IP_ROUTE_CLASSID
     755             :         if (cfg->fc_flow && nh->nh_tclassid != cfg->fc_flow) {
     756             :                 NL_SET_ERR_MSG(extack,
     757             :                                "Nexthop class id does not match RTA_FLOW");
     758             :                 goto errout;
     759             :         }
     760             : #endif
     761             :         ret = 0;
     762             : errout:
     763             :         return ret;
     764             : }
     765             : 
     766             : /* only called when fib_nh is integrated into fib_info */
     767             : static void fib_rebalance(struct fib_info *fi)
     768             : {
     769             :         int total;
     770             :         int w;
     771             : 
     772             :         if (fib_info_num_path(fi) < 2)
     773             :                 return;
     774             : 
     775             :         total = 0;
     776             :         for_nexthops(fi) {
     777             :                 if (nh->fib_nh_flags & RTNH_F_DEAD)
     778             :                         continue;
     779             : 
     780             :                 if (ip_ignore_linkdown(nh->fib_nh_dev) &&
     781             :                     nh->fib_nh_flags & RTNH_F_LINKDOWN)
     782             :                         continue;
     783             : 
     784             :                 total += nh->fib_nh_weight;
     785             :         } endfor_nexthops(fi);
     786             : 
     787             :         w = 0;
     788             :         change_nexthops(fi) {
     789             :                 int upper_bound;
     790             : 
     791             :                 if (nexthop_nh->fib_nh_flags & RTNH_F_DEAD) {
     792             :                         upper_bound = -1;
     793             :                 } else if (ip_ignore_linkdown(nexthop_nh->fib_nh_dev) &&
     794             :                            nexthop_nh->fib_nh_flags & RTNH_F_LINKDOWN) {
     795             :                         upper_bound = -1;
     796             :                 } else {
     797             :                         w += nexthop_nh->fib_nh_weight;
     798             :                         upper_bound = DIV_ROUND_CLOSEST_ULL((u64)w << 31,
     799             :                                                             total) - 1;
     800             :                 }
     801             : 
     802             :                 atomic_set(&nexthop_nh->fib_nh_upper_bound, upper_bound);
     803             :         } endfor_nexthops(fi);
     804             : }
     805             : #else /* CONFIG_IP_ROUTE_MULTIPATH */
     806             : 
     807           0 : static int fib_get_nhs(struct fib_info *fi, struct rtnexthop *rtnh,
     808             :                        int remaining, struct fib_config *cfg,
     809             :                        struct netlink_ext_ack *extack)
     810             : {
     811           0 :         NL_SET_ERR_MSG(extack, "Multipath support not enabled in kernel");
     812             : 
     813             :         return -EINVAL;
     814             : }
     815             : 
     816             : #define fib_rebalance(fi) do { } while (0)
     817             : 
     818             : #endif /* CONFIG_IP_ROUTE_MULTIPATH */
     819             : 
     820             : static int fib_encap_match(struct net *net, u16 encap_type,
     821             :                            struct nlattr *encap,
     822             :                            const struct fib_nh *nh,
     823             :                            const struct fib_config *cfg,
     824             :                            struct netlink_ext_ack *extack)
     825             : {
     826             :         struct lwtunnel_state *lwtstate;
     827             :         int ret, result = 0;
     828             : 
     829             :         if (encap_type == LWTUNNEL_ENCAP_NONE)
     830             :                 return 0;
     831             : 
     832             :         ret = lwtunnel_build_state(net, encap_type, encap, AF_INET,
     833             :                                    cfg, &lwtstate, extack);
     834             :         if (!ret) {
     835             :                 result = lwtunnel_cmp_encap(lwtstate, nh->fib_nh_lws);
     836             :                 lwtstate_free(lwtstate);
     837             :         }
     838             : 
     839             :         return result;
     840             : }
     841             : 
     842           0 : int fib_nh_match(struct net *net, struct fib_config *cfg, struct fib_info *fi,
     843             :                  struct netlink_ext_ack *extack)
     844             : {
     845             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
     846             :         struct rtnexthop *rtnh;
     847             :         int remaining;
     848             : #endif
     849             : 
     850           0 :         if (cfg->fc_priority && cfg->fc_priority != fi->fib_priority)
     851             :                 return 1;
     852             : 
     853           0 :         if (cfg->fc_nh_id) {
     854           0 :                 if (fi->nh && cfg->fc_nh_id == fi->nh->id)
     855             :                         return 0;
     856           0 :                 return 1;
     857             :         }
     858             : 
     859           0 :         if (cfg->fc_oif || cfg->fc_gw_family) {
     860           0 :                 struct fib_nh *nh = fib_info_nh(fi, 0);
     861             : 
     862           0 :                 if (cfg->fc_encap) {
     863             :                         if (fib_encap_match(net, cfg->fc_encap_type,
     864             :                                             cfg->fc_encap, nh, cfg, extack))
     865             :                                 return 1;
     866             :                 }
     867             : #ifdef CONFIG_IP_ROUTE_CLASSID
     868             :                 if (cfg->fc_flow &&
     869             :                     cfg->fc_flow != nh->nh_tclassid)
     870             :                         return 1;
     871             : #endif
     872           0 :                 if ((cfg->fc_oif && cfg->fc_oif != nh->fib_nh_oif) ||
     873           0 :                     (cfg->fc_gw_family &&
     874           0 :                      cfg->fc_gw_family != nh->fib_nh_gw_family))
     875             :                         return 1;
     876             : 
     877           0 :                 if (cfg->fc_gw_family == AF_INET &&
     878           0 :                     cfg->fc_gw4 != nh->fib_nh_gw4)
     879             :                         return 1;
     880             : 
     881           0 :                 if (cfg->fc_gw_family == AF_INET6 &&
     882           0 :                     ipv6_addr_cmp(&cfg->fc_gw6, &nh->fib_nh_gw6))
     883             :                         return 1;
     884             : 
     885           0 :                 return 0;
     886             :         }
     887             : 
     888             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
     889             :         if (!cfg->fc_mp)
     890             :                 return 0;
     891             : 
     892             :         rtnh = cfg->fc_mp;
     893             :         remaining = cfg->fc_mp_len;
     894             : 
     895             :         for_nexthops(fi) {
     896             :                 int attrlen;
     897             : 
     898             :                 if (!rtnh_ok(rtnh, remaining))
     899             :                         return -EINVAL;
     900             : 
     901             :                 if (rtnh->rtnh_ifindex && rtnh->rtnh_ifindex != nh->fib_nh_oif)
     902             :                         return 1;
     903             : 
     904             :                 attrlen = rtnh_attrlen(rtnh);
     905             :                 if (attrlen > 0) {
     906             :                         struct nlattr *nla, *nlav, *attrs = rtnh_attrs(rtnh);
     907             : 
     908             :                         nla = nla_find(attrs, attrlen, RTA_GATEWAY);
     909             :                         nlav = nla_find(attrs, attrlen, RTA_VIA);
     910             :                         if (nla && nlav) {
     911             :                                 NL_SET_ERR_MSG(extack,
     912             :                                                "Nexthop configuration can not contain both GATEWAY and VIA");
     913             :                                 return -EINVAL;
     914             :                         }
     915             : 
     916             :                         if (nla) {
     917             :                                 if (nh->fib_nh_gw_family != AF_INET ||
     918             :                                     nla_get_in_addr(nla) != nh->fib_nh_gw4)
     919             :                                         return 1;
     920             :                         } else if (nlav) {
     921             :                                 struct fib_config cfg2;
     922             :                                 int err;
     923             : 
     924             :                                 err = fib_gw_from_via(&cfg2, nlav, extack);
     925             :                                 if (err)
     926             :                                         return err;
     927             : 
     928             :                                 switch (nh->fib_nh_gw_family) {
     929             :                                 case AF_INET:
     930             :                                         if (cfg2.fc_gw_family != AF_INET ||
     931             :                                             cfg2.fc_gw4 != nh->fib_nh_gw4)
     932             :                                                 return 1;
     933             :                                         break;
     934             :                                 case AF_INET6:
     935             :                                         if (cfg2.fc_gw_family != AF_INET6 ||
     936             :                                             ipv6_addr_cmp(&cfg2.fc_gw6,
     937             :                                                           &nh->fib_nh_gw6))
     938             :                                                 return 1;
     939             :                                         break;
     940             :                                 }
     941             :                         }
     942             : 
     943             : #ifdef CONFIG_IP_ROUTE_CLASSID
     944             :                         nla = nla_find(attrs, attrlen, RTA_FLOW);
     945             :                         if (nla && nla_get_u32(nla) != nh->nh_tclassid)
     946             :                                 return 1;
     947             : #endif
     948             :                 }
     949             : 
     950             :                 rtnh = rtnh_next(rtnh, &remaining);
     951             :         } endfor_nexthops(fi);
     952             : #endif
     953             :         return 0;
     954             : }
     955             : 
     956           0 : bool fib_metrics_match(struct fib_config *cfg, struct fib_info *fi)
     957             : {
     958           0 :         struct nlattr *nla;
     959           0 :         int remaining;
     960             : 
     961           0 :         if (!cfg->fc_mx)
     962             :                 return true;
     963             : 
     964           0 :         nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
     965           0 :                 int type = nla_type(nla);
     966           0 :                 u32 fi_val, val;
     967             : 
     968           0 :                 if (!type)
     969           0 :                         continue;
     970           0 :                 if (type > RTAX_MAX)
     971             :                         return false;
     972             : 
     973           0 :                 if (type == RTAX_CC_ALGO) {
     974           0 :                         char tmp[TCP_CA_NAME_MAX];
     975           0 :                         bool ecn_ca = false;
     976             : 
     977           0 :                         nla_strscpy(tmp, nla, sizeof(tmp));
     978           0 :                         val = tcp_ca_get_key_by_name(fi->fib_net, tmp, &ecn_ca);
     979             :                 } else {
     980           0 :                         if (nla_len(nla) != sizeof(u32))
     981             :                                 return false;
     982           0 :                         val = nla_get_u32(nla);
     983             :                 }
     984             : 
     985           0 :                 fi_val = fi->fib_metrics->metrics[type - 1];
     986           0 :                 if (type == RTAX_FEATURES)
     987           0 :                         fi_val &= ~DST_FEATURE_ECN_CA;
     988             : 
     989           0 :                 if (fi_val != val)
     990             :                         return false;
     991             :         }
     992             : 
     993             :         return true;
     994             : }
     995             : 
     996           0 : static int fib_check_nh_v6_gw(struct net *net, struct fib_nh *nh,
     997             :                               u32 table, struct netlink_ext_ack *extack)
     998             : {
     999           0 :         struct fib6_config cfg = {
    1000             :                 .fc_table = table,
    1001           0 :                 .fc_flags = nh->fib_nh_flags | RTF_GATEWAY,
    1002           0 :                 .fc_ifindex = nh->fib_nh_oif,
    1003             :                 .fc_gateway = nh->fib_nh_gw6,
    1004             :         };
    1005           0 :         struct fib6_nh fib6_nh = {};
    1006           0 :         int err;
    1007             : 
    1008           0 :         err = ipv6_stub->fib6_nh_init(net, &fib6_nh, &cfg, GFP_KERNEL, extack);
    1009           0 :         if (!err) {
    1010           0 :                 nh->fib_nh_dev = fib6_nh.fib_nh_dev;
    1011           0 :                 dev_hold(nh->fib_nh_dev);
    1012           0 :                 nh->fib_nh_oif = nh->fib_nh_dev->ifindex;
    1013           0 :                 nh->fib_nh_scope = RT_SCOPE_LINK;
    1014             : 
    1015           0 :                 ipv6_stub->fib6_nh_release(&fib6_nh);
    1016             :         }
    1017             : 
    1018           0 :         return err;
    1019             : }
    1020             : 
    1021             : /*
    1022             :  * Picture
    1023             :  * -------
    1024             :  *
    1025             :  * Semantics of nexthop is very messy by historical reasons.
    1026             :  * We have to take into account, that:
    1027             :  * a) gateway can be actually local interface address,
    1028             :  *    so that gatewayed route is direct.
    1029             :  * b) gateway must be on-link address, possibly
    1030             :  *    described not by an ifaddr, but also by a direct route.
    1031             :  * c) If both gateway and interface are specified, they should not
    1032             :  *    contradict.
    1033             :  * d) If we use tunnel routes, gateway could be not on-link.
    1034             :  *
    1035             :  * Attempt to reconcile all of these (alas, self-contradictory) conditions
    1036             :  * results in pretty ugly and hairy code with obscure logic.
    1037             :  *
    1038             :  * I chose to generalized it instead, so that the size
    1039             :  * of code does not increase practically, but it becomes
    1040             :  * much more general.
    1041             :  * Every prefix is assigned a "scope" value: "host" is local address,
    1042             :  * "link" is direct route,
    1043             :  * [ ... "site" ... "interior" ... ]
    1044             :  * and "universe" is true gateway route with global meaning.
    1045             :  *
    1046             :  * Every prefix refers to a set of "nexthop"s (gw, oif),
    1047             :  * where gw must have narrower scope. This recursion stops
    1048             :  * when gw has LOCAL scope or if "nexthop" is declared ONLINK,
    1049             :  * which means that gw is forced to be on link.
    1050             :  *
    1051             :  * Code is still hairy, but now it is apparently logically
    1052             :  * consistent and very flexible. F.e. as by-product it allows
    1053             :  * to co-exists in peace independent exterior and interior
    1054             :  * routing processes.
    1055             :  *
    1056             :  * Normally it looks as following.
    1057             :  *
    1058             :  * {universe prefix}  -> (gw, oif) [scope link]
    1059             :  *                |
    1060             :  *                |-> {link prefix} -> (gw, oif) [scope local]
    1061             :  *                                      |
    1062             :  *                                      |-> {local prefix} (terminal node)
    1063             :  */
    1064           1 : static int fib_check_nh_v4_gw(struct net *net, struct fib_nh *nh, u32 table,
    1065             :                               u8 scope, struct netlink_ext_ack *extack)
    1066             : {
    1067           1 :         struct net_device *dev;
    1068           1 :         struct fib_result res;
    1069           1 :         int err = 0;
    1070             : 
    1071           1 :         if (nh->fib_nh_flags & RTNH_F_ONLINK) {
    1072           0 :                 unsigned int addr_type;
    1073             : 
    1074           0 :                 if (scope >= RT_SCOPE_LINK) {
    1075           0 :                         NL_SET_ERR_MSG(extack, "Nexthop has invalid scope");
    1076           0 :                         return -EINVAL;
    1077             :                 }
    1078           0 :                 dev = __dev_get_by_index(net, nh->fib_nh_oif);
    1079           0 :                 if (!dev) {
    1080           0 :                         NL_SET_ERR_MSG(extack, "Nexthop device required for onlink");
    1081           0 :                         return -ENODEV;
    1082             :                 }
    1083           0 :                 if (!(dev->flags & IFF_UP)) {
    1084           0 :                         NL_SET_ERR_MSG(extack, "Nexthop device is not up");
    1085           0 :                         return -ENETDOWN;
    1086             :                 }
    1087           0 :                 addr_type = inet_addr_type_dev_table(net, dev, nh->fib_nh_gw4);
    1088           0 :                 if (addr_type != RTN_UNICAST) {
    1089           0 :                         NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
    1090           0 :                         return -EINVAL;
    1091             :                 }
    1092           0 :                 if (!netif_carrier_ok(dev))
    1093           0 :                         nh->fib_nh_flags |= RTNH_F_LINKDOWN;
    1094           0 :                 nh->fib_nh_dev = dev;
    1095           0 :                 dev_hold(dev);
    1096           0 :                 nh->fib_nh_scope = RT_SCOPE_LINK;
    1097           0 :                 return 0;
    1098             :         }
    1099           1 :         rcu_read_lock();
    1100             :         {
    1101           1 :                 struct fib_table *tbl = NULL;
    1102           1 :                 struct flowi4 fl4 = {
    1103           1 :                         .daddr = nh->fib_nh_gw4,
    1104           1 :                         .flowi4_scope = scope + 1,
    1105           1 :                         .flowi4_oif = nh->fib_nh_oif,
    1106             :                         .flowi4_iif = LOOPBACK_IFINDEX,
    1107             :                 };
    1108             : 
    1109             :                 /* It is not necessary, but requires a bit of thinking */
    1110           1 :                 if (fl4.flowi4_scope < RT_SCOPE_LINK)
    1111           1 :                         fl4.flowi4_scope = RT_SCOPE_LINK;
    1112             : 
    1113           1 :                 if (table && table != RT_TABLE_MAIN)
    1114           0 :                         tbl = fib_get_table(net, table);
    1115             : 
    1116           0 :                 if (tbl)
    1117           0 :                         err = fib_table_lookup(tbl, &fl4, &res,
    1118             :                                                FIB_LOOKUP_IGNORE_LINKSTATE |
    1119             :                                                FIB_LOOKUP_NOREF);
    1120             : 
    1121             :                 /* on error or if no table given do full lookup. This
    1122             :                  * is needed for example when nexthops are in the local
    1123             :                  * table rather than the given table
    1124             :                  */
    1125           1 :                 if (!tbl || err) {
    1126           1 :                         err = fib_lookup(net, &fl4, &res,
    1127             :                                          FIB_LOOKUP_IGNORE_LINKSTATE);
    1128             :                 }
    1129             : 
    1130           1 :                 if (err) {
    1131           0 :                         NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
    1132           0 :                         goto out;
    1133             :                 }
    1134             :         }
    1135             : 
    1136           1 :         err = -EINVAL;
    1137           1 :         if (res.type != RTN_UNICAST && res.type != RTN_LOCAL) {
    1138           0 :                 NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
    1139           0 :                 goto out;
    1140             :         }
    1141           1 :         nh->fib_nh_scope = res.scope;
    1142           1 :         nh->fib_nh_oif = FIB_RES_OIF(res);
    1143           1 :         nh->fib_nh_dev = dev = FIB_RES_DEV(res);
    1144           1 :         if (!dev) {
    1145           0 :                 NL_SET_ERR_MSG(extack,
    1146             :                                "No egress device for nexthop gateway");
    1147           0 :                 goto out;
    1148             :         }
    1149           1 :         dev_hold(dev);
    1150           1 :         if (!netif_carrier_ok(dev))
    1151           0 :                 nh->fib_nh_flags |= RTNH_F_LINKDOWN;
    1152           1 :         err = (dev->flags & IFF_UP) ? 0 : -ENETDOWN;
    1153           1 : out:
    1154           1 :         rcu_read_unlock();
    1155           1 :         return err;
    1156             : }
    1157             : 
    1158           7 : static int fib_check_nh_nongw(struct net *net, struct fib_nh *nh,
    1159             :                               struct netlink_ext_ack *extack)
    1160             : {
    1161           7 :         struct in_device *in_dev;
    1162           7 :         int err;
    1163             : 
    1164           7 :         if (nh->fib_nh_flags & (RTNH_F_PERVASIVE | RTNH_F_ONLINK)) {
    1165           0 :                 NL_SET_ERR_MSG(extack,
    1166             :                                "Invalid flags for nexthop - PERVASIVE and ONLINK can not be set");
    1167           0 :                 return -EINVAL;
    1168             :         }
    1169             : 
    1170           7 :         rcu_read_lock();
    1171             : 
    1172           7 :         err = -ENODEV;
    1173           7 :         in_dev = inetdev_by_index(net, nh->fib_nh_oif);
    1174           7 :         if (!in_dev)
    1175           0 :                 goto out;
    1176           7 :         err = -ENETDOWN;
    1177           7 :         if (!(in_dev->dev->flags & IFF_UP)) {
    1178           0 :                 NL_SET_ERR_MSG(extack, "Device for nexthop is not up");
    1179           0 :                 goto out;
    1180             :         }
    1181             : 
    1182           7 :         nh->fib_nh_dev = in_dev->dev;
    1183           7 :         dev_hold(nh->fib_nh_dev);
    1184           7 :         nh->fib_nh_scope = RT_SCOPE_HOST;
    1185           7 :         if (!netif_carrier_ok(nh->fib_nh_dev))
    1186           0 :                 nh->fib_nh_flags |= RTNH_F_LINKDOWN;
    1187             :         err = 0;
    1188           7 : out:
    1189           7 :         rcu_read_unlock();
    1190           7 :         return err;
    1191             : }
    1192             : 
    1193           8 : int fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope,
    1194             :                  struct netlink_ext_ack *extack)
    1195             : {
    1196           8 :         int err;
    1197             : 
    1198           8 :         if (nh->fib_nh_gw_family == AF_INET)
    1199           1 :                 err = fib_check_nh_v4_gw(net, nh, table, scope, extack);
    1200           7 :         else if (nh->fib_nh_gw_family == AF_INET6)
    1201           0 :                 err = fib_check_nh_v6_gw(net, nh, table, extack);
    1202             :         else
    1203           7 :                 err = fib_check_nh_nongw(net, nh, extack);
    1204             : 
    1205           8 :         return err;
    1206             : }
    1207             : 
    1208           5 : static inline unsigned int fib_laddr_hashfn(__be32 val)
    1209             : {
    1210           5 :         unsigned int mask = (fib_info_hash_size - 1);
    1211             : 
    1212           5 :         return ((__force u32)val ^
    1213           5 :                 ((__force u32)val >> 7) ^
    1214           5 :                 ((__force u32)val >> 14)) & mask;
    1215             : }
    1216             : 
    1217           2 : static struct hlist_head *fib_info_hash_alloc(int bytes)
    1218             : {
    1219           2 :         if (bytes <= PAGE_SIZE)
    1220           2 :                 return kzalloc(bytes, GFP_KERNEL);
    1221             :         else
    1222           0 :                 return (struct hlist_head *)
    1223           0 :                         __get_free_pages(GFP_KERNEL | __GFP_ZERO,
    1224           0 :                                          get_order(bytes));
    1225             : }
    1226             : 
    1227           2 : static void fib_info_hash_free(struct hlist_head *hash, int bytes)
    1228             : {
    1229           2 :         if (!hash)
    1230             :                 return;
    1231             : 
    1232           0 :         if (bytes <= PAGE_SIZE)
    1233           0 :                 kfree(hash);
    1234             :         else
    1235           0 :                 free_pages((unsigned long) hash, get_order(bytes));
    1236             : }
    1237             : 
    1238           1 : static void fib_info_hash_move(struct hlist_head *new_info_hash,
    1239             :                                struct hlist_head *new_laddrhash,
    1240             :                                unsigned int new_size)
    1241             : {
    1242           1 :         struct hlist_head *old_info_hash, *old_laddrhash;
    1243           1 :         unsigned int old_size = fib_info_hash_size;
    1244           1 :         unsigned int i, bytes;
    1245             : 
    1246           1 :         spin_lock_bh(&fib_info_lock);
    1247           1 :         old_info_hash = fib_info_hash;
    1248           1 :         old_laddrhash = fib_info_laddrhash;
    1249           1 :         fib_info_hash_size = new_size;
    1250             : 
    1251           1 :         for (i = 0; i < old_size; i++) {
    1252           0 :                 struct hlist_head *head = &fib_info_hash[i];
    1253           0 :                 struct hlist_node *n;
    1254           0 :                 struct fib_info *fi;
    1255             : 
    1256           0 :                 hlist_for_each_entry_safe(fi, n, head, fib_hash) {
    1257           0 :                         struct hlist_head *dest;
    1258           0 :                         unsigned int new_hash;
    1259             : 
    1260           0 :                         new_hash = fib_info_hashfn(fi);
    1261           0 :                         dest = &new_info_hash[new_hash];
    1262           0 :                         hlist_add_head(&fi->fib_hash, dest);
    1263             :                 }
    1264             :         }
    1265           1 :         fib_info_hash = new_info_hash;
    1266             : 
    1267           1 :         for (i = 0; i < old_size; i++) {
    1268           0 :                 struct hlist_head *lhead = &fib_info_laddrhash[i];
    1269           0 :                 struct hlist_node *n;
    1270           0 :                 struct fib_info *fi;
    1271             : 
    1272           0 :                 hlist_for_each_entry_safe(fi, n, lhead, fib_lhash) {
    1273           0 :                         struct hlist_head *ldest;
    1274           0 :                         unsigned int new_hash;
    1275             : 
    1276           0 :                         new_hash = fib_laddr_hashfn(fi->fib_prefsrc);
    1277           0 :                         ldest = &new_laddrhash[new_hash];
    1278           0 :                         hlist_add_head(&fi->fib_lhash, ldest);
    1279             :                 }
    1280             :         }
    1281           1 :         fib_info_laddrhash = new_laddrhash;
    1282             : 
    1283           1 :         spin_unlock_bh(&fib_info_lock);
    1284             : 
    1285           1 :         bytes = old_size * sizeof(struct hlist_head *);
    1286           1 :         fib_info_hash_free(old_info_hash, bytes);
    1287           1 :         fib_info_hash_free(old_laddrhash, bytes);
    1288           1 : }
    1289             : 
    1290          12 : __be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
    1291             :                                  unsigned char scope)
    1292             : {
    1293          12 :         struct fib_nh *nh;
    1294             : 
    1295          12 :         if (nhc->nhc_family != AF_INET)
    1296           0 :                 return inet_select_addr(nhc->nhc_dev, 0, scope);
    1297             : 
    1298          12 :         nh = container_of(nhc, struct fib_nh, nh_common);
    1299          12 :         nh->nh_saddr = inet_select_addr(nh->fib_nh_dev, nh->fib_nh_gw4, scope);
    1300          12 :         nh->nh_saddr_genid = atomic_read(&net->ipv4.dev_addr_genid);
    1301             : 
    1302          12 :         return nh->nh_saddr;
    1303             : }
    1304             : 
    1305           7 : __be32 fib_result_prefsrc(struct net *net, struct fib_result *res)
    1306             : {
    1307           7 :         struct fib_nh_common *nhc = res->nhc;
    1308             : 
    1309           7 :         if (res->fi->fib_prefsrc)
    1310             :                 return res->fi->fib_prefsrc;
    1311             : 
    1312           0 :         if (nhc->nhc_family == AF_INET) {
    1313           0 :                 struct fib_nh *nh;
    1314             : 
    1315           0 :                 nh = container_of(nhc, struct fib_nh, nh_common);
    1316           0 :                 if (nh->nh_saddr_genid == atomic_read(&net->ipv4.dev_addr_genid))
    1317           0 :                         return nh->nh_saddr;
    1318             :         }
    1319             : 
    1320           0 :         return fib_info_update_nhc_saddr(net, nhc, res->fi->fib_scope);
    1321             : }
    1322             : 
    1323          10 : static bool fib_valid_prefsrc(struct fib_config *cfg, __be32 fib_prefsrc)
    1324             : {
    1325          10 :         if (cfg->fc_type != RTN_LOCAL || !cfg->fc_dst ||
    1326             :             fib_prefsrc != cfg->fc_dst) {
    1327           7 :                 u32 tb_id = cfg->fc_table;
    1328           7 :                 int rc;
    1329             : 
    1330           7 :                 if (tb_id == RT_TABLE_MAIN)
    1331           1 :                         tb_id = RT_TABLE_LOCAL;
    1332             : 
    1333           7 :                 rc = inet_addr_type_table(cfg->fc_nlinfo.nl_net,
    1334             :                                           fib_prefsrc, tb_id);
    1335             : 
    1336           7 :                 if (rc != RTN_LOCAL && tb_id != RT_TABLE_LOCAL) {
    1337           0 :                         rc = inet_addr_type_table(cfg->fc_nlinfo.nl_net,
    1338             :                                                   fib_prefsrc, RT_TABLE_LOCAL);
    1339             :                 }
    1340             : 
    1341           7 :                 if (rc != RTN_LOCAL)
    1342           0 :                         return false;
    1343             :         }
    1344             :         return true;
    1345             : }
    1346             : 
    1347          12 : struct fib_info *fib_create_info(struct fib_config *cfg,
    1348             :                                  struct netlink_ext_ack *extack)
    1349             : {
    1350          12 :         int err;
    1351          12 :         struct fib_info *fi = NULL;
    1352          12 :         struct nexthop *nh = NULL;
    1353          12 :         struct fib_info *ofi;
    1354          12 :         int nhs = 1;
    1355          12 :         struct net *net = cfg->fc_nlinfo.nl_net;
    1356             : 
    1357          12 :         if (cfg->fc_type > RTN_MAX)
    1358           0 :                 goto err_inval;
    1359             : 
    1360             :         /* Fast check to catch the most weird cases */
    1361          12 :         if (fib_props[cfg->fc_type].scope > cfg->fc_scope) {
    1362           0 :                 NL_SET_ERR_MSG(extack, "Invalid scope");
    1363           0 :                 goto err_inval;
    1364             :         }
    1365             : 
    1366          12 :         if (cfg->fc_flags & (RTNH_F_DEAD | RTNH_F_LINKDOWN)) {
    1367           0 :                 NL_SET_ERR_MSG(extack,
    1368             :                                "Invalid rtm_flags - can not contain DEAD or LINKDOWN");
    1369           0 :                 goto err_inval;
    1370             :         }
    1371             : 
    1372          12 :         if (cfg->fc_nh_id) {
    1373           0 :                 if (!cfg->fc_mx) {
    1374           0 :                         fi = fib_find_info_nh(net, cfg);
    1375           0 :                         if (fi) {
    1376           0 :                                 fi->fib_treeref++;
    1377           0 :                                 return fi;
    1378             :                         }
    1379             :                 }
    1380             : 
    1381           0 :                 nh = nexthop_find_by_id(net, cfg->fc_nh_id);
    1382           0 :                 if (!nh) {
    1383           0 :                         NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
    1384           0 :                         goto err_inval;
    1385             :                 }
    1386             :                 nhs = 0;
    1387             :         }
    1388             : 
    1389             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
    1390             :         if (cfg->fc_mp) {
    1391             :                 nhs = fib_count_nexthops(cfg->fc_mp, cfg->fc_mp_len, extack);
    1392             :                 if (nhs == 0)
    1393             :                         goto err_inval;
    1394             :         }
    1395             : #endif
    1396             : 
    1397          12 :         err = -ENOBUFS;
    1398          12 :         if (fib_info_cnt >= fib_info_hash_size) {
    1399           1 :                 unsigned int new_size = fib_info_hash_size << 1;
    1400           1 :                 struct hlist_head *new_info_hash;
    1401           1 :                 struct hlist_head *new_laddrhash;
    1402           1 :                 unsigned int bytes;
    1403             : 
    1404           1 :                 if (!new_size)
    1405           1 :                         new_size = 16;
    1406           1 :                 bytes = new_size * sizeof(struct hlist_head *);
    1407           1 :                 new_info_hash = fib_info_hash_alloc(bytes);
    1408           1 :                 new_laddrhash = fib_info_hash_alloc(bytes);
    1409           1 :                 if (!new_info_hash || !new_laddrhash) {
    1410           0 :                         fib_info_hash_free(new_info_hash, bytes);
    1411           0 :                         fib_info_hash_free(new_laddrhash, bytes);
    1412             :                 } else
    1413           1 :                         fib_info_hash_move(new_info_hash, new_laddrhash, new_size);
    1414             : 
    1415           1 :                 if (!fib_info_hash_size)
    1416           0 :                         goto failure;
    1417             :         }
    1418             : 
    1419          12 :         fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
    1420          12 :         if (!fi)
    1421           0 :                 goto failure;
    1422          12 :         fi->fib_metrics = ip_fib_metrics_init(fi->fib_net, cfg->fc_mx,
    1423             :                                               cfg->fc_mx_len, extack);
    1424          12 :         if (IS_ERR(fi->fib_metrics)) {
    1425           0 :                 err = PTR_ERR(fi->fib_metrics);
    1426           0 :                 kfree(fi);
    1427           0 :                 return ERR_PTR(err);
    1428             :         }
    1429             : 
    1430          12 :         fib_info_cnt++;
    1431          12 :         fi->fib_net = net;
    1432          12 :         fi->fib_protocol = cfg->fc_protocol;
    1433          12 :         fi->fib_scope = cfg->fc_scope;
    1434          12 :         fi->fib_flags = cfg->fc_flags;
    1435          12 :         fi->fib_priority = cfg->fc_priority;
    1436          12 :         fi->fib_prefsrc = cfg->fc_prefsrc;
    1437          12 :         fi->fib_type = cfg->fc_type;
    1438          12 :         fi->fib_tb_id = cfg->fc_table;
    1439             : 
    1440          12 :         fi->fib_nhs = nhs;
    1441          12 :         if (nh) {
    1442           0 :                 if (!nexthop_get(nh)) {
    1443           0 :                         NL_SET_ERR_MSG(extack, "Nexthop has been deleted");
    1444             :                         err = -EINVAL;
    1445             :                 } else {
    1446           0 :                         err = 0;
    1447           0 :                         fi->nh = nh;
    1448             :                 }
    1449             :         } else {
    1450          24 :                 change_nexthops(fi) {
    1451          12 :                         nexthop_nh->nh_parent = fi;
    1452             :                 } endfor_nexthops(fi)
    1453             : 
    1454          12 :                 if (cfg->fc_mp)
    1455           0 :                         err = fib_get_nhs(fi, cfg->fc_mp, cfg->fc_mp_len, cfg,
    1456             :                                           extack);
    1457             :                 else
    1458          12 :                         err = fib_nh_init(net, fi->fib_nh, cfg, 1, extack);
    1459             :         }
    1460             : 
    1461          12 :         if (err != 0)
    1462           0 :                 goto failure;
    1463             : 
    1464          12 :         if (fib_props[cfg->fc_type].error) {
    1465           0 :                 if (cfg->fc_gw_family || cfg->fc_oif || cfg->fc_mp) {
    1466           0 :                         NL_SET_ERR_MSG(extack,
    1467             :                                        "Gateway, device and multipath can not be specified for this route type");
    1468           0 :                         goto err_inval;
    1469             :                 }
    1470           0 :                 goto link_it;
    1471             :         } else {
    1472          12 :                 switch (cfg->fc_type) {
    1473             :                 case RTN_UNICAST:
    1474             :                 case RTN_LOCAL:
    1475             :                 case RTN_BROADCAST:
    1476             :                 case RTN_ANYCAST:
    1477             :                 case RTN_MULTICAST:
    1478          12 :                         break;
    1479           0 :                 default:
    1480           0 :                         NL_SET_ERR_MSG(extack, "Invalid route type");
    1481           0 :                         goto err_inval;
    1482             :                 }
    1483             :         }
    1484             : 
    1485          12 :         if (cfg->fc_scope > RT_SCOPE_HOST) {
    1486           0 :                 NL_SET_ERR_MSG(extack, "Invalid scope");
    1487           0 :                 goto err_inval;
    1488             :         }
    1489             : 
    1490          12 :         if (fi->nh) {
    1491           0 :                 err = fib_check_nexthop(fi->nh, cfg->fc_scope, extack);
    1492           0 :                 if (err)
    1493           0 :                         goto failure;
    1494          12 :         } else if (cfg->fc_scope == RT_SCOPE_HOST) {
    1495           4 :                 struct fib_nh *nh = fi->fib_nh;
    1496             : 
    1497             :                 /* Local address is added. */
    1498           4 :                 if (nhs != 1) {
    1499           0 :                         NL_SET_ERR_MSG(extack,
    1500             :                                        "Route with host scope can not have multiple nexthops");
    1501           0 :                         goto err_inval;
    1502             :                 }
    1503           4 :                 if (nh->fib_nh_gw_family) {
    1504           0 :                         NL_SET_ERR_MSG(extack,
    1505             :                                        "Route with host scope can not have a gateway");
    1506           0 :                         goto err_inval;
    1507             :                 }
    1508           4 :                 nh->fib_nh_scope = RT_SCOPE_NOWHERE;
    1509           4 :                 nh->fib_nh_dev = dev_get_by_index(net, nh->fib_nh_oif);
    1510           4 :                 err = -ENODEV;
    1511           4 :                 if (!nh->fib_nh_dev)
    1512           0 :                         goto failure;
    1513             :         } else {
    1514           8 :                 int linkdown = 0;
    1515             : 
    1516          16 :                 change_nexthops(fi) {
    1517          16 :                         err = fib_check_nh(cfg->fc_nlinfo.nl_net, nexthop_nh,
    1518           8 :                                            cfg->fc_table, cfg->fc_scope,
    1519             :                                            extack);
    1520           8 :                         if (err != 0)
    1521           0 :                                 goto failure;
    1522           8 :                         if (nexthop_nh->fib_nh_flags & RTNH_F_LINKDOWN)
    1523           0 :                                 linkdown++;
    1524             :                 } endfor_nexthops(fi)
    1525           8 :                 if (linkdown == fi->fib_nhs)
    1526           0 :                         fi->fib_flags |= RTNH_F_LINKDOWN;
    1527             :         }
    1528             : 
    1529          12 :         if (fi->fib_prefsrc && !fib_valid_prefsrc(cfg, fi->fib_prefsrc)) {
    1530           0 :                 NL_SET_ERR_MSG(extack, "Invalid prefsrc address");
    1531           0 :                 goto err_inval;
    1532             :         }
    1533             : 
    1534          12 :         if (!fi->nh) {
    1535          24 :                 change_nexthops(fi) {
    1536          12 :                         fib_info_update_nhc_saddr(net, &nexthop_nh->nh_common,
    1537          12 :                                                   fi->fib_scope);
    1538          12 :                         if (nexthop_nh->fib_nh_gw_family == AF_INET6)
    1539           0 :                                 fi->fib_nh_is_v6 = true;
    1540             :                 } endfor_nexthops(fi)
    1541             : 
    1542          12 :                 fib_rebalance(fi);
    1543             :         }
    1544             : 
    1545          12 : link_it:
    1546          12 :         ofi = fib_find_info(fi);
    1547          12 :         if (ofi) {
    1548           5 :                 fi->fib_dead = 1;
    1549           5 :                 free_fib_info(fi);
    1550           5 :                 ofi->fib_treeref++;
    1551           5 :                 return ofi;
    1552             :         }
    1553             : 
    1554           7 :         fi->fib_treeref++;
    1555           7 :         refcount_set(&fi->fib_clntref, 1);
    1556           7 :         spin_lock_bh(&fib_info_lock);
    1557          14 :         hlist_add_head(&fi->fib_hash,
    1558           7 :                        &fib_info_hash[fib_info_hashfn(fi)]);
    1559           7 :         if (fi->fib_prefsrc) {
    1560           5 :                 struct hlist_head *head;
    1561             : 
    1562           5 :                 head = &fib_info_laddrhash[fib_laddr_hashfn(fi->fib_prefsrc)];
    1563           5 :                 hlist_add_head(&fi->fib_lhash, head);
    1564             :         }
    1565           7 :         if (fi->nh) {
    1566           0 :                 list_add(&fi->nh_list, &nh->fi_list);
    1567             :         } else {
    1568          14 :                 change_nexthops(fi) {
    1569           7 :                         struct hlist_head *head;
    1570           7 :                         unsigned int hash;
    1571             : 
    1572           7 :                         if (!nexthop_nh->fib_nh_dev)
    1573           0 :                                 continue;
    1574           7 :                         hash = fib_devindex_hashfn(nexthop_nh->fib_nh_dev->ifindex);
    1575           7 :                         head = &fib_info_devhash[hash];
    1576          21 :                         hlist_add_head(&nexthop_nh->nh_hash, head);
    1577             :                 } endfor_nexthops(fi)
    1578             :         }
    1579           7 :         spin_unlock_bh(&fib_info_lock);
    1580           7 :         return fi;
    1581             : 
    1582             : err_inval:
    1583           0 :         err = -EINVAL;
    1584             : 
    1585           0 : failure:
    1586           0 :         if (fi) {
    1587           0 :                 fi->fib_dead = 1;
    1588           0 :                 free_fib_info(fi);
    1589             :         }
    1590             : 
    1591           0 :         return ERR_PTR(err);
    1592             : }
    1593             : 
    1594          19 : int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nhc,
    1595             :                      u8 rt_family, unsigned char *flags, bool skip_oif)
    1596             : {
    1597          19 :         if (nhc->nhc_flags & RTNH_F_DEAD)
    1598           0 :                 *flags |= RTNH_F_DEAD;
    1599             : 
    1600          19 :         if (nhc->nhc_flags & RTNH_F_LINKDOWN) {
    1601           0 :                 *flags |= RTNH_F_LINKDOWN;
    1602             : 
    1603           0 :                 rcu_read_lock();
    1604           0 :                 switch (nhc->nhc_family) {
    1605           0 :                 case AF_INET:
    1606           0 :                         if (ip_ignore_linkdown(nhc->nhc_dev))
    1607           0 :                                 *flags |= RTNH_F_DEAD;
    1608             :                         break;
    1609           0 :                 case AF_INET6:
    1610           0 :                         if (ip6_ignore_linkdown(nhc->nhc_dev))
    1611           0 :                                 *flags |= RTNH_F_DEAD;
    1612             :                         break;
    1613             :                 }
    1614           0 :                 rcu_read_unlock();
    1615             :         }
    1616             : 
    1617          19 :         switch (nhc->nhc_gw_family) {
    1618           2 :         case AF_INET:
    1619           2 :                 if (nla_put_in_addr(skb, RTA_GATEWAY, nhc->nhc_gw.ipv4))
    1620           0 :                         goto nla_put_failure;
    1621             :                 break;
    1622           0 :         case AF_INET6:
    1623             :                 /* if gateway family does not match nexthop family
    1624             :                  * gateway is encoded as RTA_VIA
    1625             :                  */
    1626           0 :                 if (rt_family != nhc->nhc_gw_family) {
    1627           0 :                         int alen = sizeof(struct in6_addr);
    1628           0 :                         struct nlattr *nla;
    1629           0 :                         struct rtvia *via;
    1630             : 
    1631           0 :                         nla = nla_reserve(skb, RTA_VIA, alen + 2);
    1632           0 :                         if (!nla)
    1633           0 :                                 goto nla_put_failure;
    1634             : 
    1635           0 :                         via = nla_data(nla);
    1636           0 :                         via->rtvia_family = AF_INET6;
    1637           0 :                         memcpy(via->rtvia_addr, &nhc->nhc_gw.ipv6, alen);
    1638           0 :                 } else if (nla_put_in6_addr(skb, RTA_GATEWAY,
    1639             :                                             &nhc->nhc_gw.ipv6) < 0) {
    1640           0 :                         goto nla_put_failure;
    1641             :                 }
    1642             :                 break;
    1643             :         }
    1644             : 
    1645          19 :         *flags |= (nhc->nhc_flags &
    1646             :                    (RTNH_F_ONLINK | RTNH_F_OFFLOAD | RTNH_F_TRAP));
    1647             : 
    1648          19 :         if (!skip_oif && nhc->nhc_dev &&
    1649          19 :             nla_put_u32(skb, RTA_OIF, nhc->nhc_dev->ifindex))
    1650           0 :                 goto nla_put_failure;
    1651             : 
    1652          19 :         if (nhc->nhc_lwtstate &&
    1653          19 :             lwtunnel_fill_encap(skb, nhc->nhc_lwtstate,
    1654             :                                 RTA_ENCAP, RTA_ENCAP_TYPE) < 0)
    1655             :                 goto nla_put_failure;
    1656             : 
    1657          19 :         return 0;
    1658             : 
    1659             : nla_put_failure:
    1660             :         return -EMSGSIZE;
    1661             : }
    1662             : EXPORT_SYMBOL_GPL(fib_nexthop_info);
    1663             : 
    1664             : #if IS_ENABLED(CONFIG_IP_ROUTE_MULTIPATH) || IS_ENABLED(CONFIG_IPV6)
    1665             : int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nhc,
    1666             :                     int nh_weight, u8 rt_family)
    1667             : {
    1668             :         const struct net_device *dev = nhc->nhc_dev;
    1669             :         struct rtnexthop *rtnh;
    1670             :         unsigned char flags = 0;
    1671             : 
    1672             :         rtnh = nla_reserve_nohdr(skb, sizeof(*rtnh));
    1673             :         if (!rtnh)
    1674             :                 goto nla_put_failure;
    1675             : 
    1676             :         rtnh->rtnh_hops = nh_weight - 1;
    1677             :         rtnh->rtnh_ifindex = dev ? dev->ifindex : 0;
    1678             : 
    1679             :         if (fib_nexthop_info(skb, nhc, rt_family, &flags, true) < 0)
    1680             :                 goto nla_put_failure;
    1681             : 
    1682             :         rtnh->rtnh_flags = flags;
    1683             : 
    1684             :         /* length of rtnetlink header + attributes */
    1685             :         rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *)rtnh;
    1686             : 
    1687             :         return 0;
    1688             : 
    1689             : nla_put_failure:
    1690             :         return -EMSGSIZE;
    1691             : }
    1692             : EXPORT_SYMBOL_GPL(fib_add_nexthop);
    1693             : #endif
    1694             : 
    1695             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
    1696             : static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
    1697             : {
    1698             :         struct nlattr *mp;
    1699             : 
    1700             :         mp = nla_nest_start_noflag(skb, RTA_MULTIPATH);
    1701             :         if (!mp)
    1702             :                 goto nla_put_failure;
    1703             : 
    1704             :         if (unlikely(fi->nh)) {
    1705             :                 if (nexthop_mpath_fill_node(skb, fi->nh, AF_INET) < 0)
    1706             :                         goto nla_put_failure;
    1707             :                 goto mp_end;
    1708             :         }
    1709             : 
    1710             :         for_nexthops(fi) {
    1711             :                 if (fib_add_nexthop(skb, &nh->nh_common, nh->fib_nh_weight,
    1712             :                                     AF_INET) < 0)
    1713             :                         goto nla_put_failure;
    1714             : #ifdef CONFIG_IP_ROUTE_CLASSID
    1715             :                 if (nh->nh_tclassid &&
    1716             :                     nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
    1717             :                         goto nla_put_failure;
    1718             : #endif
    1719             :         } endfor_nexthops(fi);
    1720             : 
    1721             : mp_end:
    1722             :         nla_nest_end(skb, mp);
    1723             : 
    1724             :         return 0;
    1725             : 
    1726             : nla_put_failure:
    1727             :         return -EMSGSIZE;
    1728             : }
    1729             : #else
    1730             : static int fib_add_multipath(struct sk_buff *skb, struct fib_info *fi)
    1731             : {
    1732             :         return 0;
    1733             : }
    1734             : #endif
    1735             : 
    1736          19 : int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
    1737             :                   const struct fib_rt_info *fri, unsigned int flags)
    1738             : {
    1739          19 :         unsigned int nhs = fib_info_num_path(fri->fi);
    1740          19 :         struct fib_info *fi = fri->fi;
    1741          19 :         u32 tb_id = fri->tb_id;
    1742          19 :         struct nlmsghdr *nlh;
    1743          19 :         struct rtmsg *rtm;
    1744             : 
    1745          19 :         nlh = nlmsg_put(skb, portid, seq, event, sizeof(*rtm), flags);
    1746          19 :         if (!nlh)
    1747             :                 return -EMSGSIZE;
    1748             : 
    1749          19 :         rtm = nlmsg_data(nlh);
    1750          19 :         rtm->rtm_family = AF_INET;
    1751          19 :         rtm->rtm_dst_len = fri->dst_len;
    1752          19 :         rtm->rtm_src_len = 0;
    1753          19 :         rtm->rtm_tos = fri->tos;
    1754          19 :         if (tb_id < 256)
    1755          19 :                 rtm->rtm_table = tb_id;
    1756             :         else
    1757           0 :                 rtm->rtm_table = RT_TABLE_COMPAT;
    1758          19 :         if (nla_put_u32(skb, RTA_TABLE, tb_id))
    1759           0 :                 goto nla_put_failure;
    1760          19 :         rtm->rtm_type = fri->type;
    1761          19 :         rtm->rtm_flags = fi->fib_flags;
    1762          19 :         rtm->rtm_scope = fi->fib_scope;
    1763          19 :         rtm->rtm_protocol = fi->fib_protocol;
    1764             : 
    1765          19 :         if (rtm->rtm_dst_len &&
    1766          17 :             nla_put_in_addr(skb, RTA_DST, fri->dst))
    1767           0 :                 goto nla_put_failure;
    1768          19 :         if (fi->fib_priority &&
    1769           1 :             nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority))
    1770           0 :                 goto nla_put_failure;
    1771          19 :         if (rtnetlink_put_metrics(skb, fi->fib_metrics->metrics) < 0)
    1772           0 :                 goto nla_put_failure;
    1773             : 
    1774          19 :         if (fi->fib_prefsrc &&
    1775          16 :             nla_put_in_addr(skb, RTA_PREFSRC, fi->fib_prefsrc))
    1776           0 :                 goto nla_put_failure;
    1777             : 
    1778          19 :         if (fi->nh) {
    1779           0 :                 if (nla_put_u32(skb, RTA_NH_ID, fi->nh->id))
    1780           0 :                         goto nla_put_failure;
    1781           0 :                 if (nexthop_is_blackhole(fi->nh))
    1782           0 :                         rtm->rtm_type = RTN_BLACKHOLE;
    1783           0 :                 if (!fi->fib_net->ipv4.sysctl_nexthop_compat_mode)
    1784           0 :                         goto offload;
    1785             :         }
    1786             : 
    1787          19 :         if (nhs == 1) {
    1788          19 :                 const struct fib_nh_common *nhc = fib_info_nhc(fi, 0);
    1789          19 :                 unsigned char flags = 0;
    1790             : 
    1791          19 :                 if (fib_nexthop_info(skb, nhc, AF_INET, &flags, false) < 0)
    1792           0 :                         goto nla_put_failure;
    1793             : 
    1794          19 :                 rtm->rtm_flags = flags;
    1795             : #ifdef CONFIG_IP_ROUTE_CLASSID
    1796             :                 if (nhc->nhc_family == AF_INET) {
    1797             :                         struct fib_nh *nh;
    1798             : 
    1799             :                         nh = container_of(nhc, struct fib_nh, nh_common);
    1800             :                         if (nh->nh_tclassid &&
    1801             :                             nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
    1802             :                                 goto nla_put_failure;
    1803             :                 }
    1804             : #endif
    1805             :         } else {
    1806          19 :                 if (fib_add_multipath(skb, fi) < 0)
    1807             :                         goto nla_put_failure;
    1808             :         }
    1809             : 
    1810          19 : offload:
    1811          19 :         if (fri->offload)
    1812           0 :                 rtm->rtm_flags |= RTM_F_OFFLOAD;
    1813          19 :         if (fri->trap)
    1814           0 :                 rtm->rtm_flags |= RTM_F_TRAP;
    1815          19 :         if (fri->offload_failed)
    1816           0 :                 rtm->rtm_flags |= RTM_F_OFFLOAD_FAILED;
    1817             : 
    1818          19 :         nlmsg_end(skb, nlh);
    1819          19 :         return 0;
    1820             : 
    1821           0 : nla_put_failure:
    1822           0 :         nlmsg_cancel(skb, nlh);
    1823           0 :         return -EMSGSIZE;
    1824             : }
    1825             : 
    1826             : /*
    1827             :  * Update FIB if:
    1828             :  * - local address disappeared -> we must delete all the entries
    1829             :  *   referring to it.
    1830             :  * - device went down -> we must shutdown all nexthops going via it.
    1831             :  */
    1832           0 : int fib_sync_down_addr(struct net_device *dev, __be32 local)
    1833             : {
    1834           0 :         int ret = 0;
    1835           0 :         unsigned int hash = fib_laddr_hashfn(local);
    1836           0 :         struct hlist_head *head = &fib_info_laddrhash[hash];
    1837           0 :         int tb_id = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
    1838           0 :         struct net *net = dev_net(dev);
    1839           0 :         struct fib_info *fi;
    1840             : 
    1841           0 :         if (!fib_info_laddrhash || local == 0)
    1842             :                 return 0;
    1843             : 
    1844           0 :         hlist_for_each_entry(fi, head, fib_lhash) {
    1845           0 :                 if (!net_eq(fi->fib_net, net) ||
    1846           0 :                     fi->fib_tb_id != tb_id)
    1847           0 :                         continue;
    1848           0 :                 if (fi->fib_prefsrc == local) {
    1849           0 :                         fi->fib_flags |= RTNH_F_DEAD;
    1850           0 :                         ret++;
    1851             :                 }
    1852             :         }
    1853             :         return ret;
    1854             : }
    1855             : 
    1856           0 : static int call_fib_nh_notifiers(struct fib_nh *nh,
    1857             :                                  enum fib_event_type event_type)
    1858             : {
    1859           0 :         bool ignore_link_down = ip_ignore_linkdown(nh->fib_nh_dev);
    1860           0 :         struct fib_nh_notifier_info info = {
    1861             :                 .fib_nh = nh,
    1862             :         };
    1863             : 
    1864           0 :         switch (event_type) {
    1865           0 :         case FIB_EVENT_NH_ADD:
    1866           0 :                 if (nh->fib_nh_flags & RTNH_F_DEAD)
    1867             :                         break;
    1868           0 :                 if (ignore_link_down && nh->fib_nh_flags & RTNH_F_LINKDOWN)
    1869             :                         break;
    1870           0 :                 return call_fib4_notifiers(dev_net(nh->fib_nh_dev), event_type,
    1871             :                                            &info.info);
    1872           0 :         case FIB_EVENT_NH_DEL:
    1873           0 :                 if ((ignore_link_down && nh->fib_nh_flags & RTNH_F_LINKDOWN) ||
    1874           0 :                     (nh->fib_nh_flags & RTNH_F_DEAD))
    1875           0 :                         return call_fib4_notifiers(dev_net(nh->fib_nh_dev),
    1876             :                                                    event_type, &info.info);
    1877             :         default:
    1878             :                 break;
    1879             :         }
    1880             : 
    1881           0 :         return NOTIFY_DONE;
    1882             : }
    1883             : 
    1884             : /* Update the PMTU of exceptions when:
    1885             :  * - the new MTU of the first hop becomes smaller than the PMTU
    1886             :  * - the old MTU was the same as the PMTU, and it limited discovery of
    1887             :  *   larger MTUs on the path. With that limit raised, we can now
    1888             :  *   discover larger MTUs
    1889             :  * A special case is locked exceptions, for which the PMTU is smaller
    1890             :  * than the minimal accepted PMTU:
    1891             :  * - if the new MTU is greater than the PMTU, don't make any change
    1892             :  * - otherwise, unlock and set PMTU
    1893             :  */
    1894           0 : void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig)
    1895             : {
    1896           0 :         struct fnhe_hash_bucket *bucket;
    1897           0 :         int i;
    1898             : 
    1899           0 :         bucket = rcu_dereference_protected(nhc->nhc_exceptions, 1);
    1900           0 :         if (!bucket)
    1901             :                 return;
    1902             : 
    1903           0 :         for (i = 0; i < FNHE_HASH_SIZE; i++) {
    1904           0 :                 struct fib_nh_exception *fnhe;
    1905             : 
    1906           0 :                 for (fnhe = rcu_dereference_protected(bucket[i].chain, 1);
    1907           0 :                      fnhe;
    1908           0 :                      fnhe = rcu_dereference_protected(fnhe->fnhe_next, 1)) {
    1909           0 :                         if (fnhe->fnhe_mtu_locked) {
    1910           0 :                                 if (new <= fnhe->fnhe_pmtu) {
    1911           0 :                                         fnhe->fnhe_pmtu = new;
    1912           0 :                                         fnhe->fnhe_mtu_locked = false;
    1913             :                                 }
    1914           0 :                         } else if (new < fnhe->fnhe_pmtu ||
    1915             :                                    orig == fnhe->fnhe_pmtu) {
    1916           0 :                                 fnhe->fnhe_pmtu = new;
    1917             :                         }
    1918             :                 }
    1919             :         }
    1920             : }
    1921             : 
    1922           0 : void fib_sync_mtu(struct net_device *dev, u32 orig_mtu)
    1923             : {
    1924           0 :         unsigned int hash = fib_devindex_hashfn(dev->ifindex);
    1925           0 :         struct hlist_head *head = &fib_info_devhash[hash];
    1926           0 :         struct fib_nh *nh;
    1927             : 
    1928           0 :         hlist_for_each_entry(nh, head, nh_hash) {
    1929           0 :                 if (nh->fib_nh_dev == dev)
    1930           0 :                         fib_nhc_update_mtu(&nh->nh_common, dev->mtu, orig_mtu);
    1931             :         }
    1932           0 : }
    1933             : 
    1934             : /* Event              force Flags           Description
    1935             :  * NETDEV_CHANGE      0     LINKDOWN        Carrier OFF, not for scope host
    1936             :  * NETDEV_DOWN        0     LINKDOWN|DEAD   Link down, not for scope host
    1937             :  * NETDEV_DOWN        1     LINKDOWN|DEAD   Last address removed
    1938             :  * NETDEV_UNREGISTER  1     LINKDOWN|DEAD   Device removed
    1939             :  *
    1940             :  * only used when fib_nh is built into fib_info
    1941             :  */
    1942           0 : int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force)
    1943             : {
    1944           0 :         int ret = 0;
    1945           0 :         int scope = RT_SCOPE_NOWHERE;
    1946           0 :         struct fib_info *prev_fi = NULL;
    1947           0 :         unsigned int hash = fib_devindex_hashfn(dev->ifindex);
    1948           0 :         struct hlist_head *head = &fib_info_devhash[hash];
    1949           0 :         struct fib_nh *nh;
    1950             : 
    1951           0 :         if (force)
    1952           0 :                 scope = -1;
    1953             : 
    1954           0 :         hlist_for_each_entry(nh, head, nh_hash) {
    1955           0 :                 struct fib_info *fi = nh->nh_parent;
    1956           0 :                 int dead;
    1957             : 
    1958           0 :                 BUG_ON(!fi->fib_nhs);
    1959           0 :                 if (nh->fib_nh_dev != dev || fi == prev_fi)
    1960           0 :                         continue;
    1961           0 :                 prev_fi = fi;
    1962           0 :                 dead = 0;
    1963           0 :                 change_nexthops(fi) {
    1964           0 :                         if (nexthop_nh->fib_nh_flags & RTNH_F_DEAD)
    1965           0 :                                 dead++;
    1966           0 :                         else if (nexthop_nh->fib_nh_dev == dev &&
    1967           0 :                                  nexthop_nh->fib_nh_scope != scope) {
    1968           0 :                                 switch (event) {
    1969           0 :                                 case NETDEV_DOWN:
    1970             :                                 case NETDEV_UNREGISTER:
    1971           0 :                                         nexthop_nh->fib_nh_flags |= RTNH_F_DEAD;
    1972           0 :                                         fallthrough;
    1973           0 :                                 case NETDEV_CHANGE:
    1974           0 :                                         nexthop_nh->fib_nh_flags |= RTNH_F_LINKDOWN;
    1975           0 :                                         break;
    1976             :                                 }
    1977           0 :                                 call_fib_nh_notifiers(nexthop_nh,
    1978             :                                                       FIB_EVENT_NH_DEL);
    1979           0 :                                 dead++;
    1980             :                         }
    1981             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
    1982             :                         if (event == NETDEV_UNREGISTER &&
    1983             :                             nexthop_nh->fib_nh_dev == dev) {
    1984             :                                 dead = fi->fib_nhs;
    1985             :                                 break;
    1986             :                         }
    1987             : #endif
    1988             :                 } endfor_nexthops(fi)
    1989           0 :                 if (dead == fi->fib_nhs) {
    1990           0 :                         switch (event) {
    1991           0 :                         case NETDEV_DOWN:
    1992             :                         case NETDEV_UNREGISTER:
    1993           0 :                                 fi->fib_flags |= RTNH_F_DEAD;
    1994           0 :                                 fallthrough;
    1995           0 :                         case NETDEV_CHANGE:
    1996           0 :                                 fi->fib_flags |= RTNH_F_LINKDOWN;
    1997           0 :                                 break;
    1998             :                         }
    1999           0 :                         ret++;
    2000             :                 }
    2001             : 
    2002           0 :                 fib_rebalance(fi);
    2003             :         }
    2004             : 
    2005           0 :         return ret;
    2006             : }
    2007             : 
    2008             : /* Must be invoked inside of an RCU protected region.  */
    2009           0 : static void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
    2010             : {
    2011           0 :         struct fib_info *fi = NULL, *last_resort = NULL;
    2012           0 :         struct hlist_head *fa_head = res->fa_head;
    2013           0 :         struct fib_table *tb = res->table;
    2014           0 :         u8 slen = 32 - res->prefixlen;
    2015           0 :         int order = -1, last_idx = -1;
    2016           0 :         struct fib_alias *fa, *fa1 = NULL;
    2017           0 :         u32 last_prio = res->fi->fib_priority;
    2018           0 :         u8 last_tos = 0;
    2019             : 
    2020           0 :         hlist_for_each_entry_rcu(fa, fa_head, fa_list) {
    2021           0 :                 struct fib_info *next_fi = fa->fa_info;
    2022           0 :                 struct fib_nh_common *nhc;
    2023             : 
    2024           0 :                 if (fa->fa_slen != slen)
    2025           0 :                         continue;
    2026           0 :                 if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
    2027           0 :                         continue;
    2028           0 :                 if (fa->tb_id != tb->tb_id)
    2029           0 :                         continue;
    2030           0 :                 if (next_fi->fib_priority > last_prio &&
    2031             :                     fa->fa_tos == last_tos) {
    2032           0 :                         if (last_tos)
    2033           0 :                                 continue;
    2034             :                         break;
    2035             :                 }
    2036           0 :                 if (next_fi->fib_flags & RTNH_F_DEAD)
    2037           0 :                         continue;
    2038           0 :                 last_tos = fa->fa_tos;
    2039           0 :                 last_prio = next_fi->fib_priority;
    2040             : 
    2041           0 :                 if (next_fi->fib_scope != res->scope ||
    2042           0 :                     fa->fa_type != RTN_UNICAST)
    2043           0 :                         continue;
    2044             : 
    2045           0 :                 nhc = fib_info_nhc(next_fi, 0);
    2046           0 :                 if (!nhc->nhc_gw_family || nhc->nhc_scope != RT_SCOPE_LINK)
    2047           0 :                         continue;
    2048             : 
    2049           0 :                 fib_alias_accessed(fa);
    2050             : 
    2051           0 :                 if (!fi) {
    2052           0 :                         if (next_fi != res->fi)
    2053             :                                 break;
    2054             :                         fa1 = fa;
    2055           0 :                 } else if (!fib_detect_death(fi, order, &last_resort,
    2056           0 :                                              &last_idx, fa1->fa_default)) {
    2057           0 :                         fib_result_assign(res, fi);
    2058           0 :                         fa1->fa_default = order;
    2059           0 :                         goto out;
    2060             :                 }
    2061           0 :                 fi = next_fi;
    2062           0 :                 order++;
    2063             :         }
    2064             : 
    2065           0 :         if (order <= 0 || !fi) {
    2066           0 :                 if (fa1)
    2067           0 :                         fa1->fa_default = -1;
    2068           0 :                 goto out;
    2069             :         }
    2070             : 
    2071           0 :         if (!fib_detect_death(fi, order, &last_resort, &last_idx,
    2072           0 :                               fa1->fa_default)) {
    2073           0 :                 fib_result_assign(res, fi);
    2074           0 :                 fa1->fa_default = order;
    2075           0 :                 goto out;
    2076             :         }
    2077             : 
    2078           0 :         if (last_idx >= 0)
    2079           0 :                 fib_result_assign(res, last_resort);
    2080           0 :         fa1->fa_default = last_idx;
    2081           0 : out:
    2082           0 :         return;
    2083             : }
    2084             : 
    2085             : /*
    2086             :  * Dead device goes up. We wake up dead nexthops.
    2087             :  * It takes sense only on multipath routes.
    2088             :  *
    2089             :  * only used when fib_nh is built into fib_info
    2090             :  */
    2091           0 : int fib_sync_up(struct net_device *dev, unsigned char nh_flags)
    2092             : {
    2093           0 :         struct fib_info *prev_fi;
    2094           0 :         unsigned int hash;
    2095           0 :         struct hlist_head *head;
    2096           0 :         struct fib_nh *nh;
    2097           0 :         int ret;
    2098             : 
    2099           0 :         if (!(dev->flags & IFF_UP))
    2100             :                 return 0;
    2101             : 
    2102           0 :         if (nh_flags & RTNH_F_DEAD) {
    2103           0 :                 unsigned int flags = dev_get_flags(dev);
    2104             : 
    2105           0 :                 if (flags & (IFF_RUNNING | IFF_LOWER_UP))
    2106           0 :                         nh_flags |= RTNH_F_LINKDOWN;
    2107             :         }
    2108             : 
    2109           0 :         prev_fi = NULL;
    2110           0 :         hash = fib_devindex_hashfn(dev->ifindex);
    2111           0 :         head = &fib_info_devhash[hash];
    2112           0 :         ret = 0;
    2113             : 
    2114           0 :         hlist_for_each_entry(nh, head, nh_hash) {
    2115           0 :                 struct fib_info *fi = nh->nh_parent;
    2116           0 :                 int alive;
    2117             : 
    2118           0 :                 BUG_ON(!fi->fib_nhs);
    2119           0 :                 if (nh->fib_nh_dev != dev || fi == prev_fi)
    2120           0 :                         continue;
    2121             : 
    2122           0 :                 prev_fi = fi;
    2123           0 :                 alive = 0;
    2124           0 :                 change_nexthops(fi) {
    2125           0 :                         if (!(nexthop_nh->fib_nh_flags & nh_flags)) {
    2126           0 :                                 alive++;
    2127           0 :                                 continue;
    2128             :                         }
    2129           0 :                         if (!nexthop_nh->fib_nh_dev ||
    2130           0 :                             !(nexthop_nh->fib_nh_dev->flags & IFF_UP))
    2131           0 :                                 continue;
    2132           0 :                         if (nexthop_nh->fib_nh_dev != dev ||
    2133           0 :                             !__in_dev_get_rtnl(dev))
    2134           0 :                                 continue;
    2135           0 :                         alive++;
    2136           0 :                         nexthop_nh->fib_nh_flags &= ~nh_flags;
    2137           0 :                         call_fib_nh_notifiers(nexthop_nh, FIB_EVENT_NH_ADD);
    2138             :                 } endfor_nexthops(fi)
    2139             : 
    2140           0 :                 if (alive > 0) {
    2141           0 :                         fi->fib_flags &= ~nh_flags;
    2142           0 :                         ret++;
    2143             :                 }
    2144             : 
    2145           0 :                 fib_rebalance(fi);
    2146             :         }
    2147             : 
    2148             :         return ret;
    2149             : }
    2150             : 
    2151             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
    2152             : static bool fib_good_nh(const struct fib_nh *nh)
    2153             : {
    2154             :         int state = NUD_REACHABLE;
    2155             : 
    2156             :         if (nh->fib_nh_scope == RT_SCOPE_LINK) {
    2157             :                 struct neighbour *n;
    2158             : 
    2159             :                 rcu_read_lock_bh();
    2160             : 
    2161             :                 if (likely(nh->fib_nh_gw_family == AF_INET))
    2162             :                         n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev,
    2163             :                                                    (__force u32)nh->fib_nh_gw4);
    2164             :                 else if (nh->fib_nh_gw_family == AF_INET6)
    2165             :                         n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev,
    2166             :                                                            &nh->fib_nh_gw6);
    2167             :                 else
    2168             :                         n = NULL;
    2169             :                 if (n)
    2170             :                         state = n->nud_state;
    2171             : 
    2172             :                 rcu_read_unlock_bh();
    2173             :         }
    2174             : 
    2175             :         return !!(state & NUD_VALID);
    2176             : }
    2177             : 
    2178             : void fib_select_multipath(struct fib_result *res, int hash)
    2179             : {
    2180             :         struct fib_info *fi = res->fi;
    2181             :         struct net *net = fi->fib_net;
    2182             :         bool first = false;
    2183             : 
    2184             :         if (unlikely(res->fi->nh)) {
    2185             :                 nexthop_path_fib_result(res, hash);
    2186             :                 return;
    2187             :         }
    2188             : 
    2189             :         change_nexthops(fi) {
    2190             :                 if (net->ipv4.sysctl_fib_multipath_use_neigh) {
    2191             :                         if (!fib_good_nh(nexthop_nh))
    2192             :                                 continue;
    2193             :                         if (!first) {
    2194             :                                 res->nh_sel = nhsel;
    2195             :                                 res->nhc = &nexthop_nh->nh_common;
    2196             :                                 first = true;
    2197             :                         }
    2198             :                 }
    2199             : 
    2200             :                 if (hash > atomic_read(&nexthop_nh->fib_nh_upper_bound))
    2201             :                         continue;
    2202             : 
    2203             :                 res->nh_sel = nhsel;
    2204             :                 res->nhc = &nexthop_nh->nh_common;
    2205             :                 return;
    2206             :         } endfor_nexthops(fi);
    2207             : }
    2208             : #endif
    2209             : 
    2210          26 : void fib_select_path(struct net *net, struct fib_result *res,
    2211             :                      struct flowi4 *fl4, const struct sk_buff *skb)
    2212             : {
    2213          26 :         if (fl4->flowi4_oif && !(fl4->flowi4_flags & FLOWI_FLAG_SKIP_NH_OIF))
    2214           0 :                 goto check_saddr;
    2215             : 
    2216             : #ifdef CONFIG_IP_ROUTE_MULTIPATH
    2217             :         if (fib_info_num_path(res->fi) > 1) {
    2218             :                 int h = fib_multipath_hash(net, fl4, skb, NULL);
    2219             : 
    2220             :                 fib_select_multipath(res, h);
    2221             :         }
    2222             :         else
    2223             : #endif
    2224          26 :         if (!res->prefixlen &&
    2225           0 :             res->table->tb_num_default > 1 &&
    2226           0 :             res->type == RTN_UNICAST)
    2227           0 :                 fib_select_default(fl4, res);
    2228             : 
    2229          26 : check_saddr:
    2230          26 :         if (!fl4->saddr)
    2231           7 :                 fl4->saddr = fib_result_prefsrc(net, res);
    2232          26 : }

Generated by: LCOV version 1.14