diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 126 |
1 files changed, 74 insertions, 52 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8e80fd279100..7c7e963260e1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -222,11 +222,11 @@ static const u32 ip6_template_metrics[RTAX_MAX] = { | |||
222 | [RTAX_HOPLIMIT - 1] = 255, | 222 | [RTAX_HOPLIMIT - 1] = 255, |
223 | }; | 223 | }; |
224 | 224 | ||
225 | static struct rt6_info ip6_null_entry_template = { | 225 | static 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, |
229 | .obsolete = -1, | 229 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
230 | .error = -ENETUNREACH, | 230 | .error = -ENETUNREACH, |
231 | .input = ip6_pkt_discard, | 231 | .input = ip6_pkt_discard, |
232 | .output = ip6_pkt_discard_out, | 232 | .output = ip6_pkt_discard_out, |
@@ -242,11 +242,11 @@ static struct rt6_info ip6_null_entry_template = { | |||
242 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 242 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
243 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 243 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); |
244 | 244 | ||
245 | static struct rt6_info ip6_prohibit_entry_template = { | 245 | static 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, |
249 | .obsolete = -1, | 249 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
250 | .error = -EACCES, | 250 | .error = -EACCES, |
251 | .input = ip6_pkt_prohibit, | 251 | .input = ip6_pkt_prohibit, |
252 | .output = ip6_pkt_prohibit_out, | 252 | .output = ip6_pkt_prohibit_out, |
@@ -257,11 +257,11 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
257 | .rt6i_ref = ATOMIC_INIT(1), | 257 | .rt6i_ref = ATOMIC_INIT(1), |
258 | }; | 258 | }; |
259 | 259 | ||
260 | static struct rt6_info ip6_blk_hole_entry_template = { | 260 | static 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, |
264 | .obsolete = -1, | 264 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
265 | .error = -EINVAL, | 265 | .error = -EINVAL, |
266 | .input = dst_discard, | 266 | .input = dst_discard, |
267 | .output = dst_discard, | 267 | .output = dst_discard, |
@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, | |||
281 | struct fib6_table *table) | 281 | struct fib6_table *table) |
282 | { | 282 | { |
283 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, | 283 | struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev, |
284 | 0, DST_OBSOLETE_NONE, flags); | 284 | 0, DST_OBSOLETE_FORCE_CHK, flags); |
285 | 285 | ||
286 | if (rt) { | 286 | if (rt) { |
287 | struct dst_entry *dst = &rt->dst; | 287 | struct dst_entry *dst = &rt->dst; |
288 | 288 | ||
289 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); | 289 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); |
290 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); | 290 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); |
291 | rt->rt6i_genid = rt_genid(net); | ||
291 | } | 292 | } |
292 | return rt; | 293 | return rt; |
293 | } | 294 | } |
@@ -369,15 +370,11 @@ static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
369 | 370 | ||
370 | static bool rt6_check_expired(const struct rt6_info *rt) | 371 | static bool rt6_check_expired(const struct rt6_info *rt) |
371 | { | 372 | { |
372 | struct rt6_info *ort = NULL; | ||
373 | |||
374 | if (rt->rt6i_flags & RTF_EXPIRES) { | 373 | if (rt->rt6i_flags & RTF_EXPIRES) { |
375 | if (time_after(jiffies, rt->dst.expires)) | 374 | if (time_after(jiffies, rt->dst.expires)) |
376 | return true; | 375 | return true; |
377 | } else if (rt->dst.from) { | 376 | } else if (rt->dst.from) { |
378 | ort = (struct rt6_info *) rt->dst.from; | 377 | return rt6_check_expired((struct rt6_info *) rt->dst.from); |
379 | return (ort->rt6i_flags & RTF_EXPIRES) && | ||
380 | time_after(jiffies, ort->dst.expires); | ||
381 | } | 378 | } |
382 | return false; | 379 | return false; |
383 | } | 380 | } |
@@ -451,10 +448,9 @@ static void rt6_probe(struct rt6_info *rt) | |||
451 | * Router Reachability Probe MUST be rate-limited | 448 | * Router Reachability Probe MUST be rate-limited |
452 | * to no more than one per minute. | 449 | * to no more than one per minute. |
453 | */ | 450 | */ |
454 | rcu_read_lock(); | ||
455 | neigh = rt ? rt->n : NULL; | 451 | neigh = rt ? rt->n : NULL; |
456 | if (!neigh || (neigh->nud_state & NUD_VALID)) | 452 | if (!neigh || (neigh->nud_state & NUD_VALID)) |
457 | goto out; | 453 | return; |
458 | read_lock_bh(&neigh->lock); | 454 | read_lock_bh(&neigh->lock); |
459 | if (!(neigh->nud_state & NUD_VALID) && | 455 | if (!(neigh->nud_state & NUD_VALID) && |
460 | 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)) { |
@@ -470,8 +466,6 @@ static void rt6_probe(struct rt6_info *rt) | |||
470 | } else { | 466 | } else { |
471 | read_unlock_bh(&neigh->lock); | 467 | read_unlock_bh(&neigh->lock); |
472 | } | 468 | } |
473 | out: | ||
474 | rcu_read_unlock(); | ||
475 | } | 469 | } |
476 | #else | 470 | #else |
477 | static inline void rt6_probe(struct rt6_info *rt) | 471 | static inline void rt6_probe(struct rt6_info *rt) |
@@ -498,7 +492,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt) | |||
498 | struct neighbour *neigh; | 492 | struct neighbour *neigh; |
499 | int m; | 493 | int m; |
500 | 494 | ||
501 | rcu_read_lock(); | ||
502 | neigh = rt->n; | 495 | neigh = rt->n; |
503 | if (rt->rt6i_flags & RTF_NONEXTHOP || | 496 | if (rt->rt6i_flags & RTF_NONEXTHOP || |
504 | !(rt->rt6i_flags & RTF_GATEWAY)) | 497 | !(rt->rt6i_flags & RTF_GATEWAY)) |
@@ -516,7 +509,6 @@ static inline int rt6_check_neigh(struct rt6_info *rt) | |||
516 | read_unlock_bh(&neigh->lock); | 509 | read_unlock_bh(&neigh->lock); |
517 | } else | 510 | } else |
518 | m = 0; | 511 | m = 0; |
519 | rcu_read_unlock(); | ||
520 | return m; | 512 | return m; |
521 | } | 513 | } |
522 | 514 | ||
@@ -965,7 +957,7 @@ struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk, | |||
965 | { | 957 | { |
966 | int flags = 0; | 958 | int flags = 0; |
967 | 959 | ||
968 | fl6->flowi6_iif = net->loopback_dev->ifindex; | 960 | fl6->flowi6_iif = LOOPBACK_IFINDEX; |
969 | 961 | ||
970 | 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)) |
971 | flags |= RT6_LOOKUP_F_IFACE; | 963 | flags |= RT6_LOOKUP_F_IFACE; |
@@ -1031,6 +1023,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
1031 | 1023 | ||
1032 | rt = (struct rt6_info *) dst; | 1024 | rt = (struct rt6_info *) dst; |
1033 | 1025 | ||
1026 | /* All IPV6 dsts are created with ->obsolete set to the value | ||
1027 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | ||
1028 | * into this function always. | ||
1029 | */ | ||
1030 | if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev))) | ||
1031 | return NULL; | ||
1032 | |||
1034 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { | 1033 | if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) { |
1035 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { | 1034 | if (rt->rt6i_peer_genid != rt6_peer_genid()) { |
1036 | if (!rt6_has_peer(rt)) | 1035 | if (!rt6_has_peer(rt)) |
@@ -1397,8 +1396,6 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1397 | goto out; | 1396 | goto out; |
1398 | } | 1397 | } |
1399 | 1398 | ||
1400 | rt->dst.obsolete = -1; | ||
1401 | |||
1402 | if (cfg->fc_flags & RTF_EXPIRES) | 1399 | if (cfg->fc_flags & RTF_EXPIRES) |
1403 | rt6_set_expires(rt, jiffies + | 1400 | rt6_set_expires(rt, jiffies + |
1404 | clock_t_to_jiffies(cfg->fc_expires)); | 1401 | clock_t_to_jiffies(cfg->fc_expires)); |
@@ -1463,8 +1460,21 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1463 | } | 1460 | } |
1464 | rt->dst.output = ip6_pkt_discard_out; | 1461 | rt->dst.output = ip6_pkt_discard_out; |
1465 | rt->dst.input = ip6_pkt_discard; | 1462 | rt->dst.input = ip6_pkt_discard; |
1466 | rt->dst.error = -ENETUNREACH; | ||
1467 | 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 | } | ||
1468 | goto install_route; | 1478 | goto install_route; |
1469 | } | 1479 | } |
1470 | 1480 | ||
@@ -1583,17 +1593,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) | |||
1583 | struct fib6_table *table; | 1593 | struct fib6_table *table; |
1584 | struct net *net = dev_net(rt->dst.dev); | 1594 | struct net *net = dev_net(rt->dst.dev); |
1585 | 1595 | ||
1586 | if (rt == net->ipv6.ip6_null_entry) | 1596 | if (rt == net->ipv6.ip6_null_entry) { |
1587 | return -ENOENT; | 1597 | err = -ENOENT; |
1598 | goto out; | ||
1599 | } | ||
1588 | 1600 | ||
1589 | table = rt->rt6i_table; | 1601 | table = rt->rt6i_table; |
1590 | write_lock_bh(&table->tb6_lock); | 1602 | write_lock_bh(&table->tb6_lock); |
1591 | |||
1592 | err = fib6_del(rt, info); | 1603 | err = fib6_del(rt, info); |
1593 | dst_release(&rt->dst); | ||
1594 | |||
1595 | write_unlock_bh(&table->tb6_lock); | 1604 | write_unlock_bh(&table->tb6_lock); |
1596 | 1605 | ||
1606 | out: | ||
1607 | dst_release(&rt->dst); | ||
1597 | return err; | 1608 | return err; |
1598 | } | 1609 | } |
1599 | 1610 | ||
@@ -1829,7 +1840,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1829 | if (!table) | 1840 | if (!table) |
1830 | return NULL; | 1841 | return NULL; |
1831 | 1842 | ||
1832 | write_lock_bh(&table->tb6_lock); | 1843 | read_lock_bh(&table->tb6_lock); |
1833 | fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0); | 1844 | fn = fib6_locate(&table->tb6_root, prefix ,prefixlen, NULL, 0); |
1834 | if (!fn) | 1845 | if (!fn) |
1835 | goto out; | 1846 | goto out; |
@@ -1845,7 +1856,7 @@ static struct rt6_info *rt6_get_route_info(struct net *net, | |||
1845 | break; | 1856 | break; |
1846 | } | 1857 | } |
1847 | out: | 1858 | out: |
1848 | write_unlock_bh(&table->tb6_lock); | 1859 | read_unlock_bh(&table->tb6_lock); |
1849 | return rt; | 1860 | return rt; |
1850 | } | 1861 | } |
1851 | 1862 | ||
@@ -1861,7 +1872,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net, | |||
1861 | .fc_dst_len = prefixlen, | 1872 | .fc_dst_len = prefixlen, |
1862 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | | 1873 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_ROUTEINFO | |
1863 | RTF_UP | RTF_PREF(pref), | 1874 | RTF_UP | RTF_PREF(pref), |
1864 | .fc_nlinfo.pid = 0, | 1875 | .fc_nlinfo.portid = 0, |
1865 | .fc_nlinfo.nlh = NULL, | 1876 | .fc_nlinfo.nlh = NULL, |
1866 | .fc_nlinfo.nl_net = net, | 1877 | .fc_nlinfo.nl_net = net, |
1867 | }; | 1878 | }; |
@@ -1888,7 +1899,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev | |||
1888 | if (!table) | 1899 | if (!table) |
1889 | return NULL; | 1900 | return NULL; |
1890 | 1901 | ||
1891 | write_lock_bh(&table->tb6_lock); | 1902 | read_lock_bh(&table->tb6_lock); |
1892 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { | 1903 | for (rt = table->tb6_root.leaf; rt; rt=rt->dst.rt6_next) { |
1893 | if (dev == rt->dst.dev && | 1904 | if (dev == rt->dst.dev && |
1894 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && | 1905 | ((rt->rt6i_flags & (RTF_ADDRCONF | RTF_DEFAULT)) == (RTF_ADDRCONF | RTF_DEFAULT)) && |
@@ -1897,7 +1908,7 @@ struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_dev | |||
1897 | } | 1908 | } |
1898 | if (rt) | 1909 | if (rt) |
1899 | dst_hold(&rt->dst); | 1910 | dst_hold(&rt->dst); |
1900 | write_unlock_bh(&table->tb6_lock); | 1911 | read_unlock_bh(&table->tb6_lock); |
1901 | return rt; | 1912 | return rt; |
1902 | } | 1913 | } |
1903 | 1914 | ||
@@ -1911,7 +1922,7 @@ struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, | |||
1911 | .fc_ifindex = dev->ifindex, | 1922 | .fc_ifindex = dev->ifindex, |
1912 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | | 1923 | .fc_flags = RTF_GATEWAY | RTF_ADDRCONF | RTF_DEFAULT | |
1913 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), | 1924 | RTF_UP | RTF_EXPIRES | RTF_PREF(pref), |
1914 | .fc_nlinfo.pid = 0, | 1925 | .fc_nlinfo.portid = 0, |
1915 | .fc_nlinfo.nlh = NULL, | 1926 | .fc_nlinfo.nlh = NULL, |
1916 | .fc_nlinfo.nl_net = dev_net(dev), | 1927 | .fc_nlinfo.nl_net = dev_net(dev), |
1917 | }; | 1928 | }; |
@@ -2080,7 +2091,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2080 | rt->dst.input = ip6_input; | 2091 | rt->dst.input = ip6_input; |
2081 | rt->dst.output = ip6_output; | 2092 | rt->dst.output = ip6_output; |
2082 | rt->rt6i_idev = idev; | 2093 | rt->rt6i_idev = idev; |
2083 | rt->dst.obsolete = -1; | ||
2084 | 2094 | ||
2085 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 2095 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
2086 | if (anycast) | 2096 | if (anycast) |
@@ -2261,14 +2271,18 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
2261 | cfg->fc_src_len = rtm->rtm_src_len; | 2271 | cfg->fc_src_len = rtm->rtm_src_len; |
2262 | cfg->fc_flags = RTF_UP; | 2272 | cfg->fc_flags = RTF_UP; |
2263 | cfg->fc_protocol = rtm->rtm_protocol; | 2273 | cfg->fc_protocol = rtm->rtm_protocol; |
2274 | cfg->fc_type = rtm->rtm_type; | ||
2264 | 2275 | ||
2265 | if (rtm->rtm_type == RTN_UNREACHABLE) | 2276 | if (rtm->rtm_type == RTN_UNREACHABLE || |
2277 | rtm->rtm_type == RTN_BLACKHOLE || | ||
2278 | rtm->rtm_type == RTN_PROHIBIT || | ||
2279 | rtm->rtm_type == RTN_THROW) | ||
2266 | cfg->fc_flags |= RTF_REJECT; | 2280 | cfg->fc_flags |= RTF_REJECT; |
2267 | 2281 | ||
2268 | if (rtm->rtm_type == RTN_LOCAL) | 2282 | if (rtm->rtm_type == RTN_LOCAL) |
2269 | cfg->fc_flags |= RTF_LOCAL; | 2283 | cfg->fc_flags |= RTF_LOCAL; |
2270 | 2284 | ||
2271 | cfg->fc_nlinfo.pid = NETLINK_CB(skb).pid; | 2285 | cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid; |
2272 | cfg->fc_nlinfo.nlh = nlh; | 2286 | cfg->fc_nlinfo.nlh = nlh; |
2273 | cfg->fc_nlinfo.nl_net = sock_net(skb->sk); | 2287 | cfg->fc_nlinfo.nl_net = sock_net(skb->sk); |
2274 | 2288 | ||
@@ -2359,7 +2373,7 @@ static inline size_t rt6_nlmsg_size(void) | |||
2359 | static int rt6_fill_node(struct net *net, | 2373 | static int rt6_fill_node(struct net *net, |
2360 | struct sk_buff *skb, struct rt6_info *rt, | 2374 | struct sk_buff *skb, struct rt6_info *rt, |
2361 | struct in6_addr *dst, struct in6_addr *src, | 2375 | struct in6_addr *dst, struct in6_addr *src, |
2362 | int iif, int type, u32 pid, u32 seq, | 2376 | int iif, int type, u32 portid, u32 seq, |
2363 | int prefix, int nowait, unsigned int flags) | 2377 | int prefix, int nowait, unsigned int flags) |
2364 | { | 2378 | { |
2365 | struct rtmsg *rtm; | 2379 | struct rtmsg *rtm; |
@@ -2375,7 +2389,7 @@ static int rt6_fill_node(struct net *net, | |||
2375 | } | 2389 | } |
2376 | } | 2390 | } |
2377 | 2391 | ||
2378 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); | 2392 | nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags); |
2379 | if (!nlh) | 2393 | if (!nlh) |
2380 | return -EMSGSIZE; | 2394 | return -EMSGSIZE; |
2381 | 2395 | ||
@@ -2391,8 +2405,22 @@ static int rt6_fill_node(struct net *net, | |||
2391 | rtm->rtm_table = table; | 2405 | rtm->rtm_table = table; |
2392 | if (nla_put_u32(skb, RTA_TABLE, table)) | 2406 | if (nla_put_u32(skb, RTA_TABLE, table)) |
2393 | goto nla_put_failure; | 2407 | goto nla_put_failure; |
2394 | if (rt->rt6i_flags & RTF_REJECT) | 2408 | if (rt->rt6i_flags & RTF_REJECT) { |
2395 | rtm->rtm_type = RTN_UNREACHABLE; | 2409 | switch (rt->dst.error) { |
2410 | case -EINVAL: | ||
2411 | rtm->rtm_type = RTN_BLACKHOLE; | ||
2412 | break; | ||
2413 | case -EACCES: | ||
2414 | rtm->rtm_type = RTN_PROHIBIT; | ||
2415 | break; | ||
2416 | case -EAGAIN: | ||
2417 | rtm->rtm_type = RTN_THROW; | ||
2418 | break; | ||
2419 | default: | ||
2420 | rtm->rtm_type = RTN_UNREACHABLE; | ||
2421 | break; | ||
2422 | } | ||
2423 | } | ||
2396 | else if (rt->rt6i_flags & RTF_LOCAL) | 2424 | else if (rt->rt6i_flags & RTF_LOCAL) |
2397 | rtm->rtm_type = RTN_LOCAL; | 2425 | rtm->rtm_type = RTN_LOCAL; |
2398 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) | 2426 | else if (rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) |
@@ -2465,15 +2493,11 @@ static int rt6_fill_node(struct net *net, | |||
2465 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) | 2493 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2466 | goto nla_put_failure; | 2494 | goto nla_put_failure; |
2467 | 2495 | ||
2468 | rcu_read_lock(); | ||
2469 | n = rt->n; | 2496 | n = rt->n; |
2470 | if (n) { | 2497 | if (n) { |
2471 | if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) { | 2498 | if (nla_put(skb, RTA_GATEWAY, 16, &n->primary_key) < 0) |
2472 | rcu_read_unlock(); | ||
2473 | goto nla_put_failure; | 2499 | goto nla_put_failure; |
2474 | } | ||
2475 | } | 2500 | } |
2476 | rcu_read_unlock(); | ||
2477 | 2501 | ||
2478 | if (rt->dst.dev && | 2502 | if (rt->dst.dev && |
2479 | nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) | 2503 | nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex)) |
@@ -2506,7 +2530,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg) | |||
2506 | 2530 | ||
2507 | return rt6_fill_node(arg->net, | 2531 | return rt6_fill_node(arg->net, |
2508 | arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, | 2532 | arg->skb, rt, NULL, NULL, 0, RTM_NEWROUTE, |
2509 | NETLINK_CB(arg->cb->skb).pid, arg->cb->nlh->nlmsg_seq, | 2533 | NETLINK_CB(arg->cb->skb).portid, arg->cb->nlh->nlmsg_seq, |
2510 | prefix, 0, NLM_F_MULTI); | 2534 | prefix, 0, NLM_F_MULTI); |
2511 | } | 2535 | } |
2512 | 2536 | ||
@@ -2586,14 +2610,14 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void | |||
2586 | skb_dst_set(skb, &rt->dst); | 2610 | skb_dst_set(skb, &rt->dst); |
2587 | 2611 | ||
2588 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, | 2612 | err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif, |
2589 | RTM_NEWROUTE, NETLINK_CB(in_skb).pid, | 2613 | RTM_NEWROUTE, NETLINK_CB(in_skb).portid, |
2590 | nlh->nlmsg_seq, 0, 0, 0); | 2614 | nlh->nlmsg_seq, 0, 0, 0); |
2591 | if (err < 0) { | 2615 | if (err < 0) { |
2592 | kfree_skb(skb); | 2616 | kfree_skb(skb); |
2593 | goto errout; | 2617 | goto errout; |
2594 | } | 2618 | } |
2595 | 2619 | ||
2596 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).pid); | 2620 | err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); |
2597 | errout: | 2621 | errout: |
2598 | return err; | 2622 | return err; |
2599 | } | 2623 | } |
@@ -2613,14 +2637,14 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2613 | goto errout; | 2637 | goto errout; |
2614 | 2638 | ||
2615 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, | 2639 | err = rt6_fill_node(net, skb, rt, NULL, NULL, 0, |
2616 | event, info->pid, seq, 0, 0, 0); | 2640 | event, info->portid, seq, 0, 0, 0); |
2617 | if (err < 0) { | 2641 | if (err < 0) { |
2618 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ | 2642 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ |
2619 | WARN_ON(err == -EMSGSIZE); | 2643 | WARN_ON(err == -EMSGSIZE); |
2620 | kfree_skb(skb); | 2644 | kfree_skb(skb); |
2621 | goto errout; | 2645 | goto errout; |
2622 | } | 2646 | } |
2623 | rtnl_notify(skb, net, info->pid, RTNLGRP_IPV6_ROUTE, | 2647 | rtnl_notify(skb, net, info->portid, RTNLGRP_IPV6_ROUTE, |
2624 | info->nlh, gfp_any()); | 2648 | info->nlh, gfp_any()); |
2625 | return; | 2649 | return; |
2626 | errout: | 2650 | errout: |
@@ -2675,14 +2699,12 @@ static int rt6_info_route(struct rt6_info *rt, void *p_arg) | |||
2675 | #else | 2699 | #else |
2676 | seq_puts(m, "00000000000000000000000000000000 00 "); | 2700 | seq_puts(m, "00000000000000000000000000000000 00 "); |
2677 | #endif | 2701 | #endif |
2678 | rcu_read_lock(); | ||
2679 | n = rt->n; | 2702 | n = rt->n; |
2680 | if (n) { | 2703 | if (n) { |
2681 | seq_printf(m, "%pi6", n->primary_key); | 2704 | seq_printf(m, "%pi6", n->primary_key); |
2682 | } else { | 2705 | } else { |
2683 | seq_puts(m, "00000000000000000000000000000000"); | 2706 | seq_puts(m, "00000000000000000000000000000000"); |
2684 | } | 2707 | } |
2685 | rcu_read_unlock(); | ||
2686 | seq_printf(m, " %08x %08x %08x %08x %8s\n", | 2708 | seq_printf(m, " %08x %08x %08x %08x %8s\n", |
2687 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), | 2709 | rt->rt6i_metric, atomic_read(&rt->dst.__refcnt), |
2688 | rt->dst.__use, rt->rt6i_flags, | 2710 | rt->dst.__use, rt->rt6i_flags, |