blob: aa19d86937afabf5fb7dd29ce7c2379241281c06 [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
Kees Cooke99e88a2017-10-16 14:43:17 -070054static void neigh_timer_handler(struct timer_list *t);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -070055static void __neigh_notify(struct neighbour *n, int type, int flags,
56 u32 pid);
57static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +020058static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
59 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Amos Waterland45fc3b12005-09-24 16:53:16 -070061#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +020062static const struct seq_operations neigh_stat_seq_ops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070063#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65/*
66 Neighbour hash table buckets are protected with rwlock tbl->lock.
67
68 - All the scans/updates to hash buckets MUST be made under this lock.
69 - NOTHING clever should be made under this lock: no callbacks
70 to protocol backends, no attempts to send something to network.
71 It will result in deadlocks, if backend/driver wants to use neighbour
72 cache.
73 - If the entry requires some non-trivial actions, increase
74 its reference count and release table lock.
75
76 Neighbour entries are protected:
77 - with reference count.
78 - with rwlock neigh->lock
79
80 Reference count prevents destruction.
81
82 neigh->lock mainly serializes ll address data and its validity state.
83 However, the same lock is used to protect another entry fields:
84 - timer
85 - resolution queue
86
87 Again, nothing clever shall be made under neigh->lock,
88 the most complicated procedure, which we allow is dev->hard_header.
89 It is supposed, that dev->hard_header is simplistic and does
90 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 */
92
David S. Miller8f40b162011-07-17 13:34:11 -070093static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
95 kfree_skb(skb);
96 return -ENETDOWN;
97}
98
Thomas Graf4f494552007-08-08 23:12:36 -070099static void neigh_cleanup_and_release(struct neighbour *neigh)
100{
101 if (neigh->parms->neigh_cleanup)
102 neigh->parms->neigh_cleanup(neigh);
103
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700104 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100105 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Thomas Graf4f494552007-08-08 23:12:36 -0700106 neigh_release(neigh);
107}
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/*
110 * It is random distribution in the interval (1/2)*base...(3/2)*base.
111 * It corresponds to default IPv6 settings and is not overridable,
112 * because it is really reasonable choice.
113 */
114
115unsigned long neigh_rand_reach_time(unsigned long base)
116{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500117 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900119EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700122static bool neigh_del(struct neighbour *n, __u8 state, __u8 flags,
Sowmini Varadhan50710342017-06-02 09:01:49 -0700123 struct neighbour __rcu **np, struct neigh_table *tbl)
124{
125 bool retval = false;
126
127 write_lock(&n->lock);
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700128 if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state) &&
129 !(n->flags & flags)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700130 struct neighbour *neigh;
131
132 neigh = rcu_dereference_protected(n->next,
133 lockdep_is_held(&tbl->lock));
134 rcu_assign_pointer(*np, neigh);
135 n->dead = 1;
136 retval = true;
137 }
138 write_unlock(&n->lock);
139 if (retval)
140 neigh_cleanup_and_release(n);
141 return retval;
142}
143
144bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
145{
146 struct neigh_hash_table *nht;
147 void *pkey = ndel->primary_key;
148 u32 hash_val;
149 struct neighbour *n;
150 struct neighbour __rcu **np;
151
152 nht = rcu_dereference_protected(tbl->nht,
153 lockdep_is_held(&tbl->lock));
154 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
155 hash_val = hash_val >> (32 - nht->hash_shift);
156
157 np = &nht->hash_buckets[hash_val];
158 while ((n = rcu_dereference_protected(*np,
159 lockdep_is_held(&tbl->lock)))) {
160 if (n == ndel)
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700161 return neigh_del(n, 0, 0, np, tbl);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700162 np = &n->next;
163 }
164 return false;
165}
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167static int neigh_forced_gc(struct neigh_table *tbl)
168{
169 int shrunk = 0;
170 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000171 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
174
175 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000176 nht = rcu_dereference_protected(tbl->nht,
177 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700178 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700179 struct neighbour *n;
180 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000182 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700183 while ((n = rcu_dereference_protected(*np,
184 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 /* Neighbour record may be discarded if:
186 * - nobody refers to it.
187 * - it is not permanent
188 */
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700189 if (neigh_del(n, NUD_PERMANENT, NTF_EXT_LEARNED, np,
190 tbl)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700191 shrunk = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 continue;
193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 np = &n->next;
195 }
196 }
197
198 tbl->last_flush = jiffies;
199
200 write_unlock_bh(&tbl->lock);
201
202 return shrunk;
203}
204
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800205static void neigh_add_timer(struct neighbour *n, unsigned long when)
206{
207 neigh_hold(n);
208 if (unlikely(mod_timer(&n->timer, when))) {
209 printk("NEIGH: BUG, double timer add, state is %x\n",
210 n->nud_state);
211 dump_stack();
212 }
213}
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215static int neigh_del_timer(struct neighbour *n)
216{
217 if ((n->nud_state & NUD_IN_TIMER) &&
218 del_timer(&n->timer)) {
219 neigh_release(n);
220 return 1;
221 }
222 return 0;
223}
224
225static void pneigh_queue_purge(struct sk_buff_head *list)
226{
227 struct sk_buff *skb;
228
229 while ((skb = skb_dequeue(list)) != NULL) {
230 dev_put(skb->dev);
231 kfree_skb(skb);
232 }
233}
234
Herbert Xu49636bb2005-10-23 17:18:00 +1000235static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236{
237 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000238 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000240 nht = rcu_dereference_protected(tbl->nht,
241 lockdep_is_held(&tbl->lock));
242
David S. Millercd089332011-07-11 01:28:12 -0700243 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700244 struct neighbour *n;
245 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Eric Dumazet767e97e2010-10-06 17:49:21 -0700247 while ((n = rcu_dereference_protected(*np,
248 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 if (dev && n->dev != dev) {
250 np = &n->next;
251 continue;
252 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700253 rcu_assign_pointer(*np,
254 rcu_dereference_protected(n->next,
255 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256 write_lock(&n->lock);
257 neigh_del_timer(n);
258 n->dead = 1;
259
Reshetova, Elena9f237432017-06-30 13:07:55 +0300260 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 /* The most unpleasant situation.
262 We must destroy neighbour entry,
263 but someone still uses it.
264
265 The destroy will be delayed until
266 the last user releases us, but
267 we must kill timers etc. and move
268 it to safe state.
269 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700270 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000271 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 n->output = neigh_blackhole;
273 if (n->nud_state & NUD_VALID)
274 n->nud_state = NUD_NOARP;
275 else
276 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000277 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700280 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281 }
282 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000283}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284
Herbert Xu49636bb2005-10-23 17:18:00 +1000285void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
286{
287 write_lock_bh(&tbl->lock);
288 neigh_flush_dev(tbl, dev);
289 write_unlock_bh(&tbl->lock);
290}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900291EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000292
293int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
294{
295 write_lock_bh(&tbl->lock);
296 neigh_flush_dev(tbl, dev);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200297 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298
299 del_timer_sync(&tbl->proxy_timer);
300 pneigh_queue_purge(&tbl->proxy_queue);
301 return 0;
302}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900303EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
David Miller596b9b62011-07-25 00:01:25 +0000305static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306{
307 struct neighbour *n = NULL;
308 unsigned long now = jiffies;
309 int entries;
310
311 entries = atomic_inc_return(&tbl->entries) - 1;
312 if (entries >= tbl->gc_thresh3 ||
313 (entries >= tbl->gc_thresh2 &&
314 time_after(now, tbl->last_flush + 5 * HZ))) {
315 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700316 entries >= tbl->gc_thresh3) {
317 net_info_ratelimited("%s: neighbor table overflow!\n",
318 tbl->id);
319 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700321 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322 }
323
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000324 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 if (!n)
326 goto out_entries;
327
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700328 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000330 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 n->updated = n->used = now;
332 n->nud_state = NUD_NONE;
333 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700334 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 n->parms = neigh_parms_clone(&tbl->parms);
Kees Cooke99e88a2017-10-16 14:43:17 -0700336 timer_setup(&n->timer, neigh_timer_handler, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337
338 NEIGH_CACHE_STAT_INC(tbl, allocs);
339 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300340 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 n->dead = 1;
342out:
343 return n;
344
345out_entries:
346 atomic_dec(&tbl->entries);
347 goto out;
348}
349
David S. Miller2c2aba62011-12-28 15:06:58 -0500350static void neigh_get_hash_rnd(u32 *x)
351{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400352 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500353}
354
David S. Millercd089332011-07-11 01:28:12 -0700355static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356{
David S. Millercd089332011-07-11 01:28:12 -0700357 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000358 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000359 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500360 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000362 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
363 if (!ret)
364 return NULL;
365 if (size <= PAGE_SIZE)
366 buckets = kzalloc(size, GFP_ATOMIC);
367 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000368 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000369 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
370 get_order(size));
371 if (!buckets) {
372 kfree(ret);
373 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000375 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700376 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500377 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
378 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 return ret;
380}
381
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000382static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000384 struct neigh_hash_table *nht = container_of(head,
385 struct neigh_hash_table,
386 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700387 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000388 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
390 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000391 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000393 free_pages((unsigned long)buckets, get_order(size));
394 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395}
396
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000397static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700398 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000400 unsigned int i, hash;
401 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402
403 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
404
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000405 old_nht = rcu_dereference_protected(tbl->nht,
406 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700407 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 if (!new_nht)
409 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410
David S. Millercd089332011-07-11 01:28:12 -0700411 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 struct neighbour *n, *next;
413
Eric Dumazet767e97e2010-10-06 17:49:21 -0700414 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
415 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000416 n != NULL;
417 n = next) {
418 hash = tbl->hash(n->primary_key, n->dev,
419 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
David S. Millercd089332011-07-11 01:28:12 -0700421 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700422 next = rcu_dereference_protected(n->next,
423 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424
Eric Dumazet767e97e2010-10-06 17:49:21 -0700425 rcu_assign_pointer(n->next,
426 rcu_dereference_protected(
427 new_nht->hash_buckets[hash],
428 lockdep_is_held(&tbl->lock)));
429 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430 }
431 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000433 rcu_assign_pointer(tbl->nht, new_nht);
434 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
435 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436}
437
438struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
439 struct net_device *dev)
440{
441 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900442
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 NEIGH_CACHE_STAT_INC(tbl, lookups);
444
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000445 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600446 n = __neigh_lookup_noref(tbl, pkey, dev);
447 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300448 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600449 n = NULL;
450 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700452
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000453 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 return n;
455}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900456EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
Eric W. Biederman426b5302008-01-24 00:13:18 -0800458struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
459 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
461 struct neighbour *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300462 unsigned int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800463 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000464 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465
466 NEIGH_CACHE_STAT_INC(tbl, lookups);
467
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000468 rcu_read_lock_bh();
469 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700470 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700471
472 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
473 n != NULL;
474 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800475 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900476 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300477 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700478 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 NEIGH_CACHE_STAT_INC(tbl, hits);
480 break;
481 }
482 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700483
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000484 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 return n;
486}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900487EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
David S. Millera263b302012-07-02 02:02:15 -0700489struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
490 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491{
492 u32 hash_val;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300493 unsigned int key_len = tbl->key_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 int error;
David Miller596b9b62011-07-25 00:01:25 +0000495 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000496 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
498 if (!n) {
499 rc = ERR_PTR(-ENOBUFS);
500 goto out;
501 }
502
503 memcpy(n->primary_key, pkey, key_len);
504 n->dev = dev;
505 dev_hold(dev);
506
507 /* Protocol specific setup. */
508 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
509 rc = ERR_PTR(error);
510 goto out_neigh_release;
511 }
512
David Millerda6a8fa2011-07-25 00:01:38 +0000513 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200514 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000515 if (error < 0) {
516 rc = ERR_PTR(error);
517 goto out_neigh_release;
518 }
519 }
520
David S. Miller447f2192011-12-19 15:04:41 -0500521 /* Device specific setup. */
522 if (n->parms->neigh_setup &&
523 (error = n->parms->neigh_setup(n)) < 0) {
524 rc = ERR_PTR(error);
525 goto out_neigh_release;
526 }
527
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100528 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529
530 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000531 nht = rcu_dereference_protected(tbl->nht,
532 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533
David S. Millercd089332011-07-11 01:28:12 -0700534 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
535 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
Jim Westfall096b9852018-01-14 04:18:50 -0800537 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
539 if (n->parms->dead) {
540 rc = ERR_PTR(-EINVAL);
541 goto out_tbl_unlock;
542 }
543
Eric Dumazet767e97e2010-10-06 17:49:21 -0700544 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
545 lockdep_is_held(&tbl->lock));
546 n1 != NULL;
547 n1 = rcu_dereference_protected(n1->next,
548 lockdep_is_held(&tbl->lock))) {
Jim Westfall096b9852018-01-14 04:18:50 -0800549 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700550 if (want_ref)
551 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 rc = n1;
553 goto out_tbl_unlock;
554 }
555 }
556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700558 if (want_ref)
559 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700560 rcu_assign_pointer(n->next,
561 rcu_dereference_protected(nht->hash_buckets[hash_val],
562 lockdep_is_held(&tbl->lock)));
563 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000565 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 rc = n;
567out:
568 return rc;
569out_tbl_unlock:
570 write_unlock_bh(&tbl->lock);
571out_neigh_release:
572 neigh_release(n);
573 goto out;
574}
David S. Millera263b302012-07-02 02:02:15 -0700575EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300577static u32 pneigh_hash(const void *pkey, unsigned int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700578{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700579 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700580 hash_val ^= (hash_val >> 16);
581 hash_val ^= hash_val >> 8;
582 hash_val ^= hash_val >> 4;
583 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900584 return hash_val;
585}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700586
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900587static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
588 struct net *net,
589 const void *pkey,
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300590 unsigned int key_len,
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900591 struct net_device *dev)
592{
593 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700594 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900595 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700596 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900597 return n;
598 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700599 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900600 return NULL;
601}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700602
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900603struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
604 struct net *net, const void *pkey, struct net_device *dev)
605{
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300606 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900607 u32 hash_val = pneigh_hash(pkey, key_len);
608
609 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
610 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700611}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900612EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700613
Eric W. Biederman426b5302008-01-24 00:13:18 -0800614struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
615 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 struct net_device *dev, int creat)
617{
618 struct pneigh_entry *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300619 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900620 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900623 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
624 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900626
627 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 goto out;
629
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700630 ASSERT_RTNL();
631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
633 if (!n)
634 goto out;
635
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500636 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 memcpy(n->key, pkey, key_len);
638 n->dev = dev;
639 if (dev)
640 dev_hold(dev);
641
642 if (tbl->pconstructor && tbl->pconstructor(n)) {
643 if (dev)
644 dev_put(dev);
645 kfree(n);
646 n = NULL;
647 goto out;
648 }
649
650 write_lock_bh(&tbl->lock);
651 n->next = tbl->phash_buckets[hash_val];
652 tbl->phash_buckets[hash_val] = n;
653 write_unlock_bh(&tbl->lock);
654out:
655 return n;
656}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900657EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659
Eric W. Biederman426b5302008-01-24 00:13:18 -0800660int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700661 struct net_device *dev)
662{
663 struct pneigh_entry *n, **np;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300664 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900665 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666
667 write_lock_bh(&tbl->lock);
668 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
669 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800670 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900671 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 *np = n->next;
673 write_unlock_bh(&tbl->lock);
674 if (tbl->pdestructor)
675 tbl->pdestructor(n);
676 if (n->dev)
677 dev_put(n->dev);
678 kfree(n);
679 return 0;
680 }
681 }
682 write_unlock_bh(&tbl->lock);
683 return -ENOENT;
684}
685
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200686static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
687 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688{
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200689 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 u32 h;
691
692 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
693 np = &tbl->phash_buckets[h];
694 while ((n = *np) != NULL) {
695 if (!dev || n->dev == dev) {
696 *np = n->next;
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200697 n->next = freelist;
698 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 continue;
700 }
701 np = &n->next;
702 }
703 }
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200704 write_unlock_bh(&tbl->lock);
705 while ((n = freelist)) {
706 freelist = n->next;
707 n->next = NULL;
708 if (tbl->pdestructor)
709 tbl->pdestructor(n);
710 if (n->dev)
711 dev_put(n->dev);
712 kfree(n);
713 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 return -ENOENT;
715}
716
Denis V. Lunev06f05112008-01-24 00:30:58 -0800717static void neigh_parms_destroy(struct neigh_parms *parms);
718
719static inline void neigh_parms_put(struct neigh_parms *parms)
720{
Reshetova, Elena63439442017-06-30 13:07:56 +0300721 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800722 neigh_parms_destroy(parms);
723}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725/*
726 * neighbour must already be out of the table;
727 *
728 */
729void neigh_destroy(struct neighbour *neigh)
730{
David Millerda6a8fa2011-07-25 00:01:38 +0000731 struct net_device *dev = neigh->dev;
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
734
735 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000736 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 dump_stack();
738 return;
739 }
740
741 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000742 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700744 write_lock_bh(&neigh->lock);
745 __skb_queue_purge(&neigh->arp_queue);
746 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000747 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748
David S. Miller447f2192011-12-19 15:04:41 -0500749 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200750 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500751
David Millerda6a8fa2011-07-25 00:01:38 +0000752 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 neigh_parms_put(neigh->parms);
754
Joe Perchesd5d427c2013-04-15 15:17:19 +0000755 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
757 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000758 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900760EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762/* Neighbour state is suspicious;
763 disable fast path.
764
765 Called with write_locked neigh.
766 */
767static void neigh_suspect(struct neighbour *neigh)
768{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000769 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770
771 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772}
773
774/* Neighbour state is OK;
775 enable fast path.
776
777 Called with write_locked neigh.
778 */
779static void neigh_connect(struct neighbour *neigh)
780{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000781 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782
783 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784}
785
Eric Dumazete4c4e442009-07-30 03:15:07 +0000786static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000788 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700789 struct neighbour *n;
790 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000792 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793
794 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
795
Eric Dumazete4c4e442009-07-30 03:15:07 +0000796 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000797 nht = rcu_dereference_protected(tbl->nht,
798 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800 /*
801 * periodically recompute ReachableTime from random function
802 */
803
Eric Dumazete4c4e442009-07-30 03:15:07 +0000804 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000806 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100807 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100809 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 }
811
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800812 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
813 goto out;
814
David S. Millercd089332011-07-11 01:28:12 -0700815 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000816 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Eric Dumazet767e97e2010-10-06 17:49:21 -0700818 while ((n = rcu_dereference_protected(*np,
819 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000820 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Eric Dumazete4c4e442009-07-30 03:15:07 +0000822 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700823
Eric Dumazete4c4e442009-07-30 03:15:07 +0000824 state = n->nud_state;
Roopa Prabhu9ce33e42018-04-24 13:49:34 -0700825 if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
826 (n->flags & NTF_EXT_LEARNED)) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000827 write_unlock(&n->lock);
828 goto next_elt;
829 }
830
831 if (time_before(n->used, n->confirmed))
832 n->used = n->confirmed;
833
Reshetova, Elena9f237432017-06-30 13:07:55 +0300834 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000835 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100836 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000837 *np = n->next;
838 n->dead = 1;
839 write_unlock(&n->lock);
840 neigh_cleanup_and_release(n);
841 continue;
842 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844
845next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000846 np = &n->next;
847 }
848 /*
849 * It's fine to release lock here, even if hash table
850 * grows while we are preempted.
851 */
852 write_unlock_bh(&tbl->lock);
853 cond_resched();
854 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500855 nht = rcu_dereference_protected(tbl->nht,
856 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000858out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100859 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
860 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
861 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 */
viresh kumarf6180022014-01-22 12:23:33 +0530863 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100864 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000865 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866}
867
868static __inline__ int neigh_max_probes(struct neighbour *n)
869{
870 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900871 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
872 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
873 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
Timo Teras5ef12d92009-06-11 04:16:28 -0700876static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000877 __releases(neigh->lock)
878 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700879{
880 struct sk_buff *skb;
881
882 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000883 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700884 neigh->updated = jiffies;
885
886 /* It is very thin place. report_unreachable is very complicated
887 routine. Particularly, it can hit the same neighbour entry!
888
889 So that, we try to be accurate and avoid dead loop. --ANK
890 */
891 while (neigh->nud_state == NUD_FAILED &&
892 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
893 write_unlock(&neigh->lock);
894 neigh->ops->error_report(neigh, skb);
895 write_lock(&neigh->lock);
896 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700897 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000898 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700899}
900
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000901static void neigh_probe(struct neighbour *neigh)
902 __releases(neigh->lock)
903{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200904 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000905 /* keep skb alive even if arp_queue overflows */
906 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800907 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000908 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700909 if (neigh->ops->solicit)
910 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000911 atomic_inc(&neigh->probes);
912 kfree_skb(skb);
913}
914
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915/* Called when a timer expires for a neighbour entry. */
916
Kees Cooke99e88a2017-10-16 14:43:17 -0700917static void neigh_timer_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918{
919 unsigned long now, next;
Kees Cooke99e88a2017-10-16 14:43:17 -0700920 struct neighbour *neigh = from_timer(neigh, t, timer);
Eric Dumazet95c96172012-04-15 05:58:06 +0000921 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 int notify = 0;
923
924 write_lock(&neigh->lock);
925
926 state = neigh->nud_state;
927 now = jiffies;
928 next = now + HZ;
929
David S. Miller045f7b32011-11-01 17:45:55 -0400930 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932
933 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900934 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000936 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 next = neigh->confirmed + neigh->parms->reachable_time;
938 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100939 neigh->used +
940 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000941 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800943 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100945 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000947 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800949 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700951 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 }
953 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900954 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100955 neigh->confirmed +
956 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000957 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800959 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700961 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 next = neigh->confirmed + neigh->parms->reachable_time;
963 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000964 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800966 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900968 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100969 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 }
971 } else {
972 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100973 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 }
975
976 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
977 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 neigh->nud_state = NUD_FAILED;
979 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700980 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800981 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 }
983
984 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 if (time_before(next, jiffies + HZ/2))
986 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000987 if (!mod_timer(&neigh->timer, next))
988 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000991 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800992 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800993out:
David S. Miller9ff56602008-02-17 18:39:54 -0800994 write_unlock(&neigh->lock);
995 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
Thomas Grafd961db32007-08-08 23:12:56 -0700997 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700998 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -0700999
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 neigh_release(neigh);
1001}
1002
1003int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
1004{
1005 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001006 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
1008 write_lock_bh(&neigh->lock);
1009
1010 rc = 0;
1011 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1012 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001013 if (neigh->dead)
1014 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001017 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1018 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001019 unsigned long next, now = jiffies;
1020
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001021 atomic_set(&neigh->probes,
1022 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001024 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001025 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1026 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001027 neigh_add_timer(neigh, next);
1028 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 } else {
1030 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001031 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 write_unlock_bh(&neigh->lock);
1033
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001034 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return 1;
1036 }
1037 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001038 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001040 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001041 neigh_add_timer(neigh, jiffies +
1042 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 }
1044
1045 if (neigh->nud_state == NUD_INCOMPLETE) {
1046 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001047 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001048 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001050
David S. Millerf72051b2008-09-23 01:11:18 -07001051 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001052 if (!buff)
1053 break;
1054 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001056 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001058 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001060 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001061 }
1062 rc = 1;
1063 }
1064out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001065 if (immediate_probe)
1066 neigh_probe(neigh);
1067 else
1068 write_unlock(&neigh->lock);
1069 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001071
1072out_dead:
1073 if (neigh->nud_state & NUD_STALE)
1074 goto out_unlock_bh;
1075 write_unlock_bh(&neigh->lock);
1076 kfree_skb(skb);
1077 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001079EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080
David S. Millerf6b72b622011-07-14 07:53:20 -07001081static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082{
1083 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001084 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001085 = NULL;
1086
1087 if (neigh->dev->header_ops)
1088 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089
1090 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001091 hh = &neigh->hh;
1092 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001093 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001095 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096 }
1097 }
1098}
1099
1100
1101
1102/* Generic update routine.
1103 -- lladdr is new lladdr or NULL, if it is not supplied.
1104 -- new is new state.
1105 -- flags
1106 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1107 if it is different.
1108 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001109 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1112
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001113 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 NTF_ROUTER flag.
1115 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1116 a router.
1117
1118 Caller MUST hold reference count on the entry.
1119 */
1120
1121int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001122 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123{
1124 u8 old;
1125 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 struct net_device *dev;
1128 int update_isrouter = 0;
1129
1130 write_lock_bh(&neigh->lock);
1131
1132 dev = neigh->dev;
1133 old = neigh->nud_state;
1134 err = -EPERM;
1135
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001136 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 (old & (NUD_NOARP | NUD_PERMANENT)))
1138 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001139 if (neigh->dead)
1140 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001142 neigh_update_ext_learned(neigh, flags, &notify);
1143
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 if (!(new & NUD_VALID)) {
1145 neigh_del_timer(neigh);
1146 if (old & NUD_CONNECTED)
1147 neigh_suspect(neigh);
1148 neigh->nud_state = new;
1149 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150 notify = old & NUD_VALID;
Roopa Prabhu8e3262892018-06-25 20:32:53 -07001151 if (((old & (NUD_INCOMPLETE | NUD_PROBE)) ||
1152 (flags & NEIGH_UPDATE_F_ADMIN)) &&
Timo Teras5ef12d92009-06-11 04:16:28 -07001153 (new & NUD_FAILED)) {
1154 neigh_invalidate(neigh);
1155 notify = 1;
1156 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 goto out;
1158 }
1159
1160 /* Compare new lladdr with cached one */
1161 if (!dev->addr_len) {
1162 /* First case: device needs no address. */
1163 lladdr = neigh->ha;
1164 } else if (lladdr) {
1165 /* The second case: if something is already cached
1166 and a new address is proposed:
1167 - compare new & old
1168 - if they are different, check override flag
1169 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001170 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 !memcmp(lladdr, neigh->ha, dev->addr_len))
1172 lladdr = neigh->ha;
1173 } else {
1174 /* No address is supplied; if we know something,
1175 use it, otherwise discard the request.
1176 */
1177 err = -EINVAL;
1178 if (!(old & NUD_VALID))
1179 goto out;
1180 lladdr = neigh->ha;
1181 }
1182
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 /* If entry was valid and address is not changed,
1184 do not change entry state, if new one is STALE.
1185 */
1186 err = 0;
1187 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1188 if (old & NUD_VALID) {
1189 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1190 update_isrouter = 0;
1191 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1192 (old & NUD_CONNECTED)) {
1193 lladdr = neigh->ha;
1194 new = NUD_STALE;
1195 } else
1196 goto out;
1197 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001198 if (lladdr == neigh->ha && new == NUD_STALE &&
1199 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 new = old;
1201 }
1202 }
1203
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001204 /* Update timestamps only once we know we will make a change to the
1205 * neighbour entry. Otherwise we risk to move the locktime window with
1206 * noop updates and ignore relevant ARP updates.
1207 */
1208 if (new != old || lladdr != neigh->ha) {
1209 if (new & NUD_CONNECTED)
1210 neigh->confirmed = jiffies;
1211 neigh->updated = jiffies;
1212 }
1213
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 if (new != old) {
1215 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001216 if (new & NUD_PROBE)
1217 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001218 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001219 neigh_add_timer(neigh, (jiffies +
1220 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001221 neigh->parms->reachable_time :
1222 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001224 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 }
1226
1227 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001228 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001230 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 neigh_update_hhs(neigh);
1232 if (!(new & NUD_CONNECTED))
1233 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001234 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 }
1237 if (new == old)
1238 goto out;
1239 if (new & NUD_CONNECTED)
1240 neigh_connect(neigh);
1241 else
1242 neigh_suspect(neigh);
1243 if (!(old & NUD_VALID)) {
1244 struct sk_buff *skb;
1245
1246 /* Again: avoid dead loop if something went wrong */
1247
1248 while (neigh->nud_state & NUD_VALID &&
1249 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001250 struct dst_entry *dst = skb_dst(skb);
1251 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001253
1254 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001255
1256 /* Why not just use 'neigh' as-is? The problem is that
1257 * things such as shaper, eql, and sch_teql can end up
1258 * using alternative, different, neigh objects to output
1259 * the packet in the output path. So what we need to do
1260 * here is re-lookup the top-level neigh in the path so
1261 * we can reinject the packet there.
1262 */
1263 n2 = NULL;
1264 if (dst) {
1265 n2 = dst_neigh_lookup_skb(dst, skb);
1266 if (n2)
1267 n1 = n2;
1268 }
David S. Miller8f40b162011-07-17 13:34:11 -07001269 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001270 if (n2)
1271 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001272 rcu_read_unlock();
1273
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 write_lock_bh(&neigh->lock);
1275 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001276 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001277 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278 }
1279out:
1280 if (update_isrouter) {
1281 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1282 (neigh->flags | NTF_ROUTER) :
1283 (neigh->flags & ~NTF_ROUTER);
1284 }
1285 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001286
1287 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001288 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001289
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290 return err;
1291}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001292EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293
Jiri Benc7e980562013-12-11 13:48:20 +01001294/* Update the neigh to listen temporarily for probe responses, even if it is
1295 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1296 */
1297void __neigh_set_probe_once(struct neighbour *neigh)
1298{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001299 if (neigh->dead)
1300 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001301 neigh->updated = jiffies;
1302 if (!(neigh->nud_state & NUD_FAILED))
1303 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001304 neigh->nud_state = NUD_INCOMPLETE;
1305 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001306 neigh_add_timer(neigh,
1307 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1308}
1309EXPORT_SYMBOL(__neigh_set_probe_once);
1310
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1312 u8 *lladdr, void *saddr,
1313 struct net_device *dev)
1314{
1315 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1316 lladdr || !dev->addr_len);
1317 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001318 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001319 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320 return neigh;
1321}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001322EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323
Eric Dumazet34d101d2010-10-11 09:16:57 -07001324/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001325static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001327 struct net_device *dev = n->dev;
1328 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001329 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001330
1331 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001332
David S. Millerf6b72b622011-07-14 07:53:20 -07001333 /* Only one thread can come in here and initialize the
1334 * hh_cache entry.
1335 */
David S. Millerb23b5452011-07-16 17:45:02 -07001336 if (!hh->hh_len)
1337 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001338
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001339 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340}
1341
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342/* Slow and careful. */
1343
David S. Miller8f40b162011-07-17 13:34:11 -07001344int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 int rc = 0;
1347
Linus Torvalds1da177e2005-04-16 15:20:36 -07001348 if (!neigh_event_send(neigh, skb)) {
1349 int err;
1350 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001351 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001352
David S. Millerf6b72b622011-07-14 07:53:20 -07001353 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001354 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001355
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001356 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001357 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001358 seq = read_seqbegin(&neigh->ha_lock);
1359 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1360 neigh->ha, NULL, skb->len);
1361 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001364 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 else
1366 goto out_kfree_skb;
1367 }
1368out:
1369 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370out_kfree_skb:
1371 rc = -EINVAL;
1372 kfree_skb(skb);
1373 goto out;
1374}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001375EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376
1377/* As fast as possible without hh cache */
1378
David S. Miller8f40b162011-07-17 13:34:11 -07001379int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001382 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001383 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001385 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001386 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001387 seq = read_seqbegin(&neigh->ha_lock);
1388 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1389 neigh->ha, NULL, skb->len);
1390 } while (read_seqretry(&neigh->ha_lock, seq));
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001393 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 else {
1395 err = -EINVAL;
1396 kfree_skb(skb);
1397 }
1398 return err;
1399}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001400EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
David S. Miller8f40b162011-07-17 13:34:11 -07001402int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1403{
1404 return dev_queue_xmit(skb);
1405}
1406EXPORT_SYMBOL(neigh_direct_output);
1407
Kees Cooke99e88a2017-10-16 14:43:17 -07001408static void neigh_proxy_process(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409{
Kees Cooke99e88a2017-10-16 14:43:17 -07001410 struct neigh_table *tbl = from_timer(tbl, t, proxy_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411 long sched_next = 0;
1412 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001413 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001414
1415 spin_lock(&tbl->proxy_queue.lock);
1416
David S. Millerf72051b2008-09-23 01:11:18 -07001417 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1418 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
Linus Torvalds1da177e2005-04-16 15:20:36 -07001420 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001421 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001422
David S. Millerf72051b2008-09-23 01:11:18 -07001423 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001424 if (tbl->proxy_redo && netif_running(dev)) {
1425 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001426 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001427 rcu_read_unlock();
1428 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001429 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001431
1432 dev_put(dev);
1433 } else if (!sched_next || tdif < sched_next)
1434 sched_next = tdif;
1435 }
1436 del_timer(&tbl->proxy_timer);
1437 if (sched_next)
1438 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1439 spin_unlock(&tbl->proxy_queue.lock);
1440}
1441
1442void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1443 struct sk_buff *skb)
1444{
1445 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001446
1447 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001448 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001450 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 kfree_skb(skb);
1452 return;
1453 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001454
1455 NEIGH_CB(skb)->sched_next = sched_next;
1456 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
1458 spin_lock(&tbl->proxy_queue.lock);
1459 if (del_timer(&tbl->proxy_timer)) {
1460 if (time_before(tbl->proxy_timer.expires, sched_next))
1461 sched_next = tbl->proxy_timer.expires;
1462 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001463 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 dev_hold(skb->dev);
1465 __skb_queue_tail(&tbl->proxy_queue, skb);
1466 mod_timer(&tbl->proxy_timer, sched_next);
1467 spin_unlock(&tbl->proxy_queue.lock);
1468}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001469EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001471static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001472 struct net *net, int ifindex)
1473{
1474 struct neigh_parms *p;
1475
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001476 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001477 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001478 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001479 return p;
1480 }
1481
1482 return NULL;
1483}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484
1485struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1486 struct neigh_table *tbl)
1487{
Gao fengcf89d6b2013-06-20 10:01:32 +08001488 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001489 struct net *net = dev_net(dev);
1490 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491
Gao fengcf89d6b2013-06-20 10:01:32 +08001492 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001495 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001497 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001498 dev_hold(dev);
1499 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001500 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001502
1503 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001504 dev_put(dev);
1505 kfree(p);
1506 return NULL;
1507 }
1508
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001510 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001512
1513 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 }
1515 return p;
1516}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001517EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518
1519static void neigh_rcu_free_parms(struct rcu_head *head)
1520{
1521 struct neigh_parms *parms =
1522 container_of(head, struct neigh_parms, rcu_head);
1523
1524 neigh_parms_put(parms);
1525}
1526
1527void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1528{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 if (!parms || parms == &tbl->parms)
1530 return;
1531 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001532 list_del(&parms->list);
1533 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001535 if (parms->dev)
1536 dev_put(parms->dev);
1537 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001539EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540
Denis V. Lunev06f05112008-01-24 00:30:58 -08001541static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542{
1543 kfree(parms);
1544}
1545
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001546static struct lock_class_key neigh_table_proxy_queue_class;
1547
WANG Congd7480fd2014-11-10 15:59:36 -08001548static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1549
1550void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551{
1552 unsigned long now = jiffies;
1553 unsigned long phsize;
1554
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001555 INIT_LIST_HEAD(&tbl->parms_list);
1556 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001557 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001558 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001560 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 tbl->stats = alloc_percpu(struct neigh_statistics);
1563 if (!tbl->stats)
1564 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001565
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +02001567 if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat,
1568 &neigh_stat_seq_ops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570#endif
1571
David S. Millercd089332011-07-11 01:28:12 -07001572 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
1574 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001575 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001577 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 panic("cannot allocate neighbour cache hashes");
1579
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001580 if (!tbl->entry_size)
1581 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1582 tbl->key_len, NEIGH_PRIV_ALIGN);
1583 else
1584 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1585
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001587 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301588 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1589 tbl->parms.reachable_time);
Kees Cooke99e88a2017-10-16 14:43:17 -07001590 timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001591 skb_queue_head_init_class(&tbl->proxy_queue,
1592 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593
1594 tbl->last_flush = now;
1595 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001596
WANG Congd7480fd2014-11-10 15:59:36 -08001597 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001599EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
WANG Congd7480fd2014-11-10 15:59:36 -08001601int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602{
WANG Congd7480fd2014-11-10 15:59:36 -08001603 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001605 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 del_timer_sync(&tbl->proxy_timer);
1607 pneigh_queue_purge(&tbl->proxy_queue);
1608 neigh_ifdown(tbl, NULL);
1609 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001610 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001612 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1613 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001614 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
1616 kfree(tbl->phash_buckets);
1617 tbl->phash_buckets = NULL;
1618
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001619 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1620
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001621 free_percpu(tbl->stats);
1622 tbl->stats = NULL;
1623
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 return 0;
1625}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001626EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
WANG Congd7480fd2014-11-10 15:59:36 -08001628static struct neigh_table *neigh_find_table(int family)
1629{
1630 struct neigh_table *tbl = NULL;
1631
1632 switch (family) {
1633 case AF_INET:
1634 tbl = neigh_tables[NEIGH_ARP_TABLE];
1635 break;
1636 case AF_INET6:
1637 tbl = neigh_tables[NEIGH_ND_TABLE];
1638 break;
1639 case AF_DECnet:
1640 tbl = neigh_tables[NEIGH_DN_TABLE];
1641 break;
1642 }
1643
1644 return tbl;
1645}
1646
David Ahernc21ef3e2017-04-16 09:48:24 -07001647static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1648 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001650 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001651 struct ndmsg *ndm;
1652 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001654 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001656 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657
Eric Dumazet110b2492010-10-04 04:27:36 +00001658 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001659 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660 goto out;
1661
Thomas Grafa14a49d2006-08-07 17:53:08 -07001662 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1663 if (dst_attr == NULL)
1664 goto out;
1665
1666 ndm = nlmsg_data(nlh);
1667 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001668 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001669 if (dev == NULL) {
1670 err = -ENODEV;
1671 goto out;
1672 }
1673 }
1674
WANG Congd7480fd2014-11-10 15:59:36 -08001675 tbl = neigh_find_table(ndm->ndm_family);
1676 if (tbl == NULL)
1677 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001679 if (nla_len(dst_attr) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001680 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001681
WANG Congd7480fd2014-11-10 15:59:36 -08001682 if (ndm->ndm_flags & NTF_PROXY) {
1683 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001684 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 }
WANG Congd7480fd2014-11-10 15:59:36 -08001686
1687 if (dev == NULL)
1688 goto out;
1689
1690 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1691 if (neigh == NULL) {
1692 err = -ENOENT;
1693 goto out;
1694 }
1695
1696 err = neigh_update(neigh, NULL, NUD_FAILED,
1697 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001698 NEIGH_UPDATE_F_ADMIN,
1699 NETLINK_CB(skb).portid);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001700 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001701 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001702 neigh_remove_one(neigh, tbl);
1703 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001704
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705out:
1706 return err;
1707}
1708
David Ahernc21ef3e2017-04-16 09:48:24 -07001709static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1710 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711{
WANG Congd7480fd2014-11-10 15:59:36 -08001712 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001713 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001714 struct ndmsg *ndm;
1715 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716 struct neigh_table *tbl;
1717 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001718 struct neighbour *neigh;
1719 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001720 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721
Eric Dumazet110b2492010-10-04 04:27:36 +00001722 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001723 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001724 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725 goto out;
1726
Thomas Graf5208deb2006-08-07 17:55:40 -07001727 err = -EINVAL;
1728 if (tb[NDA_DST] == NULL)
1729 goto out;
1730
1731 ndm = nlmsg_data(nlh);
1732 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001733 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001734 if (dev == NULL) {
1735 err = -ENODEV;
1736 goto out;
1737 }
1738
1739 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001740 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001741 }
1742
WANG Congd7480fd2014-11-10 15:59:36 -08001743 tbl = neigh_find_table(ndm->ndm_family);
1744 if (tbl == NULL)
1745 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001747 if (nla_len(tb[NDA_DST]) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001748 goto out;
1749 dst = nla_data(tb[NDA_DST]);
1750 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
WANG Congd7480fd2014-11-10 15:59:36 -08001752 if (ndm->ndm_flags & NTF_PROXY) {
1753 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754
WANG Congd7480fd2014-11-10 15:59:36 -08001755 err = -ENOBUFS;
1756 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1757 if (pn) {
1758 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001759 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001760 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001761 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 }
1763
WANG Congd7480fd2014-11-10 15:59:36 -08001764 if (dev == NULL)
1765 goto out;
1766
1767 neigh = neigh_lookup(tbl, dst, dev);
1768 if (neigh == NULL) {
1769 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1770 err = -ENOENT;
1771 goto out;
1772 }
1773
1774 neigh = __neigh_lookup_errno(tbl, dst, dev);
1775 if (IS_ERR(neigh)) {
1776 err = PTR_ERR(neigh);
1777 goto out;
1778 }
1779 } else {
1780 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1781 err = -EEXIST;
1782 neigh_release(neigh);
1783 goto out;
1784 }
1785
1786 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1787 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1788 }
1789
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001790 if (ndm->ndm_flags & NTF_EXT_LEARNED)
1791 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1792
WANG Congd7480fd2014-11-10 15:59:36 -08001793 if (ndm->ndm_flags & NTF_USE) {
1794 neigh_event_send(neigh, NULL);
1795 err = 0;
1796 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001797 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1798 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001799 neigh_release(neigh);
1800
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801out:
1802 return err;
1803}
1804
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001805static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1806{
Thomas Grafca860fb2006-08-07 18:00:18 -07001807 struct nlattr *nest;
1808
1809 nest = nla_nest_start(skb, NDTA_PARMS);
1810 if (nest == NULL)
1811 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001812
David S. Miller9a6308d2012-04-01 20:06:28 -04001813 if ((parms->dev &&
1814 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001815 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001816 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1817 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001818 /* approximative value for deprecated QUEUE_LEN (in packets) */
1819 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001820 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1821 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1822 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1823 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1824 NEIGH_VAR(parms, UCAST_PROBES)) ||
1825 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1826 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001827 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1828 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001829 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1830 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001831 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001832 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001833 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001834 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001835 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001836 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001837 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001838 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001839 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001840 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001841 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001842 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001843 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001844 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001845 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001846 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001847
Thomas Grafca860fb2006-08-07 18:00:18 -07001848nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001849 nla_nest_cancel(skb, nest);
1850 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001851}
1852
Thomas Grafca860fb2006-08-07 18:00:18 -07001853static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1854 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855{
1856 struct nlmsghdr *nlh;
1857 struct ndtmsg *ndtmsg;
1858
Thomas Grafca860fb2006-08-07 18:00:18 -07001859 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1860 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001861 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001862
Thomas Grafca860fb2006-08-07 18:00:18 -07001863 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001864
1865 read_lock_bh(&tbl->lock);
1866 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001867 ndtmsg->ndtm_pad1 = 0;
1868 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001869
David S. Miller9a6308d2012-04-01 20:06:28 -04001870 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001871 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001872 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1873 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1874 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1875 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001876 {
1877 unsigned long now = jiffies;
1878 unsigned int flush_delta = now - tbl->last_flush;
1879 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001880 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881 struct ndt_config ndc = {
1882 .ndtc_key_len = tbl->key_len,
1883 .ndtc_entry_size = tbl->entry_size,
1884 .ndtc_entries = atomic_read(&tbl->entries),
1885 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1886 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1888 };
1889
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001890 rcu_read_lock_bh();
1891 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001892 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001893 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001894 rcu_read_unlock_bh();
1895
David S. Miller9a6308d2012-04-01 20:06:28 -04001896 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1897 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001898 }
1899
1900 {
1901 int cpu;
1902 struct ndt_stats ndst;
1903
1904 memset(&ndst, 0, sizeof(ndst));
1905
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001906 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001907 struct neigh_statistics *st;
1908
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001909 st = per_cpu_ptr(tbl->stats, cpu);
1910 ndst.ndts_allocs += st->allocs;
1911 ndst.ndts_destroys += st->destroys;
1912 ndst.ndts_hash_grows += st->hash_grows;
1913 ndst.ndts_res_failed += st->res_failed;
1914 ndst.ndts_lookups += st->lookups;
1915 ndst.ndts_hits += st->hits;
1916 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1917 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1918 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1919 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001920 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921 }
1922
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001923 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1924 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001925 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001926 }
1927
1928 BUG_ON(tbl->parms.dev);
1929 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001930 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001931
1932 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001933 nlmsg_end(skb, nlh);
1934 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001935
Thomas Grafca860fb2006-08-07 18:00:18 -07001936nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001938 nlmsg_cancel(skb, nlh);
1939 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001940}
1941
Thomas Grafca860fb2006-08-07 18:00:18 -07001942static int neightbl_fill_param_info(struct sk_buff *skb,
1943 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001945 u32 pid, u32 seq, int type,
1946 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001947{
1948 struct ndtmsg *ndtmsg;
1949 struct nlmsghdr *nlh;
1950
Thomas Grafca860fb2006-08-07 18:00:18 -07001951 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1952 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001953 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001954
Thomas Grafca860fb2006-08-07 18:00:18 -07001955 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001956
1957 read_lock_bh(&tbl->lock);
1958 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001959 ndtmsg->ndtm_pad1 = 0;
1960 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001961
Thomas Grafca860fb2006-08-07 18:00:18 -07001962 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1963 neightbl_fill_parms(skb, parms) < 0)
1964 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001965
1966 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001967 nlmsg_end(skb, nlh);
1968 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001969errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001970 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001971 nlmsg_cancel(skb, nlh);
1972 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001973}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001974
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001975static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001976 [NDTA_NAME] = { .type = NLA_STRING },
1977 [NDTA_THRESH1] = { .type = NLA_U32 },
1978 [NDTA_THRESH2] = { .type = NLA_U32 },
1979 [NDTA_THRESH3] = { .type = NLA_U32 },
1980 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1981 [NDTA_PARMS] = { .type = NLA_NESTED },
1982};
1983
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001984static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001985 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1986 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1987 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1988 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1989 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1990 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001991 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001992 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1993 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1994 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1995 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1996 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1997 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1998 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1999};
2000
David Ahernc21ef3e2017-04-16 09:48:24 -07002001static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
2002 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002003{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002004 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002005 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002006 struct ndtmsg *ndtmsg;
2007 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08002008 bool found = false;
2009 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010
Thomas Graf6b3f8672006-08-07 17:58:53 -07002011 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07002012 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 if (err < 0)
2014 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002015
Thomas Graf6b3f8672006-08-07 17:58:53 -07002016 if (tb[NDTA_NAME] == NULL) {
2017 err = -EINVAL;
2018 goto errout;
2019 }
2020
2021 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002022
2023 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2024 tbl = neigh_tables[tidx];
2025 if (!tbl)
2026 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002027 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2028 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002029 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2030 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002031 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002032 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002033 }
2034
WANG Congd7480fd2014-11-10 15:59:36 -08002035 if (!found)
2036 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002037
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002038 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002039 * We acquire tbl->lock to be nice to the periodic timers and
2040 * make sure they always see a consistent set of values.
2041 */
2042 write_lock_bh(&tbl->lock);
2043
Thomas Graf6b3f8672006-08-07 17:58:53 -07002044 if (tb[NDTA_PARMS]) {
2045 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002046 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002047 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002048
Thomas Graf6b3f8672006-08-07 17:58:53 -07002049 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002050 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002051 if (err < 0)
2052 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002053
Thomas Graf6b3f8672006-08-07 17:58:53 -07002054 if (tbp[NDTPA_IFINDEX])
2055 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002056
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002057 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002058 if (p == NULL) {
2059 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002060 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002061 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002062
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 for (i = 1; i <= NDTPA_MAX; i++) {
2064 if (tbp[i] == NULL)
2065 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002066
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067 switch (i) {
2068 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002069 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2070 nla_get_u32(tbp[i]) *
2071 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002072 break;
2073 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002074 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2075 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002078 NEIGH_VAR_SET(p, PROXY_QLEN,
2079 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002080 break;
2081 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002082 NEIGH_VAR_SET(p, APP_PROBES,
2083 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002084 break;
2085 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002086 NEIGH_VAR_SET(p, UCAST_PROBES,
2087 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002088 break;
2089 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002090 NEIGH_VAR_SET(p, MCAST_PROBES,
2091 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002092 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002093 case NDTPA_MCAST_REPROBES:
2094 NEIGH_VAR_SET(p, MCAST_REPROBES,
2095 nla_get_u32(tbp[i]));
2096 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002097 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002098 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2099 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002100 /* update reachable_time as well, otherwise, the change will
2101 * only be effective after the next time neigh_periodic_work
2102 * decides to recompute it (can be multiple minutes)
2103 */
2104 p->reachable_time =
2105 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002106 break;
2107 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002108 NEIGH_VAR_SET(p, GC_STALETIME,
2109 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002110 break;
2111 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002112 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2113 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002114 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002115 break;
2116 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002117 NEIGH_VAR_SET(p, RETRANS_TIME,
2118 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002119 break;
2120 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002121 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2122 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002123 break;
2124 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002125 NEIGH_VAR_SET(p, PROXY_DELAY,
2126 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002127 break;
2128 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002129 NEIGH_VAR_SET(p, LOCKTIME,
2130 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002131 break;
2132 }
2133 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002134 }
2135
Gao fengdc25c672013-06-20 10:01:34 +08002136 err = -ENOENT;
2137 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2138 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2139 !net_eq(net, &init_net))
2140 goto errout_tbl_lock;
2141
Thomas Graf6b3f8672006-08-07 17:58:53 -07002142 if (tb[NDTA_THRESH1])
2143 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2144
2145 if (tb[NDTA_THRESH2])
2146 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2147
2148 if (tb[NDTA_THRESH3])
2149 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2150
2151 if (tb[NDTA_GC_INTERVAL])
2152 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2153
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002154 err = 0;
2155
Thomas Graf6b3f8672006-08-07 17:58:53 -07002156errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002157 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002158errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002159 return err;
2160}
2161
Thomas Grafc8822a42007-03-22 11:50:06 -07002162static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002163{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002164 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002165 int family, tidx, nidx = 0;
2166 int tbl_skip = cb->args[0];
2167 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002168 struct neigh_table *tbl;
2169
Thomas Grafca860fb2006-08-07 18:00:18 -07002170 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002171
WANG Congd7480fd2014-11-10 15:59:36 -08002172 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002173 struct neigh_parms *p;
2174
WANG Congd7480fd2014-11-10 15:59:36 -08002175 tbl = neigh_tables[tidx];
2176 if (!tbl)
2177 continue;
2178
Thomas Grafca860fb2006-08-07 18:00:18 -07002179 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180 continue;
2181
Eric W. Biederman15e47302012-09-07 20:12:54 +00002182 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002183 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002184 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002185 break;
2186
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002187 nidx = 0;
2188 p = list_next_entry(&tbl->parms, list);
2189 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002190 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002191 continue;
2192
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002193 if (nidx < neigh_skip)
2194 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002195
Thomas Grafca860fb2006-08-07 18:00:18 -07002196 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002197 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002198 cb->nlh->nlmsg_seq,
2199 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002200 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002201 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002202 next:
2203 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002204 }
2205
Thomas Grafca860fb2006-08-07 18:00:18 -07002206 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002207 }
2208out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002209 cb->args[0] = tidx;
2210 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002211
2212 return skb->len;
2213}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214
Thomas Graf8b8aec52006-08-07 17:56:37 -07002215static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2216 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217{
2218 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002220 struct nlmsghdr *nlh;
2221 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002222
Thomas Graf8b8aec52006-08-07 17:56:37 -07002223 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2224 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002225 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002226
2227 ndm = nlmsg_data(nlh);
2228 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002229 ndm->ndm_pad1 = 0;
2230 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002231 ndm->ndm_flags = neigh->flags;
2232 ndm->ndm_type = neigh->type;
2233 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002234
David S. Miller9a6308d2012-04-01 20:06:28 -04002235 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2236 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002237
2238 read_lock_bh(&neigh->lock);
2239 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002240 if (neigh->nud_state & NUD_VALID) {
2241 char haddr[MAX_ADDR_LEN];
2242
2243 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2244 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2245 read_unlock_bh(&neigh->lock);
2246 goto nla_put_failure;
2247 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002248 }
2249
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002250 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2251 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2252 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002253 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002254 read_unlock_bh(&neigh->lock);
2255
David S. Miller9a6308d2012-04-01 20:06:28 -04002256 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2257 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2258 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002259
Johannes Berg053c0952015-01-16 22:09:00 +01002260 nlmsg_end(skb, nlh);
2261 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002262
2263nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002264 nlmsg_cancel(skb, nlh);
2265 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266}
2267
Tony Zelenoff84920c12012-01-26 22:28:58 +00002268static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2269 u32 pid, u32 seq, int type, unsigned int flags,
2270 struct neigh_table *tbl)
2271{
2272 struct nlmsghdr *nlh;
2273 struct ndmsg *ndm;
2274
2275 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2276 if (nlh == NULL)
2277 return -EMSGSIZE;
2278
2279 ndm = nlmsg_data(nlh);
2280 ndm->ndm_family = tbl->family;
2281 ndm->ndm_pad1 = 0;
2282 ndm->ndm_pad2 = 0;
2283 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002284 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002285 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002286 ndm->ndm_state = NUD_NONE;
2287
David S. Miller9a6308d2012-04-01 20:06:28 -04002288 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2289 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002290
Johannes Berg053c0952015-01-16 22:09:00 +01002291 nlmsg_end(skb, nlh);
2292 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002293
2294nla_put_failure:
2295 nlmsg_cancel(skb, nlh);
2296 return -EMSGSIZE;
2297}
2298
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002299static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002300{
2301 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002302 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002303}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304
David Ahern21fdd092015-09-29 09:32:03 -07002305static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2306{
2307 struct net_device *master;
2308
2309 if (!master_idx)
2310 return false;
2311
2312 master = netdev_master_upper_dev_get(dev);
2313 if (!master || master->ifindex != master_idx)
2314 return true;
2315
2316 return false;
2317}
2318
David Ahern16660f02015-10-03 11:43:46 -07002319static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2320{
2321 if (filter_idx && dev->ifindex != filter_idx)
2322 return true;
2323
2324 return false;
2325}
2326
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2328 struct netlink_callback *cb)
2329{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002330 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002331 const struct nlmsghdr *nlh = cb->nlh;
2332 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 struct neighbour *n;
2334 int rc, h, s_h = cb->args[1];
2335 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002336 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002337 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002338 unsigned int flags = NLM_F_MULTI;
2339 int err;
2340
Johannes Bergfceb6432017-04-12 14:34:07 +02002341 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002342 if (!err) {
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002343 if (tb[NDA_IFINDEX]) {
2344 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
2345 return -EINVAL;
David Ahern16660f02015-10-03 11:43:46 -07002346 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002347 }
2348 if (tb[NDA_MASTER]) {
2349 if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
2350 return -EINVAL;
David Ahern21fdd092015-09-29 09:32:03 -07002351 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002352 }
David Ahern16660f02015-10-03 11:43:46 -07002353 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002354 flags |= NLM_F_DUMP_FILTERED;
2355 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002357 rcu_read_lock_bh();
2358 nht = rcu_dereference_bh(tbl->nht);
2359
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002360 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 if (h > s_h)
2362 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002363 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2364 n != NULL;
2365 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002366 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2367 goto next;
2368 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2369 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002370 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002371 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002373 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002374 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 rc = -1;
2376 goto out;
2377 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002378next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002379 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 }
2382 rc = skb->len;
2383out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002384 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385 cb->args[1] = h;
2386 cb->args[2] = idx;
2387 return rc;
2388}
2389
Tony Zelenoff84920c12012-01-26 22:28:58 +00002390static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2391 struct netlink_callback *cb)
2392{
2393 struct pneigh_entry *n;
2394 struct net *net = sock_net(skb->sk);
2395 int rc, h, s_h = cb->args[3];
2396 int idx, s_idx = idx = cb->args[4];
2397
2398 read_lock_bh(&tbl->lock);
2399
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002400 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002401 if (h > s_h)
2402 s_idx = 0;
2403 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002404 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002405 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002406 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002407 cb->nlh->nlmsg_seq,
2408 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002409 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002410 read_unlock_bh(&tbl->lock);
2411 rc = -1;
2412 goto out;
2413 }
2414 next:
2415 idx++;
2416 }
2417 }
2418
2419 read_unlock_bh(&tbl->lock);
2420 rc = skb->len;
2421out:
2422 cb->args[3] = h;
2423 cb->args[4] = idx;
2424 return rc;
2425
2426}
2427
Thomas Grafc8822a42007-03-22 11:50:06 -07002428static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429{
2430 struct neigh_table *tbl;
2431 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002432 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002433 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002434
Thomas Graf8b8aec52006-08-07 17:56:37 -07002435 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002436
2437 /* check for full ndmsg structure presence, family member is
2438 * the same for both structures
2439 */
2440 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2441 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2442 proxy = 1;
2443
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444 s_t = cb->args[0];
2445
WANG Congd7480fd2014-11-10 15:59:36 -08002446 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2447 tbl = neigh_tables[t];
2448
2449 if (!tbl)
2450 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451 if (t < s_t || (family && tbl->family != family))
2452 continue;
2453 if (t > s_t)
2454 memset(&cb->args[1], 0, sizeof(cb->args) -
2455 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002456 if (proxy)
2457 err = pneigh_dump_table(tbl, skb, cb);
2458 else
2459 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002460 if (err < 0)
2461 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463
2464 cb->args[0] = t;
2465 return skb->len;
2466}
2467
2468void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2469{
2470 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002471 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002473 rcu_read_lock_bh();
2474 nht = rcu_dereference_bh(tbl->nht);
2475
Eric Dumazet767e97e2010-10-06 17:49:21 -07002476 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002477 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 struct neighbour *n;
2479
Eric Dumazet767e97e2010-10-06 17:49:21 -07002480 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2481 n != NULL;
2482 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483 cb(n, cookie);
2484 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002485 read_unlock(&tbl->lock);
2486 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002487}
2488EXPORT_SYMBOL(neigh_for_each);
2489
2490/* The tbl->lock must be held as a writer and BH disabled. */
2491void __neigh_for_each_release(struct neigh_table *tbl,
2492 int (*cb)(struct neighbour *))
2493{
2494 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002495 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002497 nht = rcu_dereference_protected(tbl->nht,
2498 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002499 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002500 struct neighbour *n;
2501 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002503 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002504 while ((n = rcu_dereference_protected(*np,
2505 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 int release;
2507
2508 write_lock(&n->lock);
2509 release = cb(n);
2510 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002511 rcu_assign_pointer(*np,
2512 rcu_dereference_protected(n->next,
2513 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 n->dead = 1;
2515 } else
2516 np = &n->next;
2517 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002518 if (release)
2519 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 }
2521 }
2522}
2523EXPORT_SYMBOL(__neigh_for_each_release);
2524
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002525int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002526 const void *addr, struct sk_buff *skb)
2527{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002528 int err = -EAFNOSUPPORT;
2529 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002530 struct neigh_table *tbl;
2531 struct neighbour *neigh;
2532
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002533 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002534 if (!tbl)
2535 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002536 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002537 neigh = __neigh_lookup_noref(tbl, addr, dev);
2538 if (!neigh)
2539 neigh = __neigh_create(tbl, addr, dev, false);
2540 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002541 if (IS_ERR(neigh)) {
2542 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002543 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002544 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002545 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002546 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002547 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002548 else if (index == NEIGH_LINK_TABLE) {
2549 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2550 addr, NULL, skb->len);
2551 if (err < 0)
2552 goto out_kfree_skb;
2553 err = dev_queue_xmit(skb);
2554 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002555out:
2556 return err;
2557out_kfree_skb:
2558 kfree_skb(skb);
2559 goto out;
2560}
2561EXPORT_SYMBOL(neigh_xmit);
2562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563#ifdef CONFIG_PROC_FS
2564
2565static struct neighbour *neigh_get_first(struct seq_file *seq)
2566{
2567 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002568 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002569 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 struct neighbour *n = NULL;
2571 int bucket = state->bucket;
2572
2573 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002574 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002575 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002576
2577 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002578 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002579 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 if (state->neigh_sub_iter) {
2581 loff_t fakep = 0;
2582 void *v;
2583
2584 v = state->neigh_sub_iter(state, n, &fakep);
2585 if (!v)
2586 goto next;
2587 }
2588 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2589 break;
2590 if (n->nud_state & ~NUD_NOARP)
2591 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002592next:
2593 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 }
2595
2596 if (n)
2597 break;
2598 }
2599 state->bucket = bucket;
2600
2601 return n;
2602}
2603
2604static struct neighbour *neigh_get_next(struct seq_file *seq,
2605 struct neighbour *n,
2606 loff_t *pos)
2607{
2608 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002609 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002610 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
2612 if (state->neigh_sub_iter) {
2613 void *v = state->neigh_sub_iter(state, n, pos);
2614 if (v)
2615 return n;
2616 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002617 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618
2619 while (1) {
2620 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002621 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002622 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 if (state->neigh_sub_iter) {
2624 void *v = state->neigh_sub_iter(state, n, pos);
2625 if (v)
2626 return n;
2627 goto next;
2628 }
2629 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2630 break;
2631
2632 if (n->nud_state & ~NUD_NOARP)
2633 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002634next:
2635 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 }
2637
2638 if (n)
2639 break;
2640
David S. Millercd089332011-07-11 01:28:12 -07002641 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 break;
2643
Eric Dumazet767e97e2010-10-06 17:49:21 -07002644 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 }
2646
2647 if (n && pos)
2648 --(*pos);
2649 return n;
2650}
2651
2652static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2653{
2654 struct neighbour *n = neigh_get_first(seq);
2655
2656 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002657 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 while (*pos) {
2659 n = neigh_get_next(seq, n, pos);
2660 if (!n)
2661 break;
2662 }
2663 }
2664 return *pos ? NULL : n;
2665}
2666
2667static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2668{
2669 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002670 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002671 struct neigh_table *tbl = state->tbl;
2672 struct pneigh_entry *pn = NULL;
2673 int bucket = state->bucket;
2674
2675 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2676 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2677 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002678 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002679 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 if (pn)
2681 break;
2682 }
2683 state->bucket = bucket;
2684
2685 return pn;
2686}
2687
2688static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2689 struct pneigh_entry *pn,
2690 loff_t *pos)
2691{
2692 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002693 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694 struct neigh_table *tbl = state->tbl;
2695
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002696 do {
2697 pn = pn->next;
2698 } while (pn && !net_eq(pneigh_net(pn), net));
2699
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 while (!pn) {
2701 if (++state->bucket > PNEIGH_HASHMASK)
2702 break;
2703 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002704 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002705 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706 if (pn)
2707 break;
2708 }
2709
2710 if (pn && pos)
2711 --(*pos);
2712
2713 return pn;
2714}
2715
2716static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2717{
2718 struct pneigh_entry *pn = pneigh_get_first(seq);
2719
2720 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002721 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002722 while (*pos) {
2723 pn = pneigh_get_next(seq, pn, pos);
2724 if (!pn)
2725 break;
2726 }
2727 }
2728 return *pos ? NULL : pn;
2729}
2730
2731static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2732{
2733 struct neigh_seq_state *state = seq->private;
2734 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002735 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736
Chris Larson745e2032008-08-03 01:10:55 -07002737 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002739 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741 return rc;
2742}
2743
2744void *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 +00002745 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746{
2747 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748
2749 state->tbl = tbl;
2750 state->bucket = 0;
2751 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2752
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002753 rcu_read_lock_bh();
2754 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002755
Chris Larson745e2032008-08-03 01:10:55 -07002756 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002757}
2758EXPORT_SYMBOL(neigh_seq_start);
2759
2760void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2761{
2762 struct neigh_seq_state *state;
2763 void *rc;
2764
2765 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002766 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767 goto out;
2768 }
2769
2770 state = seq->private;
2771 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2772 rc = neigh_get_next(seq, v, NULL);
2773 if (rc)
2774 goto out;
2775 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2776 rc = pneigh_get_first(seq);
2777 } else {
2778 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2779 rc = pneigh_get_next(seq, v, NULL);
2780 }
2781out:
2782 ++(*pos);
2783 return rc;
2784}
2785EXPORT_SYMBOL(neigh_seq_next);
2786
2787void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002788 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002789{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002790 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791}
2792EXPORT_SYMBOL(neigh_seq_stop);
2793
2794/* statistics via seq_file */
2795
2796static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2797{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002798 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 int cpu;
2800
2801 if (*pos == 0)
2802 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002803
Rusty Russell0f23174a2008-12-29 12:23:42 +00002804 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002805 if (!cpu_possible(cpu))
2806 continue;
2807 *pos = cpu+1;
2808 return per_cpu_ptr(tbl->stats, cpu);
2809 }
2810 return NULL;
2811}
2812
2813static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2814{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002815 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 int cpu;
2817
Rusty Russell0f23174a2008-12-29 12:23:42 +00002818 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002819 if (!cpu_possible(cpu))
2820 continue;
2821 *pos = cpu+1;
2822 return per_cpu_ptr(tbl->stats, cpu);
2823 }
2824 return NULL;
2825}
2826
2827static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2828{
2829
2830}
2831
2832static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2833{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002834 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002835 struct neigh_statistics *st = v;
2836
2837 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002838 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 -07002839 return 0;
2840 }
2841
2842 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002843 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002844 atomic_read(&tbl->entries),
2845
2846 st->allocs,
2847 st->destroys,
2848 st->hash_grows,
2849
2850 st->lookups,
2851 st->hits,
2852
2853 st->res_failed,
2854
2855 st->rcv_probes_mcast,
2856 st->rcv_probes_ucast,
2857
2858 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002859 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002860 st->unres_discards,
2861 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002862 );
2863
2864 return 0;
2865}
2866
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002867static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868 .start = neigh_stat_seq_start,
2869 .next = neigh_stat_seq_next,
2870 .stop = neigh_stat_seq_stop,
2871 .show = neigh_stat_seq_show,
2872};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002873#endif /* CONFIG_PROC_FS */
2874
Thomas Graf339bf982006-11-10 14:10:15 -08002875static inline size_t neigh_nlmsg_size(void)
2876{
2877 return NLMSG_ALIGN(sizeof(struct ndmsg))
2878 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2879 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2880 + nla_total_size(sizeof(struct nda_cacheinfo))
2881 + nla_total_size(4); /* NDA_PROBES */
2882}
2883
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002884static void __neigh_notify(struct neighbour *n, int type, int flags,
2885 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002887 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002888 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002889 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890
Thomas Graf339bf982006-11-10 14:10:15 -08002891 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002892 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002893 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002895 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002896 if (err < 0) {
2897 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2898 WARN_ON(err == -EMSGSIZE);
2899 kfree_skb(skb);
2900 goto errout;
2901 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002902 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2903 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002904errout:
2905 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002906 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002907}
2908
2909void neigh_app_ns(struct neighbour *n)
2910{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002911 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002913EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
2915#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002916static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002917static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002918static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
Joe Perchesfe2c6332013-06-11 23:04:25 -07002920static int proc_unres_qlen(struct ctl_table *ctl, int write,
2921 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002922{
2923 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002924 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002925
Shan Weice46cc62012-12-04 18:49:15 +00002926 tmp.extra1 = &zero;
2927 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002928 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002929
2930 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2931 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2932
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002933 if (write && !ret)
2934 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2935 return ret;
2936}
2937
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002938static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2939 int family)
2940{
Jiri Pirkobba24892013-12-07 19:26:57 +01002941 switch (family) {
2942 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002943 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002944 case AF_INET6:
2945 return __in6_dev_nd_parms_get_rcu(dev);
2946 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002947 return NULL;
2948}
2949
2950static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2951 int index)
2952{
2953 struct net_device *dev;
2954 int family = neigh_parms_family(p);
2955
2956 rcu_read_lock();
2957 for_each_netdev_rcu(net, dev) {
2958 struct neigh_parms *dst_p =
2959 neigh_get_dev_parms_rcu(dev, family);
2960
2961 if (dst_p && !test_bit(index, dst_p->data_state))
2962 dst_p->data[index] = p->data[index];
2963 }
2964 rcu_read_unlock();
2965}
2966
2967static void neigh_proc_update(struct ctl_table *ctl, int write)
2968{
2969 struct net_device *dev = ctl->extra1;
2970 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002971 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002972 int index = (int *) ctl->data - p->data;
2973
2974 if (!write)
2975 return;
2976
2977 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002978 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2979 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002980 if (!dev) /* NULL dev means this is default value */
2981 neigh_copy_dflt_parms(net, p, index);
2982}
2983
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002984static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2985 void __user *buffer,
2986 size_t *lenp, loff_t *ppos)
2987{
2988 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002989 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002990
2991 tmp.extra1 = &zero;
2992 tmp.extra2 = &int_max;
2993
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002994 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2995 neigh_proc_update(ctl, write);
2996 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002997}
2998
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002999int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3000 void __user *buffer, size_t *lenp, loff_t *ppos)
3001{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003002 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3003
3004 neigh_proc_update(ctl, write);
3005 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003006}
3007EXPORT_SYMBOL(neigh_proc_dointvec);
3008
3009int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3010 void __user *buffer,
3011 size_t *lenp, loff_t *ppos)
3012{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003013 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3014
3015 neigh_proc_update(ctl, write);
3016 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003017}
3018EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3019
3020static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3021 void __user *buffer,
3022 size_t *lenp, loff_t *ppos)
3023{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003024 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3025
3026 neigh_proc_update(ctl, write);
3027 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003028}
3029
3030int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3031 void __user *buffer,
3032 size_t *lenp, loff_t *ppos)
3033{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003034 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3035
3036 neigh_proc_update(ctl, write);
3037 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003038}
3039EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3040
3041static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3042 void __user *buffer,
3043 size_t *lenp, loff_t *ppos)
3044{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003045 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3046
3047 neigh_proc_update(ctl, write);
3048 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003049}
3050
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003051static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3052 void __user *buffer,
3053 size_t *lenp, loff_t *ppos)
3054{
3055 struct neigh_parms *p = ctl->extra2;
3056 int ret;
3057
3058 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3059 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3060 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3061 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3062 else
3063 ret = -1;
3064
3065 if (write && ret == 0) {
3066 /* update reachable_time as well, otherwise, the change will
3067 * only be effective after the next time neigh_periodic_work
3068 * decides to recompute it
3069 */
3070 p->reachable_time =
3071 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3072 }
3073 return ret;
3074}
3075
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003076#define NEIGH_PARMS_DATA_OFFSET(index) \
3077 (&((struct neigh_parms *) 0)->data[index])
3078
3079#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3080 [NEIGH_VAR_ ## attr] = { \
3081 .procname = name, \
3082 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3083 .maxlen = sizeof(int), \
3084 .mode = mval, \
3085 .proc_handler = proc, \
3086 }
3087
3088#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3089 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3090
3091#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003092 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003093
3094#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003095 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003096
3097#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003098 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003099
3100#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003101 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003102
3103#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003104 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003105
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106static struct neigh_sysctl_table {
3107 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003108 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003109} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003111 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3112 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3113 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003114 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003115 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3116 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3117 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3118 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3119 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3120 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3121 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3122 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3123 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3124 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3125 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3126 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003127 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 .procname = "gc_interval",
3129 .maxlen = sizeof(int),
3130 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003131 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003133 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 .procname = "gc_thresh1",
3135 .maxlen = sizeof(int),
3136 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003137 .extra1 = &zero,
3138 .extra2 = &int_max,
3139 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003141 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 .procname = "gc_thresh2",
3143 .maxlen = sizeof(int),
3144 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003145 .extra1 = &zero,
3146 .extra2 = &int_max,
3147 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003149 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 .procname = "gc_thresh3",
3151 .maxlen = sizeof(int),
3152 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003153 .extra1 = &zero,
3154 .extra2 = &int_max,
3155 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003157 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 },
3159};
3160
3161int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003162 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003164 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003165 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003166 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003167 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003168 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003170 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003172 goto err;
3173
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003174 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003175 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003176 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003177 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
3180 if (dev) {
3181 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003182 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003183 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3184 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003186 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003187 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003188 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3189 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3190 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3191 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 }
3193
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003194 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003196 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003198 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003200 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003202 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003203 } else {
3204 /* Those handlers will update p->reachable_time after
3205 * base_reachable_time(_ms) is set to ensure the new timer starts being
3206 * applied after the next neighbour update instead of waiting for
3207 * neigh_periodic_work to update its value (can be multiple minutes)
3208 * So any handler that replaces them should do this as well
3209 */
3210 /* ReachableTime */
3211 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3212 neigh_proc_base_reachable_time;
3213 /* ReachableTime (in milliseconds) */
3214 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3215 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 }
3217
Eric W. Biederman464dc802012-11-16 03:02:59 +00003218 /* Don't export sysctls to unprivileged users */
3219 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3220 t->neigh_vars[0].procname = NULL;
3221
Jiri Pirko73af6142013-12-07 19:26:55 +01003222 switch (neigh_parms_family(p)) {
3223 case AF_INET:
3224 p_name = "ipv4";
3225 break;
3226 case AF_INET6:
3227 p_name = "ipv6";
3228 break;
3229 default:
3230 BUG();
3231 }
3232
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003233 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3234 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003235 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003236 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003237 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003238 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 p->sysctl_table = t;
3241 return 0;
3242
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003243free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003245err:
3246 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003248EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
3250void neigh_sysctl_unregister(struct neigh_parms *p)
3251{
3252 if (p->sysctl_table) {
3253 struct neigh_sysctl_table *t = p->sysctl_table;
3254 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003255 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 kfree(t);
3257 }
3258}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003259EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
3261#endif /* CONFIG_SYSCTL */
3262
Thomas Grafc8822a42007-03-22 11:50:06 -07003263static int __init neigh_init(void)
3264{
Florian Westphalb97bac62017-08-09 20:41:48 +02003265 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3266 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
3267 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003268
Greg Rosec7ac8672011-06-10 01:27:09 +00003269 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003270 0);
3271 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003272
3273 return 0;
3274}
3275
3276subsys_initcall(neigh_init);