diff options
author | YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org> | 2013-01-17 07:53:43 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-17 18:38:19 -0500 |
commit | 2152caea719657579daa3a1a57a5425a3db6d612 (patch) | |
tree | 2b81bfd342c60d7bca8857666a2f921aa34dd590 /net | |
parent | 145a36217adf91cdc6922c5b9cc985b87f8e0c73 (diff) |
ipv6: Do not depend on rt->n in rt6_probe().
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/route.c | 26 |
1 files changed, 16 insertions, 10 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index c7bcd777db23..afc8386e3d9f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -498,28 +498,34 @@ static void rt6_probe(struct rt6_info *rt) | |||
498 | * Router Reachability Probe MUST be rate-limited | 498 | * Router Reachability Probe MUST be rate-limited |
499 | * to no more than one per minute. | 499 | * to no more than one per minute. |
500 | */ | 500 | */ |
501 | neigh = rt ? rt->n : NULL; | 501 | if (!rt || !(rt->rt6i_flags & RTF_GATEWAY)) |
502 | if (!neigh) | ||
503 | return; | ||
504 | write_lock_bh(&neigh->lock); | ||
505 | if (neigh->nud_state & NUD_VALID) { | ||
506 | write_unlock_bh(&neigh->lock); | ||
507 | return; | 502 | return; |
503 | rcu_read_lock_bh(); | ||
504 | neigh = __ipv6_neigh_lookup_noref(rt->dst.dev, &rt->rt6i_gateway); | ||
505 | if (neigh) { | ||
506 | write_lock(&neigh->lock); | ||
507 | if (neigh->nud_state & NUD_VALID) | ||
508 | goto out; | ||
508 | } | 509 | } |
509 | if (!(neigh->nud_state & NUD_VALID) && | 510 | |
511 | if (!neigh || | ||
510 | time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { | 512 | time_after(jiffies, neigh->updated + rt->rt6i_idev->cnf.rtr_probe_interval)) { |
511 | struct in6_addr mcaddr; | 513 | struct in6_addr mcaddr; |
512 | struct in6_addr *target; | 514 | struct in6_addr *target; |
513 | 515 | ||
514 | neigh->updated = jiffies; | 516 | neigh->updated = jiffies; |
515 | write_unlock_bh(&neigh->lock); | ||
516 | 517 | ||
517 | target = (struct in6_addr *)&neigh->primary_key; | 518 | if (neigh) |
519 | write_unlock(&neigh->lock); | ||
520 | |||
521 | target = (struct in6_addr *)&rt->rt6i_gateway; | ||
518 | addrconf_addr_solict_mult(target, &mcaddr); | 522 | addrconf_addr_solict_mult(target, &mcaddr); |
519 | ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); | 523 | ndisc_send_ns(rt->dst.dev, NULL, target, &mcaddr, NULL); |
520 | } else { | 524 | } else { |
521 | write_unlock_bh(&neigh->lock); | 525 | out: |
526 | write_unlock(&neigh->lock); | ||
522 | } | 527 | } |
528 | rcu_read_unlock_bh(); | ||
523 | } | 529 | } |
524 | #else | 530 | #else |
525 | static inline void rt6_probe(struct rt6_info *rt) | 531 | static inline void rt6_probe(struct rt6_info *rt) |