blob: ad07990e943da544dd292e29bf132adb6f2cc0c8 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010042#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define neigh_dbg(level, fmt, ...) \
47do { \
48 if (level <= NEIGH_DEBUG) \
49 pr_debug(fmt, ##__VA_ARGS__); \
50} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define PNEIGH_HASHMASK 0xF
53
54static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070055static void __neigh_notify(struct neighbour *n, int type, int flags);
56static void neigh_update_notify(struct neighbour *neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058
Amos Waterland45fc3b12005-09-24 16:53:16 -070059#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080060static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070061#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63/*
64 Neighbour hash table buckets are protected with rwlock tbl->lock.
65
66 - All the scans/updates to hash buckets MUST be made under this lock.
67 - NOTHING clever should be made under this lock: no callbacks
68 to protocol backends, no attempts to send something to network.
69 It will result in deadlocks, if backend/driver wants to use neighbour
70 cache.
71 - If the entry requires some non-trivial actions, increase
72 its reference count and release table lock.
73
74 Neighbour entries are protected:
75 - with reference count.
76 - with rwlock neigh->lock
77
78 Reference count prevents destruction.
79
80 neigh->lock mainly serializes ll address data and its validity state.
81 However, the same lock is used to protect another entry fields:
82 - timer
83 - resolution queue
84
85 Again, nothing clever shall be made under neigh->lock,
86 the most complicated procedure, which we allow is dev->hard_header.
87 It is supposed, that dev->hard_header is simplistic and does
88 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070089 */
90
David S. Miller8f40b162011-07-17 13:34:11 -070091static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070092{
93 kfree_skb(skb);
94 return -ENETDOWN;
95}
96
Thomas Graf4f494552007-08-08 23:12:36 -070097static void neigh_cleanup_and_release(struct neighbour *neigh)
98{
99 if (neigh->parms->neigh_cleanup)
100 neigh->parms->neigh_cleanup(neigh);
101
Thomas Grafd961db32007-08-08 23:12:56 -0700102 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700103 neigh_release(neigh);
104}
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106/*
107 * It is random distribution in the interval (1/2)*base...(3/2)*base.
108 * It corresponds to default IPv6 settings and is not overridable,
109 * because it is really reasonable choice.
110 */
111
112unsigned long neigh_rand_reach_time(unsigned long base)
113{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500114 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900116EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117
118
119static int neigh_forced_gc(struct neigh_table *tbl)
120{
121 int shrunk = 0;
122 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000123 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124
125 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
126
127 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000128 nht = rcu_dereference_protected(tbl->nht,
129 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700130 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700131 struct neighbour *n;
132 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000134 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700135 while ((n = rcu_dereference_protected(*np,
136 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 /* Neighbour record may be discarded if:
138 * - nobody refers to it.
139 * - it is not permanent
140 */
141 write_lock(&n->lock);
142 if (atomic_read(&n->refcnt) == 1 &&
143 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700144 rcu_assign_pointer(*np,
145 rcu_dereference_protected(n->next,
146 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 n->dead = 1;
148 shrunk = 1;
149 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700150 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 continue;
152 }
153 write_unlock(&n->lock);
154 np = &n->next;
155 }
156 }
157
158 tbl->last_flush = jiffies;
159
160 write_unlock_bh(&tbl->lock);
161
162 return shrunk;
163}
164
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800165static void neigh_add_timer(struct neighbour *n, unsigned long when)
166{
167 neigh_hold(n);
168 if (unlikely(mod_timer(&n->timer, when))) {
169 printk("NEIGH: BUG, double timer add, state is %x\n",
170 n->nud_state);
171 dump_stack();
172 }
173}
174
Linus Torvalds1da177e2005-04-16 15:20:36 -0700175static int neigh_del_timer(struct neighbour *n)
176{
177 if ((n->nud_state & NUD_IN_TIMER) &&
178 del_timer(&n->timer)) {
179 neigh_release(n);
180 return 1;
181 }
182 return 0;
183}
184
185static void pneigh_queue_purge(struct sk_buff_head *list)
186{
187 struct sk_buff *skb;
188
189 while ((skb = skb_dequeue(list)) != NULL) {
190 dev_put(skb->dev);
191 kfree_skb(skb);
192 }
193}
194
Herbert Xu49636bb2005-10-23 17:18:00 +1000195static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196{
197 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000198 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000200 nht = rcu_dereference_protected(tbl->nht,
201 lockdep_is_held(&tbl->lock));
202
David S. Millercd089332011-07-11 01:28:12 -0700203 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700204 struct neighbour *n;
205 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206
Eric Dumazet767e97e2010-10-06 17:49:21 -0700207 while ((n = rcu_dereference_protected(*np,
208 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209 if (dev && n->dev != dev) {
210 np = &n->next;
211 continue;
212 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700213 rcu_assign_pointer(*np,
214 rcu_dereference_protected(n->next,
215 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216 write_lock(&n->lock);
217 neigh_del_timer(n);
218 n->dead = 1;
219
220 if (atomic_read(&n->refcnt) != 1) {
221 /* The most unpleasant situation.
222 We must destroy neighbour entry,
223 but someone still uses it.
224
225 The destroy will be delayed until
226 the last user releases us, but
227 we must kill timers etc. and move
228 it to safe state.
229 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700230 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000231 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700232 n->output = neigh_blackhole;
233 if (n->nud_state & NUD_VALID)
234 n->nud_state = NUD_NOARP;
235 else
236 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000237 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700238 }
239 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700240 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 }
242 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000243}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Herbert Xu49636bb2005-10-23 17:18:00 +1000245void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
246{
247 write_lock_bh(&tbl->lock);
248 neigh_flush_dev(tbl, dev);
249 write_unlock_bh(&tbl->lock);
250}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900251EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000252
253int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
254{
255 write_lock_bh(&tbl->lock);
256 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257 pneigh_ifdown(tbl, dev);
258 write_unlock_bh(&tbl->lock);
259
260 del_timer_sync(&tbl->proxy_timer);
261 pneigh_queue_purge(&tbl->proxy_queue);
262 return 0;
263}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900264EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700265
David Miller596b9b62011-07-25 00:01:25 +0000266static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267{
268 struct neighbour *n = NULL;
269 unsigned long now = jiffies;
270 int entries;
271
272 entries = atomic_inc_return(&tbl->entries) - 1;
273 if (entries >= tbl->gc_thresh3 ||
274 (entries >= tbl->gc_thresh2 &&
275 time_after(now, tbl->last_flush + 5 * HZ))) {
276 if (!neigh_forced_gc(tbl) &&
277 entries >= tbl->gc_thresh3)
278 goto out_entries;
279 }
280
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000281 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 if (!n)
283 goto out_entries;
284
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700285 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000287 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 n->updated = n->used = now;
289 n->nud_state = NUD_NONE;
290 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700291 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800293 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
295 NEIGH_CACHE_STAT_INC(tbl, allocs);
296 n->tbl = tbl;
297 atomic_set(&n->refcnt, 1);
298 n->dead = 1;
299out:
300 return n;
301
302out_entries:
303 atomic_dec(&tbl->entries);
304 goto out;
305}
306
David S. Miller2c2aba62011-12-28 15:06:58 -0500307static void neigh_get_hash_rnd(u32 *x)
308{
309 get_random_bytes(x, sizeof(*x));
310 *x |= 1;
311}
312
David S. Millercd089332011-07-11 01:28:12 -0700313static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314{
David S. Millercd089332011-07-11 01:28:12 -0700315 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000316 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000317 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500318 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000320 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
321 if (!ret)
322 return NULL;
323 if (size <= PAGE_SIZE)
324 buckets = kzalloc(size, GFP_ATOMIC);
325 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000326 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000327 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
328 get_order(size));
329 if (!buckets) {
330 kfree(ret);
331 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000333 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700334 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500335 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
336 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 return ret;
338}
339
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000340static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000342 struct neigh_hash_table *nht = container_of(head,
343 struct neigh_hash_table,
344 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700345 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000346 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347
348 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000349 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000351 free_pages((unsigned long)buckets, get_order(size));
352 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353}
354
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000355static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700356 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000358 unsigned int i, hash;
359 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
361 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
362
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 old_nht = rcu_dereference_protected(tbl->nht,
364 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700365 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000366 if (!new_nht)
367 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368
David S. Millercd089332011-07-11 01:28:12 -0700369 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 struct neighbour *n, *next;
371
Eric Dumazet767e97e2010-10-06 17:49:21 -0700372 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
373 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000374 n != NULL;
375 n = next) {
376 hash = tbl->hash(n->primary_key, n->dev,
377 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378
David S. Millercd089332011-07-11 01:28:12 -0700379 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700380 next = rcu_dereference_protected(n->next,
381 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382
Eric Dumazet767e97e2010-10-06 17:49:21 -0700383 rcu_assign_pointer(n->next,
384 rcu_dereference_protected(
385 new_nht->hash_buckets[hash],
386 lockdep_is_held(&tbl->lock)));
387 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 }
389 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000391 rcu_assign_pointer(tbl->nht, new_nht);
392 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
393 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394}
395
396struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
397 struct net_device *dev)
398{
399 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900400
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401 NEIGH_CACHE_STAT_INC(tbl, lookups);
402
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000403 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600404 n = __neigh_lookup_noref(tbl, pkey, dev);
405 if (n) {
406 if (!atomic_inc_not_zero(&n->refcnt))
407 n = NULL;
408 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700410
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000411 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 return n;
413}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900414EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
Eric W. Biederman426b5302008-01-24 00:13:18 -0800416struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
417 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
419 struct neighbour *n;
420 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800421 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000422 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
424 NEIGH_CACHE_STAT_INC(tbl, lookups);
425
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000426 rcu_read_lock_bh();
427 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700428 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700429
430 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
431 n != NULL;
432 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800433 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900434 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700435 if (!atomic_inc_not_zero(&n->refcnt))
436 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437 NEIGH_CACHE_STAT_INC(tbl, hits);
438 break;
439 }
440 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700441
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000442 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 return n;
444}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900445EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446
David S. Millera263b302012-07-02 02:02:15 -0700447struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
448 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449{
450 u32 hash_val;
451 int key_len = tbl->key_len;
452 int error;
David Miller596b9b62011-07-25 00:01:25 +0000453 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000454 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
456 if (!n) {
457 rc = ERR_PTR(-ENOBUFS);
458 goto out;
459 }
460
461 memcpy(n->primary_key, pkey, key_len);
462 n->dev = dev;
463 dev_hold(dev);
464
465 /* Protocol specific setup. */
466 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
467 rc = ERR_PTR(error);
468 goto out_neigh_release;
469 }
470
David Millerda6a8fa2011-07-25 00:01:38 +0000471 if (dev->netdev_ops->ndo_neigh_construct) {
472 error = dev->netdev_ops->ndo_neigh_construct(n);
473 if (error < 0) {
474 rc = ERR_PTR(error);
475 goto out_neigh_release;
476 }
477 }
478
David S. Miller447f2192011-12-19 15:04:41 -0500479 /* Device specific setup. */
480 if (n->parms->neigh_setup &&
481 (error = n->parms->neigh_setup(n)) < 0) {
482 rc = ERR_PTR(error);
483 goto out_neigh_release;
484 }
485
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100486 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000489 nht = rcu_dereference_protected(tbl->nht,
490 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
David S. Millercd089332011-07-11 01:28:12 -0700492 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
493 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494
David S. Millercd089332011-07-11 01:28:12 -0700495 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 if (n->parms->dead) {
498 rc = ERR_PTR(-EINVAL);
499 goto out_tbl_unlock;
500 }
501
Eric Dumazet767e97e2010-10-06 17:49:21 -0700502 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
503 lockdep_is_held(&tbl->lock));
504 n1 != NULL;
505 n1 = rcu_dereference_protected(n1->next,
506 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700508 if (want_ref)
509 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 rc = n1;
511 goto out_tbl_unlock;
512 }
513 }
514
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700516 if (want_ref)
517 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700518 rcu_assign_pointer(n->next,
519 rcu_dereference_protected(nht->hash_buckets[hash_val],
520 lockdep_is_held(&tbl->lock)));
521 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000523 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 rc = n;
525out:
526 return rc;
527out_tbl_unlock:
528 write_unlock_bh(&tbl->lock);
529out_neigh_release:
530 neigh_release(n);
531 goto out;
532}
David S. Millera263b302012-07-02 02:02:15 -0700533EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900535static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700536{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700537 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700538 hash_val ^= (hash_val >> 16);
539 hash_val ^= hash_val >> 8;
540 hash_val ^= hash_val >> 4;
541 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900542 return hash_val;
543}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700544
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900545static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
546 struct net *net,
547 const void *pkey,
548 int key_len,
549 struct net_device *dev)
550{
551 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700552 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900553 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700554 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900555 return n;
556 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700557 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 return NULL;
559}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700560
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900561struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
562 struct net *net, const void *pkey, struct net_device *dev)
563{
564 int key_len = tbl->key_len;
565 u32 hash_val = pneigh_hash(pkey, key_len);
566
567 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
568 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700569}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900570EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700571
Eric W. Biederman426b5302008-01-24 00:13:18 -0800572struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
573 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 struct net_device *dev, int creat)
575{
576 struct pneigh_entry *n;
577 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900578 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579
580 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900581 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
582 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900584
585 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586 goto out;
587
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700588 ASSERT_RTNL();
589
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
591 if (!n)
592 goto out;
593
Eric Dumazete42ea982008-11-12 00:54:54 -0800594 write_pnet(&n->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 memcpy(n->key, pkey, key_len);
596 n->dev = dev;
597 if (dev)
598 dev_hold(dev);
599
600 if (tbl->pconstructor && tbl->pconstructor(n)) {
601 if (dev)
602 dev_put(dev);
Denis V. Lunevda12f732008-02-20 00:26:16 -0800603 release_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 kfree(n);
605 n = NULL;
606 goto out;
607 }
608
609 write_lock_bh(&tbl->lock);
610 n->next = tbl->phash_buckets[hash_val];
611 tbl->phash_buckets[hash_val] = n;
612 write_unlock_bh(&tbl->lock);
613out:
614 return n;
615}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900616EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617
618
Eric W. Biederman426b5302008-01-24 00:13:18 -0800619int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 struct net_device *dev)
621{
622 struct pneigh_entry *n, **np;
623 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900624 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
626 write_lock_bh(&tbl->lock);
627 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
628 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800629 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900630 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 *np = n->next;
632 write_unlock_bh(&tbl->lock);
633 if (tbl->pdestructor)
634 tbl->pdestructor(n);
635 if (n->dev)
636 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900637 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 kfree(n);
639 return 0;
640 }
641 }
642 write_unlock_bh(&tbl->lock);
643 return -ENOENT;
644}
645
646static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
647{
648 struct pneigh_entry *n, **np;
649 u32 h;
650
651 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
652 np = &tbl->phash_buckets[h];
653 while ((n = *np) != NULL) {
654 if (!dev || n->dev == dev) {
655 *np = n->next;
656 if (tbl->pdestructor)
657 tbl->pdestructor(n);
658 if (n->dev)
659 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900660 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 kfree(n);
662 continue;
663 }
664 np = &n->next;
665 }
666 }
667 return -ENOENT;
668}
669
Denis V. Lunev06f05112008-01-24 00:30:58 -0800670static void neigh_parms_destroy(struct neigh_parms *parms);
671
672static inline void neigh_parms_put(struct neigh_parms *parms)
673{
674 if (atomic_dec_and_test(&parms->refcnt))
675 neigh_parms_destroy(parms);
676}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678/*
679 * neighbour must already be out of the table;
680 *
681 */
682void neigh_destroy(struct neighbour *neigh)
683{
David Millerda6a8fa2011-07-25 00:01:38 +0000684 struct net_device *dev = neigh->dev;
685
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
687
688 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000689 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 dump_stack();
691 return;
692 }
693
694 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000695 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700697 write_lock_bh(&neigh->lock);
698 __skb_queue_purge(&neigh->arp_queue);
699 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000700 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701
David S. Miller447f2192011-12-19 15:04:41 -0500702 if (dev->netdev_ops->ndo_neigh_destroy)
703 dev->netdev_ops->ndo_neigh_destroy(neigh);
704
David Millerda6a8fa2011-07-25 00:01:38 +0000705 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 neigh_parms_put(neigh->parms);
707
Joe Perchesd5d427c2013-04-15 15:17:19 +0000708 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
710 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000711 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900713EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
715/* Neighbour state is suspicious;
716 disable fast path.
717
718 Called with write_locked neigh.
719 */
720static void neigh_suspect(struct neighbour *neigh)
721{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000722 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725}
726
727/* Neighbour state is OK;
728 enable fast path.
729
730 Called with write_locked neigh.
731 */
732static void neigh_connect(struct neighbour *neigh)
733{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000734 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735
736 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737}
738
Eric Dumazete4c4e442009-07-30 03:15:07 +0000739static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000741 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700742 struct neighbour *n;
743 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000744 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000745 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
747 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
748
Eric Dumazete4c4e442009-07-30 03:15:07 +0000749 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000750 nht = rcu_dereference_protected(tbl->nht,
751 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 /*
754 * periodically recompute ReachableTime from random function
755 */
756
Eric Dumazete4c4e442009-07-30 03:15:07 +0000757 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000759 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100760 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100762 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 }
764
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800765 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
766 goto out;
767
David S. Millercd089332011-07-11 01:28:12 -0700768 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000769 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
Eric Dumazet767e97e2010-10-06 17:49:21 -0700771 while ((n = rcu_dereference_protected(*np,
772 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000773 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
Eric Dumazete4c4e442009-07-30 03:15:07 +0000777 state = n->nud_state;
778 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
779 write_unlock(&n->lock);
780 goto next_elt;
781 }
782
783 if (time_before(n->used, n->confirmed))
784 n->used = n->confirmed;
785
786 if (atomic_read(&n->refcnt) == 1 &&
787 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100788 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 *np = n->next;
790 n->dead = 1;
791 write_unlock(&n->lock);
792 neigh_cleanup_and_release(n);
793 continue;
794 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
797next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000798 np = &n->next;
799 }
800 /*
801 * It's fine to release lock here, even if hash table
802 * grows while we are preempted.
803 */
804 write_unlock_bh(&tbl->lock);
805 cond_resched();
806 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500807 nht = rcu_dereference_protected(tbl->nht,
808 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000810out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100811 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
812 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
813 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 */
viresh kumarf6180022014-01-22 12:23:33 +0530815 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100816 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000817 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818}
819
820static __inline__ int neigh_max_probes(struct neighbour *n)
821{
822 struct neigh_parms *p = n->parms;
Timo Teräsa960ff82014-02-26 11:43:04 +0200823 int max_probes = NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES);
824 if (!(n->nud_state & NUD_PROBE))
825 max_probes += NEIGH_VAR(p, MCAST_PROBES);
826 return max_probes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827}
828
Timo Teras5ef12d92009-06-11 04:16:28 -0700829static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000830 __releases(neigh->lock)
831 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700832{
833 struct sk_buff *skb;
834
835 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000836 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700837 neigh->updated = jiffies;
838
839 /* It is very thin place. report_unreachable is very complicated
840 routine. Particularly, it can hit the same neighbour entry!
841
842 So that, we try to be accurate and avoid dead loop. --ANK
843 */
844 while (neigh->nud_state == NUD_FAILED &&
845 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
846 write_unlock(&neigh->lock);
847 neigh->ops->error_report(neigh, skb);
848 write_lock(&neigh->lock);
849 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700850 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000851 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700852}
853
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000854static void neigh_probe(struct neighbour *neigh)
855 __releases(neigh->lock)
856{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200857 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000858 /* keep skb alive even if arp_queue overflows */
859 if (skb)
860 skb = skb_copy(skb, GFP_ATOMIC);
861 write_unlock(&neigh->lock);
862 neigh->ops->solicit(neigh, skb);
863 atomic_inc(&neigh->probes);
864 kfree_skb(skb);
865}
866
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867/* Called when a timer expires for a neighbour entry. */
868
869static void neigh_timer_handler(unsigned long arg)
870{
871 unsigned long now, next;
872 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000873 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874 int notify = 0;
875
876 write_lock(&neigh->lock);
877
878 state = neigh->nud_state;
879 now = jiffies;
880 next = now + HZ;
881
David S. Miller045f7b32011-11-01 17:45:55 -0400882 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900886 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000888 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 next = neigh->confirmed + neigh->parms->reachable_time;
890 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100891 neigh->used +
892 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000893 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800895 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100897 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000899 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800901 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700903 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 }
905 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900906 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100907 neigh->confirmed +
908 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000909 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800911 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700913 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 next = neigh->confirmed + neigh->parms->reachable_time;
915 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000916 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800918 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100920 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 }
922 } else {
923 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100924 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 }
926
927 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
928 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 neigh->nud_state = NUD_FAILED;
930 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700931 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800932 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 }
934
935 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 if (time_before(next, jiffies + HZ/2))
937 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000938 if (!mod_timer(&neigh->timer, next))
939 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 }
941 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000942 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800943 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800944out:
David S. Miller9ff56602008-02-17 18:39:54 -0800945 write_unlock(&neigh->lock);
946 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
Thomas Grafd961db32007-08-08 23:12:56 -0700948 if (notify)
949 neigh_update_notify(neigh);
950
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 neigh_release(neigh);
952}
953
954int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
955{
956 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000957 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958
959 write_lock_bh(&neigh->lock);
960
961 rc = 0;
962 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
963 goto out_unlock_bh;
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100966 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
967 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000968 unsigned long next, now = jiffies;
969
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100970 atomic_set(&neigh->probes,
971 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000973 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100974 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
975 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000976 neigh_add_timer(neigh, next);
977 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 } else {
979 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800980 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 write_unlock_bh(&neigh->lock);
982
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000983 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 return 1;
985 }
986 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000987 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800989 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100990 neigh_add_timer(neigh, jiffies +
991 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 }
993
994 if (neigh->nud_state == NUD_INCOMPLETE) {
995 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000996 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100997 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000999
David S. Millerf72051b2008-09-23 01:11:18 -07001000 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001001 if (!buff)
1002 break;
1003 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001005 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001007 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001009 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 }
1011 rc = 1;
1012 }
1013out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001014 if (immediate_probe)
1015 neigh_probe(neigh);
1016 else
1017 write_unlock(&neigh->lock);
1018 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 return rc;
1020}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001021EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022
David S. Millerf6b72b62011-07-14 07:53:20 -07001023static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024{
1025 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001026 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001027 = NULL;
1028
1029 if (neigh->dev->header_ops)
1030 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031
1032 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001033 hh = &neigh->hh;
1034 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001035 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001037 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 }
1039 }
1040}
1041
1042
1043
1044/* Generic update routine.
1045 -- lladdr is new lladdr or NULL, if it is not supplied.
1046 -- new is new state.
1047 -- flags
1048 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1049 if it is different.
1050 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001051 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 if it is different.
1053 It also allows to retain current state
1054 if lladdr is unchanged.
1055 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1056
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001057 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 NTF_ROUTER flag.
1059 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1060 a router.
1061
1062 Caller MUST hold reference count on the entry.
1063 */
1064
1065int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1066 u32 flags)
1067{
1068 u8 old;
1069 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071 struct net_device *dev;
1072 int update_isrouter = 0;
1073
1074 write_lock_bh(&neigh->lock);
1075
1076 dev = neigh->dev;
1077 old = neigh->nud_state;
1078 err = -EPERM;
1079
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001080 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 (old & (NUD_NOARP | NUD_PERMANENT)))
1082 goto out;
1083
1084 if (!(new & NUD_VALID)) {
1085 neigh_del_timer(neigh);
1086 if (old & NUD_CONNECTED)
1087 neigh_suspect(neigh);
1088 neigh->nud_state = new;
1089 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001091 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1092 (new & NUD_FAILED)) {
1093 neigh_invalidate(neigh);
1094 notify = 1;
1095 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 goto out;
1097 }
1098
1099 /* Compare new lladdr with cached one */
1100 if (!dev->addr_len) {
1101 /* First case: device needs no address. */
1102 lladdr = neigh->ha;
1103 } else if (lladdr) {
1104 /* The second case: if something is already cached
1105 and a new address is proposed:
1106 - compare new & old
1107 - if they are different, check override flag
1108 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001109 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 !memcmp(lladdr, neigh->ha, dev->addr_len))
1111 lladdr = neigh->ha;
1112 } else {
1113 /* No address is supplied; if we know something,
1114 use it, otherwise discard the request.
1115 */
1116 err = -EINVAL;
1117 if (!(old & NUD_VALID))
1118 goto out;
1119 lladdr = neigh->ha;
1120 }
1121
1122 if (new & NUD_CONNECTED)
1123 neigh->confirmed = jiffies;
1124 neigh->updated = jiffies;
1125
1126 /* If entry was valid and address is not changed,
1127 do not change entry state, if new one is STALE.
1128 */
1129 err = 0;
1130 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1131 if (old & NUD_VALID) {
1132 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1133 update_isrouter = 0;
1134 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1135 (old & NUD_CONNECTED)) {
1136 lladdr = neigh->ha;
1137 new = NUD_STALE;
1138 } else
1139 goto out;
1140 } else {
1141 if (lladdr == neigh->ha && new == NUD_STALE &&
1142 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1143 (old & NUD_CONNECTED))
1144 )
1145 new = old;
1146 }
1147 }
1148
1149 if (new != old) {
1150 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001151 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001152 neigh_add_timer(neigh, (jiffies +
1153 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001154 neigh->parms->reachable_time :
1155 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001157 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 }
1159
1160 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001161 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001163 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 neigh_update_hhs(neigh);
1165 if (!(new & NUD_CONNECTED))
1166 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001167 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 }
1170 if (new == old)
1171 goto out;
1172 if (new & NUD_CONNECTED)
1173 neigh_connect(neigh);
1174 else
1175 neigh_suspect(neigh);
1176 if (!(old & NUD_VALID)) {
1177 struct sk_buff *skb;
1178
1179 /* Again: avoid dead loop if something went wrong */
1180
1181 while (neigh->nud_state & NUD_VALID &&
1182 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001183 struct dst_entry *dst = skb_dst(skb);
1184 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001186
1187 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001188
1189 /* Why not just use 'neigh' as-is? The problem is that
1190 * things such as shaper, eql, and sch_teql can end up
1191 * using alternative, different, neigh objects to output
1192 * the packet in the output path. So what we need to do
1193 * here is re-lookup the top-level neigh in the path so
1194 * we can reinject the packet there.
1195 */
1196 n2 = NULL;
1197 if (dst) {
1198 n2 = dst_neigh_lookup_skb(dst, skb);
1199 if (n2)
1200 n1 = n2;
1201 }
David S. Miller8f40b162011-07-17 13:34:11 -07001202 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001203 if (n2)
1204 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001205 rcu_read_unlock();
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 write_lock_bh(&neigh->lock);
1208 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001209 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001210 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 }
1212out:
1213 if (update_isrouter) {
1214 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1215 (neigh->flags | NTF_ROUTER) :
1216 (neigh->flags & ~NTF_ROUTER);
1217 }
1218 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001219
1220 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001221 neigh_update_notify(neigh);
1222
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 return err;
1224}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001225EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226
Jiri Benc7e980562013-12-11 13:48:20 +01001227/* Update the neigh to listen temporarily for probe responses, even if it is
1228 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1229 */
1230void __neigh_set_probe_once(struct neighbour *neigh)
1231{
1232 neigh->updated = jiffies;
1233 if (!(neigh->nud_state & NUD_FAILED))
1234 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001235 neigh->nud_state = NUD_INCOMPLETE;
1236 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001237 neigh_add_timer(neigh,
1238 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1239}
1240EXPORT_SYMBOL(__neigh_set_probe_once);
1241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1243 u8 *lladdr, void *saddr,
1244 struct net_device *dev)
1245{
1246 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1247 lladdr || !dev->addr_len);
1248 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001249 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 NEIGH_UPDATE_F_OVERRIDE);
1251 return neigh;
1252}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001253EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254
Eric Dumazet34d101d2010-10-11 09:16:57 -07001255/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001256static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001258 struct net_device *dev = n->dev;
1259 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001260 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001261
1262 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001263
David S. Millerf6b72b62011-07-14 07:53:20 -07001264 /* Only one thread can come in here and initialize the
1265 * hh_cache entry.
1266 */
David S. Millerb23b5452011-07-16 17:45:02 -07001267 if (!hh->hh_len)
1268 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001269
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001270 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271}
1272
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273/* Slow and careful. */
1274
David S. Miller8f40b162011-07-17 13:34:11 -07001275int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 int rc = 0;
1278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 if (!neigh_event_send(neigh, skb)) {
1280 int err;
1281 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001282 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001283
David S. Millerf6b72b62011-07-14 07:53:20 -07001284 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001285 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001286
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001287 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001288 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001289 seq = read_seqbegin(&neigh->ha_lock);
1290 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1291 neigh->ha, NULL, skb->len);
1292 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001295 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 else
1297 goto out_kfree_skb;
1298 }
1299out:
1300 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301out_kfree_skb:
1302 rc = -EINVAL;
1303 kfree_skb(skb);
1304 goto out;
1305}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001306EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
1308/* As fast as possible without hh cache */
1309
David S. Miller8f40b162011-07-17 13:34:11 -07001310int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001313 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001314 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001316 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001317 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001318 seq = read_seqbegin(&neigh->ha_lock);
1319 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1320 neigh->ha, NULL, skb->len);
1321 } while (read_seqretry(&neigh->ha_lock, seq));
1322
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001324 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 else {
1326 err = -EINVAL;
1327 kfree_skb(skb);
1328 }
1329 return err;
1330}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001331EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332
David S. Miller8f40b162011-07-17 13:34:11 -07001333int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1334{
1335 return dev_queue_xmit(skb);
1336}
1337EXPORT_SYMBOL(neigh_direct_output);
1338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339static void neigh_proxy_process(unsigned long arg)
1340{
1341 struct neigh_table *tbl = (struct neigh_table *)arg;
1342 long sched_next = 0;
1343 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001344 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
1346 spin_lock(&tbl->proxy_queue.lock);
1347
David S. Millerf72051b2008-09-23 01:11:18 -07001348 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1349 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001352 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001353
David S. Millerf72051b2008-09-23 01:11:18 -07001354 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001355 if (tbl->proxy_redo && netif_running(dev)) {
1356 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001357 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001358 rcu_read_unlock();
1359 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001360 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363 dev_put(dev);
1364 } else if (!sched_next || tdif < sched_next)
1365 sched_next = tdif;
1366 }
1367 del_timer(&tbl->proxy_timer);
1368 if (sched_next)
1369 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1370 spin_unlock(&tbl->proxy_queue.lock);
1371}
1372
1373void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1374 struct sk_buff *skb)
1375{
1376 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001377
1378 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001379 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001381 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 kfree_skb(skb);
1383 return;
1384 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001385
1386 NEIGH_CB(skb)->sched_next = sched_next;
1387 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
1389 spin_lock(&tbl->proxy_queue.lock);
1390 if (del_timer(&tbl->proxy_timer)) {
1391 if (time_before(tbl->proxy_timer.expires, sched_next))
1392 sched_next = tbl->proxy_timer.expires;
1393 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001394 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 dev_hold(skb->dev);
1396 __skb_queue_tail(&tbl->proxy_queue, skb);
1397 mod_timer(&tbl->proxy_timer, sched_next);
1398 spin_unlock(&tbl->proxy_queue.lock);
1399}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001400EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001402static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001403 struct net *net, int ifindex)
1404{
1405 struct neigh_parms *p;
1406
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001407 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001408 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001409 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001410 return p;
1411 }
1412
1413 return NULL;
1414}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1417 struct neigh_table *tbl)
1418{
Gao fengcf89d6b2013-06-20 10:01:32 +08001419 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001420 struct net *net = dev_net(dev);
1421 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Gao fengcf89d6b2013-06-20 10:01:32 +08001423 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001425 p->tbl = tbl;
1426 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001428 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001429 dev_hold(dev);
1430 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001431 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001433
1434 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1435 release_net(net);
1436 dev_put(dev);
1437 kfree(p);
1438 return NULL;
1439 }
1440
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001442 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001444
1445 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 }
1447 return p;
1448}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001449EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450
1451static void neigh_rcu_free_parms(struct rcu_head *head)
1452{
1453 struct neigh_parms *parms =
1454 container_of(head, struct neigh_parms, rcu_head);
1455
1456 neigh_parms_put(parms);
1457}
1458
1459void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1460{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 if (!parms || parms == &tbl->parms)
1462 return;
1463 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001464 list_del(&parms->list);
1465 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001467 if (parms->dev)
1468 dev_put(parms->dev);
1469 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001471EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472
Denis V. Lunev06f05112008-01-24 00:30:58 -08001473static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001475 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476 kfree(parms);
1477}
1478
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001479static struct lock_class_key neigh_table_proxy_queue_class;
1480
WANG Congd7480fd2014-11-10 15:59:36 -08001481static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1482
1483void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484{
1485 unsigned long now = jiffies;
1486 unsigned long phsize;
1487
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001488 INIT_LIST_HEAD(&tbl->parms_list);
1489 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001490 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001493 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 tbl->stats = alloc_percpu(struct neigh_statistics);
1496 if (!tbl->stats)
1497 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001500 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1501 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503#endif
1504
David S. Millercd089332011-07-11 01:28:12 -07001505 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
1507 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001508 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001510 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 panic("cannot allocate neighbour cache hashes");
1512
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001513 if (!tbl->entry_size)
1514 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1515 tbl->key_len, NEIGH_PRIV_ALIGN);
1516 else
1517 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1518
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001520 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301521 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1522 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001523 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001524 skb_queue_head_init_class(&tbl->proxy_queue,
1525 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
1527 tbl->last_flush = now;
1528 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001529
WANG Congd7480fd2014-11-10 15:59:36 -08001530 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001532EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533
WANG Congd7480fd2014-11-10 15:59:36 -08001534int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535{
WANG Congd7480fd2014-11-10 15:59:36 -08001536 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001538 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539 del_timer_sync(&tbl->proxy_timer);
1540 pneigh_queue_purge(&tbl->proxy_queue);
1541 neigh_ifdown(tbl, NULL);
1542 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001543 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001545 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1546 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001547 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
1549 kfree(tbl->phash_buckets);
1550 tbl->phash_buckets = NULL;
1551
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001552 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1553
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001554 free_percpu(tbl->stats);
1555 tbl->stats = NULL;
1556
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 return 0;
1558}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001559EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
WANG Congd7480fd2014-11-10 15:59:36 -08001561static struct neigh_table *neigh_find_table(int family)
1562{
1563 struct neigh_table *tbl = NULL;
1564
1565 switch (family) {
1566 case AF_INET:
1567 tbl = neigh_tables[NEIGH_ARP_TABLE];
1568 break;
1569 case AF_INET6:
1570 tbl = neigh_tables[NEIGH_ND_TABLE];
1571 break;
1572 case AF_DECnet:
1573 tbl = neigh_tables[NEIGH_DN_TABLE];
1574 break;
1575 }
1576
1577 return tbl;
1578}
1579
Thomas Graf661d2962013-03-21 07:45:29 +00001580static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001582 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001583 struct ndmsg *ndm;
1584 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001586 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001588 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589
Eric Dumazet110b2492010-10-04 04:27:36 +00001590 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001591 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 goto out;
1593
Thomas Grafa14a49d2006-08-07 17:53:08 -07001594 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1595 if (dst_attr == NULL)
1596 goto out;
1597
1598 ndm = nlmsg_data(nlh);
1599 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001600 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001601 if (dev == NULL) {
1602 err = -ENODEV;
1603 goto out;
1604 }
1605 }
1606
WANG Congd7480fd2014-11-10 15:59:36 -08001607 tbl = neigh_find_table(ndm->ndm_family);
1608 if (tbl == NULL)
1609 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610
WANG Congd7480fd2014-11-10 15:59:36 -08001611 if (nla_len(dst_attr) < tbl->key_len)
1612 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
WANG Congd7480fd2014-11-10 15:59:36 -08001614 if (ndm->ndm_flags & NTF_PROXY) {
1615 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001616 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 }
WANG Congd7480fd2014-11-10 15:59:36 -08001618
1619 if (dev == NULL)
1620 goto out;
1621
1622 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1623 if (neigh == NULL) {
1624 err = -ENOENT;
1625 goto out;
1626 }
1627
1628 err = neigh_update(neigh, NULL, NUD_FAILED,
1629 NEIGH_UPDATE_F_OVERRIDE |
1630 NEIGH_UPDATE_F_ADMIN);
1631 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633out:
1634 return err;
1635}
1636
Thomas Graf661d2962013-03-21 07:45:29 +00001637static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
WANG Congd7480fd2014-11-10 15:59:36 -08001639 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001640 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001641 struct ndmsg *ndm;
1642 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 struct neigh_table *tbl;
1644 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001645 struct neighbour *neigh;
1646 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001647 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648
Eric Dumazet110b2492010-10-04 04:27:36 +00001649 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001650 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1651 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 goto out;
1653
Thomas Graf5208deb2006-08-07 17:55:40 -07001654 err = -EINVAL;
1655 if (tb[NDA_DST] == NULL)
1656 goto out;
1657
1658 ndm = nlmsg_data(nlh);
1659 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001660 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001661 if (dev == NULL) {
1662 err = -ENODEV;
1663 goto out;
1664 }
1665
1666 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001667 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001668 }
1669
WANG Congd7480fd2014-11-10 15:59:36 -08001670 tbl = neigh_find_table(ndm->ndm_family);
1671 if (tbl == NULL)
1672 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
WANG Congd7480fd2014-11-10 15:59:36 -08001674 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1675 goto out;
1676 dst = nla_data(tb[NDA_DST]);
1677 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
WANG Congd7480fd2014-11-10 15:59:36 -08001679 if (ndm->ndm_flags & NTF_PROXY) {
1680 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
WANG Congd7480fd2014-11-10 15:59:36 -08001682 err = -ENOBUFS;
1683 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1684 if (pn) {
1685 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001686 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001687 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001688 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689 }
1690
WANG Congd7480fd2014-11-10 15:59:36 -08001691 if (dev == NULL)
1692 goto out;
1693
1694 neigh = neigh_lookup(tbl, dst, dev);
1695 if (neigh == NULL) {
1696 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1697 err = -ENOENT;
1698 goto out;
1699 }
1700
1701 neigh = __neigh_lookup_errno(tbl, dst, dev);
1702 if (IS_ERR(neigh)) {
1703 err = PTR_ERR(neigh);
1704 goto out;
1705 }
1706 } else {
1707 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1708 err = -EEXIST;
1709 neigh_release(neigh);
1710 goto out;
1711 }
1712
1713 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1714 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1715 }
1716
1717 if (ndm->ndm_flags & NTF_USE) {
1718 neigh_event_send(neigh, NULL);
1719 err = 0;
1720 } else
1721 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1722 neigh_release(neigh);
1723
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724out:
1725 return err;
1726}
1727
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001728static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1729{
Thomas Grafca860fb2006-08-07 18:00:18 -07001730 struct nlattr *nest;
1731
1732 nest = nla_nest_start(skb, NDTA_PARMS);
1733 if (nest == NULL)
1734 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001735
David S. Miller9a6308d2012-04-01 20:06:28 -04001736 if ((parms->dev &&
1737 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1738 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001739 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1740 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001741 /* approximative value for deprecated QUEUE_LEN (in packets) */
1742 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001743 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1744 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1745 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1746 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1747 NEIGH_VAR(parms, UCAST_PROBES)) ||
1748 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1749 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001750 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1751 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001752 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1753 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1754 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001755 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001756 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1757 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1758 NEIGH_VAR(parms, RETRANS_TIME)) ||
1759 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1760 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1761 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1762 NEIGH_VAR(parms, PROXY_DELAY)) ||
1763 nla_put_msecs(skb, NDTPA_LOCKTIME,
1764 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001765 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001766 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001767
Thomas Grafca860fb2006-08-07 18:00:18 -07001768nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001769 nla_nest_cancel(skb, nest);
1770 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001771}
1772
Thomas Grafca860fb2006-08-07 18:00:18 -07001773static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1774 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001775{
1776 struct nlmsghdr *nlh;
1777 struct ndtmsg *ndtmsg;
1778
Thomas Grafca860fb2006-08-07 18:00:18 -07001779 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1780 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001781 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001782
Thomas Grafca860fb2006-08-07 18:00:18 -07001783 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001784
1785 read_lock_bh(&tbl->lock);
1786 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001787 ndtmsg->ndtm_pad1 = 0;
1788 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001789
David S. Miller9a6308d2012-04-01 20:06:28 -04001790 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1791 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1792 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1793 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1794 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1795 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001796 {
1797 unsigned long now = jiffies;
1798 unsigned int flush_delta = now - tbl->last_flush;
1799 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001800 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001801 struct ndt_config ndc = {
1802 .ndtc_key_len = tbl->key_len,
1803 .ndtc_entry_size = tbl->entry_size,
1804 .ndtc_entries = atomic_read(&tbl->entries),
1805 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1806 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001807 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1808 };
1809
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001810 rcu_read_lock_bh();
1811 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001812 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001813 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001814 rcu_read_unlock_bh();
1815
David S. Miller9a6308d2012-04-01 20:06:28 -04001816 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1817 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001818 }
1819
1820 {
1821 int cpu;
1822 struct ndt_stats ndst;
1823
1824 memset(&ndst, 0, sizeof(ndst));
1825
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001826 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001827 struct neigh_statistics *st;
1828
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001829 st = per_cpu_ptr(tbl->stats, cpu);
1830 ndst.ndts_allocs += st->allocs;
1831 ndst.ndts_destroys += st->destroys;
1832 ndst.ndts_hash_grows += st->hash_grows;
1833 ndst.ndts_res_failed += st->res_failed;
1834 ndst.ndts_lookups += st->lookups;
1835 ndst.ndts_hits += st->hits;
1836 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1837 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1838 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1839 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1840 }
1841
David S. Miller9a6308d2012-04-01 20:06:28 -04001842 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1843 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844 }
1845
1846 BUG_ON(tbl->parms.dev);
1847 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001848 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001849
1850 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001851 nlmsg_end(skb, nlh);
1852 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853
Thomas Grafca860fb2006-08-07 18:00:18 -07001854nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001856 nlmsg_cancel(skb, nlh);
1857 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001858}
1859
Thomas Grafca860fb2006-08-07 18:00:18 -07001860static int neightbl_fill_param_info(struct sk_buff *skb,
1861 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001862 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001863 u32 pid, u32 seq, int type,
1864 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001865{
1866 struct ndtmsg *ndtmsg;
1867 struct nlmsghdr *nlh;
1868
Thomas Grafca860fb2006-08-07 18:00:18 -07001869 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1870 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001871 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001872
Thomas Grafca860fb2006-08-07 18:00:18 -07001873 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001874
1875 read_lock_bh(&tbl->lock);
1876 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001877 ndtmsg->ndtm_pad1 = 0;
1878 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001879
Thomas Grafca860fb2006-08-07 18:00:18 -07001880 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1881 neightbl_fill_parms(skb, parms) < 0)
1882 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001883
1884 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001885 nlmsg_end(skb, nlh);
1886 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001887errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001888 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001889 nlmsg_cancel(skb, nlh);
1890 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001891}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001892
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001893static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001894 [NDTA_NAME] = { .type = NLA_STRING },
1895 [NDTA_THRESH1] = { .type = NLA_U32 },
1896 [NDTA_THRESH2] = { .type = NLA_U32 },
1897 [NDTA_THRESH3] = { .type = NLA_U32 },
1898 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1899 [NDTA_PARMS] = { .type = NLA_NESTED },
1900};
1901
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001902static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001903 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1904 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1905 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1906 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1907 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1908 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1909 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1910 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1911 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1912 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1913 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1914 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1915 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1916};
1917
Thomas Graf661d2962013-03-21 07:45:29 +00001918static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001919{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001920 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001922 struct ndtmsg *ndtmsg;
1923 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001924 bool found = false;
1925 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001926
Thomas Graf6b3f8672006-08-07 17:58:53 -07001927 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1928 nl_neightbl_policy);
1929 if (err < 0)
1930 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001931
Thomas Graf6b3f8672006-08-07 17:58:53 -07001932 if (tb[NDTA_NAME] == NULL) {
1933 err = -EINVAL;
1934 goto errout;
1935 }
1936
1937 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001938
1939 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1940 tbl = neigh_tables[tidx];
1941 if (!tbl)
1942 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001943 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1944 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08001945 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1946 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001947 break;
WANG Congd7480fd2014-11-10 15:59:36 -08001948 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949 }
1950
WANG Congd7480fd2014-11-10 15:59:36 -08001951 if (!found)
1952 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001953
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001954 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001955 * We acquire tbl->lock to be nice to the periodic timers and
1956 * make sure they always see a consistent set of values.
1957 */
1958 write_lock_bh(&tbl->lock);
1959
Thomas Graf6b3f8672006-08-07 17:58:53 -07001960 if (tb[NDTA_PARMS]) {
1961 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001962 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001963 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001964
Thomas Graf6b3f8672006-08-07 17:58:53 -07001965 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1966 nl_ntbl_parm_policy);
1967 if (err < 0)
1968 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001969
Thomas Graf6b3f8672006-08-07 17:58:53 -07001970 if (tbp[NDTPA_IFINDEX])
1971 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001972
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001973 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001974 if (p == NULL) {
1975 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001976 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001977 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001978
Thomas Graf6b3f8672006-08-07 17:58:53 -07001979 for (i = 1; i <= NDTPA_MAX; i++) {
1980 if (tbp[i] == NULL)
1981 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001982
Thomas Graf6b3f8672006-08-07 17:58:53 -07001983 switch (i) {
1984 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001985 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
1986 nla_get_u32(tbp[i]) *
1987 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001988 break;
1989 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001990 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
1991 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001992 break;
1993 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001994 NEIGH_VAR_SET(p, PROXY_QLEN,
1995 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001996 break;
1997 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001998 NEIGH_VAR_SET(p, APP_PROBES,
1999 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 break;
2001 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002002 NEIGH_VAR_SET(p, UCAST_PROBES,
2003 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002004 break;
2005 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002006 NEIGH_VAR_SET(p, MCAST_PROBES,
2007 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002008 break;
2009 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002010 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2011 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002012 /* update reachable_time as well, otherwise, the change will
2013 * only be effective after the next time neigh_periodic_work
2014 * decides to recompute it (can be multiple minutes)
2015 */
2016 p->reachable_time =
2017 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002018 break;
2019 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002020 NEIGH_VAR_SET(p, GC_STALETIME,
2021 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002022 break;
2023 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002024 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2025 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002026 break;
2027 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002028 NEIGH_VAR_SET(p, RETRANS_TIME,
2029 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002030 break;
2031 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002032 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2033 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002034 break;
2035 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002036 NEIGH_VAR_SET(p, PROXY_DELAY,
2037 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002038 break;
2039 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002040 NEIGH_VAR_SET(p, LOCKTIME,
2041 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002042 break;
2043 }
2044 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002045 }
2046
Gao fengdc25c672013-06-20 10:01:34 +08002047 err = -ENOENT;
2048 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2049 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2050 !net_eq(net, &init_net))
2051 goto errout_tbl_lock;
2052
Thomas Graf6b3f8672006-08-07 17:58:53 -07002053 if (tb[NDTA_THRESH1])
2054 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2055
2056 if (tb[NDTA_THRESH2])
2057 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2058
2059 if (tb[NDTA_THRESH3])
2060 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2061
2062 if (tb[NDTA_GC_INTERVAL])
2063 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2064
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002065 err = 0;
2066
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002068 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002069errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002070 return err;
2071}
2072
Thomas Grafc8822a42007-03-22 11:50:06 -07002073static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002074{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002075 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002076 int family, tidx, nidx = 0;
2077 int tbl_skip = cb->args[0];
2078 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002079 struct neigh_table *tbl;
2080
Thomas Grafca860fb2006-08-07 18:00:18 -07002081 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002082
WANG Congd7480fd2014-11-10 15:59:36 -08002083 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002084 struct neigh_parms *p;
2085
WANG Congd7480fd2014-11-10 15:59:36 -08002086 tbl = neigh_tables[tidx];
2087 if (!tbl)
2088 continue;
2089
Thomas Grafca860fb2006-08-07 18:00:18 -07002090 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002091 continue;
2092
Eric W. Biederman15e47302012-09-07 20:12:54 +00002093 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002094 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002095 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002096 break;
2097
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002098 nidx = 0;
2099 p = list_next_entry(&tbl->parms, list);
2100 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002101 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002102 continue;
2103
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002104 if (nidx < neigh_skip)
2105 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002106
Thomas Grafca860fb2006-08-07 18:00:18 -07002107 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002108 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002109 cb->nlh->nlmsg_seq,
2110 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002111 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002112 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002113 next:
2114 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002115 }
2116
Thomas Grafca860fb2006-08-07 18:00:18 -07002117 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002118 }
2119out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002120 cb->args[0] = tidx;
2121 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002122
2123 return skb->len;
2124}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125
Thomas Graf8b8aec52006-08-07 17:56:37 -07002126static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2127 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128{
2129 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002131 struct nlmsghdr *nlh;
2132 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133
Thomas Graf8b8aec52006-08-07 17:56:37 -07002134 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2135 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002136 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002137
2138 ndm = nlmsg_data(nlh);
2139 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002140 ndm->ndm_pad1 = 0;
2141 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002142 ndm->ndm_flags = neigh->flags;
2143 ndm->ndm_type = neigh->type;
2144 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002145
David S. Miller9a6308d2012-04-01 20:06:28 -04002146 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2147 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002148
2149 read_lock_bh(&neigh->lock);
2150 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002151 if (neigh->nud_state & NUD_VALID) {
2152 char haddr[MAX_ADDR_LEN];
2153
2154 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2155 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2156 read_unlock_bh(&neigh->lock);
2157 goto nla_put_failure;
2158 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002159 }
2160
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002161 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2162 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2163 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002164 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2165 read_unlock_bh(&neigh->lock);
2166
David S. Miller9a6308d2012-04-01 20:06:28 -04002167 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2168 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2169 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002170
Johannes Berg053c0952015-01-16 22:09:00 +01002171 nlmsg_end(skb, nlh);
2172 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002173
2174nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002175 nlmsg_cancel(skb, nlh);
2176 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177}
2178
Tony Zelenoff84920c12012-01-26 22:28:58 +00002179static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2180 u32 pid, u32 seq, int type, unsigned int flags,
2181 struct neigh_table *tbl)
2182{
2183 struct nlmsghdr *nlh;
2184 struct ndmsg *ndm;
2185
2186 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2187 if (nlh == NULL)
2188 return -EMSGSIZE;
2189
2190 ndm = nlmsg_data(nlh);
2191 ndm->ndm_family = tbl->family;
2192 ndm->ndm_pad1 = 0;
2193 ndm->ndm_pad2 = 0;
2194 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002195 ndm->ndm_type = RTN_UNICAST;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002196 ndm->ndm_ifindex = pn->dev->ifindex;
2197 ndm->ndm_state = NUD_NONE;
2198
David S. Miller9a6308d2012-04-01 20:06:28 -04002199 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2200 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002201
Johannes Berg053c0952015-01-16 22:09:00 +01002202 nlmsg_end(skb, nlh);
2203 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002204
2205nla_put_failure:
2206 nlmsg_cancel(skb, nlh);
2207 return -EMSGSIZE;
2208}
2209
Thomas Grafd961db32007-08-08 23:12:56 -07002210static void neigh_update_notify(struct neighbour *neigh)
2211{
2212 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2213 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2214}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
2216static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2217 struct netlink_callback *cb)
2218{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002219 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002220 struct neighbour *n;
2221 int rc, h, s_h = cb->args[1];
2222 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002223 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002225 rcu_read_lock_bh();
2226 nht = rcu_dereference_bh(tbl->nht);
2227
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002228 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229 if (h > s_h)
2230 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002231 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2232 n != NULL;
2233 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002234 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002235 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002236 if (idx < s_idx)
2237 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002238 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002240 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002241 NLM_F_MULTI) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 rc = -1;
2243 goto out;
2244 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002245next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002246 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248 }
2249 rc = skb->len;
2250out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002251 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002252 cb->args[1] = h;
2253 cb->args[2] = idx;
2254 return rc;
2255}
2256
Tony Zelenoff84920c12012-01-26 22:28:58 +00002257static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2258 struct netlink_callback *cb)
2259{
2260 struct pneigh_entry *n;
2261 struct net *net = sock_net(skb->sk);
2262 int rc, h, s_h = cb->args[3];
2263 int idx, s_idx = idx = cb->args[4];
2264
2265 read_lock_bh(&tbl->lock);
2266
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002267 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002268 if (h > s_h)
2269 s_idx = 0;
2270 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2271 if (dev_net(n->dev) != net)
2272 continue;
2273 if (idx < s_idx)
2274 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002275 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002276 cb->nlh->nlmsg_seq,
2277 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002278 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002279 read_unlock_bh(&tbl->lock);
2280 rc = -1;
2281 goto out;
2282 }
2283 next:
2284 idx++;
2285 }
2286 }
2287
2288 read_unlock_bh(&tbl->lock);
2289 rc = skb->len;
2290out:
2291 cb->args[3] = h;
2292 cb->args[4] = idx;
2293 return rc;
2294
2295}
2296
Thomas Grafc8822a42007-03-22 11:50:06 -07002297static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298{
2299 struct neigh_table *tbl;
2300 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002301 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002302 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Thomas Graf8b8aec52006-08-07 17:56:37 -07002304 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002305
2306 /* check for full ndmsg structure presence, family member is
2307 * the same for both structures
2308 */
2309 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2310 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2311 proxy = 1;
2312
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313 s_t = cb->args[0];
2314
WANG Congd7480fd2014-11-10 15:59:36 -08002315 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2316 tbl = neigh_tables[t];
2317
2318 if (!tbl)
2319 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320 if (t < s_t || (family && tbl->family != family))
2321 continue;
2322 if (t > s_t)
2323 memset(&cb->args[1], 0, sizeof(cb->args) -
2324 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002325 if (proxy)
2326 err = pneigh_dump_table(tbl, skb, cb);
2327 else
2328 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002329 if (err < 0)
2330 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332
2333 cb->args[0] = t;
2334 return skb->len;
2335}
2336
2337void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2338{
2339 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002340 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002342 rcu_read_lock_bh();
2343 nht = rcu_dereference_bh(tbl->nht);
2344
Eric Dumazet767e97e2010-10-06 17:49:21 -07002345 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002346 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 struct neighbour *n;
2348
Eric Dumazet767e97e2010-10-06 17:49:21 -07002349 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2350 n != NULL;
2351 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 cb(n, cookie);
2353 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002354 read_unlock(&tbl->lock);
2355 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356}
2357EXPORT_SYMBOL(neigh_for_each);
2358
2359/* The tbl->lock must be held as a writer and BH disabled. */
2360void __neigh_for_each_release(struct neigh_table *tbl,
2361 int (*cb)(struct neighbour *))
2362{
2363 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002364 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002366 nht = rcu_dereference_protected(tbl->nht,
2367 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002368 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002369 struct neighbour *n;
2370 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002372 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002373 while ((n = rcu_dereference_protected(*np,
2374 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 int release;
2376
2377 write_lock(&n->lock);
2378 release = cb(n);
2379 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002380 rcu_assign_pointer(*np,
2381 rcu_dereference_protected(n->next,
2382 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 n->dead = 1;
2384 } else
2385 np = &n->next;
2386 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002387 if (release)
2388 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389 }
2390 }
2391}
2392EXPORT_SYMBOL(__neigh_for_each_release);
2393
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002394int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002395 const void *addr, struct sk_buff *skb)
2396{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002397 int err = -EAFNOSUPPORT;
2398 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002399 struct neigh_table *tbl;
2400 struct neighbour *neigh;
2401
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002402 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002403 if (!tbl)
2404 goto out;
2405 neigh = __neigh_lookup_noref(tbl, addr, dev);
2406 if (!neigh)
2407 neigh = __neigh_create(tbl, addr, dev, false);
2408 err = PTR_ERR(neigh);
2409 if (IS_ERR(neigh))
2410 goto out_kfree_skb;
2411 err = neigh->output(neigh, skb);
2412 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002413 else if (index == NEIGH_LINK_TABLE) {
2414 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2415 addr, NULL, skb->len);
2416 if (err < 0)
2417 goto out_kfree_skb;
2418 err = dev_queue_xmit(skb);
2419 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002420out:
2421 return err;
2422out_kfree_skb:
2423 kfree_skb(skb);
2424 goto out;
2425}
2426EXPORT_SYMBOL(neigh_xmit);
2427
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428#ifdef CONFIG_PROC_FS
2429
2430static struct neighbour *neigh_get_first(struct seq_file *seq)
2431{
2432 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002433 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002434 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 struct neighbour *n = NULL;
2436 int bucket = state->bucket;
2437
2438 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002439 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002440 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
2442 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002443 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002444 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 if (state->neigh_sub_iter) {
2446 loff_t fakep = 0;
2447 void *v;
2448
2449 v = state->neigh_sub_iter(state, n, &fakep);
2450 if (!v)
2451 goto next;
2452 }
2453 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2454 break;
2455 if (n->nud_state & ~NUD_NOARP)
2456 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002457next:
2458 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 }
2460
2461 if (n)
2462 break;
2463 }
2464 state->bucket = bucket;
2465
2466 return n;
2467}
2468
2469static struct neighbour *neigh_get_next(struct seq_file *seq,
2470 struct neighbour *n,
2471 loff_t *pos)
2472{
2473 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002474 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002475 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
2477 if (state->neigh_sub_iter) {
2478 void *v = state->neigh_sub_iter(state, n, pos);
2479 if (v)
2480 return n;
2481 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002482 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
2484 while (1) {
2485 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002486 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002487 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002488 if (state->neigh_sub_iter) {
2489 void *v = state->neigh_sub_iter(state, n, pos);
2490 if (v)
2491 return n;
2492 goto next;
2493 }
2494 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2495 break;
2496
2497 if (n->nud_state & ~NUD_NOARP)
2498 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002499next:
2500 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 }
2502
2503 if (n)
2504 break;
2505
David S. Millercd089332011-07-11 01:28:12 -07002506 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 break;
2508
Eric Dumazet767e97e2010-10-06 17:49:21 -07002509 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510 }
2511
2512 if (n && pos)
2513 --(*pos);
2514 return n;
2515}
2516
2517static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2518{
2519 struct neighbour *n = neigh_get_first(seq);
2520
2521 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002522 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 while (*pos) {
2524 n = neigh_get_next(seq, n, pos);
2525 if (!n)
2526 break;
2527 }
2528 }
2529 return *pos ? NULL : n;
2530}
2531
2532static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2533{
2534 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002535 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 struct neigh_table *tbl = state->tbl;
2537 struct pneigh_entry *pn = NULL;
2538 int bucket = state->bucket;
2539
2540 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2541 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2542 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002543 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002544 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 if (pn)
2546 break;
2547 }
2548 state->bucket = bucket;
2549
2550 return pn;
2551}
2552
2553static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2554 struct pneigh_entry *pn,
2555 loff_t *pos)
2556{
2557 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002558 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 struct neigh_table *tbl = state->tbl;
2560
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002561 do {
2562 pn = pn->next;
2563 } while (pn && !net_eq(pneigh_net(pn), net));
2564
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 while (!pn) {
2566 if (++state->bucket > PNEIGH_HASHMASK)
2567 break;
2568 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002569 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002570 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 if (pn)
2572 break;
2573 }
2574
2575 if (pn && pos)
2576 --(*pos);
2577
2578 return pn;
2579}
2580
2581static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2582{
2583 struct pneigh_entry *pn = pneigh_get_first(seq);
2584
2585 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002586 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 while (*pos) {
2588 pn = pneigh_get_next(seq, pn, pos);
2589 if (!pn)
2590 break;
2591 }
2592 }
2593 return *pos ? NULL : pn;
2594}
2595
2596static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2597{
2598 struct neigh_seq_state *state = seq->private;
2599 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002600 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
Chris Larson745e2032008-08-03 01:10:55 -07002602 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002604 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002605
2606 return rc;
2607}
2608
2609void *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 +00002610 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611{
2612 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
2614 state->tbl = tbl;
2615 state->bucket = 0;
2616 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2617
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002618 rcu_read_lock_bh();
2619 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002620
Chris Larson745e2032008-08-03 01:10:55 -07002621 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622}
2623EXPORT_SYMBOL(neigh_seq_start);
2624
2625void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2626{
2627 struct neigh_seq_state *state;
2628 void *rc;
2629
2630 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002631 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 goto out;
2633 }
2634
2635 state = seq->private;
2636 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2637 rc = neigh_get_next(seq, v, NULL);
2638 if (rc)
2639 goto out;
2640 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2641 rc = pneigh_get_first(seq);
2642 } else {
2643 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2644 rc = pneigh_get_next(seq, v, NULL);
2645 }
2646out:
2647 ++(*pos);
2648 return rc;
2649}
2650EXPORT_SYMBOL(neigh_seq_next);
2651
2652void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002653 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002655 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656}
2657EXPORT_SYMBOL(neigh_seq_stop);
2658
2659/* statistics via seq_file */
2660
2661static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2662{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002663 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 int cpu;
2665
2666 if (*pos == 0)
2667 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002668
Rusty Russell0f23174a2008-12-29 12:23:42 +00002669 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 if (!cpu_possible(cpu))
2671 continue;
2672 *pos = cpu+1;
2673 return per_cpu_ptr(tbl->stats, cpu);
2674 }
2675 return NULL;
2676}
2677
2678static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2679{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002680 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 int cpu;
2682
Rusty Russell0f23174a2008-12-29 12:23:42 +00002683 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 if (!cpu_possible(cpu))
2685 continue;
2686 *pos = cpu+1;
2687 return per_cpu_ptr(tbl->stats, cpu);
2688 }
2689 return NULL;
2690}
2691
2692static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2693{
2694
2695}
2696
2697static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2698{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002699 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 struct neigh_statistics *st = v;
2701
2702 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002703 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 -07002704 return 0;
2705 }
2706
2707 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002708 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 atomic_read(&tbl->entries),
2710
2711 st->allocs,
2712 st->destroys,
2713 st->hash_grows,
2714
2715 st->lookups,
2716 st->hits,
2717
2718 st->res_failed,
2719
2720 st->rcv_probes_mcast,
2721 st->rcv_probes_ucast,
2722
2723 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002724 st->forced_gc_runs,
2725 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726 );
2727
2728 return 0;
2729}
2730
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002731static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 .start = neigh_stat_seq_start,
2733 .next = neigh_stat_seq_next,
2734 .stop = neigh_stat_seq_stop,
2735 .show = neigh_stat_seq_show,
2736};
2737
2738static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2739{
2740 int ret = seq_open(file, &neigh_stat_seq_ops);
2741
2742 if (!ret) {
2743 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002744 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 }
2746 return ret;
2747};
2748
Arjan van de Ven9a321442007-02-12 00:55:35 -08002749static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002750 .owner = THIS_MODULE,
2751 .open = neigh_stat_seq_open,
2752 .read = seq_read,
2753 .llseek = seq_lseek,
2754 .release = seq_release,
2755};
2756
2757#endif /* CONFIG_PROC_FS */
2758
Thomas Graf339bf982006-11-10 14:10:15 -08002759static inline size_t neigh_nlmsg_size(void)
2760{
2761 return NLMSG_ALIGN(sizeof(struct ndmsg))
2762 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2763 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2764 + nla_total_size(sizeof(struct nda_cacheinfo))
2765 + nla_total_size(4); /* NDA_PROBES */
2766}
2767
Thomas Grafb8673312006-08-15 00:33:14 -07002768static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002770 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002771 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002772 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773
Thomas Graf339bf982006-11-10 14:10:15 -08002774 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002775 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002776 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777
Thomas Grafb8673312006-08-15 00:33:14 -07002778 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002779 if (err < 0) {
2780 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2781 WARN_ON(err == -EMSGSIZE);
2782 kfree_skb(skb);
2783 goto errout;
2784 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002785 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2786 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002787errout:
2788 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002789 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002790}
2791
2792void neigh_app_ns(struct neighbour *n)
2793{
2794 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002796EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
2798#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002799static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002800static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002801static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802
Joe Perchesfe2c6332013-06-11 23:04:25 -07002803static int proc_unres_qlen(struct ctl_table *ctl, int write,
2804 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002805{
2806 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002807 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002808
Shan Weice46cc62012-12-04 18:49:15 +00002809 tmp.extra1 = &zero;
2810 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002811 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002812
2813 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2814 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2815
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002816 if (write && !ret)
2817 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2818 return ret;
2819}
2820
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002821static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2822 int family)
2823{
Jiri Pirkobba24892013-12-07 19:26:57 +01002824 switch (family) {
2825 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002826 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002827 case AF_INET6:
2828 return __in6_dev_nd_parms_get_rcu(dev);
2829 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002830 return NULL;
2831}
2832
2833static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2834 int index)
2835{
2836 struct net_device *dev;
2837 int family = neigh_parms_family(p);
2838
2839 rcu_read_lock();
2840 for_each_netdev_rcu(net, dev) {
2841 struct neigh_parms *dst_p =
2842 neigh_get_dev_parms_rcu(dev, family);
2843
2844 if (dst_p && !test_bit(index, dst_p->data_state))
2845 dst_p->data[index] = p->data[index];
2846 }
2847 rcu_read_unlock();
2848}
2849
2850static void neigh_proc_update(struct ctl_table *ctl, int write)
2851{
2852 struct net_device *dev = ctl->extra1;
2853 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002854 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002855 int index = (int *) ctl->data - p->data;
2856
2857 if (!write)
2858 return;
2859
2860 set_bit(index, p->data_state);
2861 if (!dev) /* NULL dev means this is default value */
2862 neigh_copy_dflt_parms(net, p, index);
2863}
2864
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002865static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2866 void __user *buffer,
2867 size_t *lenp, loff_t *ppos)
2868{
2869 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002870 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002871
2872 tmp.extra1 = &zero;
2873 tmp.extra2 = &int_max;
2874
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002875 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2876 neigh_proc_update(ctl, write);
2877 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002878}
2879
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002880int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2881 void __user *buffer, size_t *lenp, loff_t *ppos)
2882{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002883 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2884
2885 neigh_proc_update(ctl, write);
2886 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002887}
2888EXPORT_SYMBOL(neigh_proc_dointvec);
2889
2890int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2891 void __user *buffer,
2892 size_t *lenp, loff_t *ppos)
2893{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002894 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2895
2896 neigh_proc_update(ctl, write);
2897 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002898}
2899EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2900
2901static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2902 void __user *buffer,
2903 size_t *lenp, loff_t *ppos)
2904{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002905 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2906
2907 neigh_proc_update(ctl, write);
2908 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002909}
2910
2911int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2912 void __user *buffer,
2913 size_t *lenp, loff_t *ppos)
2914{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002915 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2916
2917 neigh_proc_update(ctl, write);
2918 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002919}
2920EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2921
2922static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2923 void __user *buffer,
2924 size_t *lenp, loff_t *ppos)
2925{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002926 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2927
2928 neigh_proc_update(ctl, write);
2929 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002930}
2931
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002932static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
2933 void __user *buffer,
2934 size_t *lenp, loff_t *ppos)
2935{
2936 struct neigh_parms *p = ctl->extra2;
2937 int ret;
2938
2939 if (strcmp(ctl->procname, "base_reachable_time") == 0)
2940 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2941 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
2942 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2943 else
2944 ret = -1;
2945
2946 if (write && ret == 0) {
2947 /* update reachable_time as well, otherwise, the change will
2948 * only be effective after the next time neigh_periodic_work
2949 * decides to recompute it
2950 */
2951 p->reachable_time =
2952 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
2953 }
2954 return ret;
2955}
2956
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002957#define NEIGH_PARMS_DATA_OFFSET(index) \
2958 (&((struct neigh_parms *) 0)->data[index])
2959
2960#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2961 [NEIGH_VAR_ ## attr] = { \
2962 .procname = name, \
2963 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2964 .maxlen = sizeof(int), \
2965 .mode = mval, \
2966 .proc_handler = proc, \
2967 }
2968
2969#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2970 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2971
2972#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002973 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002974
2975#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002976 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002977
2978#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002979 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002980
2981#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002982 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002983
2984#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002985 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002986
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987static struct neigh_sysctl_table {
2988 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002989 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002990} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002992 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2993 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2994 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2995 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2996 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2997 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2998 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2999 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3000 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3001 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3002 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3003 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3004 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3005 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3006 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003007 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 .procname = "gc_interval",
3009 .maxlen = sizeof(int),
3010 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003011 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003013 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014 .procname = "gc_thresh1",
3015 .maxlen = sizeof(int),
3016 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003017 .extra1 = &zero,
3018 .extra2 = &int_max,
3019 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003021 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003022 .procname = "gc_thresh2",
3023 .maxlen = sizeof(int),
3024 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003025 .extra1 = &zero,
3026 .extra2 = &int_max,
3027 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003029 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003030 .procname = "gc_thresh3",
3031 .maxlen = sizeof(int),
3032 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003033 .extra1 = &zero,
3034 .extra2 = &int_max,
3035 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003037 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038 },
3039};
3040
3041int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003042 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003044 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003045 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003046 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003047 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003048 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003050 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003052 goto err;
3053
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003054 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003055 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003056 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003057 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003058 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059
3060 if (dev) {
3061 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003062 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003063 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3064 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003066 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003067 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003068 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3069 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3070 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3071 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 }
3073
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003074 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003076 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003077 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003078 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003080 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003082 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003083 } else {
3084 /* Those handlers will update p->reachable_time after
3085 * base_reachable_time(_ms) is set to ensure the new timer starts being
3086 * applied after the next neighbour update instead of waiting for
3087 * neigh_periodic_work to update its value (can be multiple minutes)
3088 * So any handler that replaces them should do this as well
3089 */
3090 /* ReachableTime */
3091 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3092 neigh_proc_base_reachable_time;
3093 /* ReachableTime (in milliseconds) */
3094 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3095 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 }
3097
Eric W. Biederman464dc802012-11-16 03:02:59 +00003098 /* Don't export sysctls to unprivileged users */
3099 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3100 t->neigh_vars[0].procname = NULL;
3101
Jiri Pirko73af6142013-12-07 19:26:55 +01003102 switch (neigh_parms_family(p)) {
3103 case AF_INET:
3104 p_name = "ipv4";
3105 break;
3106 case AF_INET6:
3107 p_name = "ipv6";
3108 break;
3109 default:
3110 BUG();
3111 }
3112
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003113 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3114 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003115 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003116 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003117 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003118 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003119
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 p->sysctl_table = t;
3121 return 0;
3122
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003123free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003125err:
3126 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003128EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
3130void neigh_sysctl_unregister(struct neigh_parms *p)
3131{
3132 if (p->sysctl_table) {
3133 struct neigh_sysctl_table *t = p->sysctl_table;
3134 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003135 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003136 kfree(t);
3137 }
3138}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003139EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140
3141#endif /* CONFIG_SYSCTL */
3142
Thomas Grafc8822a42007-03-22 11:50:06 -07003143static int __init neigh_init(void)
3144{
Greg Rosec7ac8672011-06-10 01:27:09 +00003145 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3146 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3147 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003148
Greg Rosec7ac8672011-06-10 01:27:09 +00003149 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3150 NULL);
3151 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003152
3153 return 0;
3154}
3155
3156subsys_initcall(neigh_init);
3157