blob: 7bb12e07ffef4273e156893cc150ea5c9d79e8bd [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);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100103 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Thomas Graf4f494552007-08-08 23:12:36 -0700104 neigh_release(neigh);
105}
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107/*
108 * It is random distribution in the interval (1/2)*base...(3/2)*base.
109 * It corresponds to default IPv6 settings and is not overridable,
110 * because it is really reasonable choice.
111 */
112
113unsigned long neigh_rand_reach_time(unsigned long base)
114{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500115 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900117EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119
120static int neigh_forced_gc(struct neigh_table *tbl)
121{
122 int shrunk = 0;
123 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000124 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
127
128 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000129 nht = rcu_dereference_protected(tbl->nht,
130 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700131 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700132 struct neighbour *n;
133 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000135 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700136 while ((n = rcu_dereference_protected(*np,
137 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138 /* Neighbour record may be discarded if:
139 * - nobody refers to it.
140 * - it is not permanent
141 */
142 write_lock(&n->lock);
143 if (atomic_read(&n->refcnt) == 1 &&
144 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700145 rcu_assign_pointer(*np,
146 rcu_dereference_protected(n->next,
147 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 n->dead = 1;
149 shrunk = 1;
150 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700151 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 continue;
153 }
154 write_unlock(&n->lock);
155 np = &n->next;
156 }
157 }
158
159 tbl->last_flush = jiffies;
160
161 write_unlock_bh(&tbl->lock);
162
163 return shrunk;
164}
165
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800166static void neigh_add_timer(struct neighbour *n, unsigned long when)
167{
168 neigh_hold(n);
169 if (unlikely(mod_timer(&n->timer, when))) {
170 printk("NEIGH: BUG, double timer add, state is %x\n",
171 n->nud_state);
172 dump_stack();
173 }
174}
175
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176static int neigh_del_timer(struct neighbour *n)
177{
178 if ((n->nud_state & NUD_IN_TIMER) &&
179 del_timer(&n->timer)) {
180 neigh_release(n);
181 return 1;
182 }
183 return 0;
184}
185
186static void pneigh_queue_purge(struct sk_buff_head *list)
187{
188 struct sk_buff *skb;
189
190 while ((skb = skb_dequeue(list)) != NULL) {
191 dev_put(skb->dev);
192 kfree_skb(skb);
193 }
194}
195
Herbert Xu49636bb2005-10-23 17:18:00 +1000196static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197{
198 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000199 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000201 nht = rcu_dereference_protected(tbl->nht,
202 lockdep_is_held(&tbl->lock));
203
David S. Millercd089332011-07-11 01:28:12 -0700204 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700205 struct neighbour *n;
206 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700207
Eric Dumazet767e97e2010-10-06 17:49:21 -0700208 while ((n = rcu_dereference_protected(*np,
209 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210 if (dev && n->dev != dev) {
211 np = &n->next;
212 continue;
213 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700214 rcu_assign_pointer(*np,
215 rcu_dereference_protected(n->next,
216 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700217 write_lock(&n->lock);
218 neigh_del_timer(n);
219 n->dead = 1;
220
221 if (atomic_read(&n->refcnt) != 1) {
222 /* The most unpleasant situation.
223 We must destroy neighbour entry,
224 but someone still uses it.
225
226 The destroy will be delayed until
227 the last user releases us, but
228 we must kill timers etc. and move
229 it to safe state.
230 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700231 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000232 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233 n->output = neigh_blackhole;
234 if (n->nud_state & NUD_VALID)
235 n->nud_state = NUD_NOARP;
236 else
237 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000238 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 }
240 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700241 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 }
243 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000244}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245
Herbert Xu49636bb2005-10-23 17:18:00 +1000246void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
247{
248 write_lock_bh(&tbl->lock);
249 neigh_flush_dev(tbl, dev);
250 write_unlock_bh(&tbl->lock);
251}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900252EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000253
254int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
255{
256 write_lock_bh(&tbl->lock);
257 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 pneigh_ifdown(tbl, dev);
259 write_unlock_bh(&tbl->lock);
260
261 del_timer_sync(&tbl->proxy_timer);
262 pneigh_queue_purge(&tbl->proxy_queue);
263 return 0;
264}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900265EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
David Miller596b9b62011-07-25 00:01:25 +0000267static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
269 struct neighbour *n = NULL;
270 unsigned long now = jiffies;
271 int entries;
272
273 entries = atomic_inc_return(&tbl->entries) - 1;
274 if (entries >= tbl->gc_thresh3 ||
275 (entries >= tbl->gc_thresh2 &&
276 time_after(now, tbl->last_flush + 5 * HZ))) {
277 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700278 entries >= tbl->gc_thresh3) {
279 net_info_ratelimited("%s: neighbor table overflow!\n",
280 tbl->id);
281 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000286 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (!n)
288 goto out_entries;
289
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700290 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000292 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 n->updated = n->used = now;
294 n->nud_state = NUD_NONE;
295 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700296 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800298 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 NEIGH_CACHE_STAT_INC(tbl, allocs);
301 n->tbl = tbl;
302 atomic_set(&n->refcnt, 1);
303 n->dead = 1;
304out:
305 return n;
306
307out_entries:
308 atomic_dec(&tbl->entries);
309 goto out;
310}
311
David S. Miller2c2aba62011-12-28 15:06:58 -0500312static void neigh_get_hash_rnd(u32 *x)
313{
314 get_random_bytes(x, sizeof(*x));
315 *x |= 1;
316}
317
David S. Millercd089332011-07-11 01:28:12 -0700318static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
David S. Millercd089332011-07-11 01:28:12 -0700320 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000321 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000322 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500323 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000325 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
326 if (!ret)
327 return NULL;
328 if (size <= PAGE_SIZE)
329 buckets = kzalloc(size, GFP_ATOMIC);
330 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000331 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000332 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
333 get_order(size));
334 if (!buckets) {
335 kfree(ret);
336 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000338 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700339 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500340 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
341 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 return ret;
343}
344
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000345static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000347 struct neigh_hash_table *nht = container_of(head,
348 struct neigh_hash_table,
349 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700350 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000351 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000354 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 free_pages((unsigned long)buckets, get_order(size));
357 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700361 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 unsigned int i, hash;
364 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
367
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000368 old_nht = rcu_dereference_protected(tbl->nht,
369 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700370 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000371 if (!new_nht)
372 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
David S. Millercd089332011-07-11 01:28:12 -0700374 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 struct neighbour *n, *next;
376
Eric Dumazet767e97e2010-10-06 17:49:21 -0700377 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
378 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000379 n != NULL;
380 n = next) {
381 hash = tbl->hash(n->primary_key, n->dev,
382 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
David S. Millercd089332011-07-11 01:28:12 -0700384 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700385 next = rcu_dereference_protected(n->next,
386 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Eric Dumazet767e97e2010-10-06 17:49:21 -0700388 rcu_assign_pointer(n->next,
389 rcu_dereference_protected(
390 new_nht->hash_buckets[hash],
391 lockdep_is_held(&tbl->lock)));
392 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000396 rcu_assign_pointer(tbl->nht, new_nht);
397 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
398 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
401struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
402 struct net_device *dev)
403{
404 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 NEIGH_CACHE_STAT_INC(tbl, lookups);
407
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600409 n = __neigh_lookup_noref(tbl, pkey, dev);
410 if (n) {
411 if (!atomic_inc_not_zero(&n->refcnt))
412 n = NULL;
413 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700415
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000416 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return n;
418}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900419EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Eric W. Biederman426b5302008-01-24 00:13:18 -0800421struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
422 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 struct neighbour *n;
425 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800426 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 NEIGH_CACHE_STAT_INC(tbl, lookups);
430
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000431 rcu_read_lock_bh();
432 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700433 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700434
435 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
436 n != NULL;
437 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800438 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900439 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700440 if (!atomic_inc_not_zero(&n->refcnt))
441 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 NEIGH_CACHE_STAT_INC(tbl, hits);
443 break;
444 }
445 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700446
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000447 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return n;
449}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900450EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
David S. Millera263b302012-07-02 02:02:15 -0700452struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
453 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 u32 hash_val;
456 int key_len = tbl->key_len;
457 int error;
David Miller596b9b62011-07-25 00:01:25 +0000458 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000459 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 if (!n) {
462 rc = ERR_PTR(-ENOBUFS);
463 goto out;
464 }
465
466 memcpy(n->primary_key, pkey, key_len);
467 n->dev = dev;
468 dev_hold(dev);
469
470 /* Protocol specific setup. */
471 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
472 rc = ERR_PTR(error);
473 goto out_neigh_release;
474 }
475
David Millerda6a8fa2011-07-25 00:01:38 +0000476 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200477 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000478 if (error < 0) {
479 rc = ERR_PTR(error);
480 goto out_neigh_release;
481 }
482 }
483
David S. Miller447f2192011-12-19 15:04:41 -0500484 /* Device specific setup. */
485 if (n->parms->neigh_setup &&
486 (error = n->parms->neigh_setup(n)) < 0) {
487 rc = ERR_PTR(error);
488 goto out_neigh_release;
489 }
490
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100491 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 nht = rcu_dereference_protected(tbl->nht,
495 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
David S. Millercd089332011-07-11 01:28:12 -0700497 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
498 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
David S. Millercd089332011-07-11 01:28:12 -0700500 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 if (n->parms->dead) {
503 rc = ERR_PTR(-EINVAL);
504 goto out_tbl_unlock;
505 }
506
Eric Dumazet767e97e2010-10-06 17:49:21 -0700507 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
508 lockdep_is_held(&tbl->lock));
509 n1 != NULL;
510 n1 = rcu_dereference_protected(n1->next,
511 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700513 if (want_ref)
514 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 rc = n1;
516 goto out_tbl_unlock;
517 }
518 }
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700521 if (want_ref)
522 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700523 rcu_assign_pointer(n->next,
524 rcu_dereference_protected(nht->hash_buckets[hash_val],
525 lockdep_is_held(&tbl->lock)));
526 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000528 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 rc = n;
530out:
531 return rc;
532out_tbl_unlock:
533 write_unlock_bh(&tbl->lock);
534out_neigh_release:
535 neigh_release(n);
536 goto out;
537}
David S. Millera263b302012-07-02 02:02:15 -0700538EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900540static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700541{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700542 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700543 hash_val ^= (hash_val >> 16);
544 hash_val ^= hash_val >> 8;
545 hash_val ^= hash_val >> 4;
546 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900547 return hash_val;
548}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700549
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900550static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
551 struct net *net,
552 const void *pkey,
553 int key_len,
554 struct net_device *dev)
555{
556 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700557 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700559 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900560 return n;
561 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700562 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900563 return NULL;
564}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700565
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900566struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
567 struct net *net, const void *pkey, struct net_device *dev)
568{
569 int key_len = tbl->key_len;
570 u32 hash_val = pneigh_hash(pkey, key_len);
571
572 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
573 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700574}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900575EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576
Eric W. Biederman426b5302008-01-24 00:13:18 -0800577struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
578 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 struct net_device *dev, int creat)
580{
581 struct pneigh_entry *n;
582 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900583 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900586 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
587 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900589
590 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 goto out;
592
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700593 ASSERT_RTNL();
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
596 if (!n)
597 goto out;
598
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500599 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 memcpy(n->key, pkey, key_len);
601 n->dev = dev;
602 if (dev)
603 dev_hold(dev);
604
605 if (tbl->pconstructor && tbl->pconstructor(n)) {
606 if (dev)
607 dev_put(dev);
608 kfree(n);
609 n = NULL;
610 goto out;
611 }
612
613 write_lock_bh(&tbl->lock);
614 n->next = tbl->phash_buckets[hash_val];
615 tbl->phash_buckets[hash_val] = n;
616 write_unlock_bh(&tbl->lock);
617out:
618 return n;
619}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900620EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622
Eric W. Biederman426b5302008-01-24 00:13:18 -0800623int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 struct net_device *dev)
625{
626 struct pneigh_entry *n, **np;
627 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900628 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 write_lock_bh(&tbl->lock);
631 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
632 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800633 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900634 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 *np = n->next;
636 write_unlock_bh(&tbl->lock);
637 if (tbl->pdestructor)
638 tbl->pdestructor(n);
639 if (n->dev)
640 dev_put(n->dev);
641 kfree(n);
642 return 0;
643 }
644 }
645 write_unlock_bh(&tbl->lock);
646 return -ENOENT;
647}
648
649static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
650{
651 struct pneigh_entry *n, **np;
652 u32 h;
653
654 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
655 np = &tbl->phash_buckets[h];
656 while ((n = *np) != NULL) {
657 if (!dev || n->dev == dev) {
658 *np = n->next;
659 if (tbl->pdestructor)
660 tbl->pdestructor(n);
661 if (n->dev)
662 dev_put(n->dev);
663 kfree(n);
664 continue;
665 }
666 np = &n->next;
667 }
668 }
669 return -ENOENT;
670}
671
Denis V. Lunev06f05112008-01-24 00:30:58 -0800672static void neigh_parms_destroy(struct neigh_parms *parms);
673
674static inline void neigh_parms_put(struct neigh_parms *parms)
675{
676 if (atomic_dec_and_test(&parms->refcnt))
677 neigh_parms_destroy(parms);
678}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680/*
681 * neighbour must already be out of the table;
682 *
683 */
684void neigh_destroy(struct neighbour *neigh)
685{
David Millerda6a8fa2011-07-25 00:01:38 +0000686 struct net_device *dev = neigh->dev;
687
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
689
690 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000691 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 dump_stack();
693 return;
694 }
695
696 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000697 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700699 write_lock_bh(&neigh->lock);
700 __skb_queue_purge(&neigh->arp_queue);
701 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000702 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703
David S. Miller447f2192011-12-19 15:04:41 -0500704 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200705 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500706
David Millerda6a8fa2011-07-25 00:01:38 +0000707 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 neigh_parms_put(neigh->parms);
709
Joe Perchesd5d427c2013-04-15 15:17:19 +0000710 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000713 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900715EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717/* Neighbour state is suspicious;
718 disable fast path.
719
720 Called with write_locked neigh.
721 */
722static void neigh_suspect(struct neighbour *neigh)
723{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000724 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727}
728
729/* Neighbour state is OK;
730 enable fast path.
731
732 Called with write_locked neigh.
733 */
734static void neigh_connect(struct neighbour *neigh)
735{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000736 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737
738 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739}
740
Eric Dumazete4c4e442009-07-30 03:15:07 +0000741static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000743 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700744 struct neighbour *n;
745 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000746 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000747 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
749 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
750
Eric Dumazete4c4e442009-07-30 03:15:07 +0000751 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000752 nht = rcu_dereference_protected(tbl->nht,
753 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 /*
756 * periodically recompute ReachableTime from random function
757 */
758
Eric Dumazete4c4e442009-07-30 03:15:07 +0000759 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000761 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100762 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100764 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 }
766
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800767 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
768 goto out;
769
David S. Millercd089332011-07-11 01:28:12 -0700770 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000771 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Eric Dumazet767e97e2010-10-06 17:49:21 -0700773 while ((n = rcu_dereference_protected(*np,
774 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776
Eric Dumazete4c4e442009-07-30 03:15:07 +0000777 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778
Eric Dumazete4c4e442009-07-30 03:15:07 +0000779 state = n->nud_state;
780 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
781 write_unlock(&n->lock);
782 goto next_elt;
783 }
784
785 if (time_before(n->used, n->confirmed))
786 n->used = n->confirmed;
787
788 if (atomic_read(&n->refcnt) == 1 &&
789 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100790 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 *np = n->next;
792 n->dead = 1;
793 write_unlock(&n->lock);
794 neigh_cleanup_and_release(n);
795 continue;
796 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798
799next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000800 np = &n->next;
801 }
802 /*
803 * It's fine to release lock here, even if hash table
804 * grows while we are preempted.
805 */
806 write_unlock_bh(&tbl->lock);
807 cond_resched();
808 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500809 nht = rcu_dereference_protected(tbl->nht,
810 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000812out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100813 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
814 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
815 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 */
viresh kumarf6180022014-01-22 12:23:33 +0530817 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100818 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000819 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820}
821
822static __inline__ int neigh_max_probes(struct neighbour *n)
823{
824 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900825 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
826 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
827 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
Timo Teras5ef12d92009-06-11 04:16:28 -0700830static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000831 __releases(neigh->lock)
832 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700833{
834 struct sk_buff *skb;
835
836 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000837 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700838 neigh->updated = jiffies;
839
840 /* It is very thin place. report_unreachable is very complicated
841 routine. Particularly, it can hit the same neighbour entry!
842
843 So that, we try to be accurate and avoid dead loop. --ANK
844 */
845 while (neigh->nud_state == NUD_FAILED &&
846 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
847 write_unlock(&neigh->lock);
848 neigh->ops->error_report(neigh, skb);
849 write_lock(&neigh->lock);
850 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700851 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000852 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700853}
854
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000855static void neigh_probe(struct neighbour *neigh)
856 __releases(neigh->lock)
857{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200858 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000859 /* keep skb alive even if arp_queue overflows */
860 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800861 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000862 write_unlock(&neigh->lock);
863 neigh->ops->solicit(neigh, skb);
864 atomic_inc(&neigh->probes);
865 kfree_skb(skb);
866}
867
Linus Torvalds1da177e2005-04-16 15:20:36 -0700868/* Called when a timer expires for a neighbour entry. */
869
870static void neigh_timer_handler(unsigned long arg)
871{
872 unsigned long now, next;
873 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000874 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875 int notify = 0;
876
877 write_lock(&neigh->lock);
878
879 state = neigh->nud_state;
880 now = jiffies;
881 next = now + HZ;
882
David S. Miller045f7b32011-11-01 17:45:55 -0400883 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900887 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000889 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 next = neigh->confirmed + neigh->parms->reachable_time;
891 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100892 neigh->used +
893 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000894 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800896 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100898 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000900 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800902 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700904 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 }
906 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900907 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100908 neigh->confirmed +
909 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000910 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800912 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700914 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 next = neigh->confirmed + neigh->parms->reachable_time;
916 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000917 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800919 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900921 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100922 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 }
924 } else {
925 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100926 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 }
928
929 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
930 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 neigh->nud_state = NUD_FAILED;
932 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700933 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800934 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
936
937 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 if (time_before(next, jiffies + HZ/2))
939 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000940 if (!mod_timer(&neigh->timer, next))
941 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 }
943 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000944 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800945 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800946out:
David S. Miller9ff56602008-02-17 18:39:54 -0800947 write_unlock(&neigh->lock);
948 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949
Thomas Grafd961db32007-08-08 23:12:56 -0700950 if (notify)
951 neigh_update_notify(neigh);
952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 neigh_release(neigh);
954}
955
956int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
957{
958 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000959 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960
961 write_lock_bh(&neigh->lock);
962
963 rc = 0;
964 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
965 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +0300966 if (neigh->dead)
967 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100970 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
971 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000972 unsigned long next, now = jiffies;
973
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100974 atomic_set(&neigh->probes,
975 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000977 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100978 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
979 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000980 neigh_add_timer(neigh, next);
981 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 } else {
983 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800984 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 write_unlock_bh(&neigh->lock);
986
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000987 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 return 1;
989 }
990 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000991 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800993 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100994 neigh_add_timer(neigh, jiffies +
995 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 }
997
998 if (neigh->nud_state == NUD_INCOMPLETE) {
999 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001000 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001001 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001003
David S. Millerf72051b2008-09-23 01:11:18 -07001004 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001005 if (!buff)
1006 break;
1007 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001009 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001011 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001013 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 }
1015 rc = 1;
1016 }
1017out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001018 if (immediate_probe)
1019 neigh_probe(neigh);
1020 else
1021 write_unlock(&neigh->lock);
1022 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001024
1025out_dead:
1026 if (neigh->nud_state & NUD_STALE)
1027 goto out_unlock_bh;
1028 write_unlock_bh(&neigh->lock);
1029 kfree_skb(skb);
1030 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001032EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033
David S. Millerf6b72b62011-07-14 07:53:20 -07001034static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
1036 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001037 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001038 = NULL;
1039
1040 if (neigh->dev->header_ops)
1041 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042
1043 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001044 hh = &neigh->hh;
1045 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001046 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001048 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 }
1050 }
1051}
1052
1053
1054
1055/* Generic update routine.
1056 -- lladdr is new lladdr or NULL, if it is not supplied.
1057 -- new is new state.
1058 -- flags
1059 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1060 if it is different.
1061 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001062 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001063 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1065
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001066 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 NTF_ROUTER flag.
1068 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1069 a router.
1070
1071 Caller MUST hold reference count on the entry.
1072 */
1073
1074int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1075 u32 flags)
1076{
1077 u8 old;
1078 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 struct net_device *dev;
1081 int update_isrouter = 0;
1082
1083 write_lock_bh(&neigh->lock);
1084
1085 dev = neigh->dev;
1086 old = neigh->nud_state;
1087 err = -EPERM;
1088
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001089 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 (old & (NUD_NOARP | NUD_PERMANENT)))
1091 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001092 if (neigh->dead)
1093 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
1095 if (!(new & NUD_VALID)) {
1096 neigh_del_timer(neigh);
1097 if (old & NUD_CONNECTED)
1098 neigh_suspect(neigh);
1099 neigh->nud_state = new;
1100 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001102 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1103 (new & NUD_FAILED)) {
1104 neigh_invalidate(neigh);
1105 notify = 1;
1106 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107 goto out;
1108 }
1109
1110 /* Compare new lladdr with cached one */
1111 if (!dev->addr_len) {
1112 /* First case: device needs no address. */
1113 lladdr = neigh->ha;
1114 } else if (lladdr) {
1115 /* The second case: if something is already cached
1116 and a new address is proposed:
1117 - compare new & old
1118 - if they are different, check override flag
1119 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001120 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 !memcmp(lladdr, neigh->ha, dev->addr_len))
1122 lladdr = neigh->ha;
1123 } else {
1124 /* No address is supplied; if we know something,
1125 use it, otherwise discard the request.
1126 */
1127 err = -EINVAL;
1128 if (!(old & NUD_VALID))
1129 goto out;
1130 lladdr = neigh->ha;
1131 }
1132
1133 if (new & NUD_CONNECTED)
1134 neigh->confirmed = jiffies;
1135 neigh->updated = jiffies;
1136
1137 /* If entry was valid and address is not changed,
1138 do not change entry state, if new one is STALE.
1139 */
1140 err = 0;
1141 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1142 if (old & NUD_VALID) {
1143 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1144 update_isrouter = 0;
1145 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1146 (old & NUD_CONNECTED)) {
1147 lladdr = neigh->ha;
1148 new = NUD_STALE;
1149 } else
1150 goto out;
1151 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001152 if (lladdr == neigh->ha && new == NUD_STALE &&
1153 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 new = old;
1155 }
1156 }
1157
1158 if (new != old) {
1159 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001160 if (new & NUD_PROBE)
1161 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001162 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001163 neigh_add_timer(neigh, (jiffies +
1164 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001165 neigh->parms->reachable_time :
1166 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001168 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 }
1170
1171 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001172 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001174 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 neigh_update_hhs(neigh);
1176 if (!(new & NUD_CONNECTED))
1177 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001178 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 }
1181 if (new == old)
1182 goto out;
1183 if (new & NUD_CONNECTED)
1184 neigh_connect(neigh);
1185 else
1186 neigh_suspect(neigh);
1187 if (!(old & NUD_VALID)) {
1188 struct sk_buff *skb;
1189
1190 /* Again: avoid dead loop if something went wrong */
1191
1192 while (neigh->nud_state & NUD_VALID &&
1193 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001194 struct dst_entry *dst = skb_dst(skb);
1195 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001197
1198 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001199
1200 /* Why not just use 'neigh' as-is? The problem is that
1201 * things such as shaper, eql, and sch_teql can end up
1202 * using alternative, different, neigh objects to output
1203 * the packet in the output path. So what we need to do
1204 * here is re-lookup the top-level neigh in the path so
1205 * we can reinject the packet there.
1206 */
1207 n2 = NULL;
1208 if (dst) {
1209 n2 = dst_neigh_lookup_skb(dst, skb);
1210 if (n2)
1211 n1 = n2;
1212 }
David S. Miller8f40b162011-07-17 13:34:11 -07001213 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001214 if (n2)
1215 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001216 rcu_read_unlock();
1217
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 write_lock_bh(&neigh->lock);
1219 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001220 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001221 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 }
1223out:
1224 if (update_isrouter) {
1225 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1226 (neigh->flags | NTF_ROUTER) :
1227 (neigh->flags & ~NTF_ROUTER);
1228 }
1229 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001230
1231 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001232 neigh_update_notify(neigh);
1233
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 return err;
1235}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001236EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
Jiri Benc7e980562013-12-11 13:48:20 +01001238/* Update the neigh to listen temporarily for probe responses, even if it is
1239 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1240 */
1241void __neigh_set_probe_once(struct neighbour *neigh)
1242{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001243 if (neigh->dead)
1244 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001245 neigh->updated = jiffies;
1246 if (!(neigh->nud_state & NUD_FAILED))
1247 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001248 neigh->nud_state = NUD_INCOMPLETE;
1249 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001250 neigh_add_timer(neigh,
1251 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1252}
1253EXPORT_SYMBOL(__neigh_set_probe_once);
1254
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1256 u8 *lladdr, void *saddr,
1257 struct net_device *dev)
1258{
1259 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1260 lladdr || !dev->addr_len);
1261 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001262 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 NEIGH_UPDATE_F_OVERRIDE);
1264 return neigh;
1265}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001266EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001267
Eric Dumazet34d101d2010-10-11 09:16:57 -07001268/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001269static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001271 struct net_device *dev = n->dev;
1272 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001273 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001274
1275 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001276
David S. Millerf6b72b62011-07-14 07:53:20 -07001277 /* Only one thread can come in here and initialize the
1278 * hh_cache entry.
1279 */
David S. Millerb23b5452011-07-16 17:45:02 -07001280 if (!hh->hh_len)
1281 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001282
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001283 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284}
1285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286/* Slow and careful. */
1287
David S. Miller8f40b162011-07-17 13:34:11 -07001288int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 int rc = 0;
1291
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 if (!neigh_event_send(neigh, skb)) {
1293 int err;
1294 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001295 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001296
David S. Millerf6b72b62011-07-14 07:53:20 -07001297 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001298 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001299
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001300 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001301 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001302 seq = read_seqbegin(&neigh->ha_lock);
1303 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1304 neigh->ha, NULL, skb->len);
1305 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001306
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001308 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 else
1310 goto out_kfree_skb;
1311 }
1312out:
1313 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314out_kfree_skb:
1315 rc = -EINVAL;
1316 kfree_skb(skb);
1317 goto out;
1318}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001319EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
1321/* As fast as possible without hh cache */
1322
David S. Miller8f40b162011-07-17 13:34:11 -07001323int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001326 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001327 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001329 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001330 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001331 seq = read_seqbegin(&neigh->ha_lock);
1332 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1333 neigh->ha, NULL, skb->len);
1334 } while (read_seqretry(&neigh->ha_lock, seq));
1335
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001337 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 else {
1339 err = -EINVAL;
1340 kfree_skb(skb);
1341 }
1342 return err;
1343}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001344EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345
David S. Miller8f40b162011-07-17 13:34:11 -07001346int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1347{
1348 return dev_queue_xmit(skb);
1349}
1350EXPORT_SYMBOL(neigh_direct_output);
1351
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352static void neigh_proxy_process(unsigned long arg)
1353{
1354 struct neigh_table *tbl = (struct neigh_table *)arg;
1355 long sched_next = 0;
1356 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001357 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358
1359 spin_lock(&tbl->proxy_queue.lock);
1360
David S. Millerf72051b2008-09-23 01:11:18 -07001361 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1362 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001365 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001366
David S. Millerf72051b2008-09-23 01:11:18 -07001367 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001368 if (tbl->proxy_redo && netif_running(dev)) {
1369 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001370 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001371 rcu_read_unlock();
1372 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001373 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001374 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375
1376 dev_put(dev);
1377 } else if (!sched_next || tdif < sched_next)
1378 sched_next = tdif;
1379 }
1380 del_timer(&tbl->proxy_timer);
1381 if (sched_next)
1382 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1383 spin_unlock(&tbl->proxy_queue.lock);
1384}
1385
1386void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1387 struct sk_buff *skb)
1388{
1389 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001390
1391 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001392 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001394 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395 kfree_skb(skb);
1396 return;
1397 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001398
1399 NEIGH_CB(skb)->sched_next = sched_next;
1400 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 spin_lock(&tbl->proxy_queue.lock);
1403 if (del_timer(&tbl->proxy_timer)) {
1404 if (time_before(tbl->proxy_timer.expires, sched_next))
1405 sched_next = tbl->proxy_timer.expires;
1406 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001407 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 dev_hold(skb->dev);
1409 __skb_queue_tail(&tbl->proxy_queue, skb);
1410 mod_timer(&tbl->proxy_timer, sched_next);
1411 spin_unlock(&tbl->proxy_queue.lock);
1412}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001413EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001415static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001416 struct net *net, int ifindex)
1417{
1418 struct neigh_parms *p;
1419
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001420 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001421 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001422 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001423 return p;
1424 }
1425
1426 return NULL;
1427}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1430 struct neigh_table *tbl)
1431{
Gao fengcf89d6b2013-06-20 10:01:32 +08001432 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001433 struct net *net = dev_net(dev);
1434 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Gao fengcf89d6b2013-06-20 10:01:32 +08001436 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 p->tbl = tbl;
1439 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001441 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001442 dev_hold(dev);
1443 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001444 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001446
1447 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001448 dev_put(dev);
1449 kfree(p);
1450 return NULL;
1451 }
1452
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001454 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001456
1457 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458 }
1459 return p;
1460}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001461EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462
1463static void neigh_rcu_free_parms(struct rcu_head *head)
1464{
1465 struct neigh_parms *parms =
1466 container_of(head, struct neigh_parms, rcu_head);
1467
1468 neigh_parms_put(parms);
1469}
1470
1471void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1472{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001473 if (!parms || parms == &tbl->parms)
1474 return;
1475 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001476 list_del(&parms->list);
1477 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001479 if (parms->dev)
1480 dev_put(parms->dev);
1481 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001483EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
Denis V. Lunev06f05112008-01-24 00:30:58 -08001485static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
1487 kfree(parms);
1488}
1489
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001490static struct lock_class_key neigh_table_proxy_queue_class;
1491
WANG Congd7480fd2014-11-10 15:59:36 -08001492static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1493
1494void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495{
1496 unsigned long now = jiffies;
1497 unsigned long phsize;
1498
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001499 INIT_LIST_HEAD(&tbl->parms_list);
1500 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001501 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001504 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 tbl->stats = alloc_percpu(struct neigh_statistics);
1507 if (!tbl->stats)
1508 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001509
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001511 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1512 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514#endif
1515
David S. Millercd089332011-07-11 01:28:12 -07001516 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
1518 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001519 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001521 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 panic("cannot allocate neighbour cache hashes");
1523
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001524 if (!tbl->entry_size)
1525 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1526 tbl->key_len, NEIGH_PRIV_ALIGN);
1527 else
1528 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1529
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001531 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301532 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1533 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001534 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001535 skb_queue_head_init_class(&tbl->proxy_queue,
1536 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 tbl->last_flush = now;
1539 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001540
WANG Congd7480fd2014-11-10 15:59:36 -08001541 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001543EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544
WANG Congd7480fd2014-11-10 15:59:36 -08001545int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546{
WANG Congd7480fd2014-11-10 15:59:36 -08001547 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001549 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 del_timer_sync(&tbl->proxy_timer);
1551 pneigh_queue_purge(&tbl->proxy_queue);
1552 neigh_ifdown(tbl, NULL);
1553 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001554 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001556 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1557 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001558 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
1560 kfree(tbl->phash_buckets);
1561 tbl->phash_buckets = NULL;
1562
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001563 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1564
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001565 free_percpu(tbl->stats);
1566 tbl->stats = NULL;
1567
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 return 0;
1569}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001570EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571
WANG Congd7480fd2014-11-10 15:59:36 -08001572static struct neigh_table *neigh_find_table(int family)
1573{
1574 struct neigh_table *tbl = NULL;
1575
1576 switch (family) {
1577 case AF_INET:
1578 tbl = neigh_tables[NEIGH_ARP_TABLE];
1579 break;
1580 case AF_INET6:
1581 tbl = neigh_tables[NEIGH_ND_TABLE];
1582 break;
1583 case AF_DECnet:
1584 tbl = neigh_tables[NEIGH_DN_TABLE];
1585 break;
1586 }
1587
1588 return tbl;
1589}
1590
Thomas Graf661d2962013-03-21 07:45:29 +00001591static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001593 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001594 struct ndmsg *ndm;
1595 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001597 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001599 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Eric Dumazet110b2492010-10-04 04:27:36 +00001601 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001602 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 goto out;
1604
Thomas Grafa14a49d2006-08-07 17:53:08 -07001605 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1606 if (dst_attr == NULL)
1607 goto out;
1608
1609 ndm = nlmsg_data(nlh);
1610 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001611 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001612 if (dev == NULL) {
1613 err = -ENODEV;
1614 goto out;
1615 }
1616 }
1617
WANG Congd7480fd2014-11-10 15:59:36 -08001618 tbl = neigh_find_table(ndm->ndm_family);
1619 if (tbl == NULL)
1620 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621
WANG Congd7480fd2014-11-10 15:59:36 -08001622 if (nla_len(dst_attr) < tbl->key_len)
1623 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
WANG Congd7480fd2014-11-10 15:59:36 -08001625 if (ndm->ndm_flags & NTF_PROXY) {
1626 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001627 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 }
WANG Congd7480fd2014-11-10 15:59:36 -08001629
1630 if (dev == NULL)
1631 goto out;
1632
1633 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1634 if (neigh == NULL) {
1635 err = -ENOENT;
1636 goto out;
1637 }
1638
1639 err = neigh_update(neigh, NULL, NUD_FAILED,
1640 NEIGH_UPDATE_F_OVERRIDE |
1641 NEIGH_UPDATE_F_ADMIN);
1642 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001643
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644out:
1645 return err;
1646}
1647
Thomas Graf661d2962013-03-21 07:45:29 +00001648static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
WANG Congd7480fd2014-11-10 15:59:36 -08001650 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001651 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001652 struct ndmsg *ndm;
1653 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654 struct neigh_table *tbl;
1655 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001656 struct neighbour *neigh;
1657 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001658 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659
Eric Dumazet110b2492010-10-04 04:27:36 +00001660 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001661 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1662 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001663 goto out;
1664
Thomas Graf5208deb2006-08-07 17:55:40 -07001665 err = -EINVAL;
1666 if (tb[NDA_DST] == NULL)
1667 goto out;
1668
1669 ndm = nlmsg_data(nlh);
1670 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001671 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001672 if (dev == NULL) {
1673 err = -ENODEV;
1674 goto out;
1675 }
1676
1677 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001678 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001679 }
1680
WANG Congd7480fd2014-11-10 15:59:36 -08001681 tbl = neigh_find_table(ndm->ndm_family);
1682 if (tbl == NULL)
1683 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684
WANG Congd7480fd2014-11-10 15:59:36 -08001685 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1686 goto out;
1687 dst = nla_data(tb[NDA_DST]);
1688 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
WANG Congd7480fd2014-11-10 15:59:36 -08001690 if (ndm->ndm_flags & NTF_PROXY) {
1691 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692
WANG Congd7480fd2014-11-10 15:59:36 -08001693 err = -ENOBUFS;
1694 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1695 if (pn) {
1696 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001697 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001698 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001699 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 }
1701
WANG Congd7480fd2014-11-10 15:59:36 -08001702 if (dev == NULL)
1703 goto out;
1704
1705 neigh = neigh_lookup(tbl, dst, dev);
1706 if (neigh == NULL) {
1707 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1708 err = -ENOENT;
1709 goto out;
1710 }
1711
1712 neigh = __neigh_lookup_errno(tbl, dst, dev);
1713 if (IS_ERR(neigh)) {
1714 err = PTR_ERR(neigh);
1715 goto out;
1716 }
1717 } else {
1718 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1719 err = -EEXIST;
1720 neigh_release(neigh);
1721 goto out;
1722 }
1723
1724 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1725 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1726 }
1727
1728 if (ndm->ndm_flags & NTF_USE) {
1729 neigh_event_send(neigh, NULL);
1730 err = 0;
1731 } else
1732 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1733 neigh_release(neigh);
1734
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735out:
1736 return err;
1737}
1738
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001739static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1740{
Thomas Grafca860fb2006-08-07 18:00:18 -07001741 struct nlattr *nest;
1742
1743 nest = nla_nest_start(skb, NDTA_PARMS);
1744 if (nest == NULL)
1745 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001746
David S. Miller9a6308d2012-04-01 20:06:28 -04001747 if ((parms->dev &&
1748 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1749 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001750 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1751 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001752 /* approximative value for deprecated QUEUE_LEN (in packets) */
1753 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001754 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1755 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1756 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1757 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1758 NEIGH_VAR(parms, UCAST_PROBES)) ||
1759 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1760 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001761 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1762 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001763 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1764 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001765 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001766 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001767 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001768 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001769 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001770 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001771 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001772 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001773 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001774 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001775 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001776 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001777 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001778 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001779 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001780 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001781
Thomas Grafca860fb2006-08-07 18:00:18 -07001782nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001783 nla_nest_cancel(skb, nest);
1784 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001785}
1786
Thomas Grafca860fb2006-08-07 18:00:18 -07001787static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1788 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001789{
1790 struct nlmsghdr *nlh;
1791 struct ndtmsg *ndtmsg;
1792
Thomas Grafca860fb2006-08-07 18:00:18 -07001793 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1794 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001795 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001796
Thomas Grafca860fb2006-08-07 18:00:18 -07001797 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001798
1799 read_lock_bh(&tbl->lock);
1800 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001801 ndtmsg->ndtm_pad1 = 0;
1802 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001803
David S. Miller9a6308d2012-04-01 20:06:28 -04001804 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001805 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001806 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1807 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1808 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1809 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001810 {
1811 unsigned long now = jiffies;
1812 unsigned int flush_delta = now - tbl->last_flush;
1813 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001814 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001815 struct ndt_config ndc = {
1816 .ndtc_key_len = tbl->key_len,
1817 .ndtc_entry_size = tbl->entry_size,
1818 .ndtc_entries = atomic_read(&tbl->entries),
1819 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1820 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001821 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1822 };
1823
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001824 rcu_read_lock_bh();
1825 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001826 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001827 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001828 rcu_read_unlock_bh();
1829
David S. Miller9a6308d2012-04-01 20:06:28 -04001830 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1831 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001832 }
1833
1834 {
1835 int cpu;
1836 struct ndt_stats ndst;
1837
1838 memset(&ndst, 0, sizeof(ndst));
1839
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001840 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001841 struct neigh_statistics *st;
1842
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001843 st = per_cpu_ptr(tbl->stats, cpu);
1844 ndst.ndts_allocs += st->allocs;
1845 ndst.ndts_destroys += st->destroys;
1846 ndst.ndts_hash_grows += st->hash_grows;
1847 ndst.ndts_res_failed += st->res_failed;
1848 ndst.ndts_lookups += st->lookups;
1849 ndst.ndts_hits += st->hits;
1850 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1851 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1852 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1853 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001854 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855 }
1856
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001857 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1858 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001859 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001860 }
1861
1862 BUG_ON(tbl->parms.dev);
1863 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001864 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001865
1866 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001867 nlmsg_end(skb, nlh);
1868 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001869
Thomas Grafca860fb2006-08-07 18:00:18 -07001870nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001871 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001872 nlmsg_cancel(skb, nlh);
1873 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001874}
1875
Thomas Grafca860fb2006-08-07 18:00:18 -07001876static int neightbl_fill_param_info(struct sk_buff *skb,
1877 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001879 u32 pid, u32 seq, int type,
1880 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881{
1882 struct ndtmsg *ndtmsg;
1883 struct nlmsghdr *nlh;
1884
Thomas Grafca860fb2006-08-07 18:00:18 -07001885 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1886 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001887 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001888
Thomas Grafca860fb2006-08-07 18:00:18 -07001889 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001890
1891 read_lock_bh(&tbl->lock);
1892 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001893 ndtmsg->ndtm_pad1 = 0;
1894 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001895
Thomas Grafca860fb2006-08-07 18:00:18 -07001896 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1897 neightbl_fill_parms(skb, parms) < 0)
1898 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001899
1900 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001901 nlmsg_end(skb, nlh);
1902 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001903errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001904 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001905 nlmsg_cancel(skb, nlh);
1906 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001907}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001908
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001909static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001910 [NDTA_NAME] = { .type = NLA_STRING },
1911 [NDTA_THRESH1] = { .type = NLA_U32 },
1912 [NDTA_THRESH2] = { .type = NLA_U32 },
1913 [NDTA_THRESH3] = { .type = NLA_U32 },
1914 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1915 [NDTA_PARMS] = { .type = NLA_NESTED },
1916};
1917
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001918static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001919 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1920 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1921 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1922 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1923 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1924 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001925 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001926 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1927 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1928 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1929 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1930 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1931 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1932 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1933};
1934
Thomas Graf661d2962013-03-21 07:45:29 +00001935static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001936{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001937 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001938 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001939 struct ndtmsg *ndtmsg;
1940 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001941 bool found = false;
1942 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001943
Thomas Graf6b3f8672006-08-07 17:58:53 -07001944 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1945 nl_neightbl_policy);
1946 if (err < 0)
1947 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001948
Thomas Graf6b3f8672006-08-07 17:58:53 -07001949 if (tb[NDTA_NAME] == NULL) {
1950 err = -EINVAL;
1951 goto errout;
1952 }
1953
1954 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001955
1956 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1957 tbl = neigh_tables[tidx];
1958 if (!tbl)
1959 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001960 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1961 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08001962 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1963 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001964 break;
WANG Congd7480fd2014-11-10 15:59:36 -08001965 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001966 }
1967
WANG Congd7480fd2014-11-10 15:59:36 -08001968 if (!found)
1969 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001970
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001971 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001972 * We acquire tbl->lock to be nice to the periodic timers and
1973 * make sure they always see a consistent set of values.
1974 */
1975 write_lock_bh(&tbl->lock);
1976
Thomas Graf6b3f8672006-08-07 17:58:53 -07001977 if (tb[NDTA_PARMS]) {
1978 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001979 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001980 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001981
Thomas Graf6b3f8672006-08-07 17:58:53 -07001982 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1983 nl_ntbl_parm_policy);
1984 if (err < 0)
1985 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986
Thomas Graf6b3f8672006-08-07 17:58:53 -07001987 if (tbp[NDTPA_IFINDEX])
1988 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001989
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001990 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001991 if (p == NULL) {
1992 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001993 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001994 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001995
Thomas Graf6b3f8672006-08-07 17:58:53 -07001996 for (i = 1; i <= NDTPA_MAX; i++) {
1997 if (tbp[i] == NULL)
1998 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001999
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 switch (i) {
2001 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002002 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2003 nla_get_u32(tbp[i]) *
2004 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002005 break;
2006 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002007 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2008 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 break;
2010 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002011 NEIGH_VAR_SET(p, PROXY_QLEN,
2012 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 break;
2014 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002015 NEIGH_VAR_SET(p, APP_PROBES,
2016 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002017 break;
2018 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002019 NEIGH_VAR_SET(p, UCAST_PROBES,
2020 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002021 break;
2022 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002023 NEIGH_VAR_SET(p, MCAST_PROBES,
2024 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002026 case NDTPA_MCAST_REPROBES:
2027 NEIGH_VAR_SET(p, MCAST_REPROBES,
2028 nla_get_u32(tbp[i]));
2029 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002030 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002031 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2032 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002033 /* update reachable_time as well, otherwise, the change will
2034 * only be effective after the next time neigh_periodic_work
2035 * decides to recompute it (can be multiple minutes)
2036 */
2037 p->reachable_time =
2038 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002039 break;
2040 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002041 NEIGH_VAR_SET(p, GC_STALETIME,
2042 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 break;
2044 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002045 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2046 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002047 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002048 break;
2049 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002050 NEIGH_VAR_SET(p, RETRANS_TIME,
2051 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002052 break;
2053 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002054 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2055 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002056 break;
2057 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002058 NEIGH_VAR_SET(p, PROXY_DELAY,
2059 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002060 break;
2061 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002062 NEIGH_VAR_SET(p, LOCKTIME,
2063 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064 break;
2065 }
2066 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002067 }
2068
Gao fengdc25c672013-06-20 10:01:34 +08002069 err = -ENOENT;
2070 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2071 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2072 !net_eq(net, &init_net))
2073 goto errout_tbl_lock;
2074
Thomas Graf6b3f8672006-08-07 17:58:53 -07002075 if (tb[NDTA_THRESH1])
2076 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2077
2078 if (tb[NDTA_THRESH2])
2079 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2080
2081 if (tb[NDTA_THRESH3])
2082 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2083
2084 if (tb[NDTA_GC_INTERVAL])
2085 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2086
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002087 err = 0;
2088
Thomas Graf6b3f8672006-08-07 17:58:53 -07002089errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002090 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002091errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002092 return err;
2093}
2094
Thomas Grafc8822a42007-03-22 11:50:06 -07002095static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002096{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002097 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002098 int family, tidx, nidx = 0;
2099 int tbl_skip = cb->args[0];
2100 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002101 struct neigh_table *tbl;
2102
Thomas Grafca860fb2006-08-07 18:00:18 -07002103 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002104
WANG Congd7480fd2014-11-10 15:59:36 -08002105 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002106 struct neigh_parms *p;
2107
WANG Congd7480fd2014-11-10 15:59:36 -08002108 tbl = neigh_tables[tidx];
2109 if (!tbl)
2110 continue;
2111
Thomas Grafca860fb2006-08-07 18:00:18 -07002112 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002113 continue;
2114
Eric W. Biederman15e47302012-09-07 20:12:54 +00002115 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002116 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002117 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002118 break;
2119
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002120 nidx = 0;
2121 p = list_next_entry(&tbl->parms, list);
2122 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002123 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002124 continue;
2125
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002126 if (nidx < neigh_skip)
2127 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002128
Thomas Grafca860fb2006-08-07 18:00:18 -07002129 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002130 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002131 cb->nlh->nlmsg_seq,
2132 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002133 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002134 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002135 next:
2136 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002137 }
2138
Thomas Grafca860fb2006-08-07 18:00:18 -07002139 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002140 }
2141out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002142 cb->args[0] = tidx;
2143 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144
2145 return skb->len;
2146}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002147
Thomas Graf8b8aec52006-08-07 17:56:37 -07002148static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2149 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150{
2151 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002153 struct nlmsghdr *nlh;
2154 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002155
Thomas Graf8b8aec52006-08-07 17:56:37 -07002156 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2157 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002158 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002159
2160 ndm = nlmsg_data(nlh);
2161 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002162 ndm->ndm_pad1 = 0;
2163 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002164 ndm->ndm_flags = neigh->flags;
2165 ndm->ndm_type = neigh->type;
2166 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167
David S. Miller9a6308d2012-04-01 20:06:28 -04002168 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2169 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002170
2171 read_lock_bh(&neigh->lock);
2172 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002173 if (neigh->nud_state & NUD_VALID) {
2174 char haddr[MAX_ADDR_LEN];
2175
2176 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2177 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2178 read_unlock_bh(&neigh->lock);
2179 goto nla_put_failure;
2180 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002181 }
2182
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002183 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2184 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2185 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002186 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2187 read_unlock_bh(&neigh->lock);
2188
David S. Miller9a6308d2012-04-01 20:06:28 -04002189 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2190 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2191 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002192
Johannes Berg053c0952015-01-16 22:09:00 +01002193 nlmsg_end(skb, nlh);
2194 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002195
2196nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002197 nlmsg_cancel(skb, nlh);
2198 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002199}
2200
Tony Zelenoff84920c12012-01-26 22:28:58 +00002201static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2202 u32 pid, u32 seq, int type, unsigned int flags,
2203 struct neigh_table *tbl)
2204{
2205 struct nlmsghdr *nlh;
2206 struct ndmsg *ndm;
2207
2208 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2209 if (nlh == NULL)
2210 return -EMSGSIZE;
2211
2212 ndm = nlmsg_data(nlh);
2213 ndm->ndm_family = tbl->family;
2214 ndm->ndm_pad1 = 0;
2215 ndm->ndm_pad2 = 0;
2216 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002217 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002218 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002219 ndm->ndm_state = NUD_NONE;
2220
David S. Miller9a6308d2012-04-01 20:06:28 -04002221 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2222 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002223
Johannes Berg053c0952015-01-16 22:09:00 +01002224 nlmsg_end(skb, nlh);
2225 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002226
2227nla_put_failure:
2228 nlmsg_cancel(skb, nlh);
2229 return -EMSGSIZE;
2230}
2231
Thomas Grafd961db32007-08-08 23:12:56 -07002232static void neigh_update_notify(struct neighbour *neigh)
2233{
2234 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2235 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2236}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237
David Ahern21fdd092015-09-29 09:32:03 -07002238static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2239{
2240 struct net_device *master;
2241
2242 if (!master_idx)
2243 return false;
2244
2245 master = netdev_master_upper_dev_get(dev);
2246 if (!master || master->ifindex != master_idx)
2247 return true;
2248
2249 return false;
2250}
2251
David Ahern16660f02015-10-03 11:43:46 -07002252static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2253{
2254 if (filter_idx && dev->ifindex != filter_idx)
2255 return true;
2256
2257 return false;
2258}
2259
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2261 struct netlink_callback *cb)
2262{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002263 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002264 const struct nlmsghdr *nlh = cb->nlh;
2265 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 struct neighbour *n;
2267 int rc, h, s_h = cb->args[1];
2268 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002269 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002270 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002271 unsigned int flags = NLM_F_MULTI;
2272 int err;
2273
2274 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL);
2275 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002276 if (tb[NDA_IFINDEX])
2277 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2278
David Ahern21fdd092015-09-29 09:32:03 -07002279 if (tb[NDA_MASTER])
2280 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2281
David Ahern16660f02015-10-03 11:43:46 -07002282 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002283 flags |= NLM_F_DUMP_FILTERED;
2284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002286 rcu_read_lock_bh();
2287 nht = rcu_dereference_bh(tbl->nht);
2288
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002289 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290 if (h > s_h)
2291 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002292 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2293 n != NULL;
2294 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002295 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2296 goto next;
2297 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2298 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002299 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002300 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002302 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002303 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304 rc = -1;
2305 goto out;
2306 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002307next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002308 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310 }
2311 rc = skb->len;
2312out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002313 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 cb->args[1] = h;
2315 cb->args[2] = idx;
2316 return rc;
2317}
2318
Tony Zelenoff84920c12012-01-26 22:28:58 +00002319static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2320 struct netlink_callback *cb)
2321{
2322 struct pneigh_entry *n;
2323 struct net *net = sock_net(skb->sk);
2324 int rc, h, s_h = cb->args[3];
2325 int idx, s_idx = idx = cb->args[4];
2326
2327 read_lock_bh(&tbl->lock);
2328
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002329 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002330 if (h > s_h)
2331 s_idx = 0;
2332 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002333 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002334 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002335 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002336 cb->nlh->nlmsg_seq,
2337 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002338 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002339 read_unlock_bh(&tbl->lock);
2340 rc = -1;
2341 goto out;
2342 }
2343 next:
2344 idx++;
2345 }
2346 }
2347
2348 read_unlock_bh(&tbl->lock);
2349 rc = skb->len;
2350out:
2351 cb->args[3] = h;
2352 cb->args[4] = idx;
2353 return rc;
2354
2355}
2356
Thomas Grafc8822a42007-03-22 11:50:06 -07002357static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358{
2359 struct neigh_table *tbl;
2360 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002361 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002362 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363
Thomas Graf8b8aec52006-08-07 17:56:37 -07002364 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002365
2366 /* check for full ndmsg structure presence, family member is
2367 * the same for both structures
2368 */
2369 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2370 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2371 proxy = 1;
2372
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373 s_t = cb->args[0];
2374
WANG Congd7480fd2014-11-10 15:59:36 -08002375 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2376 tbl = neigh_tables[t];
2377
2378 if (!tbl)
2379 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 if (t < s_t || (family && tbl->family != family))
2381 continue;
2382 if (t > s_t)
2383 memset(&cb->args[1], 0, sizeof(cb->args) -
2384 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002385 if (proxy)
2386 err = pneigh_dump_table(tbl, skb, cb);
2387 else
2388 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002389 if (err < 0)
2390 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002391 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392
2393 cb->args[0] = t;
2394 return skb->len;
2395}
2396
2397void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2398{
2399 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002400 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002402 rcu_read_lock_bh();
2403 nht = rcu_dereference_bh(tbl->nht);
2404
Eric Dumazet767e97e2010-10-06 17:49:21 -07002405 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002406 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 struct neighbour *n;
2408
Eric Dumazet767e97e2010-10-06 17:49:21 -07002409 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2410 n != NULL;
2411 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412 cb(n, cookie);
2413 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002414 read_unlock(&tbl->lock);
2415 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416}
2417EXPORT_SYMBOL(neigh_for_each);
2418
2419/* The tbl->lock must be held as a writer and BH disabled. */
2420void __neigh_for_each_release(struct neigh_table *tbl,
2421 int (*cb)(struct neighbour *))
2422{
2423 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002424 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002426 nht = rcu_dereference_protected(tbl->nht,
2427 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002428 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002429 struct neighbour *n;
2430 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002432 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002433 while ((n = rcu_dereference_protected(*np,
2434 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 int release;
2436
2437 write_lock(&n->lock);
2438 release = cb(n);
2439 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002440 rcu_assign_pointer(*np,
2441 rcu_dereference_protected(n->next,
2442 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 n->dead = 1;
2444 } else
2445 np = &n->next;
2446 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002447 if (release)
2448 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002449 }
2450 }
2451}
2452EXPORT_SYMBOL(__neigh_for_each_release);
2453
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002454int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002455 const void *addr, struct sk_buff *skb)
2456{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002457 int err = -EAFNOSUPPORT;
2458 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002459 struct neigh_table *tbl;
2460 struct neighbour *neigh;
2461
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002462 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002463 if (!tbl)
2464 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002465 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002466 neigh = __neigh_lookup_noref(tbl, addr, dev);
2467 if (!neigh)
2468 neigh = __neigh_create(tbl, addr, dev, false);
2469 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002470 if (IS_ERR(neigh)) {
2471 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002472 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002473 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002474 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002475 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002476 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002477 else if (index == NEIGH_LINK_TABLE) {
2478 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2479 addr, NULL, skb->len);
2480 if (err < 0)
2481 goto out_kfree_skb;
2482 err = dev_queue_xmit(skb);
2483 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002484out:
2485 return err;
2486out_kfree_skb:
2487 kfree_skb(skb);
2488 goto out;
2489}
2490EXPORT_SYMBOL(neigh_xmit);
2491
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492#ifdef CONFIG_PROC_FS
2493
2494static struct neighbour *neigh_get_first(struct seq_file *seq)
2495{
2496 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002497 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002498 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 struct neighbour *n = NULL;
2500 int bucket = state->bucket;
2501
2502 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002503 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002504 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505
2506 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002507 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002508 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 if (state->neigh_sub_iter) {
2510 loff_t fakep = 0;
2511 void *v;
2512
2513 v = state->neigh_sub_iter(state, n, &fakep);
2514 if (!v)
2515 goto next;
2516 }
2517 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2518 break;
2519 if (n->nud_state & ~NUD_NOARP)
2520 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002521next:
2522 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002523 }
2524
2525 if (n)
2526 break;
2527 }
2528 state->bucket = bucket;
2529
2530 return n;
2531}
2532
2533static struct neighbour *neigh_get_next(struct seq_file *seq,
2534 struct neighbour *n,
2535 loff_t *pos)
2536{
2537 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002538 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002539 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540
2541 if (state->neigh_sub_iter) {
2542 void *v = state->neigh_sub_iter(state, n, pos);
2543 if (v)
2544 return n;
2545 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002546 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 while (1) {
2549 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002550 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002551 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002552 if (state->neigh_sub_iter) {
2553 void *v = state->neigh_sub_iter(state, n, pos);
2554 if (v)
2555 return n;
2556 goto next;
2557 }
2558 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2559 break;
2560
2561 if (n->nud_state & ~NUD_NOARP)
2562 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002563next:
2564 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 }
2566
2567 if (n)
2568 break;
2569
David S. Millercd089332011-07-11 01:28:12 -07002570 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 break;
2572
Eric Dumazet767e97e2010-10-06 17:49:21 -07002573 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 }
2575
2576 if (n && pos)
2577 --(*pos);
2578 return n;
2579}
2580
2581static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2582{
2583 struct neighbour *n = neigh_get_first(seq);
2584
2585 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002586 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 while (*pos) {
2588 n = neigh_get_next(seq, n, pos);
2589 if (!n)
2590 break;
2591 }
2592 }
2593 return *pos ? NULL : n;
2594}
2595
2596static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2597{
2598 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002599 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 struct neigh_table *tbl = state->tbl;
2601 struct pneigh_entry *pn = NULL;
2602 int bucket = state->bucket;
2603
2604 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2605 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2606 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002607 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002608 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 if (pn)
2610 break;
2611 }
2612 state->bucket = bucket;
2613
2614 return pn;
2615}
2616
2617static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2618 struct pneigh_entry *pn,
2619 loff_t *pos)
2620{
2621 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002622 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 struct neigh_table *tbl = state->tbl;
2624
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002625 do {
2626 pn = pn->next;
2627 } while (pn && !net_eq(pneigh_net(pn), net));
2628
Linus Torvalds1da177e2005-04-16 15:20:36 -07002629 while (!pn) {
2630 if (++state->bucket > PNEIGH_HASHMASK)
2631 break;
2632 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002633 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002634 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 if (pn)
2636 break;
2637 }
2638
2639 if (pn && pos)
2640 --(*pos);
2641
2642 return pn;
2643}
2644
2645static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2646{
2647 struct pneigh_entry *pn = pneigh_get_first(seq);
2648
2649 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002650 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 while (*pos) {
2652 pn = pneigh_get_next(seq, pn, pos);
2653 if (!pn)
2654 break;
2655 }
2656 }
2657 return *pos ? NULL : pn;
2658}
2659
2660static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2661{
2662 struct neigh_seq_state *state = seq->private;
2663 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002664 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665
Chris Larson745e2032008-08-03 01:10:55 -07002666 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002668 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
2670 return rc;
2671}
2672
2673void *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 +00002674 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675{
2676 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677
2678 state->tbl = tbl;
2679 state->bucket = 0;
2680 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2681
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002682 rcu_read_lock_bh();
2683 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002684
Chris Larson745e2032008-08-03 01:10:55 -07002685 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687EXPORT_SYMBOL(neigh_seq_start);
2688
2689void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2690{
2691 struct neigh_seq_state *state;
2692 void *rc;
2693
2694 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002695 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 goto out;
2697 }
2698
2699 state = seq->private;
2700 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2701 rc = neigh_get_next(seq, v, NULL);
2702 if (rc)
2703 goto out;
2704 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2705 rc = pneigh_get_first(seq);
2706 } else {
2707 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2708 rc = pneigh_get_next(seq, v, NULL);
2709 }
2710out:
2711 ++(*pos);
2712 return rc;
2713}
2714EXPORT_SYMBOL(neigh_seq_next);
2715
2716void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002717 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002719 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720}
2721EXPORT_SYMBOL(neigh_seq_stop);
2722
2723/* statistics via seq_file */
2724
2725static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2726{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002727 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 int cpu;
2729
2730 if (*pos == 0)
2731 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002732
Rusty Russell0f23174a2008-12-29 12:23:42 +00002733 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002734 if (!cpu_possible(cpu))
2735 continue;
2736 *pos = cpu+1;
2737 return per_cpu_ptr(tbl->stats, cpu);
2738 }
2739 return NULL;
2740}
2741
2742static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2743{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002744 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 int cpu;
2746
Rusty Russell0f23174a2008-12-29 12:23:42 +00002747 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 if (!cpu_possible(cpu))
2749 continue;
2750 *pos = cpu+1;
2751 return per_cpu_ptr(tbl->stats, cpu);
2752 }
2753 return NULL;
2754}
2755
2756static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2757{
2758
2759}
2760
2761static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2762{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002763 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 struct neigh_statistics *st = v;
2765
2766 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002767 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 table_fulls\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768 return 0;
2769 }
2770
2771 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002772 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002773 atomic_read(&tbl->entries),
2774
2775 st->allocs,
2776 st->destroys,
2777 st->hash_grows,
2778
2779 st->lookups,
2780 st->hits,
2781
2782 st->res_failed,
2783
2784 st->rcv_probes_mcast,
2785 st->rcv_probes_ucast,
2786
2787 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002788 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002789 st->unres_discards,
2790 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 );
2792
2793 return 0;
2794}
2795
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002796static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 .start = neigh_stat_seq_start,
2798 .next = neigh_stat_seq_next,
2799 .stop = neigh_stat_seq_stop,
2800 .show = neigh_stat_seq_show,
2801};
2802
2803static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2804{
2805 int ret = seq_open(file, &neigh_stat_seq_ops);
2806
2807 if (!ret) {
2808 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002809 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 }
2811 return ret;
2812};
2813
Arjan van de Ven9a321442007-02-12 00:55:35 -08002814static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 .owner = THIS_MODULE,
2816 .open = neigh_stat_seq_open,
2817 .read = seq_read,
2818 .llseek = seq_lseek,
2819 .release = seq_release,
2820};
2821
2822#endif /* CONFIG_PROC_FS */
2823
Thomas Graf339bf982006-11-10 14:10:15 -08002824static inline size_t neigh_nlmsg_size(void)
2825{
2826 return NLMSG_ALIGN(sizeof(struct ndmsg))
2827 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2828 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2829 + nla_total_size(sizeof(struct nda_cacheinfo))
2830 + nla_total_size(4); /* NDA_PROBES */
2831}
2832
Thomas Grafb8673312006-08-15 00:33:14 -07002833static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002834{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002835 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002836 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002837 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002838
Thomas Graf339bf982006-11-10 14:10:15 -08002839 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002840 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002841 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842
Thomas Grafb8673312006-08-15 00:33:14 -07002843 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002844 if (err < 0) {
2845 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2846 WARN_ON(err == -EMSGSIZE);
2847 kfree_skb(skb);
2848 goto errout;
2849 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002850 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2851 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002852errout:
2853 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002854 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002855}
2856
2857void neigh_app_ns(struct neighbour *n)
2858{
2859 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002861EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862
2863#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002864static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002865static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002866static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002867
Joe Perchesfe2c6332013-06-11 23:04:25 -07002868static int proc_unres_qlen(struct ctl_table *ctl, int write,
2869 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002870{
2871 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002872 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002873
Shan Weice46cc62012-12-04 18:49:15 +00002874 tmp.extra1 = &zero;
2875 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002876 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002877
2878 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2879 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2880
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002881 if (write && !ret)
2882 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2883 return ret;
2884}
2885
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002886static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2887 int family)
2888{
Jiri Pirkobba24892013-12-07 19:26:57 +01002889 switch (family) {
2890 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002891 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002892 case AF_INET6:
2893 return __in6_dev_nd_parms_get_rcu(dev);
2894 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002895 return NULL;
2896}
2897
2898static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2899 int index)
2900{
2901 struct net_device *dev;
2902 int family = neigh_parms_family(p);
2903
2904 rcu_read_lock();
2905 for_each_netdev_rcu(net, dev) {
2906 struct neigh_parms *dst_p =
2907 neigh_get_dev_parms_rcu(dev, family);
2908
2909 if (dst_p && !test_bit(index, dst_p->data_state))
2910 dst_p->data[index] = p->data[index];
2911 }
2912 rcu_read_unlock();
2913}
2914
2915static void neigh_proc_update(struct ctl_table *ctl, int write)
2916{
2917 struct net_device *dev = ctl->extra1;
2918 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002919 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002920 int index = (int *) ctl->data - p->data;
2921
2922 if (!write)
2923 return;
2924
2925 set_bit(index, p->data_state);
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002926 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002927 if (!dev) /* NULL dev means this is default value */
2928 neigh_copy_dflt_parms(net, p, index);
2929}
2930
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002931static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2932 void __user *buffer,
2933 size_t *lenp, loff_t *ppos)
2934{
2935 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002936 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002937
2938 tmp.extra1 = &zero;
2939 tmp.extra2 = &int_max;
2940
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002941 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2942 neigh_proc_update(ctl, write);
2943 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002944}
2945
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002946int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2947 void __user *buffer, size_t *lenp, loff_t *ppos)
2948{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002949 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2950
2951 neigh_proc_update(ctl, write);
2952 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002953}
2954EXPORT_SYMBOL(neigh_proc_dointvec);
2955
2956int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2957 void __user *buffer,
2958 size_t *lenp, loff_t *ppos)
2959{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002960 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2961
2962 neigh_proc_update(ctl, write);
2963 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002964}
2965EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2966
2967static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2968 void __user *buffer,
2969 size_t *lenp, loff_t *ppos)
2970{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002971 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2972
2973 neigh_proc_update(ctl, write);
2974 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002975}
2976
2977int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2978 void __user *buffer,
2979 size_t *lenp, loff_t *ppos)
2980{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002981 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2982
2983 neigh_proc_update(ctl, write);
2984 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002985}
2986EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2987
2988static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2989 void __user *buffer,
2990 size_t *lenp, loff_t *ppos)
2991{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002992 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2993
2994 neigh_proc_update(ctl, write);
2995 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002996}
2997
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002998static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
2999 void __user *buffer,
3000 size_t *lenp, loff_t *ppos)
3001{
3002 struct neigh_parms *p = ctl->extra2;
3003 int ret;
3004
3005 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3006 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3007 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3008 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3009 else
3010 ret = -1;
3011
3012 if (write && ret == 0) {
3013 /* update reachable_time as well, otherwise, the change will
3014 * only be effective after the next time neigh_periodic_work
3015 * decides to recompute it
3016 */
3017 p->reachable_time =
3018 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3019 }
3020 return ret;
3021}
3022
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003023#define NEIGH_PARMS_DATA_OFFSET(index) \
3024 (&((struct neigh_parms *) 0)->data[index])
3025
3026#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3027 [NEIGH_VAR_ ## attr] = { \
3028 .procname = name, \
3029 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3030 .maxlen = sizeof(int), \
3031 .mode = mval, \
3032 .proc_handler = proc, \
3033 }
3034
3035#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3036 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3037
3038#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003039 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003040
3041#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003042 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003043
3044#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003045 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003046
3047#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003048 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003049
3050#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003051 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003052
Linus Torvalds1da177e2005-04-16 15:20:36 -07003053static struct neigh_sysctl_table {
3054 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003055 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003056} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003058 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3059 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3060 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003061 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003062 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3063 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3064 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3065 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3066 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3067 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3068 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3069 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3070 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3071 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3072 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3073 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003074 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 .procname = "gc_interval",
3076 .maxlen = sizeof(int),
3077 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003078 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003080 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081 .procname = "gc_thresh1",
3082 .maxlen = sizeof(int),
3083 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003084 .extra1 = &zero,
3085 .extra2 = &int_max,
3086 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003087 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003088 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 .procname = "gc_thresh2",
3090 .maxlen = sizeof(int),
3091 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003092 .extra1 = &zero,
3093 .extra2 = &int_max,
3094 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003096 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003097 .procname = "gc_thresh3",
3098 .maxlen = sizeof(int),
3099 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003100 .extra1 = &zero,
3101 .extra2 = &int_max,
3102 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003104 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 },
3106};
3107
3108int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003109 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003111 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003112 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003113 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003114 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003115 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003116
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003117 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003119 goto err;
3120
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003121 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003122 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003123 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003124 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003125 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126
3127 if (dev) {
3128 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003129 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003130 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3131 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003133 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003134 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003135 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3136 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3137 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3138 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 }
3140
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003141 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003143 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003145 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003147 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003149 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003150 } else {
3151 /* Those handlers will update p->reachable_time after
3152 * base_reachable_time(_ms) is set to ensure the new timer starts being
3153 * applied after the next neighbour update instead of waiting for
3154 * neigh_periodic_work to update its value (can be multiple minutes)
3155 * So any handler that replaces them should do this as well
3156 */
3157 /* ReachableTime */
3158 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3159 neigh_proc_base_reachable_time;
3160 /* ReachableTime (in milliseconds) */
3161 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3162 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 }
3164
Eric W. Biederman464dc802012-11-16 03:02:59 +00003165 /* Don't export sysctls to unprivileged users */
3166 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3167 t->neigh_vars[0].procname = NULL;
3168
Jiri Pirko73af6142013-12-07 19:26:55 +01003169 switch (neigh_parms_family(p)) {
3170 case AF_INET:
3171 p_name = "ipv4";
3172 break;
3173 case AF_INET6:
3174 p_name = "ipv6";
3175 break;
3176 default:
3177 BUG();
3178 }
3179
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003180 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3181 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003182 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003183 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003184 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003185 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003186
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 p->sysctl_table = t;
3188 return 0;
3189
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003190free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003192err:
3193 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003195EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196
3197void neigh_sysctl_unregister(struct neigh_parms *p)
3198{
3199 if (p->sysctl_table) {
3200 struct neigh_sysctl_table *t = p->sysctl_table;
3201 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003202 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 kfree(t);
3204 }
3205}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003206EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207
3208#endif /* CONFIG_SYSCTL */
3209
Thomas Grafc8822a42007-03-22 11:50:06 -07003210static int __init neigh_init(void)
3211{
Greg Rosec7ac8672011-06-10 01:27:09 +00003212 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3213 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3214 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003215
Greg Rosec7ac8672011-06-10 01:27:09 +00003216 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3217 NULL);
3218 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003219
3220 return 0;
3221}
3222
3223subsys_initcall(neigh_init);
3224