blob: b9e9e0d38672a8ca9a17f8d6ec8daf88b8a09a65 [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 Pirko1f9248e52013-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
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000769 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
770 goto out;
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 /*
773 * periodically recompute ReachableTime from random function
774 */
775
Eric Dumazete4c4e442009-07-30 03:15:07 +0000776 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000778 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 for (p = &tbl->parms; p; p = p->next)
780 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100781 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 }
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 Pirko1f9248e52013-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 Pirko1f9248e52013-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 Pirko1f9248e52013-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;
Eric Dumazeta02cec22010-09-22 20:43:57 +0000839 return (n->nud_state & NUD_PROBE) ?
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100840 NEIGH_VAR(p, UCAST_PROBES) :
841 NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
842 NEIGH_VAR(p, MCAST_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);
878 neigh->ops->solicit(neigh, skb);
879 atomic_inc(&neigh->probes);
880 kfree_skb(skb);
881}
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883/* Called when a timer expires for a neighbour entry. */
884
885static void neigh_timer_handler(unsigned long arg)
886{
887 unsigned long now, next;
888 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000889 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 int notify = 0;
891
892 write_lock(&neigh->lock);
893
894 state = neigh->nud_state;
895 now = jiffies;
896 next = now + HZ;
897
David S. Miller045f7b32011-11-01 17:45:55 -0400898 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900902 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000904 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 next = neigh->confirmed + neigh->parms->reachable_time;
906 } else if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100907 neigh->used +
908 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000909 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800911 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 neigh_suspect(neigh);
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100913 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000915 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800917 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700919 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900922 if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100923 neigh->confirmed +
924 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000925 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800927 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700929 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 next = neigh->confirmed + neigh->parms->reachable_time;
931 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000932 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800934 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100936 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
938 } else {
939 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100940 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
942
943 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
944 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 neigh->nud_state = NUD_FAILED;
946 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700947 neigh_invalidate(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 }
949
950 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (time_before(next, jiffies + HZ/2))
952 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000953 if (!mod_timer(&neigh->timer, next))
954 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 }
956 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000957 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800958 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800959out:
David S. Miller9ff56602008-02-17 18:39:54 -0800960 write_unlock(&neigh->lock);
961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Thomas Grafd961db32007-08-08 23:12:56 -0700963 if (notify)
964 neigh_update_notify(neigh);
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 neigh_release(neigh);
967}
968
969int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
970{
971 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000972 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
974 write_lock_bh(&neigh->lock);
975
976 rc = 0;
977 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
978 goto out_unlock_bh;
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100981 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
982 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000983 unsigned long next, now = jiffies;
984
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100985 atomic_set(&neigh->probes,
986 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000988 neigh->updated = now;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100989 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
990 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000991 neigh_add_timer(neigh, next);
992 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 } else {
994 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800995 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 write_unlock_bh(&neigh->lock);
997
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000998 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return 1;
1000 }
1001 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001002 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001004 neigh->updated = jiffies;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001005 neigh_add_timer(neigh, jiffies +
1006 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 }
1008
1009 if (neigh->nud_state == NUD_INCOMPLETE) {
1010 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001011 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001012 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001014
David S. Millerf72051b2008-09-23 01:11:18 -07001015 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001016 if (!buff)
1017 break;
1018 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001020 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001022 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001024 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
1026 rc = 1;
1027 }
1028out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001029 if (immediate_probe)
1030 neigh_probe(neigh);
1031 else
1032 write_unlock(&neigh->lock);
1033 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return rc;
1035}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001036EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
David S. Millerf6b72b62011-07-14 07:53:20 -07001038static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039{
1040 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001041 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001042 = NULL;
1043
1044 if (neigh->dev->header_ops)
1045 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001048 hh = &neigh->hh;
1049 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001050 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001052 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054 }
1055}
1056
1057
1058
1059/* Generic update routine.
1060 -- lladdr is new lladdr or NULL, if it is not supplied.
1061 -- new is new state.
1062 -- flags
1063 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1064 if it is different.
1065 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001066 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 if it is different.
1068 It also allows to retain current state
1069 if lladdr is unchanged.
1070 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1071
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001072 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 NTF_ROUTER flag.
1074 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1075 a router.
1076
1077 Caller MUST hold reference count on the entry.
1078 */
1079
1080int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1081 u32 flags)
1082{
1083 u8 old;
1084 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 struct net_device *dev;
1087 int update_isrouter = 0;
1088
1089 write_lock_bh(&neigh->lock);
1090
1091 dev = neigh->dev;
1092 old = neigh->nud_state;
1093 err = -EPERM;
1094
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001095 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 (old & (NUD_NOARP | NUD_PERMANENT)))
1097 goto out;
1098
1099 if (!(new & NUD_VALID)) {
1100 neigh_del_timer(neigh);
1101 if (old & NUD_CONNECTED)
1102 neigh_suspect(neigh);
1103 neigh->nud_state = new;
1104 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001106 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1107 (new & NUD_FAILED)) {
1108 neigh_invalidate(neigh);
1109 notify = 1;
1110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 goto out;
1112 }
1113
1114 /* Compare new lladdr with cached one */
1115 if (!dev->addr_len) {
1116 /* First case: device needs no address. */
1117 lladdr = neigh->ha;
1118 } else if (lladdr) {
1119 /* The second case: if something is already cached
1120 and a new address is proposed:
1121 - compare new & old
1122 - if they are different, check override flag
1123 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001124 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 !memcmp(lladdr, neigh->ha, dev->addr_len))
1126 lladdr = neigh->ha;
1127 } else {
1128 /* No address is supplied; if we know something,
1129 use it, otherwise discard the request.
1130 */
1131 err = -EINVAL;
1132 if (!(old & NUD_VALID))
1133 goto out;
1134 lladdr = neigh->ha;
1135 }
1136
1137 if (new & NUD_CONNECTED)
1138 neigh->confirmed = jiffies;
1139 neigh->updated = jiffies;
1140
1141 /* If entry was valid and address is not changed,
1142 do not change entry state, if new one is STALE.
1143 */
1144 err = 0;
1145 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1146 if (old & NUD_VALID) {
1147 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1148 update_isrouter = 0;
1149 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1150 (old & NUD_CONNECTED)) {
1151 lladdr = neigh->ha;
1152 new = NUD_STALE;
1153 } else
1154 goto out;
1155 } else {
1156 if (lladdr == neigh->ha && new == NUD_STALE &&
1157 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1158 (old & NUD_CONNECTED))
1159 )
1160 new = old;
1161 }
1162 }
1163
1164 if (new != old) {
1165 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001166 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001167 neigh_add_timer(neigh, (jiffies +
1168 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001169 neigh->parms->reachable_time :
1170 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001172 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 }
1174
1175 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001176 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001178 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 neigh_update_hhs(neigh);
1180 if (!(new & NUD_CONNECTED))
1181 neigh->confirmed = jiffies -
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001182 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185 if (new == old)
1186 goto out;
1187 if (new & NUD_CONNECTED)
1188 neigh_connect(neigh);
1189 else
1190 neigh_suspect(neigh);
1191 if (!(old & NUD_VALID)) {
1192 struct sk_buff *skb;
1193
1194 /* Again: avoid dead loop if something went wrong */
1195
1196 while (neigh->nud_state & NUD_VALID &&
1197 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001198 struct dst_entry *dst = skb_dst(skb);
1199 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001201
1202 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001203
1204 /* Why not just use 'neigh' as-is? The problem is that
1205 * things such as shaper, eql, and sch_teql can end up
1206 * using alternative, different, neigh objects to output
1207 * the packet in the output path. So what we need to do
1208 * here is re-lookup the top-level neigh in the path so
1209 * we can reinject the packet there.
1210 */
1211 n2 = NULL;
1212 if (dst) {
1213 n2 = dst_neigh_lookup_skb(dst, skb);
1214 if (n2)
1215 n1 = n2;
1216 }
David S. Miller8f40b162011-07-17 13:34:11 -07001217 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001218 if (n2)
1219 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001220 rcu_read_unlock();
1221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 write_lock_bh(&neigh->lock);
1223 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001224 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001225 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 }
1227out:
1228 if (update_isrouter) {
1229 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1230 (neigh->flags | NTF_ROUTER) :
1231 (neigh->flags & ~NTF_ROUTER);
1232 }
1233 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001234
1235 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001236 neigh_update_notify(neigh);
1237
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 return err;
1239}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001240EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Jiri Benc7e980562013-12-11 13:48:20 +01001242/* Update the neigh to listen temporarily for probe responses, even if it is
1243 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1244 */
1245void __neigh_set_probe_once(struct neighbour *neigh)
1246{
1247 neigh->updated = jiffies;
1248 if (!(neigh->nud_state & NUD_FAILED))
1249 return;
1250 neigh->nud_state = NUD_PROBE;
1251 atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
1252 neigh_add_timer(neigh,
1253 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1254}
1255EXPORT_SYMBOL(__neigh_set_probe_once);
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1258 u8 *lladdr, void *saddr,
1259 struct net_device *dev)
1260{
1261 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1262 lladdr || !dev->addr_len);
1263 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001264 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 NEIGH_UPDATE_F_OVERRIDE);
1266 return neigh;
1267}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001268EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Eric Dumazet34d101d2010-10-11 09:16:57 -07001270/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001271static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001274 __be16 prot = dst->ops->protocol;
1275 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001276
1277 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001278
David S. Millerf6b72b62011-07-14 07:53:20 -07001279 /* Only one thread can come in here and initialize the
1280 * hh_cache entry.
1281 */
David S. Millerb23b5452011-07-16 17:45:02 -07001282 if (!hh->hh_len)
1283 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001284
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001285 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286}
1287
1288/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001289 * worked, f.e. if you want to override normal output path (eql, shaper),
1290 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 */
1292
David S. Miller8f40b162011-07-17 13:34:11 -07001293int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294{
1295 struct net_device *dev = skb->dev;
1296
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001297 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001299 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1300 skb->len) < 0 &&
David S. Miller22053692013-12-31 16:23:35 -05001301 dev_rebuild_header(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return 0;
1303
1304 return dev_queue_xmit(skb);
1305}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001306EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308/* Slow and careful. */
1309
David S. Miller8f40b162011-07-17 13:34:11 -07001310int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
Eric Dumazetadf30902009-06-02 05:19:30 +00001312 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 int rc = 0;
1314
David S. Miller8f40b162011-07-17 13:34:11 -07001315 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 goto discard;
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 if (!neigh_event_send(neigh, skb)) {
1319 int err;
1320 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001321 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001322
David S. Millerf6b72b62011-07-14 07:53:20 -07001323 if (dev->header_ops->cache && !neigh->hh.hh_len)
1324 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001325
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001326 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001327 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001328 seq = read_seqbegin(&neigh->ha_lock);
1329 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1330 neigh->ha, NULL, skb->len);
1331 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001334 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 else
1336 goto out_kfree_skb;
1337 }
1338out:
1339 return rc;
1340discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001341 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342out_kfree_skb:
1343 rc = -EINVAL;
1344 kfree_skb(skb);
1345 goto out;
1346}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001347EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
1349/* As fast as possible without hh cache */
1350
David S. Miller8f40b162011-07-17 13:34:11 -07001351int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001354 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001355 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001357 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001358 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001359 seq = read_seqbegin(&neigh->ha_lock);
1360 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1361 neigh->ha, NULL, skb->len);
1362 } while (read_seqretry(&neigh->ha_lock, seq));
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001365 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 else {
1367 err = -EINVAL;
1368 kfree_skb(skb);
1369 }
1370 return err;
1371}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001372EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
David S. Miller8f40b162011-07-17 13:34:11 -07001374int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1375{
1376 return dev_queue_xmit(skb);
1377}
1378EXPORT_SYMBOL(neigh_direct_output);
1379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380static void neigh_proxy_process(unsigned long arg)
1381{
1382 struct neigh_table *tbl = (struct neigh_table *)arg;
1383 long sched_next = 0;
1384 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001385 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 spin_lock(&tbl->proxy_queue.lock);
1388
David S. Millerf72051b2008-09-23 01:11:18 -07001389 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1390 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001393 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001394
David S. Millerf72051b2008-09-23 01:11:18 -07001395 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001396 if (tbl->proxy_redo && netif_running(dev)) {
1397 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001398 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001399 rcu_read_unlock();
1400 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001401 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
1404 dev_put(dev);
1405 } else if (!sched_next || tdif < sched_next)
1406 sched_next = tdif;
1407 }
1408 del_timer(&tbl->proxy_timer);
1409 if (sched_next)
1410 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1411 spin_unlock(&tbl->proxy_queue.lock);
1412}
1413
1414void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1415 struct sk_buff *skb)
1416{
1417 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001418
1419 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001420 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001422 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 kfree_skb(skb);
1424 return;
1425 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001426
1427 NEIGH_CB(skb)->sched_next = sched_next;
1428 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
1430 spin_lock(&tbl->proxy_queue.lock);
1431 if (del_timer(&tbl->proxy_timer)) {
1432 if (time_before(tbl->proxy_timer.expires, sched_next))
1433 sched_next = tbl->proxy_timer.expires;
1434 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001435 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 dev_hold(skb->dev);
1437 __skb_queue_tail(&tbl->proxy_queue, skb);
1438 mod_timer(&tbl->proxy_timer, sched_next);
1439 spin_unlock(&tbl->proxy_queue.lock);
1440}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001441EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001443static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001444 struct net *net, int ifindex)
1445{
1446 struct neigh_parms *p;
1447
1448 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001449 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001450 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001451 return p;
1452 }
1453
1454 return NULL;
1455}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1458 struct neigh_table *tbl)
1459{
Gao fengcf89d6b2013-06-20 10:01:32 +08001460 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001461 struct net *net = dev_net(dev);
1462 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
Gao fengcf89d6b2013-06-20 10:01:32 +08001464 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 p->tbl = tbl;
1467 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001469 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001470 dev_hold(dev);
1471 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001472 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001474
1475 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1476 release_net(net);
1477 dev_put(dev);
1478 kfree(p);
1479 return NULL;
1480 }
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 write_lock_bh(&tbl->lock);
1483 p->next = tbl->parms.next;
1484 tbl->parms.next = p;
1485 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001486
1487 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 }
1489 return p;
1490}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001491EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493static void neigh_rcu_free_parms(struct rcu_head *head)
1494{
1495 struct neigh_parms *parms =
1496 container_of(head, struct neigh_parms, rcu_head);
1497
1498 neigh_parms_put(parms);
1499}
1500
1501void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1502{
1503 struct neigh_parms **p;
1504
1505 if (!parms || parms == &tbl->parms)
1506 return;
1507 write_lock_bh(&tbl->lock);
1508 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1509 if (*p == parms) {
1510 *p = parms->next;
1511 parms->dead = 1;
1512 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001513 if (parms->dev)
1514 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1516 return;
1517 }
1518 }
1519 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001520 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001522EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Denis V. Lunev06f05112008-01-24 00:30:58 -08001524static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001526 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 kfree(parms);
1528}
1529
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001530static struct lock_class_key neigh_table_proxy_queue_class;
1531
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001532static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
1534 unsigned long now = jiffies;
1535 unsigned long phsize;
1536
Eric Dumazete42ea982008-11-12 00:54:54 -08001537 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 tbl->parms.reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001540 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 tbl->stats = alloc_percpu(struct neigh_statistics);
1543 if (!tbl->stats)
1544 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001547 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1548 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550#endif
1551
David S. Millercd089332011-07-11 01:28:12 -07001552 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
1554 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001555 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001557 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 panic("cannot allocate neighbour cache hashes");
1559
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001560 if (!tbl->entry_size)
1561 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1562 tbl->key_len, NEIGH_PRIV_ALIGN);
1563 else
1564 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1565
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001567 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301568 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1569 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001570 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001571 skb_queue_head_init_class(&tbl->proxy_queue,
1572 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
1574 tbl->last_flush = now;
1575 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001576}
1577
1578void neigh_table_init(struct neigh_table *tbl)
1579{
1580 struct neigh_table *tmp;
1581
1582 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001584 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1585 if (tmp->family == tbl->family)
1586 break;
1587 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 tbl->next = neigh_tables;
1589 neigh_tables = tbl;
1590 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001591
1592 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001593 pr_err("Registering multiple tables for family %d\n",
1594 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001595 dump_stack();
1596 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001598EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
1600int neigh_table_clear(struct neigh_table *tbl)
1601{
1602 struct neigh_table **tp;
1603
1604 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001605 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 del_timer_sync(&tbl->proxy_timer);
1607 pneigh_queue_purge(&tbl->proxy_queue);
1608 neigh_ifdown(tbl, NULL);
1609 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001610 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 write_lock(&neigh_tbl_lock);
1612 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1613 if (*tp == tbl) {
1614 *tp = tbl->next;
1615 break;
1616 }
1617 }
1618 write_unlock(&neigh_tbl_lock);
1619
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001620 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1621 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001622 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623
1624 kfree(tbl->phash_buckets);
1625 tbl->phash_buckets = NULL;
1626
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001627 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1628
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001629 free_percpu(tbl->stats);
1630 tbl->stats = NULL;
1631
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632 return 0;
1633}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001634EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635
Thomas Graf661d2962013-03-21 07:45:29 +00001636static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001638 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001639 struct ndmsg *ndm;
1640 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 struct neigh_table *tbl;
1642 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001643 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
Eric Dumazet110b2492010-10-04 04:27:36 +00001645 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001646 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 goto out;
1648
Thomas Grafa14a49d2006-08-07 17:53:08 -07001649 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1650 if (dst_attr == NULL)
1651 goto out;
1652
1653 ndm = nlmsg_data(nlh);
1654 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001655 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001656 if (dev == NULL) {
1657 err = -ENODEV;
1658 goto out;
1659 }
1660 }
1661
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662 read_lock(&neigh_tbl_lock);
1663 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001664 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
1666 if (tbl->family != ndm->ndm_family)
1667 continue;
1668 read_unlock(&neigh_tbl_lock);
1669
Thomas Grafa14a49d2006-08-07 17:53:08 -07001670 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001671 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672
1673 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001674 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001675 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 }
1677
Thomas Grafa14a49d2006-08-07 17:53:08 -07001678 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001679 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
Thomas Grafa14a49d2006-08-07 17:53:08 -07001681 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1682 if (neigh == NULL) {
1683 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001684 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001686
1687 err = neigh_update(neigh, NULL, NUD_FAILED,
1688 NEIGH_UPDATE_F_OVERRIDE |
1689 NEIGH_UPDATE_F_ADMIN);
1690 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001691 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692 }
1693 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001694 err = -EAFNOSUPPORT;
1695
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696out:
1697 return err;
1698}
1699
Thomas Graf661d2962013-03-21 07:45:29 +00001700static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001702 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001703 struct ndmsg *ndm;
1704 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 struct neigh_table *tbl;
1706 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001707 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Eric Dumazet110b2492010-10-04 04:27:36 +00001709 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001710 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1711 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 goto out;
1713
Thomas Graf5208deb2006-08-07 17:55:40 -07001714 err = -EINVAL;
1715 if (tb[NDA_DST] == NULL)
1716 goto out;
1717
1718 ndm = nlmsg_data(nlh);
1719 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001720 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001721 if (dev == NULL) {
1722 err = -ENODEV;
1723 goto out;
1724 }
1725
1726 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001727 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001728 }
1729
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730 read_lock(&neigh_tbl_lock);
1731 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001732 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1733 struct neighbour *neigh;
1734 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
1736 if (tbl->family != ndm->ndm_family)
1737 continue;
1738 read_unlock(&neigh_tbl_lock);
1739
Thomas Graf5208deb2006-08-07 17:55:40 -07001740 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001741 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001742 dst = nla_data(tb[NDA_DST]);
1743 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744
1745 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001746 struct pneigh_entry *pn;
1747
1748 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001749 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001750 if (pn) {
1751 pn->flags = ndm->ndm_flags;
1752 err = 0;
1753 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001754 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 }
1756
Thomas Graf5208deb2006-08-07 17:55:40 -07001757 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001758 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001759
1760 neigh = neigh_lookup(tbl, dst, dev);
1761 if (neigh == NULL) {
1762 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1763 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001764 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001765 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001766
Thomas Graf5208deb2006-08-07 17:55:40 -07001767 neigh = __neigh_lookup_errno(tbl, dst, dev);
1768 if (IS_ERR(neigh)) {
1769 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001770 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001771 }
1772 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1774 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001775 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001776 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001778
1779 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1780 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 }
1782
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001783 if (ndm->ndm_flags & NTF_USE) {
1784 neigh_event_send(neigh, NULL);
1785 err = 0;
1786 } else
1787 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001788 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001789 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001790 }
1791
1792 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001793 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001794out:
1795 return err;
1796}
1797
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001798static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1799{
Thomas Grafca860fb2006-08-07 18:00:18 -07001800 struct nlattr *nest;
1801
1802 nest = nla_nest_start(skb, NDTA_PARMS);
1803 if (nest == NULL)
1804 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001805
David S. Miller9a6308d2012-04-01 20:06:28 -04001806 if ((parms->dev &&
1807 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1808 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001809 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1810 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001811 /* approximative value for deprecated QUEUE_LEN (in packets) */
1812 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001813 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1814 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1815 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1816 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1817 NEIGH_VAR(parms, UCAST_PROBES)) ||
1818 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1819 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001820 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1821 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001822 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1823 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1824 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001825 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001826 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1827 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1828 NEIGH_VAR(parms, RETRANS_TIME)) ||
1829 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1830 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1831 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1832 NEIGH_VAR(parms, PROXY_DELAY)) ||
1833 nla_put_msecs(skb, NDTPA_LOCKTIME,
1834 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001835 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001836 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001837
Thomas Grafca860fb2006-08-07 18:00:18 -07001838nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001839 nla_nest_cancel(skb, nest);
1840 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001841}
1842
Thomas Grafca860fb2006-08-07 18:00:18 -07001843static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1844 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001845{
1846 struct nlmsghdr *nlh;
1847 struct ndtmsg *ndtmsg;
1848
Thomas Grafca860fb2006-08-07 18:00:18 -07001849 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1850 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001851 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852
Thomas Grafca860fb2006-08-07 18:00:18 -07001853 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001854
1855 read_lock_bh(&tbl->lock);
1856 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001857 ndtmsg->ndtm_pad1 = 0;
1858 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001859
David S. Miller9a6308d2012-04-01 20:06:28 -04001860 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1861 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1862 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1863 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1864 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1865 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001866 {
1867 unsigned long now = jiffies;
1868 unsigned int flush_delta = now - tbl->last_flush;
1869 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001870 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001871 struct ndt_config ndc = {
1872 .ndtc_key_len = tbl->key_len,
1873 .ndtc_entry_size = tbl->entry_size,
1874 .ndtc_entries = atomic_read(&tbl->entries),
1875 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1876 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001877 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1878 };
1879
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001880 rcu_read_lock_bh();
1881 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001882 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001883 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001884 rcu_read_unlock_bh();
1885
David S. Miller9a6308d2012-04-01 20:06:28 -04001886 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1887 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001888 }
1889
1890 {
1891 int cpu;
1892 struct ndt_stats ndst;
1893
1894 memset(&ndst, 0, sizeof(ndst));
1895
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001896 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001897 struct neigh_statistics *st;
1898
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001899 st = per_cpu_ptr(tbl->stats, cpu);
1900 ndst.ndts_allocs += st->allocs;
1901 ndst.ndts_destroys += st->destroys;
1902 ndst.ndts_hash_grows += st->hash_grows;
1903 ndst.ndts_res_failed += st->res_failed;
1904 ndst.ndts_lookups += st->lookups;
1905 ndst.ndts_hits += st->hits;
1906 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1907 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1908 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1909 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1910 }
1911
David S. Miller9a6308d2012-04-01 20:06:28 -04001912 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1913 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001914 }
1915
1916 BUG_ON(tbl->parms.dev);
1917 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001918 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001919
1920 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001921 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001922
Thomas Grafca860fb2006-08-07 18:00:18 -07001923nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001924 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001925 nlmsg_cancel(skb, nlh);
1926 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001927}
1928
Thomas Grafca860fb2006-08-07 18:00:18 -07001929static int neightbl_fill_param_info(struct sk_buff *skb,
1930 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001931 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001932 u32 pid, u32 seq, int type,
1933 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001934{
1935 struct ndtmsg *ndtmsg;
1936 struct nlmsghdr *nlh;
1937
Thomas Grafca860fb2006-08-07 18:00:18 -07001938 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1939 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001940 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001941
Thomas Grafca860fb2006-08-07 18:00:18 -07001942 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001943
1944 read_lock_bh(&tbl->lock);
1945 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001946 ndtmsg->ndtm_pad1 = 0;
1947 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001948
Thomas Grafca860fb2006-08-07 18:00:18 -07001949 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1950 neightbl_fill_parms(skb, parms) < 0)
1951 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001952
1953 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001954 return nlmsg_end(skb, nlh);
1955errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001956 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001957 nlmsg_cancel(skb, nlh);
1958 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001959}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001960
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001961static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001962 [NDTA_NAME] = { .type = NLA_STRING },
1963 [NDTA_THRESH1] = { .type = NLA_U32 },
1964 [NDTA_THRESH2] = { .type = NLA_U32 },
1965 [NDTA_THRESH3] = { .type = NLA_U32 },
1966 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1967 [NDTA_PARMS] = { .type = NLA_NESTED },
1968};
1969
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001970static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001971 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1972 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1973 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1974 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1975 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1976 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1977 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1978 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1979 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1980 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1981 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1982 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1983 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1984};
1985
Thomas Graf661d2962013-03-21 07:45:29 +00001986static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001987{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001988 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001989 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001990 struct ndtmsg *ndtmsg;
1991 struct nlattr *tb[NDTA_MAX+1];
1992 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001993
Thomas Graf6b3f8672006-08-07 17:58:53 -07001994 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1995 nl_neightbl_policy);
1996 if (err < 0)
1997 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001998
Thomas Graf6b3f8672006-08-07 17:58:53 -07001999 if (tb[NDTA_NAME] == NULL) {
2000 err = -EINVAL;
2001 goto errout;
2002 }
2003
2004 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002005 read_lock(&neigh_tbl_lock);
2006 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
2007 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2008 continue;
2009
Thomas Graf6b3f8672006-08-07 17:58:53 -07002010 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002011 break;
2012 }
2013
2014 if (tbl == NULL) {
2015 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002016 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002017 }
2018
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002019 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002020 * We acquire tbl->lock to be nice to the periodic timers and
2021 * make sure they always see a consistent set of values.
2022 */
2023 write_lock_bh(&tbl->lock);
2024
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 if (tb[NDTA_PARMS]) {
2026 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002027 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002028 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002029
Thomas Graf6b3f8672006-08-07 17:58:53 -07002030 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2031 nl_ntbl_parm_policy);
2032 if (err < 0)
2033 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002034
Thomas Graf6b3f8672006-08-07 17:58:53 -07002035 if (tbp[NDTPA_IFINDEX])
2036 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002037
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002038 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002039 if (p == NULL) {
2040 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002041 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002042 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002043
Thomas Graf6b3f8672006-08-07 17:58:53 -07002044 for (i = 1; i <= NDTPA_MAX; i++) {
2045 if (tbp[i] == NULL)
2046 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002047
Thomas Graf6b3f8672006-08-07 17:58:53 -07002048 switch (i) {
2049 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002050 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2051 nla_get_u32(tbp[i]) *
2052 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002053 break;
2054 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002055 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2056 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002057 break;
2058 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002059 NEIGH_VAR_SET(p, PROXY_QLEN,
2060 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002061 break;
2062 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002063 NEIGH_VAR_SET(p, APP_PROBES,
2064 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002065 break;
2066 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002067 NEIGH_VAR_SET(p, UCAST_PROBES,
2068 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002069 break;
2070 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002071 NEIGH_VAR_SET(p, MCAST_PROBES,
2072 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002073 break;
2074 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002075 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2076 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002077 break;
2078 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002079 NEIGH_VAR_SET(p, GC_STALETIME,
2080 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002081 break;
2082 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002083 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2084 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002085 break;
2086 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002087 NEIGH_VAR_SET(p, RETRANS_TIME,
2088 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002089 break;
2090 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002091 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2092 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002093 break;
2094 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002095 NEIGH_VAR_SET(p, PROXY_DELAY,
2096 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002097 break;
2098 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002099 NEIGH_VAR_SET(p, LOCKTIME,
2100 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002101 break;
2102 }
2103 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002104 }
2105
Gao fengdc25c672013-06-20 10:01:34 +08002106 err = -ENOENT;
2107 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2108 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2109 !net_eq(net, &init_net))
2110 goto errout_tbl_lock;
2111
Thomas Graf6b3f8672006-08-07 17:58:53 -07002112 if (tb[NDTA_THRESH1])
2113 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2114
2115 if (tb[NDTA_THRESH2])
2116 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2117
2118 if (tb[NDTA_THRESH3])
2119 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2120
2121 if (tb[NDTA_GC_INTERVAL])
2122 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2123
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002124 err = 0;
2125
Thomas Graf6b3f8672006-08-07 17:58:53 -07002126errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002127 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002128errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002129 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002130errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002131 return err;
2132}
2133
Thomas Grafc8822a42007-03-22 11:50:06 -07002134static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002135{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002136 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002137 int family, tidx, nidx = 0;
2138 int tbl_skip = cb->args[0];
2139 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002140 struct neigh_table *tbl;
2141
Thomas Grafca860fb2006-08-07 18:00:18 -07002142 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002143
2144 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002145 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146 struct neigh_parms *p;
2147
Thomas Grafca860fb2006-08-07 18:00:18 -07002148 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002149 continue;
2150
Eric W. Biederman15e47302012-09-07 20:12:54 +00002151 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002152 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2153 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002154 break;
2155
Eric W. Biederman426b5302008-01-24 00:13:18 -08002156 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002157 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002158 continue;
2159
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002160 if (nidx < neigh_skip)
2161 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002162
Thomas Grafca860fb2006-08-07 18:00:18 -07002163 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002164 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002165 cb->nlh->nlmsg_seq,
2166 RTM_NEWNEIGHTBL,
2167 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002168 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002169 next:
2170 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002171 }
2172
Thomas Grafca860fb2006-08-07 18:00:18 -07002173 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002174 }
2175out:
2176 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002177 cb->args[0] = tidx;
2178 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002179
2180 return skb->len;
2181}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002182
Thomas Graf8b8aec52006-08-07 17:56:37 -07002183static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2184 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
2186 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002188 struct nlmsghdr *nlh;
2189 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190
Thomas Graf8b8aec52006-08-07 17:56:37 -07002191 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2192 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002193 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002194
2195 ndm = nlmsg_data(nlh);
2196 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002197 ndm->ndm_pad1 = 0;
2198 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199 ndm->ndm_flags = neigh->flags;
2200 ndm->ndm_type = neigh->type;
2201 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202
David S. Miller9a6308d2012-04-01 20:06:28 -04002203 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2204 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002205
2206 read_lock_bh(&neigh->lock);
2207 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002208 if (neigh->nud_state & NUD_VALID) {
2209 char haddr[MAX_ADDR_LEN];
2210
2211 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2212 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2213 read_unlock_bh(&neigh->lock);
2214 goto nla_put_failure;
2215 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002216 }
2217
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002218 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2219 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2220 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002221 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2222 read_unlock_bh(&neigh->lock);
2223
David S. Miller9a6308d2012-04-01 20:06:28 -04002224 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2225 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2226 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002227
2228 return nlmsg_end(skb, nlh);
2229
2230nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002231 nlmsg_cancel(skb, nlh);
2232 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233}
2234
Tony Zelenoff84920c12012-01-26 22:28:58 +00002235static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2236 u32 pid, u32 seq, int type, unsigned int flags,
2237 struct neigh_table *tbl)
2238{
2239 struct nlmsghdr *nlh;
2240 struct ndmsg *ndm;
2241
2242 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2243 if (nlh == NULL)
2244 return -EMSGSIZE;
2245
2246 ndm = nlmsg_data(nlh);
2247 ndm->ndm_family = tbl->family;
2248 ndm->ndm_pad1 = 0;
2249 ndm->ndm_pad2 = 0;
2250 ndm->ndm_flags = pn->flags | NTF_PROXY;
2251 ndm->ndm_type = NDA_DST;
2252 ndm->ndm_ifindex = pn->dev->ifindex;
2253 ndm->ndm_state = NUD_NONE;
2254
David S. Miller9a6308d2012-04-01 20:06:28 -04002255 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2256 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002257
2258 return nlmsg_end(skb, nlh);
2259
2260nla_put_failure:
2261 nlmsg_cancel(skb, nlh);
2262 return -EMSGSIZE;
2263}
2264
Thomas Grafd961db32007-08-08 23:12:56 -07002265static void neigh_update_notify(struct neighbour *neigh)
2266{
2267 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2268 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2269}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270
2271static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2272 struct netlink_callback *cb)
2273{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002274 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 struct neighbour *n;
2276 int rc, h, s_h = cb->args[1];
2277 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002278 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002280 rcu_read_lock_bh();
2281 nht = rcu_dereference_bh(tbl->nht);
2282
Eric Dumazet4bd66832012-06-07 04:58:35 +00002283 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284 if (h > s_h)
2285 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002286 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2287 n != NULL;
2288 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002289 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002290 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002291 if (idx < s_idx)
2292 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002293 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002295 RTM_NEWNEIGH,
2296 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 rc = -1;
2298 goto out;
2299 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002300next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002301 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 }
2304 rc = skb->len;
2305out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002306 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002307 cb->args[1] = h;
2308 cb->args[2] = idx;
2309 return rc;
2310}
2311
Tony Zelenoff84920c12012-01-26 22:28:58 +00002312static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2313 struct netlink_callback *cb)
2314{
2315 struct pneigh_entry *n;
2316 struct net *net = sock_net(skb->sk);
2317 int rc, h, s_h = cb->args[3];
2318 int idx, s_idx = idx = cb->args[4];
2319
2320 read_lock_bh(&tbl->lock);
2321
Eric Dumazet4bd66832012-06-07 04:58:35 +00002322 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002323 if (h > s_h)
2324 s_idx = 0;
2325 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2326 if (dev_net(n->dev) != net)
2327 continue;
2328 if (idx < s_idx)
2329 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002330 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002331 cb->nlh->nlmsg_seq,
2332 RTM_NEWNEIGH,
2333 NLM_F_MULTI, tbl) <= 0) {
2334 read_unlock_bh(&tbl->lock);
2335 rc = -1;
2336 goto out;
2337 }
2338 next:
2339 idx++;
2340 }
2341 }
2342
2343 read_unlock_bh(&tbl->lock);
2344 rc = skb->len;
2345out:
2346 cb->args[3] = h;
2347 cb->args[4] = idx;
2348 return rc;
2349
2350}
2351
Thomas Grafc8822a42007-03-22 11:50:06 -07002352static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353{
2354 struct neigh_table *tbl;
2355 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002356 int proxy = 0;
Eric Dumazet4bd66832012-06-07 04:58:35 +00002357 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
2359 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002360 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002361
2362 /* check for full ndmsg structure presence, family member is
2363 * the same for both structures
2364 */
2365 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2366 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2367 proxy = 1;
2368
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 s_t = cb->args[0];
2370
Eric Dumazet4bd66832012-06-07 04:58:35 +00002371 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002372 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 if (t < s_t || (family && tbl->family != family))
2374 continue;
2375 if (t > s_t)
2376 memset(&cb->args[1], 0, sizeof(cb->args) -
2377 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002378 if (proxy)
2379 err = pneigh_dump_table(tbl, skb, cb);
2380 else
2381 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd66832012-06-07 04:58:35 +00002382 if (err < 0)
2383 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 }
2385 read_unlock(&neigh_tbl_lock);
2386
2387 cb->args[0] = t;
2388 return skb->len;
2389}
2390
2391void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2392{
2393 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002394 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002396 rcu_read_lock_bh();
2397 nht = rcu_dereference_bh(tbl->nht);
2398
Eric Dumazet767e97e2010-10-06 17:49:21 -07002399 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002400 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401 struct neighbour *n;
2402
Eric Dumazet767e97e2010-10-06 17:49:21 -07002403 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2404 n != NULL;
2405 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 cb(n, cookie);
2407 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002408 read_unlock(&tbl->lock);
2409 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410}
2411EXPORT_SYMBOL(neigh_for_each);
2412
2413/* The tbl->lock must be held as a writer and BH disabled. */
2414void __neigh_for_each_release(struct neigh_table *tbl,
2415 int (*cb)(struct neighbour *))
2416{
2417 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002418 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002420 nht = rcu_dereference_protected(tbl->nht,
2421 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002422 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002423 struct neighbour *n;
2424 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002426 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002427 while ((n = rcu_dereference_protected(*np,
2428 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 int release;
2430
2431 write_lock(&n->lock);
2432 release = cb(n);
2433 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002434 rcu_assign_pointer(*np,
2435 rcu_dereference_protected(n->next,
2436 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 n->dead = 1;
2438 } else
2439 np = &n->next;
2440 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002441 if (release)
2442 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 }
2444 }
2445}
2446EXPORT_SYMBOL(__neigh_for_each_release);
2447
2448#ifdef CONFIG_PROC_FS
2449
2450static struct neighbour *neigh_get_first(struct seq_file *seq)
2451{
2452 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002453 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002454 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 struct neighbour *n = NULL;
2456 int bucket = state->bucket;
2457
2458 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002459 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002460 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461
2462 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002463 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002464 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 if (state->neigh_sub_iter) {
2466 loff_t fakep = 0;
2467 void *v;
2468
2469 v = state->neigh_sub_iter(state, n, &fakep);
2470 if (!v)
2471 goto next;
2472 }
2473 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2474 break;
2475 if (n->nud_state & ~NUD_NOARP)
2476 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002477next:
2478 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479 }
2480
2481 if (n)
2482 break;
2483 }
2484 state->bucket = bucket;
2485
2486 return n;
2487}
2488
2489static struct neighbour *neigh_get_next(struct seq_file *seq,
2490 struct neighbour *n,
2491 loff_t *pos)
2492{
2493 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002494 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002495 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
2497 if (state->neigh_sub_iter) {
2498 void *v = state->neigh_sub_iter(state, n, pos);
2499 if (v)
2500 return n;
2501 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002502 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503
2504 while (1) {
2505 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002506 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002507 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 if (state->neigh_sub_iter) {
2509 void *v = state->neigh_sub_iter(state, n, pos);
2510 if (v)
2511 return n;
2512 goto next;
2513 }
2514 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2515 break;
2516
2517 if (n->nud_state & ~NUD_NOARP)
2518 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002519next:
2520 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 }
2522
2523 if (n)
2524 break;
2525
David S. Millercd089332011-07-11 01:28:12 -07002526 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 break;
2528
Eric Dumazet767e97e2010-10-06 17:49:21 -07002529 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 }
2531
2532 if (n && pos)
2533 --(*pos);
2534 return n;
2535}
2536
2537static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2538{
2539 struct neighbour *n = neigh_get_first(seq);
2540
2541 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002542 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 while (*pos) {
2544 n = neigh_get_next(seq, n, pos);
2545 if (!n)
2546 break;
2547 }
2548 }
2549 return *pos ? NULL : n;
2550}
2551
2552static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2553{
2554 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002555 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556 struct neigh_table *tbl = state->tbl;
2557 struct pneigh_entry *pn = NULL;
2558 int bucket = state->bucket;
2559
2560 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2561 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2562 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002563 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002564 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 if (pn)
2566 break;
2567 }
2568 state->bucket = bucket;
2569
2570 return pn;
2571}
2572
2573static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2574 struct pneigh_entry *pn,
2575 loff_t *pos)
2576{
2577 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002578 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 struct neigh_table *tbl = state->tbl;
2580
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002581 do {
2582 pn = pn->next;
2583 } while (pn && !net_eq(pneigh_net(pn), net));
2584
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 while (!pn) {
2586 if (++state->bucket > PNEIGH_HASHMASK)
2587 break;
2588 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002589 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002590 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 if (pn)
2592 break;
2593 }
2594
2595 if (pn && pos)
2596 --(*pos);
2597
2598 return pn;
2599}
2600
2601static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2602{
2603 struct pneigh_entry *pn = pneigh_get_first(seq);
2604
2605 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002606 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 while (*pos) {
2608 pn = pneigh_get_next(seq, pn, pos);
2609 if (!pn)
2610 break;
2611 }
2612 }
2613 return *pos ? NULL : pn;
2614}
2615
2616static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2617{
2618 struct neigh_seq_state *state = seq->private;
2619 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002620 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621
Chris Larson745e2032008-08-03 01:10:55 -07002622 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002624 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625
2626 return rc;
2627}
2628
2629void *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 +00002630 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
2632 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
2634 state->tbl = tbl;
2635 state->bucket = 0;
2636 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2637
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002638 rcu_read_lock_bh();
2639 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002640
Chris Larson745e2032008-08-03 01:10:55 -07002641 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642}
2643EXPORT_SYMBOL(neigh_seq_start);
2644
2645void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2646{
2647 struct neigh_seq_state *state;
2648 void *rc;
2649
2650 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002651 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652 goto out;
2653 }
2654
2655 state = seq->private;
2656 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2657 rc = neigh_get_next(seq, v, NULL);
2658 if (rc)
2659 goto out;
2660 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2661 rc = pneigh_get_first(seq);
2662 } else {
2663 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2664 rc = pneigh_get_next(seq, v, NULL);
2665 }
2666out:
2667 ++(*pos);
2668 return rc;
2669}
2670EXPORT_SYMBOL(neigh_seq_next);
2671
2672void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002673 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002675 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676}
2677EXPORT_SYMBOL(neigh_seq_stop);
2678
2679/* statistics via seq_file */
2680
2681static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2682{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002683 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 int cpu;
2685
2686 if (*pos == 0)
2687 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002688
Rusty Russell0f23174a2008-12-29 12:23:42 +00002689 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 if (!cpu_possible(cpu))
2691 continue;
2692 *pos = cpu+1;
2693 return per_cpu_ptr(tbl->stats, cpu);
2694 }
2695 return NULL;
2696}
2697
2698static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2699{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002700 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 int cpu;
2702
Rusty Russell0f23174a2008-12-29 12:23:42 +00002703 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 if (!cpu_possible(cpu))
2705 continue;
2706 *pos = cpu+1;
2707 return per_cpu_ptr(tbl->stats, cpu);
2708 }
2709 return NULL;
2710}
2711
2712static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2713{
2714
2715}
2716
2717static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2718{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002719 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 struct neigh_statistics *st = v;
2721
2722 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002723 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 -07002724 return 0;
2725 }
2726
2727 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002728 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002729 atomic_read(&tbl->entries),
2730
2731 st->allocs,
2732 st->destroys,
2733 st->hash_grows,
2734
2735 st->lookups,
2736 st->hits,
2737
2738 st->res_failed,
2739
2740 st->rcv_probes_mcast,
2741 st->rcv_probes_ucast,
2742
2743 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002744 st->forced_gc_runs,
2745 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 );
2747
2748 return 0;
2749}
2750
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002751static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 .start = neigh_stat_seq_start,
2753 .next = neigh_stat_seq_next,
2754 .stop = neigh_stat_seq_stop,
2755 .show = neigh_stat_seq_show,
2756};
2757
2758static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2759{
2760 int ret = seq_open(file, &neigh_stat_seq_ops);
2761
2762 if (!ret) {
2763 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002764 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 }
2766 return ret;
2767};
2768
Arjan van de Ven9a321442007-02-12 00:55:35 -08002769static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770 .owner = THIS_MODULE,
2771 .open = neigh_stat_seq_open,
2772 .read = seq_read,
2773 .llseek = seq_lseek,
2774 .release = seq_release,
2775};
2776
2777#endif /* CONFIG_PROC_FS */
2778
Thomas Graf339bf982006-11-10 14:10:15 -08002779static inline size_t neigh_nlmsg_size(void)
2780{
2781 return NLMSG_ALIGN(sizeof(struct ndmsg))
2782 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2783 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2784 + nla_total_size(sizeof(struct nda_cacheinfo))
2785 + nla_total_size(4); /* NDA_PROBES */
2786}
2787
Thomas Grafb8673312006-08-15 00:33:14 -07002788static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002790 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002791 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002792 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793
Thomas Graf339bf982006-11-10 14:10:15 -08002794 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002795 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002796 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Thomas Grafb8673312006-08-15 00:33:14 -07002798 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002799 if (err < 0) {
2800 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2801 WARN_ON(err == -EMSGSIZE);
2802 kfree_skb(skb);
2803 goto errout;
2804 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002805 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2806 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002807errout:
2808 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002809 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002810}
2811
2812void neigh_app_ns(struct neighbour *n)
2813{
2814 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002816EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817
2818#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002819static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002820static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002821static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822
Joe Perchesfe2c6332013-06-11 23:04:25 -07002823static int proc_unres_qlen(struct ctl_table *ctl, int write,
2824 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002825{
2826 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002827 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002828
Shan Weice46cc62012-12-04 18:49:15 +00002829 tmp.extra1 = &zero;
2830 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002831 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002832
2833 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2834 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2835
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002836 if (write && !ret)
2837 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2838 return ret;
2839}
2840
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002841static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2842 int family)
2843{
Jiri Pirkobba24892013-12-07 19:26:57 +01002844 switch (family) {
2845 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002846 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002847 case AF_INET6:
2848 return __in6_dev_nd_parms_get_rcu(dev);
2849 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002850 return NULL;
2851}
2852
2853static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2854 int index)
2855{
2856 struct net_device *dev;
2857 int family = neigh_parms_family(p);
2858
2859 rcu_read_lock();
2860 for_each_netdev_rcu(net, dev) {
2861 struct neigh_parms *dst_p =
2862 neigh_get_dev_parms_rcu(dev, family);
2863
2864 if (dst_p && !test_bit(index, dst_p->data_state))
2865 dst_p->data[index] = p->data[index];
2866 }
2867 rcu_read_unlock();
2868}
2869
2870static void neigh_proc_update(struct ctl_table *ctl, int write)
2871{
2872 struct net_device *dev = ctl->extra1;
2873 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002874 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002875 int index = (int *) ctl->data - p->data;
2876
2877 if (!write)
2878 return;
2879
2880 set_bit(index, p->data_state);
2881 if (!dev) /* NULL dev means this is default value */
2882 neigh_copy_dflt_parms(net, p, index);
2883}
2884
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002885static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2886 void __user *buffer,
2887 size_t *lenp, loff_t *ppos)
2888{
2889 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002890 int ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002891
2892 tmp.extra1 = &zero;
2893 tmp.extra2 = &int_max;
2894
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002895 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2896 neigh_proc_update(ctl, write);
2897 return ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002898}
2899
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002900int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2901 void __user *buffer, size_t *lenp, loff_t *ppos)
2902{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002903 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2904
2905 neigh_proc_update(ctl, write);
2906 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002907}
2908EXPORT_SYMBOL(neigh_proc_dointvec);
2909
2910int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2911 void __user *buffer,
2912 size_t *lenp, loff_t *ppos)
2913{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002914 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2915
2916 neigh_proc_update(ctl, write);
2917 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002918}
2919EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2920
2921static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2922 void __user *buffer,
2923 size_t *lenp, loff_t *ppos)
2924{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002925 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2926
2927 neigh_proc_update(ctl, write);
2928 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002929}
2930
2931int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2932 void __user *buffer,
2933 size_t *lenp, loff_t *ppos)
2934{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002935 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2936
2937 neigh_proc_update(ctl, write);
2938 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002939}
2940EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2941
2942static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2943 void __user *buffer,
2944 size_t *lenp, loff_t *ppos)
2945{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002946 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2947
2948 neigh_proc_update(ctl, write);
2949 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002950}
2951
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002952#define NEIGH_PARMS_DATA_OFFSET(index) \
2953 (&((struct neigh_parms *) 0)->data[index])
2954
2955#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2956 [NEIGH_VAR_ ## attr] = { \
2957 .procname = name, \
2958 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2959 .maxlen = sizeof(int), \
2960 .mode = mval, \
2961 .proc_handler = proc, \
2962 }
2963
2964#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2965 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2966
2967#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002968 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002969
2970#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002971 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002972
2973#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002974 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002975
2976#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002977 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002978
2979#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002980 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002981
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982static struct neigh_sysctl_table {
2983 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002984 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002985} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 .neigh_vars = {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002987 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2988 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2989 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2990 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2991 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2992 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2993 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2994 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2995 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2996 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2997 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2998 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
2999 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3000 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3001 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003002 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 .procname = "gc_interval",
3004 .maxlen = sizeof(int),
3005 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003006 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003008 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 .procname = "gc_thresh1",
3010 .maxlen = sizeof(int),
3011 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003012 .extra1 = &zero,
3013 .extra2 = &int_max,
3014 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003016 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 .procname = "gc_thresh2",
3018 .maxlen = sizeof(int),
3019 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003020 .extra1 = &zero,
3021 .extra2 = &int_max,
3022 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003024 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 .procname = "gc_thresh3",
3026 .maxlen = sizeof(int),
3027 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003028 .extra1 = &zero,
3029 .extra2 = &int_max,
3030 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003032 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 },
3034};
3035
3036int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003037 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038{
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003039 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003040 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003041 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003042 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003043 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003045 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003047 goto err;
3048
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003049 for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003050 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003051 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003052 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
3055 if (dev) {
3056 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003057 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003058 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3059 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 } else {
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003061 dev_name_source = "default";
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003062 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = (int *)(p + 1);
3063 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = (int *)(p + 1) + 1;
3064 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = (int *)(p + 1) + 2;
3065 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 }
3067
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003068 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003070 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003072 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003073 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003074 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003076 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 }
3078
Eric W. Biederman464dc802012-11-16 03:02:59 +00003079 /* Don't export sysctls to unprivileged users */
3080 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3081 t->neigh_vars[0].procname = NULL;
3082
Jiri Pirko73af6142013-12-07 19:26:55 +01003083 switch (neigh_parms_family(p)) {
3084 case AF_INET:
3085 p_name = "ipv4";
3086 break;
3087 case AF_INET6:
3088 p_name = "ipv6";
3089 break;
3090 default:
3091 BUG();
3092 }
3093
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003094 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3095 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003096 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003097 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003098 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003099 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003100
Linus Torvalds1da177e2005-04-16 15:20:36 -07003101 p->sysctl_table = t;
3102 return 0;
3103
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003104free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003106err:
3107 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003109EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111void neigh_sysctl_unregister(struct neigh_parms *p)
3112{
3113 if (p->sysctl_table) {
3114 struct neigh_sysctl_table *t = p->sysctl_table;
3115 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003116 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003117 kfree(t);
3118 }
3119}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003120EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121
3122#endif /* CONFIG_SYSCTL */
3123
Thomas Grafc8822a42007-03-22 11:50:06 -07003124static int __init neigh_init(void)
3125{
Greg Rosec7ac8672011-06-10 01:27:09 +00003126 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3127 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3128 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003129
Greg Rosec7ac8672011-06-10 01:27:09 +00003130 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3131 NULL);
3132 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003133
3134 return 0;
3135}
3136
3137subsys_initcall(neigh_init);
3138