Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0-or-later */
2 : : /*
3 : : * INET An implementation of the TCP/IP protocol suite for the LINUX
4 : : * operating system. INET is implemented using the BSD Socket
5 : : * interface as the means of communication with the user level.
6 : : *
7 : : * Definitions for the Forwarding Information Base.
8 : : *
9 : : * Authors: A.N.Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 : : */
11 : :
12 : : #ifndef _NET_IP_FIB_H
13 : : #define _NET_IP_FIB_H
14 : :
15 : : #include <net/flow.h>
16 : : #include <linux/seq_file.h>
17 : : #include <linux/rcupdate.h>
18 : : #include <net/fib_notifier.h>
19 : : #include <net/fib_rules.h>
20 : : #include <net/inetpeer.h>
21 : : #include <linux/percpu.h>
22 : : #include <linux/notifier.h>
23 : : #include <linux/refcount.h>
24 : :
25 : : struct fib_config {
26 : : u8 fc_dst_len;
27 : : u8 fc_tos;
28 : : u8 fc_protocol;
29 : : u8 fc_scope;
30 : : u8 fc_type;
31 : : u8 fc_gw_family;
32 : : /* 2 bytes unused */
33 : : u32 fc_table;
34 : : __be32 fc_dst;
35 : : union {
36 : : __be32 fc_gw4;
37 : : struct in6_addr fc_gw6;
38 : : };
39 : : int fc_oif;
40 : : u32 fc_flags;
41 : : u32 fc_priority;
42 : : __be32 fc_prefsrc;
43 : : u32 fc_nh_id;
44 : : struct nlattr *fc_mx;
45 : : struct rtnexthop *fc_mp;
46 : : int fc_mx_len;
47 : : int fc_mp_len;
48 : : u32 fc_flow;
49 : : u32 fc_nlflags;
50 : : struct nl_info fc_nlinfo;
51 : : struct nlattr *fc_encap;
52 : : u16 fc_encap_type;
53 : : };
54 : :
55 : : struct fib_info;
56 : : struct rtable;
57 : :
58 : : struct fib_nh_exception {
59 : : struct fib_nh_exception __rcu *fnhe_next;
60 : : int fnhe_genid;
61 : : __be32 fnhe_daddr;
62 : : u32 fnhe_pmtu;
63 : : bool fnhe_mtu_locked;
64 : : __be32 fnhe_gw;
65 : : unsigned long fnhe_expires;
66 : : struct rtable __rcu *fnhe_rth_input;
67 : : struct rtable __rcu *fnhe_rth_output;
68 : : unsigned long fnhe_stamp;
69 : : struct rcu_head rcu;
70 : : };
71 : :
72 : : struct fnhe_hash_bucket {
73 : : struct fib_nh_exception __rcu *chain;
74 : : };
75 : :
76 : : #define FNHE_HASH_SHIFT 11
77 : : #define FNHE_HASH_SIZE (1 << FNHE_HASH_SHIFT)
78 : : #define FNHE_RECLAIM_DEPTH 5
79 : :
80 : : struct fib_nh_common {
81 : : struct net_device *nhc_dev;
82 : : int nhc_oif;
83 : : unsigned char nhc_scope;
84 : : u8 nhc_family;
85 : : u8 nhc_gw_family;
86 : : unsigned char nhc_flags;
87 : : struct lwtunnel_state *nhc_lwtstate;
88 : :
89 : : union {
90 : : __be32 ipv4;
91 : : struct in6_addr ipv6;
92 : : } nhc_gw;
93 : :
94 : : int nhc_weight;
95 : : atomic_t nhc_upper_bound;
96 : :
97 : : /* v4 specific, but allows fib6_nh with v4 routes */
98 : : struct rtable __rcu * __percpu *nhc_pcpu_rth_output;
99 : : struct rtable __rcu *nhc_rth_input;
100 : : struct fnhe_hash_bucket __rcu *nhc_exceptions;
101 : : };
102 : :
103 : : struct fib_nh {
104 : : struct fib_nh_common nh_common;
105 : : struct hlist_node nh_hash;
106 : : struct fib_info *nh_parent;
107 : : #ifdef CONFIG_IP_ROUTE_CLASSID
108 : : __u32 nh_tclassid;
109 : : #endif
110 : : __be32 nh_saddr;
111 : : int nh_saddr_genid;
112 : : #define fib_nh_family nh_common.nhc_family
113 : : #define fib_nh_dev nh_common.nhc_dev
114 : : #define fib_nh_oif nh_common.nhc_oif
115 : : #define fib_nh_flags nh_common.nhc_flags
116 : : #define fib_nh_lws nh_common.nhc_lwtstate
117 : : #define fib_nh_scope nh_common.nhc_scope
118 : : #define fib_nh_gw_family nh_common.nhc_gw_family
119 : : #define fib_nh_gw4 nh_common.nhc_gw.ipv4
120 : : #define fib_nh_gw6 nh_common.nhc_gw.ipv6
121 : : #define fib_nh_weight nh_common.nhc_weight
122 : : #define fib_nh_upper_bound nh_common.nhc_upper_bound
123 : : };
124 : :
125 : : /*
126 : : * This structure contains data shared by many of routes.
127 : : */
128 : :
129 : : struct nexthop;
130 : :
131 : : struct fib_info {
132 : : struct hlist_node fib_hash;
133 : : struct hlist_node fib_lhash;
134 : : struct list_head nh_list;
135 : : struct net *fib_net;
136 : : int fib_treeref;
137 : : refcount_t fib_clntref;
138 : : unsigned int fib_flags;
139 : : unsigned char fib_dead;
140 : : unsigned char fib_protocol;
141 : : unsigned char fib_scope;
142 : : unsigned char fib_type;
143 : : __be32 fib_prefsrc;
144 : : u32 fib_tb_id;
145 : : u32 fib_priority;
146 : : struct dst_metrics *fib_metrics;
147 : : #define fib_mtu fib_metrics->metrics[RTAX_MTU-1]
148 : : #define fib_window fib_metrics->metrics[RTAX_WINDOW-1]
149 : : #define fib_rtt fib_metrics->metrics[RTAX_RTT-1]
150 : : #define fib_advmss fib_metrics->metrics[RTAX_ADVMSS-1]
151 : : int fib_nhs;
152 : : bool fib_nh_is_v6;
153 : : bool nh_updated;
154 : : struct nexthop *nh;
155 : : struct rcu_head rcu;
156 : : struct fib_nh fib_nh[0];
157 : : };
158 : :
159 : :
160 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
161 : : struct fib_rule;
162 : : #endif
163 : :
164 : : struct fib_table;
165 : : struct fib_result {
166 : : __be32 prefix;
167 : : unsigned char prefixlen;
168 : : unsigned char nh_sel;
169 : : unsigned char type;
170 : : unsigned char scope;
171 : : u32 tclassid;
172 : : struct fib_nh_common *nhc;
173 : : struct fib_info *fi;
174 : : struct fib_table *table;
175 : : struct hlist_head *fa_head;
176 : : };
177 : :
178 : : struct fib_result_nl {
179 : : __be32 fl_addr; /* To be looked up*/
180 : : u32 fl_mark;
181 : : unsigned char fl_tos;
182 : : unsigned char fl_scope;
183 : : unsigned char tb_id_in;
184 : :
185 : : unsigned char tb_id; /* Results */
186 : : unsigned char prefixlen;
187 : : unsigned char nh_sel;
188 : : unsigned char type;
189 : : unsigned char scope;
190 : : int err;
191 : : };
192 : :
193 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
194 : : #define FIB_TABLE_HASHSZ 256
195 : : #else
196 : : #define FIB_TABLE_HASHSZ 2
197 : : #endif
198 : :
199 : : __be32 fib_info_update_nhc_saddr(struct net *net, struct fib_nh_common *nhc,
200 : : unsigned char scope);
201 : : __be32 fib_result_prefsrc(struct net *net, struct fib_result *res);
202 : :
203 : : #define FIB_RES_NHC(res) ((res).nhc)
204 : : #define FIB_RES_DEV(res) (FIB_RES_NHC(res)->nhc_dev)
205 : : #define FIB_RES_OIF(res) (FIB_RES_NHC(res)->nhc_oif)
206 : :
207 : : struct fib_rt_info {
208 : : struct fib_info *fi;
209 : : u32 tb_id;
210 : : __be32 dst;
211 : : int dst_len;
212 : : u8 tos;
213 : : u8 type;
214 : : u8 offload:1,
215 : : trap:1,
216 : : unused:6;
217 : : };
218 : :
219 : : struct fib_entry_notifier_info {
220 : : struct fib_notifier_info info; /* must be first */
221 : : u32 dst;
222 : : int dst_len;
223 : : struct fib_info *fi;
224 : : u8 tos;
225 : : u8 type;
226 : : u32 tb_id;
227 : : };
228 : :
229 : : struct fib_nh_notifier_info {
230 : : struct fib_notifier_info info; /* must be first */
231 : : struct fib_nh *fib_nh;
232 : : };
233 : :
234 : : int call_fib4_notifier(struct notifier_block *nb,
235 : : enum fib_event_type event_type,
236 : : struct fib_notifier_info *info);
237 : : int call_fib4_notifiers(struct net *net, enum fib_event_type event_type,
238 : : struct fib_notifier_info *info);
239 : :
240 : : int __net_init fib4_notifier_init(struct net *net);
241 : : void __net_exit fib4_notifier_exit(struct net *net);
242 : :
243 : : void fib_info_notify_update(struct net *net, struct nl_info *info);
244 : : int fib_notify(struct net *net, struct notifier_block *nb,
245 : : struct netlink_ext_ack *extack);
246 : :
247 : : struct fib_table {
248 : : struct hlist_node tb_hlist;
249 : : u32 tb_id;
250 : : int tb_num_default;
251 : : struct rcu_head rcu;
252 : : unsigned long *tb_data;
253 : : unsigned long __data[0];
254 : : };
255 : :
256 : : struct fib_dump_filter {
257 : : u32 table_id;
258 : : /* filter_set is an optimization that an entry is set */
259 : : bool filter_set;
260 : : bool dump_all_families;
261 : : bool dump_routes;
262 : : bool dump_exceptions;
263 : : unsigned char protocol;
264 : : unsigned char rt_type;
265 : : unsigned int flags;
266 : : struct net_device *dev;
267 : : };
268 : :
269 : : int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
270 : : struct fib_result *res, int fib_flags);
271 : : int fib_table_insert(struct net *, struct fib_table *, struct fib_config *,
272 : : struct netlink_ext_ack *extack);
273 : : int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
274 : : struct netlink_ext_ack *extack);
275 : : int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
276 : : struct netlink_callback *cb, struct fib_dump_filter *filter);
277 : : int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
278 : : struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
279 : : void fib_table_flush_external(struct fib_table *table);
280 : : void fib_free_table(struct fib_table *tb);
281 : :
282 : : #ifndef CONFIG_IP_MULTIPLE_TABLES
283 : :
284 : : #define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1))
285 : : #define TABLE_MAIN_INDEX (RT_TABLE_MAIN & (FIB_TABLE_HASHSZ - 1))
286 : :
287 : : static inline struct fib_table *fib_get_table(struct net *net, u32 id)
288 : : {
289 : : struct hlist_node *tb_hlist;
290 : : struct hlist_head *ptr;
291 : :
292 : : ptr = id == RT_TABLE_LOCAL ?
293 : : &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
294 : : &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
295 : :
296 : : tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr));
297 : :
298 : : return hlist_entry(tb_hlist, struct fib_table, tb_hlist);
299 : : }
300 : :
301 : : static inline struct fib_table *fib_new_table(struct net *net, u32 id)
302 : : {
303 : : return fib_get_table(net, id);
304 : : }
305 : :
306 : : static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
307 : : struct fib_result *res, unsigned int flags)
308 : : {
309 : : struct fib_table *tb;
310 : : int err = -ENETUNREACH;
311 : :
312 : : rcu_read_lock();
313 : :
314 : : tb = fib_get_table(net, RT_TABLE_MAIN);
315 : : if (tb)
316 : : err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
317 : :
318 : : if (err == -EAGAIN)
319 : : err = -ENETUNREACH;
320 : :
321 : : rcu_read_unlock();
322 : :
323 : : return err;
324 : : }
325 : :
326 : : static inline bool fib4_has_custom_rules(const struct net *net)
327 : : {
328 : : return false;
329 : : }
330 : :
331 : : static inline bool fib4_rule_default(const struct fib_rule *rule)
332 : : {
333 : : return true;
334 : : }
335 : :
336 : : static inline int fib4_rules_dump(struct net *net, struct notifier_block *nb,
337 : : struct netlink_ext_ack *extack)
338 : : {
339 : : return 0;
340 : : }
341 : :
342 : : static inline unsigned int fib4_rules_seq_read(struct net *net)
343 : : {
344 : : return 0;
345 : : }
346 : :
347 : : static inline bool fib4_rules_early_flow_dissect(struct net *net,
348 : : struct sk_buff *skb,
349 : : struct flowi4 *fl4,
350 : : struct flow_keys *flkeys)
351 : : {
352 : : return false;
353 : : }
354 : : #else /* CONFIG_IP_MULTIPLE_TABLES */
355 : : int __net_init fib4_rules_init(struct net *net);
356 : : void __net_exit fib4_rules_exit(struct net *net);
357 : :
358 : : struct fib_table *fib_new_table(struct net *net, u32 id);
359 : : struct fib_table *fib_get_table(struct net *net, u32 id);
360 : :
361 : : int __fib_lookup(struct net *net, struct flowi4 *flp,
362 : : struct fib_result *res, unsigned int flags);
363 : :
364 : 2408 : static inline int fib_lookup(struct net *net, struct flowi4 *flp,
365 : : struct fib_result *res, unsigned int flags)
366 : : {
367 : 2408 : struct fib_table *tb;
368 : 2408 : int err = -ENETUNREACH;
369 : :
370 : 2408 : flags |= FIB_LOOKUP_NOREF;
371 [ - + ]: 2408 : if (net->ipv4.fib_has_custom_rules)
372 : 0 : return __fib_lookup(net, flp, res, flags);
373 : :
374 : 2408 : rcu_read_lock();
375 : :
376 : 2408 : res->tclassid = 0;
377 : :
378 [ + - ]: 2408 : tb = rcu_dereference_rtnl(net->ipv4.fib_main);
379 [ + - ]: 2408 : if (tb)
380 : 2408 : err = fib_table_lookup(tb, flp, res, flags);
381 : :
382 [ + + ]: 2408 : if (!err)
383 : 56 : goto out;
384 : :
385 [ + - ]: 2352 : tb = rcu_dereference_rtnl(net->ipv4.fib_default);
386 [ + - ]: 2352 : if (tb)
387 : 0 : err = fib_table_lookup(tb, flp, res, flags);
388 : :
389 : 2352 : out:
390 [ + + ]: 2408 : if (err == -EAGAIN)
391 : 2352 : err = -ENETUNREACH;
392 : :
393 : 2408 : rcu_read_unlock();
394 : :
395 : 2408 : return err;
396 : : }
397 : :
398 : 0 : static inline bool fib4_has_custom_rules(const struct net *net)
399 : : {
400 [ # # ]: 0 : return net->ipv4.fib_has_custom_rules;
401 : : }
402 : :
403 : : bool fib4_rule_default(const struct fib_rule *rule);
404 : : int fib4_rules_dump(struct net *net, struct notifier_block *nb,
405 : : struct netlink_ext_ack *extack);
406 : : unsigned int fib4_rules_seq_read(struct net *net);
407 : :
408 : 0 : static inline bool fib4_rules_early_flow_dissect(struct net *net,
409 : : struct sk_buff *skb,
410 : : struct flowi4 *fl4,
411 : : struct flow_keys *flkeys)
412 : : {
413 : 0 : unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
414 : :
415 [ # # ]: 0 : if (!net->ipv4.fib_rules_require_fldissect)
416 : : return false;
417 : :
418 : 0 : skb_flow_dissect_flow_keys(skb, flkeys, flag);
419 : 0 : fl4->fl4_sport = flkeys->ports.src;
420 : 0 : fl4->fl4_dport = flkeys->ports.dst;
421 : 0 : fl4->flowi4_proto = flkeys->basic.ip_proto;
422 : :
423 : 0 : return true;
424 : : }
425 : :
426 : : #endif /* CONFIG_IP_MULTIPLE_TABLES */
427 : :
428 : : /* Exported by fib_frontend.c */
429 : : extern const struct nla_policy rtm_ipv4_policy[];
430 : : void ip_fib_init(void);
431 : : int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla,
432 : : struct netlink_ext_ack *extack);
433 : : __be32 fib_compute_spec_dst(struct sk_buff *skb);
434 : : bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev);
435 : : int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
436 : : u8 tos, int oif, struct net_device *dev,
437 : : struct in_device *idev, u32 *itag);
438 : : #ifdef CONFIG_IP_ROUTE_CLASSID
439 : : static inline int fib_num_tclassid_users(struct net *net)
440 : : {
441 : : return net->ipv4.fib_num_tclassid_users;
442 : : }
443 : : #else
444 : 0 : static inline int fib_num_tclassid_users(struct net *net)
445 : : {
446 [ # # ]: 0 : return 0;
447 : : }
448 : : #endif
449 : : int fib_unmerge(struct net *net);
450 : :
451 : : /* Exported by fib_semantics.c */
452 : : int ip_fib_check_default(__be32 gw, struct net_device *dev);
453 : : int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
454 : : int fib_sync_down_addr(struct net_device *dev, __be32 local);
455 : : int fib_sync_up(struct net_device *dev, unsigned char nh_flags);
456 : : void fib_sync_mtu(struct net_device *dev, u32 orig_mtu);
457 : : void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig);
458 : :
459 : : #ifdef CONFIG_IP_ROUTE_MULTIPATH
460 : : int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
461 : : const struct sk_buff *skb, struct flow_keys *flkeys);
462 : : #endif
463 : : int fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope,
464 : : struct netlink_ext_ack *extack);
465 : : void fib_select_multipath(struct fib_result *res, int hash);
466 : : void fib_select_path(struct net *net, struct fib_result *res,
467 : : struct flowi4 *fl4, const struct sk_buff *skb);
468 : :
469 : : int fib_nh_init(struct net *net, struct fib_nh *fib_nh,
470 : : struct fib_config *cfg, int nh_weight,
471 : : struct netlink_ext_ack *extack);
472 : : void fib_nh_release(struct net *net, struct fib_nh *fib_nh);
473 : : int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *fc_encap,
474 : : u16 fc_encap_type, void *cfg, gfp_t gfp_flags,
475 : : struct netlink_ext_ack *extack);
476 : : void fib_nh_common_release(struct fib_nh_common *nhc);
477 : :
478 : : /* Exported by fib_trie.c */
479 : : void fib_alias_hw_flags_set(struct net *net, const struct fib_rt_info *fri);
480 : : void fib_trie_init(void);
481 : : struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
482 : :
483 : 0 : static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
484 : : {
485 : : #ifdef CONFIG_IP_ROUTE_CLASSID
486 : : struct fib_nh_common *nhc = res->nhc;
487 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
488 : : u32 rtag;
489 : : #endif
490 : : if (nhc->nhc_family == AF_INET) {
491 : : struct fib_nh *nh;
492 : :
493 : : nh = container_of(nhc, struct fib_nh, nh_common);
494 : : *itag = nh->nh_tclassid << 16;
495 : : } else {
496 : : *itag = 0;
497 : : }
498 : :
499 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
500 : : rtag = res->tclassid;
501 : : if (*itag == 0)
502 : : *itag = (rtag<<16);
503 : : *itag |= (rtag>>16);
504 : : #endif
505 : : #endif
506 : 0 : }
507 : :
508 : : void fib_flush(struct net *net);
509 : : void free_fib_info(struct fib_info *fi);
510 : :
511 : : static inline void fib_info_hold(struct fib_info *fi)
512 : : {
513 : : refcount_inc(&fi->fib_clntref);
514 : : }
515 : :
516 : 0 : static inline void fib_info_put(struct fib_info *fi)
517 : : {
518 [ # # ]: 0 : if (refcount_dec_and_test(&fi->fib_clntref))
519 : 0 : free_fib_info(fi);
520 : 0 : }
521 : :
522 : : #ifdef CONFIG_PROC_FS
523 : : int __net_init fib_proc_init(struct net *net);
524 : : void __net_exit fib_proc_exit(struct net *net);
525 : : #else
526 : : static inline int fib_proc_init(struct net *net)
527 : : {
528 : : return 0;
529 : : }
530 : : static inline void fib_proc_exit(struct net *net)
531 : : {
532 : : }
533 : : #endif
534 : :
535 : : u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
536 : :
537 : : int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
538 : : struct fib_dump_filter *filter,
539 : : struct netlink_callback *cb);
540 : :
541 : : int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
542 : : u8 rt_family, unsigned char *flags, bool skip_oif);
543 : : int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
544 : : int nh_weight, u8 rt_family);
545 : : #endif /* _NET_FIB_H */
|