1  /* SPDX-License-Identifier: GPL-2.0-or-later */
2  /*
3   *	Linux INET6 implementation
4   *
5   *	Authors:
6   *	Pedro Roque		<roque@di.fc.ul.pt>
7   */
8  
9  #ifndef _IP6_FIB_H
10  #define _IP6_FIB_H
11  
12  #include <linux/ipv6_route.h>
13  #include <linux/rtnetlink.h>
14  #include <linux/spinlock.h>
15  #include <linux/notifier.h>
16  #include <net/dst.h>
17  #include <net/flow.h>
18  #include <net/ip_fib.h>
19  #include <net/netlink.h>
20  #include <net/inetpeer.h>
21  #include <net/fib_notifier.h>
22  #include <linux/indirect_call_wrapper.h>
23  #include <uapi/linux/bpf.h>
24  
25  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
26  #define FIB6_TABLE_HASHSZ 256
27  #else
28  #define FIB6_TABLE_HASHSZ 1
29  #endif
30  
31  #define RT6_DEBUG 2
32  
33  struct rt6_info;
34  struct fib6_info;
35  
36  struct fib6_config {
37  	u32		fc_table;
38  	u32		fc_metric;
39  	int		fc_dst_len;
40  	int		fc_src_len;
41  	int		fc_ifindex;
42  	u32		fc_flags;
43  	u32		fc_protocol;
44  	u16		fc_type;        /* only 8 bits are used */
45  	u16		fc_delete_all_nh : 1,
46  			fc_ignore_dev_down:1,
47  			__unused : 14;
48  	u32		fc_nh_id;
49  
50  	struct in6_addr	fc_dst;
51  	struct in6_addr	fc_src;
52  	struct in6_addr	fc_prefsrc;
53  	struct in6_addr	fc_gateway;
54  
55  	unsigned long	fc_expires;
56  	struct nlattr	*fc_mx;
57  	int		fc_mx_len;
58  	int		fc_mp_len;
59  	struct nlattr	*fc_mp;
60  
61  	struct nl_info	fc_nlinfo;
62  	struct nlattr	*fc_encap;
63  	u16		fc_encap_type;
64  	bool		fc_is_fdb;
65  };
66  
67  struct fib6_node {
68  	struct fib6_node __rcu	*parent;
69  	struct fib6_node __rcu	*left;
70  	struct fib6_node __rcu	*right;
71  #ifdef CONFIG_IPV6_SUBTREES
72  	struct fib6_node __rcu	*subtree;
73  #endif
74  	struct fib6_info __rcu	*leaf;
75  
76  	__u16			fn_bit;		/* bit key */
77  	__u16			fn_flags;
78  	int			fn_sernum;
79  	struct fib6_info __rcu	*rr_ptr;
80  	struct rcu_head		rcu;
81  };
82  
83  struct fib6_gc_args {
84  	int			timeout;
85  	int			more;
86  };
87  
88  #ifndef CONFIG_IPV6_SUBTREES
89  #define FIB6_SUBTREE(fn)	NULL
90  
fib6_routes_require_src(const struct net * net)91  static inline bool fib6_routes_require_src(const struct net *net)
92  {
93  	return false;
94  }
95  
fib6_routes_require_src_inc(struct net * net)96  static inline void fib6_routes_require_src_inc(struct net *net) {}
fib6_routes_require_src_dec(struct net * net)97  static inline void fib6_routes_require_src_dec(struct net *net) {}
98  
99  #else
100  
fib6_routes_require_src(const struct net * net)101  static inline bool fib6_routes_require_src(const struct net *net)
102  {
103  	return net->ipv6.fib6_routes_require_src > 0;
104  }
105  
fib6_routes_require_src_inc(struct net * net)106  static inline void fib6_routes_require_src_inc(struct net *net)
107  {
108  	net->ipv6.fib6_routes_require_src++;
109  }
110  
fib6_routes_require_src_dec(struct net * net)111  static inline void fib6_routes_require_src_dec(struct net *net)
112  {
113  	net->ipv6.fib6_routes_require_src--;
114  }
115  
116  #define FIB6_SUBTREE(fn)	(rcu_dereference_protected((fn)->subtree, 1))
117  #endif
118  
119  /*
120   *	routing information
121   *
122   */
123  
124  struct rt6key {
125  	struct in6_addr	addr;
126  	int		plen;
127  };
128  
129  struct fib6_table;
130  
131  struct rt6_exception_bucket {
132  	struct hlist_head	chain;
133  	int			depth;
134  };
135  
136  struct rt6_exception {
137  	struct hlist_node	hlist;
138  	struct rt6_info		*rt6i;
139  	unsigned long		stamp;
140  	struct rcu_head		rcu;
141  };
142  
143  #define FIB6_EXCEPTION_BUCKET_SIZE_SHIFT 10
144  #define FIB6_EXCEPTION_BUCKET_SIZE (1 << FIB6_EXCEPTION_BUCKET_SIZE_SHIFT)
145  #define FIB6_MAX_DEPTH 5
146  
147  struct fib6_nh {
148  	struct fib_nh_common	nh_common;
149  
150  #ifdef CONFIG_IPV6_ROUTER_PREF
151  	unsigned long		last_probe;
152  #endif
153  
154  	struct rt6_info * __percpu *rt6i_pcpu;
155  	struct rt6_exception_bucket __rcu *rt6i_exception_bucket;
156  };
157  
158  struct fib6_info {
159  	struct fib6_table		*fib6_table;
160  	struct fib6_info __rcu		*fib6_next;
161  	struct fib6_node __rcu		*fib6_node;
162  
163  	/* Multipath routes:
164  	 * siblings is a list of fib6_info that have the same metric/weight,
165  	 * destination, but not the same gateway. nsiblings is just a cache
166  	 * to speed up lookup.
167  	 */
168  	union {
169  		struct list_head	fib6_siblings;
170  		struct list_head	nh_list;
171  	};
172  	unsigned int			fib6_nsiblings;
173  
174  	refcount_t			fib6_ref;
175  	unsigned long			expires;
176  
177  	struct hlist_node		gc_link;
178  
179  	struct dst_metrics		*fib6_metrics;
180  #define fib6_pmtu		fib6_metrics->metrics[RTAX_MTU-1]
181  
182  	struct rt6key			fib6_dst;
183  	u32				fib6_flags;
184  	struct rt6key			fib6_src;
185  	struct rt6key			fib6_prefsrc;
186  
187  	u32				fib6_metric;
188  	u8				fib6_protocol;
189  	u8				fib6_type;
190  
191  	u8				offload;
192  	u8				trap;
193  	u8				offload_failed;
194  
195  	u8				should_flush:1,
196  					dst_nocount:1,
197  					dst_nopolicy:1,
198  					fib6_destroying:1,
199  					unused:4;
200  
201  	struct rcu_head			rcu;
202  	struct nexthop			*nh;
203  	struct fib6_nh			fib6_nh[];
204  };
205  
206  struct rt6_info {
207  	struct dst_entry		dst;
208  	struct fib6_info __rcu		*from;
209  	int				sernum;
210  
211  	struct rt6key			rt6i_dst;
212  	struct rt6key			rt6i_src;
213  	struct in6_addr			rt6i_gateway;
214  	struct inet6_dev		*rt6i_idev;
215  	u32				rt6i_flags;
216  
217  	/* more non-fragment space at head required */
218  	unsigned short			rt6i_nfheader_len;
219  };
220  
221  struct fib6_result {
222  	struct fib6_nh		*nh;
223  	struct fib6_info	*f6i;
224  	u32			fib6_flags;
225  	u8			fib6_type;
226  	struct rt6_info		*rt6;
227  };
228  
229  #define for_each_fib6_node_rt_rcu(fn)					\
230  	for (rt = rcu_dereference((fn)->leaf); rt;			\
231  	     rt = rcu_dereference(rt->fib6_next))
232  
233  #define for_each_fib6_walker_rt(w)					\
234  	for (rt = (w)->leaf; rt;					\
235  	     rt = rcu_dereference_protected(rt->fib6_next, 1))
236  
237  #define dst_rt6_info(_ptr) container_of_const(_ptr, struct rt6_info, dst)
238  
ip6_dst_idev(const struct dst_entry * dst)239  static inline struct inet6_dev *ip6_dst_idev(const struct dst_entry *dst)
240  {
241  	return dst_rt6_info(dst)->rt6i_idev;
242  }
243  
fib6_requires_src(const struct fib6_info * rt)244  static inline bool fib6_requires_src(const struct fib6_info *rt)
245  {
246  	return rt->fib6_src.plen > 0;
247  }
248  
249  /* The callers should hold f6i->fib6_table->tb6_lock if a route has ever
250   * been added to a table before.
251   */
fib6_clean_expires(struct fib6_info * f6i)252  static inline void fib6_clean_expires(struct fib6_info *f6i)
253  {
254  	f6i->fib6_flags &= ~RTF_EXPIRES;
255  	f6i->expires = 0;
256  }
257  
258  /* The callers should hold f6i->fib6_table->tb6_lock if a route has ever
259   * been added to a table before.
260   */
fib6_set_expires(struct fib6_info * f6i,unsigned long expires)261  static inline void fib6_set_expires(struct fib6_info *f6i,
262  				    unsigned long expires)
263  {
264  	f6i->expires = expires;
265  	f6i->fib6_flags |= RTF_EXPIRES;
266  }
267  
fib6_check_expired(const struct fib6_info * f6i)268  static inline bool fib6_check_expired(const struct fib6_info *f6i)
269  {
270  	if (f6i->fib6_flags & RTF_EXPIRES)
271  		return time_after(jiffies, f6i->expires);
272  	return false;
273  }
274  
275  /* Function to safely get fn->fn_sernum for passed in rt
276   * and store result in passed in cookie.
277   * Return true if we can get cookie safely
278   * Return false if not
279   */
fib6_get_cookie_safe(const struct fib6_info * f6i,u32 * cookie)280  static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i,
281  					u32 *cookie)
282  {
283  	struct fib6_node *fn;
284  	bool status = false;
285  
286  	fn = rcu_dereference(f6i->fib6_node);
287  
288  	if (fn) {
289  		*cookie = READ_ONCE(fn->fn_sernum);
290  		/* pairs with smp_wmb() in __fib6_update_sernum_upto_root() */
291  		smp_rmb();
292  		status = true;
293  	}
294  
295  	return status;
296  }
297  
rt6_get_cookie(const struct rt6_info * rt)298  static inline u32 rt6_get_cookie(const struct rt6_info *rt)
299  {
300  	struct fib6_info *from;
301  	u32 cookie = 0;
302  
303  	if (rt->sernum)
304  		return rt->sernum;
305  
306  	rcu_read_lock();
307  
308  	from = rcu_dereference(rt->from);
309  	if (from)
310  		fib6_get_cookie_safe(from, &cookie);
311  
312  	rcu_read_unlock();
313  
314  	return cookie;
315  }
316  
ip6_rt_put(struct rt6_info * rt)317  static inline void ip6_rt_put(struct rt6_info *rt)
318  {
319  	/* dst_release() accepts a NULL parameter.
320  	 * We rely on dst being first structure in struct rt6_info
321  	 */
322  	BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
323  	dst_release(&rt->dst);
324  }
325  
326  struct fib6_info *fib6_info_alloc(gfp_t gfp_flags, bool with_fib6_nh);
327  void fib6_info_destroy_rcu(struct rcu_head *head);
328  
fib6_info_hold(struct fib6_info * f6i)329  static inline void fib6_info_hold(struct fib6_info *f6i)
330  {
331  	refcount_inc(&f6i->fib6_ref);
332  }
333  
fib6_info_hold_safe(struct fib6_info * f6i)334  static inline bool fib6_info_hold_safe(struct fib6_info *f6i)
335  {
336  	return refcount_inc_not_zero(&f6i->fib6_ref);
337  }
338  
fib6_info_release(struct fib6_info * f6i)339  static inline void fib6_info_release(struct fib6_info *f6i)
340  {
341  	if (f6i && refcount_dec_and_test(&f6i->fib6_ref)) {
342  		DEBUG_NET_WARN_ON_ONCE(!hlist_unhashed(&f6i->gc_link));
343  		call_rcu_hurry(&f6i->rcu, fib6_info_destroy_rcu);
344  	}
345  }
346  
347  enum fib6_walk_state {
348  #ifdef CONFIG_IPV6_SUBTREES
349  	FWS_S,
350  #endif
351  	FWS_L,
352  	FWS_R,
353  	FWS_C,
354  	FWS_U
355  };
356  
357  struct fib6_walker {
358  	struct list_head lh;
359  	struct fib6_node *root, *node;
360  	struct fib6_info *leaf;
361  	enum fib6_walk_state state;
362  	unsigned int skip;
363  	unsigned int count;
364  	unsigned int skip_in_node;
365  	int (*func)(struct fib6_walker *);
366  	void *args;
367  };
368  
369  struct rt6_statistics {
370  	__u32		fib_nodes;		/* all fib6 nodes */
371  	__u32		fib_route_nodes;	/* intermediate nodes */
372  	__u32		fib_rt_entries;		/* rt entries in fib table */
373  	__u32		fib_rt_cache;		/* cached rt entries in exception table */
374  	__u32		fib_discarded_routes;	/* total number of routes delete */
375  
376  	/* The following stat is not protected by any lock */
377  	atomic_t	fib_rt_alloc;		/* total number of routes alloced */
378  };
379  
380  #define RTN_TL_ROOT	0x0001
381  #define RTN_ROOT	0x0002		/* tree root node		*/
382  #define RTN_RTINFO	0x0004		/* node with valid routing info	*/
383  
384  /*
385   *	priority levels (or metrics)
386   *
387   */
388  
389  
390  struct fib6_table {
391  	struct hlist_node	tb6_hlist;
392  	u32			tb6_id;
393  	spinlock_t		tb6_lock;
394  	struct fib6_node	tb6_root;
395  	struct inet_peer_base	tb6_peers;
396  	unsigned int		flags;
397  	unsigned int		fib_seq;
398  	struct hlist_head       tb6_gc_hlist;	/* GC candidates */
399  #define RT6_TABLE_HAS_DFLT_ROUTER	BIT(0)
400  };
401  
402  #define RT6_TABLE_UNSPEC	RT_TABLE_UNSPEC
403  #define RT6_TABLE_MAIN		RT_TABLE_MAIN
404  #define RT6_TABLE_DFLT		RT6_TABLE_MAIN
405  #define RT6_TABLE_INFO		RT6_TABLE_MAIN
406  #define RT6_TABLE_PREFIX	RT6_TABLE_MAIN
407  
408  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
409  #define FIB6_TABLE_MIN		1
410  #define FIB6_TABLE_MAX		RT_TABLE_MAX
411  #define RT6_TABLE_LOCAL		RT_TABLE_LOCAL
412  #else
413  #define FIB6_TABLE_MIN		RT_TABLE_MAIN
414  #define FIB6_TABLE_MAX		FIB6_TABLE_MIN
415  #define RT6_TABLE_LOCAL		RT6_TABLE_MAIN
416  #endif
417  
418  typedef struct rt6_info *(*pol_lookup_t)(struct net *,
419  					 struct fib6_table *,
420  					 struct flowi6 *,
421  					 const struct sk_buff *, int);
422  
423  struct fib6_entry_notifier_info {
424  	struct fib_notifier_info info; /* must be first */
425  	struct fib6_info *rt;
426  	unsigned int nsiblings;
427  };
428  
429  /*
430   *	exported functions
431   */
432  
433  struct fib6_table *fib6_get_table(struct net *net, u32 id);
434  struct fib6_table *fib6_new_table(struct net *net, u32 id);
435  struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
436  				   const struct sk_buff *skb,
437  				   int flags, pol_lookup_t lookup);
438  
439  /* called with rcu lock held; can return error pointer
440   * caller needs to select path
441   */
442  int fib6_lookup(struct net *net, int oif, struct flowi6 *fl6,
443  		struct fib6_result *res, int flags);
444  
445  /* called with rcu lock held; caller needs to select path */
446  int fib6_table_lookup(struct net *net, struct fib6_table *table,
447  		      int oif, struct flowi6 *fl6, struct fib6_result *res,
448  		      int strict);
449  
450  void fib6_select_path(const struct net *net, struct fib6_result *res,
451  		      struct flowi6 *fl6, int oif, bool have_oif_match,
452  		      const struct sk_buff *skb, int strict);
453  struct fib6_node *fib6_node_lookup(struct fib6_node *root,
454  				   const struct in6_addr *daddr,
455  				   const struct in6_addr *saddr);
456  
457  struct fib6_node *fib6_locate(struct fib6_node *root,
458  			      const struct in6_addr *daddr, int dst_len,
459  			      const struct in6_addr *saddr, int src_len,
460  			      bool exact_match);
461  
462  void fib6_clean_all(struct net *net, int (*func)(struct fib6_info *, void *arg),
463  		    void *arg);
464  void fib6_clean_all_skip_notify(struct net *net,
465  				int (*func)(struct fib6_info *, void *arg),
466  				void *arg);
467  
468  int fib6_add(struct fib6_node *root, struct fib6_info *rt,
469  	     struct nl_info *info, struct netlink_ext_ack *extack);
470  int fib6_del(struct fib6_info *rt, struct nl_info *info);
471  
472  static inline
rt6_get_prefsrc(const struct rt6_info * rt,struct in6_addr * addr)473  void rt6_get_prefsrc(const struct rt6_info *rt, struct in6_addr *addr)
474  {
475  	const struct fib6_info *from;
476  
477  	rcu_read_lock();
478  
479  	from = rcu_dereference(rt->from);
480  	if (from)
481  		*addr = from->fib6_prefsrc.addr;
482  	else
483  		*addr = in6addr_any;
484  
485  	rcu_read_unlock();
486  }
487  
488  int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
489  		 struct fib6_config *cfg, gfp_t gfp_flags,
490  		 struct netlink_ext_ack *extack);
491  void fib6_nh_release(struct fib6_nh *fib6_nh);
492  void fib6_nh_release_dsts(struct fib6_nh *fib6_nh);
493  
494  int call_fib6_entry_notifiers(struct net *net,
495  			      enum fib_event_type event_type,
496  			      struct fib6_info *rt,
497  			      struct netlink_ext_ack *extack);
498  int call_fib6_multipath_entry_notifiers(struct net *net,
499  					enum fib_event_type event_type,
500  					struct fib6_info *rt,
501  					unsigned int nsiblings,
502  					struct netlink_ext_ack *extack);
503  int call_fib6_entry_notifiers_replace(struct net *net, struct fib6_info *rt);
504  void fib6_rt_update(struct net *net, struct fib6_info *rt,
505  		    struct nl_info *info);
506  void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
507  		     unsigned int flags);
508  
509  void fib6_run_gc(unsigned long expires, struct net *net, bool force);
510  
511  void fib6_gc_cleanup(void);
512  
513  int fib6_init(void);
514  
515  /* Add the route to the gc list if it is not already there
516   *
517   * The callers should hold f6i->fib6_table->tb6_lock.
518   */
fib6_add_gc_list(struct fib6_info * f6i)519  static inline void fib6_add_gc_list(struct fib6_info *f6i)
520  {
521  	/* If fib6_node is null, the f6i is not in (or removed from) the
522  	 * table.
523  	 *
524  	 * There is a gap between finding the f6i from the table and
525  	 * calling this function without the protection of the tb6_lock.
526  	 * This check makes sure the f6i is not added to the gc list when
527  	 * it is not on the table.
528  	 */
529  	if (!rcu_dereference_protected(f6i->fib6_node,
530  				       lockdep_is_held(&f6i->fib6_table->tb6_lock)))
531  		return;
532  
533  	if (hlist_unhashed(&f6i->gc_link))
534  		hlist_add_head(&f6i->gc_link, &f6i->fib6_table->tb6_gc_hlist);
535  }
536  
537  /* Remove the route from the gc list if it is on the list.
538   *
539   * The callers should hold f6i->fib6_table->tb6_lock.
540   */
fib6_remove_gc_list(struct fib6_info * f6i)541  static inline void fib6_remove_gc_list(struct fib6_info *f6i)
542  {
543  	if (!hlist_unhashed(&f6i->gc_link))
544  		hlist_del_init(&f6i->gc_link);
545  }
546  
547  struct ipv6_route_iter {
548  	struct seq_net_private p;
549  	struct fib6_walker w;
550  	loff_t skip;
551  	struct fib6_table *tbl;
552  	int sernum;
553  };
554  
555  extern const struct seq_operations ipv6_route_seq_ops;
556  
557  int call_fib6_notifier(struct notifier_block *nb,
558  		       enum fib_event_type event_type,
559  		       struct fib_notifier_info *info);
560  int call_fib6_notifiers(struct net *net, enum fib_event_type event_type,
561  			struct fib_notifier_info *info);
562  
563  int __net_init fib6_notifier_init(struct net *net);
564  void __net_exit fib6_notifier_exit(struct net *net);
565  
566  unsigned int fib6_tables_seq_read(struct net *net);
567  int fib6_tables_dump(struct net *net, struct notifier_block *nb,
568  		     struct netlink_ext_ack *extack);
569  
570  void fib6_update_sernum(struct net *net, struct fib6_info *rt);
571  void fib6_update_sernum_upto_root(struct net *net, struct fib6_info *rt);
572  void fib6_update_sernum_stub(struct net *net, struct fib6_info *f6i);
573  
574  void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val);
fib6_metric_locked(struct fib6_info * f6i,int metric)575  static inline bool fib6_metric_locked(struct fib6_info *f6i, int metric)
576  {
577  	return !!(f6i->fib6_metrics->metrics[RTAX_LOCK - 1] & (1 << metric));
578  }
579  void fib6_info_hw_flags_set(struct net *net, struct fib6_info *f6i,
580  			    bool offload, bool trap, bool offload_failed);
581  
582  #if IS_BUILTIN(CONFIG_IPV6) && defined(CONFIG_BPF_SYSCALL)
583  struct bpf_iter__ipv6_route {
584  	__bpf_md_ptr(struct bpf_iter_meta *, meta);
585  	__bpf_md_ptr(struct fib6_info *, rt);
586  };
587  #endif
588  
589  INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_output(struct net *net,
590  					     struct fib6_table *table,
591  					     struct flowi6 *fl6,
592  					     const struct sk_buff *skb,
593  					     int flags));
594  INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_input(struct net *net,
595  					     struct fib6_table *table,
596  					     struct flowi6 *fl6,
597  					     const struct sk_buff *skb,
598  					     int flags));
599  INDIRECT_CALLABLE_DECLARE(struct rt6_info *__ip6_route_redirect(struct net *net,
600  					     struct fib6_table *table,
601  					     struct flowi6 *fl6,
602  					     const struct sk_buff *skb,
603  					     int flags));
604  INDIRECT_CALLABLE_DECLARE(struct rt6_info *ip6_pol_route_lookup(struct net *net,
605  					     struct fib6_table *table,
606  					     struct flowi6 *fl6,
607  					     const struct sk_buff *skb,
608  					     int flags));
pol_lookup_func(pol_lookup_t lookup,struct net * net,struct fib6_table * table,struct flowi6 * fl6,const struct sk_buff * skb,int flags)609  static inline struct rt6_info *pol_lookup_func(pol_lookup_t lookup,
610  						struct net *net,
611  						struct fib6_table *table,
612  						struct flowi6 *fl6,
613  						const struct sk_buff *skb,
614  						int flags)
615  {
616  	return INDIRECT_CALL_4(lookup,
617  			       ip6_pol_route_output,
618  			       ip6_pol_route_input,
619  			       ip6_pol_route_lookup,
620  			       __ip6_route_redirect,
621  			       net, table, fl6, skb, flags);
622  }
623  
624  #ifdef CONFIG_IPV6_MULTIPLE_TABLES
fib6_has_custom_rules(const struct net * net)625  static inline bool fib6_has_custom_rules(const struct net *net)
626  {
627  	return net->ipv6.fib6_has_custom_rules;
628  }
629  
630  int fib6_rules_init(void);
631  void fib6_rules_cleanup(void);
632  bool fib6_rule_default(const struct fib_rule *rule);
633  int fib6_rules_dump(struct net *net, struct notifier_block *nb,
634  		    struct netlink_ext_ack *extack);
635  unsigned int fib6_rules_seq_read(struct net *net);
636  
fib6_rules_early_flow_dissect(struct net * net,struct sk_buff * skb,struct flowi6 * fl6,struct flow_keys * flkeys)637  static inline bool fib6_rules_early_flow_dissect(struct net *net,
638  						 struct sk_buff *skb,
639  						 struct flowi6 *fl6,
640  						 struct flow_keys *flkeys)
641  {
642  	unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
643  
644  	if (!net->ipv6.fib6_rules_require_fldissect)
645  		return false;
646  
647  	memset(flkeys, 0, sizeof(*flkeys));
648  	__skb_flow_dissect(net, skb, &flow_keys_dissector,
649  			   flkeys, NULL, 0, 0, 0, flag);
650  
651  	fl6->fl6_sport = flkeys->ports.src;
652  	fl6->fl6_dport = flkeys->ports.dst;
653  	fl6->flowi6_proto = flkeys->basic.ip_proto;
654  
655  	return true;
656  }
657  #else
fib6_has_custom_rules(const struct net * net)658  static inline bool fib6_has_custom_rules(const struct net *net)
659  {
660  	return false;
661  }
fib6_rules_init(void)662  static inline int               fib6_rules_init(void)
663  {
664  	return 0;
665  }
fib6_rules_cleanup(void)666  static inline void              fib6_rules_cleanup(void)
667  {
668  	return ;
669  }
fib6_rule_default(const struct fib_rule * rule)670  static inline bool fib6_rule_default(const struct fib_rule *rule)
671  {
672  	return true;
673  }
fib6_rules_dump(struct net * net,struct notifier_block * nb,struct netlink_ext_ack * extack)674  static inline int fib6_rules_dump(struct net *net, struct notifier_block *nb,
675  				  struct netlink_ext_ack *extack)
676  {
677  	return 0;
678  }
fib6_rules_seq_read(struct net * net)679  static inline unsigned int fib6_rules_seq_read(struct net *net)
680  {
681  	return 0;
682  }
fib6_rules_early_flow_dissect(struct net * net,struct sk_buff * skb,struct flowi6 * fl6,struct flow_keys * flkeys)683  static inline bool fib6_rules_early_flow_dissect(struct net *net,
684  						 struct sk_buff *skb,
685  						 struct flowi6 *fl6,
686  						 struct flow_keys *flkeys)
687  {
688  	return false;
689  }
690  #endif
691  #endif
692