blob: 7d07d6bff83075966dad38d3eec9f3c0c678a30f [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010042#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define neigh_dbg(level, fmt, ...) \
47do { \
48 if (level <= NEIGH_DEBUG) \
49 pr_debug(fmt, ##__VA_ARGS__); \
50} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define PNEIGH_HASHMASK 0xF
53
54static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070055static void __neigh_notify(struct neighbour *n, int type, int flags);
56static void neigh_update_notify(struct neighbour *neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Ravinder Konkaa71b6682015-04-09 11:42:00 +053059static unsigned int neigh_probe_enable;
Amos Waterland45fc3b12005-09-24 16:53:16 -070060#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080061static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070062#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64/*
65 Neighbour hash table buckets are protected with rwlock tbl->lock.
66
67 - All the scans/updates to hash buckets MUST be made under this lock.
68 - NOTHING clever should be made under this lock: no callbacks
69 to protocol backends, no attempts to send something to network.
70 It will result in deadlocks, if backend/driver wants to use neighbour
71 cache.
72 - If the entry requires some non-trivial actions, increase
73 its reference count and release table lock.
74
75 Neighbour entries are protected:
76 - with reference count.
77 - with rwlock neigh->lock
78
79 Reference count prevents destruction.
80
81 neigh->lock mainly serializes ll address data and its validity state.
82 However, the same lock is used to protect another entry fields:
83 - timer
84 - resolution queue
85
86 Again, nothing clever shall be made under neigh->lock,
87 the most complicated procedure, which we allow is dev->hard_header.
88 It is supposed, that dev->hard_header is simplistic and does
89 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 */
91
David S. Miller8f40b162011-07-17 13:34:11 -070092static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070093{
94 kfree_skb(skb);
95 return -ENETDOWN;
96}
97
Thomas Graf4f494552007-08-08 23:12:36 -070098static void neigh_cleanup_and_release(struct neighbour *neigh)
99{
100 if (neigh->parms->neigh_cleanup)
101 neigh->parms->neigh_cleanup(neigh);
102
Thomas Grafd961db32007-08-08 23:12:56 -0700103 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700104 neigh_release(neigh);
105}
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107/*
108 * It is random distribution in the interval (1/2)*base...(3/2)*base.
109 * It corresponds to default IPv6 settings and is not overridable,
110 * because it is really reasonable choice.
111 */
112
113unsigned long neigh_rand_reach_time(unsigned long base)
114{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500115 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900117EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119
120static int neigh_forced_gc(struct neigh_table *tbl)
121{
122 int shrunk = 0;
123 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000124 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
127
128 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000129 nht = rcu_dereference_protected(tbl->nht,
130 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700131 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700132 struct neighbour *n;
133 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000135 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700136 while ((n = rcu_dereference_protected(*np,
137 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 /* Neighbour record may be discarded if:
139 * - nobody refers to it.
140 * - it is not permanent
141 */
142 write_lock(&n->lock);
143 if (atomic_read(&n->refcnt) == 1 &&
144 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700145 rcu_assign_pointer(*np,
146 rcu_dereference_protected(n->next,
147 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 n->dead = 1;
149 shrunk = 1;
150 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700151 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 continue;
153 }
154 write_unlock(&n->lock);
155 np = &n->next;
156 }
157 }
158
159 tbl->last_flush = jiffies;
160
161 write_unlock_bh(&tbl->lock);
162
163 return shrunk;
164}
165
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800166static void neigh_add_timer(struct neighbour *n, unsigned long when)
167{
168 neigh_hold(n);
169 if (unlikely(mod_timer(&n->timer, when))) {
170 printk("NEIGH: BUG, double timer add, state is %x\n",
171 n->nud_state);
172 dump_stack();
173 }
174}
175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176static int neigh_del_timer(struct neighbour *n)
177{
178 if ((n->nud_state & NUD_IN_TIMER) &&
179 del_timer(&n->timer)) {
180 neigh_release(n);
181 return 1;
182 }
183 return 0;
184}
185
186static void pneigh_queue_purge(struct sk_buff_head *list)
187{
188 struct sk_buff *skb;
189
190 while ((skb = skb_dequeue(list)) != NULL) {
191 dev_put(skb->dev);
192 kfree_skb(skb);
193 }
194}
195
Herbert Xu49636bb2005-10-23 17:18:00 +1000196static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197{
198 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000199 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000201 nht = rcu_dereference_protected(tbl->nht,
202 lockdep_is_held(&tbl->lock));
203
David S. Millercd089332011-07-11 01:28:12 -0700204 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700205 struct neighbour *n;
206 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
Eric Dumazet767e97e2010-10-06 17:49:21 -0700208 while ((n = rcu_dereference_protected(*np,
209 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 if (dev && n->dev != dev) {
211 np = &n->next;
212 continue;
213 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700214 rcu_assign_pointer(*np,
215 rcu_dereference_protected(n->next,
216 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 write_lock(&n->lock);
218 neigh_del_timer(n);
219 n->dead = 1;
220
221 if (atomic_read(&n->refcnt) != 1) {
222 /* The most unpleasant situation.
223 We must destroy neighbour entry,
224 but someone still uses it.
225
226 The destroy will be delayed until
227 the last user releases us, but
228 we must kill timers etc. and move
229 it to safe state.
230 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700231 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000232 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 n->output = neigh_blackhole;
234 if (n->nud_state & NUD_VALID)
235 n->nud_state = NUD_NOARP;
236 else
237 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000238 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700241 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 }
243 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000244}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Herbert Xu49636bb2005-10-23 17:18:00 +1000246void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
247{
248 write_lock_bh(&tbl->lock);
249 neigh_flush_dev(tbl, dev);
250 write_unlock_bh(&tbl->lock);
251}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900252EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000253
254int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
255{
256 write_lock_bh(&tbl->lock);
257 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 pneigh_ifdown(tbl, dev);
259 write_unlock_bh(&tbl->lock);
260
261 del_timer_sync(&tbl->proxy_timer);
262 pneigh_queue_purge(&tbl->proxy_queue);
263 return 0;
264}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900265EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
David Miller596b9b62011-07-25 00:01:25 +0000267static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
269 struct neighbour *n = NULL;
270 unsigned long now = jiffies;
271 int entries;
272
273 entries = atomic_inc_return(&tbl->entries) - 1;
274 if (entries >= tbl->gc_thresh3 ||
275 (entries >= tbl->gc_thresh2 &&
276 time_after(now, tbl->last_flush + 5 * HZ))) {
277 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700278 entries >= tbl->gc_thresh3) {
279 net_info_ratelimited("%s: neighbor table overflow!\n",
280 tbl->id);
281 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000286 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (!n)
288 goto out_entries;
289
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700290 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000292 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 n->updated = n->used = now;
294 n->nud_state = NUD_NONE;
295 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700296 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800298 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 NEIGH_CACHE_STAT_INC(tbl, allocs);
301 n->tbl = tbl;
302 atomic_set(&n->refcnt, 1);
303 n->dead = 1;
304out:
305 return n;
306
307out_entries:
308 atomic_dec(&tbl->entries);
309 goto out;
310}
311
David S. Miller2c2aba62011-12-28 15:06:58 -0500312static void neigh_get_hash_rnd(u32 *x)
313{
314 get_random_bytes(x, sizeof(*x));
315 *x |= 1;
316}
317
David S. Millercd089332011-07-11 01:28:12 -0700318static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
David S. Millercd089332011-07-11 01:28:12 -0700320 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000321 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000322 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500323 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000325 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
326 if (!ret)
327 return NULL;
328 if (size <= PAGE_SIZE)
329 buckets = kzalloc(size, GFP_ATOMIC);
330 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000331 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000332 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
333 get_order(size));
334 if (!buckets) {
335 kfree(ret);
336 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000338 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700339 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500340 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
341 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 return ret;
343}
344
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000345static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000347 struct neigh_hash_table *nht = container_of(head,
348 struct neigh_hash_table,
349 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700350 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000351 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000354 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 free_pages((unsigned long)buckets, get_order(size));
357 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700361 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 unsigned int i, hash;
364 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
367
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000368 old_nht = rcu_dereference_protected(tbl->nht,
369 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700370 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000371 if (!new_nht)
372 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
David S. Millercd089332011-07-11 01:28:12 -0700374 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 struct neighbour *n, *next;
376
Eric Dumazet767e97e2010-10-06 17:49:21 -0700377 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
378 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000379 n != NULL;
380 n = next) {
381 hash = tbl->hash(n->primary_key, n->dev,
382 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
David S. Millercd089332011-07-11 01:28:12 -0700384 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700385 next = rcu_dereference_protected(n->next,
386 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Eric Dumazet767e97e2010-10-06 17:49:21 -0700388 rcu_assign_pointer(n->next,
389 rcu_dereference_protected(
390 new_nht->hash_buckets[hash],
391 lockdep_is_held(&tbl->lock)));
392 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000396 rcu_assign_pointer(tbl->nht, new_nht);
397 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
398 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
401struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
402 struct net_device *dev)
403{
404 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 NEIGH_CACHE_STAT_INC(tbl, lookups);
407
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600409 n = __neigh_lookup_noref(tbl, pkey, dev);
410 if (n) {
411 if (!atomic_inc_not_zero(&n->refcnt))
412 n = NULL;
413 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700415
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000416 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return n;
418}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900419EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Eric W. Biederman426b5302008-01-24 00:13:18 -0800421struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
422 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 struct neighbour *n;
425 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800426 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 NEIGH_CACHE_STAT_INC(tbl, lookups);
430
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000431 rcu_read_lock_bh();
432 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700433 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700434
435 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
436 n != NULL;
437 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800438 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900439 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700440 if (!atomic_inc_not_zero(&n->refcnt))
441 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 NEIGH_CACHE_STAT_INC(tbl, hits);
443 break;
444 }
445 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700446
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000447 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return n;
449}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900450EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
David S. Millera263b302012-07-02 02:02:15 -0700452struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
453 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 u32 hash_val;
456 int key_len = tbl->key_len;
457 int error;
David Miller596b9b62011-07-25 00:01:25 +0000458 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000459 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 if (!n) {
462 rc = ERR_PTR(-ENOBUFS);
463 goto out;
464 }
465
466 memcpy(n->primary_key, pkey, key_len);
467 n->dev = dev;
468 dev_hold(dev);
469
470 /* Protocol specific setup. */
471 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
472 rc = ERR_PTR(error);
473 goto out_neigh_release;
474 }
475
David Millerda6a8fa2011-07-25 00:01:38 +0000476 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200477 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000478 if (error < 0) {
479 rc = ERR_PTR(error);
480 goto out_neigh_release;
481 }
482 }
483
David S. Miller447f2192011-12-19 15:04:41 -0500484 /* Device specific setup. */
485 if (n->parms->neigh_setup &&
486 (error = n->parms->neigh_setup(n)) < 0) {
487 rc = ERR_PTR(error);
488 goto out_neigh_release;
489 }
490
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100491 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 nht = rcu_dereference_protected(tbl->nht,
495 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
David S. Millercd089332011-07-11 01:28:12 -0700497 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
498 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Jim Westfall014510b2018-01-14 04:18:50 -0800500 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 if (n->parms->dead) {
503 rc = ERR_PTR(-EINVAL);
504 goto out_tbl_unlock;
505 }
506
Eric Dumazet767e97e2010-10-06 17:49:21 -0700507 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
508 lockdep_is_held(&tbl->lock));
509 n1 != NULL;
510 n1 = rcu_dereference_protected(n1->next,
511 lockdep_is_held(&tbl->lock))) {
Jim Westfall014510b2018-01-14 04:18:50 -0800512 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700513 if (want_ref)
514 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 rc = n1;
516 goto out_tbl_unlock;
517 }
518 }
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700521 if (want_ref)
522 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700523 rcu_assign_pointer(n->next,
524 rcu_dereference_protected(nht->hash_buckets[hash_val],
525 lockdep_is_held(&tbl->lock)));
526 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000528 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 rc = n;
530out:
531 return rc;
532out_tbl_unlock:
533 write_unlock_bh(&tbl->lock);
534out_neigh_release:
535 neigh_release(n);
536 goto out;
537}
David S. Millera263b302012-07-02 02:02:15 -0700538EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900540static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700541{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700542 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700543 hash_val ^= (hash_val >> 16);
544 hash_val ^= hash_val >> 8;
545 hash_val ^= hash_val >> 4;
546 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900547 return hash_val;
548}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700549
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900550static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
551 struct net *net,
552 const void *pkey,
553 int key_len,
554 struct net_device *dev)
555{
556 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700557 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700559 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900560 return n;
561 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700562 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900563 return NULL;
564}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700565
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900566struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
567 struct net *net, const void *pkey, struct net_device *dev)
568{
569 int key_len = tbl->key_len;
570 u32 hash_val = pneigh_hash(pkey, key_len);
571
572 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
573 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700574}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900575EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576
Eric W. Biederman426b5302008-01-24 00:13:18 -0800577struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
578 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 struct net_device *dev, int creat)
580{
581 struct pneigh_entry *n;
582 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900583 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900586 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
587 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900589
590 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 goto out;
592
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700593 ASSERT_RTNL();
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
596 if (!n)
597 goto out;
598
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500599 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 memcpy(n->key, pkey, key_len);
601 n->dev = dev;
602 if (dev)
603 dev_hold(dev);
604
605 if (tbl->pconstructor && tbl->pconstructor(n)) {
606 if (dev)
607 dev_put(dev);
608 kfree(n);
609 n = NULL;
610 goto out;
611 }
612
613 write_lock_bh(&tbl->lock);
614 n->next = tbl->phash_buckets[hash_val];
615 tbl->phash_buckets[hash_val] = n;
616 write_unlock_bh(&tbl->lock);
617out:
618 return n;
619}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900620EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622
Eric W. Biederman426b5302008-01-24 00:13:18 -0800623int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 struct net_device *dev)
625{
626 struct pneigh_entry *n, **np;
627 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900628 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 write_lock_bh(&tbl->lock);
631 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
632 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800633 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900634 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 *np = n->next;
636 write_unlock_bh(&tbl->lock);
637 if (tbl->pdestructor)
638 tbl->pdestructor(n);
639 if (n->dev)
640 dev_put(n->dev);
641 kfree(n);
642 return 0;
643 }
644 }
645 write_unlock_bh(&tbl->lock);
646 return -ENOENT;
647}
648
649static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
650{
651 struct pneigh_entry *n, **np;
652 u32 h;
653
654 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
655 np = &tbl->phash_buckets[h];
656 while ((n = *np) != NULL) {
657 if (!dev || n->dev == dev) {
658 *np = n->next;
659 if (tbl->pdestructor)
660 tbl->pdestructor(n);
661 if (n->dev)
662 dev_put(n->dev);
663 kfree(n);
664 continue;
665 }
666 np = &n->next;
667 }
668 }
669 return -ENOENT;
670}
671
Denis V. Lunev06f05112008-01-24 00:30:58 -0800672static void neigh_parms_destroy(struct neigh_parms *parms);
673
674static inline void neigh_parms_put(struct neigh_parms *parms)
675{
676 if (atomic_dec_and_test(&parms->refcnt))
677 neigh_parms_destroy(parms);
678}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680/*
681 * neighbour must already be out of the table;
682 *
683 */
684void neigh_destroy(struct neighbour *neigh)
685{
David Millerda6a8fa2011-07-25 00:01:38 +0000686 struct net_device *dev = neigh->dev;
687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
689
690 if (!neigh->dead) {
Tejaswi Tanikellad40dd0f2017-07-25 13:30:09 +0530691 pr_warn("Destroying alive neighbour %pK\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 dump_stack();
693 return;
694 }
695
696 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000697 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700699 write_lock_bh(&neigh->lock);
700 __skb_queue_purge(&neigh->arp_queue);
701 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000702 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
David S. Miller447f2192011-12-19 15:04:41 -0500704 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200705 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500706
David Millerda6a8fa2011-07-25 00:01:38 +0000707 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 neigh_parms_put(neigh->parms);
709
Joe Perchesd5d427c2013-04-15 15:17:19 +0000710 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000713 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900715EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717/* Neighbour state is suspicious;
718 disable fast path.
719
720 Called with write_locked neigh.
721 */
722static void neigh_suspect(struct neighbour *neigh)
723{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000724 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727}
728
729/* Neighbour state is OK;
730 enable fast path.
731
732 Called with write_locked neigh.
733 */
734static void neigh_connect(struct neighbour *neigh)
735{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000736 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739}
740
Eric Dumazete4c4e442009-07-30 03:15:07 +0000741static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000743 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700744 struct neighbour *n;
745 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000746 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000747 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
750
Eric Dumazete4c4e442009-07-30 03:15:07 +0000751 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000752 nht = rcu_dereference_protected(tbl->nht,
753 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 /*
756 * periodically recompute ReachableTime from random function
757 */
758
Eric Dumazete4c4e442009-07-30 03:15:07 +0000759 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000761 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100762 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100764 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 }
766
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800767 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
768 goto out;
769
David S. Millercd089332011-07-11 01:28:12 -0700770 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000771 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Eric Dumazet767e97e2010-10-06 17:49:21 -0700773 while ((n = rcu_dereference_protected(*np,
774 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
Eric Dumazete4c4e442009-07-30 03:15:07 +0000777 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
Eric Dumazete4c4e442009-07-30 03:15:07 +0000779 state = n->nud_state;
780 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
781 write_unlock(&n->lock);
782 goto next_elt;
783 }
784
785 if (time_before(n->used, n->confirmed))
786 n->used = n->confirmed;
787
788 if (atomic_read(&n->refcnt) == 1 &&
789 (state == NUD_FAILED ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100790 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 *np = n->next;
792 n->dead = 1;
793 write_unlock(&n->lock);
794 neigh_cleanup_and_release(n);
795 continue;
796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
799next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000800 np = &n->next;
801 }
802 /*
803 * It's fine to release lock here, even if hash table
804 * grows while we are preempted.
805 */
806 write_unlock_bh(&tbl->lock);
807 cond_resched();
808 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500809 nht = rcu_dereference_protected(tbl->nht,
810 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000812out:
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100813 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
814 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
815 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 */
viresh kumarf6180022014-01-22 12:23:33 +0530817 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100818 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000819 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
822static __inline__ int neigh_max_probes(struct neighbour *n)
823{
824 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900825 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
826 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
827 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
Timo Teras5ef12d92009-06-11 04:16:28 -0700830static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000831 __releases(neigh->lock)
832 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700833{
834 struct sk_buff *skb;
835
836 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000837 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700838 neigh->updated = jiffies;
839
840 /* It is very thin place. report_unreachable is very complicated
841 routine. Particularly, it can hit the same neighbour entry!
842
843 So that, we try to be accurate and avoid dead loop. --ANK
844 */
845 while (neigh->nud_state == NUD_FAILED &&
846 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
847 write_unlock(&neigh->lock);
848 neigh->ops->error_report(neigh, skb);
849 write_lock(&neigh->lock);
850 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700851 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000852 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700853}
854
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000855static void neigh_probe(struct neighbour *neigh)
856 __releases(neigh->lock)
857{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200858 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000859 /* keep skb alive even if arp_queue overflows */
860 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800861 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000862 write_unlock(&neigh->lock);
Eric Dumazet4f991612017-03-23 12:39:21 -0700863 if (neigh->ops->solicit)
864 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000865 atomic_inc(&neigh->probes);
866 kfree_skb(skb);
867}
868
Linus Torvalds1da177e2005-04-16 15:20:36 -0700869/* Called when a timer expires for a neighbour entry. */
870
871static void neigh_timer_handler(unsigned long arg)
872{
873 unsigned long now, next;
874 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000875 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 int notify = 0;
877
878 write_lock(&neigh->lock);
879
880 state = neigh->nud_state;
881 now = jiffies;
882 next = now + HZ;
883
David S. Miller045f7b32011-11-01 17:45:55 -0400884 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886
887 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900888 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000890 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 next = neigh->confirmed + neigh->parms->reachable_time;
892 } else if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100893 neigh->used +
894 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000895 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800897 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 neigh_suspect(neigh);
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100899 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000901 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800903 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700905 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 }
907 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900908 if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100909 neigh->confirmed +
910 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000911 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800913 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700915 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 next = neigh->confirmed + neigh->parms->reachable_time;
917 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000918 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800920 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900922 notify = 1;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100923 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 }
925 } else {
926 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100927 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 }
929
930 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
931 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 neigh->nud_state = NUD_FAILED;
933 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700934 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800935 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937
938 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 if (time_before(next, jiffies + HZ/2))
940 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000941 if (!mod_timer(&neigh->timer, next))
942 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 }
Sridhar Anchab7092162016-04-14 21:20:43 +0530944
945 if (neigh_probe_enable) {
946 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE | NUD_STALE))
947 neigh_probe(neigh);
948 } else if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000949 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800950 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800951out:
David S. Miller9ff56602008-02-17 18:39:54 -0800952 write_unlock(&neigh->lock);
953 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Thomas Grafd961db32007-08-08 23:12:56 -0700955 if (notify)
956 neigh_update_notify(neigh);
957
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 neigh_release(neigh);
959}
960
961int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
962{
963 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000964 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965
966 write_lock_bh(&neigh->lock);
967
968 rc = 0;
969 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
970 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +0300971 if (neigh->dead)
972 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100975 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
976 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000977 unsigned long next, now = jiffies;
978
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100979 atomic_set(&neigh->probes,
980 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000982 neigh->updated = now;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100983 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
984 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000985 neigh_add_timer(neigh, next);
986 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 } else {
988 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800989 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 write_unlock_bh(&neigh->lock);
991
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000992 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 return 1;
994 }
995 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000996 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800998 neigh->updated = jiffies;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100999 neigh_add_timer(neigh, jiffies +
1000 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002
1003 if (neigh->nud_state == NUD_INCOMPLETE) {
1004 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001005 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001006 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001008
David S. Millerf72051b2008-09-23 01:11:18 -07001009 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001010 if (!buff)
1011 break;
1012 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001014 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001016 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001018 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 }
1020 rc = 1;
1021 }
1022out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001023 if (immediate_probe)
1024 neigh_probe(neigh);
1025 else
1026 write_unlock(&neigh->lock);
1027 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001029
1030out_dead:
1031 if (neigh->nud_state & NUD_STALE)
1032 goto out_unlock_bh;
1033 write_unlock_bh(&neigh->lock);
1034 kfree_skb(skb);
1035 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001037EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
David S. Millerf6b72b62011-07-14 07:53:20 -07001039static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
1041 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001042 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001043 = NULL;
1044
1045 if (neigh->dev->header_ops)
1046 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001049 hh = &neigh->hh;
1050 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001051 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001053 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 }
1056}
1057
1058
1059
1060/* Generic update routine.
1061 -- lladdr is new lladdr or NULL, if it is not supplied.
1062 -- new is new state.
1063 -- flags
1064 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1065 if it is different.
1066 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001067 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1070
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001071 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 NTF_ROUTER flag.
1073 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1074 a router.
1075
1076 Caller MUST hold reference count on the entry.
1077 */
1078
1079int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1080 u32 flags)
1081{
1082 u8 old;
1083 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 struct net_device *dev;
1086 int update_isrouter = 0;
1087
1088 write_lock_bh(&neigh->lock);
1089
1090 dev = neigh->dev;
1091 old = neigh->nud_state;
1092 err = -EPERM;
1093
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001094 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 (old & (NUD_NOARP | NUD_PERMANENT)))
1096 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001097 if (neigh->dead)
1098 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 if (!(new & NUD_VALID)) {
1101 neigh_del_timer(neigh);
1102 if (old & NUD_CONNECTED)
1103 neigh_suspect(neigh);
1104 neigh->nud_state = new;
1105 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001107 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1108 (new & NUD_FAILED)) {
1109 neigh_invalidate(neigh);
1110 notify = 1;
1111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 goto out;
1113 }
1114
1115 /* Compare new lladdr with cached one */
1116 if (!dev->addr_len) {
1117 /* First case: device needs no address. */
1118 lladdr = neigh->ha;
1119 } else if (lladdr) {
1120 /* The second case: if something is already cached
1121 and a new address is proposed:
1122 - compare new & old
1123 - if they are different, check override flag
1124 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001125 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 !memcmp(lladdr, neigh->ha, dev->addr_len))
1127 lladdr = neigh->ha;
1128 } else {
1129 /* No address is supplied; if we know something,
1130 use it, otherwise discard the request.
1131 */
1132 err = -EINVAL;
1133 if (!(old & NUD_VALID))
1134 goto out;
1135 lladdr = neigh->ha;
1136 }
1137
1138 if (new & NUD_CONNECTED)
1139 neigh->confirmed = jiffies;
1140 neigh->updated = jiffies;
1141
1142 /* If entry was valid and address is not changed,
1143 do not change entry state, if new one is STALE.
1144 */
1145 err = 0;
1146 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1147 if (old & NUD_VALID) {
1148 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1149 update_isrouter = 0;
1150 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1151 (old & NUD_CONNECTED)) {
1152 lladdr = neigh->ha;
1153 new = NUD_STALE;
1154 } else
1155 goto out;
1156 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001157 if (lladdr == neigh->ha && new == NUD_STALE &&
1158 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 new = old;
1160 }
1161 }
1162
1163 if (new != old) {
1164 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001165 if (new & NUD_PROBE)
1166 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001167 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001168 neigh_add_timer(neigh, (jiffies +
1169 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001170 neigh->parms->reachable_time :
1171 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001173 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 }
1175
1176 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001177 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001179 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 neigh_update_hhs(neigh);
1181 if (!(new & NUD_CONNECTED))
1182 neigh->confirmed = jiffies -
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001183 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 }
1186 if (new == old)
1187 goto out;
1188 if (new & NUD_CONNECTED)
1189 neigh_connect(neigh);
1190 else
1191 neigh_suspect(neigh);
1192 if (!(old & NUD_VALID)) {
1193 struct sk_buff *skb;
1194
1195 /* Again: avoid dead loop if something went wrong */
1196
1197 while (neigh->nud_state & NUD_VALID &&
1198 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001199 struct dst_entry *dst = skb_dst(skb);
1200 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001202
1203 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001204
1205 /* Why not just use 'neigh' as-is? The problem is that
1206 * things such as shaper, eql, and sch_teql can end up
1207 * using alternative, different, neigh objects to output
1208 * the packet in the output path. So what we need to do
1209 * here is re-lookup the top-level neigh in the path so
1210 * we can reinject the packet there.
1211 */
1212 n2 = NULL;
1213 if (dst) {
1214 n2 = dst_neigh_lookup_skb(dst, skb);
1215 if (n2)
1216 n1 = n2;
1217 }
David S. Miller8f40b162011-07-17 13:34:11 -07001218 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001219 if (n2)
1220 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001221 rcu_read_unlock();
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 write_lock_bh(&neigh->lock);
1224 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001225 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001226 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
1228out:
1229 if (update_isrouter) {
1230 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1231 (neigh->flags | NTF_ROUTER) :
1232 (neigh->flags & ~NTF_ROUTER);
1233 }
1234 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001235
1236 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001237 neigh_update_notify(neigh);
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 return err;
1240}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001241EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Jiri Benc7e980562013-12-11 13:48:20 +01001243/* Update the neigh to listen temporarily for probe responses, even if it is
1244 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1245 */
1246void __neigh_set_probe_once(struct neighbour *neigh)
1247{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001248 if (neigh->dead)
1249 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001250 neigh->updated = jiffies;
1251 if (!(neigh->nud_state & NUD_FAILED))
1252 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001253 neigh->nud_state = NUD_INCOMPLETE;
1254 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001255 neigh_add_timer(neigh,
1256 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1257}
1258EXPORT_SYMBOL(__neigh_set_probe_once);
1259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1261 u8 *lladdr, void *saddr,
1262 struct net_device *dev)
1263{
1264 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1265 lladdr || !dev->addr_len);
Ravinder Konkaa71b6682015-04-09 11:42:00 +05301266 if (neigh) {
1267 if (neigh_probe_enable) {
1268 if (!(neigh->nud_state == NUD_REACHABLE)) {
1269 neigh_update(neigh, lladdr, NUD_STALE,
1270 NEIGH_UPDATE_F_OVERRIDE);
1271 write_lock(&neigh->lock);
1272 neigh_probe(neigh);
1273 neigh_update_notify(neigh);
1274 }
1275 } else {
1276 neigh_update(neigh, lladdr, NUD_STALE,
1277 NEIGH_UPDATE_F_OVERRIDE);
1278 }
1279 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 return neigh;
1281}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001282EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001283
Eric Dumazet34d101d2010-10-11 09:16:57 -07001284/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001285static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001287 struct net_device *dev = n->dev;
1288 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001289 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001290
1291 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001292
David S. Millerf6b72b62011-07-14 07:53:20 -07001293 /* Only one thread can come in here and initialize the
1294 * hh_cache entry.
1295 */
David S. Millerb23b5452011-07-16 17:45:02 -07001296 if (!hh->hh_len)
1297 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001298
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001299 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300}
1301
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302/* Slow and careful. */
1303
David S. Miller8f40b162011-07-17 13:34:11 -07001304int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 int rc = 0;
1307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 if (!neigh_event_send(neigh, skb)) {
1309 int err;
1310 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001311 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001312
David S. Millerf6b72b62011-07-14 07:53:20 -07001313 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001314 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001315
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001316 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001317 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001318 seq = read_seqbegin(&neigh->ha_lock);
1319 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1320 neigh->ha, NULL, skb->len);
1321 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001324 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 else
1326 goto out_kfree_skb;
1327 }
1328out:
1329 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330out_kfree_skb:
1331 rc = -EINVAL;
1332 kfree_skb(skb);
1333 goto out;
1334}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001335EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
1337/* As fast as possible without hh cache */
1338
David S. Miller8f40b162011-07-17 13:34:11 -07001339int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001342 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001343 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001345 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001346 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001347 seq = read_seqbegin(&neigh->ha_lock);
1348 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1349 neigh->ha, NULL, skb->len);
1350 } while (read_seqretry(&neigh->ha_lock, seq));
1351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001353 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 else {
1355 err = -EINVAL;
1356 kfree_skb(skb);
1357 }
1358 return err;
1359}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001360EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361
David S. Miller8f40b162011-07-17 13:34:11 -07001362int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1363{
1364 return dev_queue_xmit(skb);
1365}
1366EXPORT_SYMBOL(neigh_direct_output);
1367
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368static void neigh_proxy_process(unsigned long arg)
1369{
1370 struct neigh_table *tbl = (struct neigh_table *)arg;
1371 long sched_next = 0;
1372 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001373 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
1375 spin_lock(&tbl->proxy_queue.lock);
1376
David S. Millerf72051b2008-09-23 01:11:18 -07001377 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1378 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001381 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001382
David S. Millerf72051b2008-09-23 01:11:18 -07001383 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001384 if (tbl->proxy_redo && netif_running(dev)) {
1385 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001386 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001387 rcu_read_unlock();
1388 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001389 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
1392 dev_put(dev);
1393 } else if (!sched_next || tdif < sched_next)
1394 sched_next = tdif;
1395 }
1396 del_timer(&tbl->proxy_timer);
1397 if (sched_next)
1398 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1399 spin_unlock(&tbl->proxy_queue.lock);
1400}
1401
1402void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1403 struct sk_buff *skb)
1404{
1405 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001406
1407 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001408 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001410 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 kfree_skb(skb);
1412 return;
1413 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001414
1415 NEIGH_CB(skb)->sched_next = sched_next;
1416 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 spin_lock(&tbl->proxy_queue.lock);
1419 if (del_timer(&tbl->proxy_timer)) {
1420 if (time_before(tbl->proxy_timer.expires, sched_next))
1421 sched_next = tbl->proxy_timer.expires;
1422 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001423 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 dev_hold(skb->dev);
1425 __skb_queue_tail(&tbl->proxy_queue, skb);
1426 mod_timer(&tbl->proxy_timer, sched_next);
1427 spin_unlock(&tbl->proxy_queue.lock);
1428}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001429EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001431static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001432 struct net *net, int ifindex)
1433{
1434 struct neigh_parms *p;
1435
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001436 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001437 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001438 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001439 return p;
1440 }
1441
1442 return NULL;
1443}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1446 struct neigh_table *tbl)
1447{
Gao fengcf89d6b2013-06-20 10:01:32 +08001448 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001449 struct net *net = dev_net(dev);
1450 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451
Gao fengcf89d6b2013-06-20 10:01:32 +08001452 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 p->tbl = tbl;
1455 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001457 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001458 dev_hold(dev);
1459 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001460 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001462
1463 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001464 dev_put(dev);
1465 kfree(p);
1466 return NULL;
1467 }
1468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001470 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001472
1473 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 }
1475 return p;
1476}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001477EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
1479static void neigh_rcu_free_parms(struct rcu_head *head)
1480{
1481 struct neigh_parms *parms =
1482 container_of(head, struct neigh_parms, rcu_head);
1483
1484 neigh_parms_put(parms);
1485}
1486
1487void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1488{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 if (!parms || parms == &tbl->parms)
1490 return;
1491 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001492 list_del(&parms->list);
1493 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001495 if (parms->dev)
1496 dev_put(parms->dev);
1497 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001499EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
Denis V. Lunev06f05112008-01-24 00:30:58 -08001501static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
1503 kfree(parms);
1504}
1505
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001506static struct lock_class_key neigh_table_proxy_queue_class;
1507
WANG Congd7480fd2014-11-10 15:59:36 -08001508static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1509
1510void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511{
1512 unsigned long now = jiffies;
1513 unsigned long phsize;
1514
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001515 INIT_LIST_HEAD(&tbl->parms_list);
1516 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001517 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 tbl->parms.reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001520 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 tbl->stats = alloc_percpu(struct neigh_statistics);
1523 if (!tbl->stats)
1524 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001527 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1528 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530#endif
1531
David S. Millercd089332011-07-11 01:28:12 -07001532 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
1534 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001535 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001537 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 panic("cannot allocate neighbour cache hashes");
1539
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001540 if (!tbl->entry_size)
1541 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1542 tbl->key_len, NEIGH_PRIV_ALIGN);
1543 else
1544 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001547 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301548 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1549 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001550 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001551 skb_queue_head_init_class(&tbl->proxy_queue,
1552 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
1554 tbl->last_flush = now;
1555 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001556
WANG Congd7480fd2014-11-10 15:59:36 -08001557 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001559EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
WANG Congd7480fd2014-11-10 15:59:36 -08001561int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562{
WANG Congd7480fd2014-11-10 15:59:36 -08001563 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001565 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 del_timer_sync(&tbl->proxy_timer);
1567 pneigh_queue_purge(&tbl->proxy_queue);
1568 neigh_ifdown(tbl, NULL);
1569 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001570 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001572 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1573 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001574 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575
1576 kfree(tbl->phash_buckets);
1577 tbl->phash_buckets = NULL;
1578
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001579 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1580
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001581 free_percpu(tbl->stats);
1582 tbl->stats = NULL;
1583
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 return 0;
1585}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001586EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
WANG Congd7480fd2014-11-10 15:59:36 -08001588static struct neigh_table *neigh_find_table(int family)
1589{
1590 struct neigh_table *tbl = NULL;
1591
1592 switch (family) {
1593 case AF_INET:
1594 tbl = neigh_tables[NEIGH_ARP_TABLE];
1595 break;
1596 case AF_INET6:
1597 tbl = neigh_tables[NEIGH_ND_TABLE];
1598 break;
1599 case AF_DECnet:
1600 tbl = neigh_tables[NEIGH_DN_TABLE];
1601 break;
1602 }
1603
1604 return tbl;
1605}
1606
Thomas Graf661d2962013-03-21 07:45:29 +00001607static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001609 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001610 struct ndmsg *ndm;
1611 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001613 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001615 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Eric Dumazet110b2492010-10-04 04:27:36 +00001617 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001618 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 goto out;
1620
Thomas Grafa14a49d2006-08-07 17:53:08 -07001621 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1622 if (dst_attr == NULL)
1623 goto out;
1624
1625 ndm = nlmsg_data(nlh);
1626 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001627 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001628 if (dev == NULL) {
1629 err = -ENODEV;
1630 goto out;
1631 }
1632 }
1633
WANG Congd7480fd2014-11-10 15:59:36 -08001634 tbl = neigh_find_table(ndm->ndm_family);
1635 if (tbl == NULL)
1636 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637
WANG Congd7480fd2014-11-10 15:59:36 -08001638 if (nla_len(dst_attr) < tbl->key_len)
1639 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
WANG Congd7480fd2014-11-10 15:59:36 -08001641 if (ndm->ndm_flags & NTF_PROXY) {
1642 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001643 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 }
WANG Congd7480fd2014-11-10 15:59:36 -08001645
1646 if (dev == NULL)
1647 goto out;
1648
1649 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1650 if (neigh == NULL) {
1651 err = -ENOENT;
1652 goto out;
1653 }
1654
1655 err = neigh_update(neigh, NULL, NUD_FAILED,
1656 NEIGH_UPDATE_F_OVERRIDE |
1657 NEIGH_UPDATE_F_ADMIN);
1658 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001659
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660out:
1661 return err;
1662}
1663
Thomas Graf661d2962013-03-21 07:45:29 +00001664static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665{
WANG Congd7480fd2014-11-10 15:59:36 -08001666 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001667 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001668 struct ndmsg *ndm;
1669 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 struct neigh_table *tbl;
1671 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001672 struct neighbour *neigh;
1673 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001674 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Eric Dumazet110b2492010-10-04 04:27:36 +00001676 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001677 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1678 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679 goto out;
1680
Thomas Graf5208deb2006-08-07 17:55:40 -07001681 err = -EINVAL;
1682 if (tb[NDA_DST] == NULL)
1683 goto out;
1684
1685 ndm = nlmsg_data(nlh);
1686 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001687 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001688 if (dev == NULL) {
1689 err = -ENODEV;
1690 goto out;
1691 }
1692
1693 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001694 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001695 }
1696
WANG Congd7480fd2014-11-10 15:59:36 -08001697 tbl = neigh_find_table(ndm->ndm_family);
1698 if (tbl == NULL)
1699 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
WANG Congd7480fd2014-11-10 15:59:36 -08001701 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1702 goto out;
1703 dst = nla_data(tb[NDA_DST]);
1704 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
WANG Congd7480fd2014-11-10 15:59:36 -08001706 if (ndm->ndm_flags & NTF_PROXY) {
1707 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
WANG Congd7480fd2014-11-10 15:59:36 -08001709 err = -ENOBUFS;
1710 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1711 if (pn) {
1712 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001713 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001714 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001715 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 }
1717
WANG Congd7480fd2014-11-10 15:59:36 -08001718 if (dev == NULL)
1719 goto out;
1720
1721 neigh = neigh_lookup(tbl, dst, dev);
1722 if (neigh == NULL) {
1723 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1724 err = -ENOENT;
1725 goto out;
1726 }
1727
1728 neigh = __neigh_lookup_errno(tbl, dst, dev);
1729 if (IS_ERR(neigh)) {
1730 err = PTR_ERR(neigh);
1731 goto out;
1732 }
1733 } else {
1734 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1735 err = -EEXIST;
1736 neigh_release(neigh);
1737 goto out;
1738 }
1739
1740 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1741 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1742 }
1743
1744 if (ndm->ndm_flags & NTF_USE) {
1745 neigh_event_send(neigh, NULL);
1746 err = 0;
1747 } else
1748 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1749 neigh_release(neigh);
1750
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751out:
1752 return err;
1753}
1754
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001755static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1756{
Thomas Grafca860fb2006-08-07 18:00:18 -07001757 struct nlattr *nest;
1758
1759 nest = nla_nest_start(skb, NDTA_PARMS);
1760 if (nest == NULL)
1761 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001762
David S. Miller9a6308d2012-04-01 20:06:28 -04001763 if ((parms->dev &&
1764 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1765 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001766 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1767 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001768 /* approximative value for deprecated QUEUE_LEN (in packets) */
1769 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001770 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1771 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1772 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1773 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1774 NEIGH_VAR(parms, UCAST_PROBES)) ||
1775 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1776 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001777 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1778 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001779 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1780 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001781 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001782 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001783 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001784 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001785 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001786 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001787 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001788 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001789 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001790 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001791 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001792 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001793 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001794 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001795 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001796 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001797
Thomas Grafca860fb2006-08-07 18:00:18 -07001798nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001799 nla_nest_cancel(skb, nest);
1800 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001801}
1802
Thomas Grafca860fb2006-08-07 18:00:18 -07001803static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1804 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001805{
1806 struct nlmsghdr *nlh;
1807 struct ndtmsg *ndtmsg;
1808
Thomas Grafca860fb2006-08-07 18:00:18 -07001809 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1810 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001811 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001812
Thomas Grafca860fb2006-08-07 18:00:18 -07001813 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001814
1815 read_lock_bh(&tbl->lock);
1816 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001817 ndtmsg->ndtm_pad1 = 0;
1818 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001819
David S. Miller9a6308d2012-04-01 20:06:28 -04001820 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001821 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001822 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1823 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1824 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1825 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001826 {
1827 unsigned long now = jiffies;
1828 unsigned int flush_delta = now - tbl->last_flush;
1829 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001830 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001831 struct ndt_config ndc = {
1832 .ndtc_key_len = tbl->key_len,
1833 .ndtc_entry_size = tbl->entry_size,
1834 .ndtc_entries = atomic_read(&tbl->entries),
1835 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1836 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001837 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1838 };
1839
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001840 rcu_read_lock_bh();
1841 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001842 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001843 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001844 rcu_read_unlock_bh();
1845
David S. Miller9a6308d2012-04-01 20:06:28 -04001846 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1847 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001848 }
1849
1850 {
1851 int cpu;
1852 struct ndt_stats ndst;
1853
1854 memset(&ndst, 0, sizeof(ndst));
1855
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001856 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001857 struct neigh_statistics *st;
1858
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001859 st = per_cpu_ptr(tbl->stats, cpu);
1860 ndst.ndts_allocs += st->allocs;
1861 ndst.ndts_destroys += st->destroys;
1862 ndst.ndts_hash_grows += st->hash_grows;
1863 ndst.ndts_res_failed += st->res_failed;
1864 ndst.ndts_lookups += st->lookups;
1865 ndst.ndts_hits += st->hits;
1866 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1867 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1868 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1869 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001870 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001871 }
1872
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001873 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1874 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001875 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001876 }
1877
1878 BUG_ON(tbl->parms.dev);
1879 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001880 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881
1882 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001883 nlmsg_end(skb, nlh);
1884 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001885
Thomas Grafca860fb2006-08-07 18:00:18 -07001886nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001888 nlmsg_cancel(skb, nlh);
1889 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001890}
1891
Thomas Grafca860fb2006-08-07 18:00:18 -07001892static int neightbl_fill_param_info(struct sk_buff *skb,
1893 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001894 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001895 u32 pid, u32 seq, int type,
1896 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001897{
1898 struct ndtmsg *ndtmsg;
1899 struct nlmsghdr *nlh;
1900
Thomas Grafca860fb2006-08-07 18:00:18 -07001901 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1902 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001903 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001904
Thomas Grafca860fb2006-08-07 18:00:18 -07001905 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001906
1907 read_lock_bh(&tbl->lock);
1908 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001909 ndtmsg->ndtm_pad1 = 0;
1910 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001911
Thomas Grafca860fb2006-08-07 18:00:18 -07001912 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1913 neightbl_fill_parms(skb, parms) < 0)
1914 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001915
1916 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001917 nlmsg_end(skb, nlh);
1918 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001919errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001920 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001921 nlmsg_cancel(skb, nlh);
1922 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001923}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001924
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001925static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001926 [NDTA_NAME] = { .type = NLA_STRING },
1927 [NDTA_THRESH1] = { .type = NLA_U32 },
1928 [NDTA_THRESH2] = { .type = NLA_U32 },
1929 [NDTA_THRESH3] = { .type = NLA_U32 },
1930 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1931 [NDTA_PARMS] = { .type = NLA_NESTED },
1932};
1933
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001934static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001935 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1936 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1937 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1938 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1939 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1940 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001941 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001942 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1943 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1944 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1945 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1946 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1947 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1948 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1949};
1950
Thomas Graf661d2962013-03-21 07:45:29 +00001951static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001952{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001953 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001954 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001955 struct ndtmsg *ndtmsg;
1956 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001957 bool found = false;
1958 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001959
Thomas Graf6b3f8672006-08-07 17:58:53 -07001960 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1961 nl_neightbl_policy);
1962 if (err < 0)
1963 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001964
Thomas Graf6b3f8672006-08-07 17:58:53 -07001965 if (tb[NDTA_NAME] == NULL) {
1966 err = -EINVAL;
1967 goto errout;
1968 }
1969
1970 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001971
1972 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1973 tbl = neigh_tables[tidx];
1974 if (!tbl)
1975 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001976 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1977 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08001978 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1979 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001980 break;
WANG Congd7480fd2014-11-10 15:59:36 -08001981 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001982 }
1983
WANG Congd7480fd2014-11-10 15:59:36 -08001984 if (!found)
1985 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001987 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988 * We acquire tbl->lock to be nice to the periodic timers and
1989 * make sure they always see a consistent set of values.
1990 */
1991 write_lock_bh(&tbl->lock);
1992
Thomas Graf6b3f8672006-08-07 17:58:53 -07001993 if (tb[NDTA_PARMS]) {
1994 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001995 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001996 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001997
Thomas Graf6b3f8672006-08-07 17:58:53 -07001998 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1999 nl_ntbl_parm_policy);
2000 if (err < 0)
2001 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002
Thomas Graf6b3f8672006-08-07 17:58:53 -07002003 if (tbp[NDTPA_IFINDEX])
2004 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002005
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002006 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002007 if (p == NULL) {
2008 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002011
Thomas Graf6b3f8672006-08-07 17:58:53 -07002012 for (i = 1; i <= NDTPA_MAX; i++) {
2013 if (tbp[i] == NULL)
2014 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002015
Thomas Graf6b3f8672006-08-07 17:58:53 -07002016 switch (i) {
2017 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002018 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2019 nla_get_u32(tbp[i]) *
2020 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002021 break;
2022 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002023 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2024 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 break;
2026 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002027 NEIGH_VAR_SET(p, PROXY_QLEN,
2028 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002029 break;
2030 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002031 NEIGH_VAR_SET(p, APP_PROBES,
2032 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002033 break;
2034 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002035 NEIGH_VAR_SET(p, UCAST_PROBES,
2036 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002037 break;
2038 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002039 NEIGH_VAR_SET(p, MCAST_PROBES,
2040 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002041 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002042 case NDTPA_MCAST_REPROBES:
2043 NEIGH_VAR_SET(p, MCAST_REPROBES,
2044 nla_get_u32(tbp[i]));
2045 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002047 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2048 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002049 /* update reachable_time as well, otherwise, the change will
2050 * only be effective after the next time neigh_periodic_work
2051 * decides to recompute it (can be multiple minutes)
2052 */
2053 p->reachable_time =
2054 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002055 break;
2056 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002057 NEIGH_VAR_SET(p, GC_STALETIME,
2058 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 break;
2060 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002061 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2062 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002063 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064 break;
2065 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002066 NEIGH_VAR_SET(p, RETRANS_TIME,
2067 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002068 break;
2069 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002070 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2071 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002072 break;
2073 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002074 NEIGH_VAR_SET(p, PROXY_DELAY,
2075 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002078 NEIGH_VAR_SET(p, LOCKTIME,
2079 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002080 break;
2081 }
2082 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002083 }
2084
Gao fengdc25c672013-06-20 10:01:34 +08002085 err = -ENOENT;
2086 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2087 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2088 !net_eq(net, &init_net))
2089 goto errout_tbl_lock;
2090
Thomas Graf6b3f8672006-08-07 17:58:53 -07002091 if (tb[NDTA_THRESH1])
2092 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2093
2094 if (tb[NDTA_THRESH2])
2095 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2096
2097 if (tb[NDTA_THRESH3])
2098 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2099
2100 if (tb[NDTA_GC_INTERVAL])
2101 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2102
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002103 err = 0;
2104
Thomas Graf6b3f8672006-08-07 17:58:53 -07002105errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002106 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002107errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002108 return err;
2109}
2110
Thomas Grafc8822a42007-03-22 11:50:06 -07002111static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002112{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002113 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002114 int family, tidx, nidx = 0;
2115 int tbl_skip = cb->args[0];
2116 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002117 struct neigh_table *tbl;
2118
Thomas Grafca860fb2006-08-07 18:00:18 -07002119 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002120
WANG Congd7480fd2014-11-10 15:59:36 -08002121 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002122 struct neigh_parms *p;
2123
WANG Congd7480fd2014-11-10 15:59:36 -08002124 tbl = neigh_tables[tidx];
2125 if (!tbl)
2126 continue;
2127
Thomas Grafca860fb2006-08-07 18:00:18 -07002128 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002129 continue;
2130
Eric W. Biederman15e47302012-09-07 20:12:54 +00002131 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002132 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002133 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002134 break;
2135
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002136 nidx = 0;
2137 p = list_next_entry(&tbl->parms, list);
2138 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002139 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002140 continue;
2141
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002142 if (nidx < neigh_skip)
2143 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144
Thomas Grafca860fb2006-08-07 18:00:18 -07002145 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002146 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002147 cb->nlh->nlmsg_seq,
2148 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002149 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002150 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002151 next:
2152 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002153 }
2154
Thomas Grafca860fb2006-08-07 18:00:18 -07002155 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002156 }
2157out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002158 cb->args[0] = tidx;
2159 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002160
2161 return skb->len;
2162}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163
Thomas Graf8b8aec52006-08-07 17:56:37 -07002164static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2165 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002166{
2167 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002169 struct nlmsghdr *nlh;
2170 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171
Thomas Graf8b8aec52006-08-07 17:56:37 -07002172 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2173 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002174 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002175
2176 ndm = nlmsg_data(nlh);
2177 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002178 ndm->ndm_pad1 = 0;
2179 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002180 ndm->ndm_flags = neigh->flags;
2181 ndm->ndm_type = neigh->type;
2182 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
David S. Miller9a6308d2012-04-01 20:06:28 -04002184 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2185 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002186
2187 read_lock_bh(&neigh->lock);
2188 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002189 if (neigh->nud_state & NUD_VALID) {
2190 char haddr[MAX_ADDR_LEN];
2191
2192 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2193 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2194 read_unlock_bh(&neigh->lock);
2195 goto nla_put_failure;
2196 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002197 }
2198
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002199 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2200 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2201 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002202 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2203 read_unlock_bh(&neigh->lock);
2204
David S. Miller9a6308d2012-04-01 20:06:28 -04002205 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2206 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2207 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002208
Johannes Berg053c0952015-01-16 22:09:00 +01002209 nlmsg_end(skb, nlh);
2210 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002211
2212nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002213 nlmsg_cancel(skb, nlh);
2214 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215}
2216
Tony Zelenoff84920c12012-01-26 22:28:58 +00002217static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2218 u32 pid, u32 seq, int type, unsigned int flags,
2219 struct neigh_table *tbl)
2220{
2221 struct nlmsghdr *nlh;
2222 struct ndmsg *ndm;
2223
2224 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2225 if (nlh == NULL)
2226 return -EMSGSIZE;
2227
2228 ndm = nlmsg_data(nlh);
2229 ndm->ndm_family = tbl->family;
2230 ndm->ndm_pad1 = 0;
2231 ndm->ndm_pad2 = 0;
2232 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002233 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002234 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002235 ndm->ndm_state = NUD_NONE;
2236
David S. Miller9a6308d2012-04-01 20:06:28 -04002237 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2238 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002239
Johannes Berg053c0952015-01-16 22:09:00 +01002240 nlmsg_end(skb, nlh);
2241 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002242
2243nla_put_failure:
2244 nlmsg_cancel(skb, nlh);
2245 return -EMSGSIZE;
2246}
2247
Thomas Grafd961db32007-08-08 23:12:56 -07002248static void neigh_update_notify(struct neighbour *neigh)
2249{
2250 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2251 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2252}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253
David Ahern21fdd092015-09-29 09:32:03 -07002254static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2255{
2256 struct net_device *master;
2257
2258 if (!master_idx)
2259 return false;
2260
2261 master = netdev_master_upper_dev_get(dev);
2262 if (!master || master->ifindex != master_idx)
2263 return true;
2264
2265 return false;
2266}
2267
David Ahern16660f02015-10-03 11:43:46 -07002268static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2269{
2270 if (filter_idx && dev->ifindex != filter_idx)
2271 return true;
2272
2273 return false;
2274}
2275
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2277 struct netlink_callback *cb)
2278{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002279 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002280 const struct nlmsghdr *nlh = cb->nlh;
2281 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 struct neighbour *n;
2283 int rc, h, s_h = cb->args[1];
2284 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002285 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002286 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002287 unsigned int flags = NLM_F_MULTI;
2288 int err;
2289
2290 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL);
2291 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002292 if (tb[NDA_IFINDEX])
2293 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2294
David Ahern21fdd092015-09-29 09:32:03 -07002295 if (tb[NDA_MASTER])
2296 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2297
David Ahern16660f02015-10-03 11:43:46 -07002298 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002299 flags |= NLM_F_DUMP_FILTERED;
2300 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002302 rcu_read_lock_bh();
2303 nht = rcu_dereference_bh(tbl->nht);
2304
Eric Dumazet4bd66832012-06-07 04:58:35 +00002305 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 if (h > s_h)
2307 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002308 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2309 n != NULL;
2310 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002311 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002312 continue;
David Ahern16660f02015-10-03 11:43:46 -07002313 if (neigh_ifindex_filtered(n->dev, filter_idx))
2314 continue;
David Ahern21fdd092015-09-29 09:32:03 -07002315 if (neigh_master_filtered(n->dev, filter_master_idx))
2316 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002317 if (idx < s_idx)
2318 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002319 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002321 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002322 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 rc = -1;
2324 goto out;
2325 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002326next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002327 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329 }
2330 rc = skb->len;
2331out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002332 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 cb->args[1] = h;
2334 cb->args[2] = idx;
2335 return rc;
2336}
2337
Tony Zelenoff84920c12012-01-26 22:28:58 +00002338static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2339 struct netlink_callback *cb)
2340{
2341 struct pneigh_entry *n;
2342 struct net *net = sock_net(skb->sk);
2343 int rc, h, s_h = cb->args[3];
2344 int idx, s_idx = idx = cb->args[4];
2345
2346 read_lock_bh(&tbl->lock);
2347
Eric Dumazet4bd66832012-06-07 04:58:35 +00002348 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002349 if (h > s_h)
2350 s_idx = 0;
2351 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002352 if (pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002353 continue;
2354 if (idx < s_idx)
2355 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002356 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002357 cb->nlh->nlmsg_seq,
2358 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002359 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002360 read_unlock_bh(&tbl->lock);
2361 rc = -1;
2362 goto out;
2363 }
2364 next:
2365 idx++;
2366 }
2367 }
2368
2369 read_unlock_bh(&tbl->lock);
2370 rc = skb->len;
2371out:
2372 cb->args[3] = h;
2373 cb->args[4] = idx;
2374 return rc;
2375
2376}
2377
Thomas Grafc8822a42007-03-22 11:50:06 -07002378static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379{
2380 struct neigh_table *tbl;
2381 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002382 int proxy = 0;
Eric Dumazet4bd66832012-06-07 04:58:35 +00002383 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384
Thomas Graf8b8aec52006-08-07 17:56:37 -07002385 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002386
2387 /* check for full ndmsg structure presence, family member is
2388 * the same for both structures
2389 */
2390 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2391 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2392 proxy = 1;
2393
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394 s_t = cb->args[0];
2395
WANG Congd7480fd2014-11-10 15:59:36 -08002396 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2397 tbl = neigh_tables[t];
2398
2399 if (!tbl)
2400 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 if (t < s_t || (family && tbl->family != family))
2402 continue;
2403 if (t > s_t)
2404 memset(&cb->args[1], 0, sizeof(cb->args) -
2405 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002406 if (proxy)
2407 err = pneigh_dump_table(tbl, skb, cb);
2408 else
2409 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd66832012-06-07 04:58:35 +00002410 if (err < 0)
2411 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
2414 cb->args[0] = t;
2415 return skb->len;
2416}
2417
2418void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2419{
2420 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002421 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002423 rcu_read_lock_bh();
2424 nht = rcu_dereference_bh(tbl->nht);
2425
Eric Dumazet767e97e2010-10-06 17:49:21 -07002426 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002427 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 struct neighbour *n;
2429
Eric Dumazet767e97e2010-10-06 17:49:21 -07002430 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2431 n != NULL;
2432 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 cb(n, cookie);
2434 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002435 read_unlock(&tbl->lock);
2436 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437}
2438EXPORT_SYMBOL(neigh_for_each);
2439
2440/* The tbl->lock must be held as a writer and BH disabled. */
2441void __neigh_for_each_release(struct neigh_table *tbl,
2442 int (*cb)(struct neighbour *))
2443{
2444 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002445 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002447 nht = rcu_dereference_protected(tbl->nht,
2448 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002449 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002450 struct neighbour *n;
2451 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002453 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002454 while ((n = rcu_dereference_protected(*np,
2455 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 int release;
2457
2458 write_lock(&n->lock);
2459 release = cb(n);
2460 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002461 rcu_assign_pointer(*np,
2462 rcu_dereference_protected(n->next,
2463 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 n->dead = 1;
2465 } else
2466 np = &n->next;
2467 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002468 if (release)
2469 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 }
2471 }
2472}
2473EXPORT_SYMBOL(__neigh_for_each_release);
2474
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002475int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002476 const void *addr, struct sk_buff *skb)
2477{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002478 int err = -EAFNOSUPPORT;
2479 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002480 struct neigh_table *tbl;
2481 struct neighbour *neigh;
2482
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002483 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002484 if (!tbl)
2485 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002486 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002487 neigh = __neigh_lookup_noref(tbl, addr, dev);
2488 if (!neigh)
2489 neigh = __neigh_create(tbl, addr, dev, false);
2490 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002491 if (IS_ERR(neigh)) {
2492 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002493 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002494 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002495 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002496 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002497 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002498 else if (index == NEIGH_LINK_TABLE) {
2499 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2500 addr, NULL, skb->len);
2501 if (err < 0)
2502 goto out_kfree_skb;
2503 err = dev_queue_xmit(skb);
2504 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002505out:
2506 return err;
2507out_kfree_skb:
2508 kfree_skb(skb);
2509 goto out;
2510}
2511EXPORT_SYMBOL(neigh_xmit);
2512
Linus Torvalds1da177e2005-04-16 15:20:36 -07002513#ifdef CONFIG_PROC_FS
2514
2515static struct neighbour *neigh_get_first(struct seq_file *seq)
2516{
2517 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002518 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002519 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 struct neighbour *n = NULL;
2521 int bucket = state->bucket;
2522
2523 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002524 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002525 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526
2527 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002528 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002529 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 if (state->neigh_sub_iter) {
2531 loff_t fakep = 0;
2532 void *v;
2533
2534 v = state->neigh_sub_iter(state, n, &fakep);
2535 if (!v)
2536 goto next;
2537 }
2538 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2539 break;
2540 if (n->nud_state & ~NUD_NOARP)
2541 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002542next:
2543 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 }
2545
2546 if (n)
2547 break;
2548 }
2549 state->bucket = bucket;
2550
2551 return n;
2552}
2553
2554static struct neighbour *neigh_get_next(struct seq_file *seq,
2555 struct neighbour *n,
2556 loff_t *pos)
2557{
2558 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002559 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002560 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
2562 if (state->neigh_sub_iter) {
2563 void *v = state->neigh_sub_iter(state, n, pos);
2564 if (v)
2565 return n;
2566 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002567 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002568
2569 while (1) {
2570 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002571 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002572 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 if (state->neigh_sub_iter) {
2574 void *v = state->neigh_sub_iter(state, n, pos);
2575 if (v)
2576 return n;
2577 goto next;
2578 }
2579 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2580 break;
2581
2582 if (n->nud_state & ~NUD_NOARP)
2583 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002584next:
2585 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 }
2587
2588 if (n)
2589 break;
2590
David S. Millercd089332011-07-11 01:28:12 -07002591 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 break;
2593
Eric Dumazet767e97e2010-10-06 17:49:21 -07002594 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595 }
2596
2597 if (n && pos)
2598 --(*pos);
2599 return n;
2600}
2601
2602static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2603{
2604 struct neighbour *n = neigh_get_first(seq);
2605
2606 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002607 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 while (*pos) {
2609 n = neigh_get_next(seq, n, pos);
2610 if (!n)
2611 break;
2612 }
2613 }
2614 return *pos ? NULL : n;
2615}
2616
2617static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2618{
2619 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002620 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 struct neigh_table *tbl = state->tbl;
2622 struct pneigh_entry *pn = NULL;
2623 int bucket = state->bucket;
2624
2625 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2626 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2627 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002628 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002629 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 if (pn)
2631 break;
2632 }
2633 state->bucket = bucket;
2634
2635 return pn;
2636}
2637
2638static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2639 struct pneigh_entry *pn,
2640 loff_t *pos)
2641{
2642 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002643 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002644 struct neigh_table *tbl = state->tbl;
2645
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002646 do {
2647 pn = pn->next;
2648 } while (pn && !net_eq(pneigh_net(pn), net));
2649
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 while (!pn) {
2651 if (++state->bucket > PNEIGH_HASHMASK)
2652 break;
2653 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002654 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002655 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656 if (pn)
2657 break;
2658 }
2659
2660 if (pn && pos)
2661 --(*pos);
2662
2663 return pn;
2664}
2665
2666static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2667{
2668 struct pneigh_entry *pn = pneigh_get_first(seq);
2669
2670 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002671 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 while (*pos) {
2673 pn = pneigh_get_next(seq, pn, pos);
2674 if (!pn)
2675 break;
2676 }
2677 }
2678 return *pos ? NULL : pn;
2679}
2680
2681static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2682{
2683 struct neigh_seq_state *state = seq->private;
2684 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002685 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686
Chris Larson745e2032008-08-03 01:10:55 -07002687 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002689 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
2691 return rc;
2692}
2693
2694void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002695 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696{
2697 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
2699 state->tbl = tbl;
2700 state->bucket = 0;
2701 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2702
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002703 rcu_read_lock_bh();
2704 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002705
Chris Larson745e2032008-08-03 01:10:55 -07002706 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707}
2708EXPORT_SYMBOL(neigh_seq_start);
2709
2710void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2711{
2712 struct neigh_seq_state *state;
2713 void *rc;
2714
2715 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002716 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 goto out;
2718 }
2719
2720 state = seq->private;
2721 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2722 rc = neigh_get_next(seq, v, NULL);
2723 if (rc)
2724 goto out;
2725 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2726 rc = pneigh_get_first(seq);
2727 } else {
2728 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2729 rc = pneigh_get_next(seq, v, NULL);
2730 }
2731out:
2732 ++(*pos);
2733 return rc;
2734}
2735EXPORT_SYMBOL(neigh_seq_next);
2736
2737void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002738 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002740 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741}
2742EXPORT_SYMBOL(neigh_seq_stop);
2743
2744/* statistics via seq_file */
2745
2746static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2747{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002748 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749 int cpu;
2750
2751 if (*pos == 0)
2752 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002753
Rusty Russell0f23174a2008-12-29 12:23:42 +00002754 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 if (!cpu_possible(cpu))
2756 continue;
2757 *pos = cpu+1;
2758 return per_cpu_ptr(tbl->stats, cpu);
2759 }
2760 return NULL;
2761}
2762
2763static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2764{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002765 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 int cpu;
2767
Rusty Russell0f23174a2008-12-29 12:23:42 +00002768 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 if (!cpu_possible(cpu))
2770 continue;
2771 *pos = cpu+1;
2772 return per_cpu_ptr(tbl->stats, cpu);
2773 }
2774 return NULL;
2775}
2776
2777static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2778{
2779
2780}
2781
2782static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2783{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002784 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 struct neigh_statistics *st = v;
2786
2787 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002788 seq_printf(seq, "entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789 return 0;
2790 }
2791
2792 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002793 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 atomic_read(&tbl->entries),
2795
2796 st->allocs,
2797 st->destroys,
2798 st->hash_grows,
2799
2800 st->lookups,
2801 st->hits,
2802
2803 st->res_failed,
2804
2805 st->rcv_probes_mcast,
2806 st->rcv_probes_ucast,
2807
2808 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002809 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002810 st->unres_discards,
2811 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812 );
2813
2814 return 0;
2815}
2816
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002817static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818 .start = neigh_stat_seq_start,
2819 .next = neigh_stat_seq_next,
2820 .stop = neigh_stat_seq_stop,
2821 .show = neigh_stat_seq_show,
2822};
2823
2824static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2825{
2826 int ret = seq_open(file, &neigh_stat_seq_ops);
2827
2828 if (!ret) {
2829 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002830 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002831 }
2832 return ret;
2833};
2834
Arjan van de Ven9a321442007-02-12 00:55:35 -08002835static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 .owner = THIS_MODULE,
2837 .open = neigh_stat_seq_open,
2838 .read = seq_read,
2839 .llseek = seq_lseek,
2840 .release = seq_release,
2841};
2842
2843#endif /* CONFIG_PROC_FS */
2844
Thomas Graf339bf982006-11-10 14:10:15 -08002845static inline size_t neigh_nlmsg_size(void)
2846{
2847 return NLMSG_ALIGN(sizeof(struct ndmsg))
2848 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2849 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2850 + nla_total_size(sizeof(struct nda_cacheinfo))
2851 + nla_total_size(4); /* NDA_PROBES */
2852}
2853
Thomas Grafb8673312006-08-15 00:33:14 -07002854static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002855{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002856 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002857 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002858 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859
Thomas Graf339bf982006-11-10 14:10:15 -08002860 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002861 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002862 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002863
Thomas Grafb8673312006-08-15 00:33:14 -07002864 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002865 if (err < 0) {
2866 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2867 WARN_ON(err == -EMSGSIZE);
2868 kfree_skb(skb);
2869 goto errout;
2870 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002871 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2872 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002873errout:
2874 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002875 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002876}
2877
2878void neigh_app_ns(struct neighbour *n)
2879{
2880 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002882EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883
2884#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002885static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002886static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002887static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002888
Joe Perchesfe2c6332013-06-11 23:04:25 -07002889static int proc_unres_qlen(struct ctl_table *ctl, int write,
2890 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002891{
2892 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002893 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002894
Shan Weice46cc62012-12-04 18:49:15 +00002895 tmp.extra1 = &zero;
2896 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002897 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002898
2899 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2900 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2901
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002902 if (write && !ret)
2903 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2904 return ret;
2905}
2906
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002907static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2908 int family)
2909{
Jiri Pirkobba24892013-12-07 19:26:57 +01002910 switch (family) {
2911 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002912 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002913 case AF_INET6:
2914 return __in6_dev_nd_parms_get_rcu(dev);
2915 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002916 return NULL;
2917}
2918
2919static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2920 int index)
2921{
2922 struct net_device *dev;
2923 int family = neigh_parms_family(p);
2924
2925 rcu_read_lock();
2926 for_each_netdev_rcu(net, dev) {
2927 struct neigh_parms *dst_p =
2928 neigh_get_dev_parms_rcu(dev, family);
2929
2930 if (dst_p && !test_bit(index, dst_p->data_state))
2931 dst_p->data[index] = p->data[index];
2932 }
2933 rcu_read_unlock();
2934}
2935
2936static void neigh_proc_update(struct ctl_table *ctl, int write)
2937{
2938 struct net_device *dev = ctl->extra1;
2939 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002940 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002941 int index = (int *) ctl->data - p->data;
2942
2943 if (!write)
2944 return;
2945
2946 set_bit(index, p->data_state);
Marcus Huewe6c854af2017-02-15 01:00:36 +01002947 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2948 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002949 if (!dev) /* NULL dev means this is default value */
2950 neigh_copy_dflt_parms(net, p, index);
2951}
2952
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002953static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2954 void __user *buffer,
2955 size_t *lenp, loff_t *ppos)
2956{
2957 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002958 int ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002959
2960 tmp.extra1 = &zero;
2961 tmp.extra2 = &int_max;
2962
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002963 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2964 neigh_proc_update(ctl, write);
2965 return ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002966}
2967
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002968int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2969 void __user *buffer, size_t *lenp, loff_t *ppos)
2970{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002971 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2972
2973 neigh_proc_update(ctl, write);
2974 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002975}
2976EXPORT_SYMBOL(neigh_proc_dointvec);
2977
2978int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2979 void __user *buffer,
2980 size_t *lenp, loff_t *ppos)
2981{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002982 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2983
2984 neigh_proc_update(ctl, write);
2985 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002986}
2987EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2988
2989static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2990 void __user *buffer,
2991 size_t *lenp, loff_t *ppos)
2992{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002993 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2994
2995 neigh_proc_update(ctl, write);
2996 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002997}
2998
2999int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3000 void __user *buffer,
3001 size_t *lenp, loff_t *ppos)
3002{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003003 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3004
3005 neigh_proc_update(ctl, write);
3006 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003007}
3008EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3009
3010static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3011 void __user *buffer,
3012 size_t *lenp, loff_t *ppos)
3013{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003014 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3015
3016 neigh_proc_update(ctl, write);
3017 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003018}
3019
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003020static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3021 void __user *buffer,
3022 size_t *lenp, loff_t *ppos)
3023{
3024 struct neigh_parms *p = ctl->extra2;
3025 int ret;
3026
3027 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3028 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3029 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3030 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3031 else
3032 ret = -1;
3033
3034 if (write && ret == 0) {
3035 /* update reachable_time as well, otherwise, the change will
3036 * only be effective after the next time neigh_periodic_work
3037 * decides to recompute it
3038 */
3039 p->reachable_time =
3040 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3041 }
3042 return ret;
3043}
3044
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003045#define NEIGH_PARMS_DATA_OFFSET(index) \
3046 (&((struct neigh_parms *) 0)->data[index])
3047
3048#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3049 [NEIGH_VAR_ ## attr] = { \
3050 .procname = name, \
3051 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3052 .maxlen = sizeof(int), \
3053 .mode = mval, \
3054 .proc_handler = proc, \
3055 }
3056
3057#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3058 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3059
3060#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003061 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003062
3063#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003064 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003065
3066#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003067 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003068
3069#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003070 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003071
3072#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003073 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003074
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075static struct neigh_sysctl_table {
3076 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003077 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003078} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 .neigh_vars = {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003080 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3081 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3082 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003083 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003084 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3085 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3086 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3087 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3088 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3089 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3090 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3091 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3092 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3093 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3094 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3095 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003096 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 .procname = "gc_interval",
3098 .maxlen = sizeof(int),
3099 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003100 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003102 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 .procname = "gc_thresh1",
3104 .maxlen = sizeof(int),
3105 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003106 .extra1 = &zero,
3107 .extra2 = &int_max,
3108 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003110 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 .procname = "gc_thresh2",
3112 .maxlen = sizeof(int),
3113 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003114 .extra1 = &zero,
3115 .extra2 = &int_max,
3116 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003118 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 .procname = "gc_thresh3",
3120 .maxlen = sizeof(int),
3121 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003122 .extra1 = &zero,
3123 .extra2 = &int_max,
3124 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 },
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303126 [NEIGH_VAR_PROBE] = {
3127 .procname = "neigh_probe",
3128 .maxlen = sizeof(int),
3129 .mode = 0644,
3130 .proc_handler = proc_dointvec,
3131 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003132 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 },
3134};
3135
3136int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003137 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138{
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003139 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003140 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003141 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003142 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003143 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003145 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003147 goto err;
3148
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003149 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003150 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003151 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003152 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154
3155 if (dev) {
3156 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003157 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003158 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3159 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003161 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003162 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003163 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3164 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3165 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3166 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303167 t->neigh_vars[NEIGH_VAR_PROBE].data = &neigh_probe_enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168 }
3169
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003170 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003172 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003173 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003174 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003176 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003177 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003178 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003179 } else {
3180 /* Those handlers will update p->reachable_time after
3181 * base_reachable_time(_ms) is set to ensure the new timer starts being
3182 * applied after the next neighbour update instead of waiting for
3183 * neigh_periodic_work to update its value (can be multiple minutes)
3184 * So any handler that replaces them should do this as well
3185 */
3186 /* ReachableTime */
3187 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3188 neigh_proc_base_reachable_time;
3189 /* ReachableTime (in milliseconds) */
3190 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3191 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 }
3193
Eric W. Biederman464dc802012-11-16 03:02:59 +00003194 /* Don't export sysctls to unprivileged users */
3195 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3196 t->neigh_vars[0].procname = NULL;
3197
Jiri Pirko73af6142013-12-07 19:26:55 +01003198 switch (neigh_parms_family(p)) {
3199 case AF_INET:
3200 p_name = "ipv4";
3201 break;
3202 case AF_INET6:
3203 p_name = "ipv6";
3204 break;
3205 default:
3206 BUG();
3207 }
3208
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003209 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3210 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003211 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003212 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003213 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003214 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003215
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 p->sysctl_table = t;
3217 return 0;
3218
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003219free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003221err:
3222 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003223}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003224EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003225
3226void neigh_sysctl_unregister(struct neigh_parms *p)
3227{
3228 if (p->sysctl_table) {
3229 struct neigh_sysctl_table *t = p->sysctl_table;
3230 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003231 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 kfree(t);
3233 }
3234}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003235EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236
3237#endif /* CONFIG_SYSCTL */
3238
Thomas Grafc8822a42007-03-22 11:50:06 -07003239static int __init neigh_init(void)
3240{
Greg Rosec7ac8672011-06-10 01:27:09 +00003241 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3242 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3243 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003244
Greg Rosec7ac8672011-06-10 01:27:09 +00003245 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3246 NULL);
3247 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003248
3249 return 0;
3250}
3251
3252subsys_initcall(neigh_init);
3253