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.c138
1 files changed, 90 insertions, 48 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ef1f086feb..f02fe523bd3 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -72,7 +72,8 @@
72#define RT6_TRACE(x...) do { ; } while (0) 72#define RT6_TRACE(x...) do { ; } while (0)
73#endif 73#endif
74 74
75static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); 75static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
76 const struct in6_addr *dest);
76static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); 77static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
77static unsigned int ip6_default_advmss(const struct dst_entry *dst); 78static unsigned int ip6_default_advmss(const struct dst_entry *dst);
78static unsigned int ip6_default_mtu(const struct dst_entry *dst); 79static unsigned int ip6_default_mtu(const struct dst_entry *dst);
@@ -103,6 +104,9 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
103 struct inet_peer *peer; 104 struct inet_peer *peer;
104 u32 *p = NULL; 105 u32 *p = NULL;
105 106
107 if (!(rt->dst.flags & DST_HOST))
108 return NULL;
109
106 if (!rt->rt6i_peer) 110 if (!rt->rt6i_peer)
107 rt6_bind_peer(rt, 1); 111 rt6_bind_peer(rt, 1);
108 112
@@ -127,6 +131,11 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old)
127 return p; 131 return p;
128} 132}
129 133
134static struct neighbour *ip6_neigh_lookup(const struct dst_entry *dst, const void *daddr)
135{
136 return __neigh_lookup_errno(&nd_tbl, daddr, dst->dev);
137}
138
130static struct dst_ops ip6_dst_ops_template = { 139static struct dst_ops ip6_dst_ops_template = {
131 .family = AF_INET6, 140 .family = AF_INET6,
132 .protocol = cpu_to_be16(ETH_P_IPV6), 141 .protocol = cpu_to_be16(ETH_P_IPV6),
@@ -142,6 +151,7 @@ static struct dst_ops ip6_dst_ops_template = {
142 .link_failure = ip6_link_failure, 151 .link_failure = ip6_link_failure,
143 .update_pmtu = ip6_rt_update_pmtu, 152 .update_pmtu = ip6_rt_update_pmtu,
144 .local_out = __ip6_local_out, 153 .local_out = __ip6_local_out,
154 .neigh_lookup = ip6_neigh_lookup,
145}; 155};
146 156
147static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst) 157static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
@@ -168,6 +178,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
168 .default_advmss = ip6_default_advmss, 178 .default_advmss = ip6_default_advmss,
169 .update_pmtu = ip6_rt_blackhole_update_pmtu, 179 .update_pmtu = ip6_rt_blackhole_update_pmtu,
170 .cow_metrics = ip6_rt_blackhole_cow_metrics, 180 .cow_metrics = ip6_rt_blackhole_cow_metrics,
181 .neigh_lookup = ip6_neigh_lookup,
171}; 182};
172 183
173static const u32 ip6_template_metrics[RTAX_MAX] = { 184static const u32 ip6_template_metrics[RTAX_MAX] = {
@@ -233,7 +244,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops,
233{ 244{
234 struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); 245 struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags);
235 246
236 memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); 247 if (rt != NULL)
248 memset(&rt->rt6i_table, 0,
249 sizeof(*rt) - sizeof(struct dst_entry));
237 250
238 return rt; 251 return rt;
239} 252}
@@ -244,6 +257,9 @@ static void ip6_dst_destroy(struct dst_entry *dst)
244 struct inet6_dev *idev = rt->rt6i_idev; 257 struct inet6_dev *idev = rt->rt6i_idev;
245 struct inet_peer *peer = rt->rt6i_peer; 258 struct inet_peer *peer = rt->rt6i_peer;
246 259
260 if (!(rt->dst.flags & DST_HOST))
261 dst_destroy_metrics_generic(dst);
262
247 if (idev != NULL) { 263 if (idev != NULL) {
248 rt->rt6i_idev = NULL; 264 rt->rt6i_idev = NULL;
249 in6_dev_put(idev); 265 in6_dev_put(idev);
@@ -356,7 +372,7 @@ out:
356#ifdef CONFIG_IPV6_ROUTER_PREF 372#ifdef CONFIG_IPV6_ROUTER_PREF
357static void rt6_probe(struct rt6_info *rt) 373static void rt6_probe(struct rt6_info *rt)
358{ 374{
359 struct neighbour *neigh = rt ? rt->rt6i_nexthop : NULL; 375 struct neighbour *neigh;
360 /* 376 /*
361 * Okay, this does not seem to be appropriate 377 * Okay, this does not seem to be appropriate
362 * for now, however, we need to check if it 378 * for now, however, we need to check if it
@@ -365,8 +381,10 @@ static void rt6_probe(struct rt6_info *rt)
365 * Router Reachability Probe MUST be rate-limited 381 * Router Reachability Probe MUST be rate-limited
366 * to no more than one per minute. 382 * to no more than one per minute.
367 */ 383 */
384 rcu_read_lock();
385 neigh = rt ? dst_get_neighbour(&rt->dst) : NULL;
368 if (!neigh || (neigh->nud_state & NUD_VALID)) 386 if (!neigh || (neigh->nud_state & NUD_VALID))
369 return; 387 goto out;
370 read_lock_bh(&neigh->lock); 388 read_lock_bh(&neigh->lock);
371 if (!(neigh->nud_state & NUD_VALID) && 389 if (!(neigh->nud_state & NUD_VALID) &&
372 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { 390 time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) {
@@ -379,8 +397,11 @@ static void rt6_probe(struct rt6_info *rt)
379 target = (struct in6_addr *)&neigh->primary_key; 397 target = (struct in6_addr *)&neigh->primary_key;
380 addrconf_addr_solict_mult(target, &mcaddr); 398 addrconf_addr_solict_mult(target, &mcaddr);
381 ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL); 399 ndisc_send_ns(rt->rt6i_dev, NULL, target, &mcaddr, NULL);
382 } else 400 } else {
383 read_unlock_bh(&neigh->lock); 401 read_unlock_bh(&neigh->lock);
402 }
403out:
404 rcu_read_unlock();
384} 405}
385#else 406#else
386static inline void rt6_probe(struct rt6_info *rt) 407static inline void rt6_probe(struct rt6_info *rt)
@@ -404,8 +425,11 @@ static inline int rt6_check_dev(struct rt6_info *rt, int oif)
404 425
405static inline int rt6_check_neigh(struct rt6_info *rt) 426static inline int rt6_check_neigh(struct rt6_info *rt)
406{ 427{
407 struct neighbour *neigh = rt->rt6i_nexthop; 428 struct neighbour *neigh;
408 int m; 429 int m;
430
431 rcu_read_lock();
432 neigh = dst_get_neighbour(&rt->dst);
409 if (rt->rt6i_flags & RTF_NONEXTHOP || 433 if (rt->rt6i_flags & RTF_NONEXTHOP ||
410 !(rt->rt6i_flags & RTF_GATEWAY)) 434 !(rt->rt6i_flags & RTF_GATEWAY))
411 m = 1; 435 m = 1;
@@ -422,6 +446,7 @@ static inline int rt6_check_neigh(struct rt6_info *rt)
422 read_unlock_bh(&neigh->lock); 446 read_unlock_bh(&neigh->lock);
423 } else 447 } else
424 m = 0; 448 m = 0;
449 rcu_read_unlock();
425 return m; 450 return m;
426} 451}
427 452
@@ -683,7 +708,8 @@ int ip6_ins_rt(struct rt6_info *rt)
683 return __ip6_ins_rt(rt, &info); 708 return __ip6_ins_rt(rt, &info);
684} 709}
685 710
686static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, 711static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort,
712 const struct in6_addr *daddr,
687 const struct in6_addr *saddr) 713 const struct in6_addr *saddr)
688{ 714{
689 struct rt6_info *rt; 715 struct rt6_info *rt;
@@ -692,23 +718,20 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
692 * Clone the route. 718 * Clone the route.
693 */ 719 */
694 720
695 rt = ip6_rt_copy(ort); 721 rt = ip6_rt_copy(ort, daddr);
696 722
697 if (rt) { 723 if (rt) {
698 struct neighbour *neigh; 724 struct neighbour *neigh;
699 int attempts = !in_softirq(); 725 int attempts = !in_softirq();
700 726
701 if (!(rt->rt6i_flags&RTF_GATEWAY)) { 727 if (!(rt->rt6i_flags&RTF_GATEWAY)) {
702 if (rt->rt6i_dst.plen != 128 && 728 if (ort->rt6i_dst.plen != 128 &&
703 ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) 729 ipv6_addr_equal(&ort->rt6i_dst.addr, daddr))
704 rt->rt6i_flags |= RTF_ANYCAST; 730 rt->rt6i_flags |= RTF_ANYCAST;
705 ipv6_addr_copy(&rt->rt6i_gateway, daddr); 731 ipv6_addr_copy(&rt->rt6i_gateway, daddr);
706 } 732 }
707 733
708 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
709 rt->rt6i_dst.plen = 128;
710 rt->rt6i_flags |= RTF_CACHE; 734 rt->rt6i_flags |= RTF_CACHE;
711 rt->dst.flags |= DST_HOST;
712 735
713#ifdef CONFIG_IPV6_SUBTREES 736#ifdef CONFIG_IPV6_SUBTREES
714 if (rt->rt6i_src.plen && saddr) { 737 if (rt->rt6i_src.plen && saddr) {
@@ -745,22 +768,21 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_add
745 dst_free(&rt->dst); 768 dst_free(&rt->dst);
746 return NULL; 769 return NULL;
747 } 770 }
748 rt->rt6i_nexthop = neigh; 771 dst_set_neighbour(&rt->dst, neigh);
749 772
750 } 773 }
751 774
752 return rt; 775 return rt;
753} 776}
754 777
755static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr) 778static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort,
779 const struct in6_addr *daddr)
756{ 780{
757 struct rt6_info *rt = ip6_rt_copy(ort); 781 struct rt6_info *rt = ip6_rt_copy(ort, daddr);
782
758 if (rt) { 783 if (rt) {
759 ipv6_addr_copy(&rt->rt6i_dst.addr, daddr);
760 rt->rt6i_dst.plen = 128;
761 rt->rt6i_flags |= RTF_CACHE; 784 rt->rt6i_flags |= RTF_CACHE;
762 rt->dst.flags |= DST_HOST; 785 dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst)));
763 rt->rt6i_nexthop = neigh_clone(ort->rt6i_nexthop);
764 } 786 }
765 return rt; 787 return rt;
766} 788}
@@ -794,7 +816,7 @@ restart:
794 dst_hold(&rt->dst); 816 dst_hold(&rt->dst);
795 read_unlock_bh(&table->tb6_lock); 817 read_unlock_bh(&table->tb6_lock);
796 818
797 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 819 if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
798 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); 820 nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr);
799 else if (!(rt->dst.flags & DST_HOST)) 821 else if (!(rt->dst.flags & DST_HOST))
800 nrt = rt6_alloc_clone(rt, &fl6->daddr); 822 nrt = rt6_alloc_clone(rt, &fl6->daddr);
@@ -900,7 +922,10 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori
900 new->input = dst_discard; 922 new->input = dst_discard;
901 new->output = dst_discard; 923 new->output = dst_discard;
902 924
903 dst_copy_metrics(new, &ort->dst); 925 if (dst_metrics_read_only(&ort->dst))
926 new->_metrics = ort->dst._metrics;
927 else
928 dst_copy_metrics(new, &ort->dst);
904 rt->rt6i_idev = ort->rt6i_idev; 929 rt->rt6i_idev = ort->rt6i_idev;
905 if (rt->rt6i_idev) 930 if (rt->rt6i_idev)
906 in6_dev_hold(rt->rt6i_idev); 931 in6_dev_hold(rt->rt6i_idev);
@@ -1057,11 +1082,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
1057 neigh = NULL; 1082 neigh = NULL;
1058 } 1083 }
1059 1084
1060 rt->rt6i_idev = idev; 1085 rt->dst.flags |= DST_HOST;
1061 rt->rt6i_nexthop = neigh; 1086 rt->dst.output = ip6_output;
1087 dst_set_neighbour(&rt->dst, neigh);
1062 atomic_set(&rt->dst.__refcnt, 1); 1088 atomic_set(&rt->dst.__refcnt, 1);
1089 ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
1090 rt->rt6i_dst.plen = 128;
1091 rt->rt6i_idev = idev;
1063 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); 1092 dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255);
1064 rt->dst.output = ip6_output;
1065 1093
1066 spin_lock_bh(&icmp6_dst_lock); 1094 spin_lock_bh(&icmp6_dst_lock);
1067 rt->dst.next = icmp6_dst_gc_list; 1095 rt->dst.next = icmp6_dst_gc_list;
@@ -1239,6 +1267,14 @@ int ip6_route_add(struct fib6_config *cfg)
1239 if (rt->rt6i_dst.plen == 128) 1267 if (rt->rt6i_dst.plen == 128)
1240 rt->dst.flags |= DST_HOST; 1268 rt->dst.flags |= DST_HOST;
1241 1269
1270 if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) {
1271 u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL);
1272 if (!metrics) {
1273 err = -ENOMEM;
1274 goto out;
1275 }
1276 dst_init_metrics(&rt->dst, metrics, 0);
1277 }
1242#ifdef CONFIG_IPV6_SUBTREES 1278#ifdef CONFIG_IPV6_SUBTREES
1243 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); 1279 ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len);
1244 rt->rt6i_src.plen = cfg->fc_src_len; 1280 rt->rt6i_src.plen = cfg->fc_src_len;
@@ -1338,12 +1374,12 @@ int ip6_route_add(struct fib6_config *cfg)
1338 rt->rt6i_prefsrc.plen = 0; 1374 rt->rt6i_prefsrc.plen = 0;
1339 1375
1340 if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { 1376 if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) {
1341 rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); 1377 struct neighbour *n = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev);
1342 if (IS_ERR(rt->rt6i_nexthop)) { 1378 if (IS_ERR(n)) {
1343 err = PTR_ERR(rt->rt6i_nexthop); 1379 err = PTR_ERR(n);
1344 rt->rt6i_nexthop = NULL;
1345 goto out; 1380 goto out;
1346 } 1381 }
1382 dst_set_neighbour(&rt->dst, n);
1347 } 1383 }
1348 1384
1349 rt->rt6i_flags = cfg->fc_flags; 1385 rt->rt6i_flags = cfg->fc_flags;
@@ -1574,10 +1610,10 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
1574 dst_confirm(&rt->dst); 1610 dst_confirm(&rt->dst);
1575 1611
1576 /* Duplicate redirect: silently ignore. */ 1612 /* Duplicate redirect: silently ignore. */
1577 if (neigh == rt->dst.neighbour) 1613 if (neigh == dst_get_neighbour_raw(&rt->dst))
1578 goto out; 1614 goto out;
1579 1615
1580 nrt = ip6_rt_copy(rt); 1616 nrt = ip6_rt_copy(rt, dest);
1581 if (nrt == NULL) 1617 if (nrt == NULL)
1582 goto out; 1618 goto out;
1583 1619
@@ -1585,12 +1621,8 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src,
1585 if (on_link) 1621 if (on_link)
1586 nrt->rt6i_flags &= ~RTF_GATEWAY; 1622 nrt->rt6i_flags &= ~RTF_GATEWAY;
1587 1623
1588 ipv6_addr_copy(&nrt->rt6i_dst.addr, dest);
1589 nrt->rt6i_dst.plen = 128;
1590 nrt->dst.flags |= DST_HOST;
1591
1592 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); 1624 ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key);
1593 nrt->rt6i_nexthop = neigh_clone(neigh); 1625 dst_set_neighbour(&nrt->dst, neigh_clone(neigh));
1594 1626
1595 if (ip6_ins_rt(nrt)) 1627 if (ip6_ins_rt(nrt))
1596 goto out; 1628 goto out;
@@ -1670,7 +1702,7 @@ again:
1670 1. It is connected route. Action: COW 1702 1. It is connected route. Action: COW
1671 2. It is gatewayed route or NONEXTHOP route. Action: clone it. 1703 2. It is gatewayed route or NONEXTHOP route. Action: clone it.
1672 */ 1704 */
1673 if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) 1705 if (!dst_get_neighbour_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP))
1674 nrt = rt6_alloc_cow(rt, daddr, saddr); 1706 nrt = rt6_alloc_cow(rt, daddr, saddr);
1675 else 1707 else
1676 nrt = rt6_alloc_clone(rt, daddr); 1708 nrt = rt6_alloc_clone(rt, daddr);
@@ -1723,7 +1755,8 @@ void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *sad
1723 * Misc support functions 1755 * Misc support functions
1724 */ 1756 */
1725 1757
1726static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) 1758static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
1759 const struct in6_addr *dest)
1727{ 1760{
1728 struct net *net = dev_net(ort->rt6i_dev); 1761 struct net *net = dev_net(ort->rt6i_dev);
1729 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, 1762 struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops,
@@ -1732,7 +1765,10 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1732 if (rt) { 1765 if (rt) {
1733 rt->dst.input = ort->dst.input; 1766 rt->dst.input = ort->dst.input;
1734 rt->dst.output = ort->dst.output; 1767 rt->dst.output = ort->dst.output;
1768 rt->dst.flags |= DST_HOST;
1735 1769
1770 ipv6_addr_copy(&rt->rt6i_dst.addr, dest);
1771 rt->rt6i_dst.plen = 128;
1736 dst_copy_metrics(&rt->dst, &ort->dst); 1772 dst_copy_metrics(&rt->dst, &ort->dst);
1737 rt->dst.error = ort->dst.error; 1773 rt->dst.error = ort->dst.error;
1738 rt->rt6i_idev = ort->rt6i_idev; 1774 rt->rt6i_idev = ort->rt6i_idev;
@@ -1745,7 +1781,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort)
1745 rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES; 1781 rt->rt6i_flags = ort->rt6i_flags & ~RTF_EXPIRES;
1746 rt->rt6i_metric = 0; 1782 rt->rt6i_metric = 0;
1747 1783
1748 memcpy(&rt->rt6i_dst, &ort->rt6i_dst, sizeof(struct rt6key));
1749#ifdef CONFIG_IPV6_SUBTREES 1784#ifdef CONFIG_IPV6_SUBTREES
1750 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key)); 1785 memcpy(&rt->rt6i_src, &ort->rt6i_src, sizeof(struct rt6key));
1751#endif 1786#endif
@@ -2035,7 +2070,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
2035 2070
2036 return ERR_CAST(neigh); 2071 return ERR_CAST(neigh);
2037 } 2072 }
2038 rt->rt6i_nexthop = neigh; 2073 dst_set_neighbour(&rt->dst, neigh);
2039 2074
2040 ipv6_addr_copy(&rt->rt6i_dst.addr, addr); 2075 ipv6_addr_copy(&rt->rt6i_dst.addr, addr);
2041 rt->rt6i_dst.plen = 128; 2076 rt->rt6i_dst.plen = 128;
@@ -2312,6 +2347,7 @@ static int rt6_fill_node(struct net *net,
2312 struct nlmsghdr *nlh; 2347 struct nlmsghdr *nlh;
2313 long expires; 2348 long expires;
2314 u32 table; 2349 u32 table;
2350 struct neighbour *n;
2315 2351
2316 if (prefix) { /* user wants prefix routes only */ 2352 if (prefix) { /* user wants prefix routes only */
2317 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) { 2353 if (!(rt->rt6i_flags & RTF_PREFIX_RT)) {
@@ -2400,8 +2436,11 @@ static int rt6_fill_node(struct net *net,
2400 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) 2436 if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
2401 goto nla_put_failure; 2437 goto nla_put_failure;
2402 2438
2403 if (rt->dst.neighbour) 2439 rcu_read_lock();
2404 NLA_PUT(skb, RTA_GATEWAY, 16, &rt->dst.neighbour->primary_key); 2440 n = dst_get_neighbour(&rt->dst);
2441 if (n)
2442 NLA_PUT(skb, RTA_GATEWAY, 16, &n->primary_key);
2443 rcu_read_unlock();
2405 2444
2406 if (rt->dst.dev) 2445 if (rt->dst.dev)
2407 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex); 2446 NLA_PUT_U32(skb, RTA_OIF, rt->rt6i_dev->ifindex);
@@ -2585,6 +2624,7 @@ struct rt6_proc_arg
2585static int rt6_info_route(struct rt6_info *rt, void *p_arg) 2624static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2586{ 2625{
2587 struct seq_file *m = p_arg; 2626 struct seq_file *m = p_arg;
2627 struct neighbour *n;
2588 2628
2589 seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen); 2629 seq_printf(m, "%pi6 %02x ", &rt->rt6i_dst.addr, rt->rt6i_dst.plen);
2590 2630
@@ -2593,12 +2633,14 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg)
2593#else 2633#else
2594 seq_puts(m, "00000000000000000000000000000000 00 "); 2634 seq_puts(m, "00000000000000000000000000000000 00 ");
2595#endif 2635#endif
2596 2636 rcu_read_lock();
2597 if (rt->rt6i_nexthop) { 2637 n = dst_get_neighbour(&rt->dst);
2598 seq_printf(m, "%pi6", rt->rt6i_nexthop->primary_key); 2638 if (n) {
2639 seq_printf(m, "%pi6", n->primary_key);
2599 } else { 2640 } else {
2600 seq_puts(m, "00000000000000000000000000000000"); 2641 seq_puts(m, "00000000000000000000000000000000");
2601 } 2642 }
2643 rcu_read_unlock();
2602 seq_printf(m, " %08x %08x %08x %08x %8s\n", 2644 seq_printf(m, " %08x %08x %08x %08x %8s\n",
2603 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), 2645 rt->rt6i_metric, atomic_read(&rt->dst.__refcnt),
2604 rt->dst.__use, rt->rt6i_flags, 2646 rt->dst.__use, rt->rt6i_flags,
@@ -2918,9 +2960,9 @@ int __init ip6_route_init(void)
2918 goto xfrm6_init; 2960 goto xfrm6_init;
2919 2961
2920 ret = -ENOBUFS; 2962 ret = -ENOBUFS;
2921 if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL) || 2963 if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) ||
2922 __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL) || 2964 __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) ||
2923 __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL)) 2965 __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL))
2924 goto fib6_rules_init; 2966 goto fib6_rules_init;
2925 2967
2926 ret = register_netdevice_notifier(&ip6_route_dev_notifier); 2968 ret = register_netdevice_notifier(&ip6_route_dev_notifier);