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_entry_notifier_info {
208 : : struct fib_notifier_info info; /* must be first */
209 : : u32 dst;
210 : : int dst_len;
211 : : struct fib_info *fi;
212 : : u8 tos;
213 : : u8 type;
214 : : u32 tb_id;
215 : : };
216 : :
217 : : struct fib_nh_notifier_info {
218 : : struct fib_notifier_info info; /* must be first */
219 : : struct fib_nh *fib_nh;
220 : : };
221 : :
222 : : int call_fib4_notifier(struct notifier_block *nb, struct net *net,
223 : : enum fib_event_type event_type,
224 : : struct fib_notifier_info *info);
225 : : int call_fib4_notifiers(struct net *net, enum fib_event_type event_type,
226 : : struct fib_notifier_info *info);
227 : :
228 : : int __net_init fib4_notifier_init(struct net *net);
229 : : void __net_exit fib4_notifier_exit(struct net *net);
230 : :
231 : : void fib_info_notify_update(struct net *net, struct nl_info *info);
232 : : void fib_notify(struct net *net, struct notifier_block *nb);
233 : :
234 : : struct fib_table {
235 : : struct hlist_node tb_hlist;
236 : : u32 tb_id;
237 : : int tb_num_default;
238 : : struct rcu_head rcu;
239 : : unsigned long *tb_data;
240 : : unsigned long __data[0];
241 : : };
242 : :
243 : : struct fib_dump_filter {
244 : : u32 table_id;
245 : : /* filter_set is an optimization that an entry is set */
246 : : bool filter_set;
247 : : bool dump_routes;
248 : : bool dump_exceptions;
249 : : unsigned char protocol;
250 : : unsigned char rt_type;
251 : : unsigned int flags;
252 : : struct net_device *dev;
253 : : };
254 : :
255 : : int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
256 : : struct fib_result *res, int fib_flags);
257 : : int fib_table_insert(struct net *, struct fib_table *, struct fib_config *,
258 : : struct netlink_ext_ack *extack);
259 : : int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
260 : : struct netlink_ext_ack *extack);
261 : : int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
262 : : struct netlink_callback *cb, struct fib_dump_filter *filter);
263 : : int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
264 : : struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
265 : : void fib_table_flush_external(struct fib_table *table);
266 : : void fib_free_table(struct fib_table *tb);
267 : :
268 : : #ifndef CONFIG_IP_MULTIPLE_TABLES
269 : :
270 : : #define TABLE_LOCAL_INDEX (RT_TABLE_LOCAL & (FIB_TABLE_HASHSZ - 1))
271 : : #define TABLE_MAIN_INDEX (RT_TABLE_MAIN & (FIB_TABLE_HASHSZ - 1))
272 : :
273 : : static inline struct fib_table *fib_get_table(struct net *net, u32 id)
274 : : {
275 : : struct hlist_node *tb_hlist;
276 : : struct hlist_head *ptr;
277 : :
278 : : ptr = id == RT_TABLE_LOCAL ?
279 : : &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX] :
280 : : &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX];
281 : :
282 : : tb_hlist = rcu_dereference_rtnl(hlist_first_rcu(ptr));
283 : :
284 : : return hlist_entry(tb_hlist, struct fib_table, tb_hlist);
285 : : }
286 : :
287 : : static inline struct fib_table *fib_new_table(struct net *net, u32 id)
288 : : {
289 : : return fib_get_table(net, id);
290 : : }
291 : :
292 : : static inline int fib_lookup(struct net *net, const struct flowi4 *flp,
293 : : struct fib_result *res, unsigned int flags)
294 : : {
295 : : struct fib_table *tb;
296 : : int err = -ENETUNREACH;
297 : :
298 : : rcu_read_lock();
299 : :
300 : : tb = fib_get_table(net, RT_TABLE_MAIN);
301 : : if (tb)
302 : : err = fib_table_lookup(tb, flp, res, flags | FIB_LOOKUP_NOREF);
303 : :
304 : : if (err == -EAGAIN)
305 : : err = -ENETUNREACH;
306 : :
307 : : rcu_read_unlock();
308 : :
309 : : return err;
310 : : }
311 : :
312 : : static inline bool fib4_rule_default(const struct fib_rule *rule)
313 : : {
314 : : return true;
315 : : }
316 : :
317 : : static inline int fib4_rules_dump(struct net *net, struct notifier_block *nb)
318 : : {
319 : : return 0;
320 : : }
321 : :
322 : : static inline unsigned int fib4_rules_seq_read(struct net *net)
323 : : {
324 : : return 0;
325 : : }
326 : :
327 : : static inline bool fib4_rules_early_flow_dissect(struct net *net,
328 : : struct sk_buff *skb,
329 : : struct flowi4 *fl4,
330 : : struct flow_keys *flkeys)
331 : : {
332 : : return false;
333 : : }
334 : : #else /* CONFIG_IP_MULTIPLE_TABLES */
335 : : int __net_init fib4_rules_init(struct net *net);
336 : : void __net_exit fib4_rules_exit(struct net *net);
337 : :
338 : : struct fib_table *fib_new_table(struct net *net, u32 id);
339 : : struct fib_table *fib_get_table(struct net *net, u32 id);
340 : :
341 : : int __fib_lookup(struct net *net, struct flowi4 *flp,
342 : : struct fib_result *res, unsigned int flags);
343 : :
344 : 15905 : static inline int fib_lookup(struct net *net, struct flowi4 *flp,
345 : : struct fib_result *res, unsigned int flags)
346 : : {
347 : : struct fib_table *tb;
348 : : int err = -ENETUNREACH;
349 : :
350 : 15905 : flags |= FIB_LOOKUP_NOREF;
351 [ - + ]: 15905 : if (net->ipv4.fib_has_custom_rules)
352 : 0 : return __fib_lookup(net, flp, res, flags);
353 : :
354 : : rcu_read_lock();
355 : :
356 : 15905 : res->tclassid = 0;
357 : :
358 : 15905 : tb = rcu_dereference_rtnl(net->ipv4.fib_main);
359 [ + - ]: 15905 : if (tb)
360 : 15905 : err = fib_table_lookup(tb, flp, res, flags);
361 : :
362 [ + + ]: 15905 : if (!err)
363 : : goto out;
364 : :
365 : 4696 : tb = rcu_dereference_rtnl(net->ipv4.fib_default);
366 [ - + ]: 4696 : if (tb)
367 : 0 : err = fib_table_lookup(tb, flp, res, flags);
368 : :
369 : : out:
370 [ + + ]: 15905 : if (err == -EAGAIN)
371 : : err = -ENETUNREACH;
372 : :
373 : : rcu_read_unlock();
374 : :
375 : 15905 : return err;
376 : : }
377 : :
378 : : bool fib4_rule_default(const struct fib_rule *rule);
379 : : int fib4_rules_dump(struct net *net, struct notifier_block *nb);
380 : : unsigned int fib4_rules_seq_read(struct net *net);
381 : :
382 : : static inline bool fib4_rules_early_flow_dissect(struct net *net,
383 : : struct sk_buff *skb,
384 : : struct flowi4 *fl4,
385 : : struct flow_keys *flkeys)
386 : : {
387 : : unsigned int flag = FLOW_DISSECTOR_F_STOP_AT_ENCAP;
388 : :
389 [ - + ]: 5187 : if (!net->ipv4.fib_rules_require_fldissect)
390 : : return false;
391 : :
392 : 0 : skb_flow_dissect_flow_keys(skb, flkeys, flag);
393 : 0 : fl4->fl4_sport = flkeys->ports.src;
394 : 0 : fl4->fl4_dport = flkeys->ports.dst;
395 : 0 : fl4->flowi4_proto = flkeys->basic.ip_proto;
396 : :
397 : : return true;
398 : : }
399 : :
400 : : #endif /* CONFIG_IP_MULTIPLE_TABLES */
401 : :
402 : : /* Exported by fib_frontend.c */
403 : : extern const struct nla_policy rtm_ipv4_policy[];
404 : : void ip_fib_init(void);
405 : : int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla,
406 : : struct netlink_ext_ack *extack);
407 : : __be32 fib_compute_spec_dst(struct sk_buff *skb);
408 : : bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev);
409 : : int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
410 : : u8 tos, int oif, struct net_device *dev,
411 : : struct in_device *idev, u32 *itag);
412 : : #ifdef CONFIG_IP_ROUTE_CLASSID
413 : : static inline int fib_num_tclassid_users(struct net *net)
414 : : {
415 : 6446 : return net->ipv4.fib_num_tclassid_users;
416 : : }
417 : : #else
418 : : static inline int fib_num_tclassid_users(struct net *net)
419 : : {
420 : : return 0;
421 : : }
422 : : #endif
423 : : int fib_unmerge(struct net *net);
424 : :
425 : : static inline bool nhc_l3mdev_matches_dev(const struct fib_nh_common *nhc,
426 : : const struct net_device *dev)
427 : : {
428 [ # # # # : 0 : if (nhc->nhc_dev == dev ||
# # # # #
# # # ]
429 : 0 : l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex)
430 : : return true;
431 : :
432 : : return false;
433 : : }
434 : :
435 : : /* Exported by fib_semantics.c */
436 : : int ip_fib_check_default(__be32 gw, struct net_device *dev);
437 : : int fib_sync_down_dev(struct net_device *dev, unsigned long event, bool force);
438 : : int fib_sync_down_addr(struct net_device *dev, __be32 local);
439 : : int fib_sync_up(struct net_device *dev, unsigned char nh_flags);
440 : : void fib_sync_mtu(struct net_device *dev, u32 orig_mtu);
441 : : void fib_nhc_update_mtu(struct fib_nh_common *nhc, u32 new, u32 orig);
442 : :
443 : : #ifdef CONFIG_IP_ROUTE_MULTIPATH
444 : : int fib_multipath_hash(const struct net *net, const struct flowi4 *fl4,
445 : : const struct sk_buff *skb, struct flow_keys *flkeys);
446 : : #endif
447 : : int fib_check_nh(struct net *net, struct fib_nh *nh, u32 table, u8 scope,
448 : : struct netlink_ext_ack *extack);
449 : : void fib_select_multipath(struct fib_result *res, int hash);
450 : : void fib_select_path(struct net *net, struct fib_result *res,
451 : : struct flowi4 *fl4, const struct sk_buff *skb);
452 : :
453 : : int fib_nh_init(struct net *net, struct fib_nh *fib_nh,
454 : : struct fib_config *cfg, int nh_weight,
455 : : struct netlink_ext_ack *extack);
456 : : void fib_nh_release(struct net *net, struct fib_nh *fib_nh);
457 : : int fib_nh_common_init(struct fib_nh_common *nhc, struct nlattr *fc_encap,
458 : : u16 fc_encap_type, void *cfg, gfp_t gfp_flags,
459 : : struct netlink_ext_ack *extack);
460 : : void fib_nh_common_release(struct fib_nh_common *nhc);
461 : :
462 : : /* Exported by fib_trie.c */
463 : : void fib_trie_init(void);
464 : : struct fib_table *fib_trie_table(u32 id, struct fib_table *alias);
465 : :
466 : : static inline void fib_combine_itag(u32 *itag, const struct fib_result *res)
467 : : {
468 : : #ifdef CONFIG_IP_ROUTE_CLASSID
469 : 0 : struct fib_nh_common *nhc = res->nhc;
470 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
471 : : u32 rtag;
472 : : #endif
473 [ # # ]: 0 : if (nhc->nhc_family == AF_INET) {
474 : : struct fib_nh *nh;
475 : :
476 : : nh = container_of(nhc, struct fib_nh, nh_common);
477 : 0 : *itag = nh->nh_tclassid << 16;
478 : : } else {
479 : 0 : *itag = 0;
480 : : }
481 : :
482 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
483 : 0 : rtag = res->tclassid;
484 [ # # ]: 0 : if (*itag == 0)
485 : 0 : *itag = (rtag<<16);
486 : 0 : *itag |= (rtag>>16);
487 : : #endif
488 : : #endif
489 : : }
490 : :
491 : : void fib_flush(struct net *net);
492 : : void free_fib_info(struct fib_info *fi);
493 : :
494 : : static inline void fib_info_hold(struct fib_info *fi)
495 : : {
496 : : refcount_inc(&fi->fib_clntref);
497 : : }
498 : :
499 : 0 : static inline void fib_info_put(struct fib_info *fi)
500 : : {
501 [ # # ]: 0 : if (refcount_dec_and_test(&fi->fib_clntref))
502 : 0 : free_fib_info(fi);
503 : 0 : }
504 : :
505 : : #ifdef CONFIG_PROC_FS
506 : : int __net_init fib_proc_init(struct net *net);
507 : : void __net_exit fib_proc_exit(struct net *net);
508 : : #else
509 : : static inline int fib_proc_init(struct net *net)
510 : : {
511 : : return 0;
512 : : }
513 : : static inline void fib_proc_exit(struct net *net)
514 : : {
515 : : }
516 : : #endif
517 : :
518 : : u32 ip_mtu_from_fib_result(struct fib_result *res, __be32 daddr);
519 : :
520 : : int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
521 : : struct fib_dump_filter *filter,
522 : : struct netlink_callback *cb);
523 : :
524 : : int fib_nexthop_info(struct sk_buff *skb, const struct fib_nh_common *nh,
525 : : u8 rt_family, unsigned char *flags, bool skip_oif);
526 : : int fib_add_nexthop(struct sk_buff *skb, const struct fib_nh_common *nh,
527 : : int nh_weight, u8 rt_family);
528 : : #endif /* _NET_FIB_H */
|