blob: 59399fad65a21ac0f83537815b360f764be6f0b5 [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
59static struct neigh_table *neigh_tables;
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.
90
91 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
92 list of neighbour tables. This list is used only in process context,
93 */
94
95static DEFINE_RWLOCK(neigh_tbl_lock);
96
David S. Miller8f40b162011-07-17 13:34:11 -070097static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
99 kfree_skb(skb);
100 return -ENETDOWN;
101}
102
Thomas Graf4f494552007-08-08 23:12:36 -0700103static void neigh_cleanup_and_release(struct neighbour *neigh)
104{
105 if (neigh->parms->neigh_cleanup)
106 neigh->parms->neigh_cleanup(neigh);
107
Thomas Grafd961db32007-08-08 23:12:56 -0700108 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700109 neigh_release(neigh);
110}
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112/*
113 * It is random distribution in the interval (1/2)*base...(3/2)*base.
114 * It corresponds to default IPv6 settings and is not overridable,
115 * because it is really reasonable choice.
116 */
117
118unsigned long neigh_rand_reach_time(unsigned long base)
119{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500120 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900122EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124
125static int neigh_forced_gc(struct neigh_table *tbl)
126{
127 int shrunk = 0;
128 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000129 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
132
133 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000134 nht = rcu_dereference_protected(tbl->nht,
135 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700136 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700137 struct neighbour *n;
138 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000140 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700141 while ((n = rcu_dereference_protected(*np,
142 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 /* Neighbour record may be discarded if:
144 * - nobody refers to it.
145 * - it is not permanent
146 */
147 write_lock(&n->lock);
148 if (atomic_read(&n->refcnt) == 1 &&
149 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700150 rcu_assign_pointer(*np,
151 rcu_dereference_protected(n->next,
152 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 n->dead = 1;
154 shrunk = 1;
155 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700156 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 continue;
158 }
159 write_unlock(&n->lock);
160 np = &n->next;
161 }
162 }
163
164 tbl->last_flush = jiffies;
165
166 write_unlock_bh(&tbl->lock);
167
168 return shrunk;
169}
170
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800171static void neigh_add_timer(struct neighbour *n, unsigned long when)
172{
173 neigh_hold(n);
174 if (unlikely(mod_timer(&n->timer, when))) {
175 printk("NEIGH: BUG, double timer add, state is %x\n",
176 n->nud_state);
177 dump_stack();
178 }
179}
180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181static int neigh_del_timer(struct neighbour *n)
182{
183 if ((n->nud_state & NUD_IN_TIMER) &&
184 del_timer(&n->timer)) {
185 neigh_release(n);
186 return 1;
187 }
188 return 0;
189}
190
191static void pneigh_queue_purge(struct sk_buff_head *list)
192{
193 struct sk_buff *skb;
194
195 while ((skb = skb_dequeue(list)) != NULL) {
196 dev_put(skb->dev);
197 kfree_skb(skb);
198 }
199}
200
Herbert Xu49636bb2005-10-23 17:18:00 +1000201static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202{
203 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000204 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000206 nht = rcu_dereference_protected(tbl->nht,
207 lockdep_is_held(&tbl->lock));
208
David S. Millercd089332011-07-11 01:28:12 -0700209 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700210 struct neighbour *n;
211 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Eric Dumazet767e97e2010-10-06 17:49:21 -0700213 while ((n = rcu_dereference_protected(*np,
214 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (dev && n->dev != dev) {
216 np = &n->next;
217 continue;
218 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700219 rcu_assign_pointer(*np,
220 rcu_dereference_protected(n->next,
221 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 write_lock(&n->lock);
223 neigh_del_timer(n);
224 n->dead = 1;
225
226 if (atomic_read(&n->refcnt) != 1) {
227 /* The most unpleasant situation.
228 We must destroy neighbour entry,
229 but someone still uses it.
230
231 The destroy will be delayed until
232 the last user releases us, but
233 we must kill timers etc. and move
234 it to safe state.
235 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700236 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000237 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 n->output = neigh_blackhole;
239 if (n->nud_state & NUD_VALID)
240 n->nud_state = NUD_NOARP;
241 else
242 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000243 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 }
245 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700246 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 }
248 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000249}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Herbert Xu49636bb2005-10-23 17:18:00 +1000251void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
252{
253 write_lock_bh(&tbl->lock);
254 neigh_flush_dev(tbl, dev);
255 write_unlock_bh(&tbl->lock);
256}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900257EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000258
259int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
260{
261 write_lock_bh(&tbl->lock);
262 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 pneigh_ifdown(tbl, dev);
264 write_unlock_bh(&tbl->lock);
265
266 del_timer_sync(&tbl->proxy_timer);
267 pneigh_queue_purge(&tbl->proxy_queue);
268 return 0;
269}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900270EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
David Miller596b9b62011-07-25 00:01:25 +0000272static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273{
274 struct neighbour *n = NULL;
275 unsigned long now = jiffies;
276 int entries;
277
278 entries = atomic_inc_return(&tbl->entries) - 1;
279 if (entries >= tbl->gc_thresh3 ||
280 (entries >= tbl->gc_thresh2 &&
281 time_after(now, tbl->last_flush + 5 * HZ))) {
282 if (!neigh_forced_gc(tbl) &&
283 entries >= tbl->gc_thresh3)
284 goto out_entries;
285 }
286
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000287 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 if (!n)
289 goto out_entries;
290
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700291 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000293 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 n->updated = n->used = now;
295 n->nud_state = NUD_NONE;
296 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700297 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800299 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 NEIGH_CACHE_STAT_INC(tbl, allocs);
302 n->tbl = tbl;
303 atomic_set(&n->refcnt, 1);
304 n->dead = 1;
305out:
306 return n;
307
308out_entries:
309 atomic_dec(&tbl->entries);
310 goto out;
311}
312
David S. Miller2c2aba62011-12-28 15:06:58 -0500313static void neigh_get_hash_rnd(u32 *x)
314{
315 get_random_bytes(x, sizeof(*x));
316 *x |= 1;
317}
318
David S. Millercd089332011-07-11 01:28:12 -0700319static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
David S. Millercd089332011-07-11 01:28:12 -0700321 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000322 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000323 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500324 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000326 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
327 if (!ret)
328 return NULL;
329 if (size <= PAGE_SIZE)
330 buckets = kzalloc(size, GFP_ATOMIC);
331 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000332 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000333 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
334 get_order(size));
335 if (!buckets) {
336 kfree(ret);
337 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000339 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700340 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500341 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
342 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return ret;
344}
345
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000346static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000348 struct neigh_hash_table *nht = container_of(head,
349 struct neigh_hash_table,
350 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700351 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000352 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000355 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000357 free_pages((unsigned long)buckets, get_order(size));
358 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000361static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700362 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000364 unsigned int i, hash;
365 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
368
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000369 old_nht = rcu_dereference_protected(tbl->nht,
370 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700371 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000372 if (!new_nht)
373 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
David S. Millercd089332011-07-11 01:28:12 -0700375 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 struct neighbour *n, *next;
377
Eric Dumazet767e97e2010-10-06 17:49:21 -0700378 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
379 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000380 n != NULL;
381 n = next) {
382 hash = tbl->hash(n->primary_key, n->dev,
383 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
David S. Millercd089332011-07-11 01:28:12 -0700385 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700386 next = rcu_dereference_protected(n->next,
387 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Eric Dumazet767e97e2010-10-06 17:49:21 -0700389 rcu_assign_pointer(n->next,
390 rcu_dereference_protected(
391 new_nht->hash_buckets[hash],
392 lockdep_is_held(&tbl->lock)));
393 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000397 rcu_assign_pointer(tbl->nht, new_nht);
398 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
399 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400}
401
402struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
403 struct net_device *dev)
404{
405 struct neighbour *n;
406 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800407 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 struct neigh_hash_table *nht;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 NEIGH_CACHE_STAT_INC(tbl, lookups);
411
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000412 rcu_read_lock_bh();
413 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700414 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700415
416 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
417 n != NULL;
418 n = rcu_dereference_bh(n->next)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700420 if (!atomic_inc_not_zero(&n->refcnt))
421 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 NEIGH_CACHE_STAT_INC(tbl, hits);
423 break;
424 }
425 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700426
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 return n;
429}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900430EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Eric W. Biederman426b5302008-01-24 00:13:18 -0800432struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
433 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
435 struct neighbour *n;
436 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800437 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000438 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440 NEIGH_CACHE_STAT_INC(tbl, lookups);
441
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000442 rcu_read_lock_bh();
443 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700444 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700445
446 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
447 n != NULL;
448 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800449 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900450 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700451 if (!atomic_inc_not_zero(&n->refcnt))
452 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 NEIGH_CACHE_STAT_INC(tbl, hits);
454 break;
455 }
456 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700457
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000458 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 return n;
460}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900461EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
David S. Millera263b302012-07-02 02:02:15 -0700463struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
464 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 u32 hash_val;
467 int key_len = tbl->key_len;
468 int error;
David Miller596b9b62011-07-25 00:01:25 +0000469 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000470 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 if (!n) {
473 rc = ERR_PTR(-ENOBUFS);
474 goto out;
475 }
476
477 memcpy(n->primary_key, pkey, key_len);
478 n->dev = dev;
479 dev_hold(dev);
480
481 /* Protocol specific setup. */
482 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
483 rc = ERR_PTR(error);
484 goto out_neigh_release;
485 }
486
David Millerda6a8fa2011-07-25 00:01:38 +0000487 if (dev->netdev_ops->ndo_neigh_construct) {
488 error = dev->netdev_ops->ndo_neigh_construct(n);
489 if (error < 0) {
490 rc = ERR_PTR(error);
491 goto out_neigh_release;
492 }
493 }
494
David S. Miller447f2192011-12-19 15:04:41 -0500495 /* Device specific setup. */
496 if (n->parms->neigh_setup &&
497 (error = n->parms->neigh_setup(n)) < 0) {
498 rc = ERR_PTR(error);
499 goto out_neigh_release;
500 }
501
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100502 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000505 nht = rcu_dereference_protected(tbl->nht,
506 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
David S. Millercd089332011-07-11 01:28:12 -0700508 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
509 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
David S. Millercd089332011-07-11 01:28:12 -0700511 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 if (n->parms->dead) {
514 rc = ERR_PTR(-EINVAL);
515 goto out_tbl_unlock;
516 }
517
Eric Dumazet767e97e2010-10-06 17:49:21 -0700518 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
519 lockdep_is_held(&tbl->lock));
520 n1 != NULL;
521 n1 = rcu_dereference_protected(n1->next,
522 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700524 if (want_ref)
525 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 rc = n1;
527 goto out_tbl_unlock;
528 }
529 }
530
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700532 if (want_ref)
533 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700534 rcu_assign_pointer(n->next,
535 rcu_dereference_protected(nht->hash_buckets[hash_val],
536 lockdep_is_held(&tbl->lock)));
537 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000539 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 rc = n;
541out:
542 return rc;
543out_tbl_unlock:
544 write_unlock_bh(&tbl->lock);
545out_neigh_release:
546 neigh_release(n);
547 goto out;
548}
David S. Millera263b302012-07-02 02:02:15 -0700549EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900551static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700552{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700553 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700554 hash_val ^= (hash_val >> 16);
555 hash_val ^= hash_val >> 8;
556 hash_val ^= hash_val >> 4;
557 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 return hash_val;
559}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700560
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900561static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
562 struct net *net,
563 const void *pkey,
564 int key_len,
565 struct net_device *dev)
566{
567 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700568 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900569 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700570 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900571 return n;
572 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700573 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900574 return NULL;
575}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900577struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
578 struct net *net, const void *pkey, struct net_device *dev)
579{
580 int key_len = tbl->key_len;
581 u32 hash_val = pneigh_hash(pkey, key_len);
582
583 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
584 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700585}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900586EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700587
Eric W. Biederman426b5302008-01-24 00:13:18 -0800588struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
589 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 struct net_device *dev, int creat)
591{
592 struct pneigh_entry *n;
593 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900594 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900597 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
598 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900600
601 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 goto out;
603
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700604 ASSERT_RTNL();
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
607 if (!n)
608 goto out;
609
Eric Dumazete42ea982008-11-12 00:54:54 -0800610 write_pnet(&n->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 memcpy(n->key, pkey, key_len);
612 n->dev = dev;
613 if (dev)
614 dev_hold(dev);
615
616 if (tbl->pconstructor && tbl->pconstructor(n)) {
617 if (dev)
618 dev_put(dev);
Denis V. Lunevda12f732008-02-20 00:26:16 -0800619 release_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 kfree(n);
621 n = NULL;
622 goto out;
623 }
624
625 write_lock_bh(&tbl->lock);
626 n->next = tbl->phash_buckets[hash_val];
627 tbl->phash_buckets[hash_val] = n;
628 write_unlock_bh(&tbl->lock);
629out:
630 return n;
631}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900632EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634
Eric W. Biederman426b5302008-01-24 00:13:18 -0800635int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 struct net_device *dev)
637{
638 struct pneigh_entry *n, **np;
639 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900640 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642 write_lock_bh(&tbl->lock);
643 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
644 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800645 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900646 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 *np = n->next;
648 write_unlock_bh(&tbl->lock);
649 if (tbl->pdestructor)
650 tbl->pdestructor(n);
651 if (n->dev)
652 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900653 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 kfree(n);
655 return 0;
656 }
657 }
658 write_unlock_bh(&tbl->lock);
659 return -ENOENT;
660}
661
662static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
663{
664 struct pneigh_entry *n, **np;
665 u32 h;
666
667 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
668 np = &tbl->phash_buckets[h];
669 while ((n = *np) != NULL) {
670 if (!dev || n->dev == dev) {
671 *np = n->next;
672 if (tbl->pdestructor)
673 tbl->pdestructor(n);
674 if (n->dev)
675 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900676 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 kfree(n);
678 continue;
679 }
680 np = &n->next;
681 }
682 }
683 return -ENOENT;
684}
685
Denis V. Lunev06f05112008-01-24 00:30:58 -0800686static void neigh_parms_destroy(struct neigh_parms *parms);
687
688static inline void neigh_parms_put(struct neigh_parms *parms)
689{
690 if (atomic_dec_and_test(&parms->refcnt))
691 neigh_parms_destroy(parms);
692}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694/*
695 * neighbour must already be out of the table;
696 *
697 */
698void neigh_destroy(struct neighbour *neigh)
699{
David Millerda6a8fa2011-07-25 00:01:38 +0000700 struct net_device *dev = neigh->dev;
701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
703
704 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000705 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 dump_stack();
707 return;
708 }
709
710 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000711 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700713 write_lock_bh(&neigh->lock);
714 __skb_queue_purge(&neigh->arp_queue);
715 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000716 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
David S. Miller447f2192011-12-19 15:04:41 -0500718 if (dev->netdev_ops->ndo_neigh_destroy)
719 dev->netdev_ops->ndo_neigh_destroy(neigh);
720
David Millerda6a8fa2011-07-25 00:01:38 +0000721 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 neigh_parms_put(neigh->parms);
723
Joe Perchesd5d427c2013-04-15 15:17:19 +0000724 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000727 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900729EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731/* Neighbour state is suspicious;
732 disable fast path.
733
734 Called with write_locked neigh.
735 */
736static void neigh_suspect(struct neighbour *neigh)
737{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000738 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741}
742
743/* Neighbour state is OK;
744 enable fast path.
745
746 Called with write_locked neigh.
747 */
748static void neigh_connect(struct neighbour *neigh)
749{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000750 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Eric Dumazete4c4e442009-07-30 03:15:07 +0000755static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000757 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700758 struct neighbour *n;
759 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000760 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000761 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
764
Eric Dumazete4c4e442009-07-30 03:15:07 +0000765 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000766 nht = rcu_dereference_protected(tbl->nht,
767 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 /*
770 * periodically recompute ReachableTime from random function
771 */
772
Eric Dumazete4c4e442009-07-30 03:15:07 +0000773 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 for (p = &tbl->parms; p; p = p->next)
777 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100778 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 }
780
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800781 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
782 goto out;
783
David S. Millercd089332011-07-11 01:28:12 -0700784 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000785 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Eric Dumazet767e97e2010-10-06 17:49:21 -0700787 while ((n = rcu_dereference_protected(*np,
788 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Eric Dumazete4c4e442009-07-30 03:15:07 +0000793 state = n->nud_state;
794 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
795 write_unlock(&n->lock);
796 goto next_elt;
797 }
798
799 if (time_before(n->used, n->confirmed))
800 n->used = n->confirmed;
801
802 if (atomic_read(&n->refcnt) == 1 &&
803 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100804 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000805 *np = n->next;
806 n->dead = 1;
807 write_unlock(&n->lock);
808 neigh_cleanup_and_release(n);
809 continue;
810 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000814 np = &n->next;
815 }
816 /*
817 * It's fine to release lock here, even if hash table
818 * grows while we are preempted.
819 */
820 write_unlock_bh(&tbl->lock);
821 cond_resched();
822 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500823 nht = rcu_dereference_protected(tbl->nht,
824 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000826out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100827 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
828 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
829 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 */
viresh kumarf6180022014-01-22 12:23:33 +0530831 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100832 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000833 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834}
835
836static __inline__ int neigh_max_probes(struct neighbour *n)
837{
838 struct neigh_parms *p = n->parms;
Timo Teräsa960ff82014-02-26 11:43:04 +0200839 int max_probes = NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES);
840 if (!(n->nud_state & NUD_PROBE))
841 max_probes += NEIGH_VAR(p, MCAST_PROBES);
842 return max_probes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Timo Teras5ef12d92009-06-11 04:16:28 -0700845static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000846 __releases(neigh->lock)
847 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700848{
849 struct sk_buff *skb;
850
851 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000852 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700853 neigh->updated = jiffies;
854
855 /* It is very thin place. report_unreachable is very complicated
856 routine. Particularly, it can hit the same neighbour entry!
857
858 So that, we try to be accurate and avoid dead loop. --ANK
859 */
860 while (neigh->nud_state == NUD_FAILED &&
861 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
862 write_unlock(&neigh->lock);
863 neigh->ops->error_report(neigh, skb);
864 write_lock(&neigh->lock);
865 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700866 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000867 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700868}
869
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000870static void neigh_probe(struct neighbour *neigh)
871 __releases(neigh->lock)
872{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200873 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000874 /* keep skb alive even if arp_queue overflows */
875 if (skb)
876 skb = skb_copy(skb, GFP_ATOMIC);
877 write_unlock(&neigh->lock);
Eric Dumazetbb904f22017-03-23 12:39:21 -0700878 if (neigh->ops->solicit)
879 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000880 atomic_inc(&neigh->probes);
881 kfree_skb(skb);
882}
883
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884/* Called when a timer expires for a neighbour entry. */
885
886static void neigh_timer_handler(unsigned long arg)
887{
888 unsigned long now, next;
889 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000890 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 int notify = 0;
892
893 write_lock(&neigh->lock);
894
895 state = neigh->nud_state;
896 now = jiffies;
897 next = now + HZ;
898
David S. Miller045f7b32011-11-01 17:45:55 -0400899 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900903 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000905 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906 next = neigh->confirmed + neigh->parms->reachable_time;
907 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100908 neigh->used +
909 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000910 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800912 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100914 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000916 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800918 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700920 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
922 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900923 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100924 neigh->confirmed +
925 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000926 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800928 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700930 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 next = neigh->confirmed + neigh->parms->reachable_time;
932 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000933 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800935 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100937 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 } else {
940 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100941 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 }
943
944 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
945 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 neigh->nud_state = NUD_FAILED;
947 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700948 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800949 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
951
952 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if (time_before(next, jiffies + HZ/2))
954 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000955 if (!mod_timer(&neigh->timer, next))
956 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 }
958 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000959 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800960 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800961out:
David S. Miller9ff56602008-02-17 18:39:54 -0800962 write_unlock(&neigh->lock);
963 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964
Thomas Grafd961db32007-08-08 23:12:56 -0700965 if (notify)
966 neigh_update_notify(neigh);
967
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 neigh_release(neigh);
969}
970
971int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
972{
973 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000974 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
976 write_lock_bh(&neigh->lock);
977
978 rc = 0;
979 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
980 goto out_unlock_bh;
Julian Anastasov76488fa2015-06-16 22:56:39 +0300981 if (neigh->dead)
982 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100985 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
986 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000987 unsigned long next, now = jiffies;
988
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100989 atomic_set(&neigh->probes,
990 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000992 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100993 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
994 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000995 neigh_add_timer(neigh, next);
996 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 } else {
998 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800999 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 write_unlock_bh(&neigh->lock);
1001
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001002 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 return 1;
1004 }
1005 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001006 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001008 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001009 neigh_add_timer(neigh, jiffies +
1010 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 }
1012
1013 if (neigh->nud_state == NUD_INCOMPLETE) {
1014 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001015 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001016 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001018
David S. Millerf72051b2008-09-23 01:11:18 -07001019 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001020 if (!buff)
1021 break;
1022 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001024 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001026 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001028 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 }
1030 rc = 1;
1031 }
1032out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001033 if (immediate_probe)
1034 neigh_probe(neigh);
1035 else
1036 write_unlock(&neigh->lock);
1037 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 return rc;
Julian Anastasov76488fa2015-06-16 22:56:39 +03001039
1040out_dead:
1041 if (neigh->nud_state & NUD_STALE)
1042 goto out_unlock_bh;
1043 write_unlock_bh(&neigh->lock);
1044 kfree_skb(skb);
1045 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001047EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048
David S. Millerf6b72b62011-07-14 07:53:20 -07001049static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050{
1051 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001052 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001053 = NULL;
1054
1055 if (neigh->dev->header_ops)
1056 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057
1058 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001059 hh = &neigh->hh;
1060 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001061 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001063 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 }
1065 }
1066}
1067
1068
1069
1070/* Generic update routine.
1071 -- lladdr is new lladdr or NULL, if it is not supplied.
1072 -- new is new state.
1073 -- flags
1074 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1075 if it is different.
1076 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001077 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 if it is different.
1079 It also allows to retain current state
1080 if lladdr is unchanged.
1081 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1082
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001083 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 NTF_ROUTER flag.
1085 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1086 a router.
1087
1088 Caller MUST hold reference count on the entry.
1089 */
1090
1091int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1092 u32 flags)
1093{
1094 u8 old;
1095 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 struct net_device *dev;
1098 int update_isrouter = 0;
1099
1100 write_lock_bh(&neigh->lock);
1101
1102 dev = neigh->dev;
1103 old = neigh->nud_state;
1104 err = -EPERM;
1105
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001106 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 (old & (NUD_NOARP | NUD_PERMANENT)))
1108 goto out;
Julian Anastasov76488fa2015-06-16 22:56:39 +03001109 if (neigh->dead)
1110 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 if (!(new & NUD_VALID)) {
1113 neigh_del_timer(neigh);
1114 if (old & NUD_CONNECTED)
1115 neigh_suspect(neigh);
1116 neigh->nud_state = new;
1117 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001118 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001119 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1120 (new & NUD_FAILED)) {
1121 neigh_invalidate(neigh);
1122 notify = 1;
1123 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 goto out;
1125 }
1126
1127 /* Compare new lladdr with cached one */
1128 if (!dev->addr_len) {
1129 /* First case: device needs no address. */
1130 lladdr = neigh->ha;
1131 } else if (lladdr) {
1132 /* The second case: if something is already cached
1133 and a new address is proposed:
1134 - compare new & old
1135 - if they are different, check override flag
1136 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001137 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 !memcmp(lladdr, neigh->ha, dev->addr_len))
1139 lladdr = neigh->ha;
1140 } else {
1141 /* No address is supplied; if we know something,
1142 use it, otherwise discard the request.
1143 */
1144 err = -EINVAL;
1145 if (!(old & NUD_VALID))
1146 goto out;
1147 lladdr = neigh->ha;
1148 }
1149
1150 if (new & NUD_CONNECTED)
1151 neigh->confirmed = jiffies;
1152 neigh->updated = jiffies;
1153
1154 /* If entry was valid and address is not changed,
1155 do not change entry state, if new one is STALE.
1156 */
1157 err = 0;
1158 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1159 if (old & NUD_VALID) {
1160 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1161 update_isrouter = 0;
1162 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1163 (old & NUD_CONNECTED)) {
1164 lladdr = neigh->ha;
1165 new = NUD_STALE;
1166 } else
1167 goto out;
1168 } else {
1169 if (lladdr == neigh->ha && new == NUD_STALE &&
1170 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1171 (old & NUD_CONNECTED))
1172 )
1173 new = old;
1174 }
1175 }
1176
1177 if (new != old) {
1178 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001179 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001180 neigh_add_timer(neigh, (jiffies +
1181 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001182 neigh->parms->reachable_time :
1183 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001185 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 }
1187
1188 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001189 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001191 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 neigh_update_hhs(neigh);
1193 if (!(new & NUD_CONNECTED))
1194 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001195 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
1198 if (new == old)
1199 goto out;
1200 if (new & NUD_CONNECTED)
1201 neigh_connect(neigh);
1202 else
1203 neigh_suspect(neigh);
1204 if (!(old & NUD_VALID)) {
1205 struct sk_buff *skb;
1206
1207 /* Again: avoid dead loop if something went wrong */
1208
1209 while (neigh->nud_state & NUD_VALID &&
1210 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001211 struct dst_entry *dst = skb_dst(skb);
1212 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001214
1215 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001216
1217 /* Why not just use 'neigh' as-is? The problem is that
1218 * things such as shaper, eql, and sch_teql can end up
1219 * using alternative, different, neigh objects to output
1220 * the packet in the output path. So what we need to do
1221 * here is re-lookup the top-level neigh in the path so
1222 * we can reinject the packet there.
1223 */
1224 n2 = NULL;
1225 if (dst) {
1226 n2 = dst_neigh_lookup_skb(dst, skb);
1227 if (n2)
1228 n1 = n2;
1229 }
David S. Miller8f40b162011-07-17 13:34:11 -07001230 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001231 if (n2)
1232 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001233 rcu_read_unlock();
1234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 write_lock_bh(&neigh->lock);
1236 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001237 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001238 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 }
1240out:
1241 if (update_isrouter) {
1242 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1243 (neigh->flags | NTF_ROUTER) :
1244 (neigh->flags & ~NTF_ROUTER);
1245 }
1246 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001247
1248 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001249 neigh_update_notify(neigh);
1250
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 return err;
1252}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001253EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
Jiri Benc7e980562013-12-11 13:48:20 +01001255/* Update the neigh to listen temporarily for probe responses, even if it is
1256 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1257 */
1258void __neigh_set_probe_once(struct neighbour *neigh)
1259{
Julian Anastasov76488fa2015-06-16 22:56:39 +03001260 if (neigh->dead)
1261 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001262 neigh->updated = jiffies;
1263 if (!(neigh->nud_state & NUD_FAILED))
1264 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001265 neigh->nud_state = NUD_INCOMPLETE;
1266 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001267 neigh_add_timer(neigh,
1268 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1269}
1270EXPORT_SYMBOL(__neigh_set_probe_once);
1271
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1273 u8 *lladdr, void *saddr,
1274 struct net_device *dev)
1275{
1276 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1277 lladdr || !dev->addr_len);
1278 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001279 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 NEIGH_UPDATE_F_OVERRIDE);
1281 return neigh;
1282}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001283EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284
Eric Dumazet34d101d2010-10-11 09:16:57 -07001285/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001286static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001289 __be16 prot = dst->ops->protocol;
1290 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001291
1292 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001293
David S. Millerf6b72b62011-07-14 07:53:20 -07001294 /* Only one thread can come in here and initialize the
1295 * hh_cache entry.
1296 */
David S. Millerb23b5452011-07-16 17:45:02 -07001297 if (!hh->hh_len)
1298 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001299
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001300 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301}
1302
1303/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001304 * worked, f.e. if you want to override normal output path (eql, shaper),
1305 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 */
1307
David S. Miller8f40b162011-07-17 13:34:11 -07001308int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309{
1310 struct net_device *dev = skb->dev;
1311
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001312 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001314 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1315 skb->len) < 0 &&
David S. Miller22053692013-12-31 16:23:35 -05001316 dev_rebuild_header(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 return 0;
1318
1319 return dev_queue_xmit(skb);
1320}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001321EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
1323/* Slow and careful. */
1324
David S. Miller8f40b162011-07-17 13:34:11 -07001325int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
Eric Dumazetadf30902009-06-02 05:19:30 +00001327 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328 int rc = 0;
1329
David S. Miller8f40b162011-07-17 13:34:11 -07001330 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 goto discard;
1332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (!neigh_event_send(neigh, skb)) {
1334 int err;
1335 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001336 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001337
David S. Millerf6b72b62011-07-14 07:53:20 -07001338 if (dev->header_ops->cache && !neigh->hh.hh_len)
1339 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001340
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001341 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001342 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001343 seq = read_seqbegin(&neigh->ha_lock);
1344 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1345 neigh->ha, NULL, skb->len);
1346 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001349 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 else
1351 goto out_kfree_skb;
1352 }
1353out:
1354 return rc;
1355discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001356 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357out_kfree_skb:
1358 rc = -EINVAL;
1359 kfree_skb(skb);
1360 goto out;
1361}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001362EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364/* As fast as possible without hh cache */
1365
David S. Miller8f40b162011-07-17 13:34:11 -07001366int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001369 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001370 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001372 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001373 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001374 seq = read_seqbegin(&neigh->ha_lock);
1375 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1376 neigh->ha, NULL, skb->len);
1377 } while (read_seqretry(&neigh->ha_lock, seq));
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001380 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 else {
1382 err = -EINVAL;
1383 kfree_skb(skb);
1384 }
1385 return err;
1386}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001387EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
David S. Miller8f40b162011-07-17 13:34:11 -07001389int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1390{
1391 return dev_queue_xmit(skb);
1392}
1393EXPORT_SYMBOL(neigh_direct_output);
1394
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395static void neigh_proxy_process(unsigned long arg)
1396{
1397 struct neigh_table *tbl = (struct neigh_table *)arg;
1398 long sched_next = 0;
1399 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001400 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 spin_lock(&tbl->proxy_queue.lock);
1403
David S. Millerf72051b2008-09-23 01:11:18 -07001404 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1405 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001408 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001409
David S. Millerf72051b2008-09-23 01:11:18 -07001410 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001411 if (tbl->proxy_redo && netif_running(dev)) {
1412 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001413 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001414 rcu_read_unlock();
1415 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001416 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
1419 dev_put(dev);
1420 } else if (!sched_next || tdif < sched_next)
1421 sched_next = tdif;
1422 }
1423 del_timer(&tbl->proxy_timer);
1424 if (sched_next)
1425 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1426 spin_unlock(&tbl->proxy_queue.lock);
1427}
1428
1429void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1430 struct sk_buff *skb)
1431{
1432 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001433
1434 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001435 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001437 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 kfree_skb(skb);
1439 return;
1440 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001441
1442 NEIGH_CB(skb)->sched_next = sched_next;
1443 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 spin_lock(&tbl->proxy_queue.lock);
1446 if (del_timer(&tbl->proxy_timer)) {
1447 if (time_before(tbl->proxy_timer.expires, sched_next))
1448 sched_next = tbl->proxy_timer.expires;
1449 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001450 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 dev_hold(skb->dev);
1452 __skb_queue_tail(&tbl->proxy_queue, skb);
1453 mod_timer(&tbl->proxy_timer, sched_next);
1454 spin_unlock(&tbl->proxy_queue.lock);
1455}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001456EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001458static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001459 struct net *net, int ifindex)
1460{
1461 struct neigh_parms *p;
1462
1463 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001464 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001465 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001466 return p;
1467 }
1468
1469 return NULL;
1470}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1473 struct neigh_table *tbl)
1474{
Gao fengcf89d6b2013-06-20 10:01:32 +08001475 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001476 struct net *net = dev_net(dev);
1477 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Gao fengcf89d6b2013-06-20 10:01:32 +08001479 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 p->tbl = tbl;
1482 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001484 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001485 dev_hold(dev);
1486 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001487 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001489
1490 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1491 release_net(net);
1492 dev_put(dev);
1493 kfree(p);
1494 return NULL;
1495 }
1496
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 write_lock_bh(&tbl->lock);
1498 p->next = tbl->parms.next;
1499 tbl->parms.next = p;
1500 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001501
1502 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 }
1504 return p;
1505}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001506EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
1508static void neigh_rcu_free_parms(struct rcu_head *head)
1509{
1510 struct neigh_parms *parms =
1511 container_of(head, struct neigh_parms, rcu_head);
1512
1513 neigh_parms_put(parms);
1514}
1515
1516void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1517{
1518 struct neigh_parms **p;
1519
1520 if (!parms || parms == &tbl->parms)
1521 return;
1522 write_lock_bh(&tbl->lock);
1523 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1524 if (*p == parms) {
1525 *p = parms->next;
1526 parms->dead = 1;
1527 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001528 if (parms->dev)
1529 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1531 return;
1532 }
1533 }
1534 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001535 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001537EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Denis V. Lunev06f05112008-01-24 00:30:58 -08001539static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001541 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 kfree(parms);
1543}
1544
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001545static struct lock_class_key neigh_table_proxy_queue_class;
1546
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001547static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
1549 unsigned long now = jiffies;
1550 unsigned long phsize;
1551
Eric Dumazete42ea982008-11-12 00:54:54 -08001552 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001555 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 tbl->stats = alloc_percpu(struct neigh_statistics);
1558 if (!tbl->stats)
1559 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001560
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001562 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1563 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565#endif
1566
David S. Millercd089332011-07-11 01:28:12 -07001567 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568
1569 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001570 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001572 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 panic("cannot allocate neighbour cache hashes");
1574
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001575 if (!tbl->entry_size)
1576 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1577 tbl->key_len, NEIGH_PRIV_ALIGN);
1578 else
1579 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1580
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001582 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301583 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1584 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001585 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001586 skb_queue_head_init_class(&tbl->proxy_queue,
1587 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588
1589 tbl->last_flush = now;
1590 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001591}
1592
1593void neigh_table_init(struct neigh_table *tbl)
1594{
1595 struct neigh_table *tmp;
1596
1597 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001599 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1600 if (tmp->family == tbl->family)
1601 break;
1602 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 tbl->next = neigh_tables;
1604 neigh_tables = tbl;
1605 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001606
1607 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001608 pr_err("Registering multiple tables for family %d\n",
1609 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001610 dump_stack();
1611 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001613EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
1615int neigh_table_clear(struct neigh_table *tbl)
1616{
1617 struct neigh_table **tp;
1618
1619 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001620 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 del_timer_sync(&tbl->proxy_timer);
1622 pneigh_queue_purge(&tbl->proxy_queue);
1623 neigh_ifdown(tbl, NULL);
1624 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001625 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626 write_lock(&neigh_tbl_lock);
1627 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1628 if (*tp == tbl) {
1629 *tp = tbl->next;
1630 break;
1631 }
1632 }
1633 write_unlock(&neigh_tbl_lock);
1634
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001635 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1636 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001637 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638
1639 kfree(tbl->phash_buckets);
1640 tbl->phash_buckets = NULL;
1641
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001642 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1643
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001644 free_percpu(tbl->stats);
1645 tbl->stats = NULL;
1646
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 return 0;
1648}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001649EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
Thomas Graf661d2962013-03-21 07:45:29 +00001651static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001653 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001654 struct ndmsg *ndm;
1655 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 struct neigh_table *tbl;
1657 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001658 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
Eric Dumazet110b2492010-10-04 04:27:36 +00001660 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001661 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 goto out;
1663
Thomas Grafa14a49d2006-08-07 17:53:08 -07001664 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1665 if (dst_attr == NULL)
1666 goto out;
1667
1668 ndm = nlmsg_data(nlh);
1669 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001670 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001671 if (dev == NULL) {
1672 err = -ENODEV;
1673 goto out;
1674 }
1675 }
1676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 read_lock(&neigh_tbl_lock);
1678 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001679 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 if (tbl->family != ndm->ndm_family)
1682 continue;
1683 read_unlock(&neigh_tbl_lock);
1684
Thomas Grafa14a49d2006-08-07 17:53:08 -07001685 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001686 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687
1688 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001689 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001690 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 }
1692
Thomas Grafa14a49d2006-08-07 17:53:08 -07001693 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001694 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
Thomas Grafa14a49d2006-08-07 17:53:08 -07001696 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1697 if (neigh == NULL) {
1698 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001699 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001701
1702 err = neigh_update(neigh, NULL, NUD_FAILED,
1703 NEIGH_UPDATE_F_OVERRIDE |
1704 NEIGH_UPDATE_F_ADMIN);
1705 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001706 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707 }
1708 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001709 err = -EAFNOSUPPORT;
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711out:
1712 return err;
1713}
1714
Thomas Graf661d2962013-03-21 07:45:29 +00001715static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001717 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001718 struct ndmsg *ndm;
1719 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 struct neigh_table *tbl;
1721 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001722 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723
Eric Dumazet110b2492010-10-04 04:27:36 +00001724 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001725 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1726 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 goto out;
1728
Thomas Graf5208deb2006-08-07 17:55:40 -07001729 err = -EINVAL;
1730 if (tb[NDA_DST] == NULL)
1731 goto out;
1732
1733 ndm = nlmsg_data(nlh);
1734 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001735 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001736 if (dev == NULL) {
1737 err = -ENODEV;
1738 goto out;
1739 }
1740
1741 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001742 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001743 }
1744
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 read_lock(&neigh_tbl_lock);
1746 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001747 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1748 struct neighbour *neigh;
1749 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001750
1751 if (tbl->family != ndm->ndm_family)
1752 continue;
1753 read_unlock(&neigh_tbl_lock);
1754
Thomas Graf5208deb2006-08-07 17:55:40 -07001755 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001756 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001757 dst = nla_data(tb[NDA_DST]);
1758 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
1760 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001761 struct pneigh_entry *pn;
1762
1763 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001764 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001765 if (pn) {
1766 pn->flags = ndm->ndm_flags;
1767 err = 0;
1768 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001769 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770 }
1771
Thomas Graf5208deb2006-08-07 17:55:40 -07001772 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001773 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001774
1775 neigh = neigh_lookup(tbl, dst, dev);
1776 if (neigh == NULL) {
1777 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1778 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001779 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001780 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001781
Thomas Graf5208deb2006-08-07 17:55:40 -07001782 neigh = __neigh_lookup_errno(tbl, dst, dev);
1783 if (IS_ERR(neigh)) {
1784 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001785 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001786 }
1787 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1789 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001790 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001791 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001792 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001793
1794 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1795 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001796 }
1797
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001798 if (ndm->ndm_flags & NTF_USE) {
1799 neigh_event_send(neigh, NULL);
1800 err = 0;
1801 } else
1802 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001803 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001804 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 }
1806
1807 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001808 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001809out:
1810 return err;
1811}
1812
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001813static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1814{
Thomas Grafca860fb2006-08-07 18:00:18 -07001815 struct nlattr *nest;
1816
1817 nest = nla_nest_start(skb, NDTA_PARMS);
1818 if (nest == NULL)
1819 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001820
David S. Miller9a6308d2012-04-01 20:06:28 -04001821 if ((parms->dev &&
1822 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1823 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001824 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1825 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001826 /* approximative value for deprecated QUEUE_LEN (in packets) */
1827 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001828 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1829 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1830 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1831 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1832 NEIGH_VAR(parms, UCAST_PROBES)) ||
1833 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1834 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001835 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1836 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001837 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1838 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1839 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001840 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001841 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1842 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1843 NEIGH_VAR(parms, RETRANS_TIME)) ||
1844 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1845 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1846 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1847 NEIGH_VAR(parms, PROXY_DELAY)) ||
1848 nla_put_msecs(skb, NDTPA_LOCKTIME,
1849 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001850 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001851 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852
Thomas Grafca860fb2006-08-07 18:00:18 -07001853nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001854 nla_nest_cancel(skb, nest);
1855 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001856}
1857
Thomas Grafca860fb2006-08-07 18:00:18 -07001858static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1859 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001860{
1861 struct nlmsghdr *nlh;
1862 struct ndtmsg *ndtmsg;
1863
Thomas Grafca860fb2006-08-07 18:00:18 -07001864 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1865 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001866 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001867
Thomas Grafca860fb2006-08-07 18:00:18 -07001868 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001869
1870 read_lock_bh(&tbl->lock);
1871 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001872 ndtmsg->ndtm_pad1 = 0;
1873 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001874
David S. Miller9a6308d2012-04-01 20:06:28 -04001875 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1876 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1877 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1878 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1879 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1880 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881 {
1882 unsigned long now = jiffies;
1883 unsigned int flush_delta = now - tbl->last_flush;
1884 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001885 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001886 struct ndt_config ndc = {
1887 .ndtc_key_len = tbl->key_len,
1888 .ndtc_entry_size = tbl->entry_size,
1889 .ndtc_entries = atomic_read(&tbl->entries),
1890 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1891 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001892 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1893 };
1894
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001895 rcu_read_lock_bh();
1896 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001897 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001898 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001899 rcu_read_unlock_bh();
1900
David S. Miller9a6308d2012-04-01 20:06:28 -04001901 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1902 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001903 }
1904
1905 {
1906 int cpu;
1907 struct ndt_stats ndst;
1908
1909 memset(&ndst, 0, sizeof(ndst));
1910
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001911 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001912 struct neigh_statistics *st;
1913
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001914 st = per_cpu_ptr(tbl->stats, cpu);
1915 ndst.ndts_allocs += st->allocs;
1916 ndst.ndts_destroys += st->destroys;
1917 ndst.ndts_hash_grows += st->hash_grows;
1918 ndst.ndts_res_failed += st->res_failed;
1919 ndst.ndts_lookups += st->lookups;
1920 ndst.ndts_hits += st->hits;
1921 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1922 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1923 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1924 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1925 }
1926
David S. Miller9a6308d2012-04-01 20:06:28 -04001927 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1928 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001929 }
1930
1931 BUG_ON(tbl->parms.dev);
1932 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001933 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001934
1935 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001936 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937
Thomas Grafca860fb2006-08-07 18:00:18 -07001938nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001939 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001940 nlmsg_cancel(skb, nlh);
1941 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001942}
1943
Thomas Grafca860fb2006-08-07 18:00:18 -07001944static int neightbl_fill_param_info(struct sk_buff *skb,
1945 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001946 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001947 u32 pid, u32 seq, int type,
1948 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949{
1950 struct ndtmsg *ndtmsg;
1951 struct nlmsghdr *nlh;
1952
Thomas Grafca860fb2006-08-07 18:00:18 -07001953 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1954 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001955 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001956
Thomas Grafca860fb2006-08-07 18:00:18 -07001957 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001958
1959 read_lock_bh(&tbl->lock);
1960 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001961 ndtmsg->ndtm_pad1 = 0;
1962 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001963
Thomas Grafca860fb2006-08-07 18:00:18 -07001964 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1965 neightbl_fill_parms(skb, parms) < 0)
1966 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967
1968 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001969 return nlmsg_end(skb, nlh);
1970errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001971 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001972 nlmsg_cancel(skb, nlh);
1973 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001974}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001975
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001976static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001977 [NDTA_NAME] = { .type = NLA_STRING },
1978 [NDTA_THRESH1] = { .type = NLA_U32 },
1979 [NDTA_THRESH2] = { .type = NLA_U32 },
1980 [NDTA_THRESH3] = { .type = NLA_U32 },
1981 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1982 [NDTA_PARMS] = { .type = NLA_NESTED },
1983};
1984
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001985static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001986 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1987 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1988 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1989 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1990 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1991 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1992 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1993 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1994 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1995 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1996 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1997 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1998 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1999};
2000
Thomas Graf661d2962013-03-21 07:45:29 +00002001static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002003 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002004 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002005 struct ndtmsg *ndtmsg;
2006 struct nlattr *tb[NDTA_MAX+1];
2007 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002008
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
2010 nl_neightbl_policy);
2011 if (err < 0)
2012 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002013
Thomas Graf6b3f8672006-08-07 17:58:53 -07002014 if (tb[NDTA_NAME] == NULL) {
2015 err = -EINVAL;
2016 goto errout;
2017 }
2018
2019 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002020 read_lock(&neigh_tbl_lock);
2021 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
2022 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2023 continue;
2024
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002026 break;
2027 }
2028
2029 if (tbl == NULL) {
2030 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002031 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002032 }
2033
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002034 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002035 * We acquire tbl->lock to be nice to the periodic timers and
2036 * make sure they always see a consistent set of values.
2037 */
2038 write_lock_bh(&tbl->lock);
2039
Thomas Graf6b3f8672006-08-07 17:58:53 -07002040 if (tb[NDTA_PARMS]) {
2041 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002042 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002044
Thomas Graf6b3f8672006-08-07 17:58:53 -07002045 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2046 nl_ntbl_parm_policy);
2047 if (err < 0)
2048 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002049
Thomas Graf6b3f8672006-08-07 17:58:53 -07002050 if (tbp[NDTPA_IFINDEX])
2051 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002052
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002053 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002054 if (p == NULL) {
2055 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002056 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002057 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002058
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 for (i = 1; i <= NDTPA_MAX; i++) {
2060 if (tbp[i] == NULL)
2061 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002062
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 switch (i) {
2064 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002065 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2066 nla_get_u32(tbp[i]) *
2067 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002068 break;
2069 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002070 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2071 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002072 break;
2073 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002074 NEIGH_VAR_SET(p, PROXY_QLEN,
2075 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002078 NEIGH_VAR_SET(p, APP_PROBES,
2079 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002080 break;
2081 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002082 NEIGH_VAR_SET(p, UCAST_PROBES,
2083 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002084 break;
2085 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002086 NEIGH_VAR_SET(p, MCAST_PROBES,
2087 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002088 break;
2089 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002090 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2091 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002092 break;
2093 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002094 NEIGH_VAR_SET(p, GC_STALETIME,
2095 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002096 break;
2097 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002098 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2099 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002100 break;
2101 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002102 NEIGH_VAR_SET(p, RETRANS_TIME,
2103 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002104 break;
2105 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002106 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2107 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002108 break;
2109 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002110 NEIGH_VAR_SET(p, PROXY_DELAY,
2111 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002112 break;
2113 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002114 NEIGH_VAR_SET(p, LOCKTIME,
2115 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002116 break;
2117 }
2118 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002119 }
2120
Gao fengdc25c672013-06-20 10:01:34 +08002121 err = -ENOENT;
2122 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2123 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2124 !net_eq(net, &init_net))
2125 goto errout_tbl_lock;
2126
Thomas Graf6b3f8672006-08-07 17:58:53 -07002127 if (tb[NDTA_THRESH1])
2128 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2129
2130 if (tb[NDTA_THRESH2])
2131 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2132
2133 if (tb[NDTA_THRESH3])
2134 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2135
2136 if (tb[NDTA_GC_INTERVAL])
2137 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2138
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002139 err = 0;
2140
Thomas Graf6b3f8672006-08-07 17:58:53 -07002141errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002142 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002143errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002145errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146 return err;
2147}
2148
Thomas Grafc8822a42007-03-22 11:50:06 -07002149static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002150{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002151 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002152 int family, tidx, nidx = 0;
2153 int tbl_skip = cb->args[0];
2154 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002155 struct neigh_table *tbl;
2156
Thomas Grafca860fb2006-08-07 18:00:18 -07002157 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002158
2159 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002160 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002161 struct neigh_parms *p;
2162
Thomas Grafca860fb2006-08-07 18:00:18 -07002163 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002164 continue;
2165
Eric W. Biederman15e47302012-09-07 20:12:54 +00002166 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002167 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2168 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002169 break;
2170
Eric W. Biederman426b5302008-01-24 00:13:18 -08002171 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002172 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002173 continue;
2174
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002175 if (nidx < neigh_skip)
2176 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002177
Thomas Grafca860fb2006-08-07 18:00:18 -07002178 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002179 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002180 cb->nlh->nlmsg_seq,
2181 RTM_NEWNEIGHTBL,
2182 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002183 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002184 next:
2185 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002186 }
2187
Thomas Grafca860fb2006-08-07 18:00:18 -07002188 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002189 }
2190out:
2191 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002192 cb->args[0] = tidx;
2193 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002194
2195 return skb->len;
2196}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
Thomas Graf8b8aec52006-08-07 17:56:37 -07002198static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2199 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200{
2201 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002203 struct nlmsghdr *nlh;
2204 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
Thomas Graf8b8aec52006-08-07 17:56:37 -07002206 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2207 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002208 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002209
2210 ndm = nlmsg_data(nlh);
2211 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002212 ndm->ndm_pad1 = 0;
2213 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002214 ndm->ndm_flags = neigh->flags;
2215 ndm->ndm_type = neigh->type;
2216 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
David S. Miller9a6308d2012-04-01 20:06:28 -04002218 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2219 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002220
2221 read_lock_bh(&neigh->lock);
2222 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002223 if (neigh->nud_state & NUD_VALID) {
2224 char haddr[MAX_ADDR_LEN];
2225
2226 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2227 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2228 read_unlock_bh(&neigh->lock);
2229 goto nla_put_failure;
2230 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002231 }
2232
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002233 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2234 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2235 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002236 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2237 read_unlock_bh(&neigh->lock);
2238
David S. Miller9a6308d2012-04-01 20:06:28 -04002239 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2240 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2241 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002242
2243 return nlmsg_end(skb, nlh);
2244
2245nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002246 nlmsg_cancel(skb, nlh);
2247 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248}
2249
Tony Zelenoff84920c12012-01-26 22:28:58 +00002250static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2251 u32 pid, u32 seq, int type, unsigned int flags,
2252 struct neigh_table *tbl)
2253{
2254 struct nlmsghdr *nlh;
2255 struct ndmsg *ndm;
2256
2257 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2258 if (nlh == NULL)
2259 return -EMSGSIZE;
2260
2261 ndm = nlmsg_data(nlh);
2262 ndm->ndm_family = tbl->family;
2263 ndm->ndm_pad1 = 0;
2264 ndm->ndm_pad2 = 0;
2265 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002266 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov18c103a2015-12-01 01:14:48 +03002267 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002268 ndm->ndm_state = NUD_NONE;
2269
David S. Miller9a6308d2012-04-01 20:06:28 -04002270 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2271 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002272
2273 return nlmsg_end(skb, nlh);
2274
2275nla_put_failure:
2276 nlmsg_cancel(skb, nlh);
2277 return -EMSGSIZE;
2278}
2279
Thomas Grafd961db32007-08-08 23:12:56 -07002280static void neigh_update_notify(struct neighbour *neigh)
2281{
2282 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2283 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2284}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
2286static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2287 struct netlink_callback *cb)
2288{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002289 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 struct neighbour *n;
2291 int rc, h, s_h = cb->args[1];
2292 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002293 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002295 rcu_read_lock_bh();
2296 nht = rcu_dereference_bh(tbl->nht);
2297
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002298 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299 if (h > s_h)
2300 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002301 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2302 n != NULL;
2303 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002304 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002305 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002306 if (idx < s_idx)
2307 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002308 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002310 RTM_NEWNEIGH,
2311 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 rc = -1;
2313 goto out;
2314 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002315next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002316 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318 }
2319 rc = skb->len;
2320out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002321 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 cb->args[1] = h;
2323 cb->args[2] = idx;
2324 return rc;
2325}
2326
Tony Zelenoff84920c12012-01-26 22:28:58 +00002327static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2328 struct netlink_callback *cb)
2329{
2330 struct pneigh_entry *n;
2331 struct net *net = sock_net(skb->sk);
2332 int rc, h, s_h = cb->args[3];
2333 int idx, s_idx = idx = cb->args[4];
2334
2335 read_lock_bh(&tbl->lock);
2336
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002337 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002338 if (h > s_h)
2339 s_idx = 0;
2340 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Konstantin Khlebnikov18c103a2015-12-01 01:14:48 +03002341 if (pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002342 continue;
2343 if (idx < s_idx)
2344 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002345 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002346 cb->nlh->nlmsg_seq,
2347 RTM_NEWNEIGH,
2348 NLM_F_MULTI, tbl) <= 0) {
2349 read_unlock_bh(&tbl->lock);
2350 rc = -1;
2351 goto out;
2352 }
2353 next:
2354 idx++;
2355 }
2356 }
2357
2358 read_unlock_bh(&tbl->lock);
2359 rc = skb->len;
2360out:
2361 cb->args[3] = h;
2362 cb->args[4] = idx;
2363 return rc;
2364
2365}
2366
Thomas Grafc8822a42007-03-22 11:50:06 -07002367static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368{
2369 struct neigh_table *tbl;
2370 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002371 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002372 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
2374 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002375 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002376
2377 /* check for full ndmsg structure presence, family member is
2378 * the same for both structures
2379 */
2380 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2381 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2382 proxy = 1;
2383
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 s_t = cb->args[0];
2385
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002386 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002387 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 if (t < s_t || (family && tbl->family != family))
2389 continue;
2390 if (t > s_t)
2391 memset(&cb->args[1], 0, sizeof(cb->args) -
2392 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002393 if (proxy)
2394 err = pneigh_dump_table(tbl, skb, cb);
2395 else
2396 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002397 if (err < 0)
2398 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399 }
2400 read_unlock(&neigh_tbl_lock);
2401
2402 cb->args[0] = t;
2403 return skb->len;
2404}
2405
2406void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2407{
2408 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002409 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002411 rcu_read_lock_bh();
2412 nht = rcu_dereference_bh(tbl->nht);
2413
Eric Dumazet767e97e2010-10-06 17:49:21 -07002414 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002415 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 struct neighbour *n;
2417
Eric Dumazet767e97e2010-10-06 17:49:21 -07002418 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2419 n != NULL;
2420 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 cb(n, cookie);
2422 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002423 read_unlock(&tbl->lock);
2424 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425}
2426EXPORT_SYMBOL(neigh_for_each);
2427
2428/* The tbl->lock must be held as a writer and BH disabled. */
2429void __neigh_for_each_release(struct neigh_table *tbl,
2430 int (*cb)(struct neighbour *))
2431{
2432 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002433 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002435 nht = rcu_dereference_protected(tbl->nht,
2436 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002437 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002438 struct neighbour *n;
2439 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002441 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002442 while ((n = rcu_dereference_protected(*np,
2443 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 int release;
2445
2446 write_lock(&n->lock);
2447 release = cb(n);
2448 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002449 rcu_assign_pointer(*np,
2450 rcu_dereference_protected(n->next,
2451 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452 n->dead = 1;
2453 } else
2454 np = &n->next;
2455 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002456 if (release)
2457 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 }
2459 }
2460}
2461EXPORT_SYMBOL(__neigh_for_each_release);
2462
2463#ifdef CONFIG_PROC_FS
2464
2465static struct neighbour *neigh_get_first(struct seq_file *seq)
2466{
2467 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002468 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002469 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 struct neighbour *n = NULL;
2471 int bucket = state->bucket;
2472
2473 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002474 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002475 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
2477 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002478 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002479 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 if (state->neigh_sub_iter) {
2481 loff_t fakep = 0;
2482 void *v;
2483
2484 v = state->neigh_sub_iter(state, n, &fakep);
2485 if (!v)
2486 goto next;
2487 }
2488 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2489 break;
2490 if (n->nud_state & ~NUD_NOARP)
2491 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002492next:
2493 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 }
2495
2496 if (n)
2497 break;
2498 }
2499 state->bucket = bucket;
2500
2501 return n;
2502}
2503
2504static struct neighbour *neigh_get_next(struct seq_file *seq,
2505 struct neighbour *n,
2506 loff_t *pos)
2507{
2508 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002509 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002510 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511
2512 if (state->neigh_sub_iter) {
2513 void *v = state->neigh_sub_iter(state, n, pos);
2514 if (v)
2515 return n;
2516 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002517 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518
2519 while (1) {
2520 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002521 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002522 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 if (state->neigh_sub_iter) {
2524 void *v = state->neigh_sub_iter(state, n, pos);
2525 if (v)
2526 return n;
2527 goto next;
2528 }
2529 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2530 break;
2531
2532 if (n->nud_state & ~NUD_NOARP)
2533 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002534next:
2535 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 }
2537
2538 if (n)
2539 break;
2540
David S. Millercd089332011-07-11 01:28:12 -07002541 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 break;
2543
Eric Dumazet767e97e2010-10-06 17:49:21 -07002544 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 }
2546
2547 if (n && pos)
2548 --(*pos);
2549 return n;
2550}
2551
2552static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2553{
2554 struct neighbour *n = neigh_get_first(seq);
2555
2556 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002557 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 while (*pos) {
2559 n = neigh_get_next(seq, n, pos);
2560 if (!n)
2561 break;
2562 }
2563 }
2564 return *pos ? NULL : n;
2565}
2566
2567static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2568{
2569 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002570 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 struct neigh_table *tbl = state->tbl;
2572 struct pneigh_entry *pn = NULL;
2573 int bucket = state->bucket;
2574
2575 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2576 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2577 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002578 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002579 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if (pn)
2581 break;
2582 }
2583 state->bucket = bucket;
2584
2585 return pn;
2586}
2587
2588static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2589 struct pneigh_entry *pn,
2590 loff_t *pos)
2591{
2592 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002593 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 struct neigh_table *tbl = state->tbl;
2595
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002596 do {
2597 pn = pn->next;
2598 } while (pn && !net_eq(pneigh_net(pn), net));
2599
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 while (!pn) {
2601 if (++state->bucket > PNEIGH_HASHMASK)
2602 break;
2603 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002604 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002605 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 if (pn)
2607 break;
2608 }
2609
2610 if (pn && pos)
2611 --(*pos);
2612
2613 return pn;
2614}
2615
2616static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2617{
2618 struct pneigh_entry *pn = pneigh_get_first(seq);
2619
2620 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002621 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 while (*pos) {
2623 pn = pneigh_get_next(seq, pn, pos);
2624 if (!pn)
2625 break;
2626 }
2627 }
2628 return *pos ? NULL : pn;
2629}
2630
2631static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2632{
2633 struct neigh_seq_state *state = seq->private;
2634 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002635 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
Chris Larson745e2032008-08-03 01:10:55 -07002637 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002639 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640
2641 return rc;
2642}
2643
2644void *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 +00002645 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
2647 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648
2649 state->tbl = tbl;
2650 state->bucket = 0;
2651 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2652
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002653 rcu_read_lock_bh();
2654 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002655
Chris Larson745e2032008-08-03 01:10:55 -07002656 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657}
2658EXPORT_SYMBOL(neigh_seq_start);
2659
2660void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2661{
2662 struct neigh_seq_state *state;
2663 void *rc;
2664
2665 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002666 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 goto out;
2668 }
2669
2670 state = seq->private;
2671 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2672 rc = neigh_get_next(seq, v, NULL);
2673 if (rc)
2674 goto out;
2675 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2676 rc = pneigh_get_first(seq);
2677 } else {
2678 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2679 rc = pneigh_get_next(seq, v, NULL);
2680 }
2681out:
2682 ++(*pos);
2683 return rc;
2684}
2685EXPORT_SYMBOL(neigh_seq_next);
2686
2687void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002688 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002690 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691}
2692EXPORT_SYMBOL(neigh_seq_stop);
2693
2694/* statistics via seq_file */
2695
2696static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2697{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002698 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 int cpu;
2700
2701 if (*pos == 0)
2702 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002703
Rusty Russell0f23174a2008-12-29 12:23:42 +00002704 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 if (!cpu_possible(cpu))
2706 continue;
2707 *pos = cpu+1;
2708 return per_cpu_ptr(tbl->stats, cpu);
2709 }
2710 return NULL;
2711}
2712
2713static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2714{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002715 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 int cpu;
2717
Rusty Russell0f23174a2008-12-29 12:23:42 +00002718 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 if (!cpu_possible(cpu))
2720 continue;
2721 *pos = cpu+1;
2722 return per_cpu_ptr(tbl->stats, cpu);
2723 }
2724 return NULL;
2725}
2726
2727static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2728{
2729
2730}
2731
2732static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2733{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002734 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 struct neigh_statistics *st = v;
2736
2737 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002738 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\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 return 0;
2740 }
2741
2742 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002743 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002744 atomic_read(&tbl->entries),
2745
2746 st->allocs,
2747 st->destroys,
2748 st->hash_grows,
2749
2750 st->lookups,
2751 st->hits,
2752
2753 st->res_failed,
2754
2755 st->rcv_probes_mcast,
2756 st->rcv_probes_ucast,
2757
2758 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002759 st->forced_gc_runs,
2760 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 );
2762
2763 return 0;
2764}
2765
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002766static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 .start = neigh_stat_seq_start,
2768 .next = neigh_stat_seq_next,
2769 .stop = neigh_stat_seq_stop,
2770 .show = neigh_stat_seq_show,
2771};
2772
2773static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2774{
2775 int ret = seq_open(file, &neigh_stat_seq_ops);
2776
2777 if (!ret) {
2778 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002779 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 }
2781 return ret;
2782};
2783
Arjan van de Ven9a321442007-02-12 00:55:35 -08002784static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 .owner = THIS_MODULE,
2786 .open = neigh_stat_seq_open,
2787 .read = seq_read,
2788 .llseek = seq_lseek,
2789 .release = seq_release,
2790};
2791
2792#endif /* CONFIG_PROC_FS */
2793
Thomas Graf339bf982006-11-10 14:10:15 -08002794static inline size_t neigh_nlmsg_size(void)
2795{
2796 return NLMSG_ALIGN(sizeof(struct ndmsg))
2797 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2798 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2799 + nla_total_size(sizeof(struct nda_cacheinfo))
2800 + nla_total_size(4); /* NDA_PROBES */
2801}
2802
Thomas Grafb8673312006-08-15 00:33:14 -07002803static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002805 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002806 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002807 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002808
Thomas Graf339bf982006-11-10 14:10:15 -08002809 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002810 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002811 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002812
Thomas Grafb8673312006-08-15 00:33:14 -07002813 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002814 if (err < 0) {
2815 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2816 WARN_ON(err == -EMSGSIZE);
2817 kfree_skb(skb);
2818 goto errout;
2819 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002820 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2821 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002822errout:
2823 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002824 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002825}
2826
2827void neigh_app_ns(struct neighbour *n)
2828{
2829 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002830}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002831EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832
2833#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002834static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002835static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002836static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002837
Joe Perchesfe2c6332013-06-11 23:04:25 -07002838static int proc_unres_qlen(struct ctl_table *ctl, int write,
2839 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002840{
2841 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002842 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002843
Shan Weice46cc62012-12-04 18:49:15 +00002844 tmp.extra1 = &zero;
2845 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002846 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002847
2848 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2849 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2850
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002851 if (write && !ret)
2852 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2853 return ret;
2854}
2855
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002856static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2857 int family)
2858{
Jiri Pirkobba24892013-12-07 19:26:57 +01002859 switch (family) {
2860 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002861 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002862 case AF_INET6:
2863 return __in6_dev_nd_parms_get_rcu(dev);
2864 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002865 return NULL;
2866}
2867
2868static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2869 int index)
2870{
2871 struct net_device *dev;
2872 int family = neigh_parms_family(p);
2873
2874 rcu_read_lock();
2875 for_each_netdev_rcu(net, dev) {
2876 struct neigh_parms *dst_p =
2877 neigh_get_dev_parms_rcu(dev, family);
2878
2879 if (dst_p && !test_bit(index, dst_p->data_state))
2880 dst_p->data[index] = p->data[index];
2881 }
2882 rcu_read_unlock();
2883}
2884
2885static void neigh_proc_update(struct ctl_table *ctl, int write)
2886{
2887 struct net_device *dev = ctl->extra1;
2888 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002889 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002890 int index = (int *) ctl->data - p->data;
2891
2892 if (!write)
2893 return;
2894
2895 set_bit(index, p->data_state);
2896 if (!dev) /* NULL dev means this is default value */
2897 neigh_copy_dflt_parms(net, p, index);
2898}
2899
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002900static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2901 void __user *buffer,
2902 size_t *lenp, loff_t *ppos)
2903{
2904 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002905 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002906
2907 tmp.extra1 = &zero;
2908 tmp.extra2 = &int_max;
2909
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002910 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2911 neigh_proc_update(ctl, write);
2912 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002913}
2914
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002915int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2916 void __user *buffer, size_t *lenp, loff_t *ppos)
2917{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002918 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2919
2920 neigh_proc_update(ctl, write);
2921 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002922}
2923EXPORT_SYMBOL(neigh_proc_dointvec);
2924
2925int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2926 void __user *buffer,
2927 size_t *lenp, loff_t *ppos)
2928{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002929 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2930
2931 neigh_proc_update(ctl, write);
2932 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002933}
2934EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2935
2936static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2937 void __user *buffer,
2938 size_t *lenp, loff_t *ppos)
2939{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002940 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2941
2942 neigh_proc_update(ctl, write);
2943 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002944}
2945
2946int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2947 void __user *buffer,
2948 size_t *lenp, loff_t *ppos)
2949{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002950 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2951
2952 neigh_proc_update(ctl, write);
2953 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002954}
2955EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2956
2957static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2958 void __user *buffer,
2959 size_t *lenp, loff_t *ppos)
2960{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002961 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2962
2963 neigh_proc_update(ctl, write);
2964 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002965}
2966
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002967#define NEIGH_PARMS_DATA_OFFSET(index) \
2968 (&((struct neigh_parms *) 0)->data[index])
2969
2970#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2971 [NEIGH_VAR_ ## attr] = { \
2972 .procname = name, \
2973 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2974 .maxlen = sizeof(int), \
2975 .mode = mval, \
2976 .proc_handler = proc, \
2977 }
2978
2979#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2980 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2981
2982#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002983 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002984
2985#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002986 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002987
2988#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002989 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002990
2991#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002992 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002993
2994#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002995 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002996
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997static struct neigh_sysctl_table {
2998 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002999 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003000} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003002 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3003 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3004 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
3005 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3006 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3007 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3008 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3009 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3010 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3011 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3012 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3013 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3014 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3015 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3016 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003017 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 .procname = "gc_interval",
3019 .maxlen = sizeof(int),
3020 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003021 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003023 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 .procname = "gc_thresh1",
3025 .maxlen = sizeof(int),
3026 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003027 .extra1 = &zero,
3028 .extra2 = &int_max,
3029 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003031 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 .procname = "gc_thresh2",
3033 .maxlen = sizeof(int),
3034 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003035 .extra1 = &zero,
3036 .extra2 = &int_max,
3037 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003039 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 .procname = "gc_thresh3",
3041 .maxlen = sizeof(int),
3042 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003043 .extra1 = &zero,
3044 .extra2 = &int_max,
3045 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003047 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003048 },
3049};
3050
3051int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003052 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003054 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003055 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003056 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003057 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003058 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003060 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003062 goto err;
3063
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003064 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003065 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003066 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003067 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003068 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069
3070 if (dev) {
3071 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003072 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003073 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3074 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003076 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003077 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003078 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3079 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3080 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3081 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082 }
3083
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003084 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003085 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003086 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003088 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003090 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003092 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003093 }
3094
Eric W. Biederman464dc802012-11-16 03:02:59 +00003095 /* Don't export sysctls to unprivileged users */
3096 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3097 t->neigh_vars[0].procname = NULL;
3098
Jiri Pirko73af6142013-12-07 19:26:55 +01003099 switch (neigh_parms_family(p)) {
3100 case AF_INET:
3101 p_name = "ipv4";
3102 break;
3103 case AF_INET6:
3104 p_name = "ipv6";
3105 break;
3106 default:
3107 BUG();
3108 }
3109
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003110 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3111 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003112 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003113 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003114 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003115 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003116
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 p->sysctl_table = t;
3118 return 0;
3119
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003120free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003122err:
3123 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003125EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
3127void neigh_sysctl_unregister(struct neigh_parms *p)
3128{
3129 if (p->sysctl_table) {
3130 struct neigh_sysctl_table *t = p->sysctl_table;
3131 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003132 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 kfree(t);
3134 }
3135}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003136EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137
3138#endif /* CONFIG_SYSCTL */
3139
Thomas Grafc8822a42007-03-22 11:50:06 -07003140static int __init neigh_init(void)
3141{
Greg Rosec7ac8672011-06-10 01:27:09 +00003142 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3143 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3144 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003145
Greg Rosec7ac8672011-06-10 01:27:09 +00003146 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3147 NULL);
3148 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003149
3150 return 0;
3151}
3152
3153subsys_initcall(neigh_init);
3154