aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c96
1 files changed, 56 insertions, 40 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 854e4018d205..d1ddbc6ddac5 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -222,7 +222,7 @@ static const u32 ip6_template_metrics[RTAX_MAX] = {
222 [RTAX_HOPLIMIT - 1] = 255, 222 [RTAX_HOPLIMIT - 1] = 255,
223}; 223};
224 224
225static struct rt6_info ip6_null_entry_template = { 225static const struct rt6_info ip6_null_entry_template = {
226 .dst = { 226 .dst = {
227 .__refcnt = ATOMIC_INIT(1), 227 .__refcnt = ATOMIC_INIT(1),
228 .__use = 1, 228 .__use = 1,
@@ -242,7 +242,7 @@ static struct rt6_info ip6_null_entry_template = {
242static int ip6_pkt_prohibit(struct sk_buff *skb); 242static int ip6_pkt_prohibit(struct sk_buff *skb);
243static int ip6_pkt_prohibit_out(struct sk_buff *skb); 243static int ip6_pkt_prohibit_out(struct sk_buff *skb);
244 244
245static struct rt6_info ip6_prohibit_entry_template = { 245static const struct rt6_info ip6_prohibit_entry_template = {
246 .dst = { 246 .dst = {
247 .__refcnt = ATOMIC_INIT(1), 247 .__refcnt = ATOMIC_INIT(1),
248 .__use = 1, 248 .__use = 1,
@@ -257,7 +257,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
257 .rt6i_ref = ATOMIC_INIT(1), 257 .rt6i_ref = ATOMIC_INIT(1),
258}; 258};
259 259
260static struct rt6_info ip6_blk_hole_entry_template = { 260static const struct rt6_info ip6_blk_hole_entry_template = {
261 .dst = { 261 .dst = {
262 .__refcnt = ATOMIC_INIT(1), 262 .__refcnt = ATOMIC_INIT(1),
263 .__use = 1, 263 .__use = 1,
@@ -370,15 +370,11 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
370 370
371static bool rt6_check_expired(const struct rt6_info *rt) 371static bool rt6_check_expired(const struct rt6_info *rt)
372{ 372{
373 struct rt6_info *ort = NULL;
374
375 if (rt->rt6i_flags & RTF_EXPIRES) { 373 if (rt->rt6i_flags & RTF_EXPIRES) {
376 if (time_after(jiffies, rt->dst.expires)) 374 if (time_after(jiffies, rt->dst.expires))
377 return true; 375 return true;
378 } else if (rt->dst.from) { 376 } else if (rt->dst.from) {
379 ort = (struct rt6_info *) rt->dst.from; 377 return rt6_check_expired((struct rt6_info *) rt->dst.from);
380 return (ort->rt6i_flags & RTF_EXPIRES) &&
381 time_after(jiffies, ort->dst.expires);
382 } 378 }
383 return false; 379 return false;
384} 380}
@@ -452,10 +448,9 @@ static void rt6_probe(struct rt6_info *rt)
452 * Router Reachability Probe MUST be rate-limited 448 * Router Reachability Probe MUST be rate-limited
453 * to no more than one per minute. 449 * to no more than one per minute.
454 */ 450 */
455 rcu_read_lock();
456 neigh = rt ? rt->n : NULL; 451 neigh = rt ? rt->n : NULL;
457 if (!neigh || (neigh->nud_state & NUD_VALID)) 452 if (!neigh || (neigh->nud_state & NUD_VALID))
458 goto out; 453 return;
459 read_lock_bh(&neigh->lock); 454 read_lock_bh(&neigh->lock);
460 if (!(neigh->nud_state & NUD_VALID) && 455 if (!(neigh->nud_state & NUD_VALID) &&
461 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { 456 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -471,8 +466,6 @@ static void rt6_probe(struct rt6_info *rt)
471 } else { 466 } else {
472 read_unlock_bh(&neigh->lock); 467 read_unlock_bh(&neigh->lock);
473 } 468 }
474out:
475 rcu_read_unlock();
476} 469}
477#else 470#else
478static inline void rt6_probe(struct rt6_info *rt) 471static inline void rt6_probe(struct rt6_info *rt)
@@ -499,7 +492,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
499 struct neighbour *neigh; 492 struct neighbour *neigh;
500 int m; 493 int m;
501 494
502 rcu_read_lock();
503 neigh = rt->n; 495 neigh = rt->n;
504 if (rt->rt6i_flags & RTF_NONEXTHOP || 496 if (rt->rt6i_flags & RTF_NONEXTHOP ||
505 !(rt->rt6i_flags & RTF_GATEWAY)) 497 !(rt->rt6i_flags & RTF_GATEWAY))
@@ -517,7 +509,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
517 read_unlock_bh(&neigh->lock); 509 read_unlock_bh(&neigh->lock);
518 } else 510 } else
519 m = 0; 511 m = 0;
520 rcu_read_unlock();
521 return m; 512 return m;
522} 513}
523 514
@@ -966,7 +957,7 @@ struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk,
966{ 957{
967 int flags = 0; 958 int flags = 0;
968 959
969 fl6->flowi6_iif = net->loopback_dev->ifindex; 960 fl6->flowi6_iif = LOOPBACK_IFINDEX;
970 961
971 if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) 962 if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr))
972 flags |= RT6_LOOKUP_F_IFACE; 963 flags |= RT6_LOOKUP_F_IFACE;
@@ -1469,8 +1460,21 @@ int ip6_route_add(struct fib6_config *cfg)
1469 } 1460 }
1470 rt->dst.output = ip6_pkt_discard_out; 1461 rt->dst.output = ip6_pkt_discard_out;
1471 rt->dst.input = ip6_pkt_discard; 1462 rt->dst.input = ip6_pkt_discard;
1472 rt->dst.error = -ENETUNREACH;
1473 rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; 1463 rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
1464 switch (cfg->fc_type) {
1465 case RTN_BLACKHOLE:
1466 rt->dst.error = -EINVAL;
1467 break;
1468 case RTN_PROHIBIT:
1469 rt->dst.error = -EACCES;
1470 break;
1471 case RTN_THROW:
1472 rt->dst.error = -EAGAIN;
1473 break;
1474 default:
1475 rt->dst.error = -ENETUNREACH;
1476 break;
1477 }
1474 goto install_route; 1478 goto install_route;
1475 } 1479 }
1476 1480
@@ -1835,7 +1839,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
1835 if (!table) 1839 if (!table)
1836 return NULL; 1840 return NULL;
1837 1841
1838 write_lock_bh(&table->tb6_lock); 1842 read_lock_bh(&table->tb6_lock);
1839 fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0); 1843 fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0);
1840 if (!fn) 1844 if (!fn)
1841 goto out; 1845 goto out;
@@ -1851,7 +1855,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net,
1851 break; 1855 break;
1852 } 1856 }
1853out: 1857out:
1854 write_unlock_bh(&table->tb6_lock); 1858 read_unlock_bh(&table->tb6_lock);
1855 return rt; 1859 return rt;
1856} 1860}
1857 1861
@@ -1867,7 +1871,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net,
1867 .fc_dst_len = prefixlen, 1871 .fc_dst_len = prefixlen,
1868 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | 1872 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO |
1869 RTF_UP | RTF_PREF(pref), 1873 RTF_UP | RTF_PREF(pref),
1870 .fc_nlinfo.pid = 0, 1874 .fc_nlinfo.portid = 0,
1871 .fc_nlinfo.nlh = NULL, 1875 .fc_nlinfo.nlh = NULL,
1872 .fc_nlinfo.nl_net = net, 1876 .fc_nlinfo.nl_net = net,
1873 }; 1877 };
@@ -1894,7 +1898,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
1894 if (!table) 1898 if (!table)
1895 return NULL; 1899 return NULL;
1896 1900
1897 write_lock_bh(&table->tb6_lock); 1901 read_lock_bh(&table->tb6_lock);
1898 for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { 1902 for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) {
1899 if (dev == rt->dst.dev && 1903 if (dev == rt->dst.dev &&
1900 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && 1904 ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) &&
@@ -1903,7 +1907,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev
1903 } 1907 }
1904 if (rt) 1908 if (rt)
1905 dst_hold(&rt->dst); 1909 dst_hold(&rt->dst);
1906 write_unlock_bh(&table->tb6_lock); 1910 read_unlock_bh(&table->tb6_lock);
1907 return rt; 1911 return rt;
1908} 1912}
1909 1913
@@ -1917,7 +1921,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr,
1917 .fc_ifindex = dev->ifindex, 1921 .fc_ifindex = dev->ifindex,
1918 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | 1922 .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT |
1919 RTF_UP | RTF_EXPIRES | RTF_PREF(pref), 1923 RTF_UP | RTF_EXPIRES | RTF_PREF(pref),
1920 .fc_nlinfo.pid = 0, 1924 .fc_nlinfo.portid = 0,
1921 .fc_nlinfo.nlh = NULL, 1925 .fc_nlinfo.nlh = NULL,
1922 .fc_nlinfo.nl_net = dev_net(dev), 1926 .fc_nlinfo.nl_net = dev_net(dev),
1923 }; 1927 };
@@ -2266,14 +2270,18 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
2266 cfg->fc_src_len = rtm->rtm_src_len; 2270 cfg->fc_src_len = rtm->rtm_src_len;
2267 cfg->fc_flags = RTF_UP; 2271 cfg->fc_flags = RTF_UP;
2268 cfg->fc_protocol = rtm->rtm_protocol; 2272 cfg->fc_protocol = rtm->rtm_protocol;
2273 cfg->fc_type = rtm->rtm_type;
2269 2274
2270 if (rtm->rtm_type == RTN_UNREACHABLE) 2275 if (rtm->rtm_type == RTN_UNREACHABLE ||
2276 rtm->rtm_type == RTN_BLACKHOLE ||
2277 rtm->rtm_type == RTN_PROHIBIT ||
2278 rtm->rtm_type == RTN_THROW)
2271 cfg->fc_flags |= RTF_REJECT; 2279 cfg->fc_flags |= RTF_REJECT;
2272 2280
2273 if (rtm->rtm_type == RTN_LOCAL) 2281 if (rtm->rtm_type == RTN_LOCAL)
2274 cfg->fc_flags |= RTF_LOCAL; 2282 cfg->fc_flags |= RTF_LOCAL;
2275 2283
2276 cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; 2284 cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
2277 cfg->fc_nlinfo.nlh = nlh; 2285 cfg->fc_nlinfo.nlh = nlh;
2278 cfg->fc_nlinfo.nl_net = sock_net(skb->sk); 2286 cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
2279 2287
@@ -2364,7 +2372,7 @@ static inline size_t rt6_nlmsg_size(void)
2364static int rt6_fill_node(struct net *net, 2372static int rt6_fill_node(struct net *net,
2365 struct sk_buff *skb, struct rt6_info *rt, 2373 struct sk_buff *skb, struct rt6_info *rt,
2366 struct in6_addr *dst, struct in6_addr *src, 2374 struct in6_addr *dst, struct in6_addr *src,
2367 int iif, int type, u32 pid, u32 seq, 2375 int iif, int type, u32 portid, u32 seq,
2368 int prefix, int nowait, unsigned int flags) 2376 int prefix, int nowait, unsigned int flags)
2369{ 2377{
2370 struct rtmsg *rtm; 2378 struct rtmsg *rtm;
@@ -2380,7 +2388,7 @@ static int rt6_fill_node(struct net *net,
2380 } 2388 }
2381 } 2389 }
2382 2390
2383 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); 2391 nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags);
2384 if (!nlh) 2392 if (!nlh)
2385 return -EMSGSIZE; 2393 return -EMSGSIZE;
2386 2394
@@ -2396,8 +2404,22 @@ static int rt6_fill_node(struct net *net,
2396 rtm->rtm_table = table; 2404 rtm->rtm_table = table;
2397 if (nla_put_u32(skb, RTA_TABLE, table)) 2405 if (nla_put_u32(skb, RTA_TABLE, table))
2398 goto nla_put_failure; 2406 goto nla_put_failure;
2399 if (rt->rt6i_flags & RTF_REJECT) 2407 if (rt->rt6i_flags & RTF_REJECT) {
2400 rtm->rtm_type = RTN_UNREACHABLE; 2408 switch (rt->dst.error) {
2409 case -EINVAL:
2410 rtm->rtm_type = RTN_BLACKHOLE;
2411 break;
2412 case -EACCES:
2413 rtm->rtm_type = RTN_PROHIBIT;
2414 break;
2415 case -EAGAIN:
2416 rtm->rtm_type = RTN_THROW;
2417 break;
2418 default:
2419 rtm->rtm_type = RTN_UNREACHABLE;
2420 break;
2421 }
2422 }
2401 else if (rt->rt6i_flags & RTF_LOCAL) 2423 else if (rt->rt6i_flags & RTF_LOCAL)
2402 rtm->rtm_type = RTN_LOCAL; 2424 rtm->rtm_type = RTN_LOCAL;
2403 else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) 2425 else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK))
@@ -2470,15 +2492,11 @@ static int rt6_fill_node(struct net *net,
2470 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) 2492 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2471 goto nla_put_failure; 2493 goto nla_put_failure;
2472 2494
2473 rcu_read_lock();
2474 n = rt->n; 2495 n = rt->n;
2475 if (n) { 2496 if (n) {
2476 if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { 2497 if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0)
2477 rcu_read_unlock();
2478 goto nla_put_failure; 2498 goto nla_put_failure;
2479 }
2480 } 2499 }
2481 rcu_read_unlock();
2482 2500
2483 if (rt->dst.dev && 2501 if (rt->dst.dev &&
2484 nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) 2502 nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex))
@@ -2511,7 +2529,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
2511 2529
2512 return rt6_fill_node(arg->net, 2530 return rt6_fill_node(arg->net,
2513 arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, 2531 arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE,
2514 NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, 2532 NETLINK_CB(arg->cb->skb).portid, arg->cb->nlh->nlmsg_seq,
2515 prefix, 0, NLM_F_MULTI); 2533 prefix, 0, NLM_F_MULTI);
2516} 2534}
2517 2535
@@ -2591,14 +2609,14 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void
2591 skb_dst_set(skb, &rt->dst); 2609 skb_dst_set(skb, &rt->dst);
2592 2610
2593 err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, 2611 err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
2594 RTM_NEWROUTE, NETLINK_CB(in_skb).pid, 2612 RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
2595 nlh->nlmsg_seq, 0, 0, 0); 2613 nlh->nlmsg_seq, 0, 0, 0);
2596 if (err < 0) { 2614 if (err < 0) {
2597 kfree_skb(skb); 2615 kfree_skb(skb);
2598 goto errout; 2616 goto errout;
2599 } 2617 }
2600 2618
2601 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); 2619 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
2602errout: 2620errout:
2603 return err; 2621 return err;
2604} 2622}
@@ -2618,14 +2636,14 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2618 goto errout; 2636 goto errout;
2619 2637
2620 err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, 2638 err = rt6_fill_node(net, skb, rt, NULL, NULL, 0,
2621 event, info->pid, seq, 0, 0, 0); 2639 event, info->portid, seq, 0, 0, 0);
2622 if (err < 0) { 2640 if (err < 0) {
2623 /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ 2641 /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
2624 WARN_ON(err == -EMSGSIZE); 2642 WARN_ON(err == -EMSGSIZE);
2625 kfree_skb(skb); 2643 kfree_skb(skb);
2626 goto errout; 2644 goto errout;
2627 } 2645 }
2628 rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, 2646 rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE,
2629 info->nlh, gfp_any()); 2647 info->nlh, gfp_any());
2630 return; 2648 return;
2631errout: 2649errout:
@@ -2680,14 +2698,12 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2680#else 2698#else
2681 seq_puts(m, "00000000000000000000000000000000 00 "); 2699 seq_puts(m, "00000000000000000000000000000000 00 ");
2682#endif 2700#endif
2683 rcu_read_lock();
2684 n = rt->n; 2701 n = rt->n;
2685 if (n) { 2702 if (n) {
2686 seq_printf(m, "%pi6", n->primary_key); 2703 seq_printf(m, "%pi6", n->primary_key);
2687 } else { 2704 } else {
2688 seq_puts(m, "00000000000000000000000000000000"); 2705 seq_puts(m, "00000000000000000000000000000000");
2689 } 2706 }
2690 rcu_read_unlock();
2691 seq_printf(m, " %08x %08x %08x %08x %8s\n", 2707 seq_printf(m, " %08x %08x %08x %08x %8s\n",
2692 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), 2708 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
2693 rt->dst.__use, rt->rt6i_flags, 2709 rt->dst.__use, rt->rt6i_flags,