diff options
Diffstat (limited to 'net/ipv4/arp.c')
-rw-r--r-- | net/ipv4/arp.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index cf78f41830ca..09ead1baa99e 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c | |||
@@ -333,11 +333,14 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
333 | struct net_device *dev = neigh->dev; | 333 | struct net_device *dev = neigh->dev; |
334 | __be32 target = *(__be32*)neigh->primary_key; | 334 | __be32 target = *(__be32*)neigh->primary_key; |
335 | int probes = atomic_read(&neigh->probes); | 335 | int probes = atomic_read(&neigh->probes); |
336 | struct in_device *in_dev = in_dev_get(dev); | 336 | struct in_device *in_dev; |
337 | 337 | ||
338 | if (!in_dev) | 338 | rcu_read_lock(); |
339 | in_dev = __in_dev_get_rcu(dev); | ||
340 | if (!in_dev) { | ||
341 | rcu_read_unlock(); | ||
339 | return; | 342 | return; |
340 | 343 | } | |
341 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { | 344 | switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { |
342 | default: | 345 | default: |
343 | case 0: /* By default announce any local IP */ | 346 | case 0: /* By default announce any local IP */ |
@@ -358,9 +361,8 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) | |||
358 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ | 361 | case 2: /* Avoid secondary IPs, get a primary/preferred one */ |
359 | break; | 362 | break; |
360 | } | 363 | } |
364 | rcu_read_unlock(); | ||
361 | 365 | ||
362 | if (in_dev) | ||
363 | in_dev_put(in_dev); | ||
364 | if (!saddr) | 366 | if (!saddr) |
365 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); | 367 | saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); |
366 | 368 | ||