blob: f8012feddf6daca79b0d155215b518dee202ebab [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010042#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define neigh_dbg(level, fmt, ...) \
47do { \
48 if (level <= NEIGH_DEBUG) \
49 pr_debug(fmt, ##__VA_ARGS__); \
50} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define PNEIGH_HASHMASK 0xF
53
54static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070055static void __neigh_notify(struct neighbour *n, int type, int flags);
56static void neigh_update_notify(struct neighbour *neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
59static struct neigh_table *neigh_tables;
Amos Waterland45fc3b12005-09-24 16:53:16 -070060#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080061static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070062#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64/*
65 Neighbour hash table buckets are protected with rwlock tbl->lock.
66
67 - All the scans/updates to hash buckets MUST be made under this lock.
68 - NOTHING clever should be made under this lock: no callbacks
69 to protocol backends, no attempts to send something to network.
70 It will result in deadlocks, if backend/driver wants to use neighbour
71 cache.
72 - If the entry requires some non-trivial actions, increase
73 its reference count and release table lock.
74
75 Neighbour entries are protected:
76 - with reference count.
77 - with rwlock neigh->lock
78
79 Reference count prevents destruction.
80
81 neigh->lock mainly serializes ll address data and its validity state.
82 However, the same lock is used to protect another entry fields:
83 - timer
84 - resolution queue
85
86 Again, nothing clever shall be made under neigh->lock,
87 the most complicated procedure, which we allow is dev->hard_header.
88 It is supposed, that dev->hard_header is simplistic and does
89 not make callbacks to neighbour tables.
90
91 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
92 list of neighbour tables. This list is used only in process context,
93 */
94
95static DEFINE_RWLOCK(neigh_tbl_lock);
96
David S. Miller8f40b162011-07-17 13:34:11 -070097static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070098{
99 kfree_skb(skb);
100 return -ENETDOWN;
101}
102
Thomas Graf4f494552007-08-08 23:12:36 -0700103static void neigh_cleanup_and_release(struct neighbour *neigh)
104{
105 if (neigh->parms->neigh_cleanup)
106 neigh->parms->neigh_cleanup(neigh);
107
Thomas Grafd961db32007-08-08 23:12:56 -0700108 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700109 neigh_release(neigh);
110}
111
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112/*
113 * It is random distribution in the interval (1/2)*base...(3/2)*base.
114 * It corresponds to default IPv6 settings and is not overridable,
115 * because it is really reasonable choice.
116 */
117
118unsigned long neigh_rand_reach_time(unsigned long base)
119{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500120 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900122EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124
125static int neigh_forced_gc(struct neigh_table *tbl)
126{
127 int shrunk = 0;
128 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000129 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
132
133 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000134 nht = rcu_dereference_protected(tbl->nht,
135 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700136 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700137 struct neighbour *n;
138 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000140 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700141 while ((n = rcu_dereference_protected(*np,
142 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 /* Neighbour record may be discarded if:
144 * - nobody refers to it.
145 * - it is not permanent
146 */
147 write_lock(&n->lock);
148 if (atomic_read(&n->refcnt) == 1 &&
149 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700150 rcu_assign_pointer(*np,
151 rcu_dereference_protected(n->next,
152 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 n->dead = 1;
154 shrunk = 1;
155 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700156 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157 continue;
158 }
159 write_unlock(&n->lock);
160 np = &n->next;
161 }
162 }
163
164 tbl->last_flush = jiffies;
165
166 write_unlock_bh(&tbl->lock);
167
168 return shrunk;
169}
170
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800171static void neigh_add_timer(struct neighbour *n, unsigned long when)
172{
173 neigh_hold(n);
174 if (unlikely(mod_timer(&n->timer, when))) {
175 printk("NEIGH: BUG, double timer add, state is %x\n",
176 n->nud_state);
177 dump_stack();
178 }
179}
180
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181static int neigh_del_timer(struct neighbour *n)
182{
183 if ((n->nud_state & NUD_IN_TIMER) &&
184 del_timer(&n->timer)) {
185 neigh_release(n);
186 return 1;
187 }
188 return 0;
189}
190
191static void pneigh_queue_purge(struct sk_buff_head *list)
192{
193 struct sk_buff *skb;
194
195 while ((skb = skb_dequeue(list)) != NULL) {
196 dev_put(skb->dev);
197 kfree_skb(skb);
198 }
199}
200
Herbert Xu49636bb2005-10-23 17:18:00 +1000201static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202{
203 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000204 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700205
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000206 nht = rcu_dereference_protected(tbl->nht,
207 lockdep_is_held(&tbl->lock));
208
David S. Millercd089332011-07-11 01:28:12 -0700209 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700210 struct neighbour *n;
211 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
Eric Dumazet767e97e2010-10-06 17:49:21 -0700213 while ((n = rcu_dereference_protected(*np,
214 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215 if (dev && n->dev != dev) {
216 np = &n->next;
217 continue;
218 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700219 rcu_assign_pointer(*np,
220 rcu_dereference_protected(n->next,
221 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222 write_lock(&n->lock);
223 neigh_del_timer(n);
224 n->dead = 1;
225
226 if (atomic_read(&n->refcnt) != 1) {
227 /* The most unpleasant situation.
228 We must destroy neighbour entry,
229 but someone still uses it.
230
231 The destroy will be delayed until
232 the last user releases us, but
233 we must kill timers etc. and move
234 it to safe state.
235 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700236 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000237 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 n->output = neigh_blackhole;
239 if (n->nud_state & NUD_VALID)
240 n->nud_state = NUD_NOARP;
241 else
242 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000243 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244 }
245 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700246 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 }
248 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000249}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250
Herbert Xu49636bb2005-10-23 17:18:00 +1000251void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
252{
253 write_lock_bh(&tbl->lock);
254 neigh_flush_dev(tbl, dev);
255 write_unlock_bh(&tbl->lock);
256}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900257EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000258
259int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
260{
261 write_lock_bh(&tbl->lock);
262 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 pneigh_ifdown(tbl, dev);
264 write_unlock_bh(&tbl->lock);
265
266 del_timer_sync(&tbl->proxy_timer);
267 pneigh_queue_purge(&tbl->proxy_queue);
268 return 0;
269}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900270EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271
David Miller596b9b62011-07-25 00:01:25 +0000272static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700273{
274 struct neighbour *n = NULL;
275 unsigned long now = jiffies;
276 int entries;
277
278 entries = atomic_inc_return(&tbl->entries) - 1;
279 if (entries >= tbl->gc_thresh3 ||
280 (entries >= tbl->gc_thresh2 &&
281 time_after(now, tbl->last_flush + 5 * HZ))) {
282 if (!neigh_forced_gc(tbl) &&
283 entries >= tbl->gc_thresh3)
284 goto out_entries;
285 }
286
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000287 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 if (!n)
289 goto out_entries;
290
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700291 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000293 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 n->updated = n->used = now;
295 n->nud_state = NUD_NONE;
296 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700297 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800299 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 NEIGH_CACHE_STAT_INC(tbl, allocs);
302 n->tbl = tbl;
303 atomic_set(&n->refcnt, 1);
304 n->dead = 1;
305out:
306 return n;
307
308out_entries:
309 atomic_dec(&tbl->entries);
310 goto out;
311}
312
David S. Miller2c2aba62011-12-28 15:06:58 -0500313static void neigh_get_hash_rnd(u32 *x)
314{
315 get_random_bytes(x, sizeof(*x));
316 *x |= 1;
317}
318
David S. Millercd089332011-07-11 01:28:12 -0700319static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
David S. Millercd089332011-07-11 01:28:12 -0700321 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000322 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000323 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500324 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000326 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
327 if (!ret)
328 return NULL;
329 if (size <= PAGE_SIZE)
330 buckets = kzalloc(size, GFP_ATOMIC);
331 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000332 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000333 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
334 get_order(size));
335 if (!buckets) {
336 kfree(ret);
337 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000339 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700340 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500341 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
342 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return ret;
344}
345
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000346static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000348 struct neigh_hash_table *nht = container_of(head,
349 struct neigh_hash_table,
350 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700351 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000352 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000355 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000357 free_pages((unsigned long)buckets, get_order(size));
358 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000361static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700362 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000364 unsigned int i, hash;
365 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
368
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000369 old_nht = rcu_dereference_protected(tbl->nht,
370 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700371 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000372 if (!new_nht)
373 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
David S. Millercd089332011-07-11 01:28:12 -0700375 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 struct neighbour *n, *next;
377
Eric Dumazet767e97e2010-10-06 17:49:21 -0700378 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
379 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000380 n != NULL;
381 n = next) {
382 hash = tbl->hash(n->primary_key, n->dev,
383 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
David S. Millercd089332011-07-11 01:28:12 -0700385 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700386 next = rcu_dereference_protected(n->next,
387 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Eric Dumazet767e97e2010-10-06 17:49:21 -0700389 rcu_assign_pointer(n->next,
390 rcu_dereference_protected(
391 new_nht->hash_buckets[hash],
392 lockdep_is_held(&tbl->lock)));
393 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000397 rcu_assign_pointer(tbl->nht, new_nht);
398 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
399 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400}
401
402struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
403 struct net_device *dev)
404{
405 struct neighbour *n;
406 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800407 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 struct neigh_hash_table *nht;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900409
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 NEIGH_CACHE_STAT_INC(tbl, lookups);
411
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000412 rcu_read_lock_bh();
413 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700414 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700415
416 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
417 n != NULL;
418 n = rcu_dereference_bh(n->next)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700420 if (!atomic_inc_not_zero(&n->refcnt))
421 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422 NEIGH_CACHE_STAT_INC(tbl, hits);
423 break;
424 }
425 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700426
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 return n;
429}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900430EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Eric W. Biederman426b5302008-01-24 00:13:18 -0800432struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
433 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434{
435 struct neighbour *n;
436 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800437 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000438 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
440 NEIGH_CACHE_STAT_INC(tbl, lookups);
441
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000442 rcu_read_lock_bh();
443 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700444 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700445
446 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
447 n != NULL;
448 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800449 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900450 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700451 if (!atomic_inc_not_zero(&n->refcnt))
452 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 NEIGH_CACHE_STAT_INC(tbl, hits);
454 break;
455 }
456 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700457
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000458 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459 return n;
460}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900461EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462
David S. Millera263b302012-07-02 02:02:15 -0700463struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
464 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
466 u32 hash_val;
467 int key_len = tbl->key_len;
468 int error;
David Miller596b9b62011-07-25 00:01:25 +0000469 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000470 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 if (!n) {
473 rc = ERR_PTR(-ENOBUFS);
474 goto out;
475 }
476
477 memcpy(n->primary_key, pkey, key_len);
478 n->dev = dev;
479 dev_hold(dev);
480
481 /* Protocol specific setup. */
482 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
483 rc = ERR_PTR(error);
484 goto out_neigh_release;
485 }
486
David Millerda6a8fa2011-07-25 00:01:38 +0000487 if (dev->netdev_ops->ndo_neigh_construct) {
488 error = dev->netdev_ops->ndo_neigh_construct(n);
489 if (error < 0) {
490 rc = ERR_PTR(error);
491 goto out_neigh_release;
492 }
493 }
494
David S. Miller447f2192011-12-19 15:04:41 -0500495 /* Device specific setup. */
496 if (n->parms->neigh_setup &&
497 (error = n->parms->neigh_setup(n)) < 0) {
498 rc = ERR_PTR(error);
499 goto out_neigh_release;
500 }
501
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100502 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503
504 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000505 nht = rcu_dereference_protected(tbl->nht,
506 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
David S. Millercd089332011-07-11 01:28:12 -0700508 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
509 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
David S. Millercd089332011-07-11 01:28:12 -0700511 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
513 if (n->parms->dead) {
514 rc = ERR_PTR(-EINVAL);
515 goto out_tbl_unlock;
516 }
517
Eric Dumazet767e97e2010-10-06 17:49:21 -0700518 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
519 lockdep_is_held(&tbl->lock));
520 n1 != NULL;
521 n1 = rcu_dereference_protected(n1->next,
522 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700524 if (want_ref)
525 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 rc = n1;
527 goto out_tbl_unlock;
528 }
529 }
530
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700532 if (want_ref)
533 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700534 rcu_assign_pointer(n->next,
535 rcu_dereference_protected(nht->hash_buckets[hash_val],
536 lockdep_is_held(&tbl->lock)));
537 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000539 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 rc = n;
541out:
542 return rc;
543out_tbl_unlock:
544 write_unlock_bh(&tbl->lock);
545out_neigh_release:
546 neigh_release(n);
547 goto out;
548}
David S. Millera263b302012-07-02 02:02:15 -0700549EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900551static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700552{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700553 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700554 hash_val ^= (hash_val >> 16);
555 hash_val ^= hash_val >> 8;
556 hash_val ^= hash_val >> 4;
557 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 return hash_val;
559}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700560
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900561static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
562 struct net *net,
563 const void *pkey,
564 int key_len,
565 struct net_device *dev)
566{
567 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700568 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900569 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700570 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900571 return n;
572 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700573 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900574 return NULL;
575}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900577struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
578 struct net *net, const void *pkey, struct net_device *dev)
579{
580 int key_len = tbl->key_len;
581 u32 hash_val = pneigh_hash(pkey, key_len);
582
583 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
584 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700585}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900586EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700587
Eric W. Biederman426b5302008-01-24 00:13:18 -0800588struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
589 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 struct net_device *dev, int creat)
591{
592 struct pneigh_entry *n;
593 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900594 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
596 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900597 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
598 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700599 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900600
601 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 goto out;
603
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700604 ASSERT_RTNL();
605
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
607 if (!n)
608 goto out;
609
Eric Dumazete42ea982008-11-12 00:54:54 -0800610 write_pnet(&n->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 memcpy(n->key, pkey, key_len);
612 n->dev = dev;
613 if (dev)
614 dev_hold(dev);
615
616 if (tbl->pconstructor && tbl->pconstructor(n)) {
617 if (dev)
618 dev_put(dev);
Denis V. Lunevda12f732008-02-20 00:26:16 -0800619 release_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 kfree(n);
621 n = NULL;
622 goto out;
623 }
624
625 write_lock_bh(&tbl->lock);
626 n->next = tbl->phash_buckets[hash_val];
627 tbl->phash_buckets[hash_val] = n;
628 write_unlock_bh(&tbl->lock);
629out:
630 return n;
631}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900632EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633
634
Eric W. Biederman426b5302008-01-24 00:13:18 -0800635int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 struct net_device *dev)
637{
638 struct pneigh_entry *n, **np;
639 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900640 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641
642 write_lock_bh(&tbl->lock);
643 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
644 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800645 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900646 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 *np = n->next;
648 write_unlock_bh(&tbl->lock);
649 if (tbl->pdestructor)
650 tbl->pdestructor(n);
651 if (n->dev)
652 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900653 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 kfree(n);
655 return 0;
656 }
657 }
658 write_unlock_bh(&tbl->lock);
659 return -ENOENT;
660}
661
662static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
663{
664 struct pneigh_entry *n, **np;
665 u32 h;
666
667 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
668 np = &tbl->phash_buckets[h];
669 while ((n = *np) != NULL) {
670 if (!dev || n->dev == dev) {
671 *np = n->next;
672 if (tbl->pdestructor)
673 tbl->pdestructor(n);
674 if (n->dev)
675 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900676 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 kfree(n);
678 continue;
679 }
680 np = &n->next;
681 }
682 }
683 return -ENOENT;
684}
685
Denis V. Lunev06f05112008-01-24 00:30:58 -0800686static void neigh_parms_destroy(struct neigh_parms *parms);
687
688static inline void neigh_parms_put(struct neigh_parms *parms)
689{
690 if (atomic_dec_and_test(&parms->refcnt))
691 neigh_parms_destroy(parms);
692}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694/*
695 * neighbour must already be out of the table;
696 *
697 */
698void neigh_destroy(struct neighbour *neigh)
699{
David Millerda6a8fa2011-07-25 00:01:38 +0000700 struct net_device *dev = neigh->dev;
701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
703
704 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000705 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 dump_stack();
707 return;
708 }
709
710 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000711 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700713 write_lock_bh(&neigh->lock);
714 __skb_queue_purge(&neigh->arp_queue);
715 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000716 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
David S. Miller447f2192011-12-19 15:04:41 -0500718 if (dev->netdev_ops->ndo_neigh_destroy)
719 dev->netdev_ops->ndo_neigh_destroy(neigh);
720
David Millerda6a8fa2011-07-25 00:01:38 +0000721 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 neigh_parms_put(neigh->parms);
723
Joe Perchesd5d427c2013-04-15 15:17:19 +0000724 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000727 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900729EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731/* Neighbour state is suspicious;
732 disable fast path.
733
734 Called with write_locked neigh.
735 */
736static void neigh_suspect(struct neighbour *neigh)
737{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000738 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741}
742
743/* Neighbour state is OK;
744 enable fast path.
745
746 Called with write_locked neigh.
747 */
748static void neigh_connect(struct neighbour *neigh)
749{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000750 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Eric Dumazete4c4e442009-07-30 03:15:07 +0000755static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000757 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700758 struct neighbour *n;
759 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000760 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000761 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
764
Eric Dumazete4c4e442009-07-30 03:15:07 +0000765 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000766 nht = rcu_dereference_protected(tbl->nht,
767 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000769 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
770 goto out;
771
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 /*
773 * periodically recompute ReachableTime from random function
774 */
775
Eric Dumazete4c4e442009-07-30 03:15:07 +0000776 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000778 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 for (p = &tbl->parms; p; p = p->next)
780 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100781 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 }
783
David S. Millercd089332011-07-11 01:28:12 -0700784 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000785 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Eric Dumazet767e97e2010-10-06 17:49:21 -0700787 while ((n = rcu_dereference_protected(*np,
788 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Eric Dumazete4c4e442009-07-30 03:15:07 +0000793 state = n->nud_state;
794 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
795 write_unlock(&n->lock);
796 goto next_elt;
797 }
798
799 if (time_before(n->used, n->confirmed))
800 n->used = n->confirmed;
801
802 if (atomic_read(&n->refcnt) == 1 &&
803 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100804 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000805 *np = n->next;
806 n->dead = 1;
807 write_unlock(&n->lock);
808 neigh_cleanup_and_release(n);
809 continue;
810 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000814 np = &n->next;
815 }
816 /*
817 * It's fine to release lock here, even if hash table
818 * grows while we are preempted.
819 */
820 write_unlock_bh(&tbl->lock);
821 cond_resched();
822 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500823 nht = rcu_dereference_protected(tbl->nht,
824 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000826out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100827 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
828 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
829 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 */
Eric Dumazete4c4e442009-07-30 03:15:07 +0000831 schedule_delayed_work(&tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100832 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000833 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834}
835
836static __inline__ int neigh_max_probes(struct neighbour *n)
837{
838 struct neigh_parms *p = n->parms;
Eric Dumazeta02cec22010-09-22 20:43:57 +0000839 return (n->nud_state & NUD_PROBE) ?
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100840 NEIGH_VAR(p, UCAST_PROBES) :
841 NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
842 NEIGH_VAR(p, MCAST_PROBES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Timo Teras5ef12d92009-06-11 04:16:28 -0700845static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000846 __releases(neigh->lock)
847 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700848{
849 struct sk_buff *skb;
850
851 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000852 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700853 neigh->updated = jiffies;
854
855 /* It is very thin place. report_unreachable is very complicated
856 routine. Particularly, it can hit the same neighbour entry!
857
858 So that, we try to be accurate and avoid dead loop. --ANK
859 */
860 while (neigh->nud_state == NUD_FAILED &&
861 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
862 write_unlock(&neigh->lock);
863 neigh->ops->error_report(neigh, skb);
864 write_lock(&neigh->lock);
865 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700866 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000867 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700868}
869
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000870static void neigh_probe(struct neighbour *neigh)
871 __releases(neigh->lock)
872{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200873 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000874 /* keep skb alive even if arp_queue overflows */
875 if (skb)
876 skb = skb_copy(skb, GFP_ATOMIC);
877 write_unlock(&neigh->lock);
878 neigh->ops->solicit(neigh, skb);
879 atomic_inc(&neigh->probes);
880 kfree_skb(skb);
881}
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883/* Called when a timer expires for a neighbour entry. */
884
885static void neigh_timer_handler(unsigned long arg)
886{
887 unsigned long now, next;
888 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000889 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 int notify = 0;
891
892 write_lock(&neigh->lock);
893
894 state = neigh->nud_state;
895 now = jiffies;
896 next = now + HZ;
897
David S. Miller045f7b32011-11-01 17:45:55 -0400898 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900
901 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900902 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000904 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 next = neigh->confirmed + neigh->parms->reachable_time;
906 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-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 Pirko1f9248e2013-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 Pirko1f9248e2013-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 Pirko1f9248e2013-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 Pirko1f9248e2013-12-07 19:26:53 +0100940 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
942
943 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
944 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 neigh->nud_state = NUD_FAILED;
946 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700947 neigh_invalidate(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 }
949
950 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 if (time_before(next, jiffies + HZ/2))
952 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000953 if (!mod_timer(&neigh->timer, next))
954 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 }
956 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000957 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800958 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800959out:
David S. Miller9ff56602008-02-17 18:39:54 -0800960 write_unlock(&neigh->lock);
961 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
Thomas Grafd961db32007-08-08 23:12:56 -0700963 if (notify)
964 neigh_update_notify(neigh);
965
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966 neigh_release(neigh);
967}
968
969int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
970{
971 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000972 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973
974 write_lock_bh(&neigh->lock);
975
976 rc = 0;
977 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
978 goto out_unlock_bh;
979
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100981 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
982 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000983 unsigned long next, now = jiffies;
984
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100985 atomic_set(&neigh->probes,
986 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000988 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100989 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
990 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000991 neigh_add_timer(neigh, next);
992 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 } else {
994 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800995 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 write_unlock_bh(&neigh->lock);
997
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000998 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999 return 1;
1000 }
1001 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001002 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001004 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001005 neigh_add_timer(neigh, jiffies +
1006 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 }
1008
1009 if (neigh->nud_state == NUD_INCOMPLETE) {
1010 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001011 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001012 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001014
David S. Millerf72051b2008-09-23 01:11:18 -07001015 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001016 if (!buff)
1017 break;
1018 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001020 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001022 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001024 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 }
1026 rc = 1;
1027 }
1028out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001029 if (immediate_probe)
1030 neigh_probe(neigh);
1031 else
1032 write_unlock(&neigh->lock);
1033 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 return rc;
1035}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001036EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
David S. Millerf6b72b62011-07-14 07:53:20 -07001038static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039{
1040 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001041 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001042 = NULL;
1043
1044 if (neigh->dev->header_ops)
1045 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001048 hh = &neigh->hh;
1049 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001050 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001052 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 }
1054 }
1055}
1056
1057
1058
1059/* Generic update routine.
1060 -- lladdr is new lladdr or NULL, if it is not supplied.
1061 -- new is new state.
1062 -- flags
1063 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1064 if it is different.
1065 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001066 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 if it is different.
1068 It also allows to retain current state
1069 if lladdr is unchanged.
1070 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1071
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001072 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 NTF_ROUTER flag.
1074 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1075 a router.
1076
1077 Caller MUST hold reference count on the entry.
1078 */
1079
1080int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1081 u32 flags)
1082{
1083 u8 old;
1084 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 struct net_device *dev;
1087 int update_isrouter = 0;
1088
1089 write_lock_bh(&neigh->lock);
1090
1091 dev = neigh->dev;
1092 old = neigh->nud_state;
1093 err = -EPERM;
1094
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001095 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 (old & (NUD_NOARP | NUD_PERMANENT)))
1097 goto out;
1098
1099 if (!(new & NUD_VALID)) {
1100 neigh_del_timer(neigh);
1101 if (old & NUD_CONNECTED)
1102 neigh_suspect(neigh);
1103 neigh->nud_state = new;
1104 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001106 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1107 (new & NUD_FAILED)) {
1108 neigh_invalidate(neigh);
1109 notify = 1;
1110 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 goto out;
1112 }
1113
1114 /* Compare new lladdr with cached one */
1115 if (!dev->addr_len) {
1116 /* First case: device needs no address. */
1117 lladdr = neigh->ha;
1118 } else if (lladdr) {
1119 /* The second case: if something is already cached
1120 and a new address is proposed:
1121 - compare new & old
1122 - if they are different, check override flag
1123 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001124 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 !memcmp(lladdr, neigh->ha, dev->addr_len))
1126 lladdr = neigh->ha;
1127 } else {
1128 /* No address is supplied; if we know something,
1129 use it, otherwise discard the request.
1130 */
1131 err = -EINVAL;
1132 if (!(old & NUD_VALID))
1133 goto out;
1134 lladdr = neigh->ha;
1135 }
1136
1137 if (new & NUD_CONNECTED)
1138 neigh->confirmed = jiffies;
1139 neigh->updated = jiffies;
1140
1141 /* If entry was valid and address is not changed,
1142 do not change entry state, if new one is STALE.
1143 */
1144 err = 0;
1145 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1146 if (old & NUD_VALID) {
1147 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1148 update_isrouter = 0;
1149 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1150 (old & NUD_CONNECTED)) {
1151 lladdr = neigh->ha;
1152 new = NUD_STALE;
1153 } else
1154 goto out;
1155 } else {
1156 if (lladdr == neigh->ha && new == NUD_STALE &&
1157 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1158 (old & NUD_CONNECTED))
1159 )
1160 new = old;
1161 }
1162 }
1163
1164 if (new != old) {
1165 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001166 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001167 neigh_add_timer(neigh, (jiffies +
1168 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001169 neigh->parms->reachable_time :
1170 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001172 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 }
1174
1175 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001176 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001178 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 neigh_update_hhs(neigh);
1180 if (!(new & NUD_CONNECTED))
1181 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001182 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 }
1185 if (new == old)
1186 goto out;
1187 if (new & NUD_CONNECTED)
1188 neigh_connect(neigh);
1189 else
1190 neigh_suspect(neigh);
1191 if (!(old & NUD_VALID)) {
1192 struct sk_buff *skb;
1193
1194 /* Again: avoid dead loop if something went wrong */
1195
1196 while (neigh->nud_state & NUD_VALID &&
1197 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001198 struct dst_entry *dst = skb_dst(skb);
1199 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001201
1202 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001203
1204 /* Why not just use 'neigh' as-is? The problem is that
1205 * things such as shaper, eql, and sch_teql can end up
1206 * using alternative, different, neigh objects to output
1207 * the packet in the output path. So what we need to do
1208 * here is re-lookup the top-level neigh in the path so
1209 * we can reinject the packet there.
1210 */
1211 n2 = NULL;
1212 if (dst) {
1213 n2 = dst_neigh_lookup_skb(dst, skb);
1214 if (n2)
1215 n1 = n2;
1216 }
David S. Miller8f40b162011-07-17 13:34:11 -07001217 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001218 if (n2)
1219 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001220 rcu_read_unlock();
1221
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 write_lock_bh(&neigh->lock);
1223 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001224 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001225 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 }
1227out:
1228 if (update_isrouter) {
1229 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1230 (neigh->flags | NTF_ROUTER) :
1231 (neigh->flags & ~NTF_ROUTER);
1232 }
1233 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001234
1235 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001236 neigh_update_notify(neigh);
1237
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 return err;
1239}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001240EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
Jiri Benc7e980562013-12-11 13:48:20 +01001242/* Update the neigh to listen temporarily for probe responses, even if it is
1243 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1244 */
1245void __neigh_set_probe_once(struct neighbour *neigh)
1246{
1247 neigh->updated = jiffies;
1248 if (!(neigh->nud_state & NUD_FAILED))
1249 return;
1250 neigh->nud_state = NUD_PROBE;
1251 atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES));
1252 neigh_add_timer(neigh,
1253 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1254}
1255EXPORT_SYMBOL(__neigh_set_probe_once);
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1258 u8 *lladdr, void *saddr,
1259 struct net_device *dev)
1260{
1261 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1262 lladdr || !dev->addr_len);
1263 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001264 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 NEIGH_UPDATE_F_OVERRIDE);
1266 return neigh;
1267}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001268EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Eric Dumazet34d101d2010-10-11 09:16:57 -07001270/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001271static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001274 __be16 prot = dst->ops->protocol;
1275 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001276
1277 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001278
David S. Millerf6b72b62011-07-14 07:53:20 -07001279 /* Only one thread can come in here and initialize the
1280 * hh_cache entry.
1281 */
David S. Millerb23b5452011-07-16 17:45:02 -07001282 if (!hh->hh_len)
1283 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001284
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001285 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286}
1287
1288/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001289 * worked, f.e. if you want to override normal output path (eql, shaper),
1290 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 */
1292
David S. Miller8f40b162011-07-17 13:34:11 -07001293int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294{
1295 struct net_device *dev = skb->dev;
1296
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001297 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001299 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1300 skb->len) < 0 &&
David S. Miller22053692013-12-31 16:23:35 -05001301 dev_rebuild_header(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 return 0;
1303
1304 return dev_queue_xmit(skb);
1305}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001306EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308/* Slow and careful. */
1309
David S. Miller8f40b162011-07-17 13:34:11 -07001310int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
Eric Dumazetadf30902009-06-02 05:19:30 +00001312 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313 int rc = 0;
1314
David S. Miller8f40b162011-07-17 13:34:11 -07001315 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 goto discard;
1317
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 if (!neigh_event_send(neigh, skb)) {
1319 int err;
1320 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001321 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001322
David S. Millerf6b72b62011-07-14 07:53:20 -07001323 if (dev->header_ops->cache && !neigh->hh.hh_len)
1324 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001325
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001326 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001327 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001328 seq = read_seqbegin(&neigh->ha_lock);
1329 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1330 neigh->ha, NULL, skb->len);
1331 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001332
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001334 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 else
1336 goto out_kfree_skb;
1337 }
1338out:
1339 return rc;
1340discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001341 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342out_kfree_skb:
1343 rc = -EINVAL;
1344 kfree_skb(skb);
1345 goto out;
1346}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001347EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348
1349/* As fast as possible without hh cache */
1350
David S. Miller8f40b162011-07-17 13:34:11 -07001351int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001354 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001355 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001357 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001358 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001359 seq = read_seqbegin(&neigh->ha_lock);
1360 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1361 neigh->ha, NULL, skb->len);
1362 } while (read_seqretry(&neigh->ha_lock, seq));
1363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001365 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 else {
1367 err = -EINVAL;
1368 kfree_skb(skb);
1369 }
1370 return err;
1371}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001372EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
David S. Miller8f40b162011-07-17 13:34:11 -07001374int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1375{
1376 return dev_queue_xmit(skb);
1377}
1378EXPORT_SYMBOL(neigh_direct_output);
1379
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380static void neigh_proxy_process(unsigned long arg)
1381{
1382 struct neigh_table *tbl = (struct neigh_table *)arg;
1383 long sched_next = 0;
1384 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001385 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 spin_lock(&tbl->proxy_queue.lock);
1388
David S. Millerf72051b2008-09-23 01:11:18 -07001389 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1390 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001393 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001394
David S. Millerf72051b2008-09-23 01:11:18 -07001395 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001396 if (tbl->proxy_redo && netif_running(dev)) {
1397 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001398 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001399 rcu_read_unlock();
1400 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001401 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001402 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
1404 dev_put(dev);
1405 } else if (!sched_next || tdif < sched_next)
1406 sched_next = tdif;
1407 }
1408 del_timer(&tbl->proxy_timer);
1409 if (sched_next)
1410 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1411 spin_unlock(&tbl->proxy_queue.lock);
1412}
1413
1414void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1415 struct sk_buff *skb)
1416{
1417 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001418
1419 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001420 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001422 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423 kfree_skb(skb);
1424 return;
1425 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001426
1427 NEIGH_CB(skb)->sched_next = sched_next;
1428 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
1430 spin_lock(&tbl->proxy_queue.lock);
1431 if (del_timer(&tbl->proxy_timer)) {
1432 if (time_before(tbl->proxy_timer.expires, sched_next))
1433 sched_next = tbl->proxy_timer.expires;
1434 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001435 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436 dev_hold(skb->dev);
1437 __skb_queue_tail(&tbl->proxy_queue, skb);
1438 mod_timer(&tbl->proxy_timer, sched_next);
1439 spin_unlock(&tbl->proxy_queue.lock);
1440}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001441EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001443static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001444 struct net *net, int ifindex)
1445{
1446 struct neigh_parms *p;
1447
1448 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001449 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001450 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001451 return p;
1452 }
1453
1454 return NULL;
1455}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
1457struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1458 struct neigh_table *tbl)
1459{
Gao fengcf89d6b2013-06-20 10:01:32 +08001460 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001461 struct net *net = dev_net(dev);
1462 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463
Gao fengcf89d6b2013-06-20 10:01:32 +08001464 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 p->tbl = tbl;
1467 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001469 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001470 dev_hold(dev);
1471 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001472 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001474
1475 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1476 release_net(net);
1477 dev_put(dev);
1478 kfree(p);
1479 return NULL;
1480 }
1481
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 write_lock_bh(&tbl->lock);
1483 p->next = tbl->parms.next;
1484 tbl->parms.next = p;
1485 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001486
1487 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 }
1489 return p;
1490}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001491EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
1493static void neigh_rcu_free_parms(struct rcu_head *head)
1494{
1495 struct neigh_parms *parms =
1496 container_of(head, struct neigh_parms, rcu_head);
1497
1498 neigh_parms_put(parms);
1499}
1500
1501void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1502{
1503 struct neigh_parms **p;
1504
1505 if (!parms || parms == &tbl->parms)
1506 return;
1507 write_lock_bh(&tbl->lock);
1508 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1509 if (*p == parms) {
1510 *p = parms->next;
1511 parms->dead = 1;
1512 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001513 if (parms->dev)
1514 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1516 return;
1517 }
1518 }
1519 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001520 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001522EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Denis V. Lunev06f05112008-01-24 00:30:58 -08001524static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001526 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 kfree(parms);
1528}
1529
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001530static struct lock_class_key neigh_table_proxy_queue_class;
1531
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001532static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
1534 unsigned long now = jiffies;
1535 unsigned long phsize;
1536
Eric Dumazete42ea982008-11-12 00:54:54 -08001537 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001540 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 tbl->stats = alloc_percpu(struct neigh_statistics);
1543 if (!tbl->stats)
1544 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001547 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1548 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550#endif
1551
David S. Millercd089332011-07-11 01:28:12 -07001552 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553
1554 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001555 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001557 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 panic("cannot allocate neighbour cache hashes");
1559
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001560 if (!tbl->entry_size)
1561 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1562 tbl->key_len, NEIGH_PRIV_ALIGN);
1563 else
1564 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1565
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001567 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
Eric Dumazete4c4e442009-07-30 03:15:07 +00001568 schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001569 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001570 skb_queue_head_init_class(&tbl->proxy_queue,
1571 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
1573 tbl->last_flush = now;
1574 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001575}
1576
1577void neigh_table_init(struct neigh_table *tbl)
1578{
1579 struct neigh_table *tmp;
1580
1581 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001583 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1584 if (tmp->family == tbl->family)
1585 break;
1586 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 tbl->next = neigh_tables;
1588 neigh_tables = tbl;
1589 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001590
1591 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001592 pr_err("Registering multiple tables for family %d\n",
1593 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001594 dump_stack();
1595 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001597EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599int neigh_table_clear(struct neigh_table *tbl)
1600{
1601 struct neigh_table **tp;
1602
1603 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001604 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 del_timer_sync(&tbl->proxy_timer);
1606 pneigh_queue_purge(&tbl->proxy_queue);
1607 neigh_ifdown(tbl, NULL);
1608 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001609 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 write_lock(&neigh_tbl_lock);
1611 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1612 if (*tp == tbl) {
1613 *tp = tbl->next;
1614 break;
1615 }
1616 }
1617 write_unlock(&neigh_tbl_lock);
1618
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001619 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1620 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001621 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
1623 kfree(tbl->phash_buckets);
1624 tbl->phash_buckets = NULL;
1625
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001626 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1627
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001628 free_percpu(tbl->stats);
1629 tbl->stats = NULL;
1630
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 return 0;
1632}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001633EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634
Thomas Graf661d2962013-03-21 07:45:29 +00001635static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001637 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001638 struct ndmsg *ndm;
1639 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 struct neigh_table *tbl;
1641 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001642 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Eric Dumazet110b2492010-10-04 04:27:36 +00001644 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001645 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 goto out;
1647
Thomas Grafa14a49d2006-08-07 17:53:08 -07001648 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1649 if (dst_attr == NULL)
1650 goto out;
1651
1652 ndm = nlmsg_data(nlh);
1653 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001654 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001655 if (dev == NULL) {
1656 err = -ENODEV;
1657 goto out;
1658 }
1659 }
1660
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661 read_lock(&neigh_tbl_lock);
1662 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001663 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
1665 if (tbl->family != ndm->ndm_family)
1666 continue;
1667 read_unlock(&neigh_tbl_lock);
1668
Thomas Grafa14a49d2006-08-07 17:53:08 -07001669 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001670 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671
1672 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001673 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001674 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675 }
1676
Thomas Grafa14a49d2006-08-07 17:53:08 -07001677 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001678 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Thomas Grafa14a49d2006-08-07 17:53:08 -07001680 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1681 if (neigh == NULL) {
1682 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001683 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001685
1686 err = neigh_update(neigh, NULL, NUD_FAILED,
1687 NEIGH_UPDATE_F_OVERRIDE |
1688 NEIGH_UPDATE_F_ADMIN);
1689 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001690 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691 }
1692 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001693 err = -EAFNOSUPPORT;
1694
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695out:
1696 return err;
1697}
1698
Thomas Graf661d2962013-03-21 07:45:29 +00001699static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001701 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001702 struct ndmsg *ndm;
1703 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704 struct neigh_table *tbl;
1705 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001706 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
Eric Dumazet110b2492010-10-04 04:27:36 +00001708 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001709 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1710 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 goto out;
1712
Thomas Graf5208deb2006-08-07 17:55:40 -07001713 err = -EINVAL;
1714 if (tb[NDA_DST] == NULL)
1715 goto out;
1716
1717 ndm = nlmsg_data(nlh);
1718 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001719 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001720 if (dev == NULL) {
1721 err = -ENODEV;
1722 goto out;
1723 }
1724
1725 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001726 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001727 }
1728
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 read_lock(&neigh_tbl_lock);
1730 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001731 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1732 struct neighbour *neigh;
1733 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
1735 if (tbl->family != ndm->ndm_family)
1736 continue;
1737 read_unlock(&neigh_tbl_lock);
1738
Thomas Graf5208deb2006-08-07 17:55:40 -07001739 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001740 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001741 dst = nla_data(tb[NDA_DST]);
1742 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
1744 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001745 struct pneigh_entry *pn;
1746
1747 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001748 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001749 if (pn) {
1750 pn->flags = ndm->ndm_flags;
1751 err = 0;
1752 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001753 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 }
1755
Thomas Graf5208deb2006-08-07 17:55:40 -07001756 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001757 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001758
1759 neigh = neigh_lookup(tbl, dst, dev);
1760 if (neigh == NULL) {
1761 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1762 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001763 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001764 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001765
Thomas Graf5208deb2006-08-07 17:55:40 -07001766 neigh = __neigh_lookup_errno(tbl, dst, dev);
1767 if (IS_ERR(neigh)) {
1768 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001769 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001770 }
1771 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1773 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001774 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001775 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001777
1778 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1779 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001780 }
1781
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001782 if (ndm->ndm_flags & NTF_USE) {
1783 neigh_event_send(neigh, NULL);
1784 err = 0;
1785 } else
1786 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001787 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001788 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001789 }
1790
1791 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001792 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793out:
1794 return err;
1795}
1796
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001797static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1798{
Thomas Grafca860fb2006-08-07 18:00:18 -07001799 struct nlattr *nest;
1800
1801 nest = nla_nest_start(skb, NDTA_PARMS);
1802 if (nest == NULL)
1803 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001804
David S. Miller9a6308d2012-04-01 20:06:28 -04001805 if ((parms->dev &&
1806 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1807 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001808 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1809 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001810 /* approximative value for deprecated QUEUE_LEN (in packets) */
1811 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001812 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1813 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1814 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1815 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1816 NEIGH_VAR(parms, UCAST_PROBES)) ||
1817 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1818 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001819 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1820 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001821 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1822 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1823 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001824 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001825 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1826 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1827 NEIGH_VAR(parms, RETRANS_TIME)) ||
1828 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1829 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1830 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1831 NEIGH_VAR(parms, PROXY_DELAY)) ||
1832 nla_put_msecs(skb, NDTPA_LOCKTIME,
1833 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001834 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001835 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001836
Thomas Grafca860fb2006-08-07 18:00:18 -07001837nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001838 nla_nest_cancel(skb, nest);
1839 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001840}
1841
Thomas Grafca860fb2006-08-07 18:00:18 -07001842static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1843 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844{
1845 struct nlmsghdr *nlh;
1846 struct ndtmsg *ndtmsg;
1847
Thomas Grafca860fb2006-08-07 18:00:18 -07001848 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1849 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001850 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001851
Thomas Grafca860fb2006-08-07 18:00:18 -07001852 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853
1854 read_lock_bh(&tbl->lock);
1855 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001856 ndtmsg->ndtm_pad1 = 0;
1857 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001858
David S. Miller9a6308d2012-04-01 20:06:28 -04001859 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1860 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1861 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1862 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1863 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1864 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001865 {
1866 unsigned long now = jiffies;
1867 unsigned int flush_delta = now - tbl->last_flush;
1868 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001869 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001870 struct ndt_config ndc = {
1871 .ndtc_key_len = tbl->key_len,
1872 .ndtc_entry_size = tbl->entry_size,
1873 .ndtc_entries = atomic_read(&tbl->entries),
1874 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1875 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001876 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1877 };
1878
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001879 rcu_read_lock_bh();
1880 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001881 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001882 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001883 rcu_read_unlock_bh();
1884
David S. Miller9a6308d2012-04-01 20:06:28 -04001885 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1886 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887 }
1888
1889 {
1890 int cpu;
1891 struct ndt_stats ndst;
1892
1893 memset(&ndst, 0, sizeof(ndst));
1894
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001895 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001896 struct neigh_statistics *st;
1897
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001898 st = per_cpu_ptr(tbl->stats, cpu);
1899 ndst.ndts_allocs += st->allocs;
1900 ndst.ndts_destroys += st->destroys;
1901 ndst.ndts_hash_grows += st->hash_grows;
1902 ndst.ndts_res_failed += st->res_failed;
1903 ndst.ndts_lookups += st->lookups;
1904 ndst.ndts_hits += st->hits;
1905 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1906 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1907 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1908 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1909 }
1910
David S. Miller9a6308d2012-04-01 20:06:28 -04001911 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1912 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001913 }
1914
1915 BUG_ON(tbl->parms.dev);
1916 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001917 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001918
1919 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001920 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921
Thomas Grafca860fb2006-08-07 18:00:18 -07001922nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001923 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001924 nlmsg_cancel(skb, nlh);
1925 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001926}
1927
Thomas Grafca860fb2006-08-07 18:00:18 -07001928static int neightbl_fill_param_info(struct sk_buff *skb,
1929 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001931 u32 pid, u32 seq, int type,
1932 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001933{
1934 struct ndtmsg *ndtmsg;
1935 struct nlmsghdr *nlh;
1936
Thomas Grafca860fb2006-08-07 18:00:18 -07001937 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1938 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001939 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001940
Thomas Grafca860fb2006-08-07 18:00:18 -07001941 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001942
1943 read_lock_bh(&tbl->lock);
1944 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001945 ndtmsg->ndtm_pad1 = 0;
1946 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001947
Thomas Grafca860fb2006-08-07 18:00:18 -07001948 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1949 neightbl_fill_parms(skb, parms) < 0)
1950 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001951
1952 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001953 return nlmsg_end(skb, nlh);
1954errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001955 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001956 nlmsg_cancel(skb, nlh);
1957 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001958}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001959
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001960static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001961 [NDTA_NAME] = { .type = NLA_STRING },
1962 [NDTA_THRESH1] = { .type = NLA_U32 },
1963 [NDTA_THRESH2] = { .type = NLA_U32 },
1964 [NDTA_THRESH3] = { .type = NLA_U32 },
1965 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1966 [NDTA_PARMS] = { .type = NLA_NESTED },
1967};
1968
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001969static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001970 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1971 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1972 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1973 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1974 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1975 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1976 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1977 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1978 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1979 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1980 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1981 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1982 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1983};
1984
Thomas Graf661d2962013-03-21 07:45:29 +00001985static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001987 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001989 struct ndtmsg *ndtmsg;
1990 struct nlattr *tb[NDTA_MAX+1];
1991 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001992
Thomas Graf6b3f8672006-08-07 17:58:53 -07001993 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1994 nl_neightbl_policy);
1995 if (err < 0)
1996 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001997
Thomas Graf6b3f8672006-08-07 17:58:53 -07001998 if (tb[NDTA_NAME] == NULL) {
1999 err = -EINVAL;
2000 goto errout;
2001 }
2002
2003 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002004 read_lock(&neigh_tbl_lock);
2005 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
2006 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2007 continue;
2008
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010 break;
2011 }
2012
2013 if (tbl == NULL) {
2014 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002015 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002016 }
2017
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002018 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002019 * We acquire tbl->lock to be nice to the periodic timers and
2020 * make sure they always see a consistent set of values.
2021 */
2022 write_lock_bh(&tbl->lock);
2023
Thomas Graf6b3f8672006-08-07 17:58:53 -07002024 if (tb[NDTA_PARMS]) {
2025 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002026 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002027 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002028
Thomas Graf6b3f8672006-08-07 17:58:53 -07002029 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2030 nl_ntbl_parm_policy);
2031 if (err < 0)
2032 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002033
Thomas Graf6b3f8672006-08-07 17:58:53 -07002034 if (tbp[NDTPA_IFINDEX])
2035 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002036
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002037 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002038 if (p == NULL) {
2039 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002040 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002041 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002042
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 for (i = 1; i <= NDTPA_MAX; i++) {
2044 if (tbp[i] == NULL)
2045 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002046
Thomas Graf6b3f8672006-08-07 17:58:53 -07002047 switch (i) {
2048 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002049 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2050 nla_get_u32(tbp[i]) *
2051 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002052 break;
2053 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002054 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2055 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002056 break;
2057 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002058 NEIGH_VAR_SET(p, PROXY_QLEN,
2059 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002060 break;
2061 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002062 NEIGH_VAR_SET(p, APP_PROBES,
2063 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064 break;
2065 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002066 NEIGH_VAR_SET(p, UCAST_PROBES,
2067 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002068 break;
2069 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002070 NEIGH_VAR_SET(p, MCAST_PROBES,
2071 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002072 break;
2073 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002074 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2075 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002078 NEIGH_VAR_SET(p, GC_STALETIME,
2079 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002080 break;
2081 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002082 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2083 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002084 break;
2085 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002086 NEIGH_VAR_SET(p, RETRANS_TIME,
2087 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002088 break;
2089 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002090 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2091 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002092 break;
2093 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002094 NEIGH_VAR_SET(p, PROXY_DELAY,
2095 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002096 break;
2097 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002098 NEIGH_VAR_SET(p, LOCKTIME,
2099 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002100 break;
2101 }
2102 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002103 }
2104
Gao fengdc25c672013-06-20 10:01:34 +08002105 err = -ENOENT;
2106 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2107 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2108 !net_eq(net, &init_net))
2109 goto errout_tbl_lock;
2110
Thomas Graf6b3f8672006-08-07 17:58:53 -07002111 if (tb[NDTA_THRESH1])
2112 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2113
2114 if (tb[NDTA_THRESH2])
2115 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2116
2117 if (tb[NDTA_THRESH3])
2118 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2119
2120 if (tb[NDTA_GC_INTERVAL])
2121 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2122
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002123 err = 0;
2124
Thomas Graf6b3f8672006-08-07 17:58:53 -07002125errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002126 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002127errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002128 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002129errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002130 return err;
2131}
2132
Thomas Grafc8822a42007-03-22 11:50:06 -07002133static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002134{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002135 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002136 int family, tidx, nidx = 0;
2137 int tbl_skip = cb->args[0];
2138 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002139 struct neigh_table *tbl;
2140
Thomas Grafca860fb2006-08-07 18:00:18 -07002141 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002142
2143 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002144 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002145 struct neigh_parms *p;
2146
Thomas Grafca860fb2006-08-07 18:00:18 -07002147 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002148 continue;
2149
Eric W. Biederman15e47302012-09-07 20:12:54 +00002150 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002151 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2152 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002153 break;
2154
Eric W. Biederman426b5302008-01-24 00:13:18 -08002155 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002156 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002157 continue;
2158
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002159 if (nidx < neigh_skip)
2160 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002161
Thomas Grafca860fb2006-08-07 18:00:18 -07002162 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002163 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002164 cb->nlh->nlmsg_seq,
2165 RTM_NEWNEIGHTBL,
2166 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002167 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002168 next:
2169 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002170 }
2171
Thomas Grafca860fb2006-08-07 18:00:18 -07002172 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002173 }
2174out:
2175 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002176 cb->args[0] = tidx;
2177 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002178
2179 return skb->len;
2180}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181
Thomas Graf8b8aec52006-08-07 17:56:37 -07002182static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2183 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184{
2185 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002187 struct nlmsghdr *nlh;
2188 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Thomas Graf8b8aec52006-08-07 17:56:37 -07002190 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2191 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002192 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002193
2194 ndm = nlmsg_data(nlh);
2195 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002196 ndm->ndm_pad1 = 0;
2197 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002198 ndm->ndm_flags = neigh->flags;
2199 ndm->ndm_type = neigh->type;
2200 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
David S. Miller9a6308d2012-04-01 20:06:28 -04002202 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2203 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002204
2205 read_lock_bh(&neigh->lock);
2206 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002207 if (neigh->nud_state & NUD_VALID) {
2208 char haddr[MAX_ADDR_LEN];
2209
2210 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2211 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2212 read_unlock_bh(&neigh->lock);
2213 goto nla_put_failure;
2214 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002215 }
2216
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002217 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2218 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2219 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002220 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2221 read_unlock_bh(&neigh->lock);
2222
David S. Miller9a6308d2012-04-01 20:06:28 -04002223 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2224 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2225 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002226
2227 return nlmsg_end(skb, nlh);
2228
2229nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002230 nlmsg_cancel(skb, nlh);
2231 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232}
2233
Tony Zelenoff84920c12012-01-26 22:28:58 +00002234static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2235 u32 pid, u32 seq, int type, unsigned int flags,
2236 struct neigh_table *tbl)
2237{
2238 struct nlmsghdr *nlh;
2239 struct ndmsg *ndm;
2240
2241 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2242 if (nlh == NULL)
2243 return -EMSGSIZE;
2244
2245 ndm = nlmsg_data(nlh);
2246 ndm->ndm_family = tbl->family;
2247 ndm->ndm_pad1 = 0;
2248 ndm->ndm_pad2 = 0;
2249 ndm->ndm_flags = pn->flags | NTF_PROXY;
2250 ndm->ndm_type = NDA_DST;
2251 ndm->ndm_ifindex = pn->dev->ifindex;
2252 ndm->ndm_state = NUD_NONE;
2253
David S. Miller9a6308d2012-04-01 20:06:28 -04002254 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2255 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002256
2257 return nlmsg_end(skb, nlh);
2258
2259nla_put_failure:
2260 nlmsg_cancel(skb, nlh);
2261 return -EMSGSIZE;
2262}
2263
Thomas Grafd961db32007-08-08 23:12:56 -07002264static void neigh_update_notify(struct neighbour *neigh)
2265{
2266 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2267 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2268}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
2270static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2271 struct netlink_callback *cb)
2272{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002273 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 struct neighbour *n;
2275 int rc, h, s_h = cb->args[1];
2276 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002277 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002279 rcu_read_lock_bh();
2280 nht = rcu_dereference_bh(tbl->nht);
2281
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002282 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 if (h > s_h)
2284 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002285 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2286 n != NULL;
2287 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002288 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002289 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002290 if (idx < s_idx)
2291 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002292 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002294 RTM_NEWNEIGH,
2295 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002296 rc = -1;
2297 goto out;
2298 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002299next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002300 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 }
2303 rc = skb->len;
2304out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002305 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 cb->args[1] = h;
2307 cb->args[2] = idx;
2308 return rc;
2309}
2310
Tony Zelenoff84920c12012-01-26 22:28:58 +00002311static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2312 struct netlink_callback *cb)
2313{
2314 struct pneigh_entry *n;
2315 struct net *net = sock_net(skb->sk);
2316 int rc, h, s_h = cb->args[3];
2317 int idx, s_idx = idx = cb->args[4];
2318
2319 read_lock_bh(&tbl->lock);
2320
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002321 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002322 if (h > s_h)
2323 s_idx = 0;
2324 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2325 if (dev_net(n->dev) != net)
2326 continue;
2327 if (idx < s_idx)
2328 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002329 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002330 cb->nlh->nlmsg_seq,
2331 RTM_NEWNEIGH,
2332 NLM_F_MULTI, tbl) <= 0) {
2333 read_unlock_bh(&tbl->lock);
2334 rc = -1;
2335 goto out;
2336 }
2337 next:
2338 idx++;
2339 }
2340 }
2341
2342 read_unlock_bh(&tbl->lock);
2343 rc = skb->len;
2344out:
2345 cb->args[3] = h;
2346 cb->args[4] = idx;
2347 return rc;
2348
2349}
2350
Thomas Grafc8822a42007-03-22 11:50:06 -07002351static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352{
2353 struct neigh_table *tbl;
2354 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002355 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002356 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357
2358 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002359 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002360
2361 /* check for full ndmsg structure presence, family member is
2362 * the same for both structures
2363 */
2364 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2365 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2366 proxy = 1;
2367
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368 s_t = cb->args[0];
2369
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002370 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002371 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 if (t < s_t || (family && tbl->family != family))
2373 continue;
2374 if (t > s_t)
2375 memset(&cb->args[1], 0, sizeof(cb->args) -
2376 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002377 if (proxy)
2378 err = pneigh_dump_table(tbl, skb, cb);
2379 else
2380 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002381 if (err < 0)
2382 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 }
2384 read_unlock(&neigh_tbl_lock);
2385
2386 cb->args[0] = t;
2387 return skb->len;
2388}
2389
2390void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2391{
2392 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002393 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002394
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002395 rcu_read_lock_bh();
2396 nht = rcu_dereference_bh(tbl->nht);
2397
Eric Dumazet767e97e2010-10-06 17:49:21 -07002398 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002399 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400 struct neighbour *n;
2401
Eric Dumazet767e97e2010-10-06 17:49:21 -07002402 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2403 n != NULL;
2404 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 cb(n, cookie);
2406 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002407 read_unlock(&tbl->lock);
2408 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409}
2410EXPORT_SYMBOL(neigh_for_each);
2411
2412/* The tbl->lock must be held as a writer and BH disabled. */
2413void __neigh_for_each_release(struct neigh_table *tbl,
2414 int (*cb)(struct neighbour *))
2415{
2416 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002417 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002419 nht = rcu_dereference_protected(tbl->nht,
2420 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002421 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002422 struct neighbour *n;
2423 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002425 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002426 while ((n = rcu_dereference_protected(*np,
2427 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 int release;
2429
2430 write_lock(&n->lock);
2431 release = cb(n);
2432 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002433 rcu_assign_pointer(*np,
2434 rcu_dereference_protected(n->next,
2435 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436 n->dead = 1;
2437 } else
2438 np = &n->next;
2439 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002440 if (release)
2441 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 }
2443 }
2444}
2445EXPORT_SYMBOL(__neigh_for_each_release);
2446
2447#ifdef CONFIG_PROC_FS
2448
2449static struct neighbour *neigh_get_first(struct seq_file *seq)
2450{
2451 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002452 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002453 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 struct neighbour *n = NULL;
2455 int bucket = state->bucket;
2456
2457 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002458 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002459 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
2461 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002462 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002463 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464 if (state->neigh_sub_iter) {
2465 loff_t fakep = 0;
2466 void *v;
2467
2468 v = state->neigh_sub_iter(state, n, &fakep);
2469 if (!v)
2470 goto next;
2471 }
2472 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2473 break;
2474 if (n->nud_state & ~NUD_NOARP)
2475 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002476next:
2477 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 }
2479
2480 if (n)
2481 break;
2482 }
2483 state->bucket = bucket;
2484
2485 return n;
2486}
2487
2488static struct neighbour *neigh_get_next(struct seq_file *seq,
2489 struct neighbour *n,
2490 loff_t *pos)
2491{
2492 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002493 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002494 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495
2496 if (state->neigh_sub_iter) {
2497 void *v = state->neigh_sub_iter(state, n, pos);
2498 if (v)
2499 return n;
2500 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002501 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502
2503 while (1) {
2504 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002505 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002506 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 if (state->neigh_sub_iter) {
2508 void *v = state->neigh_sub_iter(state, n, pos);
2509 if (v)
2510 return n;
2511 goto next;
2512 }
2513 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2514 break;
2515
2516 if (n->nud_state & ~NUD_NOARP)
2517 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002518next:
2519 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 }
2521
2522 if (n)
2523 break;
2524
David S. Millercd089332011-07-11 01:28:12 -07002525 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526 break;
2527
Eric Dumazet767e97e2010-10-06 17:49:21 -07002528 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 }
2530
2531 if (n && pos)
2532 --(*pos);
2533 return n;
2534}
2535
2536static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2537{
2538 struct neighbour *n = neigh_get_first(seq);
2539
2540 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002541 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542 while (*pos) {
2543 n = neigh_get_next(seq, n, pos);
2544 if (!n)
2545 break;
2546 }
2547 }
2548 return *pos ? NULL : n;
2549}
2550
2551static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2552{
2553 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002554 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 struct neigh_table *tbl = state->tbl;
2556 struct pneigh_entry *pn = NULL;
2557 int bucket = state->bucket;
2558
2559 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2560 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2561 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002562 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002563 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 if (pn)
2565 break;
2566 }
2567 state->bucket = bucket;
2568
2569 return pn;
2570}
2571
2572static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2573 struct pneigh_entry *pn,
2574 loff_t *pos)
2575{
2576 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002577 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 struct neigh_table *tbl = state->tbl;
2579
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002580 do {
2581 pn = pn->next;
2582 } while (pn && !net_eq(pneigh_net(pn), net));
2583
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 while (!pn) {
2585 if (++state->bucket > PNEIGH_HASHMASK)
2586 break;
2587 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002588 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002589 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590 if (pn)
2591 break;
2592 }
2593
2594 if (pn && pos)
2595 --(*pos);
2596
2597 return pn;
2598}
2599
2600static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2601{
2602 struct pneigh_entry *pn = pneigh_get_first(seq);
2603
2604 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002605 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606 while (*pos) {
2607 pn = pneigh_get_next(seq, pn, pos);
2608 if (!pn)
2609 break;
2610 }
2611 }
2612 return *pos ? NULL : pn;
2613}
2614
2615static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2616{
2617 struct neigh_seq_state *state = seq->private;
2618 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002619 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620
Chris Larson745e2032008-08-03 01:10:55 -07002621 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002623 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624
2625 return rc;
2626}
2627
2628void *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 +00002629 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630{
2631 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632
2633 state->tbl = tbl;
2634 state->bucket = 0;
2635 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2636
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002637 rcu_read_lock_bh();
2638 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002639
Chris Larson745e2032008-08-03 01:10:55 -07002640 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641}
2642EXPORT_SYMBOL(neigh_seq_start);
2643
2644void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2645{
2646 struct neigh_seq_state *state;
2647 void *rc;
2648
2649 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002650 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 goto out;
2652 }
2653
2654 state = seq->private;
2655 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2656 rc = neigh_get_next(seq, v, NULL);
2657 if (rc)
2658 goto out;
2659 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2660 rc = pneigh_get_first(seq);
2661 } else {
2662 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2663 rc = pneigh_get_next(seq, v, NULL);
2664 }
2665out:
2666 ++(*pos);
2667 return rc;
2668}
2669EXPORT_SYMBOL(neigh_seq_next);
2670
2671void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002672 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002674 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675}
2676EXPORT_SYMBOL(neigh_seq_stop);
2677
2678/* statistics via seq_file */
2679
2680static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2681{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002682 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683 int cpu;
2684
2685 if (*pos == 0)
2686 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002687
Rusty Russell0f23174a2008-12-29 12:23:42 +00002688 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002689 if (!cpu_possible(cpu))
2690 continue;
2691 *pos = cpu+1;
2692 return per_cpu_ptr(tbl->stats, cpu);
2693 }
2694 return NULL;
2695}
2696
2697static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2698{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002699 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 int cpu;
2701
Rusty Russell0f23174a2008-12-29 12:23:42 +00002702 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 if (!cpu_possible(cpu))
2704 continue;
2705 *pos = cpu+1;
2706 return per_cpu_ptr(tbl->stats, cpu);
2707 }
2708 return NULL;
2709}
2710
2711static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2712{
2713
2714}
2715
2716static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2717{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002718 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 struct neigh_statistics *st = v;
2720
2721 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002722 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 -07002723 return 0;
2724 }
2725
2726 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002727 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 atomic_read(&tbl->entries),
2729
2730 st->allocs,
2731 st->destroys,
2732 st->hash_grows,
2733
2734 st->lookups,
2735 st->hits,
2736
2737 st->res_failed,
2738
2739 st->rcv_probes_mcast,
2740 st->rcv_probes_ucast,
2741
2742 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002743 st->forced_gc_runs,
2744 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 );
2746
2747 return 0;
2748}
2749
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002750static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002751 .start = neigh_stat_seq_start,
2752 .next = neigh_stat_seq_next,
2753 .stop = neigh_stat_seq_stop,
2754 .show = neigh_stat_seq_show,
2755};
2756
2757static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2758{
2759 int ret = seq_open(file, &neigh_stat_seq_ops);
2760
2761 if (!ret) {
2762 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002763 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 }
2765 return ret;
2766};
2767
Arjan van de Ven9a321442007-02-12 00:55:35 -08002768static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 .owner = THIS_MODULE,
2770 .open = neigh_stat_seq_open,
2771 .read = seq_read,
2772 .llseek = seq_lseek,
2773 .release = seq_release,
2774};
2775
2776#endif /* CONFIG_PROC_FS */
2777
Thomas Graf339bf982006-11-10 14:10:15 -08002778static inline size_t neigh_nlmsg_size(void)
2779{
2780 return NLMSG_ALIGN(sizeof(struct ndmsg))
2781 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2782 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2783 + nla_total_size(sizeof(struct nda_cacheinfo))
2784 + nla_total_size(4); /* NDA_PROBES */
2785}
2786
Thomas Grafb8673312006-08-15 00:33:14 -07002787static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002789 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002790 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002791 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
Thomas Graf339bf982006-11-10 14:10:15 -08002793 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002794 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002795 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796
Thomas Grafb8673312006-08-15 00:33:14 -07002797 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002798 if (err < 0) {
2799 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2800 WARN_ON(err == -EMSGSIZE);
2801 kfree_skb(skb);
2802 goto errout;
2803 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002804 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2805 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002806errout:
2807 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002808 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002809}
2810
2811void neigh_app_ns(struct neighbour *n)
2812{
2813 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002815EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816
2817#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002818static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002819static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002820static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002821
Joe Perchesfe2c6332013-06-11 23:04:25 -07002822static int proc_unres_qlen(struct ctl_table *ctl, int write,
2823 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002824{
2825 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002826 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002827
Shan Weice46cc62012-12-04 18:49:15 +00002828 tmp.extra1 = &zero;
2829 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002830 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002831
2832 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2833 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2834
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002835 if (write && !ret)
2836 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2837 return ret;
2838}
2839
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002840static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2841 int family)
2842{
Jiri Pirkobba24892013-12-07 19:26:57 +01002843 switch (family) {
2844 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002845 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002846 case AF_INET6:
2847 return __in6_dev_nd_parms_get_rcu(dev);
2848 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002849 return NULL;
2850}
2851
2852static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2853 int index)
2854{
2855 struct net_device *dev;
2856 int family = neigh_parms_family(p);
2857
2858 rcu_read_lock();
2859 for_each_netdev_rcu(net, dev) {
2860 struct neigh_parms *dst_p =
2861 neigh_get_dev_parms_rcu(dev, family);
2862
2863 if (dst_p && !test_bit(index, dst_p->data_state))
2864 dst_p->data[index] = p->data[index];
2865 }
2866 rcu_read_unlock();
2867}
2868
2869static void neigh_proc_update(struct ctl_table *ctl, int write)
2870{
2871 struct net_device *dev = ctl->extra1;
2872 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002873 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002874 int index = (int *) ctl->data - p->data;
2875
2876 if (!write)
2877 return;
2878
2879 set_bit(index, p->data_state);
2880 if (!dev) /* NULL dev means this is default value */
2881 neigh_copy_dflt_parms(net, p, index);
2882}
2883
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002884static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2885 void __user *buffer,
2886 size_t *lenp, loff_t *ppos)
2887{
2888 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002889 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002890
2891 tmp.extra1 = &zero;
2892 tmp.extra2 = &int_max;
2893
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002894 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2895 neigh_proc_update(ctl, write);
2896 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002897}
2898
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002899int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2900 void __user *buffer, size_t *lenp, loff_t *ppos)
2901{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002902 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2903
2904 neigh_proc_update(ctl, write);
2905 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002906}
2907EXPORT_SYMBOL(neigh_proc_dointvec);
2908
2909int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2910 void __user *buffer,
2911 size_t *lenp, loff_t *ppos)
2912{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002913 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2914
2915 neigh_proc_update(ctl, write);
2916 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002917}
2918EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2919
2920static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2921 void __user *buffer,
2922 size_t *lenp, loff_t *ppos)
2923{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002924 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2925
2926 neigh_proc_update(ctl, write);
2927 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002928}
2929
2930int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2931 void __user *buffer,
2932 size_t *lenp, loff_t *ppos)
2933{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002934 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2935
2936 neigh_proc_update(ctl, write);
2937 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002938}
2939EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2940
2941static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2942 void __user *buffer,
2943 size_t *lenp, loff_t *ppos)
2944{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002945 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2946
2947 neigh_proc_update(ctl, write);
2948 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002949}
2950
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002951#define NEIGH_PARMS_DATA_OFFSET(index) \
2952 (&((struct neigh_parms *) 0)->data[index])
2953
2954#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2955 [NEIGH_VAR_ ## attr] = { \
2956 .procname = name, \
2957 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2958 .maxlen = sizeof(int), \
2959 .mode = mval, \
2960 .proc_handler = proc, \
2961 }
2962
2963#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2964 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2965
2966#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002967 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002968
2969#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002970 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002971
2972#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002973 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002974
2975#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002976 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002977
2978#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002979 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002980
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981static struct neigh_sysctl_table {
2982 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002983 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002984} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002986 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2987 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2988 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2989 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2990 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2991 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2992 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2993 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2994 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2995 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2996 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2997 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
2998 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
2999 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3000 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003001 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003002 .procname = "gc_interval",
3003 .maxlen = sizeof(int),
3004 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003005 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003007 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 .procname = "gc_thresh1",
3009 .maxlen = sizeof(int),
3010 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003011 .extra1 = &zero,
3012 .extra2 = &int_max,
3013 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003015 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016 .procname = "gc_thresh2",
3017 .maxlen = sizeof(int),
3018 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003019 .extra1 = &zero,
3020 .extra2 = &int_max,
3021 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003023 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 .procname = "gc_thresh3",
3025 .maxlen = sizeof(int),
3026 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003027 .extra1 = &zero,
3028 .extra2 = &int_max,
3029 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003031 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 },
3033};
3034
3035int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003036 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003037{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003038 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003039 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003040 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003041 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003042 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003044 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003046 goto err;
3047
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003048 for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003049 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003050 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003051 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003052 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053
3054 if (dev) {
3055 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003056 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003057 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3058 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059 } else {
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003060 dev_name_source = "default";
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003061 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = (int *)(p + 1);
3062 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = (int *)(p + 1) + 1;
3063 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = (int *)(p + 1) + 2;
3064 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 }
3066
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003067 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003069 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003071 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003073 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003075 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 }
3077
Eric W. Biederman464dc802012-11-16 03:02:59 +00003078 /* Don't export sysctls to unprivileged users */
3079 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3080 t->neigh_vars[0].procname = NULL;
3081
Jiri Pirko73af6142013-12-07 19:26:55 +01003082 switch (neigh_parms_family(p)) {
3083 case AF_INET:
3084 p_name = "ipv4";
3085 break;
3086 case AF_INET6:
3087 p_name = "ipv6";
3088 break;
3089 default:
3090 BUG();
3091 }
3092
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003093 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3094 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003095 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003096 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003097 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003098 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003099
Linus Torvalds1da177e2005-04-16 15:20:36 -07003100 p->sysctl_table = t;
3101 return 0;
3102
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003103free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003105err:
3106 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003108EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109
3110void neigh_sysctl_unregister(struct neigh_parms *p)
3111{
3112 if (p->sysctl_table) {
3113 struct neigh_sysctl_table *t = p->sysctl_table;
3114 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003115 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116 kfree(t);
3117 }
3118}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003119EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120
3121#endif /* CONFIG_SYSCTL */
3122
Thomas Grafc8822a42007-03-22 11:50:06 -07003123static int __init neigh_init(void)
3124{
Greg Rosec7ac8672011-06-10 01:27:09 +00003125 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3126 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3127 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003128
Greg Rosec7ac8672011-06-10 01:27:09 +00003129 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3130 NULL);
3131 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003132
3133 return 0;
3134}
3135
3136subsys_initcall(neigh_init);
3137