blob: 8f8a96ef9f3f64ba519fe4c872d46c7b7c680ec9 [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
769 /*
770 * periodically recompute ReachableTime from random function
771 */
772
Eric Dumazete4c4e442009-07-30 03:15:07 +0000773 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 for (p = &tbl->parms; p; p = p->next)
777 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100778 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 }
780
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800781 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
782 goto out;
783
David S. Millercd089332011-07-11 01:28:12 -0700784 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000785 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Eric Dumazet767e97e2010-10-06 17:49:21 -0700787 while ((n = rcu_dereference_protected(*np,
788 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Eric Dumazete4c4e442009-07-30 03:15:07 +0000793 state = n->nud_state;
794 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
795 write_unlock(&n->lock);
796 goto next_elt;
797 }
798
799 if (time_before(n->used, n->confirmed))
800 n->used = n->confirmed;
801
802 if (atomic_read(&n->refcnt) == 1 &&
803 (state == NUD_FAILED ||
Jiri 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;
Timo Teräsa960ff82014-02-26 11:43:04 +0200839 int max_probes = NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES);
840 if (!(n->nud_state & NUD_PROBE))
841 max_probes += NEIGH_VAR(p, MCAST_PROBES);
842 return max_probes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Timo Teras5ef12d92009-06-11 04:16:28 -0700845static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000846 __releases(neigh->lock)
847 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700848{
849 struct sk_buff *skb;
850
851 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000852 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700853 neigh->updated = jiffies;
854
855 /* It is very thin place. report_unreachable is very complicated
856 routine. Particularly, it can hit the same neighbour entry!
857
858 So that, we try to be accurate and avoid dead loop. --ANK
859 */
860 while (neigh->nud_state == NUD_FAILED &&
861 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
862 write_unlock(&neigh->lock);
863 neigh->ops->error_report(neigh, skb);
864 write_lock(&neigh->lock);
865 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700866 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000867 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700868}
869
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000870static void neigh_probe(struct neighbour *neigh)
871 __releases(neigh->lock)
872{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200873 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000874 /* keep skb alive even if arp_queue overflows */
875 if (skb)
876 skb = skb_copy(skb, GFP_ATOMIC);
877 write_unlock(&neigh->lock);
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);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800948 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
950
951 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 if (time_before(next, jiffies + HZ/2))
953 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000954 if (!mod_timer(&neigh->timer, next))
955 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 }
957 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000958 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800959 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800960out:
David S. Miller9ff56602008-02-17 18:39:54 -0800961 write_unlock(&neigh->lock);
962 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963
Thomas Grafd961db32007-08-08 23:12:56 -0700964 if (notify)
965 neigh_update_notify(neigh);
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 neigh_release(neigh);
968}
969
970int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
971{
972 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000973 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
975 write_lock_bh(&neigh->lock);
976
977 rc = 0;
978 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
979 goto out_unlock_bh;
980
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100982 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
983 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000984 unsigned long next, now = jiffies;
985
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100986 atomic_set(&neigh->probes,
987 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000989 neigh->updated = now;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100990 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
991 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000992 neigh_add_timer(neigh, next);
993 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 } else {
995 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800996 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 write_unlock_bh(&neigh->lock);
998
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000999 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 return 1;
1001 }
1002 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001003 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001005 neigh->updated = jiffies;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001006 neigh_add_timer(neigh, jiffies +
1007 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 }
1009
1010 if (neigh->nud_state == NUD_INCOMPLETE) {
1011 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001012 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001013 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001015
David S. Millerf72051b2008-09-23 01:11:18 -07001016 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001017 if (!buff)
1018 break;
1019 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001021 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001023 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001025 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 }
1027 rc = 1;
1028 }
1029out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001030 if (immediate_probe)
1031 neigh_probe(neigh);
1032 else
1033 write_unlock(&neigh->lock);
1034 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return rc;
1036}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001037EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038
David S. Millerf6b72b62011-07-14 07:53:20 -07001039static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
1041 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001042 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001043 = NULL;
1044
1045 if (neigh->dev->header_ops)
1046 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047
1048 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001049 hh = &neigh->hh;
1050 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001051 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001053 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 }
1056}
1057
1058
1059
1060/* Generic update routine.
1061 -- lladdr is new lladdr or NULL, if it is not supplied.
1062 -- new is new state.
1063 -- flags
1064 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1065 if it is different.
1066 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001067 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 if it is different.
1069 It also allows to retain current state
1070 if lladdr is unchanged.
1071 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1072
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001073 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 NTF_ROUTER flag.
1075 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1076 a router.
1077
1078 Caller MUST hold reference count on the entry.
1079 */
1080
1081int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1082 u32 flags)
1083{
1084 u8 old;
1085 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 struct net_device *dev;
1088 int update_isrouter = 0;
1089
1090 write_lock_bh(&neigh->lock);
1091
1092 dev = neigh->dev;
1093 old = neigh->nud_state;
1094 err = -EPERM;
1095
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001096 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 (old & (NUD_NOARP | NUD_PERMANENT)))
1098 goto out;
1099
1100 if (!(new & NUD_VALID)) {
1101 neigh_del_timer(neigh);
1102 if (old & NUD_CONNECTED)
1103 neigh_suspect(neigh);
1104 neigh->nud_state = new;
1105 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001106 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001107 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1108 (new & NUD_FAILED)) {
1109 neigh_invalidate(neigh);
1110 notify = 1;
1111 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 goto out;
1113 }
1114
1115 /* Compare new lladdr with cached one */
1116 if (!dev->addr_len) {
1117 /* First case: device needs no address. */
1118 lladdr = neigh->ha;
1119 } else if (lladdr) {
1120 /* The second case: if something is already cached
1121 and a new address is proposed:
1122 - compare new & old
1123 - if they are different, check override flag
1124 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001125 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 !memcmp(lladdr, neigh->ha, dev->addr_len))
1127 lladdr = neigh->ha;
1128 } else {
1129 /* No address is supplied; if we know something,
1130 use it, otherwise discard the request.
1131 */
1132 err = -EINVAL;
1133 if (!(old & NUD_VALID))
1134 goto out;
1135 lladdr = neigh->ha;
1136 }
1137
1138 if (new & NUD_CONNECTED)
1139 neigh->confirmed = jiffies;
1140 neigh->updated = jiffies;
1141
1142 /* If entry was valid and address is not changed,
1143 do not change entry state, if new one is STALE.
1144 */
1145 err = 0;
1146 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1147 if (old & NUD_VALID) {
1148 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1149 update_isrouter = 0;
1150 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1151 (old & NUD_CONNECTED)) {
1152 lladdr = neigh->ha;
1153 new = NUD_STALE;
1154 } else
1155 goto out;
1156 } else {
1157 if (lladdr == neigh->ha && new == NUD_STALE &&
1158 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1159 (old & NUD_CONNECTED))
1160 )
1161 new = old;
1162 }
1163 }
1164
1165 if (new != old) {
1166 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001167 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001168 neigh_add_timer(neigh, (jiffies +
1169 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001170 neigh->parms->reachable_time :
1171 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001173 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 }
1175
1176 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001177 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001179 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 neigh_update_hhs(neigh);
1181 if (!(new & NUD_CONNECTED))
1182 neigh->confirmed = jiffies -
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001183 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 }
1186 if (new == old)
1187 goto out;
1188 if (new & NUD_CONNECTED)
1189 neigh_connect(neigh);
1190 else
1191 neigh_suspect(neigh);
1192 if (!(old & NUD_VALID)) {
1193 struct sk_buff *skb;
1194
1195 /* Again: avoid dead loop if something went wrong */
1196
1197 while (neigh->nud_state & NUD_VALID &&
1198 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001199 struct dst_entry *dst = skb_dst(skb);
1200 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001202
1203 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001204
1205 /* Why not just use 'neigh' as-is? The problem is that
1206 * things such as shaper, eql, and sch_teql can end up
1207 * using alternative, different, neigh objects to output
1208 * the packet in the output path. So what we need to do
1209 * here is re-lookup the top-level neigh in the path so
1210 * we can reinject the packet there.
1211 */
1212 n2 = NULL;
1213 if (dst) {
1214 n2 = dst_neigh_lookup_skb(dst, skb);
1215 if (n2)
1216 n1 = n2;
1217 }
David S. Miller8f40b162011-07-17 13:34:11 -07001218 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001219 if (n2)
1220 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001221 rcu_read_unlock();
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 write_lock_bh(&neigh->lock);
1224 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001225 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001226 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227 }
1228out:
1229 if (update_isrouter) {
1230 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1231 (neigh->flags | NTF_ROUTER) :
1232 (neigh->flags & ~NTF_ROUTER);
1233 }
1234 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001235
1236 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001237 neigh_update_notify(neigh);
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 return err;
1240}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001241EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242
Jiri Benc7e980562013-12-11 13:48:20 +01001243/* Update the neigh to listen temporarily for probe responses, even if it is
1244 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1245 */
1246void __neigh_set_probe_once(struct neighbour *neigh)
1247{
1248 neigh->updated = jiffies;
1249 if (!(neigh->nud_state & NUD_FAILED))
1250 return;
1251 neigh->nud_state = NUD_PROBE;
1252 atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
1253 neigh_add_timer(neigh,
1254 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1255}
1256EXPORT_SYMBOL(__neigh_set_probe_once);
1257
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1259 u8 *lladdr, void *saddr,
1260 struct net_device *dev)
1261{
1262 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1263 lladdr || !dev->addr_len);
1264 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001265 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 NEIGH_UPDATE_F_OVERRIDE);
1267 return neigh;
1268}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001269EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270
Eric Dumazet34d101d2010-10-11 09:16:57 -07001271/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001272static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001275 __be16 prot = dst->ops->protocol;
1276 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001277
1278 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001279
David S. Millerf6b72b62011-07-14 07:53:20 -07001280 /* Only one thread can come in here and initialize the
1281 * hh_cache entry.
1282 */
David S. Millerb23b5452011-07-16 17:45:02 -07001283 if (!hh->hh_len)
1284 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001285
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001286 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287}
1288
1289/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001290 * worked, f.e. if you want to override normal output path (eql, shaper),
1291 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 */
1293
David S. Miller8f40b162011-07-17 13:34:11 -07001294int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295{
1296 struct net_device *dev = skb->dev;
1297
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001298 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001300 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1301 skb->len) < 0 &&
David S. Miller22053692013-12-31 16:23:35 -05001302 dev_rebuild_header(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 return 0;
1304
1305 return dev_queue_xmit(skb);
1306}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001307EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
1309/* Slow and careful. */
1310
David S. Miller8f40b162011-07-17 13:34:11 -07001311int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312{
Eric Dumazetadf30902009-06-02 05:19:30 +00001313 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 int rc = 0;
1315
David S. Miller8f40b162011-07-17 13:34:11 -07001316 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 goto discard;
1318
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 if (!neigh_event_send(neigh, skb)) {
1320 int err;
1321 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001322 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001323
David S. Millerf6b72b62011-07-14 07:53:20 -07001324 if (dev->header_ops->cache && !neigh->hh.hh_len)
1325 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001326
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001327 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001328 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001329 seq = read_seqbegin(&neigh->ha_lock);
1330 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1331 neigh->ha, NULL, skb->len);
1332 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001335 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 else
1337 goto out_kfree_skb;
1338 }
1339out:
1340 return rc;
1341discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001342 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343out_kfree_skb:
1344 rc = -EINVAL;
1345 kfree_skb(skb);
1346 goto out;
1347}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001348EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349
1350/* As fast as possible without hh cache */
1351
David S. Miller8f40b162011-07-17 13:34:11 -07001352int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001355 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001356 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001358 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001359 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001360 seq = read_seqbegin(&neigh->ha_lock);
1361 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1362 neigh->ha, NULL, skb->len);
1363 } while (read_seqretry(&neigh->ha_lock, seq));
1364
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001366 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 else {
1368 err = -EINVAL;
1369 kfree_skb(skb);
1370 }
1371 return err;
1372}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001373EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
David S. Miller8f40b162011-07-17 13:34:11 -07001375int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1376{
1377 return dev_queue_xmit(skb);
1378}
1379EXPORT_SYMBOL(neigh_direct_output);
1380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381static void neigh_proxy_process(unsigned long arg)
1382{
1383 struct neigh_table *tbl = (struct neigh_table *)arg;
1384 long sched_next = 0;
1385 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001386 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
1388 spin_lock(&tbl->proxy_queue.lock);
1389
David S. Millerf72051b2008-09-23 01:11:18 -07001390 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1391 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001394 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001395
David S. Millerf72051b2008-09-23 01:11:18 -07001396 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001397 if (tbl->proxy_redo && netif_running(dev)) {
1398 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001399 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001400 rcu_read_unlock();
1401 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001402 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
1405 dev_put(dev);
1406 } else if (!sched_next || tdif < sched_next)
1407 sched_next = tdif;
1408 }
1409 del_timer(&tbl->proxy_timer);
1410 if (sched_next)
1411 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1412 spin_unlock(&tbl->proxy_queue.lock);
1413}
1414
1415void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1416 struct sk_buff *skb)
1417{
1418 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001419
1420 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001421 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001423 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 kfree_skb(skb);
1425 return;
1426 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001427
1428 NEIGH_CB(skb)->sched_next = sched_next;
1429 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431 spin_lock(&tbl->proxy_queue.lock);
1432 if (del_timer(&tbl->proxy_timer)) {
1433 if (time_before(tbl->proxy_timer.expires, sched_next))
1434 sched_next = tbl->proxy_timer.expires;
1435 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001436 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 dev_hold(skb->dev);
1438 __skb_queue_tail(&tbl->proxy_queue, skb);
1439 mod_timer(&tbl->proxy_timer, sched_next);
1440 spin_unlock(&tbl->proxy_queue.lock);
1441}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001442EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001444static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001445 struct net *net, int ifindex)
1446{
1447 struct neigh_parms *p;
1448
1449 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001450 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001451 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001452 return p;
1453 }
1454
1455 return NULL;
1456}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1459 struct neigh_table *tbl)
1460{
Gao fengcf89d6b2013-06-20 10:01:32 +08001461 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001462 struct net *net = dev_net(dev);
1463 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
Gao fengcf89d6b2013-06-20 10:01:32 +08001465 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467 p->tbl = tbl;
1468 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001470 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001471 dev_hold(dev);
1472 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001473 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001475
1476 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1477 release_net(net);
1478 dev_put(dev);
1479 kfree(p);
1480 return NULL;
1481 }
1482
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 write_lock_bh(&tbl->lock);
1484 p->next = tbl->parms.next;
1485 tbl->parms.next = p;
1486 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001487
1488 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 }
1490 return p;
1491}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001492EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493
1494static void neigh_rcu_free_parms(struct rcu_head *head)
1495{
1496 struct neigh_parms *parms =
1497 container_of(head, struct neigh_parms, rcu_head);
1498
1499 neigh_parms_put(parms);
1500}
1501
1502void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1503{
1504 struct neigh_parms **p;
1505
1506 if (!parms || parms == &tbl->parms)
1507 return;
1508 write_lock_bh(&tbl->lock);
1509 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1510 if (*p == parms) {
1511 *p = parms->next;
1512 parms->dead = 1;
1513 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001514 if (parms->dev)
1515 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1517 return;
1518 }
1519 }
1520 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001521 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001523EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Denis V. Lunev06f05112008-01-24 00:30:58 -08001525static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001527 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 kfree(parms);
1529}
1530
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001531static struct lock_class_key neigh_table_proxy_queue_class;
1532
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001533static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534{
1535 unsigned long now = jiffies;
1536 unsigned long phsize;
1537
Eric Dumazete42ea982008-11-12 00:54:54 -08001538 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 tbl->parms.reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001541 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 tbl->stats = alloc_percpu(struct neigh_statistics);
1544 if (!tbl->stats)
1545 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001546
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001548 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1549 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551#endif
1552
David S. Millercd089332011-07-11 01:28:12 -07001553 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001556 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001558 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 panic("cannot allocate neighbour cache hashes");
1560
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001561 if (!tbl->entry_size)
1562 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1563 tbl->key_len, NEIGH_PRIV_ALIGN);
1564 else
1565 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1566
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001568 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301569 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1570 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001571 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001572 skb_queue_head_init_class(&tbl->proxy_queue,
1573 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001574
1575 tbl->last_flush = now;
1576 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001577}
1578
1579void neigh_table_init(struct neigh_table *tbl)
1580{
1581 struct neigh_table *tmp;
1582
1583 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001585 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1586 if (tmp->family == tbl->family)
1587 break;
1588 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 tbl->next = neigh_tables;
1590 neigh_tables = tbl;
1591 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001592
1593 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001594 pr_err("Registering multiple tables for family %d\n",
1595 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001596 dump_stack();
1597 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001599EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
1601int neigh_table_clear(struct neigh_table *tbl)
1602{
1603 struct neigh_table **tp;
1604
1605 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001606 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 del_timer_sync(&tbl->proxy_timer);
1608 pneigh_queue_purge(&tbl->proxy_queue);
1609 neigh_ifdown(tbl, NULL);
1610 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001611 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 write_lock(&neigh_tbl_lock);
1613 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1614 if (*tp == tbl) {
1615 *tp = tbl->next;
1616 break;
1617 }
1618 }
1619 write_unlock(&neigh_tbl_lock);
1620
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001621 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1622 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001623 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625 kfree(tbl->phash_buckets);
1626 tbl->phash_buckets = NULL;
1627
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001628 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1629
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001630 free_percpu(tbl->stats);
1631 tbl->stats = NULL;
1632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 return 0;
1634}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001635EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636
Thomas Graf661d2962013-03-21 07:45:29 +00001637static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001639 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001640 struct ndmsg *ndm;
1641 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 struct neigh_table *tbl;
1643 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001644 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
Eric Dumazet110b2492010-10-04 04:27:36 +00001646 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001647 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648 goto out;
1649
Thomas Grafa14a49d2006-08-07 17:53:08 -07001650 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1651 if (dst_attr == NULL)
1652 goto out;
1653
1654 ndm = nlmsg_data(nlh);
1655 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001656 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001657 if (dev == NULL) {
1658 err = -ENODEV;
1659 goto out;
1660 }
1661 }
1662
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 read_lock(&neigh_tbl_lock);
1664 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001665 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666
1667 if (tbl->family != ndm->ndm_family)
1668 continue;
1669 read_unlock(&neigh_tbl_lock);
1670
Thomas Grafa14a49d2006-08-07 17:53:08 -07001671 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001672 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
1674 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001675 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001676 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677 }
1678
Thomas Grafa14a49d2006-08-07 17:53:08 -07001679 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001680 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
Thomas Grafa14a49d2006-08-07 17:53:08 -07001682 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1683 if (neigh == NULL) {
1684 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001685 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001687
1688 err = neigh_update(neigh, NULL, NUD_FAILED,
1689 NEIGH_UPDATE_F_OVERRIDE |
1690 NEIGH_UPDATE_F_ADMIN);
1691 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001692 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 }
1694 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001695 err = -EAFNOSUPPORT;
1696
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697out:
1698 return err;
1699}
1700
Thomas Graf661d2962013-03-21 07:45:29 +00001701static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001703 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001704 struct ndmsg *ndm;
1705 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 struct neigh_table *tbl;
1707 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001708 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709
Eric Dumazet110b2492010-10-04 04:27:36 +00001710 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001711 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1712 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 goto out;
1714
Thomas Graf5208deb2006-08-07 17:55:40 -07001715 err = -EINVAL;
1716 if (tb[NDA_DST] == NULL)
1717 goto out;
1718
1719 ndm = nlmsg_data(nlh);
1720 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001721 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001722 if (dev == NULL) {
1723 err = -ENODEV;
1724 goto out;
1725 }
1726
1727 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001728 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001729 }
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 read_lock(&neigh_tbl_lock);
1732 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001733 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1734 struct neighbour *neigh;
1735 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
1737 if (tbl->family != ndm->ndm_family)
1738 continue;
1739 read_unlock(&neigh_tbl_lock);
1740
Thomas Graf5208deb2006-08-07 17:55:40 -07001741 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001742 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001743 dst = nla_data(tb[NDA_DST]);
1744 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745
1746 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001747 struct pneigh_entry *pn;
1748
1749 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001750 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001751 if (pn) {
1752 pn->flags = ndm->ndm_flags;
1753 err = 0;
1754 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001755 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 }
1757
Thomas Graf5208deb2006-08-07 17:55:40 -07001758 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001759 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001760
1761 neigh = neigh_lookup(tbl, dst, dev);
1762 if (neigh == NULL) {
1763 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1764 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001765 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001766 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001767
Thomas Graf5208deb2006-08-07 17:55:40 -07001768 neigh = __neigh_lookup_errno(tbl, dst, dev);
1769 if (IS_ERR(neigh)) {
1770 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001771 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001772 }
1773 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1775 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001776 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001777 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001778 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001779
1780 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1781 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782 }
1783
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001784 if (ndm->ndm_flags & NTF_USE) {
1785 neigh_event_send(neigh, NULL);
1786 err = 0;
1787 } else
1788 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001789 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001790 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 }
1792
1793 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001794 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795out:
1796 return err;
1797}
1798
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001799static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1800{
Thomas Grafca860fb2006-08-07 18:00:18 -07001801 struct nlattr *nest;
1802
1803 nest = nla_nest_start(skb, NDTA_PARMS);
1804 if (nest == NULL)
1805 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001806
David S. Miller9a6308d2012-04-01 20:06:28 -04001807 if ((parms->dev &&
1808 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1809 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001810 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1811 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001812 /* approximative value for deprecated QUEUE_LEN (in packets) */
1813 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001814 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1815 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1816 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1817 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1818 NEIGH_VAR(parms, UCAST_PROBES)) ||
1819 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1820 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001821 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1822 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001823 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1824 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1825 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001826 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001827 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1828 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1829 NEIGH_VAR(parms, RETRANS_TIME)) ||
1830 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1831 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1832 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1833 NEIGH_VAR(parms, PROXY_DELAY)) ||
1834 nla_put_msecs(skb, NDTPA_LOCKTIME,
1835 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001836 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001837 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001838
Thomas Grafca860fb2006-08-07 18:00:18 -07001839nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001840 nla_nest_cancel(skb, nest);
1841 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001842}
1843
Thomas Grafca860fb2006-08-07 18:00:18 -07001844static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1845 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001846{
1847 struct nlmsghdr *nlh;
1848 struct ndtmsg *ndtmsg;
1849
Thomas Grafca860fb2006-08-07 18:00:18 -07001850 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1851 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001852 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853
Thomas Grafca860fb2006-08-07 18:00:18 -07001854 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855
1856 read_lock_bh(&tbl->lock);
1857 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001858 ndtmsg->ndtm_pad1 = 0;
1859 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001860
David S. Miller9a6308d2012-04-01 20:06:28 -04001861 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1862 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1863 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1864 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1865 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1866 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001867 {
1868 unsigned long now = jiffies;
1869 unsigned int flush_delta = now - tbl->last_flush;
1870 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001871 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001872 struct ndt_config ndc = {
1873 .ndtc_key_len = tbl->key_len,
1874 .ndtc_entry_size = tbl->entry_size,
1875 .ndtc_entries = atomic_read(&tbl->entries),
1876 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1877 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1879 };
1880
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001881 rcu_read_lock_bh();
1882 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001883 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001884 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001885 rcu_read_unlock_bh();
1886
David S. Miller9a6308d2012-04-01 20:06:28 -04001887 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1888 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001889 }
1890
1891 {
1892 int cpu;
1893 struct ndt_stats ndst;
1894
1895 memset(&ndst, 0, sizeof(ndst));
1896
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001897 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001898 struct neigh_statistics *st;
1899
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001900 st = per_cpu_ptr(tbl->stats, cpu);
1901 ndst.ndts_allocs += st->allocs;
1902 ndst.ndts_destroys += st->destroys;
1903 ndst.ndts_hash_grows += st->hash_grows;
1904 ndst.ndts_res_failed += st->res_failed;
1905 ndst.ndts_lookups += st->lookups;
1906 ndst.ndts_hits += st->hits;
1907 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1908 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1909 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1910 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1911 }
1912
David S. Miller9a6308d2012-04-01 20:06:28 -04001913 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1914 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001915 }
1916
1917 BUG_ON(tbl->parms.dev);
1918 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001919 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001920
1921 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001922 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001923
Thomas Grafca860fb2006-08-07 18:00:18 -07001924nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001925 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001926 nlmsg_cancel(skb, nlh);
1927 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001928}
1929
Thomas Grafca860fb2006-08-07 18:00:18 -07001930static int neightbl_fill_param_info(struct sk_buff *skb,
1931 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001932 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001933 u32 pid, u32 seq, int type,
1934 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001935{
1936 struct ndtmsg *ndtmsg;
1937 struct nlmsghdr *nlh;
1938
Thomas Grafca860fb2006-08-07 18:00:18 -07001939 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1940 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001941 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001942
Thomas Grafca860fb2006-08-07 18:00:18 -07001943 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944
1945 read_lock_bh(&tbl->lock);
1946 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001947 ndtmsg->ndtm_pad1 = 0;
1948 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949
Thomas Grafca860fb2006-08-07 18:00:18 -07001950 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1951 neightbl_fill_parms(skb, parms) < 0)
1952 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001953
1954 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001955 return nlmsg_end(skb, nlh);
1956errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001957 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001958 nlmsg_cancel(skb, nlh);
1959 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001960}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001961
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001962static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001963 [NDTA_NAME] = { .type = NLA_STRING },
1964 [NDTA_THRESH1] = { .type = NLA_U32 },
1965 [NDTA_THRESH2] = { .type = NLA_U32 },
1966 [NDTA_THRESH3] = { .type = NLA_U32 },
1967 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1968 [NDTA_PARMS] = { .type = NLA_NESTED },
1969};
1970
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001971static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001972 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1973 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1974 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1975 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1976 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1977 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1978 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1979 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1980 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1981 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1982 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1983 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1984 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1985};
1986
Thomas Graf661d2962013-03-21 07:45:29 +00001987static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001989 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001990 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001991 struct ndtmsg *ndtmsg;
1992 struct nlattr *tb[NDTA_MAX+1];
1993 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001994
Thomas Graf6b3f8672006-08-07 17:58:53 -07001995 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1996 nl_neightbl_policy);
1997 if (err < 0)
1998 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001999
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 if (tb[NDTA_NAME] == NULL) {
2001 err = -EINVAL;
2002 goto errout;
2003 }
2004
2005 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002006 read_lock(&neigh_tbl_lock);
2007 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
2008 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2009 continue;
2010
Thomas Graf6b3f8672006-08-07 17:58:53 -07002011 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012 break;
2013 }
2014
2015 if (tbl == NULL) {
2016 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002017 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002018 }
2019
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002020 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002021 * We acquire tbl->lock to be nice to the periodic timers and
2022 * make sure they always see a consistent set of values.
2023 */
2024 write_lock_bh(&tbl->lock);
2025
Thomas Graf6b3f8672006-08-07 17:58:53 -07002026 if (tb[NDTA_PARMS]) {
2027 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002028 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002029 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002030
Thomas Graf6b3f8672006-08-07 17:58:53 -07002031 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2032 nl_ntbl_parm_policy);
2033 if (err < 0)
2034 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002035
Thomas Graf6b3f8672006-08-07 17:58:53 -07002036 if (tbp[NDTPA_IFINDEX])
2037 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002038
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002039 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002040 if (p == NULL) {
2041 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002042 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002043 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002044
Thomas Graf6b3f8672006-08-07 17:58:53 -07002045 for (i = 1; i <= NDTPA_MAX; i++) {
2046 if (tbp[i] == NULL)
2047 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002048
Thomas Graf6b3f8672006-08-07 17:58:53 -07002049 switch (i) {
2050 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002051 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2052 nla_get_u32(tbp[i]) *
2053 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002054 break;
2055 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002056 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2057 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002058 break;
2059 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002060 NEIGH_VAR_SET(p, PROXY_QLEN,
2061 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002062 break;
2063 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002064 NEIGH_VAR_SET(p, APP_PROBES,
2065 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002066 break;
2067 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002068 NEIGH_VAR_SET(p, UCAST_PROBES,
2069 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002070 break;
2071 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002072 NEIGH_VAR_SET(p, MCAST_PROBES,
2073 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002074 break;
2075 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002076 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2077 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002078 break;
2079 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002080 NEIGH_VAR_SET(p, GC_STALETIME,
2081 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002082 break;
2083 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002084 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2085 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002086 break;
2087 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002088 NEIGH_VAR_SET(p, RETRANS_TIME,
2089 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002090 break;
2091 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002092 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2093 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002094 break;
2095 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002096 NEIGH_VAR_SET(p, PROXY_DELAY,
2097 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002098 break;
2099 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002100 NEIGH_VAR_SET(p, LOCKTIME,
2101 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002102 break;
2103 }
2104 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002105 }
2106
Gao fengdc25c672013-06-20 10:01:34 +08002107 err = -ENOENT;
2108 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2109 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2110 !net_eq(net, &init_net))
2111 goto errout_tbl_lock;
2112
Thomas Graf6b3f8672006-08-07 17:58:53 -07002113 if (tb[NDTA_THRESH1])
2114 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2115
2116 if (tb[NDTA_THRESH2])
2117 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2118
2119 if (tb[NDTA_THRESH3])
2120 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2121
2122 if (tb[NDTA_GC_INTERVAL])
2123 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2124
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002125 err = 0;
2126
Thomas Graf6b3f8672006-08-07 17:58:53 -07002127errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002128 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002129errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002130 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002131errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002132 return err;
2133}
2134
Thomas Grafc8822a42007-03-22 11:50:06 -07002135static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002136{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002137 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002138 int family, tidx, nidx = 0;
2139 int tbl_skip = cb->args[0];
2140 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002141 struct neigh_table *tbl;
2142
Thomas Grafca860fb2006-08-07 18:00:18 -07002143 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144
2145 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002146 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002147 struct neigh_parms *p;
2148
Thomas Grafca860fb2006-08-07 18:00:18 -07002149 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002150 continue;
2151
Eric W. Biederman15e47302012-09-07 20:12:54 +00002152 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002153 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2154 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002155 break;
2156
Eric W. Biederman426b5302008-01-24 00:13:18 -08002157 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002158 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002159 continue;
2160
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002161 if (nidx < neigh_skip)
2162 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002163
Thomas Grafca860fb2006-08-07 18:00:18 -07002164 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002165 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002166 cb->nlh->nlmsg_seq,
2167 RTM_NEWNEIGHTBL,
2168 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002169 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002170 next:
2171 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002172 }
2173
Thomas Grafca860fb2006-08-07 18:00:18 -07002174 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002175 }
2176out:
2177 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002178 cb->args[0] = tidx;
2179 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180
2181 return skb->len;
2182}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002183
Thomas Graf8b8aec52006-08-07 17:56:37 -07002184static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2185 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186{
2187 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002189 struct nlmsghdr *nlh;
2190 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191
Thomas Graf8b8aec52006-08-07 17:56:37 -07002192 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2193 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002194 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002195
2196 ndm = nlmsg_data(nlh);
2197 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002198 ndm->ndm_pad1 = 0;
2199 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002200 ndm->ndm_flags = neigh->flags;
2201 ndm->ndm_type = neigh->type;
2202 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203
David S. Miller9a6308d2012-04-01 20:06:28 -04002204 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2205 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002206
2207 read_lock_bh(&neigh->lock);
2208 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002209 if (neigh->nud_state & NUD_VALID) {
2210 char haddr[MAX_ADDR_LEN];
2211
2212 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2213 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2214 read_unlock_bh(&neigh->lock);
2215 goto nla_put_failure;
2216 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002217 }
2218
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002219 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2220 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2221 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002222 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2223 read_unlock_bh(&neigh->lock);
2224
David S. Miller9a6308d2012-04-01 20:06:28 -04002225 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2226 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2227 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002228
2229 return nlmsg_end(skb, nlh);
2230
2231nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002232 nlmsg_cancel(skb, nlh);
2233 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234}
2235
Tony Zelenoff84920c12012-01-26 22:28:58 +00002236static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2237 u32 pid, u32 seq, int type, unsigned int flags,
2238 struct neigh_table *tbl)
2239{
2240 struct nlmsghdr *nlh;
2241 struct ndmsg *ndm;
2242
2243 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2244 if (nlh == NULL)
2245 return -EMSGSIZE;
2246
2247 ndm = nlmsg_data(nlh);
2248 ndm->ndm_family = tbl->family;
2249 ndm->ndm_pad1 = 0;
2250 ndm->ndm_pad2 = 0;
2251 ndm->ndm_flags = pn->flags | NTF_PROXY;
2252 ndm->ndm_type = NDA_DST;
2253 ndm->ndm_ifindex = pn->dev->ifindex;
2254 ndm->ndm_state = NUD_NONE;
2255
David S. Miller9a6308d2012-04-01 20:06:28 -04002256 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2257 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002258
2259 return nlmsg_end(skb, nlh);
2260
2261nla_put_failure:
2262 nlmsg_cancel(skb, nlh);
2263 return -EMSGSIZE;
2264}
2265
Thomas Grafd961db32007-08-08 23:12:56 -07002266static void neigh_update_notify(struct neighbour *neigh)
2267{
2268 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2269 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2270}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271
2272static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2273 struct netlink_callback *cb)
2274{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002275 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002276 struct neighbour *n;
2277 int rc, h, s_h = cb->args[1];
2278 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002279 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002281 rcu_read_lock_bh();
2282 nht = rcu_dereference_bh(tbl->nht);
2283
Eric Dumazet4bd66832012-06-07 04:58:35 +00002284 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 if (h > s_h)
2286 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002287 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2288 n != NULL;
2289 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002290 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002291 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002292 if (idx < s_idx)
2293 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002294 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002296 RTM_NEWNEIGH,
2297 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298 rc = -1;
2299 goto out;
2300 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002301next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002302 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 }
2305 rc = skb->len;
2306out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002307 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 cb->args[1] = h;
2309 cb->args[2] = idx;
2310 return rc;
2311}
2312
Tony Zelenoff84920c12012-01-26 22:28:58 +00002313static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2314 struct netlink_callback *cb)
2315{
2316 struct pneigh_entry *n;
2317 struct net *net = sock_net(skb->sk);
2318 int rc, h, s_h = cb->args[3];
2319 int idx, s_idx = idx = cb->args[4];
2320
2321 read_lock_bh(&tbl->lock);
2322
Eric Dumazet4bd66832012-06-07 04:58:35 +00002323 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002324 if (h > s_h)
2325 s_idx = 0;
2326 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2327 if (dev_net(n->dev) != net)
2328 continue;
2329 if (idx < s_idx)
2330 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002331 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002332 cb->nlh->nlmsg_seq,
2333 RTM_NEWNEIGH,
2334 NLM_F_MULTI, tbl) <= 0) {
2335 read_unlock_bh(&tbl->lock);
2336 rc = -1;
2337 goto out;
2338 }
2339 next:
2340 idx++;
2341 }
2342 }
2343
2344 read_unlock_bh(&tbl->lock);
2345 rc = skb->len;
2346out:
2347 cb->args[3] = h;
2348 cb->args[4] = idx;
2349 return rc;
2350
2351}
2352
Thomas Grafc8822a42007-03-22 11:50:06 -07002353static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354{
2355 struct neigh_table *tbl;
2356 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002357 int proxy = 0;
Eric Dumazet4bd66832012-06-07 04:58:35 +00002358 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
2360 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002361 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002362
2363 /* check for full ndmsg structure presence, family member is
2364 * the same for both structures
2365 */
2366 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2367 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2368 proxy = 1;
2369
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 s_t = cb->args[0];
2371
Eric Dumazet4bd66832012-06-07 04:58:35 +00002372 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002373 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 if (t < s_t || (family && tbl->family != family))
2375 continue;
2376 if (t > s_t)
2377 memset(&cb->args[1], 0, sizeof(cb->args) -
2378 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002379 if (proxy)
2380 err = pneigh_dump_table(tbl, skb, cb);
2381 else
2382 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd66832012-06-07 04:58:35 +00002383 if (err < 0)
2384 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 }
2386 read_unlock(&neigh_tbl_lock);
2387
2388 cb->args[0] = t;
2389 return skb->len;
2390}
2391
2392void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2393{
2394 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002395 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002397 rcu_read_lock_bh();
2398 nht = rcu_dereference_bh(tbl->nht);
2399
Eric Dumazet767e97e2010-10-06 17:49:21 -07002400 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002401 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 struct neighbour *n;
2403
Eric Dumazet767e97e2010-10-06 17:49:21 -07002404 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2405 n != NULL;
2406 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 cb(n, cookie);
2408 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002409 read_unlock(&tbl->lock);
2410 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002411}
2412EXPORT_SYMBOL(neigh_for_each);
2413
2414/* The tbl->lock must be held as a writer and BH disabled. */
2415void __neigh_for_each_release(struct neigh_table *tbl,
2416 int (*cb)(struct neighbour *))
2417{
2418 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002419 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002421 nht = rcu_dereference_protected(tbl->nht,
2422 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002423 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002424 struct neighbour *n;
2425 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002427 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002428 while ((n = rcu_dereference_protected(*np,
2429 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 int release;
2431
2432 write_lock(&n->lock);
2433 release = cb(n);
2434 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002435 rcu_assign_pointer(*np,
2436 rcu_dereference_protected(n->next,
2437 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438 n->dead = 1;
2439 } else
2440 np = &n->next;
2441 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002442 if (release)
2443 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 }
2445 }
2446}
2447EXPORT_SYMBOL(__neigh_for_each_release);
2448
2449#ifdef CONFIG_PROC_FS
2450
2451static struct neighbour *neigh_get_first(struct seq_file *seq)
2452{
2453 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002454 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002455 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 struct neighbour *n = NULL;
2457 int bucket = state->bucket;
2458
2459 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002460 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002461 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462
2463 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002464 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002465 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 if (state->neigh_sub_iter) {
2467 loff_t fakep = 0;
2468 void *v;
2469
2470 v = state->neigh_sub_iter(state, n, &fakep);
2471 if (!v)
2472 goto next;
2473 }
2474 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2475 break;
2476 if (n->nud_state & ~NUD_NOARP)
2477 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002478next:
2479 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 }
2481
2482 if (n)
2483 break;
2484 }
2485 state->bucket = bucket;
2486
2487 return n;
2488}
2489
2490static struct neighbour *neigh_get_next(struct seq_file *seq,
2491 struct neighbour *n,
2492 loff_t *pos)
2493{
2494 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002495 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002496 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
2498 if (state->neigh_sub_iter) {
2499 void *v = state->neigh_sub_iter(state, n, pos);
2500 if (v)
2501 return n;
2502 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002503 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504
2505 while (1) {
2506 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002507 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002508 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 if (state->neigh_sub_iter) {
2510 void *v = state->neigh_sub_iter(state, n, pos);
2511 if (v)
2512 return n;
2513 goto next;
2514 }
2515 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2516 break;
2517
2518 if (n->nud_state & ~NUD_NOARP)
2519 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002520next:
2521 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 }
2523
2524 if (n)
2525 break;
2526
David S. Millercd089332011-07-11 01:28:12 -07002527 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528 break;
2529
Eric Dumazet767e97e2010-10-06 17:49:21 -07002530 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 }
2532
2533 if (n && pos)
2534 --(*pos);
2535 return n;
2536}
2537
2538static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2539{
2540 struct neighbour *n = neigh_get_first(seq);
2541
2542 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002543 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 while (*pos) {
2545 n = neigh_get_next(seq, n, pos);
2546 if (!n)
2547 break;
2548 }
2549 }
2550 return *pos ? NULL : n;
2551}
2552
2553static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2554{
2555 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002556 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 struct neigh_table *tbl = state->tbl;
2558 struct pneigh_entry *pn = NULL;
2559 int bucket = state->bucket;
2560
2561 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2562 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2563 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002564 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002565 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (pn)
2567 break;
2568 }
2569 state->bucket = bucket;
2570
2571 return pn;
2572}
2573
2574static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2575 struct pneigh_entry *pn,
2576 loff_t *pos)
2577{
2578 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002579 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 struct neigh_table *tbl = state->tbl;
2581
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002582 do {
2583 pn = pn->next;
2584 } while (pn && !net_eq(pneigh_net(pn), net));
2585
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586 while (!pn) {
2587 if (++state->bucket > PNEIGH_HASHMASK)
2588 break;
2589 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002590 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002591 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 if (pn)
2593 break;
2594 }
2595
2596 if (pn && pos)
2597 --(*pos);
2598
2599 return pn;
2600}
2601
2602static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2603{
2604 struct pneigh_entry *pn = pneigh_get_first(seq);
2605
2606 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002607 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608 while (*pos) {
2609 pn = pneigh_get_next(seq, pn, pos);
2610 if (!pn)
2611 break;
2612 }
2613 }
2614 return *pos ? NULL : pn;
2615}
2616
2617static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2618{
2619 struct neigh_seq_state *state = seq->private;
2620 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002621 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Chris Larson745e2032008-08-03 01:10:55 -07002623 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002625 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626
2627 return rc;
2628}
2629
2630void *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 +00002631 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632{
2633 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634
2635 state->tbl = tbl;
2636 state->bucket = 0;
2637 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2638
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002639 rcu_read_lock_bh();
2640 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002641
Chris Larson745e2032008-08-03 01:10:55 -07002642 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002643}
2644EXPORT_SYMBOL(neigh_seq_start);
2645
2646void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2647{
2648 struct neigh_seq_state *state;
2649 void *rc;
2650
2651 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002652 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 goto out;
2654 }
2655
2656 state = seq->private;
2657 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2658 rc = neigh_get_next(seq, v, NULL);
2659 if (rc)
2660 goto out;
2661 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2662 rc = pneigh_get_first(seq);
2663 } else {
2664 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2665 rc = pneigh_get_next(seq, v, NULL);
2666 }
2667out:
2668 ++(*pos);
2669 return rc;
2670}
2671EXPORT_SYMBOL(neigh_seq_next);
2672
2673void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002674 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002676 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677}
2678EXPORT_SYMBOL(neigh_seq_stop);
2679
2680/* statistics via seq_file */
2681
2682static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2683{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002684 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 int cpu;
2686
2687 if (*pos == 0)
2688 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002689
Rusty Russell0f23174a2008-12-29 12:23:42 +00002690 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 if (!cpu_possible(cpu))
2692 continue;
2693 *pos = cpu+1;
2694 return per_cpu_ptr(tbl->stats, cpu);
2695 }
2696 return NULL;
2697}
2698
2699static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2700{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002701 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 int cpu;
2703
Rusty Russell0f23174a2008-12-29 12:23:42 +00002704 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002705 if (!cpu_possible(cpu))
2706 continue;
2707 *pos = cpu+1;
2708 return per_cpu_ptr(tbl->stats, cpu);
2709 }
2710 return NULL;
2711}
2712
2713static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2714{
2715
2716}
2717
2718static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2719{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002720 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 struct neigh_statistics *st = v;
2722
2723 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002724 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 -07002725 return 0;
2726 }
2727
2728 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002729 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 atomic_read(&tbl->entries),
2731
2732 st->allocs,
2733 st->destroys,
2734 st->hash_grows,
2735
2736 st->lookups,
2737 st->hits,
2738
2739 st->res_failed,
2740
2741 st->rcv_probes_mcast,
2742 st->rcv_probes_ucast,
2743
2744 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002745 st->forced_gc_runs,
2746 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 );
2748
2749 return 0;
2750}
2751
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002752static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002753 .start = neigh_stat_seq_start,
2754 .next = neigh_stat_seq_next,
2755 .stop = neigh_stat_seq_stop,
2756 .show = neigh_stat_seq_show,
2757};
2758
2759static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2760{
2761 int ret = seq_open(file, &neigh_stat_seq_ops);
2762
2763 if (!ret) {
2764 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002765 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002766 }
2767 return ret;
2768};
2769
Arjan van de Ven9a321442007-02-12 00:55:35 -08002770static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 .owner = THIS_MODULE,
2772 .open = neigh_stat_seq_open,
2773 .read = seq_read,
2774 .llseek = seq_lseek,
2775 .release = seq_release,
2776};
2777
2778#endif /* CONFIG_PROC_FS */
2779
Thomas Graf339bf982006-11-10 14:10:15 -08002780static inline size_t neigh_nlmsg_size(void)
2781{
2782 return NLMSG_ALIGN(sizeof(struct ndmsg))
2783 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2784 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2785 + nla_total_size(sizeof(struct nda_cacheinfo))
2786 + nla_total_size(4); /* NDA_PROBES */
2787}
2788
Thomas Grafb8673312006-08-15 00:33:14 -07002789static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002791 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002792 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002793 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794
Thomas Graf339bf982006-11-10 14:10:15 -08002795 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002796 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002797 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798
Thomas Grafb8673312006-08-15 00:33:14 -07002799 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002800 if (err < 0) {
2801 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2802 WARN_ON(err == -EMSGSIZE);
2803 kfree_skb(skb);
2804 goto errout;
2805 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002806 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2807 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002808errout:
2809 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002810 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002811}
2812
2813void neigh_app_ns(struct neighbour *n)
2814{
2815 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002817EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002818
2819#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002820static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002821static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002822static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823
Joe Perchesfe2c6332013-06-11 23:04:25 -07002824static int proc_unres_qlen(struct ctl_table *ctl, int write,
2825 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002826{
2827 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002828 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002829
Shan Weice46cc62012-12-04 18:49:15 +00002830 tmp.extra1 = &zero;
2831 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002832 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002833
2834 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2835 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2836
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002837 if (write && !ret)
2838 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2839 return ret;
2840}
2841
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002842static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2843 int family)
2844{
Jiri Pirkobba24892013-12-07 19:26:57 +01002845 switch (family) {
2846 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002847 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002848 case AF_INET6:
2849 return __in6_dev_nd_parms_get_rcu(dev);
2850 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002851 return NULL;
2852}
2853
2854static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2855 int index)
2856{
2857 struct net_device *dev;
2858 int family = neigh_parms_family(p);
2859
2860 rcu_read_lock();
2861 for_each_netdev_rcu(net, dev) {
2862 struct neigh_parms *dst_p =
2863 neigh_get_dev_parms_rcu(dev, family);
2864
2865 if (dst_p && !test_bit(index, dst_p->data_state))
2866 dst_p->data[index] = p->data[index];
2867 }
2868 rcu_read_unlock();
2869}
2870
2871static void neigh_proc_update(struct ctl_table *ctl, int write)
2872{
2873 struct net_device *dev = ctl->extra1;
2874 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002875 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002876 int index = (int *) ctl->data - p->data;
2877
2878 if (!write)
2879 return;
2880
2881 set_bit(index, p->data_state);
2882 if (!dev) /* NULL dev means this is default value */
2883 neigh_copy_dflt_parms(net, p, index);
2884}
2885
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002886static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2887 void __user *buffer,
2888 size_t *lenp, loff_t *ppos)
2889{
2890 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002891 int ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002892
2893 tmp.extra1 = &zero;
2894 tmp.extra2 = &int_max;
2895
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002896 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2897 neigh_proc_update(ctl, write);
2898 return ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002899}
2900
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002901int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2902 void __user *buffer, size_t *lenp, loff_t *ppos)
2903{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002904 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2905
2906 neigh_proc_update(ctl, write);
2907 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002908}
2909EXPORT_SYMBOL(neigh_proc_dointvec);
2910
2911int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2912 void __user *buffer,
2913 size_t *lenp, loff_t *ppos)
2914{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002915 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2916
2917 neigh_proc_update(ctl, write);
2918 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002919}
2920EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2921
2922static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2923 void __user *buffer,
2924 size_t *lenp, loff_t *ppos)
2925{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002926 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2927
2928 neigh_proc_update(ctl, write);
2929 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002930}
2931
2932int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2933 void __user *buffer,
2934 size_t *lenp, loff_t *ppos)
2935{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002936 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2937
2938 neigh_proc_update(ctl, write);
2939 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002940}
2941EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2942
2943static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2944 void __user *buffer,
2945 size_t *lenp, loff_t *ppos)
2946{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002947 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2948
2949 neigh_proc_update(ctl, write);
2950 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002951}
2952
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002953#define NEIGH_PARMS_DATA_OFFSET(index) \
2954 (&((struct neigh_parms *) 0)->data[index])
2955
2956#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2957 [NEIGH_VAR_ ## attr] = { \
2958 .procname = name, \
2959 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2960 .maxlen = sizeof(int), \
2961 .mode = mval, \
2962 .proc_handler = proc, \
2963 }
2964
2965#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2966 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2967
2968#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002969 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002970
2971#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002972 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002973
2974#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002975 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002976
2977#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002978 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002979
2980#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002981 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002982
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983static struct neigh_sysctl_table {
2984 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002985 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002986} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 .neigh_vars = {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002988 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2989 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2990 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2991 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2992 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2993 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2994 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2995 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2996 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2997 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2998 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2999 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3000 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3001 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3002 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003003 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003004 .procname = "gc_interval",
3005 .maxlen = sizeof(int),
3006 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003007 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003009 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010 .procname = "gc_thresh1",
3011 .maxlen = sizeof(int),
3012 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003013 .extra1 = &zero,
3014 .extra2 = &int_max,
3015 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003017 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 .procname = "gc_thresh2",
3019 .maxlen = sizeof(int),
3020 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003021 .extra1 = &zero,
3022 .extra2 = &int_max,
3023 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003025 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 .procname = "gc_thresh3",
3027 .maxlen = sizeof(int),
3028 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003029 .extra1 = &zero,
3030 .extra2 = &int_max,
3031 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003033 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 },
3035};
3036
3037int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003038 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039{
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003040 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003041 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003042 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003043 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003044 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003046 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003048 goto err;
3049
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003050 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003051 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003052 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003053 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003054 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003055
3056 if (dev) {
3057 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003058 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003059 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3060 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 } else {
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003062 dev_name_source = "default";
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003063 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = (int *)(p + 1);
3064 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = (int *)(p + 1) + 1;
3065 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = (int *)(p + 1) + 2;
3066 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 }
3068
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003069 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003071 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003073 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003075 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003077 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078 }
3079
Eric W. Biederman464dc802012-11-16 03:02:59 +00003080 /* Don't export sysctls to unprivileged users */
3081 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3082 t->neigh_vars[0].procname = NULL;
3083
Jiri Pirko73af6142013-12-07 19:26:55 +01003084 switch (neigh_parms_family(p)) {
3085 case AF_INET:
3086 p_name = "ipv4";
3087 break;
3088 case AF_INET6:
3089 p_name = "ipv6";
3090 break;
3091 default:
3092 BUG();
3093 }
3094
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003095 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3096 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003097 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003098 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003099 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003100 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003101
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 p->sysctl_table = t;
3103 return 0;
3104
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003105free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003107err:
3108 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003110EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111
3112void neigh_sysctl_unregister(struct neigh_parms *p)
3113{
3114 if (p->sysctl_table) {
3115 struct neigh_sysctl_table *t = p->sysctl_table;
3116 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003117 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 kfree(t);
3119 }
3120}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003121EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122
3123#endif /* CONFIG_SYSCTL */
3124
Thomas Grafc8822a42007-03-22 11:50:06 -07003125static int __init neigh_init(void)
3126{
Greg Rosec7ac8672011-06-10 01:27:09 +00003127 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3128 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3129 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003130
Greg Rosec7ac8672011-06-10 01:27:09 +00003131 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3132 NULL);
3133 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003134
3135 return 0;
3136}
3137
3138subsys_initcall(neigh_init);
3139