blob: 0e8b32efc0316c85e56c4b7a95c4c903fde63ecf [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 W. Biedermanefd7ef12015-03-11 23:04:08 -0500594 write_pnet(&n->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);
603 kfree(n);
604 n = NULL;
605 goto out;
606 }
607
608 write_lock_bh(&tbl->lock);
609 n->next = tbl->phash_buckets[hash_val];
610 tbl->phash_buckets[hash_val] = n;
611 write_unlock_bh(&tbl->lock);
612out:
613 return n;
614}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900615EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
617
Eric W. Biederman426b5302008-01-24 00:13:18 -0800618int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 struct net_device *dev)
620{
621 struct pneigh_entry *n, **np;
622 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900623 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624
625 write_lock_bh(&tbl->lock);
626 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
627 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800628 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900629 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 *np = n->next;
631 write_unlock_bh(&tbl->lock);
632 if (tbl->pdestructor)
633 tbl->pdestructor(n);
634 if (n->dev)
635 dev_put(n->dev);
636 kfree(n);
637 return 0;
638 }
639 }
640 write_unlock_bh(&tbl->lock);
641 return -ENOENT;
642}
643
644static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
645{
646 struct pneigh_entry *n, **np;
647 u32 h;
648
649 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
650 np = &tbl->phash_buckets[h];
651 while ((n = *np) != NULL) {
652 if (!dev || n->dev == dev) {
653 *np = n->next;
654 if (tbl->pdestructor)
655 tbl->pdestructor(n);
656 if (n->dev)
657 dev_put(n->dev);
658 kfree(n);
659 continue;
660 }
661 np = &n->next;
662 }
663 }
664 return -ENOENT;
665}
666
Denis V. Lunev06f05112008-01-24 00:30:58 -0800667static void neigh_parms_destroy(struct neigh_parms *parms);
668
669static inline void neigh_parms_put(struct neigh_parms *parms)
670{
671 if (atomic_dec_and_test(&parms->refcnt))
672 neigh_parms_destroy(parms);
673}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674
675/*
676 * neighbour must already be out of the table;
677 *
678 */
679void neigh_destroy(struct neighbour *neigh)
680{
David Millerda6a8fa2011-07-25 00:01:38 +0000681 struct net_device *dev = neigh->dev;
682
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
684
685 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000686 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 dump_stack();
688 return;
689 }
690
691 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000692 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700694 write_lock_bh(&neigh->lock);
695 __skb_queue_purge(&neigh->arp_queue);
696 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000697 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
David S. Miller447f2192011-12-19 15:04:41 -0500699 if (dev->netdev_ops->ndo_neigh_destroy)
700 dev->netdev_ops->ndo_neigh_destroy(neigh);
701
David Millerda6a8fa2011-07-25 00:01:38 +0000702 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 neigh_parms_put(neigh->parms);
704
Joe Perchesd5d427c2013-04-15 15:17:19 +0000705 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000708 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900710EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712/* Neighbour state is suspicious;
713 disable fast path.
714
715 Called with write_locked neigh.
716 */
717static void neigh_suspect(struct neighbour *neigh)
718{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000719 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722}
723
724/* Neighbour state is OK;
725 enable fast path.
726
727 Called with write_locked neigh.
728 */
729static void neigh_connect(struct neighbour *neigh)
730{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000731 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734}
735
Eric Dumazete4c4e442009-07-30 03:15:07 +0000736static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000738 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700739 struct neighbour *n;
740 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000741 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000742 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
744 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
745
Eric Dumazete4c4e442009-07-30 03:15:07 +0000746 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000747 nht = rcu_dereference_protected(tbl->nht,
748 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 /*
751 * periodically recompute ReachableTime from random function
752 */
753
Eric Dumazete4c4e442009-07-30 03:15:07 +0000754 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000756 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100757 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100759 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
761
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800762 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
763 goto out;
764
David S. Millercd089332011-07-11 01:28:12 -0700765 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000766 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
Eric Dumazet767e97e2010-10-06 17:49:21 -0700768 while ((n = rcu_dereference_protected(*np,
769 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000770 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771
Eric Dumazete4c4e442009-07-30 03:15:07 +0000772 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Eric Dumazete4c4e442009-07-30 03:15:07 +0000774 state = n->nud_state;
775 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
776 write_unlock(&n->lock);
777 goto next_elt;
778 }
779
780 if (time_before(n->used, n->confirmed))
781 n->used = n->confirmed;
782
783 if (atomic_read(&n->refcnt) == 1 &&
784 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100785 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000786 *np = n->next;
787 n->dead = 1;
788 write_unlock(&n->lock);
789 neigh_cleanup_and_release(n);
790 continue;
791 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000795 np = &n->next;
796 }
797 /*
798 * It's fine to release lock here, even if hash table
799 * grows while we are preempted.
800 */
801 write_unlock_bh(&tbl->lock);
802 cond_resched();
803 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500804 nht = rcu_dereference_protected(tbl->nht,
805 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000807out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100808 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
809 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
810 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 */
viresh kumarf6180022014-01-22 12:23:33 +0530812 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100813 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000814 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815}
816
817static __inline__ int neigh_max_probes(struct neighbour *n)
818{
819 struct neigh_parms *p = n->parms;
Timo Teräsa960ff82014-02-26 11:43:04 +0200820 int max_probes = NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES);
821 if (!(n->nud_state & NUD_PROBE))
822 max_probes += NEIGH_VAR(p, MCAST_PROBES);
823 return max_probes;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824}
825
Timo Teras5ef12d92009-06-11 04:16:28 -0700826static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000827 __releases(neigh->lock)
828 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700829{
830 struct sk_buff *skb;
831
832 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000833 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700834 neigh->updated = jiffies;
835
836 /* It is very thin place. report_unreachable is very complicated
837 routine. Particularly, it can hit the same neighbour entry!
838
839 So that, we try to be accurate and avoid dead loop. --ANK
840 */
841 while (neigh->nud_state == NUD_FAILED &&
842 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
843 write_unlock(&neigh->lock);
844 neigh->ops->error_report(neigh, skb);
845 write_lock(&neigh->lock);
846 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700847 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000848 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700849}
850
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000851static void neigh_probe(struct neighbour *neigh)
852 __releases(neigh->lock)
853{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200854 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000855 /* keep skb alive even if arp_queue overflows */
856 if (skb)
857 skb = skb_copy(skb, GFP_ATOMIC);
858 write_unlock(&neigh->lock);
859 neigh->ops->solicit(neigh, skb);
860 atomic_inc(&neigh->probes);
861 kfree_skb(skb);
862}
863
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864/* Called when a timer expires for a neighbour entry. */
865
866static void neigh_timer_handler(unsigned long arg)
867{
868 unsigned long now, next;
869 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000870 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 int notify = 0;
872
873 write_lock(&neigh->lock);
874
875 state = neigh->nud_state;
876 now = jiffies;
877 next = now + HZ;
878
David S. Miller045f7b32011-11-01 17:45:55 -0400879 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
882 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900883 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000885 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 next = neigh->confirmed + neigh->parms->reachable_time;
887 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100888 neigh->used +
889 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000890 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800892 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100894 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000896 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800898 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700900 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 }
902 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900903 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100904 neigh->confirmed +
905 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000906 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800908 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700910 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 next = neigh->confirmed + neigh->parms->reachable_time;
912 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000913 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800915 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100917 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 }
919 } else {
920 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100921 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 }
923
924 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
925 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 neigh->nud_state = NUD_FAILED;
927 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700928 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800929 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 }
931
932 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 if (time_before(next, jiffies + HZ/2))
934 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000935 if (!mod_timer(&neigh->timer, next))
936 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
938 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000939 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800940 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800941out:
David S. Miller9ff56602008-02-17 18:39:54 -0800942 write_unlock(&neigh->lock);
943 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944
Thomas Grafd961db32007-08-08 23:12:56 -0700945 if (notify)
946 neigh_update_notify(neigh);
947
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 neigh_release(neigh);
949}
950
951int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
952{
953 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000954 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955
956 write_lock_bh(&neigh->lock);
957
958 rc = 0;
959 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
960 goto out_unlock_bh;
961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100963 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
964 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000965 unsigned long next, now = jiffies;
966
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100967 atomic_set(&neigh->probes,
968 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000970 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100971 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
972 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000973 neigh_add_timer(neigh, next);
974 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 } else {
976 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800977 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 write_unlock_bh(&neigh->lock);
979
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000980 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 return 1;
982 }
983 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000984 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800986 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100987 neigh_add_timer(neigh, jiffies +
988 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990
991 if (neigh->nud_state == NUD_INCOMPLETE) {
992 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000993 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100994 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000996
David S. Millerf72051b2008-09-23 01:11:18 -0700997 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000998 if (!buff)
999 break;
1000 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001002 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001004 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001006 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 }
1008 rc = 1;
1009 }
1010out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001011 if (immediate_probe)
1012 neigh_probe(neigh);
1013 else
1014 write_unlock(&neigh->lock);
1015 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 return rc;
1017}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001018EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019
David S. Millerf6b72b62011-07-14 07:53:20 -07001020static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021{
1022 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001023 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001024 = NULL;
1025
1026 if (neigh->dev->header_ops)
1027 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028
1029 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001030 hh = &neigh->hh;
1031 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001032 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001034 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
1036 }
1037}
1038
1039
1040
1041/* Generic update routine.
1042 -- lladdr is new lladdr or NULL, if it is not supplied.
1043 -- new is new state.
1044 -- flags
1045 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1046 if it is different.
1047 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001048 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 if it is different.
1050 It also allows to retain current state
1051 if lladdr is unchanged.
1052 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1053
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001054 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 NTF_ROUTER flag.
1056 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1057 a router.
1058
1059 Caller MUST hold reference count on the entry.
1060 */
1061
1062int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1063 u32 flags)
1064{
1065 u8 old;
1066 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 struct net_device *dev;
1069 int update_isrouter = 0;
1070
1071 write_lock_bh(&neigh->lock);
1072
1073 dev = neigh->dev;
1074 old = neigh->nud_state;
1075 err = -EPERM;
1076
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001077 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 (old & (NUD_NOARP | NUD_PERMANENT)))
1079 goto out;
1080
1081 if (!(new & NUD_VALID)) {
1082 neigh_del_timer(neigh);
1083 if (old & NUD_CONNECTED)
1084 neigh_suspect(neigh);
1085 neigh->nud_state = new;
1086 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001088 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1089 (new & NUD_FAILED)) {
1090 neigh_invalidate(neigh);
1091 notify = 1;
1092 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 goto out;
1094 }
1095
1096 /* Compare new lladdr with cached one */
1097 if (!dev->addr_len) {
1098 /* First case: device needs no address. */
1099 lladdr = neigh->ha;
1100 } else if (lladdr) {
1101 /* The second case: if something is already cached
1102 and a new address is proposed:
1103 - compare new & old
1104 - if they are different, check override flag
1105 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001106 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 !memcmp(lladdr, neigh->ha, dev->addr_len))
1108 lladdr = neigh->ha;
1109 } else {
1110 /* No address is supplied; if we know something,
1111 use it, otherwise discard the request.
1112 */
1113 err = -EINVAL;
1114 if (!(old & NUD_VALID))
1115 goto out;
1116 lladdr = neigh->ha;
1117 }
1118
1119 if (new & NUD_CONNECTED)
1120 neigh->confirmed = jiffies;
1121 neigh->updated = jiffies;
1122
1123 /* If entry was valid and address is not changed,
1124 do not change entry state, if new one is STALE.
1125 */
1126 err = 0;
1127 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1128 if (old & NUD_VALID) {
1129 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1130 update_isrouter = 0;
1131 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1132 (old & NUD_CONNECTED)) {
1133 lladdr = neigh->ha;
1134 new = NUD_STALE;
1135 } else
1136 goto out;
1137 } else {
1138 if (lladdr == neigh->ha && new == NUD_STALE &&
1139 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1140 (old & NUD_CONNECTED))
1141 )
1142 new = old;
1143 }
1144 }
1145
1146 if (new != old) {
1147 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001148 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001149 neigh_add_timer(neigh, (jiffies +
1150 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001151 neigh->parms->reachable_time :
1152 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001154 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 }
1156
1157 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001158 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001160 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 neigh_update_hhs(neigh);
1162 if (!(new & NUD_CONNECTED))
1163 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001164 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 }
1167 if (new == old)
1168 goto out;
1169 if (new & NUD_CONNECTED)
1170 neigh_connect(neigh);
1171 else
1172 neigh_suspect(neigh);
1173 if (!(old & NUD_VALID)) {
1174 struct sk_buff *skb;
1175
1176 /* Again: avoid dead loop if something went wrong */
1177
1178 while (neigh->nud_state & NUD_VALID &&
1179 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001180 struct dst_entry *dst = skb_dst(skb);
1181 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001183
1184 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001185
1186 /* Why not just use 'neigh' as-is? The problem is that
1187 * things such as shaper, eql, and sch_teql can end up
1188 * using alternative, different, neigh objects to output
1189 * the packet in the output path. So what we need to do
1190 * here is re-lookup the top-level neigh in the path so
1191 * we can reinject the packet there.
1192 */
1193 n2 = NULL;
1194 if (dst) {
1195 n2 = dst_neigh_lookup_skb(dst, skb);
1196 if (n2)
1197 n1 = n2;
1198 }
David S. Miller8f40b162011-07-17 13:34:11 -07001199 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001200 if (n2)
1201 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001202 rcu_read_unlock();
1203
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 write_lock_bh(&neigh->lock);
1205 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001206 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001207 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 }
1209out:
1210 if (update_isrouter) {
1211 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1212 (neigh->flags | NTF_ROUTER) :
1213 (neigh->flags & ~NTF_ROUTER);
1214 }
1215 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001216
1217 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001218 neigh_update_notify(neigh);
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 return err;
1221}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001222EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223
Jiri Benc7e980562013-12-11 13:48:20 +01001224/* Update the neigh to listen temporarily for probe responses, even if it is
1225 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1226 */
1227void __neigh_set_probe_once(struct neighbour *neigh)
1228{
1229 neigh->updated = jiffies;
1230 if (!(neigh->nud_state & NUD_FAILED))
1231 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001232 neigh->nud_state = NUD_INCOMPLETE;
1233 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001234 neigh_add_timer(neigh,
1235 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1236}
1237EXPORT_SYMBOL(__neigh_set_probe_once);
1238
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1240 u8 *lladdr, void *saddr,
1241 struct net_device *dev)
1242{
1243 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1244 lladdr || !dev->addr_len);
1245 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001246 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 NEIGH_UPDATE_F_OVERRIDE);
1248 return neigh;
1249}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001250EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251
Eric Dumazet34d101d2010-10-11 09:16:57 -07001252/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001253static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001255 struct net_device *dev = n->dev;
1256 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001257 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001258
1259 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001260
David S. Millerf6b72b62011-07-14 07:53:20 -07001261 /* Only one thread can come in here and initialize the
1262 * hh_cache entry.
1263 */
David S. Millerb23b5452011-07-16 17:45:02 -07001264 if (!hh->hh_len)
1265 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001266
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001267 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268}
1269
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270/* Slow and careful. */
1271
David S. Miller8f40b162011-07-17 13:34:11 -07001272int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 int rc = 0;
1275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 if (!neigh_event_send(neigh, skb)) {
1277 int err;
1278 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001279 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001280
David S. Millerf6b72b62011-07-14 07:53:20 -07001281 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001282 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001283
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001284 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001285 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001286 seq = read_seqbegin(&neigh->ha_lock);
1287 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1288 neigh->ha, NULL, skb->len);
1289 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001290
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001292 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 else
1294 goto out_kfree_skb;
1295 }
1296out:
1297 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298out_kfree_skb:
1299 rc = -EINVAL;
1300 kfree_skb(skb);
1301 goto out;
1302}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001303EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
1305/* As fast as possible without hh cache */
1306
David S. Miller8f40b162011-07-17 13:34:11 -07001307int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001310 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001311 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001313 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001314 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001315 seq = read_seqbegin(&neigh->ha_lock);
1316 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1317 neigh->ha, NULL, skb->len);
1318 } while (read_seqretry(&neigh->ha_lock, seq));
1319
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001321 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322 else {
1323 err = -EINVAL;
1324 kfree_skb(skb);
1325 }
1326 return err;
1327}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001328EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329
David S. Miller8f40b162011-07-17 13:34:11 -07001330int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1331{
1332 return dev_queue_xmit(skb);
1333}
1334EXPORT_SYMBOL(neigh_direct_output);
1335
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336static void neigh_proxy_process(unsigned long arg)
1337{
1338 struct neigh_table *tbl = (struct neigh_table *)arg;
1339 long sched_next = 0;
1340 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001341 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342
1343 spin_lock(&tbl->proxy_queue.lock);
1344
David S. Millerf72051b2008-09-23 01:11:18 -07001345 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1346 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001349 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001350
David S. Millerf72051b2008-09-23 01:11:18 -07001351 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001352 if (tbl->proxy_redo && netif_running(dev)) {
1353 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001354 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001355 rcu_read_unlock();
1356 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001357 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001358 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359
1360 dev_put(dev);
1361 } else if (!sched_next || tdif < sched_next)
1362 sched_next = tdif;
1363 }
1364 del_timer(&tbl->proxy_timer);
1365 if (sched_next)
1366 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1367 spin_unlock(&tbl->proxy_queue.lock);
1368}
1369
1370void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1371 struct sk_buff *skb)
1372{
1373 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001374
1375 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001376 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001378 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 kfree_skb(skb);
1380 return;
1381 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001382
1383 NEIGH_CB(skb)->sched_next = sched_next;
1384 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
1386 spin_lock(&tbl->proxy_queue.lock);
1387 if (del_timer(&tbl->proxy_timer)) {
1388 if (time_before(tbl->proxy_timer.expires, sched_next))
1389 sched_next = tbl->proxy_timer.expires;
1390 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001391 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 dev_hold(skb->dev);
1393 __skb_queue_tail(&tbl->proxy_queue, skb);
1394 mod_timer(&tbl->proxy_timer, sched_next);
1395 spin_unlock(&tbl->proxy_queue.lock);
1396}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001397EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001399static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001400 struct net *net, int ifindex)
1401{
1402 struct neigh_parms *p;
1403
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001404 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001405 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001406 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001407 return p;
1408 }
1409
1410 return NULL;
1411}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412
1413struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1414 struct neigh_table *tbl)
1415{
Gao fengcf89d6b2013-06-20 10:01:32 +08001416 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001417 struct net *net = dev_net(dev);
1418 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Gao fengcf89d6b2013-06-20 10:01:32 +08001420 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422 p->tbl = tbl;
1423 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001425 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001426 dev_hold(dev);
1427 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001428 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001430
1431 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001432 dev_put(dev);
1433 kfree(p);
1434 return NULL;
1435 }
1436
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001438 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001440
1441 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 }
1443 return p;
1444}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001445EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
1447static void neigh_rcu_free_parms(struct rcu_head *head)
1448{
1449 struct neigh_parms *parms =
1450 container_of(head, struct neigh_parms, rcu_head);
1451
1452 neigh_parms_put(parms);
1453}
1454
1455void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1456{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 if (!parms || parms == &tbl->parms)
1458 return;
1459 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001460 list_del(&parms->list);
1461 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001463 if (parms->dev)
1464 dev_put(parms->dev);
1465 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001467EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Denis V. Lunev06f05112008-01-24 00:30:58 -08001469static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470{
1471 kfree(parms);
1472}
1473
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001474static struct lock_class_key neigh_table_proxy_queue_class;
1475
WANG Congd7480fd32014-11-10 15:59:36 -08001476static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1477
1478void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479{
1480 unsigned long now = jiffies;
1481 unsigned long phsize;
1482
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001483 INIT_LIST_HEAD(&tbl->parms_list);
1484 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001485 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001488 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 tbl->stats = alloc_percpu(struct neigh_statistics);
1491 if (!tbl->stats)
1492 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001493
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001495 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1496 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498#endif
1499
David S. Millercd089332011-07-11 01:28:12 -07001500 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
1502 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001503 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001505 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 panic("cannot allocate neighbour cache hashes");
1507
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001508 if (!tbl->entry_size)
1509 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1510 tbl->key_len, NEIGH_PRIV_ALIGN);
1511 else
1512 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1513
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001515 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301516 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1517 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001518 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001519 skb_queue_head_init_class(&tbl->proxy_queue,
1520 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521
1522 tbl->last_flush = now;
1523 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001524
WANG Congd7480fd32014-11-10 15:59:36 -08001525 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001527EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
WANG Congd7480fd32014-11-10 15:59:36 -08001529int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530{
WANG Congd7480fd32014-11-10 15:59:36 -08001531 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001533 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 del_timer_sync(&tbl->proxy_timer);
1535 pneigh_queue_purge(&tbl->proxy_queue);
1536 neigh_ifdown(tbl, NULL);
1537 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001538 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001540 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1541 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001542 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
1544 kfree(tbl->phash_buckets);
1545 tbl->phash_buckets = NULL;
1546
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001547 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1548
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001549 free_percpu(tbl->stats);
1550 tbl->stats = NULL;
1551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 return 0;
1553}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001554EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
WANG Congd7480fd32014-11-10 15:59:36 -08001556static struct neigh_table *neigh_find_table(int family)
1557{
1558 struct neigh_table *tbl = NULL;
1559
1560 switch (family) {
1561 case AF_INET:
1562 tbl = neigh_tables[NEIGH_ARP_TABLE];
1563 break;
1564 case AF_INET6:
1565 tbl = neigh_tables[NEIGH_ND_TABLE];
1566 break;
1567 case AF_DECnet:
1568 tbl = neigh_tables[NEIGH_DN_TABLE];
1569 break;
1570 }
1571
1572 return tbl;
1573}
1574
Thomas Graf661d2962013-03-21 07:45:29 +00001575static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001577 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001578 struct ndmsg *ndm;
1579 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 struct neigh_table *tbl;
WANG Congd7480fd32014-11-10 15:59:36 -08001581 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001583 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
Eric Dumazet110b2492010-10-04 04:27:36 +00001585 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001586 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 goto out;
1588
Thomas Grafa14a49d2006-08-07 17:53:08 -07001589 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1590 if (dst_attr == NULL)
1591 goto out;
1592
1593 ndm = nlmsg_data(nlh);
1594 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001595 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001596 if (dev == NULL) {
1597 err = -ENODEV;
1598 goto out;
1599 }
1600 }
1601
WANG Congd7480fd32014-11-10 15:59:36 -08001602 tbl = neigh_find_table(ndm->ndm_family);
1603 if (tbl == NULL)
1604 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
WANG Congd7480fd32014-11-10 15:59:36 -08001606 if (nla_len(dst_attr) < tbl->key_len)
1607 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
WANG Congd7480fd32014-11-10 15:59:36 -08001609 if (ndm->ndm_flags & NTF_PROXY) {
1610 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001611 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 }
WANG Congd7480fd32014-11-10 15:59:36 -08001613
1614 if (dev == NULL)
1615 goto out;
1616
1617 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1618 if (neigh == NULL) {
1619 err = -ENOENT;
1620 goto out;
1621 }
1622
1623 err = neigh_update(neigh, NULL, NUD_FAILED,
1624 NEIGH_UPDATE_F_OVERRIDE |
1625 NEIGH_UPDATE_F_ADMIN);
1626 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001627
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628out:
1629 return err;
1630}
1631
Thomas Graf661d2962013-03-21 07:45:29 +00001632static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633{
WANG Congd7480fd32014-11-10 15:59:36 -08001634 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001635 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001636 struct ndmsg *ndm;
1637 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 struct neigh_table *tbl;
1639 struct net_device *dev = NULL;
WANG Congd7480fd32014-11-10 15:59:36 -08001640 struct neighbour *neigh;
1641 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001642 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Eric Dumazet110b2492010-10-04 04:27:36 +00001644 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001645 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1646 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 goto out;
1648
Thomas Graf5208deb2006-08-07 17:55:40 -07001649 err = -EINVAL;
1650 if (tb[NDA_DST] == NULL)
1651 goto out;
1652
1653 ndm = nlmsg_data(nlh);
1654 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001655 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001656 if (dev == NULL) {
1657 err = -ENODEV;
1658 goto out;
1659 }
1660
1661 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001662 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001663 }
1664
WANG Congd7480fd32014-11-10 15:59:36 -08001665 tbl = neigh_find_table(ndm->ndm_family);
1666 if (tbl == NULL)
1667 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
WANG Congd7480fd32014-11-10 15:59:36 -08001669 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1670 goto out;
1671 dst = nla_data(tb[NDA_DST]);
1672 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673
WANG Congd7480fd32014-11-10 15:59:36 -08001674 if (ndm->ndm_flags & NTF_PROXY) {
1675 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676
WANG Congd7480fd32014-11-10 15:59:36 -08001677 err = -ENOBUFS;
1678 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1679 if (pn) {
1680 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001681 err = 0;
WANG Congd7480fd32014-11-10 15:59:36 -08001682 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001683 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 }
1685
WANG Congd7480fd32014-11-10 15:59:36 -08001686 if (dev == NULL)
1687 goto out;
1688
1689 neigh = neigh_lookup(tbl, dst, dev);
1690 if (neigh == NULL) {
1691 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1692 err = -ENOENT;
1693 goto out;
1694 }
1695
1696 neigh = __neigh_lookup_errno(tbl, dst, dev);
1697 if (IS_ERR(neigh)) {
1698 err = PTR_ERR(neigh);
1699 goto out;
1700 }
1701 } else {
1702 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1703 err = -EEXIST;
1704 neigh_release(neigh);
1705 goto out;
1706 }
1707
1708 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1709 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1710 }
1711
1712 if (ndm->ndm_flags & NTF_USE) {
1713 neigh_event_send(neigh, NULL);
1714 err = 0;
1715 } else
1716 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1717 neigh_release(neigh);
1718
Linus Torvalds1da177e2005-04-16 15:20:36 -07001719out:
1720 return err;
1721}
1722
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001723static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1724{
Thomas Grafca860fb2006-08-07 18:00:18 -07001725 struct nlattr *nest;
1726
1727 nest = nla_nest_start(skb, NDTA_PARMS);
1728 if (nest == NULL)
1729 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001730
David S. Miller9a6308d2012-04-01 20:06:28 -04001731 if ((parms->dev &&
1732 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1733 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001734 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1735 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001736 /* approximative value for deprecated QUEUE_LEN (in packets) */
1737 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001738 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1739 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1740 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1741 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1742 NEIGH_VAR(parms, UCAST_PROBES)) ||
1743 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1744 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001745 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1746 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001747 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1748 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1749 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001750 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001751 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1752 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1753 NEIGH_VAR(parms, RETRANS_TIME)) ||
1754 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1755 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1756 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1757 NEIGH_VAR(parms, PROXY_DELAY)) ||
1758 nla_put_msecs(skb, NDTPA_LOCKTIME,
1759 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001760 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001761 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001762
Thomas Grafca860fb2006-08-07 18:00:18 -07001763nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001764 nla_nest_cancel(skb, nest);
1765 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001766}
1767
Thomas Grafca860fb2006-08-07 18:00:18 -07001768static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1769 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001770{
1771 struct nlmsghdr *nlh;
1772 struct ndtmsg *ndtmsg;
1773
Thomas Grafca860fb2006-08-07 18:00:18 -07001774 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1775 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001776 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001777
Thomas Grafca860fb2006-08-07 18:00:18 -07001778 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001779
1780 read_lock_bh(&tbl->lock);
1781 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001782 ndtmsg->ndtm_pad1 = 0;
1783 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001784
David S. Miller9a6308d2012-04-01 20:06:28 -04001785 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1786 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1787 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1788 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1789 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1790 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001791 {
1792 unsigned long now = jiffies;
1793 unsigned int flush_delta = now - tbl->last_flush;
1794 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001795 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001796 struct ndt_config ndc = {
1797 .ndtc_key_len = tbl->key_len,
1798 .ndtc_entry_size = tbl->entry_size,
1799 .ndtc_entries = atomic_read(&tbl->entries),
1800 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1801 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001802 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1803 };
1804
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001805 rcu_read_lock_bh();
1806 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001807 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001808 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001809 rcu_read_unlock_bh();
1810
David S. Miller9a6308d2012-04-01 20:06:28 -04001811 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1812 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001813 }
1814
1815 {
1816 int cpu;
1817 struct ndt_stats ndst;
1818
1819 memset(&ndst, 0, sizeof(ndst));
1820
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001821 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001822 struct neigh_statistics *st;
1823
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001824 st = per_cpu_ptr(tbl->stats, cpu);
1825 ndst.ndts_allocs += st->allocs;
1826 ndst.ndts_destroys += st->destroys;
1827 ndst.ndts_hash_grows += st->hash_grows;
1828 ndst.ndts_res_failed += st->res_failed;
1829 ndst.ndts_lookups += st->lookups;
1830 ndst.ndts_hits += st->hits;
1831 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1832 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1833 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1834 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1835 }
1836
David S. Miller9a6308d2012-04-01 20:06:28 -04001837 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1838 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001839 }
1840
1841 BUG_ON(tbl->parms.dev);
1842 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001843 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844
1845 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001846 nlmsg_end(skb, nlh);
1847 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001848
Thomas Grafca860fb2006-08-07 18:00:18 -07001849nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001850 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001851 nlmsg_cancel(skb, nlh);
1852 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853}
1854
Thomas Grafca860fb2006-08-07 18:00:18 -07001855static int neightbl_fill_param_info(struct sk_buff *skb,
1856 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001857 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001858 u32 pid, u32 seq, int type,
1859 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001860{
1861 struct ndtmsg *ndtmsg;
1862 struct nlmsghdr *nlh;
1863
Thomas Grafca860fb2006-08-07 18:00:18 -07001864 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1865 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001866 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001867
Thomas Grafca860fb2006-08-07 18:00:18 -07001868 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001869
1870 read_lock_bh(&tbl->lock);
1871 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001872 ndtmsg->ndtm_pad1 = 0;
1873 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001874
Thomas Grafca860fb2006-08-07 18:00:18 -07001875 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1876 neightbl_fill_parms(skb, parms) < 0)
1877 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878
1879 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001880 nlmsg_end(skb, nlh);
1881 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001882errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001883 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001884 nlmsg_cancel(skb, nlh);
1885 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001886}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001887
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001888static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001889 [NDTA_NAME] = { .type = NLA_STRING },
1890 [NDTA_THRESH1] = { .type = NLA_U32 },
1891 [NDTA_THRESH2] = { .type = NLA_U32 },
1892 [NDTA_THRESH3] = { .type = NLA_U32 },
1893 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1894 [NDTA_PARMS] = { .type = NLA_NESTED },
1895};
1896
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001897static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001898 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1899 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1900 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1901 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1902 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1903 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1904 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1905 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1906 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1907 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1908 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1909 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1910 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1911};
1912
Thomas Graf661d2962013-03-21 07:45:29 +00001913static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001914{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001915 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001916 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001917 struct ndtmsg *ndtmsg;
1918 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd32014-11-10 15:59:36 -08001919 bool found = false;
1920 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921
Thomas Graf6b3f8672006-08-07 17:58:53 -07001922 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1923 nl_neightbl_policy);
1924 if (err < 0)
1925 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001926
Thomas Graf6b3f8672006-08-07 17:58:53 -07001927 if (tb[NDTA_NAME] == NULL) {
1928 err = -EINVAL;
1929 goto errout;
1930 }
1931
1932 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd32014-11-10 15:59:36 -08001933
1934 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1935 tbl = neigh_tables[tidx];
1936 if (!tbl)
1937 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001938 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1939 continue;
WANG Congd7480fd32014-11-10 15:59:36 -08001940 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1941 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001942 break;
WANG Congd7480fd32014-11-10 15:59:36 -08001943 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944 }
1945
WANG Congd7480fd32014-11-10 15:59:36 -08001946 if (!found)
1947 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001948
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001949 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001950 * We acquire tbl->lock to be nice to the periodic timers and
1951 * make sure they always see a consistent set of values.
1952 */
1953 write_lock_bh(&tbl->lock);
1954
Thomas Graf6b3f8672006-08-07 17:58:53 -07001955 if (tb[NDTA_PARMS]) {
1956 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001957 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001958 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001959
Thomas Graf6b3f8672006-08-07 17:58:53 -07001960 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1961 nl_ntbl_parm_policy);
1962 if (err < 0)
1963 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001964
Thomas Graf6b3f8672006-08-07 17:58:53 -07001965 if (tbp[NDTPA_IFINDEX])
1966 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001968 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001969 if (p == NULL) {
1970 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001971 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001972 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001973
Thomas Graf6b3f8672006-08-07 17:58:53 -07001974 for (i = 1; i <= NDTPA_MAX; i++) {
1975 if (tbp[i] == NULL)
1976 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001977
Thomas Graf6b3f8672006-08-07 17:58:53 -07001978 switch (i) {
1979 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001980 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
1981 nla_get_u32(tbp[i]) *
1982 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001983 break;
1984 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001985 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
1986 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001987 break;
1988 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001989 NEIGH_VAR_SET(p, PROXY_QLEN,
1990 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001991 break;
1992 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001993 NEIGH_VAR_SET(p, APP_PROBES,
1994 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001995 break;
1996 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001997 NEIGH_VAR_SET(p, UCAST_PROBES,
1998 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07001999 break;
2000 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002001 NEIGH_VAR_SET(p, MCAST_PROBES,
2002 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002003 break;
2004 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002005 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2006 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002007 /* update reachable_time as well, otherwise, the change will
2008 * only be effective after the next time neigh_periodic_work
2009 * decides to recompute it (can be multiple minutes)
2010 */
2011 p->reachable_time =
2012 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 break;
2014 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002015 NEIGH_VAR_SET(p, GC_STALETIME,
2016 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002017 break;
2018 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002019 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2020 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002021 break;
2022 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002023 NEIGH_VAR_SET(p, RETRANS_TIME,
2024 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 break;
2026 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002027 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2028 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002029 break;
2030 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002031 NEIGH_VAR_SET(p, PROXY_DELAY,
2032 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002033 break;
2034 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002035 NEIGH_VAR_SET(p, LOCKTIME,
2036 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002037 break;
2038 }
2039 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002040 }
2041
Gao fengdc25c672013-06-20 10:01:34 +08002042 err = -ENOENT;
2043 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2044 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2045 !net_eq(net, &init_net))
2046 goto errout_tbl_lock;
2047
Thomas Graf6b3f8672006-08-07 17:58:53 -07002048 if (tb[NDTA_THRESH1])
2049 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2050
2051 if (tb[NDTA_THRESH2])
2052 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2053
2054 if (tb[NDTA_THRESH3])
2055 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2056
2057 if (tb[NDTA_GC_INTERVAL])
2058 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2059
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002060 err = 0;
2061
Thomas Graf6b3f8672006-08-07 17:58:53 -07002062errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002063 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002065 return err;
2066}
2067
Thomas Grafc8822a42007-03-22 11:50:06 -07002068static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002069{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002070 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002071 int family, tidx, nidx = 0;
2072 int tbl_skip = cb->args[0];
2073 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002074 struct neigh_table *tbl;
2075
Thomas Grafca860fb2006-08-07 18:00:18 -07002076 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002077
WANG Congd7480fd32014-11-10 15:59:36 -08002078 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002079 struct neigh_parms *p;
2080
WANG Congd7480fd32014-11-10 15:59:36 -08002081 tbl = neigh_tables[tidx];
2082 if (!tbl)
2083 continue;
2084
Thomas Grafca860fb2006-08-07 18:00:18 -07002085 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002086 continue;
2087
Eric W. Biederman15e47302012-09-07 20:12:54 +00002088 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002089 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002090 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002091 break;
2092
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002093 nidx = 0;
2094 p = list_next_entry(&tbl->parms, list);
2095 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002096 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002097 continue;
2098
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002099 if (nidx < neigh_skip)
2100 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002101
Thomas Grafca860fb2006-08-07 18:00:18 -07002102 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002103 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002104 cb->nlh->nlmsg_seq,
2105 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002106 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002107 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002108 next:
2109 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002110 }
2111
Thomas Grafca860fb2006-08-07 18:00:18 -07002112 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002113 }
2114out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002115 cb->args[0] = tidx;
2116 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002117
2118 return skb->len;
2119}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002120
Thomas Graf8b8aec52006-08-07 17:56:37 -07002121static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2122 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123{
2124 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002126 struct nlmsghdr *nlh;
2127 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002128
Thomas Graf8b8aec52006-08-07 17:56:37 -07002129 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2130 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002131 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002132
2133 ndm = nlmsg_data(nlh);
2134 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002135 ndm->ndm_pad1 = 0;
2136 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002137 ndm->ndm_flags = neigh->flags;
2138 ndm->ndm_type = neigh->type;
2139 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140
David S. Miller9a6308d2012-04-01 20:06:28 -04002141 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2142 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002143
2144 read_lock_bh(&neigh->lock);
2145 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002146 if (neigh->nud_state & NUD_VALID) {
2147 char haddr[MAX_ADDR_LEN];
2148
2149 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2150 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2151 read_unlock_bh(&neigh->lock);
2152 goto nla_put_failure;
2153 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002154 }
2155
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002156 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2157 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2158 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002159 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2160 read_unlock_bh(&neigh->lock);
2161
David S. Miller9a6308d2012-04-01 20:06:28 -04002162 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2163 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2164 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002165
Johannes Berg053c0952015-01-16 22:09:00 +01002166 nlmsg_end(skb, nlh);
2167 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002168
2169nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002170 nlmsg_cancel(skb, nlh);
2171 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172}
2173
Tony Zelenoff84920c12012-01-26 22:28:58 +00002174static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2175 u32 pid, u32 seq, int type, unsigned int flags,
2176 struct neigh_table *tbl)
2177{
2178 struct nlmsghdr *nlh;
2179 struct ndmsg *ndm;
2180
2181 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2182 if (nlh == NULL)
2183 return -EMSGSIZE;
2184
2185 ndm = nlmsg_data(nlh);
2186 ndm->ndm_family = tbl->family;
2187 ndm->ndm_pad1 = 0;
2188 ndm->ndm_pad2 = 0;
2189 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002190 ndm->ndm_type = RTN_UNICAST;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002191 ndm->ndm_ifindex = pn->dev->ifindex;
2192 ndm->ndm_state = NUD_NONE;
2193
David S. Miller9a6308d2012-04-01 20:06:28 -04002194 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2195 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002196
Johannes Berg053c0952015-01-16 22:09:00 +01002197 nlmsg_end(skb, nlh);
2198 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002199
2200nla_put_failure:
2201 nlmsg_cancel(skb, nlh);
2202 return -EMSGSIZE;
2203}
2204
Thomas Grafd961db32007-08-08 23:12:56 -07002205static void neigh_update_notify(struct neighbour *neigh)
2206{
2207 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2208 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2209}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002210
2211static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2212 struct netlink_callback *cb)
2213{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002214 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215 struct neighbour *n;
2216 int rc, h, s_h = cb->args[1];
2217 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002218 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002220 rcu_read_lock_bh();
2221 nht = rcu_dereference_bh(tbl->nht);
2222
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002223 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002224 if (h > s_h)
2225 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002226 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2227 n != NULL;
2228 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002229 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002230 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002231 if (idx < s_idx)
2232 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002233 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002235 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002236 NLM_F_MULTI) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237 rc = -1;
2238 goto out;
2239 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002240next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002241 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002243 }
2244 rc = skb->len;
2245out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002246 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 cb->args[1] = h;
2248 cb->args[2] = idx;
2249 return rc;
2250}
2251
Tony Zelenoff84920c12012-01-26 22:28:58 +00002252static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2253 struct netlink_callback *cb)
2254{
2255 struct pneigh_entry *n;
2256 struct net *net = sock_net(skb->sk);
2257 int rc, h, s_h = cb->args[3];
2258 int idx, s_idx = idx = cb->args[4];
2259
2260 read_lock_bh(&tbl->lock);
2261
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002262 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002263 if (h > s_h)
2264 s_idx = 0;
2265 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2266 if (dev_net(n->dev) != net)
2267 continue;
2268 if (idx < s_idx)
2269 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002270 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002271 cb->nlh->nlmsg_seq,
2272 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002273 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002274 read_unlock_bh(&tbl->lock);
2275 rc = -1;
2276 goto out;
2277 }
2278 next:
2279 idx++;
2280 }
2281 }
2282
2283 read_unlock_bh(&tbl->lock);
2284 rc = skb->len;
2285out:
2286 cb->args[3] = h;
2287 cb->args[4] = idx;
2288 return rc;
2289
2290}
2291
Thomas Grafc8822a42007-03-22 11:50:06 -07002292static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002293{
2294 struct neigh_table *tbl;
2295 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002296 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002297 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Thomas Graf8b8aec52006-08-07 17:56:37 -07002299 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002300
2301 /* check for full ndmsg structure presence, family member is
2302 * the same for both structures
2303 */
2304 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2305 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2306 proxy = 1;
2307
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 s_t = cb->args[0];
2309
WANG Congd7480fd32014-11-10 15:59:36 -08002310 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2311 tbl = neigh_tables[t];
2312
2313 if (!tbl)
2314 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002315 if (t < s_t || (family && tbl->family != family))
2316 continue;
2317 if (t > s_t)
2318 memset(&cb->args[1], 0, sizeof(cb->args) -
2319 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002320 if (proxy)
2321 err = pneigh_dump_table(tbl, skb, cb);
2322 else
2323 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002324 if (err < 0)
2325 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327
2328 cb->args[0] = t;
2329 return skb->len;
2330}
2331
2332void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2333{
2334 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002335 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002337 rcu_read_lock_bh();
2338 nht = rcu_dereference_bh(tbl->nht);
2339
Eric Dumazet767e97e2010-10-06 17:49:21 -07002340 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002341 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002342 struct neighbour *n;
2343
Eric Dumazet767e97e2010-10-06 17:49:21 -07002344 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2345 n != NULL;
2346 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 cb(n, cookie);
2348 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002349 read_unlock(&tbl->lock);
2350 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351}
2352EXPORT_SYMBOL(neigh_for_each);
2353
2354/* The tbl->lock must be held as a writer and BH disabled. */
2355void __neigh_for_each_release(struct neigh_table *tbl,
2356 int (*cb)(struct neighbour *))
2357{
2358 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002359 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002361 nht = rcu_dereference_protected(tbl->nht,
2362 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002363 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002364 struct neighbour *n;
2365 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002367 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002368 while ((n = rcu_dereference_protected(*np,
2369 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 int release;
2371
2372 write_lock(&n->lock);
2373 release = cb(n);
2374 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002375 rcu_assign_pointer(*np,
2376 rcu_dereference_protected(n->next,
2377 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 n->dead = 1;
2379 } else
2380 np = &n->next;
2381 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002382 if (release)
2383 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 }
2385 }
2386}
2387EXPORT_SYMBOL(__neigh_for_each_release);
2388
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002389int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002390 const void *addr, struct sk_buff *skb)
2391{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002392 int err = -EAFNOSUPPORT;
2393 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002394 struct neigh_table *tbl;
2395 struct neighbour *neigh;
2396
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002397 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002398 if (!tbl)
2399 goto out;
2400 neigh = __neigh_lookup_noref(tbl, addr, dev);
2401 if (!neigh)
2402 neigh = __neigh_create(tbl, addr, dev, false);
2403 err = PTR_ERR(neigh);
2404 if (IS_ERR(neigh))
2405 goto out_kfree_skb;
2406 err = neigh->output(neigh, skb);
2407 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002408 else if (index == NEIGH_LINK_TABLE) {
2409 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2410 addr, NULL, skb->len);
2411 if (err < 0)
2412 goto out_kfree_skb;
2413 err = dev_queue_xmit(skb);
2414 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002415out:
2416 return err;
2417out_kfree_skb:
2418 kfree_skb(skb);
2419 goto out;
2420}
2421EXPORT_SYMBOL(neigh_xmit);
2422
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423#ifdef CONFIG_PROC_FS
2424
2425static struct neighbour *neigh_get_first(struct seq_file *seq)
2426{
2427 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002428 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002429 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 struct neighbour *n = NULL;
2431 int bucket = state->bucket;
2432
2433 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002434 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002435 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
2437 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002438 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002439 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 if (state->neigh_sub_iter) {
2441 loff_t fakep = 0;
2442 void *v;
2443
2444 v = state->neigh_sub_iter(state, n, &fakep);
2445 if (!v)
2446 goto next;
2447 }
2448 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2449 break;
2450 if (n->nud_state & ~NUD_NOARP)
2451 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002452next:
2453 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002454 }
2455
2456 if (n)
2457 break;
2458 }
2459 state->bucket = bucket;
2460
2461 return n;
2462}
2463
2464static struct neighbour *neigh_get_next(struct seq_file *seq,
2465 struct neighbour *n,
2466 loff_t *pos)
2467{
2468 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002469 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002470 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471
2472 if (state->neigh_sub_iter) {
2473 void *v = state->neigh_sub_iter(state, n, pos);
2474 if (v)
2475 return n;
2476 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002477 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478
2479 while (1) {
2480 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002481 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002482 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 if (state->neigh_sub_iter) {
2484 void *v = state->neigh_sub_iter(state, n, pos);
2485 if (v)
2486 return n;
2487 goto next;
2488 }
2489 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2490 break;
2491
2492 if (n->nud_state & ~NUD_NOARP)
2493 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002494next:
2495 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496 }
2497
2498 if (n)
2499 break;
2500
David S. Millercd089332011-07-11 01:28:12 -07002501 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 break;
2503
Eric Dumazet767e97e2010-10-06 17:49:21 -07002504 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 }
2506
2507 if (n && pos)
2508 --(*pos);
2509 return n;
2510}
2511
2512static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2513{
2514 struct neighbour *n = neigh_get_first(seq);
2515
2516 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002517 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518 while (*pos) {
2519 n = neigh_get_next(seq, n, pos);
2520 if (!n)
2521 break;
2522 }
2523 }
2524 return *pos ? NULL : n;
2525}
2526
2527static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2528{
2529 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002530 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002531 struct neigh_table *tbl = state->tbl;
2532 struct pneigh_entry *pn = NULL;
2533 int bucket = state->bucket;
2534
2535 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2536 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2537 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002538 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002539 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 if (pn)
2541 break;
2542 }
2543 state->bucket = bucket;
2544
2545 return pn;
2546}
2547
2548static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2549 struct pneigh_entry *pn,
2550 loff_t *pos)
2551{
2552 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002553 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 struct neigh_table *tbl = state->tbl;
2555
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002556 do {
2557 pn = pn->next;
2558 } while (pn && !net_eq(pneigh_net(pn), net));
2559
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 while (!pn) {
2561 if (++state->bucket > PNEIGH_HASHMASK)
2562 break;
2563 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002564 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002565 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566 if (pn)
2567 break;
2568 }
2569
2570 if (pn && pos)
2571 --(*pos);
2572
2573 return pn;
2574}
2575
2576static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2577{
2578 struct pneigh_entry *pn = pneigh_get_first(seq);
2579
2580 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002581 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 while (*pos) {
2583 pn = pneigh_get_next(seq, pn, pos);
2584 if (!pn)
2585 break;
2586 }
2587 }
2588 return *pos ? NULL : pn;
2589}
2590
2591static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2592{
2593 struct neigh_seq_state *state = seq->private;
2594 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002595 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
Chris Larson745e2032008-08-03 01:10:55 -07002597 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002599 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
2601 return rc;
2602}
2603
2604void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002605 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606{
2607 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 state->tbl = tbl;
2610 state->bucket = 0;
2611 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2612
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002613 rcu_read_lock_bh();
2614 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002615
Chris Larson745e2032008-08-03 01:10:55 -07002616 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002617}
2618EXPORT_SYMBOL(neigh_seq_start);
2619
2620void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2621{
2622 struct neigh_seq_state *state;
2623 void *rc;
2624
2625 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002626 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 goto out;
2628 }
2629
2630 state = seq->private;
2631 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2632 rc = neigh_get_next(seq, v, NULL);
2633 if (rc)
2634 goto out;
2635 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2636 rc = pneigh_get_first(seq);
2637 } else {
2638 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2639 rc = pneigh_get_next(seq, v, NULL);
2640 }
2641out:
2642 ++(*pos);
2643 return rc;
2644}
2645EXPORT_SYMBOL(neigh_seq_next);
2646
2647void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002648 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002650 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651}
2652EXPORT_SYMBOL(neigh_seq_stop);
2653
2654/* statistics via seq_file */
2655
2656static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2657{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002658 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 int cpu;
2660
2661 if (*pos == 0)
2662 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002663
Rusty Russell0f23174a2008-12-29 12:23:42 +00002664 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 if (!cpu_possible(cpu))
2666 continue;
2667 *pos = cpu+1;
2668 return per_cpu_ptr(tbl->stats, cpu);
2669 }
2670 return NULL;
2671}
2672
2673static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2674{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002675 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676 int cpu;
2677
Rusty Russell0f23174a2008-12-29 12:23:42 +00002678 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 if (!cpu_possible(cpu))
2680 continue;
2681 *pos = cpu+1;
2682 return per_cpu_ptr(tbl->stats, cpu);
2683 }
2684 return NULL;
2685}
2686
2687static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2688{
2689
2690}
2691
2692static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2693{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002694 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 struct neigh_statistics *st = v;
2696
2697 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002698 seq_printf(seq, "entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699 return 0;
2700 }
2701
2702 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002703 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002704 atomic_read(&tbl->entries),
2705
2706 st->allocs,
2707 st->destroys,
2708 st->hash_grows,
2709
2710 st->lookups,
2711 st->hits,
2712
2713 st->res_failed,
2714
2715 st->rcv_probes_mcast,
2716 st->rcv_probes_ucast,
2717
2718 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002719 st->forced_gc_runs,
2720 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 );
2722
2723 return 0;
2724}
2725
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002726static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727 .start = neigh_stat_seq_start,
2728 .next = neigh_stat_seq_next,
2729 .stop = neigh_stat_seq_stop,
2730 .show = neigh_stat_seq_show,
2731};
2732
2733static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2734{
2735 int ret = seq_open(file, &neigh_stat_seq_ops);
2736
2737 if (!ret) {
2738 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002739 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740 }
2741 return ret;
2742};
2743
Arjan van de Ven9a321442007-02-12 00:55:35 -08002744static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 .owner = THIS_MODULE,
2746 .open = neigh_stat_seq_open,
2747 .read = seq_read,
2748 .llseek = seq_lseek,
2749 .release = seq_release,
2750};
2751
2752#endif /* CONFIG_PROC_FS */
2753
Thomas Graf339bf982006-11-10 14:10:15 -08002754static inline size_t neigh_nlmsg_size(void)
2755{
2756 return NLMSG_ALIGN(sizeof(struct ndmsg))
2757 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2758 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2759 + nla_total_size(sizeof(struct nda_cacheinfo))
2760 + nla_total_size(4); /* NDA_PROBES */
2761}
2762
Thomas Grafb8673312006-08-15 00:33:14 -07002763static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002765 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002766 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002767 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768
Thomas Graf339bf982006-11-10 14:10:15 -08002769 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002770 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002771 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002772
Thomas Grafb8673312006-08-15 00:33:14 -07002773 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002774 if (err < 0) {
2775 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2776 WARN_ON(err == -EMSGSIZE);
2777 kfree_skb(skb);
2778 goto errout;
2779 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002780 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2781 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002782errout:
2783 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002784 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002785}
2786
2787void neigh_app_ns(struct neighbour *n)
2788{
2789 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002790}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002791EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792
2793#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002794static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002795static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002796static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797
Joe Perchesfe2c6332013-06-11 23:04:25 -07002798static int proc_unres_qlen(struct ctl_table *ctl, int write,
2799 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002800{
2801 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002802 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002803
Shan Weice46cc62012-12-04 18:49:15 +00002804 tmp.extra1 = &zero;
2805 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002806 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002807
2808 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2809 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2810
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002811 if (write && !ret)
2812 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2813 return ret;
2814}
2815
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002816static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2817 int family)
2818{
Jiri Pirkobba24892013-12-07 19:26:57 +01002819 switch (family) {
2820 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002821 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002822 case AF_INET6:
2823 return __in6_dev_nd_parms_get_rcu(dev);
2824 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002825 return NULL;
2826}
2827
2828static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2829 int index)
2830{
2831 struct net_device *dev;
2832 int family = neigh_parms_family(p);
2833
2834 rcu_read_lock();
2835 for_each_netdev_rcu(net, dev) {
2836 struct neigh_parms *dst_p =
2837 neigh_get_dev_parms_rcu(dev, family);
2838
2839 if (dst_p && !test_bit(index, dst_p->data_state))
2840 dst_p->data[index] = p->data[index];
2841 }
2842 rcu_read_unlock();
2843}
2844
2845static void neigh_proc_update(struct ctl_table *ctl, int write)
2846{
2847 struct net_device *dev = ctl->extra1;
2848 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002849 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002850 int index = (int *) ctl->data - p->data;
2851
2852 if (!write)
2853 return;
2854
2855 set_bit(index, p->data_state);
2856 if (!dev) /* NULL dev means this is default value */
2857 neigh_copy_dflt_parms(net, p, index);
2858}
2859
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002860static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2861 void __user *buffer,
2862 size_t *lenp, loff_t *ppos)
2863{
2864 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002865 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002866
2867 tmp.extra1 = &zero;
2868 tmp.extra2 = &int_max;
2869
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002870 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2871 neigh_proc_update(ctl, write);
2872 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002873}
2874
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002875int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2876 void __user *buffer, size_t *lenp, loff_t *ppos)
2877{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002878 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2879
2880 neigh_proc_update(ctl, write);
2881 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002882}
2883EXPORT_SYMBOL(neigh_proc_dointvec);
2884
2885int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2886 void __user *buffer,
2887 size_t *lenp, loff_t *ppos)
2888{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002889 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2890
2891 neigh_proc_update(ctl, write);
2892 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002893}
2894EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2895
2896static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2897 void __user *buffer,
2898 size_t *lenp, loff_t *ppos)
2899{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002900 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2901
2902 neigh_proc_update(ctl, write);
2903 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002904}
2905
2906int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2907 void __user *buffer,
2908 size_t *lenp, loff_t *ppos)
2909{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002910 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2911
2912 neigh_proc_update(ctl, write);
2913 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002914}
2915EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2916
2917static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2918 void __user *buffer,
2919 size_t *lenp, loff_t *ppos)
2920{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002921 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2922
2923 neigh_proc_update(ctl, write);
2924 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002925}
2926
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002927static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
2928 void __user *buffer,
2929 size_t *lenp, loff_t *ppos)
2930{
2931 struct neigh_parms *p = ctl->extra2;
2932 int ret;
2933
2934 if (strcmp(ctl->procname, "base_reachable_time") == 0)
2935 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2936 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
2937 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2938 else
2939 ret = -1;
2940
2941 if (write && ret == 0) {
2942 /* update reachable_time as well, otherwise, the change will
2943 * only be effective after the next time neigh_periodic_work
2944 * decides to recompute it
2945 */
2946 p->reachable_time =
2947 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
2948 }
2949 return ret;
2950}
2951
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002952#define NEIGH_PARMS_DATA_OFFSET(index) \
2953 (&((struct neigh_parms *) 0)->data[index])
2954
2955#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2956 [NEIGH_VAR_ ## attr] = { \
2957 .procname = name, \
2958 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2959 .maxlen = sizeof(int), \
2960 .mode = mval, \
2961 .proc_handler = proc, \
2962 }
2963
2964#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2965 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2966
2967#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002968 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002969
2970#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002971 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002972
2973#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002974 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002975
2976#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002977 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002978
2979#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002980 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002981
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982static struct neigh_sysctl_table {
2983 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002984 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002985} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002986 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002987 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2988 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2989 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2990 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2991 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2992 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2993 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2994 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2995 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2996 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2997 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2998 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
2999 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3000 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3001 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003002 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003003 .procname = "gc_interval",
3004 .maxlen = sizeof(int),
3005 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003006 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003008 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003009 .procname = "gc_thresh1",
3010 .maxlen = sizeof(int),
3011 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003012 .extra1 = &zero,
3013 .extra2 = &int_max,
3014 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003015 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003016 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003017 .procname = "gc_thresh2",
3018 .maxlen = sizeof(int),
3019 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003020 .extra1 = &zero,
3021 .extra2 = &int_max,
3022 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003023 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003024 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003025 .procname = "gc_thresh3",
3026 .maxlen = sizeof(int),
3027 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003028 .extra1 = &zero,
3029 .extra2 = &int_max,
3030 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003031 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003032 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 },
3034};
3035
3036int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003037 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003038{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003039 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003040 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003041 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003042 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003043 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003045 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003047 goto err;
3048
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003049 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003050 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003051 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003052 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
3055 if (dev) {
3056 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003057 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003058 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3059 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003060 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003061 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003062 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003063 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3064 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3065 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3066 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003067 }
3068
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003069 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003070 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003071 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003073 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003075 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003076 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003077 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003078 } else {
3079 /* Those handlers will update p->reachable_time after
3080 * base_reachable_time(_ms) is set to ensure the new timer starts being
3081 * applied after the next neighbour update instead of waiting for
3082 * neigh_periodic_work to update its value (can be multiple minutes)
3083 * So any handler that replaces them should do this as well
3084 */
3085 /* ReachableTime */
3086 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3087 neigh_proc_base_reachable_time;
3088 /* ReachableTime (in milliseconds) */
3089 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3090 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 }
3092
Eric W. Biederman464dc802012-11-16 03:02:59 +00003093 /* Don't export sysctls to unprivileged users */
3094 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3095 t->neigh_vars[0].procname = NULL;
3096
Jiri Pirko73af6142013-12-07 19:26:55 +01003097 switch (neigh_parms_family(p)) {
3098 case AF_INET:
3099 p_name = "ipv4";
3100 break;
3101 case AF_INET6:
3102 p_name = "ipv6";
3103 break;
3104 default:
3105 BUG();
3106 }
3107
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003108 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3109 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003110 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003111 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003112 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003113 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003114
Linus Torvalds1da177e2005-04-16 15:20:36 -07003115 p->sysctl_table = t;
3116 return 0;
3117
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003118free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003120err:
3121 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003123EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124
3125void neigh_sysctl_unregister(struct neigh_parms *p)
3126{
3127 if (p->sysctl_table) {
3128 struct neigh_sysctl_table *t = p->sysctl_table;
3129 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003130 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 kfree(t);
3132 }
3133}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003134EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135
3136#endif /* CONFIG_SYSCTL */
3137
Thomas Grafc8822a42007-03-22 11:50:06 -07003138static int __init neigh_init(void)
3139{
Greg Rosec7ac8672011-06-10 01:27:09 +00003140 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3141 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3142 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003143
Greg Rosec7ac8672011-06-10 01:27:09 +00003144 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3145 NULL);
3146 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003147
3148 return 0;
3149}
3150
3151subsys_initcall(neigh_init);
3152