^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) }