#define pr_fmt(fmt) …
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <linux/types.h>
#include <linux/times.h>
#include <linux/socket.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/route.h>
#include <linux/netdevice.h>
#include <linux/in6.h>
#include <linux/mroute6.h>
#include <linux/init.h>
#include <linux/if_arp.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/nsproxy.h>
#include <linux/slab.h>
#include <linux/jhash.h>
#include <linux/siphash.h>
#include <net/net_namespace.h>
#include <net/snmp.h>
#include <net/ipv6.h>
#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#include <net/ndisc.h>
#include <net/addrconf.h>
#include <net/tcp.h>
#include <linux/rtnetlink.h>
#include <net/dst.h>
#include <net/dst_metadata.h>
#include <net/xfrm.h>
#include <net/netevent.h>
#include <net/netlink.h>
#include <net/rtnh.h>
#include <net/lwtunnel.h>
#include <net/ip_tunnels.h>
#include <net/l3mdev.h>
#include <net/ip.h>
#include <linux/uaccess.h>
#include <linux/btf_ids.h>
#ifdef CONFIG_SYSCTL
#include <linux/sysctl.h>
#endif
static int ip6_rt_type_to_error(u8 fib6_type);
#define CREATE_TRACE_POINTS
#include <trace/events/fib6.h>
EXPORT_TRACEPOINT_SYMBOL_GPL(…);
#undef CREATE_TRACE_POINTS
enum rt6_nud_state { … };
INDIRECT_CALLABLE_SCOPE
struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
INDIRECT_CALLABLE_SCOPE
unsigned int ip6_mtu(const struct dst_entry *dst);
static void ip6_negative_advice(struct sock *sk,
struct dst_entry *dst);
static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *,
struct net_device *dev);
static void ip6_dst_gc(struct dst_ops *ops);
static int ip6_pkt_discard(struct sk_buff *skb);
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static int ip6_pkt_prohibit(struct sk_buff *skb);
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb);
static void ip6_link_failure(struct sk_buff *skb);
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu,
bool confirm_neigh);
static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb);
static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
int strict);
static size_t rt6_nlmsg_size(struct fib6_info *f6i);
static int rt6_fill_node(struct net *net, struct sk_buff *skb,
struct fib6_info *rt, struct dst_entry *dst,
struct in6_addr *dest, struct in6_addr *src,
int iif, int type, u32 portid, u32 seq,
unsigned int flags);
static struct rt6_info *rt6_find_cached_rt(const struct fib6_result *res,
const struct in6_addr *daddr,
const struct in6_addr *saddr);
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct fib6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr,
struct net_device *dev,
unsigned int pref);
static struct fib6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr,
struct net_device *dev);
#endif
struct uncached_list { … };
static DEFINE_PER_CPU_ALIGNED(struct uncached_list, rt6_uncached_list);
void rt6_uncached_list_add(struct rt6_info *rt)
{ … }
void rt6_uncached_list_del(struct rt6_info *rt)
{ … }
static void rt6_uncached_list_flush_dev(struct net_device *dev)
{ … }
static inline const void *choose_neigh_daddr(const struct in6_addr *p,
struct sk_buff *skb,
const void *daddr)
{ … }
struct neighbour *ip6_neigh_lookup(const struct in6_addr *gw,
struct net_device *dev,
struct sk_buff *skb,
const void *daddr)
{ … }
static struct neighbour *ip6_dst_neigh_lookup(const struct dst_entry *dst,
struct sk_buff *skb,
const void *daddr)
{ … }
static void ip6_confirm_neigh(const struct dst_entry *dst, const void *daddr)
{ … }
static struct dst_ops ip6_dst_ops_template = …;
static struct dst_ops ip6_dst_blackhole_ops = …;
static const u32 ip6_template_metrics[RTAX_MAX] = …;
static const struct fib6_info fib6_null_entry_template = …;
static const struct rt6_info ip6_null_entry_template = …;
#ifdef CONFIG_IPV6_MULTIPLE_TABLES
static const struct rt6_info ip6_prohibit_entry_template = …;
static const struct rt6_info ip6_blk_hole_entry_template = …;
#endif
static void rt6_info_init(struct rt6_info *rt)
{ … }
struct rt6_info *ip6_dst_alloc(struct net *net, struct net_device *dev,
int flags)
{ … }
EXPORT_SYMBOL(…);
static void ip6_dst_destroy(struct dst_entry *dst)
{ … }
static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
{ … }
static bool __rt6_check_expired(const struct rt6_info *rt)
{ … }
static bool rt6_check_expired(const struct rt6_info *rt)
{ … }
void fib6_select_path(const struct net *net, struct fib6_result *res,
struct flowi6 *fl6, int oif, bool have_oif_match,
const struct sk_buff *skb, int strict)
{ … }
static bool __rt6_device_match(struct net *net, const struct fib6_nh *nh,
const struct in6_addr *saddr, int oif, int flags)
{ … }
struct fib6_nh_dm_arg { … };
static int __rt6_nh_dev_match(struct fib6_nh *nh, void *_arg)
{ … }
static struct fib6_nh *rt6_nh_dev_match(struct net *net, struct nexthop *nh,
struct fib6_result *res,
const struct in6_addr *saddr,
int oif, int flags)
{ … }
static void rt6_device_match(struct net *net, struct fib6_result *res,
const struct in6_addr *saddr, int oif, int flags)
{ … }
#ifdef CONFIG_IPV6_ROUTER_PREF
struct __rt6_probe_work { … };
static void rt6_probe_deferred(struct work_struct *w)
{ … }
static void rt6_probe(struct fib6_nh *fib6_nh)
{ … }
#else
static inline void rt6_probe(struct fib6_nh *fib6_nh)
{
}
#endif
static enum rt6_nud_state rt6_check_neigh(const struct fib6_nh *fib6_nh)
{ … }
static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
int strict)
{ … }
static bool find_match(struct fib6_nh *nh, u32 fib6_flags,
int oif, int strict, int *mpri, bool *do_rr)
{ … }
struct fib6_nh_frl_arg { … };
static int rt6_nh_find_match(struct fib6_nh *nh, void *_arg)
{ … }
static void __find_rr_leaf(struct fib6_info *f6i_start,
struct fib6_info *nomatch, u32 metric,
struct fib6_result *res, struct fib6_info **cont,
int oif, int strict, bool *do_rr, int *mpri)
{ … }
static void find_rr_leaf(struct fib6_node *fn, struct fib6_info *leaf,
struct fib6_info *rr_head, int oif, int strict,
bool *do_rr, struct fib6_result *res)
{ … }
static void rt6_select(struct net *net, struct fib6_node *fn, int oif,
struct fib6_result *res, int strict)
{ … }
static bool rt6_is_gw_or_nonexthop(const struct fib6_result *res)
{ … }
#ifdef CONFIG_IPV6_ROUTE_INFO
int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
const struct in6_addr *gwaddr)
{ … }
#endif
static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res)
{ … }
static const int fib6_prop[RTN_MAX + 1] = …;
static int ip6_rt_type_to_error(u8 fib6_type)
{ … }
static unsigned short fib6_info_dst_flags(struct fib6_info *rt)
{ … }
static void ip6_rt_init_dst_reject(struct rt6_info *rt, u8 fib6_type)
{ … }
static void ip6_rt_init_dst(struct rt6_info *rt, const struct fib6_result *res)
{ … }
static void rt6_set_from(struct rt6_info *rt, struct fib6_info *from)
{ … }
static void ip6_rt_copy_init(struct rt6_info *rt, const struct fib6_result *res)
{ … }
static struct fib6_node* fib6_backtrack(struct fib6_node *fn,
struct in6_addr *saddr)
{ … }
static bool ip6_hold_safe(struct net *net, struct rt6_info **prt)
{ … }
static struct rt6_info *ip6_create_rt_rcu(const struct fib6_result *res)
{ … }
INDIRECT_CALLABLE_SCOPE struct rt6_info *ip6_pol_route_lookup(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6,
const struct sk_buff *skb,
int flags)
{ … }
struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,
const struct sk_buff *skb, int flags)
{ … }
EXPORT_SYMBOL_GPL(…);
struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
const struct in6_addr *saddr, int oif,
const struct sk_buff *skb, int strict)
{ … }
EXPORT_SYMBOL(…);
static int __ip6_ins_rt(struct fib6_info *rt, struct nl_info *info,
struct netlink_ext_ack *extack)
{ … }
int ip6_ins_rt(struct net *net, struct fib6_info *rt)
{ … }
static struct rt6_info *ip6_rt_cache_alloc(const struct fib6_result *res,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{ … }
static struct rt6_info *ip6_rt_pcpu_alloc(const struct fib6_result *res)
{ … }
static bool rt6_is_valid(const struct rt6_info *rt6)
{ … }
static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)
{ … }
static struct rt6_info *rt6_make_pcpu_route(struct net *net,
const struct fib6_result *res)
{ … }
static DEFINE_SPINLOCK(rt6_exception_lock);
static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
struct rt6_exception *rt6_ex)
{ … }
static void rt6_exception_remove_oldest(struct rt6_exception_bucket *bucket)
{ … }
static u32 rt6_exception_hash(const struct in6_addr *dst,
const struct in6_addr *src)
{ … }
static struct rt6_exception *
__rt6_find_exception_spinlock(struct rt6_exception_bucket **bucket,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{ … }
static struct rt6_exception *
__rt6_find_exception_rcu(struct rt6_exception_bucket **bucket,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{ … }
static unsigned int fib6_mtu(const struct fib6_result *res)
{ … }
#define FIB6_EXCEPTION_BUCKET_FLUSHED …
static
struct rt6_exception_bucket *fib6_nh_get_excptn_bucket(const struct fib6_nh *nh,
spinlock_t *lock)
{ … }
static bool fib6_nh_excptn_bucket_flushed(struct rt6_exception_bucket *bucket)
{ … }
static void fib6_nh_excptn_bucket_set_flushed(struct fib6_nh *nh,
spinlock_t *lock)
{ … }
static int rt6_insert_exception(struct rt6_info *nrt,
const struct fib6_result *res)
{ … }
static void fib6_nh_flush_exceptions(struct fib6_nh *nh, struct fib6_info *from)
{ … }
static int rt6_nh_flush_exceptions(struct fib6_nh *nh, void *arg)
{ … }
void rt6_flush_exceptions(struct fib6_info *f6i)
{ … }
static struct rt6_info *rt6_find_cached_rt(const struct fib6_result *res,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{ … }
static int fib6_nh_remove_exception(const struct fib6_nh *nh, int plen,
const struct rt6_info *rt)
{ … }
struct fib6_nh_excptn_arg { … };
static int rt6_nh_remove_exception_rt(struct fib6_nh *nh, void *_arg)
{ … }
static int rt6_remove_exception_rt(struct rt6_info *rt)
{ … }
static void fib6_nh_update_exception(const struct fib6_nh *nh, int plen,
const struct rt6_info *rt)
{ … }
struct fib6_nh_match_arg { … };
static int fib6_nh_find_match(struct fib6_nh *nh, void *_arg)
{ … }
static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
{ … }
static bool rt6_mtu_change_route_allowed(struct inet6_dev *idev,
struct rt6_info *rt, int mtu)
{ … }
static void rt6_exceptions_update_pmtu(struct inet6_dev *idev,
const struct fib6_nh *nh, int mtu)
{ … }
#define RTF_CACHE_GATEWAY …
static void fib6_nh_exceptions_clean_tohost(const struct fib6_nh *nh,
const struct in6_addr *gateway)
{ … }
static void rt6_age_examine_exception(struct rt6_exception_bucket *bucket,
struct rt6_exception *rt6_ex,
struct fib6_gc_args *gc_args,
unsigned long now)
{ … }
static void fib6_nh_age_exceptions(const struct fib6_nh *nh,
struct fib6_gc_args *gc_args,
unsigned long now)
{ … }
struct fib6_nh_age_excptn_arg { … };
static int rt6_nh_age_exceptions(struct fib6_nh *nh, void *_arg)
{ … }
void rt6_age_exceptions(struct fib6_info *f6i,
struct fib6_gc_args *gc_args,
unsigned long now)
{ … }
int fib6_table_lookup(struct net *net, struct fib6_table *table, int oif,
struct flowi6 *fl6, struct fib6_result *res, int strict)
{ … }
struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
int oif, struct flowi6 *fl6,
const struct sk_buff *skb, int flags)
{ … }
EXPORT_SYMBOL_GPL(…);
INDIRECT_CALLABLE_SCOPE struct rt6_info *ip6_pol_route_input(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6,
const struct sk_buff *skb,
int flags)
{ … }
struct dst_entry *ip6_route_input_lookup(struct net *net,
struct net_device *dev,
struct flowi6 *fl6,
const struct sk_buff *skb,
int flags)
{ … }
EXPORT_SYMBOL_GPL(…);
static void ip6_multipath_l3_keys(const struct sk_buff *skb,
struct flow_keys *keys,
struct flow_keys *flkeys)
{ … }
static u32 rt6_multipath_custom_hash_outer(const struct net *net,
const struct sk_buff *skb,
bool *p_has_inner)
{ … }
static u32 rt6_multipath_custom_hash_inner(const struct net *net,
const struct sk_buff *skb,
bool has_inner)
{ … }
static u32 rt6_multipath_custom_hash_skb(const struct net *net,
const struct sk_buff *skb)
{ … }
static u32 rt6_multipath_custom_hash_fl6(const struct net *net,
const struct flowi6 *fl6)
{ … }
u32 rt6_multipath_hash(const struct net *net, const struct flowi6 *fl6,
const struct sk_buff *skb, struct flow_keys *flkeys)
{ … }
void ip6_route_input(struct sk_buff *skb)
{ … }
INDIRECT_CALLABLE_SCOPE struct rt6_info *ip6_pol_route_output(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6,
const struct sk_buff *skb,
int flags)
{ … }
static struct dst_entry *ip6_route_output_flags_noref(struct net *net,
const struct sock *sk,
struct flowi6 *fl6,
int flags)
{ … }
struct dst_entry *ip6_route_output_flags(struct net *net,
const struct sock *sk,
struct flowi6 *fl6,
int flags)
{ … }
EXPORT_SYMBOL_GPL(…);
struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
{ … }
static bool fib6_check(struct fib6_info *f6i, u32 cookie)
{ … }
static struct dst_entry *rt6_check(struct rt6_info *rt,
struct fib6_info *from,
u32 cookie)
{ … }
static struct dst_entry *rt6_dst_from_check(struct rt6_info *rt,
struct fib6_info *from,
u32 cookie)
{ … }
INDIRECT_CALLABLE_SCOPE struct dst_entry *ip6_dst_check(struct dst_entry *dst,
u32 cookie)
{ … }
EXPORT_INDIRECT_CALLABLE(…);
static void ip6_negative_advice(struct sock *sk,
struct dst_entry *dst)
{ … }
static void ip6_link_failure(struct sk_buff *skb)
{ … }
static void rt6_update_expires(struct rt6_info *rt0, int timeout)
{ … }
static void rt6_do_update_pmtu(struct rt6_info *rt, u32 mtu)
{ … }
static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
{ … }
static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
const struct ipv6hdr *iph, u32 mtu,
bool confirm_neigh)
{ … }
static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu,
bool confirm_neigh)
{ … }
void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
int oif, u32 mark, kuid_t uid)
{ … }
EXPORT_SYMBOL_GPL(…);
void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
{ … }
EXPORT_SYMBOL_GPL(…);
void ip6_sk_dst_store_flow(struct sock *sk, struct dst_entry *dst,
const struct flowi6 *fl6)
{ … }
static bool ip6_redirect_nh_match(const struct fib6_result *res,
struct flowi6 *fl6,
const struct in6_addr *gw,
struct rt6_info **ret)
{ … }
struct fib6_nh_rd_arg { … };
static int fib6_nh_redirect_match(struct fib6_nh *nh, void *_arg)
{ … }
struct ip6rd_flowi { … };
INDIRECT_CALLABLE_SCOPE struct rt6_info *__ip6_route_redirect(struct net *net,
struct fib6_table *table,
struct flowi6 *fl6,
const struct sk_buff *skb,
int flags)
{
struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
struct rt6_info *ret = NULL;
struct fib6_result res = {};
struct fib6_nh_rd_arg arg = {
.res = &res,
.fl6 = fl6,
.gw = &rdfl->gateway,
.ret = &ret
};
struct fib6_info *rt;
struct fib6_node *fn;
rcu_read_lock();
fn = fib6_node_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
restart:
for_each_fib6_node_rt_rcu(fn) {
res.f6i = rt;
if (fib6_check_expired(rt))
continue;
if (rt->fib6_flags & RTF_REJECT)
break;
if (unlikely(rt->nh)) {
if (nexthop_is_blackhole(rt->nh))
continue;
if (nexthop_for_each_fib6_nh(rt->nh,
fib6_nh_redirect_match,
&arg))
goto out;
} else {
res.nh = rt->fib6_nh;
if (ip6_redirect_nh_match(&res, fl6, &rdfl->gateway,
&ret))
goto out;
}
}
if (!rt)
rt = net->ipv6.fib6_null_entry;
else if (rt->fib6_flags & RTF_REJECT) {
ret = net->ipv6.ip6_null_entry;
goto out;
}
if (rt == net->ipv6.fib6_null_entry) {
fn = fib6_backtrack(fn, &fl6->saddr);
if (fn)
goto restart;
}
res.f6i = rt;
res.nh = rt->fib6_nh;
out:
if (ret) {
ip6_hold_safe(net, &ret);
} else {
res.fib6_flags = res.f6i->fib6_flags;
res.fib6_type = res.f6i->fib6_type;
ret = ip6_create_rt_rcu(&res);
}
rcu_read_unlock();
trace_fib6_table_lookup(net, &res, table, fl6);
return ret;
};
static struct dst_entry *ip6_route_redirect(struct net *net,
const struct flowi6 *fl6,
const struct sk_buff *skb,
const struct in6_addr *gateway)
{ … }
void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark,
kuid_t uid)
{ … }
EXPORT_SYMBOL_GPL(…);
void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif)
{ … }
void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
{ … }
EXPORT_SYMBOL_GPL(…);
static unsigned int ip6_default_advmss(const struct dst_entry *dst)
{ … }
INDIRECT_CALLABLE_SCOPE unsigned int ip6_mtu(const struct dst_entry *dst)
{ … }
EXPORT_INDIRECT_CALLABLE(…);
u32 ip6_mtu_from_fib6(const struct fib6_result *res,
const struct in6_addr *daddr,
const struct in6_addr *saddr)
{ … }
struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
struct flowi6 *fl6)
{ … }
static void ip6_dst_gc(struct dst_ops *ops)
{ … }
static int ip6_nh_lookup_table(struct net *net, struct fib6_config *cfg,
const struct in6_addr *gw_addr, u32 tbid,
int flags, struct fib6_result *res)
{ … }
static int ip6_route_check_nh_onlink(struct net *net,
struct fib6_config *cfg,
const struct net_device *dev,
struct netlink_ext_ack *extack)
{ … }
static int ip6_route_check_nh(struct net *net,
struct fib6_config *cfg,
struct net_device **_dev,
netdevice_tracker *dev_tracker,
struct inet6_dev **idev)
{ … }
static int ip6_validate_gw(struct net *net, struct fib6_config *cfg,
struct net_device **_dev,
netdevice_tracker *dev_tracker,
struct inet6_dev **idev,
struct netlink_ext_ack *extack)
{ … }
static bool fib6_is_reject(u32 flags, struct net_device *dev, int addr_type)
{ … }
int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
struct fib6_config *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{ … }
void fib6_nh_release(struct fib6_nh *fib6_nh)
{ … }
void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
{ … }
static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{ … }
int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{ … }
static int __ip6_del_rt(struct fib6_info *rt, struct nl_info *info)
{ … }
int ip6_del_rt(struct net *net, struct fib6_info *rt, bool skip_notify)
{ … }
static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)
{ … }
static int __ip6_del_cached_rt(struct rt6_info *rt, struct fib6_config *cfg)
{ … }
static int ip6_del_cached_rt(struct fib6_config *cfg, struct fib6_info *rt,
struct fib6_nh *nh)
{ … }
struct fib6_nh_del_cached_rt_arg { … };
static int fib6_nh_del_cached_rt(struct fib6_nh *nh, void *_arg)
{ … }
static int ip6_del_cached_rt_nh(struct fib6_config *cfg, struct fib6_info *f6i)
{ … }
static int ip6_route_del(struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{ … }
static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb)
{ … }
#ifdef CONFIG_IPV6_ROUTE_INFO
static struct fib6_info *rt6_get_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr,
struct net_device *dev)
{ … }
static struct fib6_info *rt6_add_route_info(struct net *net,
const struct in6_addr *prefix, int prefixlen,
const struct in6_addr *gwaddr,
struct net_device *dev,
unsigned int pref)
{ … }
#endif
struct fib6_info *rt6_get_dflt_router(struct net *net,
const struct in6_addr *addr,
struct net_device *dev)
{ … }
struct fib6_info *rt6_add_dflt_router(struct net *net,
const struct in6_addr *gwaddr,
struct net_device *dev,
unsigned int pref,
u32 defrtr_usr_metric,
int lifetime)
{ … }
static void __rt6_purge_dflt_routers(struct net *net,
struct fib6_table *table)
{ … }
void rt6_purge_dflt_routers(struct net *net)
{ … }
static void rtmsg_to_fib6_config(struct net *net,
struct in6_rtmsg *rtmsg,
struct fib6_config *cfg)
{ … }
int ipv6_route_ioctl(struct net *net, unsigned int cmd, struct in6_rtmsg *rtmsg)
{ … }
static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
{ … }
static int ip6_pkt_discard(struct sk_buff *skb)
{ … }
static int ip6_pkt_discard_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{ … }
static int ip6_pkt_prohibit(struct sk_buff *skb)
{ … }
static int ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb)
{ … }
struct fib6_info *addrconf_f6i_alloc(struct net *net,
struct inet6_dev *idev,
const struct in6_addr *addr,
bool anycast, gfp_t gfp_flags,
struct netlink_ext_ack *extack)
{ … }
struct arg_dev_net_ip { … };
static int fib6_remove_prefsrc(struct fib6_info *rt, void *arg)
{ … }
void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
{ … }
#define RTF_RA_ROUTER …
static int fib6_clean_tohost(struct fib6_info *rt, void *arg)
{ … }
void rt6_clean_tohost(struct net *net, struct in6_addr *gateway)
{ … }
struct arg_netdev_event { … };
static struct fib6_info *rt6_multipath_first_sibling(const struct fib6_info *rt)
{ … }
static bool rt6_is_dead(const struct fib6_info *rt)
{ … }
static int rt6_multipath_total_weight(const struct fib6_info *rt)
{ … }
static void rt6_upper_bound_set(struct fib6_info *rt, int *weight, int total)
{ … }
static void rt6_multipath_upper_bound_set(struct fib6_info *rt, int total)
{ … }
void rt6_multipath_rebalance(struct fib6_info *rt)
{ … }
static int fib6_ifup(struct fib6_info *rt, void *p_arg)
{ … }
void rt6_sync_up(struct net_device *dev, unsigned char nh_flags)
{ … }
static bool rt6_multipath_uses_dev(const struct fib6_info *rt,
const struct net_device *dev)
{ … }
static void rt6_multipath_flush(struct fib6_info *rt)
{ … }
static unsigned int rt6_multipath_dead_count(const struct fib6_info *rt,
const struct net_device *down_dev)
{ … }
static void rt6_multipath_nh_flags_set(struct fib6_info *rt,
const struct net_device *dev,
unsigned char nh_flags)
{ … }
static int fib6_ifdown(struct fib6_info *rt, void *p_arg)
{ … }
void rt6_sync_down_dev(struct net_device *dev, unsigned long event)
{ … }
void rt6_disable_ip(struct net_device *dev, unsigned long event)
{ … }
struct rt6_mtu_change_arg { … };
static int fib6_nh_mtu_change(struct fib6_nh *nh, void *_arg)
{ … }
static int rt6_mtu_change_route(struct fib6_info *f6i, void *p_arg)
{ … }
void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
{ … }
static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = …;
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{ … }
struct rt6_nh { … };
static int ip6_route_info_append(struct net *net,
struct list_head *rt6_nh_list,
struct fib6_info *rt,
struct fib6_config *r_cfg)
{ … }
static void ip6_route_mpath_notify(struct fib6_info *rt,
struct fib6_info *rt_last,
struct nl_info *info,
__u16 nlflags)
{ … }
static bool ip6_route_mpath_should_notify(const struct fib6_info *rt)
{ … }
static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla,
struct netlink_ext_ack *extack)
{ … }
static int ip6_route_multipath_add(struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{ … }
static int ip6_route_multipath_del(struct fib6_config *cfg,
struct netlink_ext_ack *extack)
{ … }
static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{ … }
static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{ … }
static int rt6_nh_nlmsg_size(struct fib6_nh *nh, void *arg)
{ … }
static size_t rt6_nlmsg_size(struct fib6_info *f6i)
{ … }
static int rt6_fill_node_nexthop(struct sk_buff *skb, struct nexthop *nh,
unsigned char *flags)
{ … }
static int rt6_fill_node(struct net *net, struct sk_buff *skb,
struct fib6_info *rt, struct dst_entry *dst,
struct in6_addr *dest, struct in6_addr *src,
int iif, int type, u32 portid, u32 seq,
unsigned int flags)
{ … }
static int fib6_info_nh_uses_dev(struct fib6_nh *nh, void *arg)
{ … }
static bool fib6_info_uses_dev(const struct fib6_info *f6i,
const struct net_device *dev)
{ … }
struct fib6_nh_exception_dump_walker { … };
static int rt6_nh_dump_exceptions(struct fib6_nh *nh, void *arg)
{ … }
int rt6_dump_route(struct fib6_info *rt, void *p_arg, unsigned int skip)
{ … }
static int inet6_rtm_valid_getroute_req(struct sk_buff *skb,
const struct nlmsghdr *nlh,
struct nlattr **tb,
struct netlink_ext_ack *extack)
{ … }
static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{ … }
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
unsigned int nlm_flags)
{ … }
void fib6_rt_update(struct net *net, struct fib6_info *rt,
struct nl_info *info)
{ … }
void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
bool offload, bool trap, bool offload_failed)
{ … }
EXPORT_SYMBOL(…);
static int ip6_route_dev_notify(struct notifier_block *this,
unsigned long event, void *ptr)
{ … }
#ifdef CONFIG_PROC_FS
static int rt6_stats_seq_show(struct seq_file *seq, void *v)
{ … }
#endif
#ifdef CONFIG_SYSCTL
static int ipv6_sysctl_rtcache_flush(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{ … }
static struct ctl_table ipv6_route_table_template[] = …;
struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
{ … }
size_t ipv6_route_sysctl_table_size(struct net *net)
{ … }
#endif
static int __net_init ip6_route_net_init(struct net *net)
{ … }
static void __net_exit ip6_route_net_exit(struct net *net)
{ … }
static int __net_init ip6_route_net_init_late(struct net *net)
{ … }
static void __net_exit ip6_route_net_exit_late(struct net *net)
{ … }
static struct pernet_operations ip6_route_net_ops = …;
static int __net_init ipv6_inetpeer_init(struct net *net)
{ … }
static void __net_exit ipv6_inetpeer_exit(struct net *net)
{ … }
static struct pernet_operations ipv6_inetpeer_ops = …;
static struct pernet_operations ip6_route_net_late_ops = …;
static struct notifier_block ip6_route_dev_notifier = …;
void __init ip6_route_init_special_entries(void)
{ … }
#if IS_BUILTIN(CONFIG_IPV6)
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
DEFINE_BPF_ITER_FUNC(ipv6_route, struct bpf_iter_meta *meta, struct fib6_info *rt)
BTF_ID_LIST(btf_fib6_info_id)
BTF_ID(…)
static const struct bpf_iter_seq_info ipv6_route_seq_info = …;
static struct bpf_iter_reg ipv6_route_reg_info = …;
static int __init bpf_iter_register(void)
{ … }
static void bpf_iter_unregister(void)
{ … }
#endif
#endif
int __init ip6_route_init(void)
{ … }
void ip6_route_cleanup(void)
{ … }