blob: 65ead080167b2fe6bb3ab9ee923de2b5b3b99711 [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Joe Perchesd5d427c2013-04-15 15:17:19 +000042#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070043#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define neigh_dbg(level, fmt, ...) \
45do { \
46 if (level <= NEIGH_DEBUG) \
47 pr_debug(fmt, ##__VA_ARGS__); \
48} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
50#define PNEIGH_HASHMASK 0xF
51
52static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070053static void __neigh_notify(struct neighbour *n, int type, int flags);
54static void neigh_update_notify(struct neighbour *neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57static struct neigh_table *neigh_tables;
Amos Waterland45fc3b12005-09-24 16:53:16 -070058#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080059static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070060#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
62/*
63 Neighbour hash table buckets are protected with rwlock tbl->lock.
64
65 - All the scans/updates to hash buckets MUST be made under this lock.
66 - NOTHING clever should be made under this lock: no callbacks
67 to protocol backends, no attempts to send something to network.
68 It will result in deadlocks, if backend/driver wants to use neighbour
69 cache.
70 - If the entry requires some non-trivial actions, increase
71 its reference count and release table lock.
72
73 Neighbour entries are protected:
74 - with reference count.
75 - with rwlock neigh->lock
76
77 Reference count prevents destruction.
78
79 neigh->lock mainly serializes ll address data and its validity state.
80 However, the same lock is used to protect another entry fields:
81 - timer
82 - resolution queue
83
84 Again, nothing clever shall be made under neigh->lock,
85 the most complicated procedure, which we allow is dev->hard_header.
86 It is supposed, that dev->hard_header is simplistic and does
87 not make callbacks to neighbour tables.
88
89 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
90 list of neighbour tables. This list is used only in process context,
91 */
92
93static DEFINE_RWLOCK(neigh_tbl_lock);
94
David S. Miller8f40b162011-07-17 13:34:11 -070095static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
97 kfree_skb(skb);
98 return -ENETDOWN;
99}
100
Thomas Graf4f494552007-08-08 23:12:36 -0700101static void neigh_cleanup_and_release(struct neighbour *neigh)
102{
103 if (neigh->parms->neigh_cleanup)
104 neigh->parms->neigh_cleanup(neigh);
105
Thomas Grafd961db32007-08-08 23:12:56 -0700106 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700107 neigh_release(neigh);
108}
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110/*
111 * It is random distribution in the interval (1/2)*base...(3/2)*base.
112 * It corresponds to default IPv6 settings and is not overridable,
113 * because it is really reasonable choice.
114 */
115
116unsigned long neigh_rand_reach_time(unsigned long base)
117{
Eric Dumazeta02cec22010-09-22 20:43:57 +0000118 return base ? (net_random() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900120EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122
123static int neigh_forced_gc(struct neigh_table *tbl)
124{
125 int shrunk = 0;
126 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000127 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
129 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
130
131 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000132 nht = rcu_dereference_protected(tbl->nht,
133 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700134 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700135 struct neighbour *n;
136 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000138 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700139 while ((n = rcu_dereference_protected(*np,
140 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 /* Neighbour record may be discarded if:
142 * - nobody refers to it.
143 * - it is not permanent
144 */
145 write_lock(&n->lock);
146 if (atomic_read(&n->refcnt) == 1 &&
147 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700148 rcu_assign_pointer(*np,
149 rcu_dereference_protected(n->next,
150 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 n->dead = 1;
152 shrunk = 1;
153 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700154 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 continue;
156 }
157 write_unlock(&n->lock);
158 np = &n->next;
159 }
160 }
161
162 tbl->last_flush = jiffies;
163
164 write_unlock_bh(&tbl->lock);
165
166 return shrunk;
167}
168
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800169static void neigh_add_timer(struct neighbour *n, unsigned long when)
170{
171 neigh_hold(n);
172 if (unlikely(mod_timer(&n->timer, when))) {
173 printk("NEIGH: BUG, double timer add, state is %x\n",
174 n->nud_state);
175 dump_stack();
176 }
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179static int neigh_del_timer(struct neighbour *n)
180{
181 if ((n->nud_state & NUD_IN_TIMER) &&
182 del_timer(&n->timer)) {
183 neigh_release(n);
184 return 1;
185 }
186 return 0;
187}
188
189static void pneigh_queue_purge(struct sk_buff_head *list)
190{
191 struct sk_buff *skb;
192
193 while ((skb = skb_dequeue(list)) != NULL) {
194 dev_put(skb->dev);
195 kfree_skb(skb);
196 }
197}
198
Herbert Xu49636bb2005-10-23 17:18:00 +1000199static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
201 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000202 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000204 nht = rcu_dereference_protected(tbl->nht,
205 lockdep_is_held(&tbl->lock));
206
David S. Millercd089332011-07-11 01:28:12 -0700207 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700208 struct neighbour *n;
209 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Eric Dumazet767e97e2010-10-06 17:49:21 -0700211 while ((n = rcu_dereference_protected(*np,
212 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 if (dev && n->dev != dev) {
214 np = &n->next;
215 continue;
216 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700217 rcu_assign_pointer(*np,
218 rcu_dereference_protected(n->next,
219 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 write_lock(&n->lock);
221 neigh_del_timer(n);
222 n->dead = 1;
223
224 if (atomic_read(&n->refcnt) != 1) {
225 /* The most unpleasant situation.
226 We must destroy neighbour entry,
227 but someone still uses it.
228
229 The destroy will be delayed until
230 the last user releases us, but
231 we must kill timers etc. and move
232 it to safe state.
233 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700234 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000235 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 n->output = neigh_blackhole;
237 if (n->nud_state & NUD_VALID)
238 n->nud_state = NUD_NOARP;
239 else
240 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000241 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 }
243 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700244 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 }
246 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000247}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Herbert Xu49636bb2005-10-23 17:18:00 +1000249void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
250{
251 write_lock_bh(&tbl->lock);
252 neigh_flush_dev(tbl, dev);
253 write_unlock_bh(&tbl->lock);
254}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900255EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000256
257int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
258{
259 write_lock_bh(&tbl->lock);
260 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 pneigh_ifdown(tbl, dev);
262 write_unlock_bh(&tbl->lock);
263
264 del_timer_sync(&tbl->proxy_timer);
265 pneigh_queue_purge(&tbl->proxy_queue);
266 return 0;
267}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900268EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269
David Miller596b9b62011-07-25 00:01:25 +0000270static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271{
272 struct neighbour *n = NULL;
273 unsigned long now = jiffies;
274 int entries;
275
276 entries = atomic_inc_return(&tbl->entries) - 1;
277 if (entries >= tbl->gc_thresh3 ||
278 (entries >= tbl->gc_thresh2 &&
279 time_after(now, tbl->last_flush + 5 * HZ))) {
280 if (!neigh_forced_gc(tbl) &&
281 entries >= tbl->gc_thresh3)
282 goto out_entries;
283 }
284
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000285 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 if (!n)
287 goto out_entries;
288
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700289 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000291 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 n->updated = n->used = now;
293 n->nud_state = NUD_NONE;
294 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700295 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800297 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299 NEIGH_CACHE_STAT_INC(tbl, allocs);
300 n->tbl = tbl;
301 atomic_set(&n->refcnt, 1);
302 n->dead = 1;
303out:
304 return n;
305
306out_entries:
307 atomic_dec(&tbl->entries);
308 goto out;
309}
310
David S. Miller2c2aba62011-12-28 15:06:58 -0500311static void neigh_get_hash_rnd(u32 *x)
312{
313 get_random_bytes(x, sizeof(*x));
314 *x |= 1;
315}
316
David S. Millercd089332011-07-11 01:28:12 -0700317static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318{
David S. Millercd089332011-07-11 01:28:12 -0700319 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000320 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000321 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500322 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000324 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
325 if (!ret)
326 return NULL;
327 if (size <= PAGE_SIZE)
328 buckets = kzalloc(size, GFP_ATOMIC);
329 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000330 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000331 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
332 get_order(size));
333 if (!buckets) {
334 kfree(ret);
335 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000337 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700338 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500339 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
340 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 return ret;
342}
343
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000344static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000346 struct neigh_hash_table *nht = container_of(head,
347 struct neigh_hash_table,
348 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700349 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000350 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351
352 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000353 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000355 free_pages((unsigned long)buckets, get_order(size));
356 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357}
358
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000359static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700360 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000362 unsigned int i, hash;
363 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364
365 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
366
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000367 old_nht = rcu_dereference_protected(tbl->nht,
368 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700369 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000370 if (!new_nht)
371 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372
David S. Millercd089332011-07-11 01:28:12 -0700373 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 struct neighbour *n, *next;
375
Eric Dumazet767e97e2010-10-06 17:49:21 -0700376 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
377 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000378 n != NULL;
379 n = next) {
380 hash = tbl->hash(n->primary_key, n->dev,
381 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
David S. Millercd089332011-07-11 01:28:12 -0700383 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700384 next = rcu_dereference_protected(n->next,
385 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386
Eric Dumazet767e97e2010-10-06 17:49:21 -0700387 rcu_assign_pointer(n->next,
388 rcu_dereference_protected(
389 new_nht->hash_buckets[hash],
390 lockdep_is_held(&tbl->lock)));
391 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 }
393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000395 rcu_assign_pointer(tbl->nht, new_nht);
396 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
397 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398}
399
400struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
401 struct net_device *dev)
402{
403 struct neighbour *n;
404 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800405 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000406 struct neigh_hash_table *nht;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900407
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 NEIGH_CACHE_STAT_INC(tbl, lookups);
409
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000410 rcu_read_lock_bh();
411 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700412 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700413
414 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
415 n != NULL;
416 n = rcu_dereference_bh(n->next)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700418 if (!atomic_inc_not_zero(&n->refcnt))
419 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 NEIGH_CACHE_STAT_INC(tbl, hits);
421 break;
422 }
423 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700424
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000425 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426 return n;
427}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900428EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
Eric W. Biederman426b5302008-01-24 00:13:18 -0800430struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
431 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432{
433 struct neighbour *n;
434 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800435 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000436 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
438 NEIGH_CACHE_STAT_INC(tbl, lookups);
439
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000440 rcu_read_lock_bh();
441 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700442 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700443
444 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
445 n != NULL;
446 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800447 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900448 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700449 if (!atomic_inc_not_zero(&n->refcnt))
450 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 NEIGH_CACHE_STAT_INC(tbl, hits);
452 break;
453 }
454 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700455
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000456 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457 return n;
458}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900459EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
David S. Millera263b302012-07-02 02:02:15 -0700461struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
462 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463{
464 u32 hash_val;
465 int key_len = tbl->key_len;
466 int error;
David Miller596b9b62011-07-25 00:01:25 +0000467 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000468 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469
470 if (!n) {
471 rc = ERR_PTR(-ENOBUFS);
472 goto out;
473 }
474
475 memcpy(n->primary_key, pkey, key_len);
476 n->dev = dev;
477 dev_hold(dev);
478
479 /* Protocol specific setup. */
480 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
481 rc = ERR_PTR(error);
482 goto out_neigh_release;
483 }
484
David Millerda6a8fa2011-07-25 00:01:38 +0000485 if (dev->netdev_ops->ndo_neigh_construct) {
486 error = dev->netdev_ops->ndo_neigh_construct(n);
487 if (error < 0) {
488 rc = ERR_PTR(error);
489 goto out_neigh_release;
490 }
491 }
492
David S. Miller447f2192011-12-19 15:04:41 -0500493 /* Device specific setup. */
494 if (n->parms->neigh_setup &&
495 (error = n->parms->neigh_setup(n)) < 0) {
496 rc = ERR_PTR(error);
497 goto out_neigh_release;
498 }
499
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100500 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000503 nht = rcu_dereference_protected(tbl->nht,
504 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
David S. Millercd089332011-07-11 01:28:12 -0700506 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
507 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508
David S. Millercd089332011-07-11 01:28:12 -0700509 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
511 if (n->parms->dead) {
512 rc = ERR_PTR(-EINVAL);
513 goto out_tbl_unlock;
514 }
515
Eric Dumazet767e97e2010-10-06 17:49:21 -0700516 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
517 lockdep_is_held(&tbl->lock));
518 n1 != NULL;
519 n1 = rcu_dereference_protected(n1->next,
520 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700522 if (want_ref)
523 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 rc = n1;
525 goto out_tbl_unlock;
526 }
527 }
528
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700530 if (want_ref)
531 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700532 rcu_assign_pointer(n->next,
533 rcu_dereference_protected(nht->hash_buckets[hash_val],
534 lockdep_is_held(&tbl->lock)));
535 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000537 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 rc = n;
539out:
540 return rc;
541out_tbl_unlock:
542 write_unlock_bh(&tbl->lock);
543out_neigh_release:
544 neigh_release(n);
545 goto out;
546}
David S. Millera263b302012-07-02 02:02:15 -0700547EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900549static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700550{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700551 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700552 hash_val ^= (hash_val >> 16);
553 hash_val ^= hash_val >> 8;
554 hash_val ^= hash_val >> 4;
555 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900556 return hash_val;
557}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700558
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900559static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
560 struct net *net,
561 const void *pkey,
562 int key_len,
563 struct net_device *dev)
564{
565 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700566 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900567 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700568 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900569 return n;
570 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700571 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900572 return NULL;
573}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700574
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900575struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
576 struct net *net, const void *pkey, struct net_device *dev)
577{
578 int key_len = tbl->key_len;
579 u32 hash_val = pneigh_hash(pkey, key_len);
580
581 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
582 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700583}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900584EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700585
Eric W. Biederman426b5302008-01-24 00:13:18 -0800586struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
587 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 struct net_device *dev, int creat)
589{
590 struct pneigh_entry *n;
591 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900592 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593
594 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900595 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
596 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900598
599 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 goto out;
601
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700602 ASSERT_RTNL();
603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
605 if (!n)
606 goto out;
607
Eric Dumazete42ea982008-11-12 00:54:54 -0800608 write_pnet(&n->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 memcpy(n->key, pkey, key_len);
610 n->dev = dev;
611 if (dev)
612 dev_hold(dev);
613
614 if (tbl->pconstructor && tbl->pconstructor(n)) {
615 if (dev)
616 dev_put(dev);
Denis V. Lunevda12f732008-02-20 00:26:16 -0800617 release_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 kfree(n);
619 n = NULL;
620 goto out;
621 }
622
623 write_lock_bh(&tbl->lock);
624 n->next = tbl->phash_buckets[hash_val];
625 tbl->phash_buckets[hash_val] = n;
626 write_unlock_bh(&tbl->lock);
627out:
628 return n;
629}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900630EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631
632
Eric W. Biederman426b5302008-01-24 00:13:18 -0800633int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 struct net_device *dev)
635{
636 struct pneigh_entry *n, **np;
637 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900638 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639
640 write_lock_bh(&tbl->lock);
641 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
642 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800643 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900644 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700645 *np = n->next;
646 write_unlock_bh(&tbl->lock);
647 if (tbl->pdestructor)
648 tbl->pdestructor(n);
649 if (n->dev)
650 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900651 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 kfree(n);
653 return 0;
654 }
655 }
656 write_unlock_bh(&tbl->lock);
657 return -ENOENT;
658}
659
660static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
661{
662 struct pneigh_entry *n, **np;
663 u32 h;
664
665 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
666 np = &tbl->phash_buckets[h];
667 while ((n = *np) != NULL) {
668 if (!dev || n->dev == dev) {
669 *np = n->next;
670 if (tbl->pdestructor)
671 tbl->pdestructor(n);
672 if (n->dev)
673 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900674 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700675 kfree(n);
676 continue;
677 }
678 np = &n->next;
679 }
680 }
681 return -ENOENT;
682}
683
Denis V. Lunev06f05112008-01-24 00:30:58 -0800684static void neigh_parms_destroy(struct neigh_parms *parms);
685
686static inline void neigh_parms_put(struct neigh_parms *parms)
687{
688 if (atomic_dec_and_test(&parms->refcnt))
689 neigh_parms_destroy(parms);
690}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692/*
693 * neighbour must already be out of the table;
694 *
695 */
696void neigh_destroy(struct neighbour *neigh)
697{
David Millerda6a8fa2011-07-25 00:01:38 +0000698 struct net_device *dev = neigh->dev;
699
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
701
702 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000703 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 dump_stack();
705 return;
706 }
707
708 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000709 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700711 write_lock_bh(&neigh->lock);
712 __skb_queue_purge(&neigh->arp_queue);
713 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000714 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
David S. Miller447f2192011-12-19 15:04:41 -0500716 if (dev->netdev_ops->ndo_neigh_destroy)
717 dev->netdev_ops->ndo_neigh_destroy(neigh);
718
David Millerda6a8fa2011-07-25 00:01:38 +0000719 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 neigh_parms_put(neigh->parms);
721
Joe Perchesd5d427c2013-04-15 15:17:19 +0000722 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000725 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900727EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728
729/* Neighbour state is suspicious;
730 disable fast path.
731
732 Called with write_locked neigh.
733 */
734static void neigh_suspect(struct neighbour *neigh)
735{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000736 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739}
740
741/* Neighbour state is OK;
742 enable fast path.
743
744 Called with write_locked neigh.
745 */
746static void neigh_connect(struct neighbour *neigh)
747{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000748 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751}
752
Eric Dumazete4c4e442009-07-30 03:15:07 +0000753static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000755 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700756 struct neighbour *n;
757 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000758 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000759 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
762
Eric Dumazete4c4e442009-07-30 03:15:07 +0000763 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000764 nht = rcu_dereference_protected(tbl->nht,
765 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000767 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
768 goto out;
769
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 /*
771 * periodically recompute ReachableTime from random function
772 */
773
Eric Dumazete4c4e442009-07-30 03:15:07 +0000774 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000776 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 for (p = &tbl->parms; p; p = p->next)
778 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100779 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 }
781
David S. Millercd089332011-07-11 01:28:12 -0700782 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000783 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Eric Dumazet767e97e2010-10-06 17:49:21 -0700785 while ((n = rcu_dereference_protected(*np,
786 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000787 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 state = n->nud_state;
792 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
793 write_unlock(&n->lock);
794 goto next_elt;
795 }
796
797 if (time_before(n->used, n->confirmed))
798 n->used = n->confirmed;
799
800 if (atomic_read(&n->refcnt) == 1 &&
801 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100802 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000803 *np = n->next;
804 n->dead = 1;
805 write_unlock(&n->lock);
806 neigh_cleanup_and_release(n);
807 continue;
808 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
811next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000812 np = &n->next;
813 }
814 /*
815 * It's fine to release lock here, even if hash table
816 * grows while we are preempted.
817 */
818 write_unlock_bh(&tbl->lock);
819 cond_resched();
820 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500821 nht = rcu_dereference_protected(tbl->nht,
822 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000824out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100825 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
826 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
827 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 */
Eric Dumazete4c4e442009-07-30 03:15:07 +0000829 schedule_delayed_work(&tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100830 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000831 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832}
833
834static __inline__ int neigh_max_probes(struct neighbour *n)
835{
836 struct neigh_parms *p = n->parms;
Eric Dumazeta02cec22010-09-22 20:43:57 +0000837 return (n->nud_state & NUD_PROBE) ?
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100838 NEIGH_VAR(p, UCAST_PROBES) :
839 NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
840 NEIGH_VAR(p, MCAST_PROBES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841}
842
Timo Teras5ef12d92009-06-11 04:16:28 -0700843static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000844 __releases(neigh->lock)
845 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700846{
847 struct sk_buff *skb;
848
849 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000850 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700851 neigh->updated = jiffies;
852
853 /* It is very thin place. report_unreachable is very complicated
854 routine. Particularly, it can hit the same neighbour entry!
855
856 So that, we try to be accurate and avoid dead loop. --ANK
857 */
858 while (neigh->nud_state == NUD_FAILED &&
859 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
860 write_unlock(&neigh->lock);
861 neigh->ops->error_report(neigh, skb);
862 write_lock(&neigh->lock);
863 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700864 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000865 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700866}
867
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000868static void neigh_probe(struct neighbour *neigh)
869 __releases(neigh->lock)
870{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200871 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000872 /* keep skb alive even if arp_queue overflows */
873 if (skb)
874 skb = skb_copy(skb, GFP_ATOMIC);
875 write_unlock(&neigh->lock);
876 neigh->ops->solicit(neigh, skb);
877 atomic_inc(&neigh->probes);
878 kfree_skb(skb);
879}
880
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881/* Called when a timer expires for a neighbour entry. */
882
883static void neigh_timer_handler(unsigned long arg)
884{
885 unsigned long now, next;
886 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000887 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 int notify = 0;
889
890 write_lock(&neigh->lock);
891
892 state = neigh->nud_state;
893 now = jiffies;
894 next = now + HZ;
895
David S. Miller045f7b32011-11-01 17:45:55 -0400896 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
899 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900900 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000902 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 next = neigh->confirmed + neigh->parms->reachable_time;
904 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100905 neigh->used +
906 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000907 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800909 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100911 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000913 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800915 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700917 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900920 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100921 neigh->confirmed +
922 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000923 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800925 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700927 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 next = neigh->confirmed + neigh->parms->reachable_time;
929 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000930 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800932 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100934 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
936 } else {
937 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100938 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 }
940
941 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
942 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 neigh->nud_state = NUD_FAILED;
944 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700945 neigh_invalidate(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 }
947
948 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 if (time_before(next, jiffies + HZ/2))
950 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000951 if (!mod_timer(&neigh->timer, next))
952 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 }
954 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000955 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800956 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800957out:
David S. Miller9ff56602008-02-17 18:39:54 -0800958 write_unlock(&neigh->lock);
959 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
Thomas Grafd961db32007-08-08 23:12:56 -0700961 if (notify)
962 neigh_update_notify(neigh);
963
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 neigh_release(neigh);
965}
966
967int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
968{
969 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000970 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971
972 write_lock_bh(&neigh->lock);
973
974 rc = 0;
975 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
976 goto out_unlock_bh;
977
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100979 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
980 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000981 unsigned long next, now = jiffies;
982
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100983 atomic_set(&neigh->probes,
984 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000986 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100987 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
988 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000989 neigh_add_timer(neigh, next);
990 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 } else {
992 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800993 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 write_unlock_bh(&neigh->lock);
995
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000996 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 return 1;
998 }
999 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001000 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001002 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001003 neigh_add_timer(neigh, jiffies +
1004 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 }
1006
1007 if (neigh->nud_state == NUD_INCOMPLETE) {
1008 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001009 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001010 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001011 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001012
David S. Millerf72051b2008-09-23 01:11:18 -07001013 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001014 if (!buff)
1015 break;
1016 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001018 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001020 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001022 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 }
1024 rc = 1;
1025 }
1026out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001027 if (immediate_probe)
1028 neigh_probe(neigh);
1029 else
1030 write_unlock(&neigh->lock);
1031 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 return rc;
1033}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001034EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
David S. Millerf6b72b62011-07-14 07:53:20 -07001036static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
1038 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001039 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001040 = NULL;
1041
1042 if (neigh->dev->header_ops)
1043 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001046 hh = &neigh->hh;
1047 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001048 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001050 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052 }
1053}
1054
1055
1056
1057/* Generic update routine.
1058 -- lladdr is new lladdr or NULL, if it is not supplied.
1059 -- new is new state.
1060 -- flags
1061 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1062 if it is different.
1063 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001064 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 if it is different.
1066 It also allows to retain current state
1067 if lladdr is unchanged.
1068 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1069
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001070 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 NTF_ROUTER flag.
1072 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1073 a router.
1074
1075 Caller MUST hold reference count on the entry.
1076 */
1077
1078int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1079 u32 flags)
1080{
1081 u8 old;
1082 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 struct net_device *dev;
1085 int update_isrouter = 0;
1086
1087 write_lock_bh(&neigh->lock);
1088
1089 dev = neigh->dev;
1090 old = neigh->nud_state;
1091 err = -EPERM;
1092
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001093 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 (old & (NUD_NOARP | NUD_PERMANENT)))
1095 goto out;
1096
1097 if (!(new & NUD_VALID)) {
1098 neigh_del_timer(neigh);
1099 if (old & NUD_CONNECTED)
1100 neigh_suspect(neigh);
1101 neigh->nud_state = new;
1102 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001104 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1105 (new & NUD_FAILED)) {
1106 neigh_invalidate(neigh);
1107 notify = 1;
1108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 goto out;
1110 }
1111
1112 /* Compare new lladdr with cached one */
1113 if (!dev->addr_len) {
1114 /* First case: device needs no address. */
1115 lladdr = neigh->ha;
1116 } else if (lladdr) {
1117 /* The second case: if something is already cached
1118 and a new address is proposed:
1119 - compare new & old
1120 - if they are different, check override flag
1121 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001122 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 !memcmp(lladdr, neigh->ha, dev->addr_len))
1124 lladdr = neigh->ha;
1125 } else {
1126 /* No address is supplied; if we know something,
1127 use it, otherwise discard the request.
1128 */
1129 err = -EINVAL;
1130 if (!(old & NUD_VALID))
1131 goto out;
1132 lladdr = neigh->ha;
1133 }
1134
1135 if (new & NUD_CONNECTED)
1136 neigh->confirmed = jiffies;
1137 neigh->updated = jiffies;
1138
1139 /* If entry was valid and address is not changed,
1140 do not change entry state, if new one is STALE.
1141 */
1142 err = 0;
1143 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1144 if (old & NUD_VALID) {
1145 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1146 update_isrouter = 0;
1147 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1148 (old & NUD_CONNECTED)) {
1149 lladdr = neigh->ha;
1150 new = NUD_STALE;
1151 } else
1152 goto out;
1153 } else {
1154 if (lladdr == neigh->ha && new == NUD_STALE &&
1155 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1156 (old & NUD_CONNECTED))
1157 )
1158 new = old;
1159 }
1160 }
1161
1162 if (new != old) {
1163 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001164 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001165 neigh_add_timer(neigh, (jiffies +
1166 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001167 neigh->parms->reachable_time :
1168 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 neigh->nud_state = new;
1170 }
1171
1172 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001173 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001175 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001176 neigh_update_hhs(neigh);
1177 if (!(new & NUD_CONNECTED))
1178 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001179 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 }
1182 if (new == old)
1183 goto out;
1184 if (new & NUD_CONNECTED)
1185 neigh_connect(neigh);
1186 else
1187 neigh_suspect(neigh);
1188 if (!(old & NUD_VALID)) {
1189 struct sk_buff *skb;
1190
1191 /* Again: avoid dead loop if something went wrong */
1192
1193 while (neigh->nud_state & NUD_VALID &&
1194 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001195 struct dst_entry *dst = skb_dst(skb);
1196 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001198
1199 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001200
1201 /* Why not just use 'neigh' as-is? The problem is that
1202 * things such as shaper, eql, and sch_teql can end up
1203 * using alternative, different, neigh objects to output
1204 * the packet in the output path. So what we need to do
1205 * here is re-lookup the top-level neigh in the path so
1206 * we can reinject the packet there.
1207 */
1208 n2 = NULL;
1209 if (dst) {
1210 n2 = dst_neigh_lookup_skb(dst, skb);
1211 if (n2)
1212 n1 = n2;
1213 }
David S. Miller8f40b162011-07-17 13:34:11 -07001214 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001215 if (n2)
1216 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001217 rcu_read_unlock();
1218
Linus Torvalds1da177e2005-04-16 15:20:36 -07001219 write_lock_bh(&neigh->lock);
1220 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001221 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001222 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
1224out:
1225 if (update_isrouter) {
1226 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1227 (neigh->flags | NTF_ROUTER) :
1228 (neigh->flags & ~NTF_ROUTER);
1229 }
1230 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001231
1232 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001233 neigh_update_notify(neigh);
1234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 return err;
1236}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001237EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238
1239struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1240 u8 *lladdr, void *saddr,
1241 struct net_device *dev)
1242{
1243 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1244 lladdr || !dev->addr_len);
1245 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001246 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 NEIGH_UPDATE_F_OVERRIDE);
1248 return neigh;
1249}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001250EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Eric Dumazet34d101d2010-10-11 09:16:57 -07001252/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001253static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001256 __be16 prot = dst->ops->protocol;
1257 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001258
1259 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001260
David S. Millerf6b72b62011-07-14 07:53:20 -07001261 /* Only one thread can come in here and initialize the
1262 * hh_cache entry.
1263 */
David S. Millerb23b5452011-07-16 17:45:02 -07001264 if (!hh->hh_len)
1265 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001266
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001267 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268}
1269
1270/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001271 * worked, f.e. if you want to override normal output path (eql, shaper),
1272 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 */
1274
David S. Miller8f40b162011-07-17 13:34:11 -07001275int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
1277 struct net_device *dev = skb->dev;
1278
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001279 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001281 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1282 skb->len) < 0 &&
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001283 dev->header_ops->rebuild(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284 return 0;
1285
1286 return dev_queue_xmit(skb);
1287}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001288EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
1290/* Slow and careful. */
1291
David S. Miller8f40b162011-07-17 13:34:11 -07001292int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293{
Eric Dumazetadf30902009-06-02 05:19:30 +00001294 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 int rc = 0;
1296
David S. Miller8f40b162011-07-17 13:34:11 -07001297 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 goto discard;
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 if (!neigh_event_send(neigh, skb)) {
1301 int err;
1302 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001303 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001304
David S. Millerf6b72b62011-07-14 07:53:20 -07001305 if (dev->header_ops->cache && !neigh->hh.hh_len)
1306 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001307
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001308 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001309 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001310 seq = read_seqbegin(&neigh->ha_lock);
1311 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1312 neigh->ha, NULL, skb->len);
1313 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001316 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 else
1318 goto out_kfree_skb;
1319 }
1320out:
1321 return rc;
1322discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001323 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324out_kfree_skb:
1325 rc = -EINVAL;
1326 kfree_skb(skb);
1327 goto out;
1328}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001329EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
1331/* As fast as possible without hh cache */
1332
David S. Miller8f40b162011-07-17 13:34:11 -07001333int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001336 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001337 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001339 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001340 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001341 seq = read_seqbegin(&neigh->ha_lock);
1342 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1343 neigh->ha, NULL, skb->len);
1344 } while (read_seqretry(&neigh->ha_lock, seq));
1345
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001347 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 else {
1349 err = -EINVAL;
1350 kfree_skb(skb);
1351 }
1352 return err;
1353}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001354EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355
David S. Miller8f40b162011-07-17 13:34:11 -07001356int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1357{
1358 return dev_queue_xmit(skb);
1359}
1360EXPORT_SYMBOL(neigh_direct_output);
1361
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362static void neigh_proxy_process(unsigned long arg)
1363{
1364 struct neigh_table *tbl = (struct neigh_table *)arg;
1365 long sched_next = 0;
1366 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001367 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
1369 spin_lock(&tbl->proxy_queue.lock);
1370
David S. Millerf72051b2008-09-23 01:11:18 -07001371 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1372 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001375 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001376
David S. Millerf72051b2008-09-23 01:11:18 -07001377 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001378 if (tbl->proxy_redo && netif_running(dev)) {
1379 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001380 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001381 rcu_read_unlock();
1382 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001383 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001384 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386 dev_put(dev);
1387 } else if (!sched_next || tdif < sched_next)
1388 sched_next = tdif;
1389 }
1390 del_timer(&tbl->proxy_timer);
1391 if (sched_next)
1392 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1393 spin_unlock(&tbl->proxy_queue.lock);
1394}
1395
1396void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1397 struct sk_buff *skb)
1398{
1399 unsigned long now = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001400 unsigned long sched_next = now + (net_random() %
1401 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001403 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 kfree_skb(skb);
1405 return;
1406 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001407
1408 NEIGH_CB(skb)->sched_next = sched_next;
1409 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410
1411 spin_lock(&tbl->proxy_queue.lock);
1412 if (del_timer(&tbl->proxy_timer)) {
1413 if (time_before(tbl->proxy_timer.expires, sched_next))
1414 sched_next = tbl->proxy_timer.expires;
1415 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001416 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 dev_hold(skb->dev);
1418 __skb_queue_tail(&tbl->proxy_queue, skb);
1419 mod_timer(&tbl->proxy_timer, sched_next);
1420 spin_unlock(&tbl->proxy_queue.lock);
1421}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001422EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001423
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001424static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001425 struct net *net, int ifindex)
1426{
1427 struct neigh_parms *p;
1428
1429 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001430 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001431 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001432 return p;
1433 }
1434
1435 return NULL;
1436}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
1438struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1439 struct neigh_table *tbl)
1440{
Gao fengcf89d6b2013-06-20 10:01:32 +08001441 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001442 struct net *net = dev_net(dev);
1443 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
Gao fengcf89d6b2013-06-20 10:01:32 +08001445 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 p->tbl = tbl;
1448 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001450 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001451 dev_hold(dev);
1452 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001453 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001455
1456 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1457 release_net(net);
1458 dev_put(dev);
1459 kfree(p);
1460 return NULL;
1461 }
1462
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 write_lock_bh(&tbl->lock);
1464 p->next = tbl->parms.next;
1465 tbl->parms.next = p;
1466 write_unlock_bh(&tbl->lock);
1467 }
1468 return p;
1469}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001470EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472static void neigh_rcu_free_parms(struct rcu_head *head)
1473{
1474 struct neigh_parms *parms =
1475 container_of(head, struct neigh_parms, rcu_head);
1476
1477 neigh_parms_put(parms);
1478}
1479
1480void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1481{
1482 struct neigh_parms **p;
1483
1484 if (!parms || parms == &tbl->parms)
1485 return;
1486 write_lock_bh(&tbl->lock);
1487 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1488 if (*p == parms) {
1489 *p = parms->next;
1490 parms->dead = 1;
1491 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001492 if (parms->dev)
1493 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1495 return;
1496 }
1497 }
1498 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001499 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001501EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
Denis V. Lunev06f05112008-01-24 00:30:58 -08001503static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001505 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 kfree(parms);
1507}
1508
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001509static struct lock_class_key neigh_table_proxy_queue_class;
1510
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001511static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512{
1513 unsigned long now = jiffies;
1514 unsigned long phsize;
1515
Eric Dumazete42ea982008-11-12 00:54:54 -08001516 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001519 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 tbl->stats = alloc_percpu(struct neigh_statistics);
1522 if (!tbl->stats)
1523 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001524
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001526 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1527 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529#endif
1530
David S. Millercd089332011-07-11 01:28:12 -07001531 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532
1533 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001534 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001536 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 panic("cannot allocate neighbour cache hashes");
1538
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001539 if (!tbl->entry_size)
1540 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1541 tbl->key_len, NEIGH_PRIV_ALIGN);
1542 else
1543 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1544
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001546 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
Eric Dumazete4c4e442009-07-30 03:15:07 +00001547 schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001548 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001549 skb_queue_head_init_class(&tbl->proxy_queue,
1550 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 tbl->last_flush = now;
1553 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001554}
1555
1556void neigh_table_init(struct neigh_table *tbl)
1557{
1558 struct neigh_table *tmp;
1559
1560 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001562 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1563 if (tmp->family == tbl->family)
1564 break;
1565 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 tbl->next = neigh_tables;
1567 neigh_tables = tbl;
1568 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001569
1570 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001571 pr_err("Registering multiple tables for family %d\n",
1572 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001573 dump_stack();
1574 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001576EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
1578int neigh_table_clear(struct neigh_table *tbl)
1579{
1580 struct neigh_table **tp;
1581
1582 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001583 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584 del_timer_sync(&tbl->proxy_timer);
1585 pneigh_queue_purge(&tbl->proxy_queue);
1586 neigh_ifdown(tbl, NULL);
1587 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001588 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589 write_lock(&neigh_tbl_lock);
1590 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1591 if (*tp == tbl) {
1592 *tp = tbl->next;
1593 break;
1594 }
1595 }
1596 write_unlock(&neigh_tbl_lock);
1597
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001598 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1599 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001600 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 kfree(tbl->phash_buckets);
1603 tbl->phash_buckets = NULL;
1604
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001605 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1606
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001607 free_percpu(tbl->stats);
1608 tbl->stats = NULL;
1609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 return 0;
1611}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001612EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
Thomas Graf661d2962013-03-21 07:45:29 +00001614static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001616 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001617 struct ndmsg *ndm;
1618 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001619 struct neigh_table *tbl;
1620 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001621 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622
Eric Dumazet110b2492010-10-04 04:27:36 +00001623 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001624 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 goto out;
1626
Thomas Grafa14a49d2006-08-07 17:53:08 -07001627 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1628 if (dst_attr == NULL)
1629 goto out;
1630
1631 ndm = nlmsg_data(nlh);
1632 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001633 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001634 if (dev == NULL) {
1635 err = -ENODEV;
1636 goto out;
1637 }
1638 }
1639
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 read_lock(&neigh_tbl_lock);
1641 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001642 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
1644 if (tbl->family != ndm->ndm_family)
1645 continue;
1646 read_unlock(&neigh_tbl_lock);
1647
Thomas Grafa14a49d2006-08-07 17:53:08 -07001648 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001649 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650
1651 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001652 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001653 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 }
1655
Thomas Grafa14a49d2006-08-07 17:53:08 -07001656 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001657 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658
Thomas Grafa14a49d2006-08-07 17:53:08 -07001659 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1660 if (neigh == NULL) {
1661 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001662 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001664
1665 err = neigh_update(neigh, NULL, NUD_FAILED,
1666 NEIGH_UPDATE_F_OVERRIDE |
1667 NEIGH_UPDATE_F_ADMIN);
1668 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001669 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670 }
1671 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001672 err = -EAFNOSUPPORT;
1673
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674out:
1675 return err;
1676}
1677
Thomas Graf661d2962013-03-21 07:45:29 +00001678static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001680 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001681 struct ndmsg *ndm;
1682 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683 struct neigh_table *tbl;
1684 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001685 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
Eric Dumazet110b2492010-10-04 04:27:36 +00001687 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001688 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1689 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 goto out;
1691
Thomas Graf5208deb2006-08-07 17:55:40 -07001692 err = -EINVAL;
1693 if (tb[NDA_DST] == NULL)
1694 goto out;
1695
1696 ndm = nlmsg_data(nlh);
1697 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001698 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001699 if (dev == NULL) {
1700 err = -ENODEV;
1701 goto out;
1702 }
1703
1704 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001705 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001706 }
1707
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708 read_lock(&neigh_tbl_lock);
1709 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001710 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1711 struct neighbour *neigh;
1712 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
1714 if (tbl->family != ndm->ndm_family)
1715 continue;
1716 read_unlock(&neigh_tbl_lock);
1717
Thomas Graf5208deb2006-08-07 17:55:40 -07001718 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001719 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001720 dst = nla_data(tb[NDA_DST]);
1721 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
1723 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001724 struct pneigh_entry *pn;
1725
1726 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001727 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001728 if (pn) {
1729 pn->flags = ndm->ndm_flags;
1730 err = 0;
1731 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001732 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733 }
1734
Thomas Graf5208deb2006-08-07 17:55:40 -07001735 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001736 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001737
1738 neigh = neigh_lookup(tbl, dst, dev);
1739 if (neigh == NULL) {
1740 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1741 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001742 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001743 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001744
Thomas Graf5208deb2006-08-07 17:55:40 -07001745 neigh = __neigh_lookup_errno(tbl, dst, dev);
1746 if (IS_ERR(neigh)) {
1747 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001748 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001749 }
1750 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1752 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001753 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001754 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001755 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001756
1757 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1758 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 }
1760
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001761 if (ndm->ndm_flags & NTF_USE) {
1762 neigh_event_send(neigh, NULL);
1763 err = 0;
1764 } else
1765 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001766 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001767 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768 }
1769
1770 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001771 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772out:
1773 return err;
1774}
1775
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001776static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1777{
Thomas Grafca860fb2006-08-07 18:00:18 -07001778 struct nlattr *nest;
1779
1780 nest = nla_nest_start(skb, NDTA_PARMS);
1781 if (nest == NULL)
1782 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001783
David S. Miller9a6308d2012-04-01 20:06:28 -04001784 if ((parms->dev &&
1785 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1786 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001787 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1788 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001789 /* approximative value for deprecated QUEUE_LEN (in packets) */
1790 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001791 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1792 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1793 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1794 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1795 NEIGH_VAR(parms, UCAST_PROBES)) ||
1796 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1797 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001798 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1799 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001800 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1801 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1802 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001803 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001804 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1805 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1806 NEIGH_VAR(parms, RETRANS_TIME)) ||
1807 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1808 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1809 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1810 NEIGH_VAR(parms, PROXY_DELAY)) ||
1811 nla_put_msecs(skb, NDTPA_LOCKTIME,
1812 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001813 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001814 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001815
Thomas Grafca860fb2006-08-07 18:00:18 -07001816nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001817 nla_nest_cancel(skb, nest);
1818 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001819}
1820
Thomas Grafca860fb2006-08-07 18:00:18 -07001821static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1822 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001823{
1824 struct nlmsghdr *nlh;
1825 struct ndtmsg *ndtmsg;
1826
Thomas Grafca860fb2006-08-07 18:00:18 -07001827 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1828 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001829 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001830
Thomas Grafca860fb2006-08-07 18:00:18 -07001831 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001832
1833 read_lock_bh(&tbl->lock);
1834 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001835 ndtmsg->ndtm_pad1 = 0;
1836 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001837
David S. Miller9a6308d2012-04-01 20:06:28 -04001838 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1839 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1840 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1841 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1842 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1843 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844 {
1845 unsigned long now = jiffies;
1846 unsigned int flush_delta = now - tbl->last_flush;
1847 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001848 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001849 struct ndt_config ndc = {
1850 .ndtc_key_len = tbl->key_len,
1851 .ndtc_entry_size = tbl->entry_size,
1852 .ndtc_entries = atomic_read(&tbl->entries),
1853 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1854 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1856 };
1857
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001858 rcu_read_lock_bh();
1859 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001860 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001861 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001862 rcu_read_unlock_bh();
1863
David S. Miller9a6308d2012-04-01 20:06:28 -04001864 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1865 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001866 }
1867
1868 {
1869 int cpu;
1870 struct ndt_stats ndst;
1871
1872 memset(&ndst, 0, sizeof(ndst));
1873
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001874 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001875 struct neigh_statistics *st;
1876
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001877 st = per_cpu_ptr(tbl->stats, cpu);
1878 ndst.ndts_allocs += st->allocs;
1879 ndst.ndts_destroys += st->destroys;
1880 ndst.ndts_hash_grows += st->hash_grows;
1881 ndst.ndts_res_failed += st->res_failed;
1882 ndst.ndts_lookups += st->lookups;
1883 ndst.ndts_hits += st->hits;
1884 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1885 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1886 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1887 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1888 }
1889
David S. Miller9a6308d2012-04-01 20:06:28 -04001890 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1891 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001892 }
1893
1894 BUG_ON(tbl->parms.dev);
1895 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001896 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001897
1898 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001899 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001900
Thomas Grafca860fb2006-08-07 18:00:18 -07001901nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001902 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001903 nlmsg_cancel(skb, nlh);
1904 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001905}
1906
Thomas Grafca860fb2006-08-07 18:00:18 -07001907static int neightbl_fill_param_info(struct sk_buff *skb,
1908 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001909 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001910 u32 pid, u32 seq, int type,
1911 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001912{
1913 struct ndtmsg *ndtmsg;
1914 struct nlmsghdr *nlh;
1915
Thomas Grafca860fb2006-08-07 18:00:18 -07001916 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1917 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001918 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001919
Thomas Grafca860fb2006-08-07 18:00:18 -07001920 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921
1922 read_lock_bh(&tbl->lock);
1923 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001924 ndtmsg->ndtm_pad1 = 0;
1925 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001926
Thomas Grafca860fb2006-08-07 18:00:18 -07001927 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1928 neightbl_fill_parms(skb, parms) < 0)
1929 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930
1931 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001932 return nlmsg_end(skb, nlh);
1933errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001934 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001935 nlmsg_cancel(skb, nlh);
1936 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001938
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001939static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001940 [NDTA_NAME] = { .type = NLA_STRING },
1941 [NDTA_THRESH1] = { .type = NLA_U32 },
1942 [NDTA_THRESH2] = { .type = NLA_U32 },
1943 [NDTA_THRESH3] = { .type = NLA_U32 },
1944 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1945 [NDTA_PARMS] = { .type = NLA_NESTED },
1946};
1947
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001948static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001949 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1950 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1951 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1952 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1953 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1954 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1955 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1956 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1957 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1958 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1959 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1960 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1961 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1962};
1963
Thomas Graf661d2962013-03-21 07:45:29 +00001964static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001965{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001966 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001968 struct ndtmsg *ndtmsg;
1969 struct nlattr *tb[NDTA_MAX+1];
1970 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001971
Thomas Graf6b3f8672006-08-07 17:58:53 -07001972 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1973 nl_neightbl_policy);
1974 if (err < 0)
1975 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001976
Thomas Graf6b3f8672006-08-07 17:58:53 -07001977 if (tb[NDTA_NAME] == NULL) {
1978 err = -EINVAL;
1979 goto errout;
1980 }
1981
1982 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001983 read_lock(&neigh_tbl_lock);
1984 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1985 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1986 continue;
1987
Thomas Graf6b3f8672006-08-07 17:58:53 -07001988 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001989 break;
1990 }
1991
1992 if (tbl == NULL) {
1993 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001994 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001995 }
1996
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001997 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001998 * We acquire tbl->lock to be nice to the periodic timers and
1999 * make sure they always see a consistent set of values.
2000 */
2001 write_lock_bh(&tbl->lock);
2002
Thomas Graf6b3f8672006-08-07 17:58:53 -07002003 if (tb[NDTA_PARMS]) {
2004 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002005 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002006 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002007
Thomas Graf6b3f8672006-08-07 17:58:53 -07002008 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2009 nl_ntbl_parm_policy);
2010 if (err < 0)
2011 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 if (tbp[NDTPA_IFINDEX])
2014 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002015
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002016 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002017 if (p == NULL) {
2018 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002019 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002020 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002021
Thomas Graf6b3f8672006-08-07 17:58:53 -07002022 for (i = 1; i <= NDTPA_MAX; i++) {
2023 if (tbp[i] == NULL)
2024 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002025
Thomas Graf6b3f8672006-08-07 17:58:53 -07002026 switch (i) {
2027 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002028 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2029 nla_get_u32(tbp[i]) *
2030 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002031 break;
2032 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002033 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2034 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002035 break;
2036 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002037 NEIGH_VAR_SET(p, PROXY_QLEN,
2038 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002039 break;
2040 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002041 NEIGH_VAR_SET(p, APP_PROBES,
2042 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 break;
2044 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002045 NEIGH_VAR_SET(p, UCAST_PROBES,
2046 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002047 break;
2048 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002049 NEIGH_VAR_SET(p, MCAST_PROBES,
2050 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002051 break;
2052 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002053 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2054 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002055 break;
2056 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002057 NEIGH_VAR_SET(p, GC_STALETIME,
2058 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 break;
2060 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002061 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2062 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 break;
2064 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002065 NEIGH_VAR_SET(p, RETRANS_TIME,
2066 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067 break;
2068 case NDTPA_ANYCAST_DELAY:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002069 NEIGH_VAR_SET(p, ANYCAST_DELAY, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002070 break;
2071 case NDTPA_PROXY_DELAY:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002072 NEIGH_VAR_SET(p, PROXY_DELAY, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002073 break;
2074 case NDTPA_LOCKTIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002075 NEIGH_VAR_SET(p, LOCKTIME, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 }
2078 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002079 }
2080
Gao fengdc25c672013-06-20 10:01:34 +08002081 err = -ENOENT;
2082 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2083 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2084 !net_eq(net, &init_net))
2085 goto errout_tbl_lock;
2086
Thomas Graf6b3f8672006-08-07 17:58:53 -07002087 if (tb[NDTA_THRESH1])
2088 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2089
2090 if (tb[NDTA_THRESH2])
2091 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2092
2093 if (tb[NDTA_THRESH3])
2094 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2095
2096 if (tb[NDTA_GC_INTERVAL])
2097 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2098
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002099 err = 0;
2100
Thomas Graf6b3f8672006-08-07 17:58:53 -07002101errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002102 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002103errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002104 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002105errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002106 return err;
2107}
2108
Thomas Grafc8822a42007-03-22 11:50:06 -07002109static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002110{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002111 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002112 int family, tidx, nidx = 0;
2113 int tbl_skip = cb->args[0];
2114 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002115 struct neigh_table *tbl;
2116
Thomas Grafca860fb2006-08-07 18:00:18 -07002117 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002118
2119 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002120 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002121 struct neigh_parms *p;
2122
Thomas Grafca860fb2006-08-07 18:00:18 -07002123 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002124 continue;
2125
Eric W. Biederman15e47302012-09-07 20:12:54 +00002126 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002127 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2128 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002129 break;
2130
Eric W. Biederman426b5302008-01-24 00:13:18 -08002131 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002132 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002133 continue;
2134
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002135 if (nidx < neigh_skip)
2136 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002137
Thomas Grafca860fb2006-08-07 18:00:18 -07002138 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002139 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002140 cb->nlh->nlmsg_seq,
2141 RTM_NEWNEIGHTBL,
2142 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002143 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002144 next:
2145 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146 }
2147
Thomas Grafca860fb2006-08-07 18:00:18 -07002148 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002149 }
2150out:
2151 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002152 cb->args[0] = tidx;
2153 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002154
2155 return skb->len;
2156}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157
Thomas Graf8b8aec52006-08-07 17:56:37 -07002158static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2159 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160{
2161 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002163 struct nlmsghdr *nlh;
2164 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165
Thomas Graf8b8aec52006-08-07 17:56:37 -07002166 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2167 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002168 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002169
2170 ndm = nlmsg_data(nlh);
2171 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002172 ndm->ndm_pad1 = 0;
2173 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002174 ndm->ndm_flags = neigh->flags;
2175 ndm->ndm_type = neigh->type;
2176 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177
David S. Miller9a6308d2012-04-01 20:06:28 -04002178 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2179 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002180
2181 read_lock_bh(&neigh->lock);
2182 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002183 if (neigh->nud_state & NUD_VALID) {
2184 char haddr[MAX_ADDR_LEN];
2185
2186 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2187 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2188 read_unlock_bh(&neigh->lock);
2189 goto nla_put_failure;
2190 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002191 }
2192
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002193 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2194 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2195 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002196 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2197 read_unlock_bh(&neigh->lock);
2198
David S. Miller9a6308d2012-04-01 20:06:28 -04002199 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2200 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2201 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002202
2203 return nlmsg_end(skb, nlh);
2204
2205nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002206 nlmsg_cancel(skb, nlh);
2207 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208}
2209
Tony Zelenoff84920c12012-01-26 22:28:58 +00002210static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2211 u32 pid, u32 seq, int type, unsigned int flags,
2212 struct neigh_table *tbl)
2213{
2214 struct nlmsghdr *nlh;
2215 struct ndmsg *ndm;
2216
2217 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2218 if (nlh == NULL)
2219 return -EMSGSIZE;
2220
2221 ndm = nlmsg_data(nlh);
2222 ndm->ndm_family = tbl->family;
2223 ndm->ndm_pad1 = 0;
2224 ndm->ndm_pad2 = 0;
2225 ndm->ndm_flags = pn->flags | NTF_PROXY;
2226 ndm->ndm_type = NDA_DST;
2227 ndm->ndm_ifindex = pn->dev->ifindex;
2228 ndm->ndm_state = NUD_NONE;
2229
David S. Miller9a6308d2012-04-01 20:06:28 -04002230 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2231 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002232
2233 return nlmsg_end(skb, nlh);
2234
2235nla_put_failure:
2236 nlmsg_cancel(skb, nlh);
2237 return -EMSGSIZE;
2238}
2239
Thomas Grafd961db32007-08-08 23:12:56 -07002240static void neigh_update_notify(struct neighbour *neigh)
2241{
2242 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2243 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2244}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245
2246static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2247 struct netlink_callback *cb)
2248{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002249 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 struct neighbour *n;
2251 int rc, h, s_h = cb->args[1];
2252 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002253 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002255 rcu_read_lock_bh();
2256 nht = rcu_dereference_bh(tbl->nht);
2257
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002258 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002259 if (h > s_h)
2260 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002261 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2262 n != NULL;
2263 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002264 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002265 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002266 if (idx < s_idx)
2267 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002268 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002270 RTM_NEWNEIGH,
2271 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 rc = -1;
2273 goto out;
2274 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002275next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002276 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278 }
2279 rc = skb->len;
2280out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002281 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282 cb->args[1] = h;
2283 cb->args[2] = idx;
2284 return rc;
2285}
2286
Tony Zelenoff84920c12012-01-26 22:28:58 +00002287static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2288 struct netlink_callback *cb)
2289{
2290 struct pneigh_entry *n;
2291 struct net *net = sock_net(skb->sk);
2292 int rc, h, s_h = cb->args[3];
2293 int idx, s_idx = idx = cb->args[4];
2294
2295 read_lock_bh(&tbl->lock);
2296
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002297 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002298 if (h > s_h)
2299 s_idx = 0;
2300 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2301 if (dev_net(n->dev) != net)
2302 continue;
2303 if (idx < s_idx)
2304 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002305 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002306 cb->nlh->nlmsg_seq,
2307 RTM_NEWNEIGH,
2308 NLM_F_MULTI, tbl) <= 0) {
2309 read_unlock_bh(&tbl->lock);
2310 rc = -1;
2311 goto out;
2312 }
2313 next:
2314 idx++;
2315 }
2316 }
2317
2318 read_unlock_bh(&tbl->lock);
2319 rc = skb->len;
2320out:
2321 cb->args[3] = h;
2322 cb->args[4] = idx;
2323 return rc;
2324
2325}
2326
Thomas Grafc8822a42007-03-22 11:50:06 -07002327static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002328{
2329 struct neigh_table *tbl;
2330 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002331 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002332 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333
2334 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002335 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002336
2337 /* check for full ndmsg structure presence, family member is
2338 * the same for both structures
2339 */
2340 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2341 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2342 proxy = 1;
2343
Linus Torvalds1da177e2005-04-16 15:20:36 -07002344 s_t = cb->args[0];
2345
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002346 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002347 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 if (t < s_t || (family && tbl->family != family))
2349 continue;
2350 if (t > s_t)
2351 memset(&cb->args[1], 0, sizeof(cb->args) -
2352 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002353 if (proxy)
2354 err = pneigh_dump_table(tbl, skb, cb);
2355 else
2356 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002357 if (err < 0)
2358 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 }
2360 read_unlock(&neigh_tbl_lock);
2361
2362 cb->args[0] = t;
2363 return skb->len;
2364}
2365
2366void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2367{
2368 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002369 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002371 rcu_read_lock_bh();
2372 nht = rcu_dereference_bh(tbl->nht);
2373
Eric Dumazet767e97e2010-10-06 17:49:21 -07002374 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002375 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376 struct neighbour *n;
2377
Eric Dumazet767e97e2010-10-06 17:49:21 -07002378 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2379 n != NULL;
2380 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 cb(n, cookie);
2382 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002383 read_unlock(&tbl->lock);
2384 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385}
2386EXPORT_SYMBOL(neigh_for_each);
2387
2388/* The tbl->lock must be held as a writer and BH disabled. */
2389void __neigh_for_each_release(struct neigh_table *tbl,
2390 int (*cb)(struct neighbour *))
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 nht = rcu_dereference_protected(tbl->nht,
2396 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002397 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002398 struct neighbour *n;
2399 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002401 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002402 while ((n = rcu_dereference_protected(*np,
2403 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 int release;
2405
2406 write_lock(&n->lock);
2407 release = cb(n);
2408 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002409 rcu_assign_pointer(*np,
2410 rcu_dereference_protected(n->next,
2411 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 n->dead = 1;
2413 } else
2414 np = &n->next;
2415 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002416 if (release)
2417 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418 }
2419 }
2420}
2421EXPORT_SYMBOL(__neigh_for_each_release);
2422
2423#ifdef CONFIG_PROC_FS
2424
2425static struct neighbour *neigh_get_first(struct seq_file *seq)
2426{
2427 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002428 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002429 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 struct neighbour *n = NULL;
2431 int bucket = state->bucket;
2432
2433 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002434 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002435 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
2437 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002438 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002439 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 if (state->neigh_sub_iter) {
2441 loff_t fakep = 0;
2442 void *v;
2443
2444 v = state->neigh_sub_iter(state, n, &fakep);
2445 if (!v)
2446 goto next;
2447 }
2448 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2449 break;
2450 if (n->nud_state & ~NUD_NOARP)
2451 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002452next:
2453 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
2455
2456 if (n)
2457 break;
2458 }
2459 state->bucket = bucket;
2460
2461 return n;
2462}
2463
2464static struct neighbour *neigh_get_next(struct seq_file *seq,
2465 struct neighbour *n,
2466 loff_t *pos)
2467{
2468 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002469 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002470 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
2472 if (state->neigh_sub_iter) {
2473 void *v = state->neigh_sub_iter(state, n, pos);
2474 if (v)
2475 return n;
2476 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002477 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
2479 while (1) {
2480 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002481 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002482 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 if (state->neigh_sub_iter) {
2484 void *v = state->neigh_sub_iter(state, n, pos);
2485 if (v)
2486 return n;
2487 goto next;
2488 }
2489 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2490 break;
2491
2492 if (n->nud_state & ~NUD_NOARP)
2493 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002494next:
2495 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 }
2497
2498 if (n)
2499 break;
2500
David S. Millercd089332011-07-11 01:28:12 -07002501 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 break;
2503
Eric Dumazet767e97e2010-10-06 17:49:21 -07002504 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 }
2506
2507 if (n && pos)
2508 --(*pos);
2509 return n;
2510}
2511
2512static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2513{
2514 struct neighbour *n = neigh_get_first(seq);
2515
2516 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002517 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 while (*pos) {
2519 n = neigh_get_next(seq, n, pos);
2520 if (!n)
2521 break;
2522 }
2523 }
2524 return *pos ? NULL : n;
2525}
2526
2527static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2528{
2529 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002530 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 struct neigh_table *tbl = state->tbl;
2532 struct pneigh_entry *pn = NULL;
2533 int bucket = state->bucket;
2534
2535 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2536 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2537 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002538 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002539 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 if (pn)
2541 break;
2542 }
2543 state->bucket = bucket;
2544
2545 return pn;
2546}
2547
2548static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2549 struct pneigh_entry *pn,
2550 loff_t *pos)
2551{
2552 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002553 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 struct neigh_table *tbl = state->tbl;
2555
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002556 do {
2557 pn = pn->next;
2558 } while (pn && !net_eq(pneigh_net(pn), net));
2559
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 while (!pn) {
2561 if (++state->bucket > PNEIGH_HASHMASK)
2562 break;
2563 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002564 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002565 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (pn)
2567 break;
2568 }
2569
2570 if (pn && pos)
2571 --(*pos);
2572
2573 return pn;
2574}
2575
2576static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2577{
2578 struct pneigh_entry *pn = pneigh_get_first(seq);
2579
2580 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002581 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 while (*pos) {
2583 pn = pneigh_get_next(seq, pn, pos);
2584 if (!pn)
2585 break;
2586 }
2587 }
2588 return *pos ? NULL : pn;
2589}
2590
2591static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2592{
2593 struct neigh_seq_state *state = seq->private;
2594 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002595 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
Chris Larson745e2032008-08-03 01:10:55 -07002597 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002599 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
2601 return rc;
2602}
2603
2604void *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 +00002605 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606{
2607 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 state->tbl = tbl;
2610 state->bucket = 0;
2611 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2612
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002613 rcu_read_lock_bh();
2614 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002615
Chris Larson745e2032008-08-03 01:10:55 -07002616 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617}
2618EXPORT_SYMBOL(neigh_seq_start);
2619
2620void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2621{
2622 struct neigh_seq_state *state;
2623 void *rc;
2624
2625 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002626 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 goto out;
2628 }
2629
2630 state = seq->private;
2631 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2632 rc = neigh_get_next(seq, v, NULL);
2633 if (rc)
2634 goto out;
2635 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2636 rc = pneigh_get_first(seq);
2637 } else {
2638 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2639 rc = pneigh_get_next(seq, v, NULL);
2640 }
2641out:
2642 ++(*pos);
2643 return rc;
2644}
2645EXPORT_SYMBOL(neigh_seq_next);
2646
2647void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002648 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002650 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651}
2652EXPORT_SYMBOL(neigh_seq_stop);
2653
2654/* statistics via seq_file */
2655
2656static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2657{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002658 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 int cpu;
2660
2661 if (*pos == 0)
2662 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002663
Rusty Russell0f23174a2008-12-29 12:23:42 +00002664 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 if (!cpu_possible(cpu))
2666 continue;
2667 *pos = cpu+1;
2668 return per_cpu_ptr(tbl->stats, cpu);
2669 }
2670 return NULL;
2671}
2672
2673static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2674{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002675 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 int cpu;
2677
Rusty Russell0f23174a2008-12-29 12:23:42 +00002678 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 if (!cpu_possible(cpu))
2680 continue;
2681 *pos = cpu+1;
2682 return per_cpu_ptr(tbl->stats, cpu);
2683 }
2684 return NULL;
2685}
2686
2687static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2688{
2689
2690}
2691
2692static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2693{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002694 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 struct neigh_statistics *st = v;
2696
2697 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002698 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 -07002699 return 0;
2700 }
2701
2702 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002703 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 atomic_read(&tbl->entries),
2705
2706 st->allocs,
2707 st->destroys,
2708 st->hash_grows,
2709
2710 st->lookups,
2711 st->hits,
2712
2713 st->res_failed,
2714
2715 st->rcv_probes_mcast,
2716 st->rcv_probes_ucast,
2717
2718 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002719 st->forced_gc_runs,
2720 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 );
2722
2723 return 0;
2724}
2725
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002726static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 .start = neigh_stat_seq_start,
2728 .next = neigh_stat_seq_next,
2729 .stop = neigh_stat_seq_stop,
2730 .show = neigh_stat_seq_show,
2731};
2732
2733static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2734{
2735 int ret = seq_open(file, &neigh_stat_seq_ops);
2736
2737 if (!ret) {
2738 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002739 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
2741 return ret;
2742};
2743
Arjan van de Ven9a321442007-02-12 00:55:35 -08002744static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 .owner = THIS_MODULE,
2746 .open = neigh_stat_seq_open,
2747 .read = seq_read,
2748 .llseek = seq_lseek,
2749 .release = seq_release,
2750};
2751
2752#endif /* CONFIG_PROC_FS */
2753
Thomas Graf339bf982006-11-10 14:10:15 -08002754static inline size_t neigh_nlmsg_size(void)
2755{
2756 return NLMSG_ALIGN(sizeof(struct ndmsg))
2757 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2758 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2759 + nla_total_size(sizeof(struct nda_cacheinfo))
2760 + nla_total_size(4); /* NDA_PROBES */
2761}
2762
Thomas Grafb8673312006-08-15 00:33:14 -07002763static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002765 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002766 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002767 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Thomas Graf339bf982006-11-10 14:10:15 -08002769 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002770 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002771 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
Thomas Grafb8673312006-08-15 00:33:14 -07002773 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002774 if (err < 0) {
2775 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2776 WARN_ON(err == -EMSGSIZE);
2777 kfree_skb(skb);
2778 goto errout;
2779 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002780 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2781 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002782errout:
2783 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002784 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002785}
2786
2787void neigh_app_ns(struct neighbour *n)
2788{
2789 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002791EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
2793#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002794static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002795static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002796static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Joe Perchesfe2c6332013-06-11 23:04:25 -07002798static int proc_unres_qlen(struct ctl_table *ctl, int write,
2799 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002800{
2801 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002802 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002803
Shan Weice46cc62012-12-04 18:49:15 +00002804 tmp.extra1 = &zero;
2805 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002806 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002807
2808 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2809 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2810
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002811 if (write && !ret)
2812 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2813 return ret;
2814}
2815
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002816static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2817 void __user *buffer,
2818 size_t *lenp, loff_t *ppos)
2819{
2820 struct ctl_table tmp = *ctl;
2821
2822 tmp.extra1 = &zero;
2823 tmp.extra2 = &int_max;
2824
2825 return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2826}
2827
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002828int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2829 void __user *buffer, size_t *lenp, loff_t *ppos)
2830{
2831 return proc_dointvec(ctl, write, buffer, lenp, ppos);
2832}
2833EXPORT_SYMBOL(neigh_proc_dointvec);
2834
2835int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2836 void __user *buffer,
2837 size_t *lenp, loff_t *ppos)
2838{
2839 return proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2840}
2841EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2842
2843static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2844 void __user *buffer,
2845 size_t *lenp, loff_t *ppos)
2846{
2847 return proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2848}
2849
2850int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2851 void __user *buffer,
2852 size_t *lenp, loff_t *ppos)
2853{
2854 return proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2855}
2856EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2857
2858static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2859 void __user *buffer,
2860 size_t *lenp, loff_t *ppos)
2861{
2862 return proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2863}
2864
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002865#define NEIGH_PARMS_DATA_OFFSET(index) \
2866 (&((struct neigh_parms *) 0)->data[index])
2867
2868#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2869 [NEIGH_VAR_ ## attr] = { \
2870 .procname = name, \
2871 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2872 .maxlen = sizeof(int), \
2873 .mode = mval, \
2874 .proc_handler = proc, \
2875 }
2876
2877#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2878 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2879
2880#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002881 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002882
2883#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002884 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002885
2886#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002887 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002888
2889#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002890 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002891
2892#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002893 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002894
Linus Torvalds1da177e2005-04-16 15:20:36 -07002895static struct neigh_sysctl_table {
2896 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002897 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002898} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002899 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002900 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2901 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2902 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2903 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2904 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2905 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2906 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2907 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2908 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2909 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2910 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2911 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
2912 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
2913 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
2914 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002915 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 .procname = "gc_interval",
2917 .maxlen = sizeof(int),
2918 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08002919 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002920 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002921 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002922 .procname = "gc_thresh1",
2923 .maxlen = sizeof(int),
2924 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02002925 .extra1 = &zero,
2926 .extra2 = &int_max,
2927 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002929 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930 .procname = "gc_thresh2",
2931 .maxlen = sizeof(int),
2932 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02002933 .extra1 = &zero,
2934 .extra2 = &int_max,
2935 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002937 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 .procname = "gc_thresh3",
2939 .maxlen = sizeof(int),
2940 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02002941 .extra1 = &zero,
2942 .extra2 = &int_max,
2943 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11002945 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07002946 },
2947};
2948
2949int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01002950 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002951{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002952 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11002953 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002954 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00002955 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01002956 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002957
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11002958 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11002960 goto err;
2961
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002962 for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002963 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002964 t->neigh_vars[i].extra1 = dev;
2965 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966
2967 if (dev) {
2968 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07002969 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002970 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
2971 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 } else {
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00002973 dev_name_source = "default";
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002974 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = (int *)(p + 1);
2975 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = (int *)(p + 1) + 1;
2976 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = (int *)(p + 1) + 2;
2977 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002978 }
2979
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08002980 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002982 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002984 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002985 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002986 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002988 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 }
2990
Eric W. Biederman464dc802012-11-16 03:02:59 +00002991 /* Don't export sysctls to unprivileged users */
2992 if (neigh_parms_net(p)->user_ns != &init_user_ns)
2993 t->neigh_vars[0].procname = NULL;
2994
Jiri Pirko73af6142013-12-07 19:26:55 +01002995 switch (neigh_parms_family(p)) {
2996 case AF_INET:
2997 p_name = "ipv4";
2998 break;
2999 case AF_INET6:
3000 p_name = "ipv6";
3001 break;
3002 default:
3003 BUG();
3004 }
3005
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003006 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3007 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003008 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003009 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003010 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003011 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003012
Linus Torvalds1da177e2005-04-16 15:20:36 -07003013 p->sysctl_table = t;
3014 return 0;
3015
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003016free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003018err:
3019 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003021EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022
3023void neigh_sysctl_unregister(struct neigh_parms *p)
3024{
3025 if (p->sysctl_table) {
3026 struct neigh_sysctl_table *t = p->sysctl_table;
3027 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003028 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029 kfree(t);
3030 }
3031}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003032EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033
3034#endif /* CONFIG_SYSCTL */
3035
Thomas Grafc8822a42007-03-22 11:50:06 -07003036static int __init neigh_init(void)
3037{
Greg Rosec7ac8672011-06-10 01:27:09 +00003038 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3039 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3040 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003041
Greg Rosec7ac8672011-06-10 01:27:09 +00003042 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3043 NULL);
3044 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003045
3046 return 0;
3047}
3048
3049subsys_initcall(neigh_init);
3050