Branch data Line data Source code
1 : : /*
2 : : * Linux INET6 implementation
3 : : * FIB front-end.
4 : : *
5 : : * Authors:
6 : : * Pedro Roque <roque@di.fc.ul.pt>
7 : : *
8 : : * This program is free software; you can redistribute it and/or
9 : : * modify it under the terms of the GNU General Public License
10 : : * as published by the Free Software Foundation; either version
11 : : * 2 of the License, or (at your option) any later version.
12 : : */
13 : :
14 : : /* Changes:
15 : : *
16 : : * YOSHIFUJI Hideaki @USAGI
17 : : * reworked default router selection.
18 : : * - respect outgoing interface
19 : : * - select from (probably) reachable routers (i.e.
20 : : * routers in REACHABLE, STALE, DELAY or PROBE states).
21 : : * - always select the same router if it is (probably)
22 : : * reachable. otherwise, round-robin the list.
23 : : * Ville Nuorvala
24 : : * Fixed routing subtrees.
25 : : */
26 : :
27 : : #define pr_fmt(fmt) "IPv6: " fmt
28 : :
29 : : #include <linux/capability.h>
30 : : #include <linux/errno.h>
31 : : #include <linux/export.h>
32 : : #include <linux/types.h>
33 : : #include <linux/times.h>
34 : : #include <linux/socket.h>
35 : : #include <linux/sockios.h>
36 : : #include <linux/net.h>
37 : : #include <linux/route.h>
38 : : #include <linux/netdevice.h>
39 : : #include <linux/in6.h>
40 : : #include <linux/mroute6.h>
41 : : #include <linux/init.h>
42 : : #include <linux/if_arp.h>
43 : : #include <linux/proc_fs.h>
44 : : #include <linux/seq_file.h>
45 : : #include <linux/nsproxy.h>
46 : : #include <linux/slab.h>
47 : : #include <net/net_namespace.h>
48 : : #include <net/snmp.h>
49 : : #include <net/ipv6.h>
50 : : #include <net/ip6_fib.h>
51 : : #include <net/ip6_route.h>
52 : : #include <net/ndisc.h>
53 : : #include <net/addrconf.h>
54 : : #include <net/tcp.h>
55 : : #include <linux/rtnetlink.h>
56 : : #include <net/dst.h>
57 : : #include <net/xfrm.h>
58 : : #include <net/netevent.h>
59 : : #include <net/netlink.h>
60 : : #include <net/nexthop.h>
61 : :
62 : : #include <asm/uaccess.h>
63 : :
64 : : #ifdef CONFIG_SYSCTL
65 : : #include <linux/sysctl.h>
66 : : #endif
67 : :
68 : : enum rt6_nud_state {
69 : : RT6_NUD_FAIL_HARD = -2,
70 : : RT6_NUD_FAIL_SOFT = -1,
71 : : RT6_NUD_SUCCEED = 1
72 : : };
73 : :
74 : : static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
75 : : const struct in6_addr *dest);
76 : : static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
77 : : static unsigned int ip6_default_advmss(const struct dst_entry *dst);
78 : : static unsigned int ip6_mtu(const struct dst_entry *dst);
79 : : static struct dst_entry *ip6_negative_advice(struct dst_entry *);
80 : : static void ip6_dst_destroy(struct dst_entry *);
81 : : static void ip6_dst_ifdown(struct dst_entry *,
82 : : struct net_device *dev, int how);
83 : : static int ip6_dst_gc(struct dst_ops *ops);
84 : :
85 : : static int ip6_pkt_discard(struct sk_buff *skb);
86 : : static int ip6_pkt_discard_out(struct sk_buff *skb);
87 : : static int ip6_pkt_prohibit(struct sk_buff *skb);
88 : : static int ip6_pkt_prohibit_out(struct sk_buff *skb);
89 : : static void ip6_link_failure(struct sk_buff *skb);
90 : : static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
91 : : struct sk_buff *skb, u32 mtu);
92 : : static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
93 : : struct sk_buff *skb);
94 : : static int rt6_score_route(struct rt6_info *rt, int oif, int strict);
95 : :
96 : : #ifdef CONFIG_IPV6_ROUTE_INFO
97 : : static struct rt6_info *rt6_add_route_info(struct net *net,
98 : : const struct in6_addr *prefix, int prefixlen,
99 : : const struct in6_addr *gwaddr, int ifindex,
100 : : unsigned int pref);
101 : : static struct rt6_info *rt6_get_route_info(struct net *net,
102 : : const struct in6_addr *prefix, int prefixlen,
103 : : const struct in6_addr *gwaddr, int ifindex);
104 : : #endif
105 : :
106 : 0 : static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
107 : : {
108 : : struct rt6_info *rt = (struct rt6_info *) dst;
109 : 105 : struct inet_peer *peer;
110 : : u32 *p = NULL;
111 : :
112 [ + ]: 105 : if (!(rt->dst.flags & DST_HOST))
113 : : return NULL;
114 : :
115 : : peer = rt6_get_peer_create(rt);
116 [ + - ]: 105 : if (peer) {
117 : 105 : u32 *old_p = __DST_METRICS_PTR(old);
118 : : unsigned long prev, new;
119 : :
120 : 105 : p = peer->metrics;
121 [ + + ]: 105 : if (inet_metrics_new(peer))
122 : 5 : memcpy(p, old_p, sizeof(u32) * RTAX_MAX);
123 : :
124 : 105 : new = (unsigned long) p;
125 : 105 : prev = cmpxchg(&dst->_metrics, old, new);
126 : :
127 [ - + ]: 105 : if (prev != old) {
128 : 0 : p = __DST_METRICS_PTR(prev);
129 [ # # ]: 0 : if (prev & DST_METRICS_READ_ONLY)
130 : : p = NULL;
131 : : }
132 : : }
133 : 105 : return p;
134 : : }
135 : :
136 : : static inline const void *choose_neigh_daddr(struct rt6_info *rt,
137 : : struct sk_buff *skb,
138 : : const void *daddr)
139 : : {
140 : 0 : struct in6_addr *p = &rt->rt6i_gateway;
141 : :
142 [ # # ]: 0 : if (!ipv6_addr_any(p))
143 : : return (const void *) p;
144 [ # # ]: 0 : else if (skb)
145 : 0 : return &ipv6_hdr(skb)->daddr;
146 : : return daddr;
147 : : }
148 : :
149 : 0 : static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst,
150 : : struct sk_buff *skb,
151 : : const void *daddr)
152 : : {
153 : : struct rt6_info *rt = (struct rt6_info *) dst;
154 : : struct neighbour *n;
155 : :
156 : : daddr = choose_neigh_daddr(rt, skb, daddr);
157 : 0 : n = __ipv6_neigh_lookup(dst->dev, daddr);
158 [ # # ]: 0 : if (n)
159 : : return n;
160 : 0 : return neigh_create(&nd_tbl, daddr, dst->dev);
161 : : }
162 : :
163 : : static struct dst_ops ip6_dst_ops_template = {
164 : : .family = AF_INET6,
165 : : .protocol = cpu_to_be16(ETH_P_IPV6),
166 : : .gc = ip6_dst_gc,
167 : : .gc_thresh = 1024,
168 : : .check = ip6_dst_check,
169 : : .default_advmss = ip6_default_advmss,
170 : : .mtu = ip6_mtu,
171 : : .cow_metrics = ipv6_cow_metrics,
172 : : .destroy = ip6_dst_destroy,
173 : : .ifdown = ip6_dst_ifdown,
174 : : .negative_advice = ip6_negative_advice,
175 : : .link_failure = ip6_link_failure,
176 : : .update_pmtu = ip6_rt_update_pmtu,
177 : : .redirect = rt6_do_redirect,
178 : : .local_out = __ip6_local_out,
179 : : .neigh_lookup = ip6_neigh_lookup,
180 : : };
181 : :
182 : 0 : static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst)
183 : : {
184 : : unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
185 : :
186 [ # # ]: 0 : return mtu ? : dst->dev->mtu;
187 : : }
188 : :
189 : 0 : static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
190 : : struct sk_buff *skb, u32 mtu)
191 : : {
192 : 0 : }
193 : :
194 : 0 : static void ip6_rt_blackhole_redirect(struct dst_entry *dst, struct sock *sk,
195 : : struct sk_buff *skb)
196 : : {
197 : 0 : }
198 : :
199 : 0 : static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
200 : : unsigned long old)
201 : : {
202 : 0 : return NULL;
203 : : }
204 : :
205 : : static struct dst_ops ip6_dst_blackhole_ops = {
206 : : .family = AF_INET6,
207 : : .protocol = cpu_to_be16(ETH_P_IPV6),
208 : : .destroy = ip6_dst_destroy,
209 : : .check = ip6_dst_check,
210 : : .mtu = ip6_blackhole_mtu,
211 : : .default_advmss = ip6_default_advmss,
212 : : .update_pmtu = ip6_rt_blackhole_update_pmtu,
213 : : .redirect = ip6_rt_blackhole_redirect,
214 : : .cow_metrics = ip6_rt_blackhole_cow_metrics,
215 : : .neigh_lookup = ip6_neigh_lookup,
216 : : };
217 : :
218 : : static const u32 ip6_template_metrics[RTAX_MAX] = {
219 : : [RTAX_HOPLIMIT - 1] = 0,
220 : : };
221 : :
222 : : static const struct rt6_info ip6_null_entry_template = {
223 : : .dst = {
224 : : .__refcnt = ATOMIC_INIT(1),
225 : : .__use = 1,
226 : : .obsolete = DST_OBSOLETE_FORCE_CHK,
227 : : .error = -ENETUNREACH,
228 : : .input = ip6_pkt_discard,
229 : : .output = ip6_pkt_discard_out,
230 : : },
231 : : .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
232 : : .rt6i_protocol = RTPROT_KERNEL,
233 : : .rt6i_metric = ~(u32) 0,
234 : : .rt6i_ref = ATOMIC_INIT(1),
235 : : };
236 : :
237 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
238 : :
239 : : static const struct rt6_info ip6_prohibit_entry_template = {
240 : : .dst = {
241 : : .__refcnt = ATOMIC_INIT(1),
242 : : .__use = 1,
243 : : .obsolete = DST_OBSOLETE_FORCE_CHK,
244 : : .error = -EACCES,
245 : : .input = ip6_pkt_prohibit,
246 : : .output = ip6_pkt_prohibit_out,
247 : : },
248 : : .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
249 : : .rt6i_protocol = RTPROT_KERNEL,
250 : : .rt6i_metric = ~(u32) 0,
251 : : .rt6i_ref = ATOMIC_INIT(1),
252 : : };
253 : :
254 : : static const struct rt6_info ip6_blk_hole_entry_template = {
255 : : .dst = {
256 : : .__refcnt = ATOMIC_INIT(1),
257 : : .__use = 1,
258 : : .obsolete = DST_OBSOLETE_FORCE_CHK,
259 : : .error = -EINVAL,
260 : : .input = dst_discard,
261 : : .output = dst_discard,
262 : : },
263 : : .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP),
264 : : .rt6i_protocol = RTPROT_KERNEL,
265 : : .rt6i_metric = ~(u32) 0,
266 : : .rt6i_ref = ATOMIC_INIT(1),
267 : : };
268 : :
269 : : #endif
270 : :
271 : : /* allocate dst with ip6_dst_ops */
272 : : static inline struct rt6_info *ip6_dst_alloc(struct net *net,
273 : : struct net_device *dev,
274 : : int flags,
275 : : struct fib6_table *table)
276 : : {
277 : 105 : struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
278 : : 0, DST_OBSOLETE_FORCE_CHK, flags);
279 : :
280 [ # # + - : 105 : if (rt) {
# # # # ]
281 : : struct dst_entry *dst = &rt->dst;
282 : :
283 : 105 : memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
284 [ + - ][ # # ]: 105 : rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
285 : 105 : rt->rt6i_genid = rt_genid_ipv6(net);
286 : 105 : INIT_LIST_HEAD(&rt->rt6i_siblings);
287 : : }
288 : : return rt;
289 : : }
290 : :
291 : 0 : static void ip6_dst_destroy(struct dst_entry *dst)
292 : : {
293 : 105 : struct rt6_info *rt = (struct rt6_info *)dst;
294 : 105 : struct inet6_dev *idev = rt->rt6i_idev;
295 : 105 : struct dst_entry *from = dst->from;
296 : :
297 [ - + ]: 105 : if (!(rt->dst.flags & DST_HOST))
298 : : dst_destroy_metrics_generic(dst);
299 : :
300 [ + - ]: 105 : if (idev) {
301 : 105 : rt->rt6i_idev = NULL;
302 : : in6_dev_put(idev);
303 : : }
304 : :
305 : 105 : dst->from = NULL;
306 : 105 : dst_release(from);
307 : :
308 [ + - ]: 105 : if (rt6_has_peer(rt)) {
309 : : struct inet_peer *peer = rt6_peer_ptr(rt);
310 : 105 : inet_putpeer(peer);
311 : : }
312 : 105 : }
313 : :
314 : 0 : void rt6_bind_peer(struct rt6_info *rt, int create)
315 : : {
316 : : struct inet_peer_base *base;
317 : : struct inet_peer *peer;
318 : :
319 : 105 : base = inetpeer_base_ptr(rt->_rt6i_peer);
320 [ + - ]: 105 : if (!base)
321 : 0 : return;
322 : :
323 : : peer = inet_getpeer_v6(base, &rt->rt6i_dst.addr, create);
324 [ + - ]: 105 : if (peer) {
325 [ - + ]: 105 : if (!rt6_set_peer(rt, peer))
326 : 0 : inet_putpeer(peer);
327 : : }
328 : : }
329 : :
330 : 0 : static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
331 : : int how)
332 : : {
333 : : struct rt6_info *rt = (struct rt6_info *)dst;
334 : 0 : struct inet6_dev *idev = rt->rt6i_idev;
335 : 0 : struct net_device *loopback_dev =
336 : : dev_net(dev)->loopback_dev;
337 : :
338 [ # # ]: 0 : if (dev != loopback_dev) {
339 [ # # ][ # # ]: 0 : if (idev && idev->dev == dev) {
340 : : struct inet6_dev *loopback_idev =
341 : : in6_dev_get(loopback_dev);
342 [ # # ]: 0 : if (loopback_idev) {
343 : 0 : rt->rt6i_idev = loopback_idev;
344 : : in6_dev_put(idev);
345 : : }
346 : : }
347 : : }
348 : 0 : }
349 : :
350 : : static bool rt6_check_expired(const struct rt6_info *rt)
351 : : {
352 [ # # ][ # # ]: 134 : if (rt->rt6i_flags & RTF_EXPIRES) {
[ # # ][ - + ]
353 [ # # ][ # # ]: 0 : if (time_after(jiffies, rt->dst.expires))
[ # # ][ # # ]
354 : : return true;
355 [ # # ][ # # ]: 134 : } else if (rt->dst.from) {
[ # # ][ + + ]
356 : : return rt6_check_expired((struct rt6_info *) rt->dst.from);
357 : : }
358 : : return false;
359 : : }
360 : :
361 : : static bool rt6_need_strict(const struct in6_addr *daddr)
362 : : {
363 : 115 : return ipv6_addr_type(daddr) &
364 : : (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK);
365 : : }
366 : :
367 : : /* Multipath route selection:
368 : : * Hash based function using packet header and flowlabel.
369 : : * Adapted from fib_info_hashfn()
370 : : */
371 : 0 : static int rt6_info_hash_nhsfn(unsigned int candidate_count,
372 : : const struct flowi6 *fl6)
373 : : {
374 : 0 : unsigned int val = fl6->flowi6_proto;
375 : :
376 : 0 : val ^= ipv6_addr_hash(&fl6->daddr);
377 : 0 : val ^= ipv6_addr_hash(&fl6->saddr);
378 : :
379 : : /* Work only if this not encapsulated */
380 [ # # # ]: 0 : switch (fl6->flowi6_proto) {
381 : : case IPPROTO_UDP:
382 : : case IPPROTO_TCP:
383 : : case IPPROTO_SCTP:
384 : 0 : val ^= (__force u16)fl6->fl6_sport;
385 : 0 : val ^= (__force u16)fl6->fl6_dport;
386 : 0 : break;
387 : :
388 : : case IPPROTO_ICMPV6:
389 : 0 : val ^= (__force u16)fl6->fl6_icmp_type;
390 : 0 : val ^= (__force u16)fl6->fl6_icmp_code;
391 : 0 : break;
392 : : }
393 : : /* RFC6438 recommands to use flowlabel */
394 : 0 : val ^= (__force u32)fl6->flowlabel;
395 : :
396 : : /* Perhaps, we need to tune, this function? */
397 : 0 : val = val ^ (val >> 7) ^ (val >> 12);
398 : 0 : return val % candidate_count;
399 : : }
400 : :
401 : 0 : static struct rt6_info *rt6_multipath_select(struct rt6_info *match,
402 : : struct flowi6 *fl6, int oif,
403 : : int strict)
404 : : {
405 : : struct rt6_info *sibling, *next_sibling;
406 : : int route_choosen;
407 : :
408 : 0 : route_choosen = rt6_info_hash_nhsfn(match->rt6i_nsiblings + 1, fl6);
409 : : /* Don't change the route, if route_choosen == 0
410 : : * (siblings does not include ourself)
411 : : */
412 [ # # ]: 0 : if (route_choosen)
413 [ # # ]: 0 : list_for_each_entry_safe(sibling, next_sibling,
414 : : &match->rt6i_siblings, rt6i_siblings) {
415 : 0 : route_choosen--;
416 [ # # ]: 0 : if (route_choosen == 0) {
417 [ # # ]: 0 : if (rt6_score_route(sibling, oif, strict) < 0)
418 : : break;
419 : : match = sibling;
420 : 0 : break;
421 : : }
422 : : }
423 : 0 : return match;
424 : : }
425 : :
426 : : /*
427 : : * Route lookup. Any table->tb6_lock is implied.
428 : : */
429 : :
430 : : static inline struct rt6_info *rt6_device_match(struct net *net,
431 : : struct rt6_info *rt,
432 : : const struct in6_addr *saddr,
433 : : int oif,
434 : : int flags)
435 : : {
436 : : struct rt6_info *local = NULL;
437 : : struct rt6_info *sprt;
438 : :
439 [ # # ][ # # ]: 0 : if (!oif && ipv6_addr_any(saddr))
440 : : goto out;
441 : :
442 [ # # ]: 0 : for (sprt = rt; sprt; sprt = sprt->dst.rt6_next) {
443 : 0 : struct net_device *dev = sprt->dst.dev;
444 : :
445 [ # # ]: 0 : if (oif) {
446 [ # # ]: 0 : if (dev->ifindex == oif)
447 : : return sprt;
448 [ # # ]: 0 : if (dev->flags & IFF_LOOPBACK) {
449 [ # # ][ # # ]: 0 : if (!sprt->rt6i_idev ||
450 : 0 : sprt->rt6i_idev->dev->ifindex != oif) {
451 [ # # ][ # # ]: 0 : if (flags & RT6_LOOKUP_F_IFACE && oif)
452 : 0 : continue;
453 [ # # ][ # # ]: 0 : if (local && (!oif ||
[ # # ]
454 : 0 : local->rt6i_idev->dev->ifindex == oif))
455 : 0 : continue;
456 : : }
457 : : local = sprt;
458 : : }
459 : : } else {
460 [ # # ]: 0 : if (ipv6_chk_addr(net, saddr, dev,
461 : : flags & RT6_LOOKUP_F_IFACE))
462 : : return sprt;
463 : : }
464 : : }
465 : :
466 [ # # ]: 0 : if (oif) {
467 [ # # ]: 0 : if (local)
468 : : return local;
469 : :
470 [ # # ]: 0 : if (flags & RT6_LOOKUP_F_IFACE)
471 : 0 : return net->ipv6.ip6_null_entry;
472 : : }
473 : : out:
474 : : return rt;
475 : : }
476 : :
477 : : #ifdef CONFIG_IPV6_ROUTER_PREF
478 : : struct __rt6_probe_work {
479 : : struct work_struct work;
480 : : struct in6_addr target;
481 : : struct net_device *dev;
482 : : };
483 : :
484 : : static void rt6_probe_deferred(struct work_struct *w)
485 : : {
486 : : struct in6_addr mcaddr;
487 : : struct __rt6_probe_work *work =
488 : : container_of(w, struct __rt6_probe_work, work);
489 : :
490 : : addrconf_addr_solict_mult(&work->target, &mcaddr);
491 : : ndisc_send_ns(work->dev, NULL, &work->target, &mcaddr, NULL);
492 : : dev_put(work->dev);
493 : : kfree(w);
494 : : }
495 : :
496 : : static void rt6_probe(struct rt6_info *rt)
497 : : {
498 : : struct neighbour *neigh;
499 : : /*
500 : : * Okay, this does not seem to be appropriate
501 : : * for now, however, we need to check if it
502 : : * is really so; aka Router Reachability Probing.
503 : : *
504 : : * Router Reachability Probe MUST be rate-limited
505 : : * to no more than one per minute.
506 : : */
507 : : if (!rt || !(rt->rt6i_flags & RTF_GATEWAY))
508 : : return;
509 : : rcu_read_lock_bh();
510 : : neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
511 : : if (neigh) {
512 : : write_lock(&neigh->lock);
513 : : if (neigh->nud_state & NUD_VALID)
514 : : goto out;
515 : : }
516 : :
517 : : if (!neigh ||
518 : : time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
519 : : struct __rt6_probe_work *work;
520 : :
521 : : work = kmalloc(sizeof(*work), GFP_ATOMIC);
522 : :
523 : : if (neigh && work)
524 : : neigh->updated = jiffies;
525 : :
526 : : if (neigh)
527 : : write_unlock(&neigh->lock);
528 : :
529 : : if (work) {
530 : : INIT_WORK(&work->work, rt6_probe_deferred);
531 : : work->target = rt->rt6i_gateway;
532 : : dev_hold(rt->dst.dev);
533 : : work->dev = rt->dst.dev;
534 : : schedule_work(&work->work);
535 : : }
536 : : } else {
537 : : out:
538 : : write_unlock(&neigh->lock);
539 : : }
540 : : rcu_read_unlock_bh();
541 : : }
542 : : #else
543 : : static inline void rt6_probe(struct rt6_info *rt)
544 : : {
545 : : }
546 : : #endif
547 : :
548 : : /*
549 : : * Default Router Selection (RFC 2461 6.3.6)
550 : : */
551 : : static inline int rt6_check_dev(struct rt6_info *rt, int oif)
552 : : {
553 : : struct net_device *dev = rt->dst.dev;
554 [ + + ][ - + ]: 122 : if (!oif || dev->ifindex == oif)
555 : : return 2;
556 [ # # ][ # # ]: 0 : if ((dev->flags & IFF_LOOPBACK) &&
557 [ # # ]: 0 : rt->rt6i_idev && rt->rt6i_idev->dev->ifindex == oif)
558 : : return 1;
559 : : return 0;
560 : : }
561 : :
562 : : static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt)
563 : : {
564 : : struct neighbour *neigh;
565 : : enum rt6_nud_state ret = RT6_NUD_FAIL_HARD;
566 : :
567 [ - + ]: 115 : if (rt->rt6i_flags & RTF_NONEXTHOP ||
568 : : !(rt->rt6i_flags & RTF_GATEWAY))
569 : : return RT6_NUD_SUCCEED;
570 : :
571 : : rcu_read_lock_bh();
572 : 0 : neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway);
573 [ # # ]: 0 : if (neigh) {
574 : 0 : read_lock(&neigh->lock);
575 [ # # ]: 0 : if (neigh->nud_state & NUD_VALID)
576 : : ret = RT6_NUD_SUCCEED;
577 : : #ifdef CONFIG_IPV6_ROUTER_PREF
578 : : else if (!(neigh->nud_state & NUD_FAILED))
579 : : ret = RT6_NUD_SUCCEED;
580 : : #endif
581 : : read_unlock(&neigh->lock);
582 : : } else {
583 : : ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ?
584 : : RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT;
585 : : }
586 : : rcu_read_unlock_bh();
587 : :
588 : : return ret;
589 : : }
590 : :
591 : 0 : static int rt6_score_route(struct rt6_info *rt, int oif,
592 : : int strict)
593 : : {
594 : : int m;
595 : :
596 : : m = rt6_check_dev(rt, oif);
597 [ - + ][ # # ]: 122 : if (!m && (strict & RT6_LOOKUP_F_IFACE))
598 : : return RT6_NUD_FAIL_HARD;
599 : : #ifdef CONFIG_IPV6_ROUTER_PREF
600 : : m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2;
601 : : #endif
602 [ + + ]: 122 : if (strict & RT6_LOOKUP_F_REACHABLE) {
603 : : int n = rt6_check_neigh(rt);
604 [ + - ]: 115 : if (n < 0)
605 : : return n;
606 : : }
607 : 122 : return m;
608 : : }
609 : :
610 : 122 : static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict,
611 : : int *mpri, struct rt6_info *match,
612 : : bool *do_rr)
613 : : {
614 : : int m;
615 : : bool match_do_rr = false;
616 : :
617 [ + - ]: 122 : if (rt6_check_expired(rt))
618 : : goto out;
619 : :
620 : 122 : m = rt6_score_route(rt, oif, strict);
621 [ + - ]: 122 : if (m == RT6_NUD_FAIL_SOFT) {
622 : : match_do_rr = true;
623 : : m = 0; /* lowest valid score */
624 [ + ]: 122 : } else if (m < 0) {
625 : : goto out;
626 : : }
627 : :
628 : : if (strict & RT6_LOOKUP_F_REACHABLE)
629 : : rt6_probe(rt);
630 : :
631 [ + - ]: 244 : if (m > *mpri) {
632 : 122 : *do_rr = match_do_rr;
633 : 122 : *mpri = m;
634 : : match = rt;
635 : : }
636 : : out:
637 : 0 : return match;
638 : : }
639 : :
640 : 122 : static struct rt6_info *find_rr_leaf(struct fib6_node *fn,
641 : : struct rt6_info *rr_head,
642 : : u32 metric, int oif, int strict,
643 : : bool *do_rr)
644 : : {
645 : : struct rt6_info *rt, *match;
646 : 122 : int mpri = -1;
647 : :
648 : : match = NULL;
649 [ + + ][ + - ]: 244 : for (rt = rr_head; rt && rt->rt6i_metric == metric;
650 : 122 : rt = rt->dst.rt6_next)
651 : 122 : match = find_match(rt, oif, strict, &mpri, match, do_rr);
652 [ - + ][ # # ]: 122 : for (rt = fn->leaf; rt && rt != rr_head && rt->rt6i_metric == metric;
653 : 0 : rt = rt->dst.rt6_next)
654 : 0 : match = find_match(rt, oif, strict, &mpri, match, do_rr);
655 : :
656 : 0 : return match;
657 : : }
658 : :
659 : 0 : static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict)
660 : : {
661 : : struct rt6_info *match, *rt0;
662 : : struct net *net;
663 : 122 : bool do_rr = false;
664 : :
665 : 122 : rt0 = fn->rr_ptr;
666 [ + + ]: 122 : if (!rt0)
667 : 6 : fn->rr_ptr = rt0 = fn->leaf;
668 : :
669 : 122 : match = find_rr_leaf(fn, rt0, rt0->rt6i_metric, oif, strict,
670 : : &do_rr);
671 : :
672 [ - + ]: 122 : if (do_rr) {
673 : 0 : struct rt6_info *next = rt0->dst.rt6_next;
674 : :
675 : : /* no entries matched; do round-robin */
676 [ # # ][ # # ]: 0 : if (!next || next->rt6i_metric != rt0->rt6i_metric)
677 : 0 : next = fn->leaf;
678 : :
679 [ # # ]: 0 : if (next != rt0)
680 : 0 : fn->rr_ptr = next;
681 : : }
682 : :
683 : : net = dev_net(rt0->dst.dev);
684 [ - - ]: 122 : return match ? match : net->ipv6.ip6_null_entry;
685 : : }
686 : :
687 : : #ifdef CONFIG_IPV6_ROUTE_INFO
688 : : int rt6_route_rcv(struct net_device *dev, u8 *opt, int len,
689 : : const struct in6_addr *gwaddr)
690 : : {
691 : : struct net *net = dev_net(dev);
692 : : struct route_info *rinfo = (struct route_info *) opt;
693 : : struct in6_addr prefix_buf, *prefix;
694 : : unsigned int pref;
695 : : unsigned long lifetime;
696 : : struct rt6_info *rt;
697 : :
698 : : if (len < sizeof(struct route_info)) {
699 : : return -EINVAL;
700 : : }
701 : :
702 : : /* Sanity check for prefix_len and length */
703 : : if (rinfo->length > 3) {
704 : : return -EINVAL;
705 : : } else if (rinfo->prefix_len > 128) {
706 : : return -EINVAL;
707 : : } else if (rinfo->prefix_len > 64) {
708 : : if (rinfo->length < 2) {
709 : : return -EINVAL;
710 : : }
711 : : } else if (rinfo->prefix_len > 0) {
712 : : if (rinfo->length < 1) {
713 : : return -EINVAL;
714 : : }
715 : : }
716 : :
717 : : pref = rinfo->route_pref;
718 : : if (pref == ICMPV6_ROUTER_PREF_INVALID)
719 : : return -EINVAL;
720 : :
721 : : lifetime = addrconf_timeout_fixup(ntohl(rinfo->lifetime), HZ);
722 : :
723 : : if (rinfo->length == 3)
724 : : prefix = (struct in6_addr *)rinfo->prefix;
725 : : else {
726 : : /* this function is safe */
727 : : ipv6_addr_prefix(&prefix_buf,
728 : : (struct in6_addr *)rinfo->prefix,
729 : : rinfo->prefix_len);
730 : : prefix = &prefix_buf;
731 : : }
732 : :
733 : : if (rinfo->prefix_len == 0)
734 : : rt = rt6_get_dflt_router(gwaddr, dev);
735 : : else
736 : : rt = rt6_get_route_info(net, prefix, rinfo->prefix_len,
737 : : gwaddr, dev->ifindex);
738 : :
739 : : if (rt && !lifetime) {
740 : : ip6_del_rt(rt);
741 : : rt = NULL;
742 : : }
743 : :
744 : : if (!rt && lifetime)
745 : : rt = rt6_add_route_info(net, prefix, rinfo->prefix_len, gwaddr, dev->ifindex,
746 : : pref);
747 : : else if (rt)
748 : : rt->rt6i_flags = RTF_ROUTEINFO |
749 : : (rt->rt6i_flags & ~RTF_PREF_MASK) | RTF_PREF(pref);
750 : :
751 : : if (rt) {
752 : : if (!addrconf_finite_timeout(lifetime))
753 : : rt6_clean_expires(rt);
754 : : else
755 : : rt6_set_expires(rt, jiffies + HZ * lifetime);
756 : :
757 : : ip6_rt_put(rt);
758 : : }
759 : : return 0;
760 : : }
761 : : #endif
762 : :
763 : : #define BACKTRACK(__net, saddr) \
764 : : do { \
765 : : if (rt == __net->ipv6.ip6_null_entry) { \
766 : : struct fib6_node *pn; \
767 : : while (1) { \
768 : : if (fn->fn_flags & RTN_TL_ROOT) \
769 : : goto out; \
770 : : pn = fn->parent; \
771 : : if (FIB6_SUBTREE(pn) && FIB6_SUBTREE(pn) != fn) \
772 : : fn = fib6_lookup(FIB6_SUBTREE(pn), NULL, saddr); \
773 : : else \
774 : : fn = pn; \
775 : : if (fn->fn_flags & RTN_RTINFO) \
776 : : goto restart; \
777 : : } \
778 : : } \
779 : : } while (0)
780 : :
781 : 0 : static struct rt6_info *ip6_pol_route_lookup(struct net *net,
782 : : struct fib6_table *table,
783 : : struct flowi6 *fl6, int flags)
784 : : {
785 : : struct fib6_node *fn;
786 : : struct rt6_info *rt;
787 : :
788 : 0 : read_lock_bh(&table->tb6_lock);
789 : 0 : fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
790 : : restart:
791 : 0 : rt = fn->leaf;
792 : 0 : rt = rt6_device_match(net, rt, &fl6->saddr, fl6->flowi6_oif, flags);
793 [ # # ][ # # ]: 0 : if (rt->rt6i_nsiblings && fl6->flowi6_oif == 0)
794 : 0 : rt = rt6_multipath_select(rt, fl6, fl6->flowi6_oif, flags);
795 [ # # ][ # # ]: 0 : BACKTRACK(net, &fl6->saddr);
[ # # ]
796 : : out:
797 : 0 : dst_use(&rt->dst, jiffies);
798 : 0 : read_unlock_bh(&table->tb6_lock);
799 : 0 : return rt;
800 : :
801 : : }
802 : :
803 : 0 : struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6,
804 : : int flags)
805 : : {
806 : 0 : return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup);
807 : : }
808 : : EXPORT_SYMBOL_GPL(ip6_route_lookup);
809 : :
810 : 0 : struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,
811 : : const struct in6_addr *saddr, int oif, int strict)
812 : : {
813 : 0 : struct flowi6 fl6 = {
814 : : .flowi6_oif = oif,
815 : : .daddr = *daddr,
816 : : };
817 : : struct dst_entry *dst;
818 : 0 : int flags = strict ? RT6_LOOKUP_F_IFACE : 0;
819 : :
820 [ # # ]: 0 : if (saddr) {
821 : 0 : memcpy(&fl6.saddr, saddr, sizeof(*saddr));
822 : 0 : flags |= RT6_LOOKUP_F_HAS_SADDR;
823 : : }
824 : :
825 : 0 : dst = fib6_rule_lookup(net, &fl6, flags, ip6_pol_route_lookup);
826 [ # # ]: 0 : if (dst->error == 0)
827 : : return (struct rt6_info *) dst;
828 : :
829 : 0 : dst_release(dst);
830 : :
831 : 0 : return NULL;
832 : : }
833 : :
834 : : EXPORT_SYMBOL(rt6_lookup);
835 : :
836 : : /* ip6_ins_rt is called with FREE table->tb6_lock.
837 : : It takes new route entry, the addition fails by any reason the
838 : : route is freed. In any case, if caller does not hold it, it may
839 : : be destroyed.
840 : : */
841 : :
842 : 0 : static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info)
843 : : {
844 : : int err;
845 : : struct fib6_table *table;
846 : :
847 : 105 : table = rt->rt6i_table;
848 : 105 : write_lock_bh(&table->tb6_lock);
849 : 105 : err = fib6_add(&table->tb6_root, rt, info);
850 : 105 : write_unlock_bh(&table->tb6_lock);
851 : :
852 : 105 : return err;
853 : : }
854 : :
855 : 0 : int ip6_ins_rt(struct rt6_info *rt)
856 : : {
857 : 105 : struct nl_info info = {
858 : : .nl_net = dev_net(rt->dst.dev),
859 : : };
860 : 105 : return __ip6_ins_rt(rt, &info);
861 : : }
862 : :
863 : 105 : static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort,
864 : : const struct in6_addr *daddr,
865 : : const struct in6_addr *saddr)
866 : : {
867 : : struct rt6_info *rt;
868 : :
869 : : /*
870 : : * Clone the route.
871 : : */
872 : :
873 : 105 : rt = ip6_rt_copy(ort, daddr);
874 : :
875 [ + ]: 105 : if (rt) {
876 [ + - ][ - + ]: 210 : if (ort->rt6i_dst.plen != 128 &&
877 : : ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
878 : 0 : rt->rt6i_flags |= RTF_ANYCAST;
879 : :
880 : 105 : rt->rt6i_flags |= RTF_CACHE;
881 : :
882 : : #ifdef CONFIG_IPV6_SUBTREES
883 : : if (rt->rt6i_src.plen && saddr) {
884 : : rt->rt6i_src.addr = *saddr;
885 : : rt->rt6i_src.plen = 128;
886 : : }
887 : : #endif
888 : : }
889 : :
890 : 0 : return rt;
891 : : }
892 : :
893 : : static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
894 : : const struct in6_addr *daddr)
895 : : {
896 : 0 : struct rt6_info *rt = ip6_rt_copy(ort, daddr);
897 : :
898 [ # # ]: 0 : if (rt)
899 : 0 : rt->rt6i_flags |= RTF_CACHE;
900 : : return rt;
901 : : }
902 : :
903 : 115 : static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif,
904 : : struct flowi6 *fl6, int flags)
905 : : {
906 : : struct fib6_node *fn;
907 : : struct rt6_info *rt, *nrt;
908 : : int strict = 0;
909 : : int attempts = 3;
910 : : int err;
911 [ + - ]: 115 : int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE;
912 : :
913 : 115 : strict |= flags & RT6_LOOKUP_F_IFACE;
914 : :
915 : : relookup:
916 : 115 : read_lock_bh(&table->tb6_lock);
917 : :
918 : : restart_2:
919 : 122 : fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
920 : :
921 : : restart:
922 : 122 : rt = rt6_select(fn, oif, strict | reachable);
923 [ - + ]: 122 : if (rt->rt6i_nsiblings)
924 : 0 : rt = rt6_multipath_select(rt, fl6, oif, strict | reachable);
925 [ + + ][ - + ]: 237 : BACKTRACK(net, &fl6->saddr);
[ # # ]
926 [ + - ][ + + ]: 235 : if (rt == net->ipv6.ip6_null_entry ||
927 : 120 : rt->rt6i_flags & RTF_CACHE)
928 : : goto out;
929 : :
930 : : dst_hold(&rt->dst);
931 : 108 : read_unlock_bh(&table->tb6_lock);
932 : :
933 [ + + ]: 108 : if (!(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_GATEWAY)))
934 : 105 : nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
935 [ - + ]: 3 : else if (!(rt->dst.flags & DST_HOST))
936 : : nrt = rt6_alloc_clone(rt, &fl6->daddr);
937 : : else
938 : : goto out2;
939 : :
940 : : ip6_rt_put(rt);
941 [ - + ]: 105 : rt = nrt ? : net->ipv6.ip6_null_entry;
942 : :
943 : : dst_hold(&rt->dst);
944 [ + - ]: 105 : if (nrt) {
945 : 105 : err = ip6_ins_rt(nrt);
946 [ - + ]: 105 : if (!err)
947 : : goto out2;
948 : : }
949 : :
950 [ # # ]: 0 : if (--attempts <= 0)
951 : : goto out2;
952 : :
953 : : /*
954 : : * Race condition! In the gap, when table->tb6_lock was
955 : : * released someone could insert this route. Relookup.
956 : : */
957 : : ip6_rt_put(rt);
958 : : goto relookup;
959 : :
960 : : out:
961 [ + + ]: 14 : if (reachable) {
962 : : reachable = 0;
963 : : goto restart_2;
964 : : }
965 : : dst_hold(&rt->dst);
966 : 7 : read_unlock_bh(&table->tb6_lock);
967 : : out2:
968 : 115 : rt->dst.lastuse = jiffies;
969 : 115 : rt->dst.__use++;
970 : :
971 : 115 : return rt;
972 : : }
973 : :
974 : 0 : static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table,
975 : : struct flowi6 *fl6, int flags)
976 : : {
977 : 111 : return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags);
978 : : }
979 : :
980 : 111 : static struct dst_entry *ip6_route_input_lookup(struct net *net,
981 : : struct net_device *dev,
982 : : struct flowi6 *fl6, int flags)
983 : : {
984 [ + - ][ + - ]: 111 : if (rt6_need_strict(&fl6->daddr) && dev->type != ARPHRD_PIMREG)
985 : 111 : flags |= RT6_LOOKUP_F_IFACE;
986 : :
987 : 111 : return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_input);
988 : : }
989 : :
990 : 0 : void ip6_route_input(struct sk_buff *skb)
991 : : {
992 : : const struct ipv6hdr *iph = ipv6_hdr(skb);
993 : : struct net *net = dev_net(skb->dev);
994 : : int flags = RT6_LOOKUP_F_HAS_SADDR;
995 : 555 : struct flowi6 fl6 = {
996 : 111 : .flowi6_iif = skb->dev->ifindex,
997 : : .daddr = iph->daddr,
998 : : .saddr = iph->saddr,
999 : : .flowlabel = ip6_flowinfo(iph),
1000 : 111 : .flowi6_mark = skb->mark,
1001 : 111 : .flowi6_proto = iph->nexthdr,
1002 : : };
1003 : :
1004 : 111 : skb_dst_set(skb, ip6_route_input_lookup(net, skb->dev, &fl6, flags));
1005 : 111 : }
1006 : :
1007 : 0 : static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table,
1008 : : struct flowi6 *fl6, int flags)
1009 : : {
1010 : 4 : return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags);
1011 : : }
1012 : :
1013 : 0 : struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk,
1014 : : struct flowi6 *fl6)
1015 : : {
1016 : : int flags = 0;
1017 : :
1018 : 4 : fl6->flowi6_iif = LOOPBACK_IFINDEX;
1019 : :
1020 [ + - ]: 8 : if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
[ + - + + ]
1021 : : flags |= RT6_LOOKUP_F_IFACE;
1022 : :
1023 [ - + ]: 4 : if (!ipv6_addr_any(&fl6->saddr))
1024 : 0 : flags |= RT6_LOOKUP_F_HAS_SADDR;
1025 [ + - ]: 4 : else if (sk)
1026 : 4 : flags |= rt6_srcprefs2flags(inet6_sk(sk)->srcprefs);
1027 : :
1028 : 4 : return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_output);
1029 : : }
1030 : :
1031 : : EXPORT_SYMBOL(ip6_route_output);
1032 : :
1033 : 0 : struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig)
1034 : : {
1035 : : struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig;
1036 : : struct dst_entry *new = NULL;
1037 : :
1038 : 0 : rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, DST_OBSOLETE_NONE, 0);
1039 [ # # ]: 0 : if (rt) {
1040 : 0 : new = &rt->dst;
1041 : :
1042 : 0 : memset(new + 1, 0, sizeof(*rt) - sizeof(*new));
1043 : 0 : rt6_init_peer(rt, net->ipv6.peers);
1044 : :
1045 : 0 : new->__use = 1;
1046 : 0 : new->input = dst_discard;
1047 : 0 : new->output = dst_discard;
1048 : :
1049 [ # # ]: 0 : if (dst_metrics_read_only(&ort->dst))
1050 : 0 : new->_metrics = ort->dst._metrics;
1051 : : else
1052 : : dst_copy_metrics(new, &ort->dst);
1053 : 0 : rt->rt6i_idev = ort->rt6i_idev;
1054 [ # # ]: 0 : if (rt->rt6i_idev)
1055 : : in6_dev_hold(rt->rt6i_idev);
1056 : :
1057 : 0 : rt->rt6i_gateway = ort->rt6i_gateway;
1058 : 0 : rt->rt6i_flags = ort->rt6i_flags;
1059 : 0 : rt->rt6i_metric = 0;
1060 : :
1061 : 0 : memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
1062 : : #ifdef CONFIG_IPV6_SUBTREES
1063 : : memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
1064 : : #endif
1065 : :
1066 : : dst_free(new);
1067 : : }
1068 : :
1069 : 0 : dst_release(dst_orig);
1070 [ # # ]: 0 : return new ? new : ERR_PTR(-ENOMEM);
1071 : : }
1072 : :
1073 : : /*
1074 : : * Destination cache support functions
1075 : : */
1076 : :
1077 : 0 : static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
1078 : : {
1079 : : struct rt6_info *rt;
1080 : :
1081 : : rt = (struct rt6_info *) dst;
1082 : :
1083 : : /* All IPV6 dsts are created with ->obsolete set to the value
1084 : : * DST_OBSOLETE_FORCE_CHK which forces validation calls down
1085 : : * into this function always.
1086 : : */
1087 [ # # ]: 0 : if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev)))
1088 : : return NULL;
1089 : :
1090 [ # # ][ # # ]: 0 : if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie))
1091 : : return NULL;
1092 : :
1093 [ # # ]: 0 : if (rt6_check_expired(rt))
1094 : : return NULL;
1095 : :
1096 : 0 : return dst;
1097 : : }
1098 : :
1099 : 0 : static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
1100 : : {
1101 : : struct rt6_info *rt = (struct rt6_info *) dst;
1102 : :
1103 [ # # ]: 0 : if (rt) {
1104 [ # # ]: 0 : if (rt->rt6i_flags & RTF_CACHE) {
1105 [ # # ]: 0 : if (rt6_check_expired(rt)) {
1106 : 0 : ip6_del_rt(rt);
1107 : : dst = NULL;
1108 : : }
1109 : : } else {
1110 : 0 : dst_release(dst);
1111 : : dst = NULL;
1112 : : }
1113 : : }
1114 : 0 : return dst;
1115 : : }
1116 : :
1117 : 0 : static void ip6_link_failure(struct sk_buff *skb)
1118 : : {
1119 : : struct rt6_info *rt;
1120 : :
1121 : 0 : icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH, 0);
1122 : :
1123 : : rt = (struct rt6_info *) skb_dst(skb);
1124 [ # # ]: 0 : if (rt) {
1125 [ # # ]: 0 : if (rt->rt6i_flags & RTF_CACHE) {
1126 : : dst_hold(&rt->dst);
1127 [ # # ]: 0 : if (ip6_del_rt(rt))
1128 : 0 : dst_free(&rt->dst);
1129 [ # # ][ # # ]: 0 : } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) {
1130 : 0 : rt->rt6i_node->fn_sernum = -1;
1131 : : }
1132 : : }
1133 : 0 : }
1134 : :
1135 : 0 : static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
1136 : : struct sk_buff *skb, u32 mtu)
1137 : : {
1138 : : struct rt6_info *rt6 = (struct rt6_info*)dst;
1139 : :
1140 : : dst_confirm(dst);
1141 [ # # ][ # # ]: 0 : if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) {
1142 : : struct net *net = dev_net(dst->dev);
1143 : :
1144 : 0 : rt6->rt6i_flags |= RTF_MODIFIED;
1145 [ # # ]: 0 : if (mtu < IPV6_MIN_MTU) {
1146 : : u32 features = dst_metric(dst, RTAX_FEATURES);
1147 : : mtu = IPV6_MIN_MTU;
1148 : 0 : features |= RTAX_FEATURE_ALLFRAG;
1149 : : dst_metric_set(dst, RTAX_FEATURES, features);
1150 : : }
1151 : : dst_metric_set(dst, RTAX_MTU, mtu);
1152 : 0 : rt6_update_expires(rt6, net->ipv6.sysctl.ip6_rt_mtu_expires);
1153 : : }
1154 : 0 : }
1155 : :
1156 : 0 : void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
1157 : : int oif, u32 mark)
1158 : : {
1159 : 0 : const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
1160 : : struct dst_entry *dst;
1161 : : struct flowi6 fl6;
1162 : :
1163 : 0 : memset(&fl6, 0, sizeof(fl6));
1164 : 0 : fl6.flowi6_oif = oif;
1165 : 0 : fl6.flowi6_mark = mark;
1166 : 0 : fl6.daddr = iph->daddr;
1167 : 0 : fl6.saddr = iph->saddr;
1168 : 0 : fl6.flowlabel = ip6_flowinfo(iph);
1169 : :
1170 : 0 : dst = ip6_route_output(net, NULL, &fl6);
1171 [ # # ]: 0 : if (!dst->error)
1172 [ # # ]: 0 : ip6_rt_update_pmtu(dst, NULL, skb, ntohl(mtu));
1173 : 0 : dst_release(dst);
1174 : 0 : }
1175 : : EXPORT_SYMBOL_GPL(ip6_update_pmtu);
1176 : :
1177 : 0 : void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
1178 : : {
1179 : 0 : ip6_update_pmtu(skb, sock_net(sk), mtu,
1180 : : sk->sk_bound_dev_if, sk->sk_mark);
1181 : 0 : }
1182 : : EXPORT_SYMBOL_GPL(ip6_sk_update_pmtu);
1183 : :
1184 : : /* Handle redirects */
1185 : : struct ip6rd_flowi {
1186 : : struct flowi6 fl6;
1187 : : struct in6_addr gateway;
1188 : : };
1189 : :
1190 : 0 : static struct rt6_info *__ip6_route_redirect(struct net *net,
1191 : : struct fib6_table *table,
1192 : : struct flowi6 *fl6,
1193 : : int flags)
1194 : : {
1195 : : struct ip6rd_flowi *rdfl = (struct ip6rd_flowi *)fl6;
1196 : : struct rt6_info *rt;
1197 : : struct fib6_node *fn;
1198 : :
1199 : : /* Get the "current" route for this destination and
1200 : : * check if the redirect has come from approriate router.
1201 : : *
1202 : : * RFC 4861 specifies that redirects should only be
1203 : : * accepted if they come from the nexthop to the target.
1204 : : * Due to the way the routes are chosen, this notion
1205 : : * is a bit fuzzy and one might need to check all possible
1206 : : * routes.
1207 : : */
1208 : :
1209 : 0 : read_lock_bh(&table->tb6_lock);
1210 : 0 : fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
1211 : : restart:
1212 [ # # ]: 0 : for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
1213 [ # # ]: 0 : if (rt6_check_expired(rt))
1214 : 0 : continue;
1215 [ # # ]: 0 : if (rt->dst.error)
1216 : : break;
1217 [ # # ]: 0 : if (!(rt->rt6i_flags & RTF_GATEWAY))
1218 : 0 : continue;
1219 [ # # ]: 0 : if (fl6->flowi6_oif != rt->dst.dev->ifindex)
1220 : 0 : continue;
1221 [ # # ]: 0 : if (!ipv6_addr_equal(&rdfl->gateway, &rt->rt6i_gateway))
1222 : 0 : continue;
1223 : : break;
1224 : : }
1225 : :
1226 [ # # ]: 0 : if (!rt)
1227 : 0 : rt = net->ipv6.ip6_null_entry;
1228 [ # # ]: 0 : else if (rt->dst.error) {
1229 : 0 : rt = net->ipv6.ip6_null_entry;
1230 : 0 : goto out;
1231 : : }
1232 [ # # ][ # # ]: 0 : BACKTRACK(net, &fl6->saddr);
[ # # ]
1233 : : out:
1234 : : dst_hold(&rt->dst);
1235 : :
1236 : 0 : read_unlock_bh(&table->tb6_lock);
1237 : :
1238 : 0 : return rt;
1239 : : };
1240 : :
1241 : 0 : static struct dst_entry *ip6_route_redirect(struct net *net,
1242 : : const struct flowi6 *fl6,
1243 : : const struct in6_addr *gateway)
1244 : : {
1245 : : int flags = RT6_LOOKUP_F_HAS_SADDR;
1246 : : struct ip6rd_flowi rdfl;
1247 : :
1248 : 0 : rdfl.fl6 = *fl6;
1249 : 0 : rdfl.gateway = *gateway;
1250 : :
1251 : 0 : return fib6_rule_lookup(net, &rdfl.fl6,
1252 : : flags, __ip6_route_redirect);
1253 : : }
1254 : :
1255 : 0 : void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
1256 : : {
1257 : 0 : const struct ipv6hdr *iph = (struct ipv6hdr *) skb->data;
1258 : : struct dst_entry *dst;
1259 : : struct flowi6 fl6;
1260 : :
1261 : 0 : memset(&fl6, 0, sizeof(fl6));
1262 : 0 : fl6.flowi6_oif = oif;
1263 : 0 : fl6.flowi6_mark = mark;
1264 : 0 : fl6.daddr = iph->daddr;
1265 : 0 : fl6.saddr = iph->saddr;
1266 : 0 : fl6.flowlabel = ip6_flowinfo(iph);
1267 : :
1268 : 0 : dst = ip6_route_redirect(net, &fl6, &ipv6_hdr(skb)->saddr);
1269 : 0 : rt6_do_redirect(dst, NULL, skb);
1270 : 0 : dst_release(dst);
1271 : 0 : }
1272 : : EXPORT_SYMBOL_GPL(ip6_redirect);
1273 : :
1274 : 0 : void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif,
1275 : : u32 mark)
1276 : : {
1277 : : const struct ipv6hdr *iph = ipv6_hdr(skb);
1278 : : const struct rd_msg *msg = (struct rd_msg *)icmp6_hdr(skb);
1279 : : struct dst_entry *dst;
1280 : : struct flowi6 fl6;
1281 : :
1282 : 0 : memset(&fl6, 0, sizeof(fl6));
1283 : 0 : fl6.flowi6_oif = oif;
1284 : 0 : fl6.flowi6_mark = mark;
1285 : 0 : fl6.daddr = msg->dest;
1286 : 0 : fl6.saddr = iph->daddr;
1287 : :
1288 : 0 : dst = ip6_route_redirect(net, &fl6, &iph->saddr);
1289 : 0 : rt6_do_redirect(dst, NULL, skb);
1290 : 0 : dst_release(dst);
1291 : 0 : }
1292 : :
1293 : 0 : void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
1294 : : {
1295 : 0 : ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
1296 : 0 : }
1297 : : EXPORT_SYMBOL_GPL(ip6_sk_redirect);
1298 : :
1299 : 0 : static unsigned int ip6_default_advmss(const struct dst_entry *dst)
1300 : : {
1301 : : struct net_device *dev = dst->dev;
1302 : : unsigned int mtu = dst_mtu(dst);
1303 : : struct net *net = dev_net(dev);
1304 : :
1305 : 0 : mtu -= sizeof(struct ipv6hdr) + sizeof(struct tcphdr);
1306 : :
1307 [ # # ]: 0 : if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
1308 : : mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
1309 : :
1310 : : /*
1311 : : * Maximal non-jumbo IPv6 payload is IPV6_MAXPLEN and
1312 : : * corresponding MSS is IPV6_MAXPLEN - tcp_header_size.
1313 : : * IPV6_MAXPLEN is also valid and means: "any MSS,
1314 : : * rely only on pmtu discovery"
1315 : : */
1316 [ # # ]: 0 : if (mtu > IPV6_MAXPLEN - sizeof(struct tcphdr))
1317 : : mtu = IPV6_MAXPLEN;
1318 : 0 : return mtu;
1319 : : }
1320 : :
1321 : 0 : static unsigned int ip6_mtu(const struct dst_entry *dst)
1322 : : {
1323 : : struct inet6_dev *idev;
1324 : : unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
1325 : :
1326 [ # # ]: 0 : if (mtu)
1327 : : return mtu;
1328 : :
1329 : : mtu = IPV6_MIN_MTU;
1330 : :
1331 : : rcu_read_lock();
1332 : 0 : idev = __in6_dev_get(dst->dev);
1333 [ # # ]: 0 : if (idev)
1334 : 0 : mtu = idev->cnf.mtu6;
1335 : : rcu_read_unlock();
1336 : :
1337 : 0 : return mtu;
1338 : : }
1339 : :
1340 : : static struct dst_entry *icmp6_dst_gc_list;
1341 : : static DEFINE_SPINLOCK(icmp6_dst_lock);
1342 : :
1343 : 0 : struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1344 : : struct flowi6 *fl6)
1345 : : {
1346 : : struct dst_entry *dst;
1347 : : struct rt6_info *rt;
1348 : : struct inet6_dev *idev = in6_dev_get(dev);
1349 : : struct net *net = dev_net(dev);
1350 : :
1351 [ # # ]: 0 : if (unlikely(!idev))
1352 : : return ERR_PTR(-ENODEV);
1353 : :
1354 : : rt = ip6_dst_alloc(net, dev, 0, NULL);
1355 [ # # ]: 0 : if (unlikely(!rt)) {
1356 : : in6_dev_put(idev);
1357 : : dst = ERR_PTR(-ENOMEM);
1358 : : goto out;
1359 : : }
1360 : :
1361 : 0 : rt->dst.flags |= DST_HOST;
1362 : 0 : rt->dst.output = ip6_output;
1363 : 0 : atomic_set(&rt->dst.__refcnt, 1);
1364 : 0 : rt->rt6i_gateway = fl6->daddr;
1365 : 0 : rt->rt6i_dst.addr = fl6->daddr;
1366 : 0 : rt->rt6i_dst.plen = 128;
1367 : 0 : rt->rt6i_idev = idev;
1368 : 0 : dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0);
1369 : :
1370 : : spin_lock_bh(&icmp6_dst_lock);
1371 : 0 : rt->dst.next = icmp6_dst_gc_list;
1372 : 0 : icmp6_dst_gc_list = &rt->dst;
1373 : : spin_unlock_bh(&icmp6_dst_lock);
1374 : :
1375 : 0 : fib6_force_start_gc(net);
1376 : :
1377 : 0 : dst = xfrm_lookup(net, &rt->dst, flowi6_to_flowi(fl6), NULL, 0);
1378 : :
1379 : : out:
1380 : 0 : return dst;
1381 : : }
1382 : :
1383 : 0 : int icmp6_dst_gc(void)
1384 : : {
1385 : : struct dst_entry *dst, **pprev;
1386 : : int more = 0;
1387 : :
1388 : : spin_lock_bh(&icmp6_dst_lock);
1389 : : pprev = &icmp6_dst_gc_list;
1390 : :
1391 [ - + ]: 110 : while ((dst = *pprev) != NULL) {
1392 [ # # ]: 0 : if (!atomic_read(&dst->__refcnt)) {
1393 : 0 : *pprev = dst->next;
1394 : : dst_free(dst);
1395 : : } else {
1396 : 0 : pprev = &dst->next;
1397 : 0 : ++more;
1398 : : }
1399 : : }
1400 : :
1401 : : spin_unlock_bh(&icmp6_dst_lock);
1402 : :
1403 : 110 : return more;
1404 : : }
1405 : :
1406 : 0 : static void icmp6_clean_all(int (*func)(struct rt6_info *rt, void *arg),
1407 : : void *arg)
1408 : : {
1409 : : struct dst_entry *dst, **pprev;
1410 : :
1411 : : spin_lock_bh(&icmp6_dst_lock);
1412 : : pprev = &icmp6_dst_gc_list;
1413 [ # # ]: 0 : while ((dst = *pprev) != NULL) {
1414 : : struct rt6_info *rt = (struct rt6_info *) dst;
1415 [ # # ]: 0 : if (func(rt, arg)) {
1416 : 0 : *pprev = dst->next;
1417 : : dst_free(dst);
1418 : : } else {
1419 : 0 : pprev = &dst->next;
1420 : : }
1421 : : }
1422 : : spin_unlock_bh(&icmp6_dst_lock);
1423 : 0 : }
1424 : :
1425 : 0 : static int ip6_dst_gc(struct dst_ops *ops)
1426 : : {
1427 : 0 : struct net *net = container_of(ops, struct net, ipv6.ip6_dst_ops);
1428 : 0 : int rt_min_interval = net->ipv6.sysctl.ip6_rt_gc_min_interval;
1429 : 0 : int rt_max_size = net->ipv6.sysctl.ip6_rt_max_size;
1430 : 0 : int rt_elasticity = net->ipv6.sysctl.ip6_rt_gc_elasticity;
1431 : 0 : int rt_gc_timeout = net->ipv6.sysctl.ip6_rt_gc_timeout;
1432 : 0 : unsigned long rt_last_gc = net->ipv6.ip6_rt_last_gc;
1433 : : int entries;
1434 : :
1435 : : entries = dst_entries_get_fast(ops);
1436 [ # # ][ # # ]: 0 : if (time_after(rt_last_gc + rt_min_interval, jiffies) &&
1437 : : entries <= rt_max_size)
1438 : : goto out;
1439 : :
1440 : 0 : net->ipv6.ip6_rt_gc_expire++;
1441 : 0 : fib6_run_gc(net->ipv6.ip6_rt_gc_expire, net, entries > rt_max_size);
1442 : : entries = dst_entries_get_slow(ops);
1443 [ # # ]: 0 : if (entries < ops->gc_thresh)
1444 : 0 : net->ipv6.ip6_rt_gc_expire = rt_gc_timeout>>1;
1445 : : out:
1446 : 0 : net->ipv6.ip6_rt_gc_expire -= net->ipv6.ip6_rt_gc_expire>>rt_elasticity;
1447 : 0 : return entries > rt_max_size;
1448 : : }
1449 : :
1450 : : /*
1451 : : *
1452 : : */
1453 : :
1454 : 0 : int ip6_route_add(struct fib6_config *cfg)
1455 : : {
1456 : : int err;
1457 : 0 : struct net *net = cfg->fc_nlinfo.nl_net;
1458 : : struct rt6_info *rt = NULL;
1459 : : struct net_device *dev = NULL;
1460 : : struct inet6_dev *idev = NULL;
1461 : : struct fib6_table *table;
1462 : : int addr_type;
1463 : :
1464 [ # # ][ # # ]: 0 : if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
1465 : : return -EINVAL;
1466 : : #ifndef CONFIG_IPV6_SUBTREES
1467 [ # # ]: 0 : if (cfg->fc_src_len)
1468 : : return -EINVAL;
1469 : : #endif
1470 [ # # ]: 0 : if (cfg->fc_ifindex) {
1471 : : err = -ENODEV;
1472 : 0 : dev = dev_get_by_index(net, cfg->fc_ifindex);
1473 [ # # ]: 0 : if (!dev)
1474 : : goto out;
1475 : : idev = in6_dev_get(dev);
1476 [ # # ]: 0 : if (!idev)
1477 : : goto out;
1478 : : }
1479 : :
1480 [ # # ]: 0 : if (cfg->fc_metric == 0)
1481 : 0 : cfg->fc_metric = IP6_RT_PRIO_USER;
1482 : :
1483 : : err = -ENOBUFS;
1484 [ # # ][ # # ]: 0 : if (cfg->fc_nlinfo.nlh &&
1485 : 0 : !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
1486 : 0 : table = fib6_get_table(net, cfg->fc_table);
1487 [ # # ]: 0 : if (!table) {
1488 : 0 : pr_warn("NLM_F_CREATE should be specified when creating new route\n");
1489 : 0 : table = fib6_new_table(net, cfg->fc_table);
1490 : : }
1491 : : } else {
1492 : 0 : table = fib6_new_table(net, cfg->fc_table);
1493 : : }
1494 : :
1495 [ # # ]: 0 : if (!table)
1496 : : goto out;
1497 : :
1498 : : rt = ip6_dst_alloc(net, NULL, DST_NOCOUNT, table);
1499 : :
1500 [ # # ]: 0 : if (!rt) {
1501 : : err = -ENOMEM;
1502 : : goto out;
1503 : : }
1504 : :
1505 [ # # ]: 0 : if (cfg->fc_flags & RTF_EXPIRES)
1506 : 0 : rt6_set_expires(rt, jiffies +
1507 : 0 : clock_t_to_jiffies(cfg->fc_expires));
1508 : : else
1509 : : rt6_clean_expires(rt);
1510 : :
1511 [ # # ]: 0 : if (cfg->fc_protocol == RTPROT_UNSPEC)
1512 : 0 : cfg->fc_protocol = RTPROT_BOOT;
1513 : 0 : rt->rt6i_protocol = cfg->fc_protocol;
1514 : :
1515 : 0 : addr_type = ipv6_addr_type(&cfg->fc_dst);
1516 : :
1517 [ # # ]: 0 : if (addr_type & IPV6_ADDR_MULTICAST)
1518 : 0 : rt->dst.input = ip6_mc_input;
1519 [ # # ]: 0 : else if (cfg->fc_flags & RTF_LOCAL)
1520 : 0 : rt->dst.input = ip6_input;
1521 : : else
1522 : 0 : rt->dst.input = ip6_forward;
1523 : :
1524 : 0 : rt->dst.output = ip6_output;
1525 : :
1526 : 0 : ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
1527 : 0 : rt->rt6i_dst.plen = cfg->fc_dst_len;
1528 [ # # ]: 0 : if (rt->rt6i_dst.plen == 128)
1529 : 0 : rt->dst.flags |= DST_HOST;
1530 : :
1531 [ # # ][ # # ]: 0 : if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) {
1532 : : u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
1533 [ # # ]: 0 : if (!metrics) {
1534 : : err = -ENOMEM;
1535 : : goto out;
1536 : : }
1537 : : dst_init_metrics(&rt->dst, metrics, 0);
1538 : : }
1539 : : #ifdef CONFIG_IPV6_SUBTREES
1540 : : ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
1541 : : rt->rt6i_src.plen = cfg->fc_src_len;
1542 : : #endif
1543 : :
1544 : 0 : rt->rt6i_metric = cfg->fc_metric;
1545 : :
1546 : : /* We cannot add true routes via loopback here,
1547 : : they would result in kernel looping; promote them to reject routes
1548 : : */
1549 [ # # ][ # # ]: 0 : if ((cfg->fc_flags & RTF_REJECT) ||
1550 [ # # ][ # # ]: 0 : (dev && (dev->flags & IFF_LOOPBACK) &&
1551 [ # # ]: 0 : !(addr_type & IPV6_ADDR_LOOPBACK) &&
1552 : 0 : !(cfg->fc_flags & RTF_LOCAL))) {
1553 : : /* hold loopback dev/idev if we haven't done so. */
1554 [ # # ]: 0 : if (dev != net->loopback_dev) {
1555 [ # # ]: 0 : if (dev) {
1556 : : dev_put(dev);
1557 : : in6_dev_put(idev);
1558 : : }
1559 : 0 : dev = net->loopback_dev;
1560 : : dev_hold(dev);
1561 : : idev = in6_dev_get(dev);
1562 [ # # ]: 0 : if (!idev) {
1563 : : err = -ENODEV;
1564 : : goto out;
1565 : : }
1566 : : }
1567 : 0 : rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
1568 [ # # # ]: 0 : switch (cfg->fc_type) {
1569 : : case RTN_BLACKHOLE:
1570 : 0 : rt->dst.error = -EINVAL;
1571 : 0 : rt->dst.output = dst_discard;
1572 : 0 : rt->dst.input = dst_discard;
1573 : 0 : break;
1574 : : case RTN_PROHIBIT:
1575 : 0 : rt->dst.error = -EACCES;
1576 : 0 : rt->dst.output = ip6_pkt_prohibit_out;
1577 : 0 : rt->dst.input = ip6_pkt_prohibit;
1578 : 0 : break;
1579 : : case RTN_THROW:
1580 : : default:
1581 [ # # ]: 0 : rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
1582 : : : -ENETUNREACH;
1583 : 0 : rt->dst.output = ip6_pkt_discard_out;
1584 : 0 : rt->dst.input = ip6_pkt_discard;
1585 : 0 : break;
1586 : : }
1587 : : goto install_route;
1588 : : }
1589 : :
1590 [ # # ]: 0 : if (cfg->fc_flags & RTF_GATEWAY) {
1591 : : const struct in6_addr *gw_addr;
1592 : : int gwa_type;
1593 : :
1594 : 0 : gw_addr = &cfg->fc_gateway;
1595 : 0 : rt->rt6i_gateway = *gw_addr;
1596 : : gwa_type = ipv6_addr_type(gw_addr);
1597 : :
1598 [ # # ]: 0 : if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
1599 : : struct rt6_info *grt;
1600 : :
1601 : : /* IPv6 strictly inhibits using not link-local
1602 : : addresses as nexthop address.
1603 : : Otherwise, router will not able to send redirects.
1604 : : It is very good, but in some (rare!) circumstances
1605 : : (SIT, PtP, NBMA NOARP links) it is handy to allow
1606 : : some exceptions. --ANK
1607 : : */
1608 : : err = -EINVAL;
1609 [ # # ]: 0 : if (!(gwa_type & IPV6_ADDR_UNICAST))
1610 : : goto out;
1611 : :
1612 : 0 : grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
1613 : :
1614 : : err = -EHOSTUNREACH;
1615 [ # # ]: 0 : if (!grt)
1616 : : goto out;
1617 [ # # ]: 0 : if (dev) {
1618 [ # # ]: 0 : if (dev != grt->dst.dev) {
1619 : : ip6_rt_put(grt);
1620 : : goto out;
1621 : : }
1622 : : } else {
1623 : 0 : dev = grt->dst.dev;
1624 : 0 : idev = grt->rt6i_idev;
1625 : : dev_hold(dev);
1626 : 0 : in6_dev_hold(grt->rt6i_idev);
1627 : : }
1628 [ # # ]: 0 : if (!(grt->rt6i_flags & RTF_GATEWAY))
1629 : : err = 0;
1630 : : ip6_rt_put(grt);
1631 : :
1632 [ # # ]: 0 : if (err)
1633 : : goto out;
1634 : : }
1635 : : err = -EINVAL;
1636 [ # # ][ # # ]: 0 : if (!dev || (dev->flags & IFF_LOOPBACK))
1637 : : goto out;
1638 : : }
1639 : :
1640 : : err = -ENODEV;
1641 [ # # ]: 0 : if (!dev)
1642 : : goto out;
1643 : :
1644 [ # # ]: 0 : if (!ipv6_addr_any(&cfg->fc_prefsrc)) {
1645 [ # # ]: 0 : if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) {
1646 : : err = -EINVAL;
1647 : : goto out;
1648 : : }
1649 : 0 : rt->rt6i_prefsrc.addr = cfg->fc_prefsrc;
1650 : 0 : rt->rt6i_prefsrc.plen = 128;
1651 : : } else
1652 : 0 : rt->rt6i_prefsrc.plen = 0;
1653 : :
1654 : 0 : rt->rt6i_flags = cfg->fc_flags;
1655 : :
1656 : : install_route:
1657 [ # # ]: 0 : if (cfg->fc_mx) {
1658 : 0 : struct nlattr *nla;
1659 : : int remaining;
1660 : :
1661 [ # # ]: 0 : nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) {
1662 : : int type = nla_type(nla);
1663 : :
1664 [ # # ]: 0 : if (type) {
1665 [ # # ]: 0 : if (type > RTAX_MAX) {
1666 : : err = -EINVAL;
1667 : : goto out;
1668 : : }
1669 : :
1670 : 0 : dst_metric_set(&rt->dst, type, nla_get_u32(nla));
1671 : : }
1672 : : }
1673 : : }
1674 : :
1675 : 0 : rt->dst.dev = dev;
1676 : 0 : rt->rt6i_idev = idev;
1677 : 0 : rt->rt6i_table = table;
1678 : :
1679 : 0 : cfg->fc_nlinfo.nl_net = dev_net(dev);
1680 : :
1681 : 0 : return __ip6_ins_rt(rt, &cfg->fc_nlinfo);
1682 : :
1683 : : out:
1684 [ # # ]: 0 : if (dev)
1685 : : dev_put(dev);
1686 [ # # ]: 0 : if (idev)
1687 : : in6_dev_put(idev);
1688 [ # # ]: 0 : if (rt)
1689 : 0 : dst_free(&rt->dst);
1690 : 0 : return err;
1691 : : }
1692 : :
1693 : 0 : static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
1694 : : {
1695 : : int err;
1696 : : struct fib6_table *table;
1697 : : struct net *net = dev_net(rt->dst.dev);
1698 : :
1699 [ # # ]: 0 : if (rt == net->ipv6.ip6_null_entry) {
1700 : : err = -ENOENT;
1701 : : goto out;
1702 : : }
1703 : :
1704 : 0 : table = rt->rt6i_table;
1705 : 0 : write_lock_bh(&table->tb6_lock);
1706 : 0 : err = fib6_del(rt, info);
1707 : 0 : write_unlock_bh(&table->tb6_lock);
1708 : :
1709 : : out:
1710 : : ip6_rt_put(rt);
1711 : 0 : return err;
1712 : : }
1713 : :
1714 : 0 : int ip6_del_rt(struct rt6_info *rt)
1715 : : {
1716 : 0 : struct nl_info info = {
1717 : : .nl_net = dev_net(rt->dst.dev),
1718 : : };
1719 : 0 : return __ip6_del_rt(rt, &info);
1720 : : }
1721 : :
1722 : 0 : static int ip6_route_del(struct fib6_config *cfg)
1723 : : {
1724 : : struct fib6_table *table;
1725 : : struct fib6_node *fn;
1726 : : struct rt6_info *rt;
1727 : : int err = -ESRCH;
1728 : :
1729 : 0 : table = fib6_get_table(cfg->fc_nlinfo.nl_net, cfg->fc_table);
1730 [ # # ]: 0 : if (!table)
1731 : : return err;
1732 : :
1733 : 0 : read_lock_bh(&table->tb6_lock);
1734 : :
1735 : 0 : fn = fib6_locate(&table->tb6_root,
1736 : 0 : &cfg->fc_dst, cfg->fc_dst_len,
1737 : 0 : &cfg->fc_src, cfg->fc_src_len);
1738 : :
1739 [ # # ]: 0 : if (fn) {
1740 [ # # ]: 0 : for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
1741 [ # # ][ # # ]: 0 : if (cfg->fc_ifindex &&
1742 [ # # ]: 0 : (!rt->dst.dev ||
1743 : 0 : rt->dst.dev->ifindex != cfg->fc_ifindex))
1744 : 0 : continue;
1745 [ # # ][ # # ]: 0 : if (cfg->fc_flags & RTF_GATEWAY &&
1746 : : !ipv6_addr_equal(&cfg->fc_gateway, &rt->rt6i_gateway))
1747 : 0 : continue;
1748 [ # # ][ # # ]: 0 : if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric)
1749 : 0 : continue;
1750 : : dst_hold(&rt->dst);
1751 : 0 : read_unlock_bh(&table->tb6_lock);
1752 : :
1753 : 0 : return __ip6_del_rt(rt, &cfg->fc_nlinfo);
1754 : : }
1755 : : }
1756 : 0 : read_unlock_bh(&table->tb6_lock);
1757 : :
1758 : 0 : return err;
1759 : : }
1760 : :
1761 : 0 : static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buff *skb)
1762 : : {
1763 : 0 : struct net *net = dev_net(skb->dev);
1764 : : struct netevent_redirect netevent;
1765 : : struct rt6_info *rt, *nrt = NULL;
1766 : : struct ndisc_options ndopts;
1767 : : struct inet6_dev *in6_dev;
1768 : : struct neighbour *neigh;
1769 : : struct rd_msg *msg;
1770 : : int optlen, on_link;
1771 : : u8 *lladdr;
1772 : :
1773 : 0 : optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
1774 : 0 : optlen -= sizeof(*msg);
1775 : :
1776 [ # # ]: 0 : if (optlen < 0) {
1777 : 0 : net_dbg_ratelimited("rt6_do_redirect: packet too short\n");
1778 : 0 : return;
1779 : : }
1780 : :
1781 : : msg = (struct rd_msg *)icmp6_hdr(skb);
1782 : :
1783 [ # # ]: 0 : if (ipv6_addr_is_multicast(&msg->dest)) {
1784 : 0 : net_dbg_ratelimited("rt6_do_redirect: destination address is multicast\n");
1785 : : return;
1786 : : }
1787 : :
1788 : : on_link = 0;
1789 [ # # ]: 0 : if (ipv6_addr_equal(&msg->dest, &msg->target)) {
1790 : : on_link = 1;
1791 [ # # ]: 0 : } else if (ipv6_addr_type(&msg->target) !=
1792 : : (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1793 : 0 : net_dbg_ratelimited("rt6_do_redirect: target address is not link-local unicast\n");
1794 : : return;
1795 : : }
1796 : :
1797 : 0 : in6_dev = __in6_dev_get(skb->dev);
1798 [ # # ]: 0 : if (!in6_dev)
1799 : : return;
1800 [ # # ][ # # ]: 0 : if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects)
1801 : : return;
1802 : :
1803 : : /* RFC2461 8.1:
1804 : : * The IP source address of the Redirect MUST be the same as the current
1805 : : * first-hop router for the specified ICMP Destination Address.
1806 : : */
1807 : :
1808 [ # # ]: 0 : if (!ndisc_parse_options(msg->opt, optlen, &ndopts)) {
1809 : 0 : net_dbg_ratelimited("rt6_redirect: invalid ND options\n");
1810 : : return;
1811 : : }
1812 : :
1813 : : lladdr = NULL;
1814 [ # # ]: 0 : if (ndopts.nd_opts_tgt_lladdr) {
1815 : 0 : lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
1816 : : skb->dev);
1817 [ # # ]: 0 : if (!lladdr) {
1818 : 0 : net_dbg_ratelimited("rt6_redirect: invalid link-layer address length\n");
1819 : : return;
1820 : : }
1821 : : }
1822 : :
1823 : : rt = (struct rt6_info *) dst;
1824 [ # # ]: 0 : if (rt == net->ipv6.ip6_null_entry) {
1825 : 0 : net_dbg_ratelimited("rt6_redirect: source isn't a valid nexthop for redirect target\n");
1826 : : return;
1827 : : }
1828 : :
1829 : : /* Redirect received -> path was valid.
1830 : : * Look, redirects are sent only in response to data packets,
1831 : : * so that this nexthop apparently is reachable. --ANK
1832 : : */
1833 : : dst_confirm(&rt->dst);
1834 : :
1835 : 0 : neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
1836 [ # # ]: 0 : if (!neigh)
1837 : : return;
1838 : :
1839 : : /*
1840 : : * We have finally decided to accept it.
1841 : : */
1842 : :
1843 [ # # ]: 0 : neigh_update(neigh, lladdr, NUD_STALE,
1844 : : NEIGH_UPDATE_F_WEAK_OVERRIDE|
1845 : : NEIGH_UPDATE_F_OVERRIDE|
1846 : : (on_link ? 0 : (NEIGH_UPDATE_F_OVERRIDE_ISROUTER|
1847 : : NEIGH_UPDATE_F_ISROUTER))
1848 : : );
1849 : :
1850 : 0 : nrt = ip6_rt_copy(rt, &msg->dest);
1851 [ # # ]: 0 : if (!nrt)
1852 : : goto out;
1853 : :
1854 : 0 : nrt->rt6i_flags = RTF_GATEWAY|RTF_UP|RTF_DYNAMIC|RTF_CACHE;
1855 [ # # ]: 0 : if (on_link)
1856 : 0 : nrt->rt6i_flags &= ~RTF_GATEWAY;
1857 : :
1858 : 0 : nrt->rt6i_gateway = *(struct in6_addr *)neigh->primary_key;
1859 : :
1860 [ # # ]: 0 : if (ip6_ins_rt(nrt))
1861 : : goto out;
1862 : :
1863 : 0 : netevent.old = &rt->dst;
1864 : 0 : netevent.new = &nrt->dst;
1865 : 0 : netevent.daddr = &msg->dest;
1866 : 0 : netevent.neigh = neigh;
1867 : 0 : call_netevent_notifiers(NETEVENT_REDIRECT, &netevent);
1868 : :
1869 [ # # ]: 0 : if (rt->rt6i_flags & RTF_CACHE) {
1870 : : rt = (struct rt6_info *) dst_clone(&rt->dst);
1871 : 0 : ip6_del_rt(rt);
1872 : : }
1873 : :
1874 : : out:
1875 : : neigh_release(neigh);
1876 : : }
1877 : :
1878 : : /*
1879 : : * Misc support functions
1880 : : */
1881 : :
1882 : 0 : static struct rt6_info *ip6_rt_copy(struct rt6_info *ort,
1883 : : const struct in6_addr *dest)
1884 : : {
1885 : : struct net *net = dev_net(ort->dst.dev);
1886 : 105 : struct rt6_info *rt = ip6_dst_alloc(net, ort->dst.dev, 0,
1887 : : ort->rt6i_table);
1888 : :
1889 [ + - ]: 105 : if (rt) {
1890 : 105 : rt->dst.input = ort->dst.input;
1891 : 105 : rt->dst.output = ort->dst.output;
1892 : 105 : rt->dst.flags |= DST_HOST;
1893 : :
1894 : 105 : rt->rt6i_dst.addr = *dest;
1895 : 105 : rt->rt6i_dst.plen = 128;
1896 : 105 : dst_copy_metrics(&rt->dst, &ort->dst);
1897 : 105 : rt->dst.error = ort->dst.error;
1898 : 105 : rt->rt6i_idev = ort->rt6i_idev;
1899 [ + - ]: 105 : if (rt->rt6i_idev)
1900 : : in6_dev_hold(rt->rt6i_idev);
1901 : 105 : rt->dst.lastuse = jiffies;
1902 : :
1903 [ - + ]: 105 : if (ort->rt6i_flags & RTF_GATEWAY)
1904 : 0 : rt->rt6i_gateway = ort->rt6i_gateway;
1905 : : else
1906 : 105 : rt->rt6i_gateway = *dest;
1907 : 105 : rt->rt6i_flags = ort->rt6i_flags;
1908 : : rt6_set_from(rt, ort);
1909 : 105 : rt->rt6i_metric = 0;
1910 : :
1911 : : #ifdef CONFIG_IPV6_SUBTREES
1912 : : memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
1913 : : #endif
1914 : 105 : memcpy(&rt->rt6i_prefsrc, &ort->rt6i_prefsrc, sizeof(struct rt6key));
1915 : 105 : rt->rt6i_table = ort->rt6i_table;
1916 : : }
1917 : 105 : return rt;
1918 : : }
1919 : :
1920 : : #ifdef CONFIG_IPV6_ROUTE_INFO
1921 : : static struct rt6_info *rt6_get_route_info(struct net *net,
1922 : : const struct in6_addr *prefix, int prefixlen,
1923 : : const struct in6_addr *gwaddr, int ifindex)
1924 : : {
1925 : : struct fib6_node *fn;
1926 : : struct rt6_info *rt = NULL;
1927 : : struct fib6_table *table;
1928 : :
1929 : : table = fib6_get_table(net, RT6_TABLE_INFO);
1930 : : if (!table)
1931 : : return NULL;
1932 : :
1933 : : read_lock_bh(&table->tb6_lock);
1934 : : fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
1935 : : if (!fn)
1936 : : goto out;
1937 : :
1938 : : for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) {
1939 : : if (rt->dst.dev->ifindex != ifindex)
1940 : : continue;
1941 : : if ((rt->rt6i_flags & (RTF_ROUTEINFO|RTF_GATEWAY)) != (RTF_ROUTEINFO|RTF_GATEWAY))
1942 : : continue;
1943 : : if (!ipv6_addr_equal(&rt->rt6i_gateway, gwaddr))
1944 : : continue;
1945 : : dst_hold(&rt->dst);
1946 : : break;
1947 : : }
1948 : : out:
1949 : : read_unlock_bh(&table->tb6_lock);
1950 : : return rt;
1951 : : }
1952 : :
1953 : : static struct rt6_info *rt6_add_route_info(struct net *net,
1954 : : const struct in6_addr *prefix, int prefixlen,
1955 : : const struct in6_addr *gwaddr, int ifindex,
1956 : : unsigned int pref)
1957 : : {
1958 : : struct fib6_config cfg = {
1959 : : .fc_table = RT6_TABLE_INFO,
1960 : : .fc_metric = IP6_RT_PRIO_USER,
1961 : : .fc_ifindex = ifindex,
1962 : : .fc_dst_len = prefixlen,
1963 : : .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
1964 : : RTF_UP | RTF_PREF(pref),
1965 : : .fc_nlinfo.portid = 0,
1966 : : .fc_nlinfo.nlh = NULL,
1967 : : .fc_nlinfo.nl_net = net,
1968 : : };
1969 : :
1970 : : cfg.fc_dst = *prefix;
1971 : : cfg.fc_gateway = *gwaddr;
1972 : :
1973 : : /* We should treat it as a default route if prefix length is 0. */
1974 : : if (!prefixlen)
1975 : : cfg.fc_flags |= RTF_DEFAULT;
1976 : :
1977 : : ip6_route_add(&cfg);
1978 : :
1979 : : return rt6_get_route_info(net, prefix, prefixlen, gwaddr, ifindex);
1980 : : }
1981 : : #endif
1982 : :
1983 : 0 : struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev)
1984 : : {
1985 : : struct rt6_info *rt;
1986 : : struct fib6_table *table;
1987 : :
1988 : 0 : table = fib6_get_table(dev_net(dev), RT6_TABLE_DFLT);
1989 [ # # ]: 0 : if (!table)
1990 : : return NULL;
1991 : :
1992 : 0 : read_lock_bh(&table->tb6_lock);
1993 [ # # ]: 0 : for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) {
1994 [ # # ][ # # ]: 0 : if (dev == rt->dst.dev &&
1995 [ # # ]: 0 : ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
1996 : : ipv6_addr_equal(&rt->rt6i_gateway, addr))
1997 : : break;
1998 : : }
1999 [ # # ]: 0 : if (rt)
2000 : : dst_hold(&rt->dst);
2001 : 0 : read_unlock_bh(&table->tb6_lock);
2002 : 0 : return rt;
2003 : : }
2004 : :
2005 : 0 : struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
2006 : : struct net_device *dev,
2007 : : unsigned int pref)
2008 : : {
2009 : 0 : struct fib6_config cfg = {
2010 : : .fc_table = RT6_TABLE_DFLT,
2011 : : .fc_metric = IP6_RT_PRIO_USER,
2012 : 0 : .fc_ifindex = dev->ifindex,
2013 : : .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
2014 : 0 : RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
2015 : : .fc_nlinfo.portid = 0,
2016 : : .fc_nlinfo.nlh = NULL,
2017 : : .fc_nlinfo.nl_net = dev_net(dev),
2018 : : };
2019 : :
2020 : 0 : cfg.fc_gateway = *gwaddr;
2021 : :
2022 : 0 : ip6_route_add(&cfg);
2023 : :
2024 : 0 : return rt6_get_dflt_router(gwaddr, dev);
2025 : : }
2026 : :
2027 : 0 : void rt6_purge_dflt_routers(struct net *net)
2028 : : {
2029 : : struct rt6_info *rt;
2030 : : struct fib6_table *table;
2031 : :
2032 : : /* NOTE: Keep consistent with rt6_get_dflt_router */
2033 : 0 : table = fib6_get_table(net, RT6_TABLE_DFLT);
2034 [ # # ]: 0 : if (!table)
2035 : 0 : return;
2036 : :
2037 : : restart:
2038 : 0 : read_lock_bh(&table->tb6_lock);
2039 [ # # ]: 0 : for (rt = table->tb6_root.leaf; rt; rt = rt->dst.rt6_next) {
2040 [ # # ][ # # ]: 0 : if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ADDRCONF) &&
2041 [ # # ]: 0 : (!rt->rt6i_idev || rt->rt6i_idev->cnf.accept_ra != 2)) {
2042 : : dst_hold(&rt->dst);
2043 : 0 : read_unlock_bh(&table->tb6_lock);
2044 : 0 : ip6_del_rt(rt);
2045 : 0 : goto restart;
2046 : : }
2047 : : }
2048 : 0 : read_unlock_bh(&table->tb6_lock);
2049 : : }
2050 : :
2051 : 0 : static void rtmsg_to_fib6_config(struct net *net,
2052 : : struct in6_rtmsg *rtmsg,
2053 : : struct fib6_config *cfg)
2054 : : {
2055 : 0 : memset(cfg, 0, sizeof(*cfg));
2056 : :
2057 : 0 : cfg->fc_table = RT6_TABLE_MAIN;
2058 : 0 : cfg->fc_ifindex = rtmsg->rtmsg_ifindex;
2059 : 0 : cfg->fc_metric = rtmsg->rtmsg_metric;
2060 : 0 : cfg->fc_expires = rtmsg->rtmsg_info;
2061 : 0 : cfg->fc_dst_len = rtmsg->rtmsg_dst_len;
2062 : 0 : cfg->fc_src_len = rtmsg->rtmsg_src_len;
2063 : 0 : cfg->fc_flags = rtmsg->rtmsg_flags;
2064 : :
2065 : 0 : cfg->fc_nlinfo.nl_net = net;
2066 : :
2067 : 0 : cfg->fc_dst = rtmsg->rtmsg_dst;
2068 : 0 : cfg->fc_src = rtmsg->rtmsg_src;
2069 : 0 : cfg->fc_gateway = rtmsg->rtmsg_gateway;
2070 : 0 : }
2071 : :
2072 : 0 : int ipv6_route_ioctl(struct net *net, unsigned int cmd, void __user *arg)
2073 : : {
2074 : : struct fib6_config cfg;
2075 : : struct in6_rtmsg rtmsg;
2076 : : int err;
2077 : :
2078 [ # # ]: 0 : switch(cmd) {
2079 : : case SIOCADDRT: /* Add a route */
2080 : : case SIOCDELRT: /* Delete a route */
2081 [ # # ]: 0 : if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
2082 : : return -EPERM;
2083 : : err = copy_from_user(&rtmsg, arg,
2084 : : sizeof(struct in6_rtmsg));
2085 [ # # ]: 0 : if (err)
2086 : : return -EFAULT;
2087 : :
2088 : 0 : rtmsg_to_fib6_config(net, &rtmsg, &cfg);
2089 : :
2090 : 0 : rtnl_lock();
2091 [ # # # ]: 0 : switch (cmd) {
2092 : : case SIOCADDRT:
2093 : 0 : err = ip6_route_add(&cfg);
2094 : 0 : break;
2095 : : case SIOCDELRT:
2096 : 0 : err = ip6_route_del(&cfg);
2097 : 0 : break;
2098 : : default:
2099 : : err = -EINVAL;
2100 : : }
2101 : 0 : rtnl_unlock();
2102 : :
2103 : 0 : return err;
2104 : : }
2105 : :
2106 : : return -EINVAL;
2107 : : }
2108 : :
2109 : : /*
2110 : : * Drop the packet on the floor
2111 : : */
2112 : :
2113 : 0 : static int ip6_pkt_drop(struct sk_buff *skb, u8 code, int ipstats_mib_noroutes)
2114 : : {
2115 : : int type;
2116 : : struct dst_entry *dst = skb_dst(skb);
2117 [ # # # ]: 0 : switch (ipstats_mib_noroutes) {
2118 : : case IPSTATS_MIB_INNOROUTES:
2119 : 0 : type = ipv6_addr_type(&ipv6_hdr(skb)->daddr);
2120 [ # # ]: 0 : if (type == IPV6_ADDR_ANY) {
2121 [ # # ]: 0 : IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
2122 : : IPSTATS_MIB_INADDRERRORS);
2123 : 0 : break;
2124 : : }
2125 : : /* FALLTHROUGH */
2126 : : case IPSTATS_MIB_OUTNOROUTES:
2127 [ # # ]: 0 : IP6_INC_STATS(dev_net(dst->dev), ip6_dst_idev(dst),
2128 : : ipstats_mib_noroutes);
2129 : 0 : break;
2130 : : }
2131 : 0 : icmpv6_send(skb, ICMPV6_DEST_UNREACH, code, 0);
2132 : 0 : kfree_skb(skb);
2133 : 0 : return 0;
2134 : : }
2135 : :
2136 : 0 : static int ip6_pkt_discard(struct sk_buff *skb)
2137 : : {
2138 : 0 : return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES);
2139 : : }
2140 : :
2141 : 0 : static int ip6_pkt_discard_out(struct sk_buff *skb)
2142 : : {
2143 : 0 : skb->dev = skb_dst(skb)->dev;
2144 : 0 : return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES);
2145 : : }
2146 : :
2147 : 0 : static int ip6_pkt_prohibit(struct sk_buff *skb)
2148 : : {
2149 : 0 : return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES);
2150 : : }
2151 : :
2152 : 0 : static int ip6_pkt_prohibit_out(struct sk_buff *skb)
2153 : : {
2154 : 0 : skb->dev = skb_dst(skb)->dev;
2155 : 0 : return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES);
2156 : : }
2157 : :
2158 : : /*
2159 : : * Allocate a dst for local (unicast / anycast) address.
2160 : : */
2161 : :
2162 : 0 : struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2163 : : const struct in6_addr *addr,
2164 : : bool anycast)
2165 : : {
2166 : : struct net *net = dev_net(idev->dev);
2167 : 0 : struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
2168 : : DST_NOCOUNT, NULL);
2169 [ # # ]: 0 : if (!rt)
2170 : : return ERR_PTR(-ENOMEM);
2171 : :
2172 : : in6_dev_hold(idev);
2173 : :
2174 : 0 : rt->dst.flags |= DST_HOST;
2175 : 0 : rt->dst.input = ip6_input;
2176 : 0 : rt->dst.output = ip6_output;
2177 : 0 : rt->rt6i_idev = idev;
2178 : :
2179 : 0 : rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
2180 [ # # ]: 0 : if (anycast)
2181 : 0 : rt->rt6i_flags |= RTF_ANYCAST;
2182 : : else
2183 : 0 : rt->rt6i_flags |= RTF_LOCAL;
2184 : :
2185 : 0 : rt->rt6i_gateway = *addr;
2186 : 0 : rt->rt6i_dst.addr = *addr;
2187 : 0 : rt->rt6i_dst.plen = 128;
2188 : 0 : rt->rt6i_table = fib6_get_table(net, RT6_TABLE_LOCAL);
2189 : :
2190 : 0 : atomic_set(&rt->dst.__refcnt, 1);
2191 : :
2192 : 0 : return rt;
2193 : : }
2194 : :
2195 : 0 : int ip6_route_get_saddr(struct net *net,
2196 : : struct rt6_info *rt,
2197 : : const struct in6_addr *daddr,
2198 : : unsigned int prefs,
2199 : : struct in6_addr *saddr)
2200 : : {
2201 : : struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt);
2202 : : int err = 0;
2203 [ - + ]: 3 : if (rt->rt6i_prefsrc.plen)
2204 : 0 : *saddr = rt->rt6i_prefsrc.addr;
2205 : : else
2206 [ + - ]: 3 : err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
2207 : : daddr, prefs, saddr);
2208 : 3 : return err;
2209 : : }
2210 : :
2211 : : /* remove deleted ip from prefsrc entries */
2212 : : struct arg_dev_net_ip {
2213 : : struct net_device *dev;
2214 : : struct net *net;
2215 : : struct in6_addr *addr;
2216 : : };
2217 : :
2218 : 0 : static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
2219 : : {
2220 : 0 : struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev;
2221 : 0 : struct net *net = ((struct arg_dev_net_ip *)arg)->net;
2222 : 0 : struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr;
2223 : :
2224 [ # # ][ # # ]: 0 : if (((void *)rt->dst.dev == dev || !dev) &&
[ # # ]
2225 [ # # ]: 0 : rt != net->ipv6.ip6_null_entry &&
2226 : : ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) {
2227 : : /* remove prefsrc entry */
2228 : 0 : rt->rt6i_prefsrc.plen = 0;
2229 : : }
2230 : 0 : return 0;
2231 : : }
2232 : :
2233 : 0 : void rt6_remove_prefsrc(struct inet6_ifaddr *ifp)
2234 : : {
2235 : : struct net *net = dev_net(ifp->idev->dev);
2236 : 0 : struct arg_dev_net_ip adni = {
2237 : 0 : .dev = ifp->idev->dev,
2238 : : .net = net,
2239 : 0 : .addr = &ifp->addr,
2240 : : };
2241 : 0 : fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni);
2242 : 0 : }
2243 : :
2244 : : struct arg_dev_net {
2245 : : struct net_device *dev;
2246 : : struct net *net;
2247 : : };
2248 : :
2249 : 0 : static int fib6_ifdown(struct rt6_info *rt, void *arg)
2250 : : {
2251 : : const struct arg_dev_net *adn = arg;
2252 : 0 : const struct net_device *dev = adn->dev;
2253 : :
2254 [ # # ][ # # ]: 0 : if ((rt->dst.dev == dev || !dev) &&
[ # # ]
2255 : 0 : rt != adn->net->ipv6.ip6_null_entry)
2256 : : return -1;
2257 : :
2258 : 0 : return 0;
2259 : : }
2260 : :
2261 : 0 : void rt6_ifdown(struct net *net, struct net_device *dev)
2262 : : {
2263 : 0 : struct arg_dev_net adn = {
2264 : : .dev = dev,
2265 : : .net = net,
2266 : : };
2267 : :
2268 : 0 : fib6_clean_all(net, fib6_ifdown, 0, &adn);
2269 : 0 : icmp6_clean_all(fib6_ifdown, &adn);
2270 : 0 : }
2271 : :
2272 : : struct rt6_mtu_change_arg {
2273 : : struct net_device *dev;
2274 : : unsigned int mtu;
2275 : : };
2276 : :
2277 : 0 : static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg)
2278 : : {
2279 : : struct rt6_mtu_change_arg *arg = (struct rt6_mtu_change_arg *) p_arg;
2280 : : struct inet6_dev *idev;
2281 : :
2282 : : /* In IPv6 pmtu discovery is not optional,
2283 : : so that RTAX_MTU lock cannot disable it.
2284 : : We still use this lock to block changes
2285 : : caused by addrconf/ndisc.
2286 : : */
2287 : :
2288 : 0 : idev = __in6_dev_get(arg->dev);
2289 [ # # ]: 0 : if (!idev)
2290 : : return 0;
2291 : :
2292 : : /* For administrative MTU increase, there is no way to discover
2293 : : IPv6 PMTU increase, so PMTU increase should be updated here.
2294 : : Since RFC 1981 doesn't include administrative MTU increase
2295 : : update PMTU increase is a MUST. (i.e. jumbo frame)
2296 : : */
2297 : : /*
2298 : : If new MTU is less than route PMTU, this new MTU will be the
2299 : : lowest MTU in the path, update the route PMTU to reflect PMTU
2300 : : decreases; if new MTU is greater than route PMTU, and the
2301 : : old MTU is the lowest MTU in the path, update the route PMTU
2302 : : to reflect the increase. In this case if the other nodes' MTU
2303 : : also have the lowest MTU, TOO BIG MESSAGE will be lead to
2304 : : PMTU discouvery.
2305 : : */
2306 [ # # ][ # # ]: 0 : if (rt->dst.dev == arg->dev &&
2307 [ # # ]: 0 : !dst_metric_locked(&rt->dst, RTAX_MTU) &&
2308 [ # # ]: 0 : (dst_mtu(&rt->dst) >= arg->mtu ||
2309 [ # # ]: 0 : (dst_mtu(&rt->dst) < arg->mtu &&
2310 : 0 : dst_mtu(&rt->dst) == idev->cnf.mtu6))) {
2311 : 0 : dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu);
2312 : : }
2313 : : return 0;
2314 : : }
2315 : :
2316 : 0 : void rt6_mtu_change(struct net_device *dev, unsigned int mtu)
2317 : : {
2318 : 0 : struct rt6_mtu_change_arg arg = {
2319 : : .dev = dev,
2320 : : .mtu = mtu,
2321 : : };
2322 : :
2323 : 0 : fib6_clean_all(dev_net(dev), rt6_mtu_change_route, 0, &arg);
2324 : 0 : }
2325 : :
2326 : : static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
2327 : : [RTA_GATEWAY] = { .len = sizeof(struct in6_addr) },
2328 : : [RTA_OIF] = { .type = NLA_U32 },
2329 : : [RTA_IIF] = { .type = NLA_U32 },
2330 : : [RTA_PRIORITY] = { .type = NLA_U32 },
2331 : : [RTA_METRICS] = { .type = NLA_NESTED },
2332 : : [RTA_MULTIPATH] = { .len = sizeof(struct rtnexthop) },
2333 : : };
2334 : :
2335 : 0 : static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
2336 : : struct fib6_config *cfg)
2337 : : {
2338 : : struct rtmsg *rtm;
2339 : : struct nlattr *tb[RTA_MAX+1];
2340 : : int err;
2341 : :
2342 : : err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
2343 [ # # ]: 0 : if (err < 0)
2344 : : goto errout;
2345 : :
2346 : : err = -EINVAL;
2347 : : rtm = nlmsg_data(nlh);
2348 : 0 : memset(cfg, 0, sizeof(*cfg));
2349 : :
2350 : 0 : cfg->fc_table = rtm->rtm_table;
2351 : 0 : cfg->fc_dst_len = rtm->rtm_dst_len;
2352 : 0 : cfg->fc_src_len = rtm->rtm_src_len;
2353 : 0 : cfg->fc_flags = RTF_UP;
2354 : 0 : cfg->fc_protocol = rtm->rtm_protocol;
2355 : 0 : cfg->fc_type = rtm->rtm_type;
2356 : :
2357 [ # # ]: 0 : if (rtm->rtm_type == RTN_UNREACHABLE ||
2358 : : rtm->rtm_type == RTN_BLACKHOLE ||
2359 : 0 : rtm->rtm_type == RTN_PROHIBIT ||
2360 : : rtm->rtm_type == RTN_THROW)
2361 : 0 : cfg->fc_flags |= RTF_REJECT;
2362 : :
2363 [ # # ]: 0 : if (rtm->rtm_type == RTN_LOCAL)
2364 : 0 : cfg->fc_flags |= RTF_LOCAL;
2365 : :
2366 : 0 : cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
2367 : 0 : cfg->fc_nlinfo.nlh = nlh;
2368 : 0 : cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
2369 : :
2370 [ # # ]: 0 : if (tb[RTA_GATEWAY]) {
2371 : 0 : nla_memcpy(&cfg->fc_gateway, tb[RTA_GATEWAY], 16);
2372 : 0 : cfg->fc_flags |= RTF_GATEWAY;
2373 : : }
2374 : :
2375 [ # # ]: 0 : if (tb[RTA_DST]) {
2376 : 0 : int plen = (rtm->rtm_dst_len + 7) >> 3;
2377 : :
2378 [ # # ]: 0 : if (nla_len(tb[RTA_DST]) < plen)
2379 : : goto errout;
2380 : :
2381 : 0 : nla_memcpy(&cfg->fc_dst, tb[RTA_DST], plen);
2382 : : }
2383 : :
2384 [ # # ]: 0 : if (tb[RTA_SRC]) {
2385 : 0 : int plen = (rtm->rtm_src_len + 7) >> 3;
2386 : :
2387 [ # # ]: 0 : if (nla_len(tb[RTA_SRC]) < plen)
2388 : : goto errout;
2389 : :
2390 : 0 : nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen);
2391 : : }
2392 : :
2393 [ # # ]: 0 : if (tb[RTA_PREFSRC])
2394 : 0 : nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16);
2395 : :
2396 [ # # ]: 0 : if (tb[RTA_OIF])
2397 : 0 : cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]);
2398 : :
2399 [ # # ]: 0 : if (tb[RTA_PRIORITY])
2400 : 0 : cfg->fc_metric = nla_get_u32(tb[RTA_PRIORITY]);
2401 : :
2402 [ # # ]: 0 : if (tb[RTA_METRICS]) {
2403 : 0 : cfg->fc_mx = nla_data(tb[RTA_METRICS]);
2404 : 0 : cfg->fc_mx_len = nla_len(tb[RTA_METRICS]);
2405 : : }
2406 : :
2407 [ # # ]: 0 : if (tb[RTA_TABLE])
2408 : 0 : cfg->fc_table = nla_get_u32(tb[RTA_TABLE]);
2409 : :
2410 [ # # ]: 0 : if (tb[RTA_MULTIPATH]) {
2411 : 0 : cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
2412 : 0 : cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
2413 : : }
2414 : :
2415 : : err = 0;
2416 : : errout:
2417 : 0 : return err;
2418 : : }
2419 : :
2420 : 0 : static int ip6_route_multipath(struct fib6_config *cfg, int add)
2421 : : {
2422 : : struct fib6_config r_cfg;
2423 : 0 : struct rtnexthop *rtnh;
2424 : : int remaining;
2425 : : int attrlen;
2426 : : int err = 0, last_err = 0;
2427 : :
2428 : : beginning:
2429 : 0 : rtnh = (struct rtnexthop *)cfg->fc_mp;
2430 : 0 : remaining = cfg->fc_mp_len;
2431 : :
2432 : : /* Parse a Multipath Entry */
2433 [ # # ]: 0 : while (rtnh_ok(rtnh, remaining)) {
2434 : 0 : memcpy(&r_cfg, cfg, sizeof(*cfg));
2435 [ # # ]: 0 : if (rtnh->rtnh_ifindex)
2436 : 0 : r_cfg.fc_ifindex = rtnh->rtnh_ifindex;
2437 : :
2438 : : attrlen = rtnh_attrlen(rtnh);
2439 [ # # ]: 0 : if (attrlen > 0) {
2440 : 0 : struct nlattr *nla, *attrs = rtnh_attrs(rtnh);
2441 : :
2442 : 0 : nla = nla_find(attrs, attrlen, RTA_GATEWAY);
2443 [ # # ]: 0 : if (nla) {
2444 : 0 : nla_memcpy(&r_cfg.fc_gateway, nla, 16);
2445 : 0 : r_cfg.fc_flags |= RTF_GATEWAY;
2446 : : }
2447 : : }
2448 [ # # ]: 0 : err = add ? ip6_route_add(&r_cfg) : ip6_route_del(&r_cfg);
2449 [ # # ]: 0 : if (err) {
2450 : : last_err = err;
2451 : : /* If we are trying to remove a route, do not stop the
2452 : : * loop when ip6_route_del() fails (because next hop is
2453 : : * already gone), we should try to remove all next hops.
2454 : : */
2455 [ # # ]: 0 : if (add) {
2456 : : /* If add fails, we should try to delete all
2457 : : * next hops that have been already added.
2458 : : */
2459 : : add = 0;
2460 : : goto beginning;
2461 : : }
2462 : : }
2463 : : /* Because each route is added like a single route we remove
2464 : : * this flag after the first nexthop (if there is a collision,
2465 : : * we have already fail to add the first nexthop:
2466 : : * fib6_add_rt2node() has reject it).
2467 : : */
2468 : 0 : cfg->fc_nlinfo.nlh->nlmsg_flags &= ~NLM_F_EXCL;
2469 : : rtnh = rtnh_next(rtnh, &remaining);
2470 : : }
2471 : :
2472 : 0 : return last_err;
2473 : : }
2474 : :
2475 : 0 : static int inet6_rtm_delroute(struct sk_buff *skb, struct nlmsghdr* nlh)
2476 : : {
2477 : : struct fib6_config cfg;
2478 : : int err;
2479 : :
2480 : 0 : err = rtm_to_fib6_config(skb, nlh, &cfg);
2481 [ # # ]: 0 : if (err < 0)
2482 : : return err;
2483 : :
2484 [ # # ]: 0 : if (cfg.fc_mp)
2485 : 0 : return ip6_route_multipath(&cfg, 0);
2486 : : else
2487 : 0 : return ip6_route_del(&cfg);
2488 : : }
2489 : :
2490 : 0 : static int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh)
2491 : : {
2492 : : struct fib6_config cfg;
2493 : : int err;
2494 : :
2495 : 0 : err = rtm_to_fib6_config(skb, nlh, &cfg);
2496 [ # # ]: 0 : if (err < 0)
2497 : : return err;
2498 : :
2499 [ # # ]: 0 : if (cfg.fc_mp)
2500 : 0 : return ip6_route_multipath(&cfg, 1);
2501 : : else
2502 : 0 : return ip6_route_add(&cfg);
2503 : : }
2504 : :
2505 : : static inline size_t rt6_nlmsg_size(void)
2506 : : {
2507 : : return NLMSG_ALIGN(sizeof(struct rtmsg))
2508 : : + nla_total_size(16) /* RTA_SRC */
2509 : : + nla_total_size(16) /* RTA_DST */
2510 : : + nla_total_size(16) /* RTA_GATEWAY */
2511 : : + nla_total_size(16) /* RTA_PREFSRC */
2512 : : + nla_total_size(4) /* RTA_TABLE */
2513 : : + nla_total_size(4) /* RTA_IIF */
2514 : : + nla_total_size(4) /* RTA_OIF */
2515 : : + nla_total_size(4) /* RTA_PRIORITY */
2516 : : + RTAX_MAX * nla_total_size(4) /* RTA_METRICS */
2517 : : + nla_total_size(sizeof(struct rta_cacheinfo));
2518 : : }
2519 : :
2520 : 0 : static int rt6_fill_node(struct net *net,
2521 : : struct sk_buff *skb, struct rt6_info *rt,
2522 : : struct in6_addr *dst, struct in6_addr *src,
2523 : : int iif, int type, u32 portid, u32 seq,
2524 : : int prefix, int nowait, unsigned int flags)
2525 : : {
2526 : : struct rtmsg *rtm;
2527 : : struct nlmsghdr *nlh;
2528 : : long expires;
2529 : : u32 table;
2530 : :
2531 [ - + ]: 210 : if (prefix) { /* user wants prefix routes only */
2532 [ # # ]: 0 : if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
2533 : : /* success since this is not a prefix route */
2534 : : return 1;
2535 : : }
2536 : : }
2537 : :
2538 : 210 : nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags);
2539 [ + - ]: 210 : if (!nlh)
2540 : : return -EMSGSIZE;
2541 : :
2542 : : rtm = nlmsg_data(nlh);
2543 : 210 : rtm->rtm_family = AF_INET6;
2544 : 210 : rtm->rtm_dst_len = rt->rt6i_dst.plen;
2545 : 210 : rtm->rtm_src_len = rt->rt6i_src.plen;
2546 : 210 : rtm->rtm_tos = 0;
2547 [ + - ]: 210 : if (rt->rt6i_table)
2548 : 210 : table = rt->rt6i_table->tb6_id;
2549 : : else
2550 : : table = RT6_TABLE_UNSPEC;
2551 : 210 : rtm->rtm_table = table;
2552 [ + ]: 210 : if (nla_put_u32(skb, RTA_TABLE, table))
2553 : : goto nla_put_failure;
2554 [ - + ]: 420 : if (rt->rt6i_flags & RTF_REJECT) {
2555 [ # # # # ]: 0 : switch (rt->dst.error) {
2556 : : case -EINVAL:
2557 : 0 : rtm->rtm_type = RTN_BLACKHOLE;
2558 : : break;
2559 : : case -EACCES:
2560 : 0 : rtm->rtm_type = RTN_PROHIBIT;
2561 : : break;
2562 : : case -EAGAIN:
2563 : 0 : rtm->rtm_type = RTN_THROW;
2564 : : break;
2565 : : default:
2566 : 0 : rtm->rtm_type = RTN_UNREACHABLE;
2567 : : break;
2568 : : }
2569 : : }
2570 [ - + ]: 210 : else if (rt->rt6i_flags & RTF_LOCAL)
2571 : 0 : rtm->rtm_type = RTN_LOCAL;
2572 [ + - ][ - + ]: 210 : else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
2573 : 0 : rtm->rtm_type = RTN_LOCAL;
2574 : : else
2575 : 210 : rtm->rtm_type = RTN_UNICAST;
2576 : 210 : rtm->rtm_flags = 0;
2577 : 210 : rtm->rtm_scope = RT_SCOPE_UNIVERSE;
2578 : 210 : rtm->rtm_protocol = rt->rt6i_protocol;
2579 [ - + ]: 210 : if (rt->rt6i_flags & RTF_DYNAMIC)
2580 : 0 : rtm->rtm_protocol = RTPROT_REDIRECT;
2581 [ - + ]: 210 : else if (rt->rt6i_flags & RTF_ADDRCONF) {
2582 [ # # ]: 0 : if (rt->rt6i_flags & (RTF_DEFAULT | RTF_ROUTEINFO))
2583 : 0 : rtm->rtm_protocol = RTPROT_RA;
2584 : : else
2585 : 0 : rtm->rtm_protocol = RTPROT_KERNEL;
2586 : : }
2587 : :
2588 [ + - ]: 210 : if (rt->rt6i_flags & RTF_CACHE)
2589 : 210 : rtm->rtm_flags |= RTM_F_CLONED;
2590 : :
2591 [ - + ]: 210 : if (dst) {
2592 [ # # ]: 0 : if (nla_put(skb, RTA_DST, 16, dst))
2593 : : goto nla_put_failure;
2594 : 0 : rtm->rtm_dst_len = 128;
2595 [ + - ]: 210 : } else if (rtm->rtm_dst_len)
2596 [ + - ]: 210 : if (nla_put(skb, RTA_DST, 16, &rt->rt6i_dst.addr))
2597 : : goto nla_put_failure;
2598 : : #ifdef CONFIG_IPV6_SUBTREES
2599 : : if (src) {
2600 : : if (nla_put(skb, RTA_SRC, 16, src))
2601 : : goto nla_put_failure;
2602 : : rtm->rtm_src_len = 128;
2603 : : } else if (rtm->rtm_src_len &&
2604 : : nla_put(skb, RTA_SRC, 16, &rt->rt6i_src.addr))
2605 : : goto nla_put_failure;
2606 : : #endif
2607 [ - + ]: 210 : if (iif) {
2608 : : #ifdef CONFIG_IPV6_MROUTE
2609 : : if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr)) {
2610 : : int err = ip6mr_get_route(net, skb, rtm, nowait);
2611 : : if (err <= 0) {
2612 : : if (!nowait) {
2613 : : if (err == 0)
2614 : : return 0;
2615 : : goto nla_put_failure;
2616 : : } else {
2617 : : if (err == -EMSGSIZE)
2618 : : goto nla_put_failure;
2619 : : }
2620 : : }
2621 : : } else
2622 : : #endif
2623 [ # # ]: 0 : if (nla_put_u32(skb, RTA_IIF, iif))
2624 : : goto nla_put_failure;
2625 [ - + ]: 210 : } else if (dst) {
2626 : : struct in6_addr saddr_buf;
2627 [ # # # # ]: 0 : if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0 &&
2628 : 0 : nla_put(skb, RTA_PREFSRC, 16, &saddr_buf))
2629 : : goto nla_put_failure;
2630 : : }
2631 : :
2632 [ # # ]: 0 : if (rt->rt6i_prefsrc.plen) {
2633 : : struct in6_addr saddr_buf;
2634 : 0 : saddr_buf = rt->rt6i_prefsrc.addr;
2635 [ # # ]: 0 : if (nla_put(skb, RTA_PREFSRC, 16, &saddr_buf))
2636 : : goto nla_put_failure;
2637 : : }
2638 : :
2639 [ + - ]: 0 : if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2640 : : goto nla_put_failure;
2641 : :
2642 [ - + ]: 210 : if (rt->rt6i_flags & RTF_GATEWAY) {
2643 [ # # ]: 0 : if (nla_put(skb, RTA_GATEWAY, 16, &rt->rt6i_gateway) < 0)
2644 : : goto nla_put_failure;
2645 : : }
2646 : :
2647 [ + - + - ]: 420 : if (rt->dst.dev &&
2648 : 210 : nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
2649 : : goto nla_put_failure;
2650 [ + - ]: 210 : if (nla_put_u32(skb, RTA_PRIORITY, rt->rt6i_metric))
2651 : : goto nla_put_failure;
2652 : :
2653 [ - + ]: 210 : expires = (rt->rt6i_flags & RTF_EXPIRES) ? rt->dst.expires - jiffies : 0;
2654 : :
2655 [ + - ]: 210 : if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires, rt->dst.error) < 0)
2656 : : goto nla_put_failure;
2657 : :
2658 : : return nlmsg_end(skb, nlh);
2659 : :
2660 : : nla_put_failure:
2661 : : nlmsg_cancel(skb, nlh);
2662 : : return -EMSGSIZE;
2663 : : }
2664 : :
2665 : 0 : int rt6_dump_route(struct rt6_info *rt, void *p_arg)
2666 : : {
2667 : : struct rt6_rtnl_dump_arg *arg = (struct rt6_rtnl_dump_arg *) p_arg;
2668 : : int prefix;
2669 : :
2670 [ # # ]: 0 : if (nlmsg_len(arg->cb->nlh) >= sizeof(struct rtmsg)) {
2671 : : struct rtmsg *rtm = nlmsg_data(arg->cb->nlh);
2672 : 0 : prefix = (rtm->rtm_flags & RTM_F_PREFIX) != 0;
2673 : : } else
2674 : : prefix = 0;
2675 : :
2676 : 0 : return rt6_fill_node(arg->net,
2677 : : arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
2678 : 0 : NETLINK_CB(arg->cb->skb).portid, arg->cb->nlh->nlmsg_seq,
2679 : : prefix, 0, NLM_F_MULTI);
2680 : : }
2681 : :
2682 : 0 : static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh)
2683 : : {
2684 : : struct net *net = sock_net(in_skb->sk);
2685 : : struct nlattr *tb[RTA_MAX+1];
2686 : : struct rt6_info *rt;
2687 : : struct sk_buff *skb;
2688 : : struct rtmsg *rtm;
2689 : : struct flowi6 fl6;
2690 : : int err, iif = 0, oif = 0;
2691 : :
2692 : : err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy);
2693 [ # # ]: 0 : if (err < 0)
2694 : : goto errout;
2695 : :
2696 : : err = -EINVAL;
2697 : 0 : memset(&fl6, 0, sizeof(fl6));
2698 : :
2699 [ # # ]: 0 : if (tb[RTA_SRC]) {
2700 [ # # ]: 0 : if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
2701 : : goto errout;
2702 : :
2703 : 0 : fl6.saddr = *(struct in6_addr *)nla_data(tb[RTA_SRC]);
2704 : : }
2705 : :
2706 [ # # ]: 0 : if (tb[RTA_DST]) {
2707 [ # # ]: 0 : if (nla_len(tb[RTA_DST]) < sizeof(struct in6_addr))
2708 : : goto errout;
2709 : :
2710 : 0 : fl6.daddr = *(struct in6_addr *)nla_data(tb[RTA_DST]);
2711 : : }
2712 : :
2713 [ # # ]: 0 : if (tb[RTA_IIF])
2714 : 0 : iif = nla_get_u32(tb[RTA_IIF]);
2715 : :
2716 [ # # ]: 0 : if (tb[RTA_OIF])
2717 : 0 : oif = nla_get_u32(tb[RTA_OIF]);
2718 : :
2719 [ # # ]: 0 : if (iif) {
2720 : : struct net_device *dev;
2721 : : int flags = 0;
2722 : :
2723 : 0 : dev = __dev_get_by_index(net, iif);
2724 [ # # ]: 0 : if (!dev) {
2725 : : err = -ENODEV;
2726 : : goto errout;
2727 : : }
2728 : :
2729 : 0 : fl6.flowi6_iif = iif;
2730 : :
2731 [ # # ]: 0 : if (!ipv6_addr_any(&fl6.saddr))
2732 : : flags |= RT6_LOOKUP_F_HAS_SADDR;
2733 : :
2734 : 0 : rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
2735 : : flags);
2736 : : } else {
2737 : 0 : fl6.flowi6_oif = oif;
2738 : :
2739 : 0 : rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
2740 : : }
2741 : :
2742 : : skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
2743 [ # # ]: 0 : if (!skb) {
2744 : : ip6_rt_put(rt);
2745 : : err = -ENOBUFS;
2746 : 0 : goto errout;
2747 : : }
2748 : :
2749 : : /* Reserve room for dummy headers, this skb can pass
2750 : : through good chunk of routing engine.
2751 : : */
2752 : : skb_reset_mac_header(skb);
2753 : : skb_reserve(skb, MAX_HEADER + sizeof(struct ipv6hdr));
2754 : :
2755 : 0 : skb_dst_set(skb, &rt->dst);
2756 : :
2757 : 0 : err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
2758 : : RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
2759 : : nlh->nlmsg_seq, 0, 0, 0);
2760 [ # # ]: 0 : if (err < 0) {
2761 : 0 : kfree_skb(skb);
2762 : 0 : goto errout;
2763 : : }
2764 : :
2765 : 0 : err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
2766 : : errout:
2767 : 0 : return err;
2768 : : }
2769 : :
2770 : 0 : void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2771 : : {
2772 : : struct sk_buff *skb;
2773 : 210 : struct net *net = info->nl_net;
2774 : : u32 seq;
2775 : : int err;
2776 : :
2777 : : err = -ENOBUFS;
2778 [ - + ]: 210 : seq = info->nlh ? info->nlh->nlmsg_seq : 0;
2779 : :
2780 : : skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
2781 [ + - ]: 210 : if (!skb)
2782 : : goto errout;
2783 : :
2784 : 210 : err = rt6_fill_node(net, skb, rt, NULL, NULL, 0,
2785 : : event, info->portid, seq, 0, 0, 0);
2786 [ - + ]: 210 : if (err < 0) {
2787 : : /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
2788 [ # # ]: 0 : WARN_ON(err == -EMSGSIZE);
2789 : 0 : kfree_skb(skb);
2790 : 0 : goto errout;
2791 : : }
2792 : 210 : rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
2793 : : info->nlh, gfp_any());
2794 : 210 : return;
2795 : : errout:
2796 [ # # ]: 0 : if (err < 0)
2797 : 0 : rtnl_set_sk_err(net, RTNLGRP_IPV6_ROUTE, err);
2798 : : }
2799 : :
2800 : 0 : static int ip6_route_dev_notify(struct notifier_block *this,
2801 : : unsigned long event, void *ptr)
2802 : : {
2803 : : struct net_device *dev = netdev_notifier_info_to_dev(ptr);
2804 : : struct net *net = dev_net(dev);
2805 : :
2806 [ # # ][ # # ]: 0 : if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
2807 : 0 : net->ipv6.ip6_null_entry->dst.dev = dev;
2808 : 0 : net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
2809 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
2810 : : net->ipv6.ip6_prohibit_entry->dst.dev = dev;
2811 : : net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
2812 : : net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
2813 : : net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
2814 : : #endif
2815 : : }
2816 : :
2817 : 0 : return NOTIFY_OK;
2818 : : }
2819 : :
2820 : : /*
2821 : : * /proc
2822 : : */
2823 : :
2824 : : #ifdef CONFIG_PROC_FS
2825 : :
2826 : : static const struct file_operations ipv6_route_proc_fops = {
2827 : : .owner = THIS_MODULE,
2828 : : .open = ipv6_route_open,
2829 : : .read = seq_read,
2830 : : .llseek = seq_lseek,
2831 : : .release = seq_release_net,
2832 : : };
2833 : :
2834 : 0 : static int rt6_stats_seq_show(struct seq_file *seq, void *v)
2835 : : {
2836 : 1 : struct net *net = (struct net *)seq->private;
2837 : 1 : seq_printf(seq, "%04x %04x %04x %04x %04x %04x %04x\n",
2838 : 1 : net->ipv6.rt6_stats->fib_nodes,
2839 : : net->ipv6.rt6_stats->fib_route_nodes,
2840 : : net->ipv6.rt6_stats->fib_rt_alloc,
2841 : : net->ipv6.rt6_stats->fib_rt_entries,
2842 : : net->ipv6.rt6_stats->fib_rt_cache,
2843 : : dst_entries_get_slow(&net->ipv6.ip6_dst_ops),
2844 : 1 : net->ipv6.rt6_stats->fib_discarded_routes);
2845 : :
2846 : 1 : return 0;
2847 : : }
2848 : :
2849 : 0 : static int rt6_stats_seq_open(struct inode *inode, struct file *file)
2850 : : {
2851 : 1 : return single_open_net(inode, file, rt6_stats_seq_show);
2852 : : }
2853 : :
2854 : : static const struct file_operations rt6_stats_seq_fops = {
2855 : : .owner = THIS_MODULE,
2856 : : .open = rt6_stats_seq_open,
2857 : : .read = seq_read,
2858 : : .llseek = seq_lseek,
2859 : : .release = single_release_net,
2860 : : };
2861 : : #endif /* CONFIG_PROC_FS */
2862 : :
2863 : : #ifdef CONFIG_SYSCTL
2864 : :
2865 : : static
2866 : 0 : int ipv6_sysctl_rtcache_flush(struct ctl_table *ctl, int write,
2867 : : void __user *buffer, size_t *lenp, loff_t *ppos)
2868 : : {
2869 : : struct net *net;
2870 : : int delay;
2871 [ # # ]: 0 : if (!write)
2872 : : return -EINVAL;
2873 : :
2874 : 0 : net = (struct net *)ctl->extra1;
2875 : 0 : delay = net->ipv6.sysctl.flush_delay;
2876 : 0 : proc_dointvec(ctl, write, buffer, lenp, ppos);
2877 : 0 : fib6_run_gc(delay <= 0 ? 0 : (unsigned long)delay, net, delay > 0);
2878 : 0 : return 0;
2879 : : }
2880 : :
2881 : : struct ctl_table ipv6_route_table_template[] = {
2882 : : {
2883 : : .procname = "flush",
2884 : : .data = &init_net.ipv6.sysctl.flush_delay,
2885 : : .maxlen = sizeof(int),
2886 : : .mode = 0200,
2887 : : .proc_handler = ipv6_sysctl_rtcache_flush
2888 : : },
2889 : : {
2890 : : .procname = "gc_thresh",
2891 : : .data = &ip6_dst_ops_template.gc_thresh,
2892 : : .maxlen = sizeof(int),
2893 : : .mode = 0644,
2894 : : .proc_handler = proc_dointvec,
2895 : : },
2896 : : {
2897 : : .procname = "max_size",
2898 : : .data = &init_net.ipv6.sysctl.ip6_rt_max_size,
2899 : : .maxlen = sizeof(int),
2900 : : .mode = 0644,
2901 : : .proc_handler = proc_dointvec,
2902 : : },
2903 : : {
2904 : : .procname = "gc_min_interval",
2905 : : .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
2906 : : .maxlen = sizeof(int),
2907 : : .mode = 0644,
2908 : : .proc_handler = proc_dointvec_jiffies,
2909 : : },
2910 : : {
2911 : : .procname = "gc_timeout",
2912 : : .data = &init_net.ipv6.sysctl.ip6_rt_gc_timeout,
2913 : : .maxlen = sizeof(int),
2914 : : .mode = 0644,
2915 : : .proc_handler = proc_dointvec_jiffies,
2916 : : },
2917 : : {
2918 : : .procname = "gc_interval",
2919 : : .data = &init_net.ipv6.sysctl.ip6_rt_gc_interval,
2920 : : .maxlen = sizeof(int),
2921 : : .mode = 0644,
2922 : : .proc_handler = proc_dointvec_jiffies,
2923 : : },
2924 : : {
2925 : : .procname = "gc_elasticity",
2926 : : .data = &init_net.ipv6.sysctl.ip6_rt_gc_elasticity,
2927 : : .maxlen = sizeof(int),
2928 : : .mode = 0644,
2929 : : .proc_handler = proc_dointvec,
2930 : : },
2931 : : {
2932 : : .procname = "mtu_expires",
2933 : : .data = &init_net.ipv6.sysctl.ip6_rt_mtu_expires,
2934 : : .maxlen = sizeof(int),
2935 : : .mode = 0644,
2936 : : .proc_handler = proc_dointvec_jiffies,
2937 : : },
2938 : : {
2939 : : .procname = "min_adv_mss",
2940 : : .data = &init_net.ipv6.sysctl.ip6_rt_min_advmss,
2941 : : .maxlen = sizeof(int),
2942 : : .mode = 0644,
2943 : : .proc_handler = proc_dointvec,
2944 : : },
2945 : : {
2946 : : .procname = "gc_min_interval_ms",
2947 : : .data = &init_net.ipv6.sysctl.ip6_rt_gc_min_interval,
2948 : : .maxlen = sizeof(int),
2949 : : .mode = 0644,
2950 : : .proc_handler = proc_dointvec_ms_jiffies,
2951 : : },
2952 : : { }
2953 : : };
2954 : :
2955 : 0 : struct ctl_table * __net_init ipv6_route_sysctl_init(struct net *net)
2956 : : {
2957 : : struct ctl_table *table;
2958 : :
2959 : 0 : table = kmemdup(ipv6_route_table_template,
2960 : : sizeof(ipv6_route_table_template),
2961 : : GFP_KERNEL);
2962 : :
2963 [ # # ]: 0 : if (table) {
2964 : 0 : table[0].data = &net->ipv6.sysctl.flush_delay;
2965 : 0 : table[0].extra1 = net;
2966 : 0 : table[1].data = &net->ipv6.ip6_dst_ops.gc_thresh;
2967 : 0 : table[2].data = &net->ipv6.sysctl.ip6_rt_max_size;
2968 : 0 : table[3].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
2969 : 0 : table[4].data = &net->ipv6.sysctl.ip6_rt_gc_timeout;
2970 : 0 : table[5].data = &net->ipv6.sysctl.ip6_rt_gc_interval;
2971 : 0 : table[6].data = &net->ipv6.sysctl.ip6_rt_gc_elasticity;
2972 : 0 : table[7].data = &net->ipv6.sysctl.ip6_rt_mtu_expires;
2973 : 0 : table[8].data = &net->ipv6.sysctl.ip6_rt_min_advmss;
2974 : 0 : table[9].data = &net->ipv6.sysctl.ip6_rt_gc_min_interval;
2975 : :
2976 : : /* Don't export sysctls to unprivileged users */
2977 [ # # ]: 0 : if (net->user_ns != &init_user_ns)
2978 : 0 : table[0].procname = NULL;
2979 : : }
2980 : :
2981 : 0 : return table;
2982 : : }
2983 : : #endif
2984 : :
2985 : 0 : static int __net_init ip6_route_net_init(struct net *net)
2986 : : {
2987 : : int ret = -ENOMEM;
2988 : :
2989 : 0 : memcpy(&net->ipv6.ip6_dst_ops, &ip6_dst_ops_template,
2990 : : sizeof(net->ipv6.ip6_dst_ops));
2991 : :
2992 [ # # ]: 0 : if (dst_entries_init(&net->ipv6.ip6_dst_ops) < 0)
2993 : : goto out_ip6_dst_ops;
2994 : :
2995 : 0 : net->ipv6.ip6_null_entry = kmemdup(&ip6_null_entry_template,
2996 : : sizeof(*net->ipv6.ip6_null_entry),
2997 : : GFP_KERNEL);
2998 [ # # ]: 0 : if (!net->ipv6.ip6_null_entry)
2999 : : goto out_ip6_dst_entries;
3000 : 0 : net->ipv6.ip6_null_entry->dst.path =
3001 : : (struct dst_entry *)net->ipv6.ip6_null_entry;
3002 : 0 : net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops;
3003 : 0 : dst_init_metrics(&net->ipv6.ip6_null_entry->dst,
3004 : : ip6_template_metrics, true);
3005 : :
3006 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
3007 : : net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template,
3008 : : sizeof(*net->ipv6.ip6_prohibit_entry),
3009 : : GFP_KERNEL);
3010 : : if (!net->ipv6.ip6_prohibit_entry)
3011 : : goto out_ip6_null_entry;
3012 : : net->ipv6.ip6_prohibit_entry->dst.path =
3013 : : (struct dst_entry *)net->ipv6.ip6_prohibit_entry;
3014 : : net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops;
3015 : : dst_init_metrics(&net->ipv6.ip6_prohibit_entry->dst,
3016 : : ip6_template_metrics, true);
3017 : :
3018 : : net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template,
3019 : : sizeof(*net->ipv6.ip6_blk_hole_entry),
3020 : : GFP_KERNEL);
3021 : : if (!net->ipv6.ip6_blk_hole_entry)
3022 : : goto out_ip6_prohibit_entry;
3023 : : net->ipv6.ip6_blk_hole_entry->dst.path =
3024 : : (struct dst_entry *)net->ipv6.ip6_blk_hole_entry;
3025 : : net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops;
3026 : : dst_init_metrics(&net->ipv6.ip6_blk_hole_entry->dst,
3027 : : ip6_template_metrics, true);
3028 : : #endif
3029 : :
3030 : 0 : net->ipv6.sysctl.flush_delay = 0;
3031 : 0 : net->ipv6.sysctl.ip6_rt_max_size = 4096;
3032 : 0 : net->ipv6.sysctl.ip6_rt_gc_min_interval = HZ / 2;
3033 : 0 : net->ipv6.sysctl.ip6_rt_gc_timeout = 60*HZ;
3034 : 0 : net->ipv6.sysctl.ip6_rt_gc_interval = 30*HZ;
3035 : 0 : net->ipv6.sysctl.ip6_rt_gc_elasticity = 9;
3036 : 0 : net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ;
3037 : 0 : net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40;
3038 : :
3039 : 0 : net->ipv6.ip6_rt_gc_expire = 30*HZ;
3040 : :
3041 : : ret = 0;
3042 : : out:
3043 : 0 : return ret;
3044 : :
3045 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
3046 : : out_ip6_prohibit_entry:
3047 : : kfree(net->ipv6.ip6_prohibit_entry);
3048 : : out_ip6_null_entry:
3049 : : kfree(net->ipv6.ip6_null_entry);
3050 : : #endif
3051 : : out_ip6_dst_entries:
3052 : : dst_entries_destroy(&net->ipv6.ip6_dst_ops);
3053 : : out_ip6_dst_ops:
3054 : : goto out;
3055 : : }
3056 : :
3057 : 0 : static void __net_exit ip6_route_net_exit(struct net *net)
3058 : : {
3059 : 0 : kfree(net->ipv6.ip6_null_entry);
3060 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
3061 : : kfree(net->ipv6.ip6_prohibit_entry);
3062 : : kfree(net->ipv6.ip6_blk_hole_entry);
3063 : : #endif
3064 : : dst_entries_destroy(&net->ipv6.ip6_dst_ops);
3065 : 0 : }
3066 : :
3067 : 0 : static int __net_init ip6_route_net_init_late(struct net *net)
3068 : : {
3069 : : #ifdef CONFIG_PROC_FS
3070 : 0 : proc_create("ipv6_route", 0, net->proc_net, &ipv6_route_proc_fops);
3071 : 0 : proc_create("rt6_stats", S_IRUGO, net->proc_net, &rt6_stats_seq_fops);
3072 : : #endif
3073 : 0 : return 0;
3074 : : }
3075 : :
3076 : 0 : static void __net_exit ip6_route_net_exit_late(struct net *net)
3077 : : {
3078 : : #ifdef CONFIG_PROC_FS
3079 : 0 : remove_proc_entry("ipv6_route", net->proc_net);
3080 : 0 : remove_proc_entry("rt6_stats", net->proc_net);
3081 : : #endif
3082 : 0 : }
3083 : :
3084 : : static struct pernet_operations ip6_route_net_ops = {
3085 : : .init = ip6_route_net_init,
3086 : : .exit = ip6_route_net_exit,
3087 : : };
3088 : :
3089 : 0 : static int __net_init ipv6_inetpeer_init(struct net *net)
3090 : : {
3091 : : struct inet_peer_base *bp = kmalloc(sizeof(*bp), GFP_KERNEL);
3092 : :
3093 [ # # ]: 0 : if (!bp)
3094 : : return -ENOMEM;
3095 : 0 : inet_peer_base_init(bp);
3096 : 0 : net->ipv6.peers = bp;
3097 : 0 : return 0;
3098 : : }
3099 : :
3100 : 0 : static void __net_exit ipv6_inetpeer_exit(struct net *net)
3101 : : {
3102 : 0 : struct inet_peer_base *bp = net->ipv6.peers;
3103 : :
3104 : 0 : net->ipv6.peers = NULL;
3105 : 0 : inetpeer_invalidate_tree(bp);
3106 : 0 : kfree(bp);
3107 : 0 : }
3108 : :
3109 : : static struct pernet_operations ipv6_inetpeer_ops = {
3110 : : .init = ipv6_inetpeer_init,
3111 : : .exit = ipv6_inetpeer_exit,
3112 : : };
3113 : :
3114 : : static struct pernet_operations ip6_route_net_late_ops = {
3115 : : .init = ip6_route_net_init_late,
3116 : : .exit = ip6_route_net_exit_late,
3117 : : };
3118 : :
3119 : : static struct notifier_block ip6_route_dev_notifier = {
3120 : : .notifier_call = ip6_route_dev_notify,
3121 : : .priority = 0,
3122 : : };
3123 : :
3124 : 0 : int __init ip6_route_init(void)
3125 : : {
3126 : : int ret;
3127 : :
3128 : : ret = -ENOMEM;
3129 : 0 : ip6_dst_ops_template.kmem_cachep =
3130 : 0 : kmem_cache_create("ip6_dst_cache", sizeof(struct rt6_info), 0,
3131 : : SLAB_HWCACHE_ALIGN, NULL);
3132 [ # # ]: 0 : if (!ip6_dst_ops_template.kmem_cachep)
3133 : : goto out;
3134 : :
3135 : : ret = dst_entries_init(&ip6_dst_blackhole_ops);
3136 [ # # ]: 0 : if (ret)
3137 : : goto out_kmem_cache;
3138 : :
3139 : 0 : ret = register_pernet_subsys(&ipv6_inetpeer_ops);
3140 [ # # ]: 0 : if (ret)
3141 : : goto out_dst_entries;
3142 : :
3143 : 0 : ret = register_pernet_subsys(&ip6_route_net_ops);
3144 [ # # ]: 0 : if (ret)
3145 : : goto out_register_inetpeer;
3146 : :
3147 : 0 : ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep;
3148 : :
3149 : : /* Registering of the loopback is done before this portion of code,
3150 : : * the loopback reference in rt6_info will not be taken, do it
3151 : : * manually for init_net */
3152 : 0 : init_net.ipv6.ip6_null_entry->dst.dev = init_net.loopback_dev;
3153 : 0 : init_net.ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3154 : : #ifdef CONFIG_IPV6_MULTIPLE_TABLES
3155 : : init_net.ipv6.ip6_prohibit_entry->dst.dev = init_net.loopback_dev;
3156 : : init_net.ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3157 : : init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev;
3158 : : init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev);
3159 : : #endif
3160 : 0 : ret = fib6_init();
3161 [ # # ]: 0 : if (ret)
3162 : : goto out_register_subsys;
3163 : :
3164 : 0 : ret = xfrm6_init();
3165 [ # # ]: 0 : if (ret)
3166 : : goto out_fib6_init;
3167 : :
3168 : : ret = fib6_rules_init();
3169 : : if (ret)
3170 : : goto xfrm6_init;
3171 : :
3172 : 0 : ret = register_pernet_subsys(&ip6_route_net_late_ops);
3173 [ # # ]: 0 : if (ret)
3174 : : goto fib6_rules_init;
3175 : :
3176 : : ret = -ENOBUFS;
3177 [ # # # # ]: 0 : if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
3178 [ # # ]: 0 : __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
3179 : 0 : __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
3180 : : goto out_register_late_subsys;
3181 : :
3182 : 0 : ret = register_netdevice_notifier(&ip6_route_dev_notifier);
3183 [ # # ]: 0 : if (ret)
3184 : : goto out_register_late_subsys;
3185 : :
3186 : : out:
3187 : 0 : return ret;
3188 : :
3189 : : out_register_late_subsys:
3190 : 0 : unregister_pernet_subsys(&ip6_route_net_late_ops);
3191 : : fib6_rules_init:
3192 : : fib6_rules_cleanup();
3193 : : xfrm6_init:
3194 : 0 : xfrm6_fini();
3195 : : out_fib6_init:
3196 : 0 : fib6_gc_cleanup();
3197 : : out_register_subsys:
3198 : 0 : unregister_pernet_subsys(&ip6_route_net_ops);
3199 : : out_register_inetpeer:
3200 : 0 : unregister_pernet_subsys(&ipv6_inetpeer_ops);
3201 : : out_dst_entries:
3202 : : dst_entries_destroy(&ip6_dst_blackhole_ops);
3203 : : out_kmem_cache:
3204 : 0 : kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
3205 : 0 : goto out;
3206 : : }
3207 : :
3208 : 0 : void ip6_route_cleanup(void)
3209 : : {
3210 : 0 : unregister_netdevice_notifier(&ip6_route_dev_notifier);
3211 : 0 : unregister_pernet_subsys(&ip6_route_net_late_ops);
3212 : : fib6_rules_cleanup();
3213 : 0 : xfrm6_fini();
3214 : 0 : fib6_gc_cleanup();
3215 : 0 : unregister_pernet_subsys(&ipv6_inetpeer_ops);
3216 : 0 : unregister_pernet_subsys(&ip6_route_net_ops);
3217 : : dst_entries_destroy(&ip6_dst_blackhole_ops);
3218 : 0 : kmem_cache_destroy(ip6_dst_ops_template.kmem_cachep);
3219 : 0 : }
|