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