blob: 0e831671634d5bac98a63fbde4f07c3bc316e44d [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>
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +030021#include <linux/kmemleak.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/types.h>
23#include <linux/kernel.h>
24#include <linux/module.h>
25#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070026#include <linux/netdevice.h>
27#include <linux/proc_fs.h>
28#ifdef CONFIG_SYSCTL
29#include <linux/sysctl.h>
30#endif
31#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020032#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <net/neighbour.h>
David Ahern86e00b72019-05-01 18:18:42 -070034#include <net/arp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <net/dst.h>
36#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070037#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070038#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070039#include <linux/rtnetlink.h>
40#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070041#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070042#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010043#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010044#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070047#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000048#define neigh_dbg(level, fmt, ...) \
49do { \
50 if (level <= NEIGH_DEBUG) \
51 pr_debug(fmt, ##__VA_ARGS__); \
52} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54#define PNEIGH_HASHMASK 0xF
55
56static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070057static void __neigh_notify(struct neighbour *n, int type, int flags);
58static void neigh_update_notify(struct neighbour *neigh);
Wolfgang Bumiller581cb192018-04-12 10:46:55 +020059static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
60 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Ravinder Konkaa71b6682015-04-09 11:42:00 +053062static unsigned int neigh_probe_enable;
Amos Waterland45fc3b12005-09-24 16:53:16 -070063#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080064static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070065#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070066
67/*
68 Neighbour hash table buckets are protected with rwlock tbl->lock.
69
70 - All the scans/updates to hash buckets MUST be made under this lock.
71 - NOTHING clever should be made under this lock: no callbacks
72 to protocol backends, no attempts to send something to network.
73 It will result in deadlocks, if backend/driver wants to use neighbour
74 cache.
75 - If the entry requires some non-trivial actions, increase
76 its reference count and release table lock.
77
78 Neighbour entries are protected:
79 - with reference count.
80 - with rwlock neigh->lock
81
82 Reference count prevents destruction.
83
84 neigh->lock mainly serializes ll address data and its validity state.
85 However, the same lock is used to protect another entry fields:
86 - timer
87 - resolution queue
88
89 Again, nothing clever shall be made under neigh->lock,
90 the most complicated procedure, which we allow is dev->hard_header.
91 It is supposed, that dev->hard_header is simplistic and does
92 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070093 */
94
David S. Miller8f40b162011-07-17 13:34:11 -070095static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096{
97 kfree_skb(skb);
98 return -ENETDOWN;
99}
100
Thomas Graf4f494552007-08-08 23:12:36 -0700101static void neigh_cleanup_and_release(struct neighbour *neigh)
102{
103 if (neigh->parms->neigh_cleanup)
104 neigh->parms->neigh_cleanup(neigh);
105
Thomas Grafd961db32007-08-08 23:12:56 -0700106 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700107 neigh_release(neigh);
108}
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110/*
111 * It is random distribution in the interval (1/2)*base...(3/2)*base.
112 * It corresponds to default IPv6 settings and is not overridable,
113 * because it is really reasonable choice.
114 */
115
116unsigned long neigh_rand_reach_time(unsigned long base)
117{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500118 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900120EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122
123static int neigh_forced_gc(struct neigh_table *tbl)
124{
125 int shrunk = 0;
126 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000127 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128
129 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
130
131 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000132 nht = rcu_dereference_protected(tbl->nht,
133 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700134 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700135 struct neighbour *n;
136 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000138 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700139 while ((n = rcu_dereference_protected(*np,
140 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 /* Neighbour record may be discarded if:
142 * - nobody refers to it.
143 * - it is not permanent
144 */
145 write_lock(&n->lock);
146 if (atomic_read(&n->refcnt) == 1 &&
147 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700148 rcu_assign_pointer(*np,
149 rcu_dereference_protected(n->next,
150 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 n->dead = 1;
152 shrunk = 1;
153 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700154 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155 continue;
156 }
157 write_unlock(&n->lock);
158 np = &n->next;
159 }
160 }
161
162 tbl->last_flush = jiffies;
163
164 write_unlock_bh(&tbl->lock);
165
166 return shrunk;
167}
168
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800169static void neigh_add_timer(struct neighbour *n, unsigned long when)
170{
171 neigh_hold(n);
172 if (unlikely(mod_timer(&n->timer, when))) {
173 printk("NEIGH: BUG, double timer add, state is %x\n",
174 n->nud_state);
175 dump_stack();
176 }
177}
178
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179static int neigh_del_timer(struct neighbour *n)
180{
181 if ((n->nud_state & NUD_IN_TIMER) &&
182 del_timer(&n->timer)) {
183 neigh_release(n);
184 return 1;
185 }
186 return 0;
187}
188
189static void pneigh_queue_purge(struct sk_buff_head *list)
190{
191 struct sk_buff *skb;
192
193 while ((skb = skb_dequeue(list)) != NULL) {
194 dev_put(skb->dev);
195 kfree_skb(skb);
196 }
197}
198
Herbert Xu49636bb2005-10-23 17:18:00 +1000199static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700200{
201 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000202 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000204 nht = rcu_dereference_protected(tbl->nht,
205 lockdep_is_held(&tbl->lock));
206
David S. Millercd089332011-07-11 01:28:12 -0700207 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700208 struct neighbour *n;
209 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700210
Eric Dumazet767e97e2010-10-06 17:49:21 -0700211 while ((n = rcu_dereference_protected(*np,
212 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213 if (dev && n->dev != dev) {
214 np = &n->next;
215 continue;
216 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700217 rcu_assign_pointer(*np,
218 rcu_dereference_protected(n->next,
219 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 write_lock(&n->lock);
221 neigh_del_timer(n);
222 n->dead = 1;
223
224 if (atomic_read(&n->refcnt) != 1) {
225 /* The most unpleasant situation.
226 We must destroy neighbour entry,
227 but someone still uses it.
228
229 The destroy will be delayed until
230 the last user releases us, but
231 we must kill timers etc. and move
232 it to safe state.
233 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700234 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000235 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236 n->output = neigh_blackhole;
237 if (n->nud_state & NUD_VALID)
238 n->nud_state = NUD_NOARP;
239 else
240 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000241 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700242 }
243 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700244 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700245 }
246 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000247}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248
Herbert Xu49636bb2005-10-23 17:18:00 +1000249void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
250{
251 write_lock_bh(&tbl->lock);
252 neigh_flush_dev(tbl, dev);
253 write_unlock_bh(&tbl->lock);
254}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900255EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000256
257int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
258{
259 write_lock_bh(&tbl->lock);
260 neigh_flush_dev(tbl, dev);
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200261 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262
263 del_timer_sync(&tbl->proxy_timer);
264 pneigh_queue_purge(&tbl->proxy_queue);
265 return 0;
266}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900267EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
David Miller596b9b62011-07-25 00:01:25 +0000269static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270{
271 struct neighbour *n = NULL;
272 unsigned long now = jiffies;
273 int entries;
274
275 entries = atomic_inc_return(&tbl->entries) - 1;
276 if (entries >= tbl->gc_thresh3 ||
277 (entries >= tbl->gc_thresh2 &&
278 time_after(now, tbl->last_flush + 5 * HZ))) {
279 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700280 entries >= tbl->gc_thresh3) {
281 net_info_ratelimited("%s: neighbor table overflow!\n",
282 tbl->id);
283 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
287
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000288 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289 if (!n)
290 goto out_entries;
291
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700292 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000294 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 n->updated = n->used = now;
296 n->nud_state = NUD_NONE;
297 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700298 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800300 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
302 NEIGH_CACHE_STAT_INC(tbl, allocs);
303 n->tbl = tbl;
304 atomic_set(&n->refcnt, 1);
305 n->dead = 1;
306out:
307 return n;
308
309out_entries:
310 atomic_dec(&tbl->entries);
311 goto out;
312}
313
David S. Miller2c2aba62011-12-28 15:06:58 -0500314static void neigh_get_hash_rnd(u32 *x)
315{
316 get_random_bytes(x, sizeof(*x));
317 *x |= 1;
318}
319
David S. Millercd089332011-07-11 01:28:12 -0700320static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700321{
David S. Millercd089332011-07-11 01:28:12 -0700322 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000323 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000324 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500325 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000327 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
328 if (!ret)
329 return NULL;
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300330 if (size <= PAGE_SIZE) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000331 buckets = kzalloc(size, GFP_ATOMIC);
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300332 } else {
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000333 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000334 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
335 get_order(size));
Konstantin Khlebnikov41feb092019-01-14 13:38:43 +0300336 kmemleak_alloc(buckets, size, 1, GFP_ATOMIC);
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300337 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000338 if (!buckets) {
339 kfree(ret);
340 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000342 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700343 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500344 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
345 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 return ret;
347}
348
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000349static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000351 struct neigh_hash_table *nht = container_of(head,
352 struct neigh_hash_table,
353 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700354 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000355 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300357 if (size <= PAGE_SIZE) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000358 kfree(buckets);
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300359 } else {
360 kmemleak_free(buckets);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000361 free_pages((unsigned long)buckets, get_order(size));
Konstantin Khlebnikov4f4594a2019-01-08 12:30:00 +0300362 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364}
365
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000366static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700367 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700368{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000369 unsigned int i, hash;
370 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371
372 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
373
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000374 old_nht = rcu_dereference_protected(tbl->nht,
375 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700376 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000377 if (!new_nht)
378 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379
David S. Millercd089332011-07-11 01:28:12 -0700380 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381 struct neighbour *n, *next;
382
Eric Dumazet767e97e2010-10-06 17:49:21 -0700383 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
384 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000385 n != NULL;
386 n = next) {
387 hash = tbl->hash(n->primary_key, n->dev,
388 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389
David S. Millercd089332011-07-11 01:28:12 -0700390 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700391 next = rcu_dereference_protected(n->next,
392 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393
Eric Dumazet767e97e2010-10-06 17:49:21 -0700394 rcu_assign_pointer(n->next,
395 rcu_dereference_protected(
396 new_nht->hash_buckets[hash],
397 lockdep_is_held(&tbl->lock)));
398 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000402 rcu_assign_pointer(tbl->nht, new_nht);
403 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
404 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700405}
406
407struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
408 struct net_device *dev)
409{
410 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900411
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 NEIGH_CACHE_STAT_INC(tbl, lookups);
413
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000414 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600415 n = __neigh_lookup_noref(tbl, pkey, dev);
416 if (n) {
417 if (!atomic_inc_not_zero(&n->refcnt))
418 n = NULL;
419 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700421
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000422 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423 return n;
424}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900425EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426
Eric W. Biederman426b5302008-01-24 00:13:18 -0800427struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
428 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429{
430 struct neighbour *n;
431 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800432 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000433 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434
435 NEIGH_CACHE_STAT_INC(tbl, lookups);
436
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000437 rcu_read_lock_bh();
438 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700439 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700440
441 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
442 n != NULL;
443 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800444 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900445 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700446 if (!atomic_inc_not_zero(&n->refcnt))
447 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 NEIGH_CACHE_STAT_INC(tbl, hits);
449 break;
450 }
451 }
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_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457
David S. Millera263b302012-07-02 02:02:15 -0700458struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
459 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
461 u32 hash_val;
462 int key_len = tbl->key_len;
463 int error;
David Miller596b9b62011-07-25 00:01:25 +0000464 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000465 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466
467 if (!n) {
468 rc = ERR_PTR(-ENOBUFS);
469 goto out;
470 }
471
472 memcpy(n->primary_key, pkey, key_len);
473 n->dev = dev;
474 dev_hold(dev);
475
476 /* Protocol specific setup. */
477 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
478 rc = ERR_PTR(error);
479 goto out_neigh_release;
480 }
481
David Millerda6a8fa2011-07-25 00:01:38 +0000482 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200483 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000484 if (error < 0) {
485 rc = ERR_PTR(error);
486 goto out_neigh_release;
487 }
488 }
489
David S. Miller447f2192011-12-19 15:04:41 -0500490 /* Device specific setup. */
491 if (n->parms->neigh_setup &&
492 (error = n->parms->neigh_setup(n)) < 0) {
493 rc = ERR_PTR(error);
494 goto out_neigh_release;
495 }
496
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100497 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498
499 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000500 nht = rcu_dereference_protected(tbl->nht,
501 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
David S. Millercd089332011-07-11 01:28:12 -0700503 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
504 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Jim Westfall014510b2018-01-14 04:18:50 -0800506 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
508 if (n->parms->dead) {
509 rc = ERR_PTR(-EINVAL);
510 goto out_tbl_unlock;
511 }
512
Eric Dumazet767e97e2010-10-06 17:49:21 -0700513 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
514 lockdep_is_held(&tbl->lock));
515 n1 != NULL;
516 n1 = rcu_dereference_protected(n1->next,
517 lockdep_is_held(&tbl->lock))) {
Jim Westfall014510b2018-01-14 04:18:50 -0800518 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700519 if (want_ref)
520 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 rc = n1;
522 goto out_tbl_unlock;
523 }
524 }
525
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700527 if (want_ref)
528 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700529 rcu_assign_pointer(n->next,
530 rcu_dereference_protected(nht->hash_buckets[hash_val],
531 lockdep_is_held(&tbl->lock)));
532 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000534 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 rc = n;
536out:
537 return rc;
538out_tbl_unlock:
539 write_unlock_bh(&tbl->lock);
540out_neigh_release:
541 neigh_release(n);
542 goto out;
543}
David S. Millera263b302012-07-02 02:02:15 -0700544EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900546static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700547{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700548 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700549 hash_val ^= (hash_val >> 16);
550 hash_val ^= hash_val >> 8;
551 hash_val ^= hash_val >> 4;
552 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900553 return hash_val;
554}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700555
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900556static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
557 struct net *net,
558 const void *pkey,
559 int key_len,
560 struct net_device *dev)
561{
562 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700563 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900564 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700565 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900566 return n;
567 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700568 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900569 return NULL;
570}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700571
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900572struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
573 struct net *net, const void *pkey, struct net_device *dev)
574{
575 int key_len = tbl->key_len;
576 u32 hash_val = pneigh_hash(pkey, key_len);
577
578 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
579 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700580}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900581EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700582
Eric W. Biederman426b5302008-01-24 00:13:18 -0800583struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
584 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 struct net_device *dev, int creat)
586{
587 struct pneigh_entry *n;
588 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900589 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590
591 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900592 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
593 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900595
596 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 goto out;
598
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700599 ASSERT_RTNL();
600
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
602 if (!n)
603 goto out;
604
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500605 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606 memcpy(n->key, pkey, key_len);
607 n->dev = dev;
608 if (dev)
609 dev_hold(dev);
610
611 if (tbl->pconstructor && tbl->pconstructor(n)) {
612 if (dev)
613 dev_put(dev);
614 kfree(n);
615 n = NULL;
616 goto out;
617 }
618
619 write_lock_bh(&tbl->lock);
620 n->next = tbl->phash_buckets[hash_val];
621 tbl->phash_buckets[hash_val] = n;
622 write_unlock_bh(&tbl->lock);
623out:
624 return n;
625}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900626EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
628
Eric W. Biederman426b5302008-01-24 00:13:18 -0800629int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 struct net_device *dev)
631{
632 struct pneigh_entry *n, **np;
633 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900634 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635
636 write_lock_bh(&tbl->lock);
637 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
638 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800639 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900640 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 *np = n->next;
642 write_unlock_bh(&tbl->lock);
643 if (tbl->pdestructor)
644 tbl->pdestructor(n);
645 if (n->dev)
646 dev_put(n->dev);
647 kfree(n);
648 return 0;
649 }
650 }
651 write_unlock_bh(&tbl->lock);
652 return -ENOENT;
653}
654
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200655static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
656 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657{
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200658 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 u32 h;
660
661 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
662 np = &tbl->phash_buckets[h];
663 while ((n = *np) != NULL) {
664 if (!dev || n->dev == dev) {
665 *np = n->next;
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200666 n->next = freelist;
667 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668 continue;
669 }
670 np = &n->next;
671 }
672 }
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200673 write_unlock_bh(&tbl->lock);
674 while ((n = freelist)) {
675 freelist = n->next;
676 n->next = NULL;
677 if (tbl->pdestructor)
678 tbl->pdestructor(n);
679 if (n->dev)
680 dev_put(n->dev);
681 kfree(n);
682 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 return -ENOENT;
684}
685
Denis V. Lunev06f05112008-01-24 00:30:58 -0800686static void neigh_parms_destroy(struct neigh_parms *parms);
687
688static inline void neigh_parms_put(struct neigh_parms *parms)
689{
690 if (atomic_dec_and_test(&parms->refcnt))
691 neigh_parms_destroy(parms);
692}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693
694/*
695 * neighbour must already be out of the table;
696 *
697 */
698void neigh_destroy(struct neighbour *neigh)
699{
David Millerda6a8fa2011-07-25 00:01:38 +0000700 struct net_device *dev = neigh->dev;
701
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
703
704 if (!neigh->dead) {
Tejaswi Tanikellad40dd0f2017-07-25 13:30:09 +0530705 pr_warn("Destroying alive neighbour %pK\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 dump_stack();
707 return;
708 }
709
710 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000711 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700713 write_lock_bh(&neigh->lock);
714 __skb_queue_purge(&neigh->arp_queue);
715 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000716 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
David S. Miller447f2192011-12-19 15:04:41 -0500718 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200719 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500720
David Millerda6a8fa2011-07-25 00:01:38 +0000721 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 neigh_parms_put(neigh->parms);
723
Joe Perchesd5d427c2013-04-15 15:17:19 +0000724 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000727 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900729EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730
731/* Neighbour state is suspicious;
732 disable fast path.
733
734 Called with write_locked neigh.
735 */
736static void neigh_suspect(struct neighbour *neigh)
737{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000738 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
740 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741}
742
743/* Neighbour state is OK;
744 enable fast path.
745
746 Called with write_locked neigh.
747 */
748static void neigh_connect(struct neighbour *neigh)
749{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000750 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753}
754
Eric Dumazete4c4e442009-07-30 03:15:07 +0000755static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000757 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700758 struct neighbour *n;
759 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000760 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000761 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
764
Eric Dumazete4c4e442009-07-30 03:15:07 +0000765 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000766 nht = rcu_dereference_protected(tbl->nht,
767 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 /*
770 * periodically recompute ReachableTime from random function
771 */
772
Eric Dumazete4c4e442009-07-30 03:15:07 +0000773 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100776 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100778 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779 }
780
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800781 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
782 goto out;
783
David S. Millercd089332011-07-11 01:28:12 -0700784 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000785 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Eric Dumazet767e97e2010-10-06 17:49:21 -0700787 while ((n = rcu_dereference_protected(*np,
788 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
Eric Dumazete4c4e442009-07-30 03:15:07 +0000791 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792
Eric Dumazete4c4e442009-07-30 03:15:07 +0000793 state = n->nud_state;
794 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
795 write_unlock(&n->lock);
796 goto next_elt;
797 }
798
799 if (time_before(n->used, n->confirmed))
800 n->used = n->confirmed;
801
802 if (atomic_read(&n->refcnt) == 1 &&
803 (state == NUD_FAILED ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100804 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000805 *np = n->next;
806 n->dead = 1;
807 write_unlock(&n->lock);
808 neigh_cleanup_and_release(n);
809 continue;
810 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000814 np = &n->next;
815 }
816 /*
817 * It's fine to release lock here, even if hash table
818 * grows while we are preempted.
819 */
820 write_unlock_bh(&tbl->lock);
821 cond_resched();
822 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500823 nht = rcu_dereference_protected(tbl->nht,
824 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000826out:
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100827 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
828 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
829 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 */
viresh kumarf6180022014-01-22 12:23:33 +0530831 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100832 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000833 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834}
835
836static __inline__ int neigh_max_probes(struct neighbour *n)
837{
838 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900839 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
840 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
841 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842}
843
Timo Teras5ef12d92009-06-11 04:16:28 -0700844static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000845 __releases(neigh->lock)
846 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700847{
848 struct sk_buff *skb;
849
850 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000851 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700852 neigh->updated = jiffies;
853
854 /* It is very thin place. report_unreachable is very complicated
855 routine. Particularly, it can hit the same neighbour entry!
856
857 So that, we try to be accurate and avoid dead loop. --ANK
858 */
859 while (neigh->nud_state == NUD_FAILED &&
860 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
861 write_unlock(&neigh->lock);
862 neigh->ops->error_report(neigh, skb);
863 write_lock(&neigh->lock);
864 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700865 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000866 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700867}
868
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000869static void neigh_probe(struct neighbour *neigh)
870 __releases(neigh->lock)
871{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200872 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000873 /* keep skb alive even if arp_queue overflows */
874 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800875 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000876 write_unlock(&neigh->lock);
Eric Dumazet4f991612017-03-23 12:39:21 -0700877 if (neigh->ops->solicit)
878 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000879 atomic_inc(&neigh->probes);
880 kfree_skb(skb);
881}
882
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883/* Called when a timer expires for a neighbour entry. */
884
885static void neigh_timer_handler(unsigned long arg)
886{
887 unsigned long now, next;
888 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000889 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 int notify = 0;
891
892 write_lock(&neigh->lock);
893
894 state = neigh->nud_state;
895 now = jiffies;
896 next = now + HZ;
897
Mohammed Javide454b412018-08-09 03:19:47 -0700898 if (!(state & NUD_IN_TIMER))
899 goto out;
900
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900902 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000904 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 next = neigh->confirmed + neigh->parms->reachable_time;
906 } else if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100907 neigh->used +
908 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000909 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800911 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 neigh_suspect(neigh);
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100913 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000915 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800917 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700919 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 }
921 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900922 if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100923 neigh->confirmed +
924 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000925 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800927 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700929 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 next = neigh->confirmed + neigh->parms->reachable_time;
931 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000932 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800934 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900936 notify = 1;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100937 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 }
939 } else {
940 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100941 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 }
943
944 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
945 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 neigh->nud_state = NUD_FAILED;
947 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700948 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800949 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
951
952 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 if (time_before(next, jiffies + HZ/2))
954 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000955 if (!mod_timer(&neigh->timer, next))
956 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 }
Sridhar Anchab7092162016-04-14 21:20:43 +0530958
959 if (neigh_probe_enable) {
960 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE | NUD_STALE))
961 neigh_probe(neigh);
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530962 else
963 write_unlock(&neigh->lock);
David S. Miller9ff56602008-02-17 18:39:54 -0800964 } else {
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530965 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
966 neigh_probe(neigh);
967 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800968out:
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530969 write_unlock(&neigh->lock);
970 }
David S. Miller9ff56602008-02-17 18:39:54 -0800971 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
Thomas Grafd961db32007-08-08 23:12:56 -0700973 if (notify)
974 neigh_update_notify(neigh);
975
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 neigh_release(neigh);
977}
978
979int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
980{
981 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000982 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983
984 write_lock_bh(&neigh->lock);
985
986 rc = 0;
987 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
988 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +0300989 if (neigh->dead)
990 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100993 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
994 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000995 unsigned long next, now = jiffies;
996
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100997 atomic_set(&neigh->probes,
998 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Lorenzo Bianconi4ebefd32019-07-14 23:36:11 +0200999 neigh_del_timer(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001001 neigh->updated = now;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001002 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1003 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001004 neigh_add_timer(neigh, next);
1005 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 } else {
1007 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001008 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 write_unlock_bh(&neigh->lock);
1010
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001011 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 return 1;
1013 }
1014 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001015 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Lorenzo Bianconi4ebefd32019-07-14 23:36:11 +02001016 neigh_del_timer(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001018 neigh->updated = jiffies;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001019 neigh_add_timer(neigh, jiffies +
1020 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 }
1022
1023 if (neigh->nud_state == NUD_INCOMPLETE) {
1024 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001025 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001026 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001028
David S. Millerf72051b2008-09-23 01:11:18 -07001029 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001030 if (!buff)
1031 break;
1032 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001034 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001036 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001038 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 }
1040 rc = 1;
1041 }
1042out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001043 if (immediate_probe)
1044 neigh_probe(neigh);
1045 else
1046 write_unlock(&neigh->lock);
1047 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001049
1050out_dead:
1051 if (neigh->nud_state & NUD_STALE)
1052 goto out_unlock_bh;
1053 write_unlock_bh(&neigh->lock);
1054 kfree_skb(skb);
1055 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001057EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058
David S. Millerf6b72b62011-07-14 07:53:20 -07001059static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060{
1061 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001062 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001063 = NULL;
1064
1065 if (neigh->dev->header_ops)
1066 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
1068 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001069 hh = &neigh->hh;
Eric Dumazet36d6d822019-11-07 18:29:11 -08001070 if (READ_ONCE(hh->hh_len)) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001071 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001073 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 }
1075 }
1076}
1077
1078
1079
1080/* Generic update routine.
1081 -- lladdr is new lladdr or NULL, if it is not supplied.
1082 -- new is new state.
1083 -- flags
1084 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1085 if it is different.
1086 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001087 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1090
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001091 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 NTF_ROUTER flag.
1093 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1094 a router.
1095
1096 Caller MUST hold reference count on the entry.
1097 */
1098
1099int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1100 u32 flags)
1101{
1102 u8 old;
1103 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001105 struct net_device *dev;
1106 int update_isrouter = 0;
1107
1108 write_lock_bh(&neigh->lock);
1109
1110 dev = neigh->dev;
1111 old = neigh->nud_state;
1112 err = -EPERM;
1113
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001114 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 (old & (NUD_NOARP | NUD_PERMANENT)))
1116 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001117 if (neigh->dead)
1118 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
1120 if (!(new & NUD_VALID)) {
1121 neigh_del_timer(neigh);
1122 if (old & NUD_CONNECTED)
1123 neigh_suspect(neigh);
1124 neigh->nud_state = new;
1125 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001127 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1128 (new & NUD_FAILED)) {
1129 neigh_invalidate(neigh);
1130 notify = 1;
1131 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132 goto out;
1133 }
1134
1135 /* Compare new lladdr with cached one */
1136 if (!dev->addr_len) {
1137 /* First case: device needs no address. */
1138 lladdr = neigh->ha;
1139 } else if (lladdr) {
1140 /* The second case: if something is already cached
1141 and a new address is proposed:
1142 - compare new & old
1143 - if they are different, check override flag
1144 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001145 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 !memcmp(lladdr, neigh->ha, dev->addr_len))
1147 lladdr = neigh->ha;
1148 } else {
1149 /* No address is supplied; if we know something,
1150 use it, otherwise discard the request.
1151 */
1152 err = -EINVAL;
1153 if (!(old & NUD_VALID))
1154 goto out;
1155 lladdr = neigh->ha;
1156 }
1157
Vasily Khoruzhicke68a49c2018-09-13 11:12:03 -07001158 /* Update confirmed timestamp for neighbour entry after we
1159 * received ARP packet even if it doesn't change IP to MAC binding.
1160 */
1161 if (new & NUD_CONNECTED)
1162 neigh->confirmed = jiffies;
1163
Linus Torvalds1da177e2005-04-16 15:20:36 -07001164 /* If entry was valid and address is not changed,
1165 do not change entry state, if new one is STALE.
1166 */
1167 err = 0;
1168 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1169 if (old & NUD_VALID) {
1170 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1171 update_isrouter = 0;
1172 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1173 (old & NUD_CONNECTED)) {
1174 lladdr = neigh->ha;
1175 new = NUD_STALE;
1176 } else
1177 goto out;
1178 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001179 if (lladdr == neigh->ha && new == NUD_STALE &&
1180 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 new = old;
1182 }
1183 }
1184
Vasily Khoruzhicke68a49c2018-09-13 11:12:03 -07001185 /* Update timestamp only once we know we will make a change to the
Ihar Hrachyshka2c260522017-05-16 08:44:24 -07001186 * neighbour entry. Otherwise we risk to move the locktime window with
1187 * noop updates and ignore relevant ARP updates.
1188 */
Vasily Khoruzhicke68a49c2018-09-13 11:12:03 -07001189 if (new != old || lladdr != neigh->ha)
Ihar Hrachyshka2c260522017-05-16 08:44:24 -07001190 neigh->updated = jiffies;
Ihar Hrachyshka2c260522017-05-16 08:44:24 -07001191
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 if (new != old) {
1193 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001194 if (new & NUD_PROBE)
1195 atomic_set(&neigh->probes, 0);
Mohammed Javide454b412018-08-09 03:19:47 -07001196 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001197 neigh_add_timer(neigh, (jiffies +
1198 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001199 neigh->parms->reachable_time :
1200 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001202 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 }
1204
1205 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001206 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001208 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 neigh_update_hhs(neigh);
1210 if (!(new & NUD_CONNECTED))
1211 neigh->confirmed = jiffies -
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001212 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001214 }
1215 if (new == old)
1216 goto out;
1217 if (new & NUD_CONNECTED)
1218 neigh_connect(neigh);
1219 else
1220 neigh_suspect(neigh);
1221 if (!(old & NUD_VALID)) {
1222 struct sk_buff *skb;
1223
1224 /* Again: avoid dead loop if something went wrong */
1225
1226 while (neigh->nud_state & NUD_VALID &&
1227 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001228 struct dst_entry *dst = skb_dst(skb);
1229 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001231
1232 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001233
1234 /* Why not just use 'neigh' as-is? The problem is that
1235 * things such as shaper, eql, and sch_teql can end up
1236 * using alternative, different, neigh objects to output
1237 * the packet in the output path. So what we need to do
1238 * here is re-lookup the top-level neigh in the path so
1239 * we can reinject the packet there.
1240 */
1241 n2 = NULL;
1242 if (dst) {
1243 n2 = dst_neigh_lookup_skb(dst, skb);
1244 if (n2)
1245 n1 = n2;
1246 }
David S. Miller8f40b162011-07-17 13:34:11 -07001247 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001248 if (n2)
1249 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001250 rcu_read_unlock();
1251
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 write_lock_bh(&neigh->lock);
1253 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001254 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001255 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 }
1257out:
1258 if (update_isrouter) {
1259 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1260 (neigh->flags | NTF_ROUTER) :
1261 (neigh->flags & ~NTF_ROUTER);
1262 }
1263 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001264
1265 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001266 neigh_update_notify(neigh);
1267
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 return err;
1269}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001270EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271
Jiri Benc7e980562013-12-11 13:48:20 +01001272/* Update the neigh to listen temporarily for probe responses, even if it is
1273 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1274 */
1275void __neigh_set_probe_once(struct neighbour *neigh)
1276{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001277 if (neigh->dead)
1278 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001279 neigh->updated = jiffies;
1280 if (!(neigh->nud_state & NUD_FAILED))
1281 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001282 neigh->nud_state = NUD_INCOMPLETE;
1283 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001284 neigh_add_timer(neigh,
1285 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1286}
1287EXPORT_SYMBOL(__neigh_set_probe_once);
1288
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1290 u8 *lladdr, void *saddr,
1291 struct net_device *dev)
1292{
1293 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1294 lladdr || !dev->addr_len);
Ravinder Konkaa71b6682015-04-09 11:42:00 +05301295 if (neigh) {
1296 if (neigh_probe_enable) {
Mohammed Javid309792a2019-01-11 16:32:29 +05301297 if (neigh->nud_state != NUD_REACHABLE &&
1298 neigh->nud_state != NUD_PERMANENT) {
Ravinder Konkaa71b6682015-04-09 11:42:00 +05301299 neigh_update(neigh, lladdr, NUD_STALE,
Mohammed Javid309792a2019-01-11 16:32:29 +05301300 NEIGH_UPDATE_F_OVERRIDE);
Ravinder Konkaa71b6682015-04-09 11:42:00 +05301301 write_lock(&neigh->lock);
1302 neigh_probe(neigh);
1303 neigh_update_notify(neigh);
1304 }
1305 } else {
1306 neigh_update(neigh, lladdr, NUD_STALE,
1307 NEIGH_UPDATE_F_OVERRIDE);
1308 }
1309 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310 return neigh;
1311}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001312EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313
Eric Dumazet34d101d2010-10-11 09:16:57 -07001314/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001315static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001317 struct net_device *dev = n->dev;
1318 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001319 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001320
1321 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001322
David S. Millerf6b72b62011-07-14 07:53:20 -07001323 /* Only one thread can come in here and initialize the
1324 * hh_cache entry.
1325 */
David S. Millerb23b5452011-07-16 17:45:02 -07001326 if (!hh->hh_len)
1327 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001328
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001329 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330}
1331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332/* Slow and careful. */
1333
David S. Miller8f40b162011-07-17 13:34:11 -07001334int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 int rc = 0;
1337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (!neigh_event_send(neigh, skb)) {
1339 int err;
1340 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001341 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001342
Eric Dumazet36d6d822019-11-07 18:29:11 -08001343 if (dev->header_ops->cache && !READ_ONCE(neigh->hh.hh_len))
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001344 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001345
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001346 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001347 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001348 seq = read_seqbegin(&neigh->ha_lock);
1349 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1350 neigh->ha, NULL, skb->len);
1351 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001352
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001354 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355 else
1356 goto out_kfree_skb;
1357 }
1358out:
1359 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360out_kfree_skb:
1361 rc = -EINVAL;
1362 kfree_skb(skb);
1363 goto out;
1364}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001365EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367/* As fast as possible without hh cache */
1368
David S. Miller8f40b162011-07-17 13:34:11 -07001369int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001372 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001373 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001375 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001376 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001377 seq = read_seqbegin(&neigh->ha_lock);
1378 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1379 neigh->ha, NULL, skb->len);
1380 } while (read_seqretry(&neigh->ha_lock, seq));
1381
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001383 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001384 else {
1385 err = -EINVAL;
1386 kfree_skb(skb);
1387 }
1388 return err;
1389}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001390EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391
David S. Miller8f40b162011-07-17 13:34:11 -07001392int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1393{
1394 return dev_queue_xmit(skb);
1395}
1396EXPORT_SYMBOL(neigh_direct_output);
1397
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398static void neigh_proxy_process(unsigned long arg)
1399{
1400 struct neigh_table *tbl = (struct neigh_table *)arg;
1401 long sched_next = 0;
1402 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001403 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404
1405 spin_lock(&tbl->proxy_queue.lock);
1406
David S. Millerf72051b2008-09-23 01:11:18 -07001407 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1408 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001411 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001412
David S. Millerf72051b2008-09-23 01:11:18 -07001413 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001414 if (tbl->proxy_redo && netif_running(dev)) {
1415 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001416 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001417 rcu_read_unlock();
1418 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001419 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001420 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001421
1422 dev_put(dev);
1423 } else if (!sched_next || tdif < sched_next)
1424 sched_next = tdif;
1425 }
1426 del_timer(&tbl->proxy_timer);
1427 if (sched_next)
1428 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1429 spin_unlock(&tbl->proxy_queue.lock);
1430}
1431
1432void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1433 struct sk_buff *skb)
1434{
1435 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001436
1437 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001438 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001440 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 kfree_skb(skb);
1442 return;
1443 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001444
1445 NEIGH_CB(skb)->sched_next = sched_next;
1446 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
1448 spin_lock(&tbl->proxy_queue.lock);
1449 if (del_timer(&tbl->proxy_timer)) {
1450 if (time_before(tbl->proxy_timer.expires, sched_next))
1451 sched_next = tbl->proxy_timer.expires;
1452 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001453 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 dev_hold(skb->dev);
1455 __skb_queue_tail(&tbl->proxy_queue, skb);
1456 mod_timer(&tbl->proxy_timer, sched_next);
1457 spin_unlock(&tbl->proxy_queue.lock);
1458}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001459EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001461static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001462 struct net *net, int ifindex)
1463{
1464 struct neigh_parms *p;
1465
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001466 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001467 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001468 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001469 return p;
1470 }
1471
1472 return NULL;
1473}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1476 struct neigh_table *tbl)
1477{
Gao fengcf89d6b2013-06-20 10:01:32 +08001478 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001479 struct net *net = dev_net(dev);
1480 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
Gao fengcf89d6b2013-06-20 10:01:32 +08001482 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 p->tbl = tbl;
1485 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001487 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001488 dev_hold(dev);
1489 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001490 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001492
1493 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001494 dev_put(dev);
1495 kfree(p);
1496 return NULL;
1497 }
1498
Linus Torvalds1da177e2005-04-16 15:20:36 -07001499 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001500 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001502
1503 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 }
1505 return p;
1506}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001507EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
1509static void neigh_rcu_free_parms(struct rcu_head *head)
1510{
1511 struct neigh_parms *parms =
1512 container_of(head, struct neigh_parms, rcu_head);
1513
1514 neigh_parms_put(parms);
1515}
1516
1517void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1518{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 if (!parms || parms == &tbl->parms)
1520 return;
1521 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001522 list_del(&parms->list);
1523 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001525 if (parms->dev)
1526 dev_put(parms->dev);
1527 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001529EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530
Denis V. Lunev06f05112008-01-24 00:30:58 -08001531static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532{
1533 kfree(parms);
1534}
1535
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001536static struct lock_class_key neigh_table_proxy_queue_class;
1537
WANG Congd7480fd2014-11-10 15:59:36 -08001538static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1539
1540void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541{
1542 unsigned long now = jiffies;
1543 unsigned long phsize;
1544
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001545 INIT_LIST_HEAD(&tbl->parms_list);
1546 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001547 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 tbl->parms.reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001550 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 tbl->stats = alloc_percpu(struct neigh_statistics);
1553 if (!tbl->stats)
1554 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001555
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001557 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1558 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560#endif
1561
David S. Millercd089332011-07-11 01:28:12 -07001562 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
1564 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001565 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001567 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 panic("cannot allocate neighbour cache hashes");
1569
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001570 if (!tbl->entry_size)
1571 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1572 tbl->key_len, NEIGH_PRIV_ALIGN);
1573 else
1574 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1575
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001577 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301578 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1579 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001580 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001581 skb_queue_head_init_class(&tbl->proxy_queue,
1582 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
1584 tbl->last_flush = now;
1585 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001586
WANG Congd7480fd2014-11-10 15:59:36 -08001587 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001589EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
WANG Congd7480fd2014-11-10 15:59:36 -08001591int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592{
WANG Congd7480fd2014-11-10 15:59:36 -08001593 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001595 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 del_timer_sync(&tbl->proxy_timer);
1597 pneigh_queue_purge(&tbl->proxy_queue);
1598 neigh_ifdown(tbl, NULL);
1599 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001600 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001602 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1603 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001604 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605
1606 kfree(tbl->phash_buckets);
1607 tbl->phash_buckets = NULL;
1608
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001609 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1610
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001611 free_percpu(tbl->stats);
1612 tbl->stats = NULL;
1613
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614 return 0;
1615}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001616EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617
WANG Congd7480fd2014-11-10 15:59:36 -08001618static struct neigh_table *neigh_find_table(int family)
1619{
1620 struct neigh_table *tbl = NULL;
1621
1622 switch (family) {
1623 case AF_INET:
1624 tbl = neigh_tables[NEIGH_ARP_TABLE];
1625 break;
1626 case AF_INET6:
1627 tbl = neigh_tables[NEIGH_ND_TABLE];
1628 break;
1629 case AF_DECnet:
1630 tbl = neigh_tables[NEIGH_DN_TABLE];
1631 break;
1632 }
1633
1634 return tbl;
1635}
1636
Thomas Graf661d2962013-03-21 07:45:29 +00001637static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001639 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001640 struct ndmsg *ndm;
1641 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001643 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001645 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Eric Dumazet110b2492010-10-04 04:27:36 +00001647 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001648 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 goto out;
1650
Thomas Grafa14a49d2006-08-07 17:53:08 -07001651 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1652 if (dst_attr == NULL)
1653 goto out;
1654
1655 ndm = nlmsg_data(nlh);
1656 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001657 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001658 if (dev == NULL) {
1659 err = -ENODEV;
1660 goto out;
1661 }
1662 }
1663
WANG Congd7480fd2014-11-10 15:59:36 -08001664 tbl = neigh_find_table(ndm->ndm_family);
1665 if (tbl == NULL)
1666 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
WANG Congd7480fd2014-11-10 15:59:36 -08001668 if (nla_len(dst_attr) < tbl->key_len)
1669 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
WANG Congd7480fd2014-11-10 15:59:36 -08001671 if (ndm->ndm_flags & NTF_PROXY) {
1672 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001673 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 }
WANG Congd7480fd2014-11-10 15:59:36 -08001675
1676 if (dev == NULL)
1677 goto out;
1678
1679 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1680 if (neigh == NULL) {
1681 err = -ENOENT;
1682 goto out;
1683 }
1684
1685 err = neigh_update(neigh, NULL, NUD_FAILED,
1686 NEIGH_UPDATE_F_OVERRIDE |
1687 NEIGH_UPDATE_F_ADMIN);
1688 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001689
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690out:
1691 return err;
1692}
1693
Thomas Graf661d2962013-03-21 07:45:29 +00001694static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695{
WANG Congd7480fd2014-11-10 15:59:36 -08001696 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001697 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001698 struct ndmsg *ndm;
1699 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700 struct neigh_table *tbl;
1701 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001702 struct neighbour *neigh;
1703 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001704 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
Eric Dumazet110b2492010-10-04 04:27:36 +00001706 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001707 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1708 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709 goto out;
1710
Thomas Graf5208deb2006-08-07 17:55:40 -07001711 err = -EINVAL;
1712 if (tb[NDA_DST] == NULL)
1713 goto out;
1714
1715 ndm = nlmsg_data(nlh);
1716 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001717 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001718 if (dev == NULL) {
1719 err = -ENODEV;
1720 goto out;
1721 }
1722
1723 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001724 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001725 }
1726
WANG Congd7480fd2014-11-10 15:59:36 -08001727 tbl = neigh_find_table(ndm->ndm_family);
1728 if (tbl == NULL)
1729 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001730
WANG Congd7480fd2014-11-10 15:59:36 -08001731 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1732 goto out;
1733 dst = nla_data(tb[NDA_DST]);
1734 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735
WANG Congd7480fd2014-11-10 15:59:36 -08001736 if (ndm->ndm_flags & NTF_PROXY) {
1737 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
WANG Congd7480fd2014-11-10 15:59:36 -08001739 err = -ENOBUFS;
1740 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1741 if (pn) {
1742 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001743 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001744 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001745 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 }
1747
WANG Congd7480fd2014-11-10 15:59:36 -08001748 if (dev == NULL)
1749 goto out;
1750
1751 neigh = neigh_lookup(tbl, dst, dev);
1752 if (neigh == NULL) {
1753 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1754 err = -ENOENT;
1755 goto out;
1756 }
1757
1758 neigh = __neigh_lookup_errno(tbl, dst, dev);
1759 if (IS_ERR(neigh)) {
1760 err = PTR_ERR(neigh);
1761 goto out;
1762 }
1763 } else {
1764 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1765 err = -EEXIST;
1766 neigh_release(neigh);
1767 goto out;
1768 }
1769
1770 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1771 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1772 }
1773
1774 if (ndm->ndm_flags & NTF_USE) {
1775 neigh_event_send(neigh, NULL);
1776 err = 0;
1777 } else
1778 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1779 neigh_release(neigh);
1780
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781out:
1782 return err;
1783}
1784
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001785static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1786{
Thomas Grafca860fb2006-08-07 18:00:18 -07001787 struct nlattr *nest;
1788
1789 nest = nla_nest_start(skb, NDTA_PARMS);
1790 if (nest == NULL)
1791 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001792
David S. Miller9a6308d2012-04-01 20:06:28 -04001793 if ((parms->dev &&
1794 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1795 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001796 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1797 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001798 /* approximative value for deprecated QUEUE_LEN (in packets) */
1799 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001800 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1801 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1802 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1803 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1804 NEIGH_VAR(parms, UCAST_PROBES)) ||
1805 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1806 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001807 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1808 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001809 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1810 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001811 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001812 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001813 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001814 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001815 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001816 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001817 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001818 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001819 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001820 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001821 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001822 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001823 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001824 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001825 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001826 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001827
Thomas Grafca860fb2006-08-07 18:00:18 -07001828nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001829 nla_nest_cancel(skb, nest);
1830 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001831}
1832
Thomas Grafca860fb2006-08-07 18:00:18 -07001833static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1834 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001835{
1836 struct nlmsghdr *nlh;
1837 struct ndtmsg *ndtmsg;
1838
Thomas Grafca860fb2006-08-07 18:00:18 -07001839 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1840 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001841 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001842
Thomas Grafca860fb2006-08-07 18:00:18 -07001843 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844
1845 read_lock_bh(&tbl->lock);
1846 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001847 ndtmsg->ndtm_pad1 = 0;
1848 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001849
David S. Miller9a6308d2012-04-01 20:06:28 -04001850 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001851 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001852 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1853 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1854 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1855 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001856 {
1857 unsigned long now = jiffies;
Eric Dumazetce556412019-11-05 14:11:49 -08001858 long flush_delta = now - tbl->last_flush;
1859 long rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001860 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001861 struct ndt_config ndc = {
1862 .ndtc_key_len = tbl->key_len,
1863 .ndtc_entry_size = tbl->entry_size,
1864 .ndtc_entries = atomic_read(&tbl->entries),
1865 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1866 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001867 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1868 };
1869
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001870 rcu_read_lock_bh();
1871 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001872 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001873 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001874 rcu_read_unlock_bh();
1875
David S. Miller9a6308d2012-04-01 20:06:28 -04001876 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1877 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878 }
1879
1880 {
1881 int cpu;
1882 struct ndt_stats ndst;
1883
1884 memset(&ndst, 0, sizeof(ndst));
1885
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001886 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887 struct neigh_statistics *st;
1888
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001889 st = per_cpu_ptr(tbl->stats, cpu);
1890 ndst.ndts_allocs += st->allocs;
1891 ndst.ndts_destroys += st->destroys;
1892 ndst.ndts_hash_grows += st->hash_grows;
1893 ndst.ndts_res_failed += st->res_failed;
1894 ndst.ndts_lookups += st->lookups;
1895 ndst.ndts_hits += st->hits;
1896 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1897 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1898 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1899 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001900 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001901 }
1902
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001903 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1904 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001905 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001906 }
1907
1908 BUG_ON(tbl->parms.dev);
1909 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001910 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001911
1912 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001913 nlmsg_end(skb, nlh);
1914 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001915
Thomas Grafca860fb2006-08-07 18:00:18 -07001916nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001917 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001918 nlmsg_cancel(skb, nlh);
1919 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001920}
1921
Thomas Grafca860fb2006-08-07 18:00:18 -07001922static int neightbl_fill_param_info(struct sk_buff *skb,
1923 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001924 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001925 u32 pid, u32 seq, int type,
1926 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001927{
1928 struct ndtmsg *ndtmsg;
1929 struct nlmsghdr *nlh;
1930
Thomas Grafca860fb2006-08-07 18:00:18 -07001931 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1932 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001933 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001934
Thomas Grafca860fb2006-08-07 18:00:18 -07001935 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001936
1937 read_lock_bh(&tbl->lock);
1938 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001939 ndtmsg->ndtm_pad1 = 0;
1940 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001941
Thomas Grafca860fb2006-08-07 18:00:18 -07001942 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1943 neightbl_fill_parms(skb, parms) < 0)
1944 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001945
1946 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001947 nlmsg_end(skb, nlh);
1948 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001949errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001950 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001951 nlmsg_cancel(skb, nlh);
1952 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001953}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001954
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001955static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001956 [NDTA_NAME] = { .type = NLA_STRING },
1957 [NDTA_THRESH1] = { .type = NLA_U32 },
1958 [NDTA_THRESH2] = { .type = NLA_U32 },
1959 [NDTA_THRESH3] = { .type = NLA_U32 },
1960 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1961 [NDTA_PARMS] = { .type = NLA_NESTED },
1962};
1963
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001964static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001965 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1966 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1967 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1968 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1969 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1970 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001971 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001972 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1973 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1974 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1975 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1976 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1977 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1978 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1979};
1980
Thomas Graf661d2962013-03-21 07:45:29 +00001981static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001982{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001983 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001984 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001985 struct ndtmsg *ndtmsg;
1986 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001987 bool found = false;
1988 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001989
Thomas Graf6b3f8672006-08-07 17:58:53 -07001990 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1991 nl_neightbl_policy);
1992 if (err < 0)
1993 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001994
Thomas Graf6b3f8672006-08-07 17:58:53 -07001995 if (tb[NDTA_NAME] == NULL) {
1996 err = -EINVAL;
1997 goto errout;
1998 }
1999
2000 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002001
2002 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2003 tbl = neigh_tables[tidx];
2004 if (!tbl)
2005 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002006 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2007 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002008 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2009 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002011 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012 }
2013
WANG Congd7480fd2014-11-10 15:59:36 -08002014 if (!found)
2015 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002016
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002017 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002018 * We acquire tbl->lock to be nice to the periodic timers and
2019 * make sure they always see a consistent set of values.
2020 */
2021 write_lock_bh(&tbl->lock);
2022
Thomas Graf6b3f8672006-08-07 17:58:53 -07002023 if (tb[NDTA_PARMS]) {
2024 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002025 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002026 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002027
Thomas Graf6b3f8672006-08-07 17:58:53 -07002028 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2029 nl_ntbl_parm_policy);
2030 if (err < 0)
2031 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002032
Thomas Graf6b3f8672006-08-07 17:58:53 -07002033 if (tbp[NDTPA_IFINDEX])
2034 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002035
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002036 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002037 if (p == NULL) {
2038 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002039 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002040 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002041
Thomas Graf6b3f8672006-08-07 17:58:53 -07002042 for (i = 1; i <= NDTPA_MAX; i++) {
2043 if (tbp[i] == NULL)
2044 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002045
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 switch (i) {
2047 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002048 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2049 nla_get_u32(tbp[i]) *
2050 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002051 break;
2052 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002053 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2054 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002055 break;
2056 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002057 NEIGH_VAR_SET(p, PROXY_QLEN,
2058 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 break;
2060 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002061 NEIGH_VAR_SET(p, APP_PROBES,
2062 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 break;
2064 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002065 NEIGH_VAR_SET(p, UCAST_PROBES,
2066 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067 break;
2068 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002069 NEIGH_VAR_SET(p, MCAST_PROBES,
2070 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002071 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002072 case NDTPA_MCAST_REPROBES:
2073 NEIGH_VAR_SET(p, MCAST_REPROBES,
2074 nla_get_u32(tbp[i]));
2075 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002077 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2078 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002079 /* update reachable_time as well, otherwise, the change will
2080 * only be effective after the next time neigh_periodic_work
2081 * decides to recompute it (can be multiple minutes)
2082 */
2083 p->reachable_time =
2084 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002085 break;
2086 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002087 NEIGH_VAR_SET(p, GC_STALETIME,
2088 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002089 break;
2090 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002091 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2092 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002093 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002094 break;
2095 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002096 NEIGH_VAR_SET(p, RETRANS_TIME,
2097 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002098 break;
2099 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002100 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2101 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002102 break;
2103 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002104 NEIGH_VAR_SET(p, PROXY_DELAY,
2105 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002106 break;
2107 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002108 NEIGH_VAR_SET(p, LOCKTIME,
2109 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002110 break;
2111 }
2112 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002113 }
2114
Gao fengdc25c672013-06-20 10:01:34 +08002115 err = -ENOENT;
2116 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2117 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2118 !net_eq(net, &init_net))
2119 goto errout_tbl_lock;
2120
Thomas Graf6b3f8672006-08-07 17:58:53 -07002121 if (tb[NDTA_THRESH1])
2122 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2123
2124 if (tb[NDTA_THRESH2])
2125 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2126
2127 if (tb[NDTA_THRESH3])
2128 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2129
2130 if (tb[NDTA_GC_INTERVAL])
2131 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2132
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002133 err = 0;
2134
Thomas Graf6b3f8672006-08-07 17:58:53 -07002135errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002136 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002137errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002138 return err;
2139}
2140
Thomas Grafc8822a42007-03-22 11:50:06 -07002141static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002142{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002143 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002144 int family, tidx, nidx = 0;
2145 int tbl_skip = cb->args[0];
2146 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002147 struct neigh_table *tbl;
2148
Thomas Grafca860fb2006-08-07 18:00:18 -07002149 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002150
WANG Congd7480fd2014-11-10 15:59:36 -08002151 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002152 struct neigh_parms *p;
2153
WANG Congd7480fd2014-11-10 15:59:36 -08002154 tbl = neigh_tables[tidx];
2155 if (!tbl)
2156 continue;
2157
Thomas Grafca860fb2006-08-07 18:00:18 -07002158 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002159 continue;
2160
Eric W. Biederman15e47302012-09-07 20:12:54 +00002161 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002162 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002163 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002164 break;
2165
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002166 nidx = 0;
2167 p = list_next_entry(&tbl->parms, list);
2168 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002169 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002170 continue;
2171
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002172 if (nidx < neigh_skip)
2173 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002174
Thomas Grafca860fb2006-08-07 18:00:18 -07002175 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002176 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002177 cb->nlh->nlmsg_seq,
2178 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002179 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002181 next:
2182 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002183 }
2184
Thomas Grafca860fb2006-08-07 18:00:18 -07002185 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002186 }
2187out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002188 cb->args[0] = tidx;
2189 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002190
2191 return skb->len;
2192}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002193
Thomas Graf8b8aec52006-08-07 17:56:37 -07002194static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2195 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002196{
2197 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199 struct nlmsghdr *nlh;
2200 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
Thomas Graf8b8aec52006-08-07 17:56:37 -07002202 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2203 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002204 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002205
2206 ndm = nlmsg_data(nlh);
2207 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002208 ndm->ndm_pad1 = 0;
2209 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002210 ndm->ndm_flags = neigh->flags;
2211 ndm->ndm_type = neigh->type;
2212 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002213
David S. Miller9a6308d2012-04-01 20:06:28 -04002214 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2215 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002216
2217 read_lock_bh(&neigh->lock);
2218 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002219 if (neigh->nud_state & NUD_VALID) {
2220 char haddr[MAX_ADDR_LEN];
2221
2222 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2223 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2224 read_unlock_bh(&neigh->lock);
2225 goto nla_put_failure;
2226 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002227 }
2228
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002229 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2230 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2231 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002232 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2233 read_unlock_bh(&neigh->lock);
2234
David S. Miller9a6308d2012-04-01 20:06:28 -04002235 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2236 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2237 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002238
Johannes Berg053c0952015-01-16 22:09:00 +01002239 nlmsg_end(skb, nlh);
2240 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002241
2242nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002243 nlmsg_cancel(skb, nlh);
2244 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002245}
2246
Tony Zelenoff84920c12012-01-26 22:28:58 +00002247static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2248 u32 pid, u32 seq, int type, unsigned int flags,
2249 struct neigh_table *tbl)
2250{
2251 struct nlmsghdr *nlh;
2252 struct ndmsg *ndm;
2253
2254 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2255 if (nlh == NULL)
2256 return -EMSGSIZE;
2257
2258 ndm = nlmsg_data(nlh);
2259 ndm->ndm_family = tbl->family;
2260 ndm->ndm_pad1 = 0;
2261 ndm->ndm_pad2 = 0;
2262 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002263 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002264 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002265 ndm->ndm_state = NUD_NONE;
2266
David S. Miller9a6308d2012-04-01 20:06:28 -04002267 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2268 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002269
Johannes Berg053c0952015-01-16 22:09:00 +01002270 nlmsg_end(skb, nlh);
2271 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002272
2273nla_put_failure:
2274 nlmsg_cancel(skb, nlh);
2275 return -EMSGSIZE;
2276}
2277
Thomas Grafd961db32007-08-08 23:12:56 -07002278static void neigh_update_notify(struct neighbour *neigh)
2279{
2280 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2281 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2282}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283
David Ahern21fdd092015-09-29 09:32:03 -07002284static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2285{
2286 struct net_device *master;
2287
2288 if (!master_idx)
2289 return false;
2290
2291 master = netdev_master_upper_dev_get(dev);
2292 if (!master || master->ifindex != master_idx)
2293 return true;
2294
2295 return false;
2296}
2297
David Ahern16660f02015-10-03 11:43:46 -07002298static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2299{
2300 if (filter_idx && dev->ifindex != filter_idx)
2301 return true;
2302
2303 return false;
2304}
2305
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2307 struct netlink_callback *cb)
2308{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002309 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002310 const struct nlmsghdr *nlh = cb->nlh;
2311 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312 struct neighbour *n;
2313 int rc, h, s_h = cb->args[1];
2314 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002315 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002316 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002317 unsigned int flags = NLM_F_MULTI;
2318 int err;
2319
2320 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL);
2321 if (!err) {
Eric Dumazet0e770d22018-04-11 14:46:00 -07002322 if (tb[NDA_IFINDEX]) {
2323 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
2324 return -EINVAL;
David Ahern16660f02015-10-03 11:43:46 -07002325 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
Eric Dumazet0e770d22018-04-11 14:46:00 -07002326 }
2327 if (tb[NDA_MASTER]) {
2328 if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
2329 return -EINVAL;
David Ahern21fdd092015-09-29 09:32:03 -07002330 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
Eric Dumazet0e770d22018-04-11 14:46:00 -07002331 }
David Ahern16660f02015-10-03 11:43:46 -07002332 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002333 flags |= NLM_F_DUMP_FILTERED;
2334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002336 rcu_read_lock_bh();
2337 nht = rcu_dereference_bh(tbl->nht);
2338
Eric Dumazet4bd66832012-06-07 04:58:35 +00002339 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 if (h > s_h)
2341 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002342 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2343 n != NULL;
2344 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002345 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002346 continue;
David Ahern16660f02015-10-03 11:43:46 -07002347 if (neigh_ifindex_filtered(n->dev, filter_idx))
2348 continue;
David Ahern21fdd092015-09-29 09:32:03 -07002349 if (neigh_master_filtered(n->dev, filter_master_idx))
2350 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002351 if (idx < s_idx)
2352 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002353 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002355 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002356 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 rc = -1;
2358 goto out;
2359 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002360next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002361 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002363 }
2364 rc = skb->len;
2365out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002366 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002367 cb->args[1] = h;
2368 cb->args[2] = idx;
2369 return rc;
2370}
2371
Tony Zelenoff84920c12012-01-26 22:28:58 +00002372static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2373 struct netlink_callback *cb)
2374{
2375 struct pneigh_entry *n;
2376 struct net *net = sock_net(skb->sk);
2377 int rc, h, s_h = cb->args[3];
2378 int idx, s_idx = idx = cb->args[4];
2379
2380 read_lock_bh(&tbl->lock);
2381
Eric Dumazet4bd66832012-06-07 04:58:35 +00002382 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002383 if (h > s_h)
2384 s_idx = 0;
2385 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002386 if (pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002387 continue;
2388 if (idx < s_idx)
2389 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002390 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002391 cb->nlh->nlmsg_seq,
2392 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002393 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002394 read_unlock_bh(&tbl->lock);
2395 rc = -1;
2396 goto out;
2397 }
2398 next:
2399 idx++;
2400 }
2401 }
2402
2403 read_unlock_bh(&tbl->lock);
2404 rc = skb->len;
2405out:
2406 cb->args[3] = h;
2407 cb->args[4] = idx;
2408 return rc;
2409
2410}
2411
Thomas Grafc8822a42007-03-22 11:50:06 -07002412static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413{
2414 struct neigh_table *tbl;
2415 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002416 int proxy = 0;
Eric Dumazet4bd66832012-06-07 04:58:35 +00002417 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002418
Thomas Graf8b8aec52006-08-07 17:56:37 -07002419 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002420
2421 /* check for full ndmsg structure presence, family member is
2422 * the same for both structures
2423 */
2424 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2425 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2426 proxy = 1;
2427
Linus Torvalds1da177e2005-04-16 15:20:36 -07002428 s_t = cb->args[0];
2429
WANG Congd7480fd2014-11-10 15:59:36 -08002430 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2431 tbl = neigh_tables[t];
2432
2433 if (!tbl)
2434 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 if (t < s_t || (family && tbl->family != family))
2436 continue;
2437 if (t > s_t)
2438 memset(&cb->args[1], 0, sizeof(cb->args) -
2439 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002440 if (proxy)
2441 err = pneigh_dump_table(tbl, skb, cb);
2442 else
2443 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd66832012-06-07 04:58:35 +00002444 if (err < 0)
2445 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002446 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447
2448 cb->args[0] = t;
2449 return skb->len;
2450}
2451
2452void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2453{
2454 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002455 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002457 rcu_read_lock_bh();
2458 nht = rcu_dereference_bh(tbl->nht);
2459
Eric Dumazet767e97e2010-10-06 17:49:21 -07002460 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002461 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 struct neighbour *n;
2463
Eric Dumazet767e97e2010-10-06 17:49:21 -07002464 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2465 n != NULL;
2466 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467 cb(n, cookie);
2468 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002469 read_unlock(&tbl->lock);
2470 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471}
2472EXPORT_SYMBOL(neigh_for_each);
2473
2474/* The tbl->lock must be held as a writer and BH disabled. */
2475void __neigh_for_each_release(struct neigh_table *tbl,
2476 int (*cb)(struct neighbour *))
2477{
2478 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002479 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002481 nht = rcu_dereference_protected(tbl->nht,
2482 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002483 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002484 struct neighbour *n;
2485 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002487 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002488 while ((n = rcu_dereference_protected(*np,
2489 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 int release;
2491
2492 write_lock(&n->lock);
2493 release = cb(n);
2494 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002495 rcu_assign_pointer(*np,
2496 rcu_dereference_protected(n->next,
2497 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 n->dead = 1;
2499 } else
2500 np = &n->next;
2501 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002502 if (release)
2503 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 }
2505 }
2506}
2507EXPORT_SYMBOL(__neigh_for_each_release);
2508
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002509int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002510 const void *addr, struct sk_buff *skb)
2511{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002512 int err = -EAFNOSUPPORT;
2513 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002514 struct neigh_table *tbl;
2515 struct neighbour *neigh;
2516
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002517 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002518 if (!tbl)
2519 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002520 rcu_read_lock_bh();
David Ahern86e00b72019-05-01 18:18:42 -07002521 if (index == NEIGH_ARP_TABLE) {
2522 u32 key = *((u32 *)addr);
2523
2524 neigh = __ipv4_neigh_lookup_noref(dev, key);
2525 } else {
2526 neigh = __neigh_lookup_noref(tbl, addr, dev);
2527 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002528 if (!neigh)
2529 neigh = __neigh_create(tbl, addr, dev, false);
2530 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002531 if (IS_ERR(neigh)) {
2532 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002533 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002534 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002535 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002536 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002537 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002538 else if (index == NEIGH_LINK_TABLE) {
2539 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2540 addr, NULL, skb->len);
2541 if (err < 0)
2542 goto out_kfree_skb;
2543 err = dev_queue_xmit(skb);
2544 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002545out:
2546 return err;
2547out_kfree_skb:
2548 kfree_skb(skb);
2549 goto out;
2550}
2551EXPORT_SYMBOL(neigh_xmit);
2552
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553#ifdef CONFIG_PROC_FS
2554
2555static struct neighbour *neigh_get_first(struct seq_file *seq)
2556{
2557 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002558 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002559 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 struct neighbour *n = NULL;
2561 int bucket = state->bucket;
2562
2563 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002564 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002565 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002566
2567 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002568 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002569 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002570 if (state->neigh_sub_iter) {
2571 loff_t fakep = 0;
2572 void *v;
2573
2574 v = state->neigh_sub_iter(state, n, &fakep);
2575 if (!v)
2576 goto next;
2577 }
2578 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2579 break;
2580 if (n->nud_state & ~NUD_NOARP)
2581 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002582next:
2583 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 }
2585
2586 if (n)
2587 break;
2588 }
2589 state->bucket = bucket;
2590
2591 return n;
2592}
2593
2594static struct neighbour *neigh_get_next(struct seq_file *seq,
2595 struct neighbour *n,
2596 loff_t *pos)
2597{
2598 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002599 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002600 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
2602 if (state->neigh_sub_iter) {
2603 void *v = state->neigh_sub_iter(state, n, pos);
2604 if (v)
2605 return n;
2606 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002607 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 while (1) {
2610 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002611 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002612 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 if (state->neigh_sub_iter) {
2614 void *v = state->neigh_sub_iter(state, n, pos);
2615 if (v)
2616 return n;
2617 goto next;
2618 }
2619 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2620 break;
2621
2622 if (n->nud_state & ~NUD_NOARP)
2623 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002624next:
2625 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 }
2627
2628 if (n)
2629 break;
2630
David S. Millercd089332011-07-11 01:28:12 -07002631 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 break;
2633
Eric Dumazet767e97e2010-10-06 17:49:21 -07002634 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002635 }
2636
2637 if (n && pos)
2638 --(*pos);
2639 return n;
2640}
2641
2642static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2643{
2644 struct neighbour *n = neigh_get_first(seq);
2645
2646 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002647 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 while (*pos) {
2649 n = neigh_get_next(seq, n, pos);
2650 if (!n)
2651 break;
2652 }
2653 }
2654 return *pos ? NULL : n;
2655}
2656
2657static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2658{
2659 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002660 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 struct neigh_table *tbl = state->tbl;
2662 struct pneigh_entry *pn = NULL;
2663 int bucket = state->bucket;
2664
2665 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2666 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2667 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002668 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002669 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670 if (pn)
2671 break;
2672 }
2673 state->bucket = bucket;
2674
2675 return pn;
2676}
2677
2678static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2679 struct pneigh_entry *pn,
2680 loff_t *pos)
2681{
2682 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002683 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 struct neigh_table *tbl = state->tbl;
2685
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002686 do {
2687 pn = pn->next;
2688 } while (pn && !net_eq(pneigh_net(pn), net));
2689
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 while (!pn) {
2691 if (++state->bucket > PNEIGH_HASHMASK)
2692 break;
2693 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002694 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002695 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696 if (pn)
2697 break;
2698 }
2699
2700 if (pn && pos)
2701 --(*pos);
2702
2703 return pn;
2704}
2705
2706static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2707{
2708 struct pneigh_entry *pn = pneigh_get_first(seq);
2709
2710 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002711 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002712 while (*pos) {
2713 pn = pneigh_get_next(seq, pn, pos);
2714 if (!pn)
2715 break;
2716 }
2717 }
2718 return *pos ? NULL : pn;
2719}
2720
2721static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2722{
2723 struct neigh_seq_state *state = seq->private;
2724 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002725 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
Chris Larson745e2032008-08-03 01:10:55 -07002727 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002729 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730
2731 return rc;
2732}
2733
2734void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetc55ce1d2019-06-15 16:28:48 -07002735 __acquires(tbl->lock)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002736 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737{
2738 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739
2740 state->tbl = tbl;
2741 state->bucket = 0;
2742 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2743
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002744 rcu_read_lock_bh();
2745 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazetc55ce1d2019-06-15 16:28:48 -07002746 read_lock(&tbl->lock);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002747
Chris Larson745e2032008-08-03 01:10:55 -07002748 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002749}
2750EXPORT_SYMBOL(neigh_seq_start);
2751
2752void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2753{
2754 struct neigh_seq_state *state;
2755 void *rc;
2756
2757 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002758 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002759 goto out;
2760 }
2761
2762 state = seq->private;
2763 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2764 rc = neigh_get_next(seq, v, NULL);
2765 if (rc)
2766 goto out;
2767 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2768 rc = pneigh_get_first(seq);
2769 } else {
2770 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2771 rc = pneigh_get_next(seq, v, NULL);
2772 }
2773out:
2774 ++(*pos);
2775 return rc;
2776}
2777EXPORT_SYMBOL(neigh_seq_next);
2778
2779void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetc55ce1d2019-06-15 16:28:48 -07002780 __releases(tbl->lock)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002781 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002782{
Eric Dumazetc55ce1d2019-06-15 16:28:48 -07002783 struct neigh_seq_state *state = seq->private;
2784 struct neigh_table *tbl = state->tbl;
2785
2786 read_unlock(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002787 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788}
2789EXPORT_SYMBOL(neigh_seq_stop);
2790
2791/* statistics via seq_file */
2792
2793static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2794{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002795 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 int cpu;
2797
2798 if (*pos == 0)
2799 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002800
Rusty Russell0f23174a2008-12-29 12:23:42 +00002801 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 if (!cpu_possible(cpu))
2803 continue;
2804 *pos = cpu+1;
2805 return per_cpu_ptr(tbl->stats, cpu);
2806 }
2807 return NULL;
2808}
2809
2810static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2811{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002812 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 int cpu;
2814
Rusty Russell0f23174a2008-12-29 12:23:42 +00002815 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 if (!cpu_possible(cpu))
2817 continue;
2818 *pos = cpu+1;
2819 return per_cpu_ptr(tbl->stats, cpu);
2820 }
2821 return NULL;
2822}
2823
2824static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2825{
2826
2827}
2828
2829static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2830{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002831 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 struct neigh_statistics *st = v;
2833
2834 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002835 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 -07002836 return 0;
2837 }
2838
2839 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002840 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 atomic_read(&tbl->entries),
2842
2843 st->allocs,
2844 st->destroys,
2845 st->hash_grows,
2846
2847 st->lookups,
2848 st->hits,
2849
2850 st->res_failed,
2851
2852 st->rcv_probes_mcast,
2853 st->rcv_probes_ucast,
2854
2855 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002856 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002857 st->unres_discards,
2858 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 );
2860
2861 return 0;
2862}
2863
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002864static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 .start = neigh_stat_seq_start,
2866 .next = neigh_stat_seq_next,
2867 .stop = neigh_stat_seq_stop,
2868 .show = neigh_stat_seq_show,
2869};
2870
2871static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2872{
2873 int ret = seq_open(file, &neigh_stat_seq_ops);
2874
2875 if (!ret) {
2876 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002877 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 }
2879 return ret;
2880};
2881
Arjan van de Ven9a321442007-02-12 00:55:35 -08002882static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 .owner = THIS_MODULE,
2884 .open = neigh_stat_seq_open,
2885 .read = seq_read,
2886 .llseek = seq_lseek,
2887 .release = seq_release,
2888};
2889
2890#endif /* CONFIG_PROC_FS */
2891
Thomas Graf339bf982006-11-10 14:10:15 -08002892static inline size_t neigh_nlmsg_size(void)
2893{
2894 return NLMSG_ALIGN(sizeof(struct ndmsg))
2895 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2896 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2897 + nla_total_size(sizeof(struct nda_cacheinfo))
2898 + nla_total_size(4); /* NDA_PROBES */
2899}
2900
Thomas Grafb8673312006-08-15 00:33:14 -07002901static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002903 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002904 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002905 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906
Thomas Graf339bf982006-11-10 14:10:15 -08002907 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002908 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002909 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Thomas Grafb8673312006-08-15 00:33:14 -07002911 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002912 if (err < 0) {
2913 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2914 WARN_ON(err == -EMSGSIZE);
2915 kfree_skb(skb);
2916 goto errout;
2917 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002918 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2919 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002920errout:
2921 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002922 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002923}
2924
2925void neigh_app_ns(struct neighbour *n)
2926{
2927 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002929EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002932static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002933static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002934static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
Joe Perchesfe2c6332013-06-11 23:04:25 -07002936static int proc_unres_qlen(struct ctl_table *ctl, int write,
2937 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002938{
2939 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002940 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002941
Shan Weice46cc62012-12-04 18:49:15 +00002942 tmp.extra1 = &zero;
2943 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002944 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002945
2946 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2947 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2948
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002949 if (write && !ret)
2950 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2951 return ret;
2952}
2953
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002954static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2955 int family)
2956{
Jiri Pirkobba24892013-12-07 19:26:57 +01002957 switch (family) {
2958 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002959 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002960 case AF_INET6:
2961 return __in6_dev_nd_parms_get_rcu(dev);
2962 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002963 return NULL;
2964}
2965
2966static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2967 int index)
2968{
2969 struct net_device *dev;
2970 int family = neigh_parms_family(p);
2971
2972 rcu_read_lock();
2973 for_each_netdev_rcu(net, dev) {
2974 struct neigh_parms *dst_p =
2975 neigh_get_dev_parms_rcu(dev, family);
2976
2977 if (dst_p && !test_bit(index, dst_p->data_state))
2978 dst_p->data[index] = p->data[index];
2979 }
2980 rcu_read_unlock();
2981}
2982
2983static void neigh_proc_update(struct ctl_table *ctl, int write)
2984{
2985 struct net_device *dev = ctl->extra1;
2986 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002987 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002988 int index = (int *) ctl->data - p->data;
2989
2990 if (!write)
2991 return;
2992
2993 set_bit(index, p->data_state);
Marcus Huewe6c854af2017-02-15 01:00:36 +01002994 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2995 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002996 if (!dev) /* NULL dev means this is default value */
2997 neigh_copy_dflt_parms(net, p, index);
2998}
2999
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003000static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3001 void __user *buffer,
3002 size_t *lenp, loff_t *ppos)
3003{
3004 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003005 int ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003006
3007 tmp.extra1 = &zero;
3008 tmp.extra2 = &int_max;
3009
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003010 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3011 neigh_proc_update(ctl, write);
3012 return ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003013}
3014
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003015int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3016 void __user *buffer, size_t *lenp, loff_t *ppos)
3017{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003018 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3019
3020 neigh_proc_update(ctl, write);
3021 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003022}
3023EXPORT_SYMBOL(neigh_proc_dointvec);
3024
3025int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3026 void __user *buffer,
3027 size_t *lenp, loff_t *ppos)
3028{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003029 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3030
3031 neigh_proc_update(ctl, write);
3032 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003033}
3034EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3035
3036static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3037 void __user *buffer,
3038 size_t *lenp, loff_t *ppos)
3039{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003040 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3041
3042 neigh_proc_update(ctl, write);
3043 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003044}
3045
3046int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3047 void __user *buffer,
3048 size_t *lenp, loff_t *ppos)
3049{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003050 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3051
3052 neigh_proc_update(ctl, write);
3053 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003054}
3055EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3056
3057static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3058 void __user *buffer,
3059 size_t *lenp, loff_t *ppos)
3060{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003061 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3062
3063 neigh_proc_update(ctl, write);
3064 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003065}
3066
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003067static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3068 void __user *buffer,
3069 size_t *lenp, loff_t *ppos)
3070{
3071 struct neigh_parms *p = ctl->extra2;
3072 int ret;
3073
3074 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3075 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3076 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3077 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3078 else
3079 ret = -1;
3080
3081 if (write && ret == 0) {
3082 /* update reachable_time as well, otherwise, the change will
3083 * only be effective after the next time neigh_periodic_work
3084 * decides to recompute it
3085 */
3086 p->reachable_time =
3087 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3088 }
3089 return ret;
3090}
3091
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003092#define NEIGH_PARMS_DATA_OFFSET(index) \
3093 (&((struct neigh_parms *) 0)->data[index])
3094
3095#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3096 [NEIGH_VAR_ ## attr] = { \
3097 .procname = name, \
3098 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3099 .maxlen = sizeof(int), \
3100 .mode = mval, \
3101 .proc_handler = proc, \
3102 }
3103
3104#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3105 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3106
3107#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003108 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003109
3110#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003111 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003112
3113#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003114 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003115
3116#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003117 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003118
3119#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003120 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003121
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122static struct neigh_sysctl_table {
3123 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003124 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003125} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 .neigh_vars = {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003127 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3128 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3129 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003130 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003131 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3132 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3133 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3134 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3135 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3136 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3137 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3138 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3139 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3140 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3141 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3142 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003143 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 .procname = "gc_interval",
3145 .maxlen = sizeof(int),
3146 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003147 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003149 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 .procname = "gc_thresh1",
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 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003157 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 .procname = "gc_thresh2",
3159 .maxlen = sizeof(int),
3160 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003161 .extra1 = &zero,
3162 .extra2 = &int_max,
3163 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003165 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 .procname = "gc_thresh3",
3167 .maxlen = sizeof(int),
3168 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003169 .extra1 = &zero,
3170 .extra2 = &int_max,
3171 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 },
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303173 [NEIGH_VAR_PROBE] = {
3174 .procname = "neigh_probe",
3175 .maxlen = sizeof(int),
3176 .mode = 0644,
3177 .proc_handler = proc_dointvec,
3178 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003179 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 },
3181};
3182
3183int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003184 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185{
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003186 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003187 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003188 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003189 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003190 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003192 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003194 goto err;
3195
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003196 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003197 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003198 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003199 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003200 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201
3202 if (dev) {
3203 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003204 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003205 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3206 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003207 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003208 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003209 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003210 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3211 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3212 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3213 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303214 t->neigh_vars[NEIGH_VAR_PROBE].data = &neigh_probe_enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 }
3216
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003217 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003219 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003221 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003223 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003225 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003226 } else {
3227 /* Those handlers will update p->reachable_time after
3228 * base_reachable_time(_ms) is set to ensure the new timer starts being
3229 * applied after the next neighbour update instead of waiting for
3230 * neigh_periodic_work to update its value (can be multiple minutes)
3231 * So any handler that replaces them should do this as well
3232 */
3233 /* ReachableTime */
3234 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3235 neigh_proc_base_reachable_time;
3236 /* ReachableTime (in milliseconds) */
3237 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3238 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 }
3240
Eric W. Biederman464dc802012-11-16 03:02:59 +00003241 /* Don't export sysctls to unprivileged users */
3242 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3243 t->neigh_vars[0].procname = NULL;
3244
Jiri Pirko73af6142013-12-07 19:26:55 +01003245 switch (neigh_parms_family(p)) {
3246 case AF_INET:
3247 p_name = "ipv4";
3248 break;
3249 case AF_INET6:
3250 p_name = "ipv6";
3251 break;
3252 default:
3253 BUG();
3254 }
3255
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003256 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3257 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003258 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003259 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003260 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003261 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003262
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263 p->sysctl_table = t;
3264 return 0;
3265
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003266free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003267 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003268err:
3269 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003271EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272
3273void neigh_sysctl_unregister(struct neigh_parms *p)
3274{
3275 if (p->sysctl_table) {
3276 struct neigh_sysctl_table *t = p->sysctl_table;
3277 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003278 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003279 kfree(t);
3280 }
3281}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003282EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283
3284#endif /* CONFIG_SYSCTL */
3285
Thomas Grafc8822a42007-03-22 11:50:06 -07003286static int __init neigh_init(void)
3287{
Greg Rosec7ac8672011-06-10 01:27:09 +00003288 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3289 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3290 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003291
Greg Rosec7ac8672011-06-10 01:27:09 +00003292 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3293 NULL);
3294 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003295
3296 return 0;
3297}
3298
3299subsys_initcall(neigh_init);
3300