162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * INET An implementation of the TCP/IP protocol suite for the LINUX 462306a36Sopenharmony_ci * operating system. INET is implemented using the BSD Socket 562306a36Sopenharmony_ci * interface as the means of communication with the user level. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Definitions for the Forwarding Information Base. 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef _NET_IP_FIB_H 1362306a36Sopenharmony_ci#define _NET_IP_FIB_H 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <net/flow.h> 1662306a36Sopenharmony_ci#include <linux/seq_file.h> 1762306a36Sopenharmony_ci#include <linux/rcupdate.h> 1862306a36Sopenharmony_ci#include <net/fib_notifier.h> 1962306a36Sopenharmony_ci#include <net/fib_rules.h> 2062306a36Sopenharmony_ci#include <net/inet_dscp.h> 2162306a36Sopenharmony_ci#include <net/inetpeer.h> 2262306a36Sopenharmony_ci#include <linux/percpu.h> 2362306a36Sopenharmony_ci#include <linux/notifier.h> 2462306a36Sopenharmony_ci#include <linux/refcount.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistruct fib_config { 2762306a36Sopenharmony_ci u8 fc_dst_len; 2862306a36Sopenharmony_ci dscp_t fc_dscp; 2962306a36Sopenharmony_ci u8 fc_protocol; 3062306a36Sopenharmony_ci u8 fc_scope; 3162306a36Sopenharmony_ci u8 fc_type; 3262306a36Sopenharmony_ci u8 fc_gw_family; 3362306a36Sopenharmony_ci /* 2 bytes unused */ 3462306a36Sopenharmony_ci u32 fc_table; 3562306a36Sopenharmony_ci __be32 fc_dst; 3662306a36Sopenharmony_ci union { 3762306a36Sopenharmony_ci __be32 fc_gw4; 3862306a36Sopenharmony_ci struct in6_addr fc_gw6; 3962306a36Sopenharmony_ci }; 4062306a36Sopenharmony_ci int fc_oif; 4162306a36Sopenharmony_ci u32 fc_flags; 4262306a36Sopenharmony_ci u32 fc_priority; 4362306a36Sopenharmony_ci __be32 fc_prefsrc; 4462306a36Sopenharmony_ci u32 fc_nh_id; 4562306a36Sopenharmony_ci struct nlattr *fc_mx; 4662306a36Sopenharmony_ci struct rtnexthop *fc_mp; 4762306a36Sopenharmony_ci int fc_mx_len; 4862306a36Sopenharmony_ci int fc_mp_len; 4962306a36Sopenharmony_ci u32 fc_flow; 5062306a36Sopenharmony_ci u32 fc_nlflags; 5162306a36Sopenharmony_ci struct nl_info fc_nlinfo; 5262306a36Sopenharmony_ci struct nlattr *fc_encap; 5362306a36Sopenharmony_ci u16 fc_encap_type; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_cistruct fib_info; 5762306a36Sopenharmony_cistruct rtable; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistruct fib_nh_exception { 6062306a36Sopenharmony_ci struct fib_nh_exception __rcu *fnhe_next; 6162306a36Sopenharmony_ci int fnhe_genid; 6262306a36Sopenharmony_ci __be32 fnhe_daddr; 6362306a36Sopenharmony_ci u32 fnhe_pmtu; 6462306a36Sopenharmony_ci bool fnhe_mtu_locked; 6562306a36Sopenharmony_ci __be32 fnhe_gw; 6662306a36Sopenharmony_ci unsigned long fnhe_expires; 6762306a36Sopenharmony_ci struct rtable __rcu *fnhe_rth_input; 6862306a36Sopenharmony_ci struct rtable __rcu *fnhe_rth_output; 6962306a36Sopenharmony_ci unsigned long fnhe_stamp; 7062306a36Sopenharmony_ci struct rcu_head rcu; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistruct fnhe_hash_bucket { 7462306a36Sopenharmony_ci struct fib_nh_exception __rcu *chain; 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define FNHE_HASH_SHIFT 11 7862306a36Sopenharmony_ci#define FNHE_HASH_SIZE (1 << FNHE_HASH_SHIFT) 7962306a36Sopenharmony_ci#define FNHE_RECLAIM_DEPTH 5 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct fib_nh_common { 8262306a36Sopenharmony_ci struct net_device *nhc_dev; 8362306a36Sopenharmony_ci netdevice_tracker nhc_dev_tracker; 8462306a36Sopenharmony_ci int nhc_oif; 8562306a36Sopenharmony_ci unsigned char nhc_scope; 8662306a36Sopenharmony_ci u8 nhc_family; 8762306a36Sopenharmony_ci u8 nhc_gw_family; 8862306a36Sopenharmony_ci unsigned char nhc_flags; 8962306a36Sopenharmony_ci struct lwtunnel_state *nhc_lwtstate; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci union { 9262306a36Sopenharmony_ci __be32 ipv4; 9362306a36Sopenharmony_ci struct in6_addr ipv6; 9462306a36Sopenharmony_ci } nhc_gw; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci int nhc_weight; 9762306a36Sopenharmony_ci atomic_t nhc_upper_bound; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* v4 specific, but allows fib6_nh with v4 routes */ 10062306a36Sopenharmony_ci struct rtable __rcu * __percpu *nhc_pcpu_rth_output; 10162306a36Sopenharmony_ci struct rtable __rcu *nhc_rth_input; 10262306a36Sopenharmony_ci struct fnhe_hash_bucket __rcu *nhc_exceptions; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct fib_nh { 10662306a36Sopenharmony_ci struct fib_nh_common nh_common; 10762306a36Sopenharmony_ci struct hlist_node nh_hash; 10862306a36Sopenharmony_ci struct fib_info *nh_parent; 10962306a36Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 11062306a36Sopenharmony_ci __u32 nh_tclassid; 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci __be32 nh_saddr; 11362306a36Sopenharmony_ci int nh_saddr_genid; 11462306a36Sopenharmony_ci#define fib_nh_family nh_common.nhc_family 11562306a36Sopenharmony_ci#define fib_nh_dev nh_common.nhc_dev 11662306a36Sopenharmony_ci#define fib_nh_dev_tracker nh_common.nhc_dev_tracker 11762306a36Sopenharmony_ci#define fib_nh_oif nh_common.nhc_oif 11862306a36Sopenharmony_ci#define fib_nh_flags nh_common.nhc_flags 11962306a36Sopenharmony_ci#define fib_nh_lws nh_common.nhc_lwtstate 12062306a36Sopenharmony_ci#define fib_nh_scope nh_common.nhc_scope 12162306a36Sopenharmony_ci#define fib_nh_gw_family nh_common.nhc_gw_family 12262306a36Sopenharmony_ci#define fib_nh_gw4 nh_common.nhc_gw.ipv4 12362306a36Sopenharmony_ci#define fib_nh_gw6 nh_common.nhc_gw.ipv6 12462306a36Sopenharmony_ci#define fib_nh_weight nh_common.nhc_weight 12562306a36Sopenharmony_ci#define fib_nh_upper_bound nh_common.nhc_upper_bound 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci/* 12962306a36Sopenharmony_ci * This structure contains data shared by many of routes. 13062306a36Sopenharmony_ci */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistruct nexthop; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_cistruct fib_info { 13562306a36Sopenharmony_ci struct hlist_node fib_hash; 13662306a36Sopenharmony_ci struct hlist_node fib_lhash; 13762306a36Sopenharmony_ci struct list_head nh_list; 13862306a36Sopenharmony_ci struct net *fib_net; 13962306a36Sopenharmony_ci refcount_t fib_treeref; 14062306a36Sopenharmony_ci refcount_t fib_clntref; 14162306a36Sopenharmony_ci unsigned int fib_flags; 14262306a36Sopenharmony_ci unsigned char fib_dead; 14362306a36Sopenharmony_ci unsigned char fib_protocol; 14462306a36Sopenharmony_ci unsigned char fib_scope; 14562306a36Sopenharmony_ci unsigned char fib_type; 14662306a36Sopenharmony_ci __be32 fib_prefsrc; 14762306a36Sopenharmony_ci u32 fib_tb_id; 14862306a36Sopenharmony_ci u32 fib_priority; 14962306a36Sopenharmony_ci struct dst_metrics *fib_metrics; 15062306a36Sopenharmony_ci#define fib_mtu fib_metrics->metrics[RTAX_MTU-1] 15162306a36Sopenharmony_ci#define fib_window fib_metrics->metrics[RTAX_WINDOW-1] 15262306a36Sopenharmony_ci#define fib_rtt fib_metrics->metrics[RTAX_RTT-1] 15362306a36Sopenharmony_ci#define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1] 15462306a36Sopenharmony_ci int fib_nhs; 15562306a36Sopenharmony_ci bool fib_nh_is_v6; 15662306a36Sopenharmony_ci bool nh_updated; 15762306a36Sopenharmony_ci bool pfsrc_removed; 15862306a36Sopenharmony_ci struct nexthop *nh; 15962306a36Sopenharmony_ci struct rcu_head rcu; 16062306a36Sopenharmony_ci struct fib_nh fib_nh[]; 16162306a36Sopenharmony_ci}; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 16562306a36Sopenharmony_cistruct fib_rule; 16662306a36Sopenharmony_ci#endif 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistruct fib_table; 16962306a36Sopenharmony_cistruct fib_result { 17062306a36Sopenharmony_ci __be32 prefix; 17162306a36Sopenharmony_ci unsigned char prefixlen; 17262306a36Sopenharmony_ci unsigned char nh_sel; 17362306a36Sopenharmony_ci unsigned char type; 17462306a36Sopenharmony_ci unsigned char scope; 17562306a36Sopenharmony_ci u32 tclassid; 17662306a36Sopenharmony_ci struct fib_nh_common *nhc; 17762306a36Sopenharmony_ci struct fib_info *fi; 17862306a36Sopenharmony_ci struct fib_table *table; 17962306a36Sopenharmony_ci struct hlist_head *fa_head; 18062306a36Sopenharmony_ci}; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistruct fib_result_nl { 18362306a36Sopenharmony_ci __be32 fl_addr; /* To be looked up*/ 18462306a36Sopenharmony_ci u32 fl_mark; 18562306a36Sopenharmony_ci unsigned char fl_tos; 18662306a36Sopenharmony_ci unsigned char fl_scope; 18762306a36Sopenharmony_ci unsigned char tb_id_in; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci unsigned char tb_id; /* Results */ 19062306a36Sopenharmony_ci unsigned char prefixlen; 19162306a36Sopenharmony_ci unsigned char nh_sel; 19262306a36Sopenharmony_ci unsigned char type; 19362306a36Sopenharmony_ci unsigned char scope; 19462306a36Sopenharmony_ci int err; 19562306a36Sopenharmony_ci}; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 19862306a36Sopenharmony_ci#define FIB_TABLE_HASHSZ 256 19962306a36Sopenharmony_ci#else 20062306a36Sopenharmony_ci#define FIB_TABLE_HASHSZ 2 20162306a36Sopenharmony_ci#endif 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci__be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc, 20462306a36Sopenharmony_ci unsigned char scope); 20562306a36Sopenharmony_ci__be32 fib_result_prefsrc(struct net *net, struct fib_result *res); 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci#define FIB_RES_NHC(res) ((res).nhc) 20862306a36Sopenharmony_ci#define FIB_RES_DEV(res) (FIB_RES_NHC(res)->nhc_dev) 20962306a36Sopenharmony_ci#define FIB_RES_OIF(res) (FIB_RES_NHC(res)->nhc_oif) 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistruct fib_rt_info { 21262306a36Sopenharmony_ci struct fib_info *fi; 21362306a36Sopenharmony_ci u32 tb_id; 21462306a36Sopenharmony_ci __be32 dst; 21562306a36Sopenharmony_ci int dst_len; 21662306a36Sopenharmony_ci dscp_t dscp; 21762306a36Sopenharmony_ci u8 type; 21862306a36Sopenharmony_ci u8 offload:1, 21962306a36Sopenharmony_ci trap:1, 22062306a36Sopenharmony_ci offload_failed:1, 22162306a36Sopenharmony_ci unused:5; 22262306a36Sopenharmony_ci}; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistruct fib_entry_notifier_info { 22562306a36Sopenharmony_ci struct fib_notifier_info info; /* must be first */ 22662306a36Sopenharmony_ci u32 dst; 22762306a36Sopenharmony_ci int dst_len; 22862306a36Sopenharmony_ci struct fib_info *fi; 22962306a36Sopenharmony_ci dscp_t dscp; 23062306a36Sopenharmony_ci u8 type; 23162306a36Sopenharmony_ci u32 tb_id; 23262306a36Sopenharmony_ci}; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistruct fib_nh_notifier_info { 23562306a36Sopenharmony_ci struct fib_notifier_info info; /* must be first */ 23662306a36Sopenharmony_ci struct fib_nh *fib_nh; 23762306a36Sopenharmony_ci}; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciint call_fib4_notifier(struct notifier_block *nb, 24062306a36Sopenharmony_ci enum fib_event_type event_type, 24162306a36Sopenharmony_ci struct fib_notifier_info *info); 24262306a36Sopenharmony_ciint call_fib4_notifiers(struct net *net, enum fib_event_type event_type, 24362306a36Sopenharmony_ci struct fib_notifier_info *info); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ciint __net_init fib4_notifier_init(struct net *net); 24662306a36Sopenharmony_civoid __net_exit fib4_notifier_exit(struct net *net); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_civoid fib_info_notify_update(struct net *net, struct nl_info *info); 24962306a36Sopenharmony_ciint fib_notify(struct net *net, struct notifier_block *nb, 25062306a36Sopenharmony_ci struct netlink_ext_ack *extack); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_cistruct fib_table { 25362306a36Sopenharmony_ci struct hlist_node tb_hlist; 25462306a36Sopenharmony_ci u32 tb_id; 25562306a36Sopenharmony_ci int tb_num_default; 25662306a36Sopenharmony_ci struct rcu_head rcu; 25762306a36Sopenharmony_ci unsigned long *tb_data; 25862306a36Sopenharmony_ci unsigned long __data[]; 25962306a36Sopenharmony_ci}; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistruct fib_dump_filter { 26262306a36Sopenharmony_ci u32 table_id; 26362306a36Sopenharmony_ci /* filter_set is an optimization that an entry is set */ 26462306a36Sopenharmony_ci bool filter_set; 26562306a36Sopenharmony_ci bool dump_routes; 26662306a36Sopenharmony_ci bool dump_exceptions; 26762306a36Sopenharmony_ci unsigned char protocol; 26862306a36Sopenharmony_ci unsigned char rt_type; 26962306a36Sopenharmony_ci unsigned int flags; 27062306a36Sopenharmony_ci struct net_device *dev; 27162306a36Sopenharmony_ci}; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ciint fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, 27462306a36Sopenharmony_ci struct fib_result *res, int fib_flags); 27562306a36Sopenharmony_ciint fib_table_insert(struct net *, struct fib_table *, struct fib_config *, 27662306a36Sopenharmony_ci struct netlink_ext_ack *extack); 27762306a36Sopenharmony_ciint fib_table_delete(struct net *, struct fib_table *, struct fib_config *, 27862306a36Sopenharmony_ci struct netlink_ext_ack *extack); 27962306a36Sopenharmony_ciint fib_table_dump(struct fib_table *table, struct sk_buff *skb, 28062306a36Sopenharmony_ci struct netlink_callback *cb, struct fib_dump_filter *filter); 28162306a36Sopenharmony_ciint fib_table_flush(struct net *net, struct fib_table *table, bool flush_all); 28262306a36Sopenharmony_cistruct fib_table *fib_trie_unmerge(struct fib_table *main_tb); 28362306a36Sopenharmony_civoid fib_table_flush_external(struct fib_table *table); 28462306a36Sopenharmony_civoid fib_free_table(struct fib_table *tb); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci#ifndef CONFIG_IP_MULTIPLE_TABLES 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci#define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1)) 28962306a36Sopenharmony_ci#define TABLE_MAIN_INDEX (RT_TABLE_MAIN & (FIB_TABLE_HASHSZ - 1)) 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_cistatic inline struct fib_table *fib_get_table(struct net *net, u32 id) 29262306a36Sopenharmony_ci{ 29362306a36Sopenharmony_ci struct hlist_node *tb_hlist; 29462306a36Sopenharmony_ci struct hlist_head *ptr; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci ptr = id == RT_TABLE_LOCAL ? 29762306a36Sopenharmony_ci &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] : 29862306a36Sopenharmony_ci &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr)); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci return hlist_entry(tb_hlist, struct fib_table, tb_hlist); 30362306a36Sopenharmony_ci} 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cistatic inline struct fib_table *fib_new_table(struct net *net, u32 id) 30662306a36Sopenharmony_ci{ 30762306a36Sopenharmony_ci return fib_get_table(net, id); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic inline int fib_lookup(struct net *net, const struct flowi4 *flp, 31162306a36Sopenharmony_ci struct fib_result *res, unsigned int flags) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct fib_table *tb; 31462306a36Sopenharmony_ci int err = -ENETUNREACH; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci rcu_read_lock(); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci tb = fib_get_table(net, RT_TABLE_MAIN); 31962306a36Sopenharmony_ci if (tb) 32062306a36Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (err == -EAGAIN) 32362306a36Sopenharmony_ci err = -ENETUNREACH; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci rcu_read_unlock(); 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci return err; 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic inline bool fib4_has_custom_rules(const struct net *net) 33162306a36Sopenharmony_ci{ 33262306a36Sopenharmony_ci return false; 33362306a36Sopenharmony_ci} 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic inline bool fib4_rule_default(const struct fib_rule *rule) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci return true; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic inline int fib4_rules_dump(struct net *net, struct notifier_block *nb, 34162306a36Sopenharmony_ci struct netlink_ext_ack *extack) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci return 0; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic inline unsigned int fib4_rules_seq_read(struct net *net) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci return 0; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic inline bool fib4_rules_early_flow_dissect(struct net *net, 35262306a36Sopenharmony_ci struct sk_buff *skb, 35362306a36Sopenharmony_ci struct flowi4 *fl4, 35462306a36Sopenharmony_ci struct flow_keys *flkeys) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci return false; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci#else /* CONFIG_IP_MULTIPLE_TABLES */ 35962306a36Sopenharmony_ciint __net_init fib4_rules_init(struct net *net); 36062306a36Sopenharmony_civoid __net_exit fib4_rules_exit(struct net *net); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistruct fib_table *fib_new_table(struct net *net, u32 id); 36362306a36Sopenharmony_cistruct fib_table *fib_get_table(struct net *net, u32 id); 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ciint __fib_lookup(struct net *net, struct flowi4 *flp, 36662306a36Sopenharmony_ci struct fib_result *res, unsigned int flags); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic inline int fib_lookup(struct net *net, struct flowi4 *flp, 36962306a36Sopenharmony_ci struct fib_result *res, unsigned int flags) 37062306a36Sopenharmony_ci{ 37162306a36Sopenharmony_ci struct fib_table *tb; 37262306a36Sopenharmony_ci int err = -ENETUNREACH; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci flags |= FIB_LOOKUP_NOREF; 37562306a36Sopenharmony_ci if (net->ipv4.fib_has_custom_rules) 37662306a36Sopenharmony_ci return __fib_lookup(net, flp, res, flags); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci rcu_read_lock(); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci res->tclassid = 0; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci tb = rcu_dereference_rtnl(net->ipv4.fib_main); 38362306a36Sopenharmony_ci if (tb) 38462306a36Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (!err) 38762306a36Sopenharmony_ci goto out; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci tb = rcu_dereference_rtnl(net->ipv4.fib_default); 39062306a36Sopenharmony_ci if (tb) 39162306a36Sopenharmony_ci err = fib_table_lookup(tb, flp, res, flags); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ciout: 39462306a36Sopenharmony_ci if (err == -EAGAIN) 39562306a36Sopenharmony_ci err = -ENETUNREACH; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci rcu_read_unlock(); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci return err; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cistatic inline bool fib4_has_custom_rules(const struct net *net) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci return net->ipv4.fib_has_custom_rules; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cibool fib4_rule_default(const struct fib_rule *rule); 40862306a36Sopenharmony_ciint fib4_rules_dump(struct net *net, struct notifier_block *nb, 40962306a36Sopenharmony_ci struct netlink_ext_ack *extack); 41062306a36Sopenharmony_ciunsigned int fib4_rules_seq_read(struct net *net); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic inline bool fib4_rules_early_flow_dissect(struct net *net, 41362306a36Sopenharmony_ci struct sk_buff *skb, 41462306a36Sopenharmony_ci struct flowi4 *fl4, 41562306a36Sopenharmony_ci struct flow_keys *flkeys) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (!net->ipv4.fib_rules_require_fldissect) 42062306a36Sopenharmony_ci return false; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci memset(flkeys, 0, sizeof(*flkeys)); 42362306a36Sopenharmony_ci __skb_flow_dissect(net, skb, &flow_keys_dissector, 42462306a36Sopenharmony_ci flkeys, NULL, 0, 0, 0, flag); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci fl4->fl4_sport = flkeys->ports.src; 42762306a36Sopenharmony_ci fl4->fl4_dport = flkeys->ports.dst; 42862306a36Sopenharmony_ci fl4->flowi4_proto = flkeys->basic.ip_proto; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci return true; 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci#endif /* CONFIG_IP_MULTIPLE_TABLES */ 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci/* Exported by fib_frontend.c */ 43662306a36Sopenharmony_ciextern const struct nla_policy rtm_ipv4_policy[]; 43762306a36Sopenharmony_civoid ip_fib_init(void); 43862306a36Sopenharmony_ciint fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla, 43962306a36Sopenharmony_ci struct netlink_ext_ack *extack); 44062306a36Sopenharmony_ci__be32 fib_compute_spec_dst(struct sk_buff *skb); 44162306a36Sopenharmony_cibool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev); 44262306a36Sopenharmony_ciint fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, 44362306a36Sopenharmony_ci u8 tos, int oif, struct net_device *dev, 44462306a36Sopenharmony_ci struct in_device *idev, u32 *itag); 44562306a36Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 44662306a36Sopenharmony_cistatic inline int fib_num_tclassid_users(struct net *net) 44762306a36Sopenharmony_ci{ 44862306a36Sopenharmony_ci return atomic_read(&net->ipv4.fib_num_tclassid_users); 44962306a36Sopenharmony_ci} 45062306a36Sopenharmony_ci#else 45162306a36Sopenharmony_cistatic inline int fib_num_tclassid_users(struct net *net) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci return 0; 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci#endif 45662306a36Sopenharmony_ciint fib_unmerge(struct net *net); 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc, 45962306a36Sopenharmony_ciconst struct net_device *dev) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci if (nhc->nhc_dev == dev || 46262306a36Sopenharmony_ci l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) 46362306a36Sopenharmony_ci return true; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci return false; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci/* Exported by fib_semantics.c */ 46962306a36Sopenharmony_ciint ip_fib_check_default(__be32 gw, struct net_device *dev); 47062306a36Sopenharmony_ciint fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force); 47162306a36Sopenharmony_ciint fib_sync_down_addr(struct net_device *dev, __be32 local); 47262306a36Sopenharmony_ciint fib_sync_up(struct net_device *dev, unsigned char nh_flags); 47362306a36Sopenharmony_civoid fib_sync_mtu(struct net_device *dev, u32 orig_mtu); 47462306a36Sopenharmony_civoid fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig); 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci/* Fields used for sysctl_fib_multipath_hash_fields. 47762306a36Sopenharmony_ci * Common to IPv4 and IPv6. 47862306a36Sopenharmony_ci * 47962306a36Sopenharmony_ci * Add new fields at the end. This is user API. 48062306a36Sopenharmony_ci */ 48162306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_SRC_IP BIT(0) 48262306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_DST_IP BIT(1) 48362306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_IP_PROTO BIT(2) 48462306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_FLOWLABEL BIT(3) 48562306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_SRC_PORT BIT(4) 48662306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_DST_PORT BIT(5) 48762306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP BIT(6) 48862306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP BIT(7) 48962306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO BIT(8) 49062306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL BIT(9) 49162306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT BIT(10) 49262306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT BIT(11) 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_OUTER_MASK \ 49562306a36Sopenharmony_ci (FIB_MULTIPATH_HASH_FIELD_SRC_IP | \ 49662306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_DST_IP | \ 49762306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_IP_PROTO | \ 49862306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_FLOWLABEL | \ 49962306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_SRC_PORT | \ 50062306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_DST_PORT) 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_INNER_MASK \ 50362306a36Sopenharmony_ci (FIB_MULTIPATH_HASH_FIELD_INNER_SRC_IP | \ 50462306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_DST_IP | \ 50562306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_IP_PROTO | \ 50662306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_FLOWLABEL | \ 50762306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_SRC_PORT | \ 50862306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_DST_PORT) 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_ALL_MASK \ 51162306a36Sopenharmony_ci (FIB_MULTIPATH_HASH_FIELD_OUTER_MASK | \ 51262306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_INNER_MASK) 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci#define FIB_MULTIPATH_HASH_FIELD_DEFAULT_MASK \ 51562306a36Sopenharmony_ci (FIB_MULTIPATH_HASH_FIELD_SRC_IP | \ 51662306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_DST_IP | \ 51762306a36Sopenharmony_ci FIB_MULTIPATH_HASH_FIELD_IP_PROTO) 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_MULTIPATH 52062306a36Sopenharmony_ciint fib_multipath_hash(const struct net *net, const struct flowi4 *fl4, 52162306a36Sopenharmony_ci const struct sk_buff *skb, struct flow_keys *flkeys); 52262306a36Sopenharmony_ci#endif 52362306a36Sopenharmony_ciint fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope, 52462306a36Sopenharmony_ci struct netlink_ext_ack *extack); 52562306a36Sopenharmony_civoid fib_select_multipath(struct fib_result *res, int hash); 52662306a36Sopenharmony_civoid fib_select_path(struct net *net, struct fib_result *res, 52762306a36Sopenharmony_ci struct flowi4 *fl4, const struct sk_buff *skb); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ciint fib_nh_init(struct net *net, struct fib_nh *fib_nh, 53062306a36Sopenharmony_ci struct fib_config *cfg, int nh_weight, 53162306a36Sopenharmony_ci struct netlink_ext_ack *extack); 53262306a36Sopenharmony_civoid fib_nh_release(struct net *net, struct fib_nh *fib_nh); 53362306a36Sopenharmony_ciint fib_nh_common_init(struct net *net, struct fib_nh_common *nhc, 53462306a36Sopenharmony_ci struct nlattr *fc_encap, u16 fc_encap_type, 53562306a36Sopenharmony_ci void *cfg, gfp_t gfp_flags, 53662306a36Sopenharmony_ci struct netlink_ext_ack *extack); 53762306a36Sopenharmony_civoid fib_nh_common_release(struct fib_nh_common *nhc); 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci/* Exported by fib_trie.c */ 54062306a36Sopenharmony_civoid fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri); 54162306a36Sopenharmony_civoid fib_trie_init(void); 54262306a36Sopenharmony_cistruct fib_table *fib_trie_table(u32 id, struct fib_table *alias); 54362306a36Sopenharmony_cibool fib_lookup_good_nhc(const struct fib_nh_common *nhc, int fib_flags, 54462306a36Sopenharmony_ci const struct flowi4 *flp); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_cistatic inline void fib_combine_itag(u32 *itag, const struct fib_result *res) 54762306a36Sopenharmony_ci{ 54862306a36Sopenharmony_ci#ifdef CONFIG_IP_ROUTE_CLASSID 54962306a36Sopenharmony_ci struct fib_nh_common *nhc = res->nhc; 55062306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 55162306a36Sopenharmony_ci u32 rtag; 55262306a36Sopenharmony_ci#endif 55362306a36Sopenharmony_ci if (nhc->nhc_family == AF_INET) { 55462306a36Sopenharmony_ci struct fib_nh *nh; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci nh = container_of(nhc, struct fib_nh, nh_common); 55762306a36Sopenharmony_ci *itag = nh->nh_tclassid << 16; 55862306a36Sopenharmony_ci } else { 55962306a36Sopenharmony_ci *itag = 0; 56062306a36Sopenharmony_ci } 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci#ifdef CONFIG_IP_MULTIPLE_TABLES 56362306a36Sopenharmony_ci rtag = res->tclassid; 56462306a36Sopenharmony_ci if (*itag == 0) 56562306a36Sopenharmony_ci *itag = (rtag<<16); 56662306a36Sopenharmony_ci *itag |= (rtag>>16); 56762306a36Sopenharmony_ci#endif 56862306a36Sopenharmony_ci#endif 56962306a36Sopenharmony_ci} 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_civoid fib_flush(struct net *net); 57262306a36Sopenharmony_civoid free_fib_info(struct fib_info *fi); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic inline void fib_info_hold(struct fib_info *fi) 57562306a36Sopenharmony_ci{ 57662306a36Sopenharmony_ci refcount_inc(&fi->fib_clntref); 57762306a36Sopenharmony_ci} 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic inline void fib_info_put(struct fib_info *fi) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci if (refcount_dec_and_test(&fi->fib_clntref)) 58262306a36Sopenharmony_ci free_fib_info(fi); 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 58662306a36Sopenharmony_ciint __net_init fib_proc_init(struct net *net); 58762306a36Sopenharmony_civoid __net_exit fib_proc_exit(struct net *net); 58862306a36Sopenharmony_ci#else 58962306a36Sopenharmony_cistatic inline int fib_proc_init(struct net *net) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci return 0; 59262306a36Sopenharmony_ci} 59362306a36Sopenharmony_cistatic inline void fib_proc_exit(struct net *net) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci#endif 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ciu32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ciint ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh, 60162306a36Sopenharmony_ci struct fib_dump_filter *filter, 60262306a36Sopenharmony_ci struct netlink_callback *cb); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ciint fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh, 60562306a36Sopenharmony_ci u8 rt_family, unsigned char *flags, bool skip_oif); 60662306a36Sopenharmony_ciint fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh, 60762306a36Sopenharmony_ci int nh_weight, u8 rt_family, u32 nh_tclassid); 60862306a36Sopenharmony_ci#endif /* _NET_FIB_H */ 609