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 : : * IPv4 Forwarding Information Base: FIB frontend.
8 : : *
9 : : * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 : : */
11 : :
12 : : #include <linux/module.h>
13 : : #include <linux/uaccess.h>
14 : : #include <linux/bitops.h>
15 : : #include <linux/capability.h>
16 : : #include <linux/types.h>
17 : : #include <linux/kernel.h>
18 : : #include <linux/mm.h>
19 : : #include <linux/string.h>
20 : : #include <linux/socket.h>
21 : : #include <linux/sockios.h>
22 : : #include <linux/errno.h>
23 : : #include <linux/in.h>
24 : : #include <linux/inet.h>
25 : : #include <linux/inetdevice.h>
26 : : #include <linux/netdevice.h>
27 : : #include <linux/if_addr.h>
28 : : #include <linux/if_arp.h>
29 : : #include <linux/skbuff.h>
30 : : #include <linux/cache.h>
31 : : #include <linux/init.h>
32 : : #include <linux/list.h>
33 : : #include <linux/slab.h>
34 : :
35 : : #include <net/ip.h>
36 : : #include <net/protocol.h>
37 : : #include <net/route.h>
38 : : #include <net/tcp.h>
39 : : #include <net/sock.h>
40 : : #include <net/arp.h>
41 : : #include <net/ip_fib.h>
42 : : #include <net/nexthop.h>
43 : : #include <net/rtnetlink.h>
44 : : #include <net/xfrm.h>
45 : : #include <net/l3mdev.h>
46 : : #include <net/lwtunnel.h>
47 : : #include <trace/events/fib.h>
48 : :
49 : : #ifndef CONFIG_IP_MULTIPLE_TABLES
50 : :
51 : : static int __net_init fib4_rules_init(struct net *net)
52 : : {
53 : : struct fib_table *local_table, *main_table;
54 : :
55 : : main_table = fib_trie_table(RT_TABLE_MAIN, NULL);
56 : : if (!main_table)
57 : : return -ENOMEM;
58 : :
59 : : local_table = fib_trie_table(RT_TABLE_LOCAL, main_table);
60 : : if (!local_table)
61 : : goto fail;
62 : :
63 : : hlist_add_head_rcu(&local_table->tb_hlist,
64 : : &net->ipv4.fib_table_hash[TABLE_LOCAL_INDEX]);
65 : : hlist_add_head_rcu(&main_table->tb_hlist,
66 : : &net->ipv4.fib_table_hash[TABLE_MAIN_INDEX]);
67 : : return 0;
68 : :
69 : : fail:
70 : : fib_free_table(main_table);
71 : : return -ENOMEM;
72 : : }
73 : : #else
74 : :
75 : 66 : struct fib_table *fib_new_table(struct net *net, u32 id)
76 : : {
77 : 66 : struct fib_table *tb, *alias = NULL;
78 : 66 : unsigned int h;
79 : :
80 [ + - ]: 66 : if (id == 0)
81 : : id = RT_TABLE_MAIN;
82 : 66 : tb = fib_get_table(net, id);
83 [ + + ]: 66 : if (tb)
84 : : return tb;
85 : :
86 [ + + + - ]: 22 : if (id == RT_TABLE_LOCAL && !net->ipv4.fib_has_custom_rules)
87 : 11 : alias = fib_new_table(net, RT_TABLE_MAIN);
88 : :
89 : 22 : tb = fib_trie_table(id, alias);
90 [ + - ]: 22 : if (!tb)
91 : : return NULL;
92 : :
93 [ + - + ]: 22 : switch (id) {
94 : 11 : case RT_TABLE_MAIN:
95 : 11 : rcu_assign_pointer(net->ipv4.fib_main, tb);
96 : : break;
97 : 0 : case RT_TABLE_DEFAULT:
98 : 0 : rcu_assign_pointer(net->ipv4.fib_default, tb);
99 : : break;
100 : : default:
101 : : break;
102 : : }
103 : :
104 : 22 : h = id & (FIB_TABLE_HASHSZ - 1);
105 : 22 : hlist_add_head_rcu(&tb->tb_hlist, &net->ipv4.fib_table_hash[h]);
106 : : return tb;
107 : : }
108 : : EXPORT_SYMBOL_GPL(fib_new_table);
109 : :
110 : : /* caller must hold either rtnl or rcu read lock */
111 : 66 : struct fib_table *fib_get_table(struct net *net, u32 id)
112 : : {
113 : 66 : struct fib_table *tb;
114 : 66 : struct hlist_head *head;
115 : 66 : unsigned int h;
116 : :
117 [ - - ]: 66 : if (id == 0)
118 : 0 : id = RT_TABLE_MAIN;
119 : 66 : h = id & (FIB_TABLE_HASHSZ - 1);
120 : :
121 : 66 : head = &net->ipv4.fib_table_hash[h];
122 [ - - - - : 66 : hlist_for_each_entry_rcu(tb, head, tb_hlist,
- - - - -
- - - - -
- - - - -
- - - - -
- - - - +
+ ]
123 : : lockdep_rtnl_is_held()) {
124 [ - - - - : 44 : if (tb->tb_id == id)
- - - - -
- - - -
+ ]
125 : 0 : return tb;
126 : : }
127 : : return NULL;
128 : : }
129 : : #endif /* CONFIG_IP_MULTIPLE_TABLES */
130 : :
131 : 0 : static void fib_replace_table(struct net *net, struct fib_table *old,
132 : : struct fib_table *new)
133 : : {
134 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
135 : 0 : switch (new->tb_id) {
136 : 0 : case RT_TABLE_MAIN:
137 : 0 : rcu_assign_pointer(net->ipv4.fib_main, new);
138 : : break;
139 : 0 : case RT_TABLE_DEFAULT:
140 : 0 : rcu_assign_pointer(net->ipv4.fib_default, new);
141 : : break;
142 : : default:
143 : : break;
144 : : }
145 : :
146 : : #endif
147 : : /* replace the old table in the hlist */
148 : 0 : hlist_replace_rcu(&old->tb_hlist, &new->tb_hlist);
149 : : }
150 : :
151 : 0 : int fib_unmerge(struct net *net)
152 : : {
153 : 0 : struct fib_table *old, *new, *main_table;
154 : :
155 : : /* attempt to fetch local table if it has been allocated */
156 : 0 : old = fib_get_table(net, RT_TABLE_LOCAL);
157 [ # # ]: 0 : if (!old)
158 : : return 0;
159 : :
160 : 0 : new = fib_trie_unmerge(old);
161 [ # # ]: 0 : if (!new)
162 : : return -ENOMEM;
163 : :
164 : : /* table is already unmerged */
165 [ # # ]: 0 : if (new == old)
166 : : return 0;
167 : :
168 : : /* replace merged table with clean table */
169 [ # # # ]: 0 : fib_replace_table(net, old, new);
170 : 0 : fib_free_table(old);
171 : :
172 : : /* attempt to fetch main table if it has been allocated */
173 : 0 : main_table = fib_get_table(net, RT_TABLE_MAIN);
174 [ # # ]: 0 : if (!main_table)
175 : : return 0;
176 : :
177 : : /* flush local entries from main table */
178 : 0 : fib_table_flush_external(main_table);
179 : :
180 : 0 : return 0;
181 : : }
182 : :
183 : 0 : void fib_flush(struct net *net)
184 : : {
185 : 0 : int flushed = 0;
186 : 0 : unsigned int h;
187 : :
188 [ # # ]: 0 : for (h = 0; h < FIB_TABLE_HASHSZ; h++) {
189 : 0 : struct hlist_head *head = &net->ipv4.fib_table_hash[h];
190 : 0 : struct hlist_node *tmp;
191 : 0 : struct fib_table *tb;
192 : :
193 [ # # # # ]: 0 : hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
194 [ # # ]: 0 : flushed += fib_table_flush(net, tb, false);
195 : : }
196 : :
197 [ # # ]: 0 : if (flushed)
198 : 0 : rt_cache_flush(net);
199 : 0 : }
200 : :
201 : : /*
202 : : * Find address type as if only "dev" was present in the system. If
203 : : * on_dev is NULL then all interfaces are taken into consideration.
204 : : */
205 : : static inline unsigned int __inet_dev_addr_type(struct net *net,
206 : : const struct net_device *dev,
207 : : __be32 addr, u32 tb_id)
208 : : {
209 : : struct flowi4 fl4 = { .daddr = addr };
210 : : struct fib_result res;
211 : : unsigned int ret = RTN_BROADCAST;
212 : : struct fib_table *table;
213 : :
214 : : if (ipv4_is_zeronet(addr) || ipv4_is_lbcast(addr))
215 : : return RTN_BROADCAST;
216 : : if (ipv4_is_multicast(addr))
217 : : return RTN_MULTICAST;
218 : :
219 : : rcu_read_lock();
220 : :
221 : : table = fib_get_table(net, tb_id);
222 : : if (table) {
223 : : ret = RTN_UNICAST;
224 : : if (!fib_table_lookup(table, &fl4, &res, FIB_LOOKUP_NOREF)) {
225 : : struct fib_nh_common *nhc = fib_info_nhc(res.fi, 0);
226 : :
227 : : if (!dev || dev == nhc->nhc_dev)
228 : : ret = res.type;
229 : : }
230 : : }
231 : :
232 : : rcu_read_unlock();
233 : : return ret;
234 : : }
235 : :
236 : 44 : unsigned int inet_addr_type_table(struct net *net, __be32 addr, u32 tb_id)
237 : : {
238 : 44 : return __inet_dev_addr_type(net, NULL, addr, tb_id);
239 : : }
240 : : EXPORT_SYMBOL(inet_addr_type_table);
241 : :
242 : 0 : unsigned int inet_addr_type(struct net *net, __be32 addr)
243 : : {
244 : 0 : return __inet_dev_addr_type(net, NULL, addr, RT_TABLE_LOCAL);
245 : : }
246 : : EXPORT_SYMBOL(inet_addr_type);
247 : :
248 : 0 : unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
249 : : __be32 addr)
250 : : {
251 : 0 : u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
252 : :
253 : 0 : return __inet_dev_addr_type(net, dev, addr, rt_table);
254 : : }
255 : : EXPORT_SYMBOL(inet_dev_addr_type);
256 : :
257 : : /* inet_addr_type with dev == NULL but using the table from a dev
258 : : * if one is associated
259 : : */
260 : 0 : unsigned int inet_addr_type_dev_table(struct net *net,
261 : : const struct net_device *dev,
262 : : __be32 addr)
263 : : {
264 : 0 : u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
265 : :
266 : 0 : return __inet_dev_addr_type(net, NULL, addr, rt_table);
267 : : }
268 : : EXPORT_SYMBOL(inet_addr_type_dev_table);
269 : :
270 : 0 : __be32 fib_compute_spec_dst(struct sk_buff *skb)
271 : : {
272 : 0 : struct net_device *dev = skb->dev;
273 : 0 : struct in_device *in_dev;
274 : 0 : struct fib_result res;
275 : 0 : struct rtable *rt;
276 : 0 : struct net *net;
277 : 0 : int scope;
278 : :
279 [ # # ]: 0 : rt = skb_rtable(skb);
280 [ # # ]: 0 : if ((rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST | RTCF_LOCAL)) ==
281 : : RTCF_LOCAL)
282 : 0 : return ip_hdr(skb)->daddr;
283 : :
284 [ # # ]: 0 : in_dev = __in_dev_get_rcu(dev);
285 : :
286 [ # # ]: 0 : net = dev_net(dev);
287 : :
288 : 0 : scope = RT_SCOPE_UNIVERSE;
289 [ # # ]: 0 : if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) {
290 [ # # # # : 0 : bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev);
# # ]
291 [ # # ]: 0 : struct flowi4 fl4 = {
292 : : .flowi4_iif = LOOPBACK_IFINDEX,
293 : : .flowi4_oif = l3mdev_master_ifindex_rcu(dev),
294 : 0 : .daddr = ip_hdr(skb)->saddr,
295 : 0 : .flowi4_tos = RT_TOS(ip_hdr(skb)->tos),
296 : : .flowi4_scope = scope,
297 [ # # ]: 0 : .flowi4_mark = vmark ? skb->mark : 0,
298 : : };
299 [ # # ]: 0 : if (!fib_lookup(net, &fl4, &res, 0))
300 : 0 : return fib_result_prefsrc(net, &res);
301 : : } else {
302 : : scope = RT_SCOPE_LINK;
303 : : }
304 : :
305 : 0 : return inet_select_addr(dev, ip_hdr(skb)->saddr, scope);
306 : : }
307 : :
308 : 0 : bool fib_info_nh_uses_dev(struct fib_info *fi, const struct net_device *dev)
309 : : {
310 : 0 : bool dev_match = false;
311 : : #ifdef CONFIG_IP_ROUTE_MULTIPATH
312 : 0 : int ret;
313 : :
314 [ # # # # ]: 0 : for (ret = 0; ret < fib_info_num_path(fi); ret++) {
315 [ # # ]: 0 : const struct fib_nh_common *nhc = fib_info_nhc(fi, ret);
316 : :
317 [ # # ]: 0 : if (nhc->nhc_dev == dev) {
318 : : dev_match = true;
319 : : break;
320 [ # # ]: 0 : } else if (l3mdev_master_ifindex_rcu(nhc->nhc_dev) == dev->ifindex) {
321 : : dev_match = true;
322 : : break;
323 : : }
324 : : }
325 : : #else
326 : : if (fib_info_nhc(fi, 0)->nhc_dev == dev)
327 : : dev_match = true;
328 : : #endif
329 : :
330 : 0 : return dev_match;
331 : : }
332 : : EXPORT_SYMBOL_GPL(fib_info_nh_uses_dev);
333 : :
334 : : /* Given (packet source, input interface) and optional (dst, oif, tos):
335 : : * - (main) check, that source is valid i.e. not broadcast or our local
336 : : * address.
337 : : * - figure out what "logical" interface this packet arrived
338 : : * and calculate "specific destination" address.
339 : : * - check, that packet arrived from expected physical interface.
340 : : * called with rcu_read_lock()
341 : : */
342 : 0 : static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
343 : : u8 tos, int oif, struct net_device *dev,
344 : : int rpf, struct in_device *idev, u32 *itag)
345 : : {
346 [ # # ]: 0 : struct net *net = dev_net(dev);
347 : 0 : struct flow_keys flkeys;
348 : 0 : int ret, no_addr;
349 : 0 : struct fib_result res;
350 : 0 : struct flowi4 fl4;
351 : 0 : bool dev_match;
352 : :
353 : 0 : fl4.flowi4_oif = 0;
354 [ # # ]: 0 : fl4.flowi4_iif = l3mdev_master_ifindex_rcu(dev);
355 : 0 : if (!fl4.flowi4_iif)
356 [ # # ]: 0 : fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX;
357 : 0 : fl4.daddr = src;
358 : 0 : fl4.saddr = dst;
359 : 0 : fl4.flowi4_tos = tos;
360 : 0 : fl4.flowi4_scope = RT_SCOPE_UNIVERSE;
361 : 0 : fl4.flowi4_tun_key.tun_id = 0;
362 : 0 : fl4.flowi4_flags = 0;
363 [ # # ]: 0 : fl4.flowi4_uid = sock_net_uid(net, NULL);
364 : :
365 : 0 : no_addr = idev->ifa_list == NULL;
366 : :
367 [ # # # # ]: 0 : fl4.flowi4_mark = IN_DEV_SRC_VMARK(idev) ? skb->mark : 0;
368 [ # # ]: 0 : if (!fib4_rules_early_flow_dissect(net, skb, &fl4, &flkeys)) {
369 : 0 : fl4.flowi4_proto = 0;
370 : 0 : fl4.fl4_sport = 0;
371 : 0 : fl4.fl4_dport = 0;
372 : : }
373 : :
374 [ # # ]: 0 : if (fib_lookup(net, &fl4, &res, 0))
375 : 0 : goto last_resort;
376 [ # # # # ]: 0 : if (res.type != RTN_UNICAST &&
377 [ # # # # ]: 0 : (res.type != RTN_LOCAL || !IN_DEV_ACCEPT_LOCAL(idev)))
378 : 0 : goto e_inval;
379 : 0 : fib_combine_itag(itag, &res);
380 : :
381 : 0 : dev_match = fib_info_nh_uses_dev(res.fi, dev);
382 : : /* This is not common, loopback packets retain skb_dst so normally they
383 : : * would not even hit this slow path.
384 : : */
385 [ # # # # ]: 0 : dev_match = dev_match || (res.type == RTN_LOCAL &&
386 [ # # ]: 0 : dev == net->loopback_dev);
387 [ # # ]: 0 : if (dev_match) {
388 : 0 : ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
389 : 0 : return ret;
390 : : }
391 [ # # ]: 0 : if (no_addr)
392 : 0 : goto last_resort;
393 [ # # ]: 0 : if (rpf == 1)
394 : 0 : goto e_rpf;
395 : 0 : fl4.flowi4_oif = dev->ifindex;
396 : :
397 : 0 : ret = 0;
398 [ # # ]: 0 : if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
399 [ # # ]: 0 : if (res.type == RTN_UNICAST)
400 : 0 : ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
401 : : }
402 : : return ret;
403 : :
404 : 0 : last_resort:
405 [ # # ]: 0 : if (rpf)
406 : 0 : goto e_rpf;
407 : 0 : *itag = 0;
408 : 0 : return 0;
409 : :
410 : : e_inval:
411 : 0 : return -EINVAL;
412 : : e_rpf:
413 : : return -EXDEV;
414 : : }
415 : :
416 : : /* Ignore rp_filter for packets protected by IPsec. */
417 : 0 : int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
418 : : u8 tos, int oif, struct net_device *dev,
419 : : struct in_device *idev, u32 *itag)
420 : : {
421 [ # # # # ]: 0 : int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev);
422 : 0 : struct net *net = dev_net(dev);
423 : :
424 [ # # ]: 0 : if (!r && !fib_num_tclassid_users(net) &&
425 [ # # # # : 0 : (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) {
# # ]
426 [ # # # # ]: 0 : if (IN_DEV_ACCEPT_LOCAL(idev))
427 : 0 : goto ok;
428 : : /* with custom local routes in place, checking local addresses
429 : : * only will be too optimistic, with custom rules, checking
430 : : * local addresses only can be too strict, e.g. due to vrf
431 : : */
432 [ # # # # ]: 0 : if (net->ipv4.fib_has_custom_local_routes ||
433 [ # # ]: 0 : fib4_has_custom_rules(net))
434 : 0 : goto full_check;
435 [ # # ]: 0 : if (inet_lookup_ifaddr_rcu(net, src))
436 : : return -EINVAL;
437 : :
438 : 0 : ok:
439 : 0 : *itag = 0;
440 : 0 : return 0;
441 : : }
442 : :
443 : 0 : full_check:
444 : 0 : return __fib_validate_source(skb, src, dst, tos, oif, dev, r, idev, itag);
445 : : }
446 : :
447 : 0 : static inline __be32 sk_extract_addr(struct sockaddr *addr)
448 : : {
449 : 0 : return ((struct sockaddr_in *) addr)->sin_addr.s_addr;
450 : : }
451 : :
452 : 0 : static int put_rtax(struct nlattr *mx, int len, int type, u32 value)
453 : : {
454 : 0 : struct nlattr *nla;
455 : :
456 : 0 : nla = (struct nlattr *) ((char *) mx + len);
457 : 0 : nla->nla_type = type;
458 : 0 : nla->nla_len = nla_attr_size(4);
459 : 0 : *(u32 *) nla_data(nla) = value;
460 : :
461 : 0 : return len + nla_total_size(4);
462 : : }
463 : :
464 : 0 : static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
465 : : struct fib_config *cfg)
466 : : {
467 : 0 : __be32 addr;
468 : 0 : int plen;
469 : :
470 : 0 : memset(cfg, 0, sizeof(*cfg));
471 : 0 : cfg->fc_nlinfo.nl_net = net;
472 : :
473 [ # # ]: 0 : if (rt->rt_dst.sa_family != AF_INET)
474 : : return -EAFNOSUPPORT;
475 : :
476 : : /*
477 : : * Check mask for validity:
478 : : * a) it must be contiguous.
479 : : * b) destination must have all host bits clear.
480 : : * c) if application forgot to set correct family (AF_INET),
481 : : * reject request unless it is absolutely clear i.e.
482 : : * both family and mask are zero.
483 : : */
484 : 0 : plen = 32;
485 : 0 : addr = sk_extract_addr(&rt->rt_dst);
486 [ # # ]: 0 : if (!(rt->rt_flags & RTF_HOST)) {
487 : 0 : __be32 mask = sk_extract_addr(&rt->rt_genmask);
488 : :
489 [ # # ]: 0 : if (rt->rt_genmask.sa_family != AF_INET) {
490 [ # # # # ]: 0 : if (mask || rt->rt_genmask.sa_family)
491 : : return -EAFNOSUPPORT;
492 : : }
493 : :
494 [ # # ]: 0 : if (bad_mask(mask, addr))
495 : : return -EINVAL;
496 : :
497 [ # # ]: 0 : plen = inet_mask_len(mask);
498 : : }
499 : :
500 : 0 : cfg->fc_dst_len = plen;
501 : 0 : cfg->fc_dst = addr;
502 : :
503 [ # # ]: 0 : if (cmd != SIOCDELRT) {
504 : 0 : cfg->fc_nlflags = NLM_F_CREATE;
505 : 0 : cfg->fc_protocol = RTPROT_BOOT;
506 : : }
507 : :
508 [ # # ]: 0 : if (rt->rt_metric)
509 : 0 : cfg->fc_priority = rt->rt_metric - 1;
510 : :
511 [ # # ]: 0 : if (rt->rt_flags & RTF_REJECT) {
512 : 0 : cfg->fc_scope = RT_SCOPE_HOST;
513 : 0 : cfg->fc_type = RTN_UNREACHABLE;
514 : 0 : return 0;
515 : : }
516 : :
517 : 0 : cfg->fc_scope = RT_SCOPE_NOWHERE;
518 : 0 : cfg->fc_type = RTN_UNICAST;
519 : :
520 [ # # ]: 0 : if (rt->rt_dev) {
521 : 0 : char *colon;
522 : 0 : struct net_device *dev;
523 : 0 : char devname[IFNAMSIZ];
524 : :
525 [ # # ]: 0 : if (copy_from_user(devname, rt->rt_dev, IFNAMSIZ-1))
526 : 0 : return -EFAULT;
527 : :
528 : 0 : devname[IFNAMSIZ-1] = 0;
529 : 0 : colon = strchr(devname, ':');
530 [ # # ]: 0 : if (colon)
531 : 0 : *colon = 0;
532 : 0 : dev = __dev_get_by_name(net, devname);
533 [ # # ]: 0 : if (!dev)
534 : : return -ENODEV;
535 : 0 : cfg->fc_oif = dev->ifindex;
536 [ # # ]: 0 : cfg->fc_table = l3mdev_fib_table(dev);
537 [ # # ]: 0 : if (colon) {
538 : 0 : const struct in_ifaddr *ifa;
539 : 0 : struct in_device *in_dev;
540 : :
541 [ # # ]: 0 : in_dev = __in_dev_get_rtnl(dev);
542 [ # # ]: 0 : if (!in_dev)
543 : : return -ENODEV;
544 : :
545 : 0 : *colon = ':';
546 : :
547 : 0 : rcu_read_lock();
548 [ # # ]: 0 : in_dev_for_each_ifa_rcu(ifa, in_dev) {
549 [ # # ]: 0 : if (strcmp(ifa->ifa_label, devname) == 0)
550 : : break;
551 : : }
552 : 0 : rcu_read_unlock();
553 : :
554 [ # # ]: 0 : if (!ifa)
555 : : return -ENODEV;
556 : 0 : cfg->fc_prefsrc = ifa->ifa_local;
557 : : }
558 : : }
559 : :
560 : 0 : addr = sk_extract_addr(&rt->rt_gateway);
561 [ # # # # ]: 0 : if (rt->rt_gateway.sa_family == AF_INET && addr) {
562 : 0 : unsigned int addr_type;
563 : :
564 : 0 : cfg->fc_gw4 = addr;
565 : 0 : cfg->fc_gw_family = AF_INET;
566 : 0 : addr_type = inet_addr_type_table(net, addr, cfg->fc_table);
567 [ # # # # ]: 0 : if (rt->rt_flags & RTF_GATEWAY &&
568 : : addr_type == RTN_UNICAST)
569 : 0 : cfg->fc_scope = RT_SCOPE_UNIVERSE;
570 : : }
571 : :
572 [ # # ]: 0 : if (cmd == SIOCDELRT)
573 : : return 0;
574 : :
575 [ # # # # ]: 0 : if (rt->rt_flags & RTF_GATEWAY && !cfg->fc_gw_family)
576 : : return -EINVAL;
577 : :
578 [ # # ]: 0 : if (cfg->fc_scope == RT_SCOPE_NOWHERE)
579 : 0 : cfg->fc_scope = RT_SCOPE_LINK;
580 : :
581 [ # # ]: 0 : if (rt->rt_flags & (RTF_MTU | RTF_WINDOW | RTF_IRTT)) {
582 : 0 : struct nlattr *mx;
583 : 0 : int len = 0;
584 : :
585 : 0 : mx = kcalloc(3, nla_total_size(4), GFP_KERNEL);
586 [ # # ]: 0 : if (!mx)
587 : : return -ENOMEM;
588 : :
589 [ # # ]: 0 : if (rt->rt_flags & RTF_MTU)
590 : 0 : len = put_rtax(mx, len, RTAX_ADVMSS, rt->rt_mtu - 40);
591 : :
592 [ # # ]: 0 : if (rt->rt_flags & RTF_WINDOW)
593 : 0 : len = put_rtax(mx, len, RTAX_WINDOW, rt->rt_window);
594 : :
595 [ # # ]: 0 : if (rt->rt_flags & RTF_IRTT)
596 : 0 : len = put_rtax(mx, len, RTAX_RTT, rt->rt_irtt << 3);
597 : :
598 : 0 : cfg->fc_mx = mx;
599 : 0 : cfg->fc_mx_len = len;
600 : : }
601 : :
602 : : return 0;
603 : : }
604 : :
605 : : /*
606 : : * Handle IP routing ioctl calls.
607 : : * These are used to manipulate the routing tables
608 : : */
609 : 0 : int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
610 : : {
611 : 0 : struct fib_config cfg;
612 : 0 : int err;
613 : :
614 [ # # ]: 0 : switch (cmd) {
615 : 0 : case SIOCADDRT: /* Add a route */
616 : : case SIOCDELRT: /* Delete a route */
617 [ # # ]: 0 : if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
618 : : return -EPERM;
619 : :
620 : 0 : rtnl_lock();
621 : 0 : err = rtentry_to_fib_config(net, cmd, rt, &cfg);
622 [ # # ]: 0 : if (err == 0) {
623 : 0 : struct fib_table *tb;
624 : :
625 [ # # ]: 0 : if (cmd == SIOCDELRT) {
626 [ # # ]: 0 : tb = fib_get_table(net, cfg.fc_table);
627 [ # # ]: 0 : if (tb)
628 : 0 : err = fib_table_delete(net, tb, &cfg,
629 : : NULL);
630 : : else
631 : : err = -ESRCH;
632 : : } else {
633 : 0 : tb = fib_new_table(net, cfg.fc_table);
634 [ # # ]: 0 : if (tb)
635 : 0 : err = fib_table_insert(net, tb,
636 : : &cfg, NULL);
637 : : else
638 : : err = -ENOBUFS;
639 : : }
640 : :
641 : : /* allocated by rtentry_to_fib_config() */
642 : 0 : kfree(cfg.fc_mx);
643 : : }
644 : 0 : rtnl_unlock();
645 : 0 : return err;
646 : : }
647 : : return -EINVAL;
648 : : }
649 : :
650 : : const struct nla_policy rtm_ipv4_policy[RTA_MAX + 1] = {
651 : : [RTA_UNSPEC] = { .strict_start_type = RTA_DPORT + 1 },
652 : : [RTA_DST] = { .type = NLA_U32 },
653 : : [RTA_SRC] = { .type = NLA_U32 },
654 : : [RTA_IIF] = { .type = NLA_U32 },
655 : : [RTA_OIF] = { .type = NLA_U32 },
656 : : [RTA_GATEWAY] = { .type = NLA_U32 },
657 : : [RTA_PRIORITY] = { .type = NLA_U32 },
658 : : [RTA_PREFSRC] = { .type = NLA_U32 },
659 : : [RTA_METRICS] = { .type = NLA_NESTED },
660 : : [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
661 : : [RTA_FLOW] = { .type = NLA_U32 },
662 : : [RTA_ENCAP_TYPE] = { .type = NLA_U16 },
663 : : [RTA_ENCAP] = { .type = NLA_NESTED },
664 : : [RTA_UID] = { .type = NLA_U32 },
665 : : [RTA_MARK] = { .type = NLA_U32 },
666 : : [RTA_TABLE] = { .type = NLA_U32 },
667 : : [RTA_IP_PROTO] = { .type = NLA_U8 },
668 : : [RTA_SPORT] = { .type = NLA_U16 },
669 : : [RTA_DPORT] = { .type = NLA_U16 },
670 : : [RTA_NH_ID] = { .type = NLA_U32 },
671 : : };
672 : :
673 : 0 : int fib_gw_from_via(struct fib_config *cfg, struct nlattr *nla,
674 : : struct netlink_ext_ack *extack)
675 : : {
676 : 0 : struct rtvia *via;
677 : 0 : int alen;
678 : :
679 [ # # ]: 0 : if (nla_len(nla) < offsetof(struct rtvia, rtvia_addr)) {
680 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid attribute length for RTA_VIA");
681 : 0 : return -EINVAL;
682 : : }
683 : :
684 [ # # # ]: 0 : via = nla_data(nla);
685 [ # # # ]: 0 : alen = nla_len(nla) - offsetof(struct rtvia, rtvia_addr);
686 : :
687 [ # # # ]: 0 : switch (via->rtvia_family) {
688 : 0 : case AF_INET:
689 [ # # ]: 0 : if (alen != sizeof(__be32)) {
690 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid IPv4 address in RTA_VIA");
691 : 0 : return -EINVAL;
692 : : }
693 : 0 : cfg->fc_gw_family = AF_INET;
694 : 0 : cfg->fc_gw4 = *((__be32 *)via->rtvia_addr);
695 : 0 : break;
696 : 0 : case AF_INET6:
697 : : #ifdef CONFIG_IPV6
698 [ # # ]: 0 : if (alen != sizeof(struct in6_addr)) {
699 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_VIA");
700 : 0 : return -EINVAL;
701 : : }
702 : 0 : cfg->fc_gw_family = AF_INET6;
703 : 0 : cfg->fc_gw6 = *((struct in6_addr *)via->rtvia_addr);
704 : : #else
705 : : NL_SET_ERR_MSG(extack, "IPv6 support not enabled in kernel");
706 : : return -EINVAL;
707 : : #endif
708 : 0 : break;
709 : 0 : default:
710 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Unsupported address family in RTA_VIA");
711 : : return -EINVAL;
712 : : }
713 : :
714 : : return 0;
715 : : }
716 : :
717 : 0 : static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
718 : : struct nlmsghdr *nlh, struct fib_config *cfg,
719 : : struct netlink_ext_ack *extack)
720 : : {
721 : 0 : bool has_gw = false, has_via = false;
722 : 0 : struct nlattr *attr;
723 : 0 : int err, remaining;
724 : 0 : struct rtmsg *rtm;
725 : :
726 [ # # ]: 0 : err = nlmsg_validate_deprecated(nlh, sizeof(*rtm), RTA_MAX,
727 : : rtm_ipv4_policy, extack);
728 [ # # ]: 0 : if (err < 0)
729 : 0 : goto errout;
730 : :
731 : 0 : memset(cfg, 0, sizeof(*cfg));
732 : :
733 [ # # ]: 0 : rtm = nlmsg_data(nlh);
734 : 0 : cfg->fc_dst_len = rtm->rtm_dst_len;
735 : 0 : cfg->fc_tos = rtm->rtm_tos;
736 : 0 : cfg->fc_table = rtm->rtm_table;
737 : 0 : cfg->fc_protocol = rtm->rtm_protocol;
738 : 0 : cfg->fc_scope = rtm->rtm_scope;
739 : 0 : cfg->fc_type = rtm->rtm_type;
740 : 0 : cfg->fc_flags = rtm->rtm_flags;
741 : 0 : cfg->fc_nlflags = nlh->nlmsg_flags;
742 : :
743 : 0 : cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
744 : 0 : cfg->fc_nlinfo.nlh = nlh;
745 : 0 : cfg->fc_nlinfo.nl_net = net;
746 : :
747 [ # # ]: 0 : if (cfg->fc_type > RTN_MAX) {
748 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid route type");
749 : 0 : err = -EINVAL;
750 : 0 : goto errout;
751 : : }
752 : :
753 [ # # ]: 0 : nlmsg_for_each_attr(attr, nlh, sizeof(struct rtmsg), remaining) {
754 [ # # # # : 0 : switch (nla_type(attr)) {
# # # # #
# # # #
# ]
755 : : case RTA_DST:
756 : 0 : cfg->fc_dst = nla_get_be32(attr);
757 : 0 : break;
758 : : case RTA_OIF:
759 : 0 : cfg->fc_oif = nla_get_u32(attr);
760 : 0 : break;
761 : 0 : case RTA_GATEWAY:
762 : 0 : has_gw = true;
763 [ # # ]: 0 : cfg->fc_gw4 = nla_get_be32(attr);
764 [ # # ]: 0 : if (cfg->fc_gw4)
765 : 0 : cfg->fc_gw_family = AF_INET;
766 : : break;
767 : 0 : case RTA_VIA:
768 : 0 : has_via = true;
769 : 0 : err = fib_gw_from_via(cfg, attr, extack);
770 [ # # ]: 0 : if (err)
771 : 0 : goto errout;
772 : : break;
773 : : case RTA_PRIORITY:
774 : 0 : cfg->fc_priority = nla_get_u32(attr);
775 : 0 : break;
776 : : case RTA_PREFSRC:
777 : 0 : cfg->fc_prefsrc = nla_get_be32(attr);
778 : 0 : break;
779 : : case RTA_METRICS:
780 : 0 : cfg->fc_mx = nla_data(attr);
781 : 0 : cfg->fc_mx_len = nla_len(attr);
782 : 0 : break;
783 : 0 : case RTA_MULTIPATH:
784 : 0 : err = lwtunnel_valid_encap_type_attr(nla_data(attr),
785 : : nla_len(attr),
786 : : extack);
787 : 0 : if (err < 0)
788 : : goto errout;
789 : 0 : cfg->fc_mp = nla_data(attr);
790 : 0 : cfg->fc_mp_len = nla_len(attr);
791 : 0 : break;
792 : : case RTA_FLOW:
793 : 0 : cfg->fc_flow = nla_get_u32(attr);
794 : 0 : break;
795 : : case RTA_TABLE:
796 : 0 : cfg->fc_table = nla_get_u32(attr);
797 : 0 : break;
798 : 0 : case RTA_ENCAP:
799 : 0 : cfg->fc_encap = attr;
800 : 0 : break;
801 : : case RTA_ENCAP_TYPE:
802 [ # # ]: 0 : cfg->fc_encap_type = nla_get_u16(attr);
803 [ # # ]: 0 : err = lwtunnel_valid_encap_type(cfg->fc_encap_type,
804 : : extack);
805 : 0 : if (err < 0)
806 : 0 : goto errout;
807 : : break;
808 : : case RTA_NH_ID:
809 : 0 : cfg->fc_nh_id = nla_get_u32(attr);
810 : 0 : break;
811 : : }
812 : 0 : }
813 : :
814 [ # # ]: 0 : if (cfg->fc_nh_id) {
815 [ # # # # ]: 0 : if (cfg->fc_oif || cfg->fc_gw_family ||
816 [ # # # # ]: 0 : cfg->fc_encap || cfg->fc_mp) {
817 [ # # ]: 0 : NL_SET_ERR_MSG(extack,
818 : : "Nexthop specification and nexthop id are mutually exclusive");
819 : 0 : return -EINVAL;
820 : : }
821 : : }
822 : :
823 [ # # ]: 0 : if (has_gw && has_via) {
824 [ # # ]: 0 : NL_SET_ERR_MSG(extack,
825 : : "Nexthop configuration can not contain both GATEWAY and VIA");
826 : 0 : goto errout;
827 : : }
828 : :
829 : : return 0;
830 : : errout:
831 : : return err;
832 : : }
833 : :
834 : 0 : static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh,
835 : : struct netlink_ext_ack *extack)
836 : : {
837 : 0 : struct net *net = sock_net(skb->sk);
838 : 0 : struct fib_config cfg;
839 : 0 : struct fib_table *tb;
840 : 0 : int err;
841 : :
842 : 0 : err = rtm_to_fib_config(net, skb, nlh, &cfg, extack);
843 [ # # ]: 0 : if (err < 0)
844 : 0 : goto errout;
845 : :
846 [ # # # # ]: 0 : if (cfg.fc_nh_id && !nexthop_find_by_id(net, cfg.fc_nh_id)) {
847 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
848 : 0 : err = -EINVAL;
849 : 0 : goto errout;
850 : : }
851 : :
852 [ # # ]: 0 : tb = fib_get_table(net, cfg.fc_table);
853 [ # # ]: 0 : if (!tb) {
854 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "FIB table does not exist");
855 : 0 : err = -ESRCH;
856 : 0 : goto errout;
857 : : }
858 : :
859 : 0 : err = fib_table_delete(net, tb, &cfg, extack);
860 : 0 : errout:
861 : 0 : return err;
862 : : }
863 : :
864 : 0 : static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
865 : : struct netlink_ext_ack *extack)
866 : : {
867 : 0 : struct net *net = sock_net(skb->sk);
868 : 0 : struct fib_config cfg;
869 : 0 : struct fib_table *tb;
870 : 0 : int err;
871 : :
872 : 0 : err = rtm_to_fib_config(net, skb, nlh, &cfg, extack);
873 [ # # ]: 0 : if (err < 0)
874 : 0 : goto errout;
875 : :
876 : 0 : tb = fib_new_table(net, cfg.fc_table);
877 [ # # ]: 0 : if (!tb) {
878 : 0 : err = -ENOBUFS;
879 : 0 : goto errout;
880 : : }
881 : :
882 : 0 : err = fib_table_insert(net, tb, &cfg, extack);
883 [ # # # # ]: 0 : if (!err && cfg.fc_type == RTN_LOCAL)
884 : 0 : net->ipv4.fib_has_custom_local_routes = true;
885 : 0 : errout:
886 : 0 : return err;
887 : : }
888 : :
889 : 0 : int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
890 : : struct fib_dump_filter *filter,
891 : : struct netlink_callback *cb)
892 : : {
893 : 0 : struct netlink_ext_ack *extack = cb->extack;
894 : 0 : struct nlattr *tb[RTA_MAX + 1];
895 : 0 : struct rtmsg *rtm;
896 : 0 : int err, i;
897 : :
898 [ # # # # ]: 0 : ASSERT_RTNL();
899 : :
900 [ # # ]: 0 : if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) {
901 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid header for FIB dump request");
902 : 0 : return -EINVAL;
903 : : }
904 : :
905 [ # # ]: 0 : rtm = nlmsg_data(nlh);
906 [ # # # # ]: 0 : if (rtm->rtm_dst_len || rtm->rtm_src_len || rtm->rtm_tos ||
907 [ # # ]: 0 : rtm->rtm_scope) {
908 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid values in header for FIB dump request");
909 : 0 : return -EINVAL;
910 : : }
911 : :
912 [ # # ]: 0 : if (rtm->rtm_flags & ~(RTM_F_CLONED | RTM_F_PREFIX)) {
913 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Invalid flags for FIB dump request");
914 : 0 : return -EINVAL;
915 : : }
916 [ # # ]: 0 : if (rtm->rtm_flags & RTM_F_CLONED)
917 : 0 : filter->dump_routes = false;
918 : : else
919 : 0 : filter->dump_exceptions = false;
920 : :
921 : 0 : filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC);
922 : 0 : filter->flags = rtm->rtm_flags;
923 : 0 : filter->protocol = rtm->rtm_protocol;
924 : 0 : filter->rt_type = rtm->rtm_type;
925 : 0 : filter->table_id = rtm->rtm_table;
926 : :
927 : 0 : err = nlmsg_parse_deprecated_strict(nlh, sizeof(*rtm), tb, RTA_MAX,
928 : : rtm_ipv4_policy, extack);
929 [ # # ]: 0 : if (err < 0)
930 : : return err;
931 : :
932 [ # # ]: 0 : for (i = 0; i <= RTA_MAX; ++i) {
933 : 0 : int ifindex;
934 : :
935 [ # # ]: 0 : if (!tb[i])
936 : 0 : continue;
937 : :
938 [ # # # ]: 0 : switch (i) {
939 : 0 : case RTA_TABLE:
940 : 0 : filter->table_id = nla_get_u32(tb[i]);
941 : 0 : break;
942 : 0 : case RTA_OIF:
943 : 0 : ifindex = nla_get_u32(tb[i]);
944 : 0 : filter->dev = __dev_get_by_index(net, ifindex);
945 [ # # ]: 0 : if (!filter->dev)
946 : : return -ENODEV;
947 : : break;
948 : 0 : default:
949 [ # # ]: 0 : NL_SET_ERR_MSG(extack, "Unsupported attribute in dump request");
950 : : return -EINVAL;
951 : : }
952 : : }
953 : :
954 [ # # ]: 0 : if (filter->flags || filter->protocol || filter->rt_type ||
955 [ # # # # ]: 0 : filter->table_id || filter->dev) {
956 : 0 : filter->filter_set = 1;
957 : 0 : cb->answer_flags = NLM_F_DUMP_FILTERED;
958 : : }
959 : :
960 : : return 0;
961 : : }
962 : : EXPORT_SYMBOL_GPL(ip_valid_fib_dump_req);
963 : :
964 : 0 : static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
965 : : {
966 : 0 : struct fib_dump_filter filter = { .dump_routes = true,
967 : : .dump_exceptions = true };
968 : 0 : const struct nlmsghdr *nlh = cb->nlh;
969 [ # # ]: 0 : struct net *net = sock_net(skb->sk);
970 : 0 : unsigned int h, s_h;
971 : 0 : unsigned int e = 0, s_e;
972 : 0 : struct fib_table *tb;
973 : 0 : struct hlist_head *head;
974 : 0 : int dumped = 0, err;
975 : :
976 [ # # ]: 0 : if (cb->strict_check) {
977 : 0 : err = ip_valid_fib_dump_req(net, nlh, &filter, cb);
978 [ # # ]: 0 : if (err < 0)
979 : : return err;
980 [ # # ]: 0 : } else if (nlmsg_len(nlh) >= sizeof(struct rtmsg)) {
981 : 0 : struct rtmsg *rtm = nlmsg_data(nlh);
982 : :
983 : 0 : filter.flags = rtm->rtm_flags & (RTM_F_PREFIX | RTM_F_CLONED);
984 : : }
985 : :
986 : : /* ipv4 does not use prefix flag */
987 [ # # ]: 0 : if (filter.flags & RTM_F_PREFIX)
988 : 0 : return skb->len;
989 : :
990 [ # # ]: 0 : if (filter.table_id) {
991 : 0 : tb = fib_get_table(net, filter.table_id);
992 [ # # ]: 0 : if (!tb) {
993 [ # # ]: 0 : if (filter.dump_all_families)
994 : 0 : return skb->len;
995 : :
996 [ # # ]: 0 : NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist");
997 : 0 : return -ENOENT;
998 : : }
999 : :
1000 : 0 : rcu_read_lock();
1001 : 0 : err = fib_table_dump(tb, skb, cb, &filter);
1002 : 0 : rcu_read_unlock();
1003 [ # # ]: 0 : return skb->len ? : err;
1004 : : }
1005 : :
1006 : 0 : s_h = cb->args[0];
1007 : 0 : s_e = cb->args[1];
1008 : :
1009 : 0 : rcu_read_lock();
1010 : :
1011 [ # # ]: 0 : for (h = s_h; h < FIB_TABLE_HASHSZ; h++, s_e = 0) {
1012 : 0 : e = 0;
1013 : 0 : head = &net->ipv4.fib_table_hash[h];
1014 [ # # # # ]: 0 : hlist_for_each_entry_rcu(tb, head, tb_hlist) {
1015 [ # # ]: 0 : if (e < s_e)
1016 : 0 : goto next;
1017 [ # # ]: 0 : if (dumped)
1018 : 0 : memset(&cb->args[2], 0, sizeof(cb->args) -
1019 : : 2 * sizeof(cb->args[0]));
1020 : 0 : err = fib_table_dump(tb, skb, cb, &filter);
1021 [ # # ]: 0 : if (err < 0) {
1022 [ # # ]: 0 : if (likely(skb->len))
1023 : 0 : goto out;
1024 : :
1025 : 0 : goto out_err;
1026 : : }
1027 : : dumped = 1;
1028 : 0 : next:
1029 [ # # ]: 0 : e++;
1030 : : }
1031 : : }
1032 : 0 : out:
1033 : 0 : err = skb->len;
1034 : 0 : out_err:
1035 : 0 : rcu_read_unlock();
1036 : :
1037 : 0 : cb->args[1] = e;
1038 : 0 : cb->args[0] = h;
1039 : :
1040 : 0 : return err;
1041 : : }
1042 : :
1043 : : /* Prepare and feed intra-kernel routing request.
1044 : : * Really, it should be netlink message, but :-( netlink
1045 : : * can be not configured, so that we feed it directly
1046 : : * to fib engine. It is legal, because all events occur
1047 : : * only when netlink is already locked.
1048 : : */
1049 : : static void fib_magic(int cmd, int type, __be32 dst, int dst_len,
1050 : : struct in_ifaddr *ifa, u32 rt_priority)
1051 : : {
1052 : : struct net *net = dev_net(ifa->ifa_dev->dev);
1053 : : u32 tb_id = l3mdev_fib_table(ifa->ifa_dev->dev);
1054 : : struct fib_table *tb;
1055 : : struct fib_config cfg = {
1056 : : .fc_protocol = RTPROT_KERNEL,
1057 : : .fc_type = type,
1058 : : .fc_dst = dst,
1059 : : .fc_dst_len = dst_len,
1060 : : .fc_priority = rt_priority,
1061 : : .fc_prefsrc = ifa->ifa_local,
1062 : : .fc_oif = ifa->ifa_dev->dev->ifindex,
1063 : : .fc_nlflags = NLM_F_CREATE | NLM_F_APPEND,
1064 : : .fc_nlinfo = {
1065 : : .nl_net = net,
1066 : : },
1067 : : };
1068 : :
1069 : : if (!tb_id)
1070 : : tb_id = (type == RTN_UNICAST) ? RT_TABLE_MAIN : RT_TABLE_LOCAL;
1071 : :
1072 : : tb = fib_new_table(net, tb_id);
1073 : : if (!tb)
1074 : : return;
1075 : :
1076 : : cfg.fc_table = tb->tb_id;
1077 : :
1078 : : if (type != RTN_LOCAL)
1079 : : cfg.fc_scope = RT_SCOPE_LINK;
1080 : : else
1081 : : cfg.fc_scope = RT_SCOPE_HOST;
1082 : :
1083 : : if (cmd == RTM_NEWROUTE)
1084 : : fib_table_insert(net, tb, &cfg, NULL);
1085 : : else
1086 : : fib_table_delete(net, tb, &cfg, NULL);
1087 : : }
1088 : :
1089 : 22 : void fib_add_ifaddr(struct in_ifaddr *ifa)
1090 : : {
1091 : 22 : struct in_device *in_dev = ifa->ifa_dev;
1092 : 22 : struct net_device *dev = in_dev->dev;
1093 : 22 : struct in_ifaddr *prim = ifa;
1094 : 22 : __be32 mask = ifa->ifa_mask;
1095 : 22 : __be32 addr = ifa->ifa_local;
1096 : 22 : __be32 prefix = ifa->ifa_address & mask;
1097 : :
1098 [ - + ]: 22 : if (ifa->ifa_flags & IFA_F_SECONDARY) {
1099 : 0 : prim = inet_ifa_byprefix(in_dev, prefix, mask);
1100 [ # # ]: 0 : if (!prim) {
1101 : 0 : pr_warn("%s: bug: prim == NULL\n", __func__);
1102 : 0 : return;
1103 : : }
1104 : : }
1105 : :
1106 : 22 : fib_magic(RTM_NEWROUTE, RTN_LOCAL, addr, 32, prim, 0);
1107 : :
1108 [ + + ]: 22 : if (!(dev->flags & IFF_UP))
1109 : : return;
1110 : :
1111 : : /* Add broadcast address, if it is explicitly assigned. */
1112 [ - + ]: 11 : if (ifa->ifa_broadcast && ifa->ifa_broadcast != htonl(0xFFFFFFFF))
1113 : 0 : fib_magic(RTM_NEWROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32,
1114 : : prim, 0);
1115 : :
1116 [ + - + - : 11 : if (!ipv4_is_zeronet(prefix) && !(ifa->ifa_flags & IFA_F_SECONDARY) &&
- + ]
1117 [ # # ]: 0 : (prefix != addr || ifa->ifa_prefixlen < 32)) {
1118 [ + - ]: 11 : if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE))
1119 : 11 : fib_magic(RTM_NEWROUTE,
1120 : 11 : dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
1121 [ - + ]: 11 : prefix, ifa->ifa_prefixlen, prim,
1122 : : ifa->ifa_rt_priority);
1123 : :
1124 : : /* Add network specific broadcasts, when it takes a sense */
1125 [ + - ]: 11 : if (ifa->ifa_prefixlen < 31) {
1126 : 11 : fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix, 32,
1127 : : prim, 0);
1128 : 11 : fib_magic(RTM_NEWROUTE, RTN_BROADCAST, prefix | ~mask,
1129 : : 32, prim, 0);
1130 : : }
1131 : : }
1132 : : }
1133 : :
1134 : 0 : void fib_modify_prefix_metric(struct in_ifaddr *ifa, u32 new_metric)
1135 : : {
1136 : 0 : __be32 prefix = ifa->ifa_address & ifa->ifa_mask;
1137 : 0 : struct in_device *in_dev = ifa->ifa_dev;
1138 : 0 : struct net_device *dev = in_dev->dev;
1139 : :
1140 [ # # ]: 0 : if (!(dev->flags & IFF_UP) ||
1141 [ # # # # ]: 0 : ifa->ifa_flags & (IFA_F_SECONDARY | IFA_F_NOPREFIXROUTE) ||
1142 : 0 : ipv4_is_zeronet(prefix) ||
1143 [ # # # # ]: 0 : (prefix == ifa->ifa_local && ifa->ifa_prefixlen == 32))
1144 : : return;
1145 : :
1146 : : /* add the new */
1147 : 0 : fib_magic(RTM_NEWROUTE,
1148 : 0 : dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
1149 [ # # ]: 0 : prefix, ifa->ifa_prefixlen, ifa, new_metric);
1150 : :
1151 : : /* delete the old */
1152 : 0 : fib_magic(RTM_DELROUTE,
1153 : 0 : dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
1154 [ # # ]: 0 : prefix, ifa->ifa_prefixlen, ifa, ifa->ifa_rt_priority);
1155 : : }
1156 : :
1157 : : /* Delete primary or secondary address.
1158 : : * Optionally, on secondary address promotion consider the addresses
1159 : : * from subnet iprim as deleted, even if they are in device list.
1160 : : * In this case the secondary ifa can be in device list.
1161 : : */
1162 : 0 : void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim)
1163 : : {
1164 : 0 : struct in_device *in_dev = ifa->ifa_dev;
1165 : 0 : struct net_device *dev = in_dev->dev;
1166 : 0 : struct in_ifaddr *ifa1;
1167 : 0 : struct in_ifaddr *prim = ifa, *prim1 = NULL;
1168 : 0 : __be32 brd = ifa->ifa_address | ~ifa->ifa_mask;
1169 : 0 : __be32 any = ifa->ifa_address & ifa->ifa_mask;
1170 : : #define LOCAL_OK 1
1171 : : #define BRD_OK 2
1172 : : #define BRD0_OK 4
1173 : : #define BRD1_OK 8
1174 : 0 : unsigned int ok = 0;
1175 : 0 : int subnet = 0; /* Primary network */
1176 : 0 : int gone = 1; /* Address is missing */
1177 : 0 : int same_prefsrc = 0; /* Another primary with same IP */
1178 : :
1179 [ # # ]: 0 : if (ifa->ifa_flags & IFA_F_SECONDARY) {
1180 : 0 : prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask);
1181 [ # # ]: 0 : if (!prim) {
1182 : : /* if the device has been deleted, we don't perform
1183 : : * address promotion
1184 : : */
1185 [ # # ]: 0 : if (!in_dev->dead)
1186 : 0 : pr_warn("%s: bug: prim == NULL\n", __func__);
1187 : 0 : return;
1188 : : }
1189 [ # # ]: 0 : if (iprim && iprim != prim) {
1190 : 0 : pr_warn("%s: bug: iprim != prim\n", __func__);
1191 : 0 : return;
1192 : : }
1193 [ # # ]: 0 : } else if (!ipv4_is_zeronet(any) &&
1194 [ # # # # ]: 0 : (any != ifa->ifa_local || ifa->ifa_prefixlen < 32)) {
1195 [ # # ]: 0 : if (!(ifa->ifa_flags & IFA_F_NOPREFIXROUTE))
1196 : 0 : fib_magic(RTM_DELROUTE,
1197 : 0 : dev->flags & IFF_LOOPBACK ? RTN_LOCAL : RTN_UNICAST,
1198 [ # # ]: 0 : any, ifa->ifa_prefixlen, prim, 0);
1199 : : subnet = 1;
1200 : : }
1201 : :
1202 [ # # ]: 0 : if (in_dev->dead)
1203 : 0 : goto no_promotions;
1204 : :
1205 : : /* Deletion is more complicated than add.
1206 : : * We should take care of not to delete too much :-)
1207 : : *
1208 : : * Scan address list to be sure that addresses are really gone.
1209 : : */
1210 : 0 : rcu_read_lock();
1211 [ # # ]: 0 : in_dev_for_each_ifa_rcu(ifa1, in_dev) {
1212 [ # # ]: 0 : if (ifa1 == ifa) {
1213 : : /* promotion, keep the IP */
1214 : 0 : gone = 0;
1215 : 0 : continue;
1216 : : }
1217 : : /* Ignore IFAs from our subnet */
1218 [ # # # # : 0 : if (iprim && ifa1->ifa_mask == iprim->ifa_mask &&
# # ]
1219 [ # # ]: 0 : inet_ifa_match(ifa1->ifa_address, iprim))
1220 : 0 : continue;
1221 : :
1222 : : /* Ignore ifa1 if it uses different primary IP (prefsrc) */
1223 [ # # ]: 0 : if (ifa1->ifa_flags & IFA_F_SECONDARY) {
1224 : : /* Another address from our subnet? */
1225 [ # # # # ]: 0 : if (ifa1->ifa_mask == prim->ifa_mask &&
1226 [ # # ]: 0 : inet_ifa_match(ifa1->ifa_address, prim))
1227 : : prim1 = prim;
1228 : : else {
1229 : : /* We reached the secondaries, so
1230 : : * same_prefsrc should be determined.
1231 : : */
1232 [ # # ]: 0 : if (!same_prefsrc)
1233 : 0 : continue;
1234 : : /* Search new prim1 if ifa1 is not
1235 : : * using the current prim1
1236 : : */
1237 [ # # ]: 0 : if (!prim1 ||
1238 [ # # # # ]: 0 : ifa1->ifa_mask != prim1->ifa_mask ||
1239 [ # # ]: 0 : !inet_ifa_match(ifa1->ifa_address, prim1))
1240 : 0 : prim1 = inet_ifa_byprefix(in_dev,
1241 : : ifa1->ifa_address,
1242 : : ifa1->ifa_mask);
1243 [ # # ]: 0 : if (!prim1)
1244 : 0 : continue;
1245 [ # # ]: 0 : if (prim1->ifa_local != prim->ifa_local)
1246 : 0 : continue;
1247 : : }
1248 : : } else {
1249 [ # # ]: 0 : if (prim->ifa_local != ifa1->ifa_local)
1250 : 0 : continue;
1251 : 0 : prim1 = ifa1;
1252 [ # # ]: 0 : if (prim != prim1)
1253 : 0 : same_prefsrc = 1;
1254 : : }
1255 [ # # ]: 0 : if (ifa->ifa_local == ifa1->ifa_local)
1256 : 0 : ok |= LOCAL_OK;
1257 [ # # ]: 0 : if (ifa->ifa_broadcast == ifa1->ifa_broadcast)
1258 : 0 : ok |= BRD_OK;
1259 [ # # ]: 0 : if (brd == ifa1->ifa_broadcast)
1260 : 0 : ok |= BRD1_OK;
1261 [ # # ]: 0 : if (any == ifa1->ifa_broadcast)
1262 : 0 : ok |= BRD0_OK;
1263 : : /* primary has network specific broadcasts */
1264 [ # # # # ]: 0 : if (prim1 == ifa1 && ifa1->ifa_prefixlen < 31) {
1265 : 0 : __be32 brd1 = ifa1->ifa_address | ~ifa1->ifa_mask;
1266 : 0 : __be32 any1 = ifa1->ifa_address & ifa1->ifa_mask;
1267 : :
1268 [ # # ]: 0 : if (!ipv4_is_zeronet(any1)) {
1269 [ # # # # ]: 0 : if (ifa->ifa_broadcast == brd1 ||
1270 : : ifa->ifa_broadcast == any1)
1271 : 0 : ok |= BRD_OK;
1272 [ # # ]: 0 : if (brd == brd1 || brd == any1)
1273 : 0 : ok |= BRD1_OK;
1274 [ # # ]: 0 : if (any == brd1 || any == any1)
1275 : 0 : ok |= BRD0_OK;
1276 : : }
1277 : : }
1278 : : }
1279 : 0 : rcu_read_unlock();
1280 : :
1281 : 0 : no_promotions:
1282 [ # # ]: 0 : if (!(ok & BRD_OK))
1283 : 0 : fib_magic(RTM_DELROUTE, RTN_BROADCAST, ifa->ifa_broadcast, 32,
1284 : : prim, 0);
1285 [ # # # # ]: 0 : if (subnet && ifa->ifa_prefixlen < 31) {
1286 [ # # ]: 0 : if (!(ok & BRD1_OK))
1287 : 0 : fib_magic(RTM_DELROUTE, RTN_BROADCAST, brd, 32,
1288 : : prim, 0);
1289 [ # # ]: 0 : if (!(ok & BRD0_OK))
1290 : 0 : fib_magic(RTM_DELROUTE, RTN_BROADCAST, any, 32,
1291 : : prim, 0);
1292 : : }
1293 [ # # ]: 0 : if (!(ok & LOCAL_OK)) {
1294 : 0 : unsigned int addr_type;
1295 : :
1296 : 0 : fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 32, prim, 0);
1297 : :
1298 : : /* Check, that this local address finally disappeared. */
1299 : 0 : addr_type = inet_addr_type_dev_table(dev_net(dev), dev,
1300 : : ifa->ifa_local);
1301 [ # # ]: 0 : if (gone && addr_type != RTN_LOCAL) {
1302 : : /* And the last, but not the least thing.
1303 : : * We must flush stray FIB entries.
1304 : : *
1305 : : * First of all, we scan fib_info list searching
1306 : : * for stray nexthop entries, then ignite fib_flush.
1307 : : */
1308 [ # # ]: 0 : if (fib_sync_down_addr(dev, ifa->ifa_local))
1309 : 0 : fib_flush(dev_net(dev));
1310 : : }
1311 : : }
1312 : : #undef LOCAL_OK
1313 : : #undef BRD_OK
1314 : : #undef BRD0_OK
1315 : : #undef BRD1_OK
1316 : : }
1317 : :
1318 : : static void nl_fib_lookup(struct net *net, struct fib_result_nl *frn)
1319 : : {
1320 : :
1321 : : struct fib_result res;
1322 : : struct flowi4 fl4 = {
1323 : : .flowi4_mark = frn->fl_mark,
1324 : : .daddr = frn->fl_addr,
1325 : : .flowi4_tos = frn->fl_tos,
1326 : : .flowi4_scope = frn->fl_scope,
1327 : : };
1328 : : struct fib_table *tb;
1329 : :
1330 : : rcu_read_lock();
1331 : :
1332 : : tb = fib_get_table(net, frn->tb_id_in);
1333 : :
1334 : : frn->err = -ENOENT;
1335 : : if (tb) {
1336 : : local_bh_disable();
1337 : :
1338 : : frn->tb_id = tb->tb_id;
1339 : : frn->err = fib_table_lookup(tb, &fl4, &res, FIB_LOOKUP_NOREF);
1340 : :
1341 : : if (!frn->err) {
1342 : : frn->prefixlen = res.prefixlen;
1343 : : frn->nh_sel = res.nh_sel;
1344 : : frn->type = res.type;
1345 : : frn->scope = res.scope;
1346 : : }
1347 : : local_bh_enable();
1348 : : }
1349 : :
1350 : : rcu_read_unlock();
1351 : : }
1352 : :
1353 : 0 : static void nl_fib_input(struct sk_buff *skb)
1354 : : {
1355 : 0 : struct net *net;
1356 : 0 : struct fib_result_nl *frn;
1357 : 0 : struct nlmsghdr *nlh;
1358 : 0 : u32 portid;
1359 : :
1360 [ # # ]: 0 : net = sock_net(skb->sk);
1361 [ # # ]: 0 : nlh = nlmsg_hdr(skb);
1362 [ # # ]: 0 : if (skb->len < nlmsg_total_size(sizeof(*frn)) ||
1363 [ # # # # ]: 0 : skb->len < nlh->nlmsg_len ||
1364 : : nlmsg_len(nlh) < sizeof(*frn))
1365 : : return;
1366 : :
1367 : 0 : skb = netlink_skb_clone(skb, GFP_KERNEL);
1368 [ # # ]: 0 : if (!skb)
1369 : : return;
1370 : 0 : nlh = nlmsg_hdr(skb);
1371 : :
1372 : 0 : frn = (struct fib_result_nl *) nlmsg_data(nlh);
1373 : 0 : nl_fib_lookup(net, frn);
1374 : :
1375 : 0 : portid = NETLINK_CB(skb).portid; /* netlink portid */
1376 : 0 : NETLINK_CB(skb).portid = 0; /* from kernel */
1377 : 0 : NETLINK_CB(skb).dst_group = 0; /* unicast */
1378 : 0 : netlink_unicast(net->ipv4.fibnl, skb, portid, MSG_DONTWAIT);
1379 : : }
1380 : :
1381 : 11 : static int __net_init nl_fib_lookup_init(struct net *net)
1382 : : {
1383 : 11 : struct sock *sk;
1384 : 11 : struct netlink_kernel_cfg cfg = {
1385 : : .input = nl_fib_input,
1386 : : };
1387 : :
1388 : 11 : sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg);
1389 [ + - ]: 11 : if (!sk)
1390 : : return -EAFNOSUPPORT;
1391 : 11 : net->ipv4.fibnl = sk;
1392 : 11 : return 0;
1393 : : }
1394 : :
1395 : 0 : static void nl_fib_lookup_exit(struct net *net)
1396 : : {
1397 : 0 : netlink_kernel_release(net->ipv4.fibnl);
1398 : 0 : net->ipv4.fibnl = NULL;
1399 : 0 : }
1400 : :
1401 : 0 : static void fib_disable_ip(struct net_device *dev, unsigned long event,
1402 : : bool force)
1403 : : {
1404 [ # # ]: 0 : if (fib_sync_down_dev(dev, event, force))
1405 : 0 : fib_flush(dev_net(dev));
1406 : : else
1407 : 0 : rt_cache_flush(dev_net(dev));
1408 : 0 : arp_ifdown(dev);
1409 : 0 : }
1410 : :
1411 : 11 : static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
1412 : : {
1413 : 11 : struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
1414 : 11 : struct net_device *dev = ifa->ifa_dev->dev;
1415 [ + - - ]: 11 : struct net *net = dev_net(dev);
1416 : :
1417 [ + - - ]: 11 : switch (event) {
1418 : 11 : case NETDEV_UP:
1419 : 11 : fib_add_ifaddr(ifa);
1420 : : #ifdef CONFIG_IP_ROUTE_MULTIPATH
1421 : 11 : fib_sync_up(dev, RTNH_F_DEAD);
1422 : : #endif
1423 : 11 : atomic_inc(&net->ipv4.dev_addr_genid);
1424 : 11 : rt_cache_flush(dev_net(dev));
1425 : 11 : break;
1426 : 0 : case NETDEV_DOWN:
1427 : 0 : fib_del_ifaddr(ifa, NULL);
1428 : 0 : atomic_inc(&net->ipv4.dev_addr_genid);
1429 [ # # ]: 0 : if (!ifa->ifa_dev->ifa_list) {
1430 : : /* Last address was deleted from this interface.
1431 : : * Disable IP.
1432 : : */
1433 : 0 : fib_disable_ip(dev, event, true);
1434 : : } else {
1435 : 0 : rt_cache_flush(dev_net(dev));
1436 : : }
1437 : : break;
1438 : : }
1439 : 11 : return NOTIFY_DONE;
1440 : : }
1441 : :
1442 : 55 : static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
1443 : : {
1444 [ - + ]: 55 : struct net_device *dev = netdev_notifier_info_to_dev(ptr);
1445 : 55 : struct netdev_notifier_changeupper_info *upper_info = ptr;
1446 : 55 : struct netdev_notifier_info_ext *info_ext = ptr;
1447 : 55 : struct in_device *in_dev;
1448 [ - + ]: 55 : struct net *net = dev_net(dev);
1449 : 55 : struct in_ifaddr *ifa;
1450 : 55 : unsigned int flags;
1451 : :
1452 [ - + ]: 55 : if (event == NETDEV_UNREGISTER) {
1453 : 0 : fib_disable_ip(dev, event, true);
1454 : 0 : rt_flush_dev(dev);
1455 : 0 : return NOTIFY_DONE;
1456 : : }
1457 : :
1458 [ + + ]: 55 : in_dev = __in_dev_get_rtnl(dev);
1459 [ + + ]: 55 : if (!in_dev)
1460 : : return NOTIFY_DONE;
1461 : :
1462 [ + - - - : 44 : switch (event) {
- + ]
1463 : 11 : case NETDEV_UP:
1464 [ + + ]: 22 : in_dev_for_each_ifa_rtnl(ifa, in_dev) {
1465 : 11 : fib_add_ifaddr(ifa);
1466 : : }
1467 : : #ifdef CONFIG_IP_ROUTE_MULTIPATH
1468 : 11 : fib_sync_up(dev, RTNH_F_DEAD);
1469 : : #endif
1470 : 11 : atomic_inc(&net->ipv4.dev_addr_genid);
1471 : 11 : rt_cache_flush(net);
1472 : 11 : break;
1473 : 0 : case NETDEV_DOWN:
1474 : 0 : fib_disable_ip(dev, event, false);
1475 : 0 : break;
1476 : 0 : case NETDEV_CHANGE:
1477 : 0 : flags = dev_get_flags(dev);
1478 [ # # ]: 0 : if (flags & (IFF_RUNNING | IFF_LOWER_UP))
1479 : 0 : fib_sync_up(dev, RTNH_F_LINKDOWN);
1480 : : else
1481 : 0 : fib_sync_down_dev(dev, event, false);
1482 : 0 : rt_cache_flush(net);
1483 : 0 : break;
1484 : 0 : case NETDEV_CHANGEMTU:
1485 : 0 : fib_sync_mtu(dev, info_ext->ext.mtu);
1486 : 0 : rt_cache_flush(net);
1487 : 0 : break;
1488 : 0 : case NETDEV_CHANGEUPPER:
1489 : 0 : upper_info = ptr;
1490 : : /* flush all routes if dev is linked to or unlinked from
1491 : : * an L3 master device (e.g., VRF)
1492 : : */
1493 [ # # # # ]: 0 : if (upper_info->upper_dev &&
1494 [ # # ]: 0 : netif_is_l3_master(upper_info->upper_dev))
1495 : 0 : fib_disable_ip(dev, NETDEV_DOWN, true);
1496 : : break;
1497 : : }
1498 : : return NOTIFY_DONE;
1499 : : }
1500 : :
1501 : : static struct notifier_block fib_inetaddr_notifier = {
1502 : : .notifier_call = fib_inetaddr_event,
1503 : : };
1504 : :
1505 : : static struct notifier_block fib_netdev_notifier = {
1506 : : .notifier_call = fib_netdev_event,
1507 : : };
1508 : :
1509 : 11 : static int __net_init ip_fib_net_init(struct net *net)
1510 : : {
1511 : 11 : int err;
1512 : 11 : size_t size = sizeof(struct hlist_head) * FIB_TABLE_HASHSZ;
1513 : :
1514 : 11 : err = fib4_notifier_init(net);
1515 [ + - ]: 11 : if (err)
1516 : : return err;
1517 : :
1518 : : /* Avoid false sharing : Use at least a full cache line */
1519 : 11 : size = max_t(size_t, size, L1_CACHE_BYTES);
1520 : :
1521 : 11 : net->ipv4.fib_table_hash = kzalloc(size, GFP_KERNEL);
1522 [ - + ]: 11 : if (!net->ipv4.fib_table_hash) {
1523 : 0 : err = -ENOMEM;
1524 : 0 : goto err_table_hash_alloc;
1525 : : }
1526 : :
1527 : 11 : err = fib4_rules_init(net);
1528 [ - + ]: 11 : if (err < 0)
1529 : 0 : goto err_rules_init;
1530 : : return 0;
1531 : :
1532 : : err_rules_init:
1533 : 0 : kfree(net->ipv4.fib_table_hash);
1534 : 0 : err_table_hash_alloc:
1535 : 0 : fib4_notifier_exit(net);
1536 : 0 : return err;
1537 : : }
1538 : :
1539 : 0 : static void ip_fib_net_exit(struct net *net)
1540 : : {
1541 : 0 : int i;
1542 : :
1543 : 0 : rtnl_lock();
1544 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
1545 : 0 : RCU_INIT_POINTER(net->ipv4.fib_main, NULL);
1546 : 0 : RCU_INIT_POINTER(net->ipv4.fib_default, NULL);
1547 : : #endif
1548 : : /* Destroy the tables in reverse order to guarantee that the
1549 : : * local table, ID 255, is destroyed before the main table, ID
1550 : : * 254. This is necessary as the local table may contain
1551 : : * references to data contained in the main table.
1552 : : */
1553 [ # # ]: 0 : for (i = FIB_TABLE_HASHSZ - 1; i >= 0; i--) {
1554 : 0 : struct hlist_head *head = &net->ipv4.fib_table_hash[i];
1555 : 0 : struct hlist_node *tmp;
1556 : 0 : struct fib_table *tb;
1557 : :
1558 [ # # # # : 0 : hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
# # ]
1559 [ # # ]: 0 : hlist_del(&tb->tb_hlist);
1560 : 0 : fib_table_flush(net, tb, true);
1561 : 0 : fib_free_table(tb);
1562 : : }
1563 : : }
1564 : :
1565 : : #ifdef CONFIG_IP_MULTIPLE_TABLES
1566 : 0 : fib4_rules_exit(net);
1567 : : #endif
1568 : 0 : rtnl_unlock();
1569 : 0 : kfree(net->ipv4.fib_table_hash);
1570 : 0 : fib4_notifier_exit(net);
1571 : 0 : }
1572 : :
1573 : 11 : static int __net_init fib_net_init(struct net *net)
1574 : : {
1575 : 11 : int error;
1576 : :
1577 : : #ifdef CONFIG_IP_ROUTE_CLASSID
1578 : : net->ipv4.fib_num_tclassid_users = 0;
1579 : : #endif
1580 : 11 : error = ip_fib_net_init(net);
1581 [ - + ]: 11 : if (error < 0)
1582 : 0 : goto out;
1583 : 11 : error = nl_fib_lookup_init(net);
1584 [ - + ]: 11 : if (error < 0)
1585 : 0 : goto out_nlfl;
1586 : 11 : error = fib_proc_init(net);
1587 [ - + ]: 11 : if (error < 0)
1588 : 0 : goto out_proc;
1589 : 11 : out:
1590 : 11 : return error;
1591 : :
1592 : : out_proc:
1593 : 0 : nl_fib_lookup_exit(net);
1594 : 0 : out_nlfl:
1595 : 0 : ip_fib_net_exit(net);
1596 : 0 : goto out;
1597 : : }
1598 : :
1599 : 0 : static void __net_exit fib_net_exit(struct net *net)
1600 : : {
1601 : 0 : fib_proc_exit(net);
1602 : 0 : nl_fib_lookup_exit(net);
1603 : 0 : ip_fib_net_exit(net);
1604 : 0 : }
1605 : :
1606 : : static struct pernet_operations fib_net_ops = {
1607 : : .init = fib_net_init,
1608 : : .exit = fib_net_exit,
1609 : : };
1610 : :
1611 : 11 : void __init ip_fib_init(void)
1612 : : {
1613 : 11 : fib_trie_init();
1614 : :
1615 : 11 : register_pernet_subsys(&fib_net_ops);
1616 : :
1617 : 11 : register_netdevice_notifier(&fib_netdev_notifier);
1618 : 11 : register_inetaddr_notifier(&fib_inetaddr_notifier);
1619 : :
1620 : 11 : rtnl_register(PF_INET, RTM_NEWROUTE, inet_rtm_newroute, NULL, 0);
1621 : 11 : rtnl_register(PF_INET, RTM_DELROUTE, inet_rtm_delroute, NULL, 0);
1622 : 11 : rtnl_register(PF_INET, RTM_GETROUTE, NULL, inet_dump_fib, 0);
1623 : 11 : }
|