18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 48c2ecf20Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 58c2ecf20Sopenharmony_ci * interface as the means of communication with the user level. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Definitions for the Forwarding Information Base. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru> 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#ifndef _NET_IP_FIB_H 138c2ecf20Sopenharmony_ci#define _NET_IP_FIB_H 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <net/flow.h> 168c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 178c2ecf20Sopenharmony_ci#include <linux/rcupdate.h> 188c2ecf20Sopenharmony_ci#include <net/fib_notifier.h> 198c2ecf20Sopenharmony_ci#include <net/fib_rules.h> 208c2ecf20Sopenharmony_ci#include <net/inetpeer.h> 218c2ecf20Sopenharmony_ci#include <linux/percpu.h> 228c2ecf20Sopenharmony_ci#include <linux/notifier.h> 238c2ecf20Sopenharmony_ci#include <linux/refcount.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct fib_config { 268c2ecf20Sopenharmony_ci u8 fc_dst_len; 278c2ecf20Sopenharmony_ci u8 fc_tos; 288c2ecf20Sopenharmony_ci u8 fc_protocol; 298c2ecf20Sopenharmony_ci u8 fc_scope; 308c2ecf20Sopenharmony_ci u8 fc_type; 318c2ecf20Sopenharmony_ci u8 fc_gw_family; 328c2ecf20Sopenharmony_ci /* 2 bytes unused */ 338c2ecf20Sopenharmony_ci u32 fc_table; 348c2ecf20Sopenharmony_ci __be32 fc_dst; 358c2ecf20Sopenharmony_ci union { 368c2ecf20Sopenharmony_ci __be32 fc_gw4; 378c2ecf20Sopenharmony_ci struct in6_addr fc_gw6; 388c2ecf20Sopenharmony_ci }; 398c2ecf20Sopenharmony_ci int fc_oif; 408c2ecf20Sopenharmony_ci u32 fc_flags; 418c2ecf20Sopenharmony_ci u32 fc_priority; 428c2ecf20Sopenharmony_ci __be32 fc_prefsrc; 438c2ecf20Sopenharmony_ci u32 fc_nh_id; 448c2ecf20Sopenharmony_ci struct nlattr *fc_mx; 458c2ecf20Sopenharmony_ci struct rtnexthop *fc_mp; 468c2ecf20Sopenharmony_ci int fc_mx_len; 478c2ecf20Sopenharmony_ci int fc_mp_len; 488c2ecf20Sopenharmony_ci u32 fc_flow; 498c2ecf20Sopenharmony_ci u32 fc_nlflags; 508c2ecf20Sopenharmony_ci struct nl_info fc_nlinfo; 518c2ecf20Sopenharmony_ci struct nlattr *fc_encap; 528c2ecf20Sopenharmony_ci u16 fc_encap_type; 538c2ecf20Sopenharmony_ci}; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistruct fib_info; 568c2ecf20Sopenharmony_cistruct rtable; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistruct fib_nh_exception { 598c2ecf20Sopenharmony_ci struct fib_nh_exception __rcu *fnhe_next; 608c2ecf20Sopenharmony_ci int fnhe_genid; 618c2ecf20Sopenharmony_ci __be32 fnhe_daddr; 628c2ecf20Sopenharmony_ci u32 fnhe_pmtu; 638c2ecf20Sopenharmony_ci bool fnhe_mtu_locked; 648c2ecf20Sopenharmony_ci __be32 fnhe_gw; 658c2ecf20Sopenharmony_ci unsigned long fnhe_expires; 668c2ecf20Sopenharmony_ci struct rtable __rcu *fnhe_rth_input; 678c2ecf20Sopenharmony_ci struct rtable __rcu *fnhe_rth_output; 688c2ecf20Sopenharmony_ci unsigned long fnhe_stamp; 698c2ecf20Sopenharmony_ci struct rcu_head rcu; 708c2ecf20Sopenharmony_ci}; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistruct fnhe_hash_bucket { 738c2ecf20Sopenharmony_ci struct fib_nh_exception __rcu *chain; 748c2ecf20Sopenharmony_ci}; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci#define FNHE_HASH_SHIFT 11 778c2ecf20Sopenharmony_ci#define FNHE_HASH_SIZE (1 << FNHE_HASH_SHIFT) 788c2ecf20Sopenharmony_ci#define FNHE_RECLAIM_DEPTH 5 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistruct fib_nh_common { 818c2ecf20Sopenharmony_ci struct net_device *nhc_dev; 828c2ecf20Sopenharmony_ci int nhc_oif; 838c2ecf20Sopenharmony_ci unsigned char nhc_scope; 848c2ecf20Sopenharmony_ci u8 nhc_family; 858c2ecf20Sopenharmony_ci u8 nhc_gw_family; 868c2ecf20Sopenharmony_ci unsigned char nhc_flags; 878c2ecf20Sopenharmony_ci struct lwtunnel_state *nhc_lwtstate; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci union { 908c2ecf20Sopenharmony_ci __be32 ipv4; 918c2ecf20Sopenharmony_ci struct in6_addr ipv6; 928c2ecf20Sopenharmony_ci } nhc_gw; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci int nhc_weight; 958c2ecf20Sopenharmony_ci atomic_t nhc_upper_bound; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* v4 specific, but allows fib6_nh with v4 routes */ 988c2ecf20Sopenharmony_ci struct rtable __rcu * __percpu *nhc_pcpu_rth_output; 998c2ecf20Sopenharmony_ci struct rtable __rcu *nhc_rth_input; 1008c2ecf20Sopenharmony_ci struct fnhe_hash_bucket __rcu *nhc_exceptions; 1018c2ecf20Sopenharmony_ci}; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistruct fib_nh { 1048c2ecf20Sopenharmony_ci struct fib_nh_common nh_common; 1058c2ecf20Sopenharmony_ci struct hlist_node nh_hash; 1068c2ecf20Sopenharmony_ci struct fib_info *nh_parent; 1078c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 1088c2ecf20Sopenharmony_ci __u32 nh_tclassid; 1098c2ecf20Sopenharmony_ci#endif 1108c2ecf20Sopenharmony_ci __be32 nh_saddr; 1118c2ecf20Sopenharmony_ci int nh_saddr_genid; 1128c2ecf20Sopenharmony_ci#define fib_nh_family nh_common.nhc_family 1138c2ecf20Sopenharmony_ci#define fib_nh_dev nh_common.nhc_dev 1148c2ecf20Sopenharmony_ci#define fib_nh_oif nh_common.nhc_oif 1158c2ecf20Sopenharmony_ci#define fib_nh_flags nh_common.nhc_flags 1168c2ecf20Sopenharmony_ci#define fib_nh_lws nh_common.nhc_lwtstate 1178c2ecf20Sopenharmony_ci#define fib_nh_scope nh_common.nhc_scope 1188c2ecf20Sopenharmony_ci#define fib_nh_gw_family nh_common.nhc_gw_family 1198c2ecf20Sopenharmony_ci#define fib_nh_gw4 nh_common.nhc_gw.ipv4 1208c2ecf20Sopenharmony_ci#define fib_nh_gw6 nh_common.nhc_gw.ipv6 1218c2ecf20Sopenharmony_ci#define fib_nh_weight nh_common.nhc_weight 1228c2ecf20Sopenharmony_ci#define fib_nh_upper_bound nh_common.nhc_upper_bound 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* 1268c2ecf20Sopenharmony_ci * This structure contains data shared by many of routes. 1278c2ecf20Sopenharmony_ci */ 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistruct nexthop; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistruct fib_info { 1328c2ecf20Sopenharmony_ci struct hlist_node fib_hash; 1338c2ecf20Sopenharmony_ci struct hlist_node fib_lhash; 1348c2ecf20Sopenharmony_ci struct list_head nh_list; 1358c2ecf20Sopenharmony_ci struct net *fib_net; 1368c2ecf20Sopenharmony_ci int fib_treeref; 1378c2ecf20Sopenharmony_ci refcount_t fib_clntref; 1388c2ecf20Sopenharmony_ci unsigned int fib_flags; 1398c2ecf20Sopenharmony_ci unsigned char fib_dead; 1408c2ecf20Sopenharmony_ci unsigned char fib_protocol; 1418c2ecf20Sopenharmony_ci unsigned char fib_scope; 1428c2ecf20Sopenharmony_ci unsigned char fib_type; 1438c2ecf20Sopenharmony_ci __be32 fib_prefsrc; 1448c2ecf20Sopenharmony_ci u32 fib_tb_id; 1458c2ecf20Sopenharmony_ci u32 fib_priority; 1468c2ecf20Sopenharmony_ci struct dst_metrics *fib_metrics; 1478c2ecf20Sopenharmony_ci#define fib_mtu fib_metrics->metrics[RTAX_MTU-1] 1488c2ecf20Sopenharmony_ci#define fib_window fib_metrics->metrics[RTAX_WINDOW-1] 1498c2ecf20Sopenharmony_ci#define fib_rtt fib_metrics->metrics[RTAX_RTT-1] 1508c2ecf20Sopenharmony_ci#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] 1518c2ecf20Sopenharmony_ci int fib_nhs; 1528c2ecf20Sopenharmony_ci bool fib_nh_is_v6; 1538c2ecf20Sopenharmony_ci bool nh_updated; 1548c2ecf20Sopenharmony_ci bool pfsrc_removed; 1558c2ecf20Sopenharmony_ci struct nexthop *nh; 1568c2ecf20Sopenharmony_ci struct rcu_head rcu; 1578c2ecf20Sopenharmony_ci struct fib_nh fib_nh[]; 1588c2ecf20Sopenharmony_ci}; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 1628c2ecf20Sopenharmony_cistruct fib_rule; 1638c2ecf20Sopenharmony_ci#endif 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistruct fib_table; 1668c2ecf20Sopenharmony_cistruct fib_result { 1678c2ecf20Sopenharmony_ci __be32 prefix; 1688c2ecf20Sopenharmony_ci unsigned char prefixlen; 1698c2ecf20Sopenharmony_ci unsigned char nh_sel; 1708c2ecf20Sopenharmony_ci unsigned char type; 1718c2ecf20Sopenharmony_ci unsigned char scope; 1728c2ecf20Sopenharmony_ci u32 tclassid; 1738c2ecf20Sopenharmony_ci struct fib_nh_common *nhc; 1748c2ecf20Sopenharmony_ci struct fib_info *fi; 1758c2ecf20Sopenharmony_ci struct fib_table *table; 1768c2ecf20Sopenharmony_ci struct hlist_head *fa_head; 1778c2ecf20Sopenharmony_ci}; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistruct fib_result_nl { 1808c2ecf20Sopenharmony_ci __be32 fl_addr; /* To be looked up*/ 1818c2ecf20Sopenharmony_ci u32 fl_mark; 1828c2ecf20Sopenharmony_ci unsigned char fl_tos; 1838c2ecf20Sopenharmony_ci unsigned char fl_scope; 1848c2ecf20Sopenharmony_ci unsigned char tb_id_in; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci unsigned char tb_id; /* Results */ 1878c2ecf20Sopenharmony_ci unsigned char prefixlen; 1888c2ecf20Sopenharmony_ci unsigned char nh_sel; 1898c2ecf20Sopenharmony_ci unsigned char type; 1908c2ecf20Sopenharmony_ci unsigned char scope; 1918c2ecf20Sopenharmony_ci int err; 1928c2ecf20Sopenharmony_ci}; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 1958c2ecf20Sopenharmony_ci#define FIB_TABLE_HASHSZ 256 1968c2ecf20Sopenharmony_ci#else 1978c2ecf20Sopenharmony_ci#define FIB_TABLE_HASHSZ 2 1988c2ecf20Sopenharmony_ci#endif 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc, 2018c2ecf20Sopenharmony_ci unsigned char scope); 2028c2ecf20Sopenharmony_ci__be32 fib_result_prefsrc(struct net *net, struct fib_result *res); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci#define FIB_RES_NHC(res) ((res).nhc) 2058c2ecf20Sopenharmony_ci#define FIB_RES_DEV(res) (FIB_RES_NHC(res)->nhc_dev) 2068c2ecf20Sopenharmony_ci#define FIB_RES_OIF(res) (FIB_RES_NHC(res)->nhc_oif) 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_cistruct fib_rt_info { 2098c2ecf20Sopenharmony_ci struct fib_info *fi; 2108c2ecf20Sopenharmony_ci u32 tb_id; 2118c2ecf20Sopenharmony_ci __be32 dst; 2128c2ecf20Sopenharmony_ci int dst_len; 2138c2ecf20Sopenharmony_ci u8 tos; 2148c2ecf20Sopenharmony_ci u8 type; 2158c2ecf20Sopenharmony_ci u8 offload:1, 2168c2ecf20Sopenharmony_ci trap:1, 2178c2ecf20Sopenharmony_ci unused:6; 2188c2ecf20Sopenharmony_ci}; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_cistruct fib_entry_notifier_info { 2218c2ecf20Sopenharmony_ci struct fib_notifier_info info; /* must be first */ 2228c2ecf20Sopenharmony_ci u32 dst; 2238c2ecf20Sopenharmony_ci int dst_len; 2248c2ecf20Sopenharmony_ci struct fib_info *fi; 2258c2ecf20Sopenharmony_ci u8 tos; 2268c2ecf20Sopenharmony_ci u8 type; 2278c2ecf20Sopenharmony_ci u32 tb_id; 2288c2ecf20Sopenharmony_ci}; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistruct fib_nh_notifier_info { 2318c2ecf20Sopenharmony_ci struct fib_notifier_info info; /* must be first */ 2328c2ecf20Sopenharmony_ci struct fib_nh *fib_nh; 2338c2ecf20Sopenharmony_ci}; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ciint call_fib4_notifier(struct notifier_block *nb, 2368c2ecf20Sopenharmony_ci enum fib_event_type event_type, 2378c2ecf20Sopenharmony_ci struct fib_notifier_info *info); 2388c2ecf20Sopenharmony_ciint call_fib4_notifiers(struct net *net, enum fib_event_type event_type, 2398c2ecf20Sopenharmony_ci struct fib_notifier_info *info); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ciint __net_init fib4_notifier_init(struct net *net); 2428c2ecf20Sopenharmony_civoid __net_exit fib4_notifier_exit(struct net *net); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_civoid fib_info_notify_update(struct net *net, struct nl_info *info); 2458c2ecf20Sopenharmony_ciint fib_notify(struct net *net, struct notifier_block *nb, 2468c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_cistruct fib_table { 2498c2ecf20Sopenharmony_ci struct hlist_node tb_hlist; 2508c2ecf20Sopenharmony_ci u32 tb_id; 2518c2ecf20Sopenharmony_ci int tb_num_default; 2528c2ecf20Sopenharmony_ci struct rcu_head rcu; 2538c2ecf20Sopenharmony_ci unsigned long *tb_data; 2548c2ecf20Sopenharmony_ci unsigned long __data[]; 2558c2ecf20Sopenharmony_ci}; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistruct fib_dump_filter { 2588c2ecf20Sopenharmony_ci u32 table_id; 2598c2ecf20Sopenharmony_ci /* filter_set is an optimization that an entry is set */ 2608c2ecf20Sopenharmony_ci bool filter_set; 2618c2ecf20Sopenharmony_ci bool dump_routes; 2628c2ecf20Sopenharmony_ci bool dump_exceptions; 2638c2ecf20Sopenharmony_ci unsigned char protocol; 2648c2ecf20Sopenharmony_ci unsigned char rt_type; 2658c2ecf20Sopenharmony_ci unsigned int flags; 2668c2ecf20Sopenharmony_ci struct net_device *dev; 2678c2ecf20Sopenharmony_ci}; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ciint fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 2708c2ecf20Sopenharmony_ci struct fib_result *res, int fib_flags); 2718c2ecf20Sopenharmony_ciint fib_table_insert(struct net *, struct fib_table *, struct fib_config *, 2728c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 2738c2ecf20Sopenharmony_ciint fib_table_delete(struct net *, struct fib_table *, struct fib_config *, 2748c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 2758c2ecf20Sopenharmony_ciint fib_table_dump(struct fib_table *table, struct sk_buff *skb, 2768c2ecf20Sopenharmony_ci struct netlink_callback *cb, struct fib_dump_filter *filter); 2778c2ecf20Sopenharmony_ciint fib_table_flush(struct net *net, struct fib_table *table, bool flush_all); 2788c2ecf20Sopenharmony_cistruct fib_table *fib_trie_unmerge(struct fib_table *main_tb); 2798c2ecf20Sopenharmony_civoid fib_table_flush_external(struct fib_table *table); 2808c2ecf20Sopenharmony_civoid fib_free_table(struct fib_table *tb); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci#ifndef CONFIG_IP_MULTIPLE_TABLES 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci#define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1)) 2858c2ecf20Sopenharmony_ci#define TABLE_MAIN_INDEX (RT_TABLE_MAIN & (FIB_TABLE_HASHSZ - 1)) 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic inline struct fib_table *fib_get_table(struct net *net, u32 id) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct hlist_node *tb_hlist; 2908c2ecf20Sopenharmony_ci struct hlist_head *ptr; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci ptr = id == RT_TABLE_LOCAL ? 2938c2ecf20Sopenharmony_ci &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] : 2948c2ecf20Sopenharmony_ci &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr)); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci return hlist_entry(tb_hlist, struct fib_table, tb_hlist); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic inline struct fib_table *fib_new_table(struct net *net, u32 id) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci return fib_get_table(net, id); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic inline int fib_lookup(struct net *net, const struct flowi4 *flp, 3078c2ecf20Sopenharmony_ci struct fib_result *res, unsigned int flags) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci struct fib_table *tb; 3108c2ecf20Sopenharmony_ci int err = -ENETUNREACH; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci rcu_read_lock(); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci tb = fib_get_table(net, RT_TABLE_MAIN); 3158c2ecf20Sopenharmony_ci if (tb) 3168c2ecf20Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (err == -EAGAIN) 3198c2ecf20Sopenharmony_ci err = -ENETUNREACH; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci rcu_read_unlock(); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return err; 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic inline bool fib4_has_custom_rules(const struct net *net) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci return false; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic inline bool fib4_rule_default(const struct fib_rule *rule) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci return true; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic inline int fib4_rules_dump(struct net *net, struct notifier_block *nb, 3378c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic inline unsigned int fib4_rules_seq_read(struct net *net) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci return 0; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic inline bool fib4_rules_early_flow_dissect(struct net *net, 3488c2ecf20Sopenharmony_ci struct sk_buff *skb, 3498c2ecf20Sopenharmony_ci struct flowi4 *fl4, 3508c2ecf20Sopenharmony_ci struct flow_keys *flkeys) 3518c2ecf20Sopenharmony_ci{ 3528c2ecf20Sopenharmony_ci return false; 3538c2ecf20Sopenharmony_ci} 3548c2ecf20Sopenharmony_ci#else /* CONFIG_IP_MULTIPLE_TABLES */ 3558c2ecf20Sopenharmony_ciint __net_init fib4_rules_init(struct net *net); 3568c2ecf20Sopenharmony_civoid __net_exit fib4_rules_exit(struct net *net); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistruct fib_table *fib_new_table(struct net *net, u32 id); 3598c2ecf20Sopenharmony_cistruct fib_table *fib_get_table(struct net *net, u32 id); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ciint __fib_lookup(struct net *net, struct flowi4 *flp, 3628c2ecf20Sopenharmony_ci struct fib_result *res, unsigned int flags); 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic inline int fib_lookup(struct net *net, struct flowi4 *flp, 3658c2ecf20Sopenharmony_ci struct fib_result *res, unsigned int flags) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct fib_table *tb; 3688c2ecf20Sopenharmony_ci int err = -ENETUNREACH; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci flags |= FIB_LOOKUP_NOREF; 3718c2ecf20Sopenharmony_ci if (net->ipv4.fib_has_custom_rules) 3728c2ecf20Sopenharmony_ci return __fib_lookup(net, flp, res, flags); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci rcu_read_lock(); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci res->tclassid = 0; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci tb = rcu_dereference_rtnl(net->ipv4.fib_main); 3798c2ecf20Sopenharmony_ci if (tb) 3808c2ecf20Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci if (!err) 3838c2ecf20Sopenharmony_ci goto out; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci tb = rcu_dereference_rtnl(net->ipv4.fib_default); 3868c2ecf20Sopenharmony_ci if (tb) 3878c2ecf20Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ciout: 3908c2ecf20Sopenharmony_ci if (err == -EAGAIN) 3918c2ecf20Sopenharmony_ci err = -ENETUNREACH; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci rcu_read_unlock(); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci return err; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic inline bool fib4_has_custom_rules(const struct net *net) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci return net->ipv4.fib_has_custom_rules; 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cibool fib4_rule_default(const struct fib_rule *rule); 4048c2ecf20Sopenharmony_ciint fib4_rules_dump(struct net *net, struct notifier_block *nb, 4058c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 4068c2ecf20Sopenharmony_ciunsigned int fib4_rules_seq_read(struct net *net); 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic inline bool fib4_rules_early_flow_dissect(struct net *net, 4098c2ecf20Sopenharmony_ci struct sk_buff *skb, 4108c2ecf20Sopenharmony_ci struct flowi4 *fl4, 4118c2ecf20Sopenharmony_ci struct flow_keys *flkeys) 4128c2ecf20Sopenharmony_ci{ 4138c2ecf20Sopenharmony_ci unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP; 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci if (!net->ipv4.fib_rules_require_fldissect) 4168c2ecf20Sopenharmony_ci return false; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci skb_flow_dissect_flow_keys(skb, flkeys, flag); 4198c2ecf20Sopenharmony_ci fl4->fl4_sport = flkeys->ports.src; 4208c2ecf20Sopenharmony_ci fl4->fl4_dport = flkeys->ports.dst; 4218c2ecf20Sopenharmony_ci fl4->flowi4_proto = flkeys->basic.ip_proto; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci return true; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci#endif /* CONFIG_IP_MULTIPLE_TABLES */ 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci/* Exported by fib_frontend.c */ 4298c2ecf20Sopenharmony_ciextern const struct nla_policy rtm_ipv4_policy[]; 4308c2ecf20Sopenharmony_civoid ip_fib_init(void); 4318c2ecf20Sopenharmony_ciint fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, 4328c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 4338c2ecf20Sopenharmony_ci__be32 fib_compute_spec_dst(struct sk_buff *skb); 4348c2ecf20Sopenharmony_cibool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev); 4358c2ecf20Sopenharmony_ciint fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, 4368c2ecf20Sopenharmony_ci u8 tos, int oif, struct net_device *dev, 4378c2ecf20Sopenharmony_ci struct in_device *idev, u32 *itag); 4388c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 4398c2ecf20Sopenharmony_cistatic inline int fib_num_tclassid_users(struct net *net) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci return atomic_read(&net->ipv4.fib_num_tclassid_users); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci#else 4448c2ecf20Sopenharmony_cistatic inline int fib_num_tclassid_users(struct net *net) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci return 0; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci#endif 4498c2ecf20Sopenharmony_ciint fib_unmerge(struct net *net); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc, 4528c2ecf20Sopenharmony_ciconst struct net_device *dev) 4538c2ecf20Sopenharmony_ci{ 4548c2ecf20Sopenharmony_ci if (nhc->nhc_dev == dev || 4558c2ecf20Sopenharmony_ci l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) 4568c2ecf20Sopenharmony_ci return true; 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci return false; 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci/* Exported by fib_semantics.c */ 4628c2ecf20Sopenharmony_ciint ip_fib_check_default(__be32 gw, struct net_device *dev); 4638c2ecf20Sopenharmony_ciint fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force); 4648c2ecf20Sopenharmony_ciint fib_sync_down_addr(struct net_device *dev, __be32 local); 4658c2ecf20Sopenharmony_ciint fib_sync_up(struct net_device *dev, unsigned char nh_flags); 4668c2ecf20Sopenharmony_civoid fib_sync_mtu(struct net_device *dev, u32 orig_mtu); 4678c2ecf20Sopenharmony_civoid fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_MULTIPATH 4708c2ecf20Sopenharmony_ciint fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, 4718c2ecf20Sopenharmony_ci const struct sk_buff *skb, struct flow_keys *flkeys); 4728c2ecf20Sopenharmony_ci#endif 4738c2ecf20Sopenharmony_ciint fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope, 4748c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 4758c2ecf20Sopenharmony_civoid fib_select_multipath(struct fib_result *res, int hash); 4768c2ecf20Sopenharmony_civoid fib_select_path(struct net *net, struct fib_result *res, 4778c2ecf20Sopenharmony_ci struct flowi4 *fl4, const struct sk_buff *skb); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ciint fib_nh_init(struct net *net, struct fib_nh *fib_nh, 4808c2ecf20Sopenharmony_ci struct fib_config *cfg, int nh_weight, 4818c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 4828c2ecf20Sopenharmony_civoid fib_nh_release(struct net *net, struct fib_nh *fib_nh); 4838c2ecf20Sopenharmony_ciint fib_nh_common_init(struct net *net, struct fib_nh_common *nhc, 4848c2ecf20Sopenharmony_ci struct nlattr *fc_encap, u16 fc_encap_type, 4858c2ecf20Sopenharmony_ci void *cfg, gfp_t gfp_flags, 4868c2ecf20Sopenharmony_ci struct netlink_ext_ack *extack); 4878c2ecf20Sopenharmony_civoid fib_nh_common_release(struct fib_nh_common *nhc); 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/* Exported by fib_trie.c */ 4908c2ecf20Sopenharmony_civoid fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri); 4918c2ecf20Sopenharmony_civoid fib_trie_init(void); 4928c2ecf20Sopenharmony_cistruct fib_table *fib_trie_table(u32 id, struct fib_table *alias); 4938c2ecf20Sopenharmony_cibool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags, 4948c2ecf20Sopenharmony_ci const struct flowi4 *flp); 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic inline void fib_combine_itag(u32 *itag, const struct fib_result *res) 4978c2ecf20Sopenharmony_ci{ 4988c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 4998c2ecf20Sopenharmony_ci struct fib_nh_common *nhc = res->nhc; 5008c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 5018c2ecf20Sopenharmony_ci u32 rtag; 5028c2ecf20Sopenharmony_ci#endif 5038c2ecf20Sopenharmony_ci if (nhc->nhc_family == AF_INET) { 5048c2ecf20Sopenharmony_ci struct fib_nh *nh; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci nh = container_of(nhc, struct fib_nh, nh_common); 5078c2ecf20Sopenharmony_ci *itag = nh->nh_tclassid << 16; 5088c2ecf20Sopenharmony_ci } else { 5098c2ecf20Sopenharmony_ci *itag = 0; 5108c2ecf20Sopenharmony_ci } 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 5138c2ecf20Sopenharmony_ci rtag = res->tclassid; 5148c2ecf20Sopenharmony_ci if (*itag == 0) 5158c2ecf20Sopenharmony_ci *itag = (rtag<<16); 5168c2ecf20Sopenharmony_ci *itag |= (rtag>>16); 5178c2ecf20Sopenharmony_ci#endif 5188c2ecf20Sopenharmony_ci#endif 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_civoid fib_flush(struct net *net); 5228c2ecf20Sopenharmony_civoid free_fib_info(struct fib_info *fi); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_cistatic inline void fib_info_hold(struct fib_info *fi) 5258c2ecf20Sopenharmony_ci{ 5268c2ecf20Sopenharmony_ci refcount_inc(&fi->fib_clntref); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic inline void fib_info_put(struct fib_info *fi) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci if (refcount_dec_and_test(&fi->fib_clntref)) 5328c2ecf20Sopenharmony_ci free_fib_info(fi); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_FS 5368c2ecf20Sopenharmony_ciint __net_init fib_proc_init(struct net *net); 5378c2ecf20Sopenharmony_civoid __net_exit fib_proc_exit(struct net *net); 5388c2ecf20Sopenharmony_ci#else 5398c2ecf20Sopenharmony_cistatic inline int fib_proc_init(struct net *net) 5408c2ecf20Sopenharmony_ci{ 5418c2ecf20Sopenharmony_ci return 0; 5428c2ecf20Sopenharmony_ci} 5438c2ecf20Sopenharmony_cistatic inline void fib_proc_exit(struct net *net) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci} 5468c2ecf20Sopenharmony_ci#endif 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ciu32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr); 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ciint ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, 5518c2ecf20Sopenharmony_ci struct fib_dump_filter *filter, 5528c2ecf20Sopenharmony_ci struct netlink_callback *cb); 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ciint fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, 5558c2ecf20Sopenharmony_ci u8 rt_family, unsigned char *flags, bool skip_oif); 5568c2ecf20Sopenharmony_ciint fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh, 5578c2ecf20Sopenharmony_ci int nh_weight, u8 rt_family, u32 nh_tclassid); 5588c2ecf20Sopenharmony_ci#endif /* _NET_FIB_H */ 559