Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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