blob: 41954e42a2ded2ac1770c4b107505a5eee57a2be [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010042#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define neigh_dbg(level, fmt, ...) \
47do { \
48 if (level <= NEIGH_DEBUG) \
49 pr_debug(fmt, ##__VA_ARGS__); \
50} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define PNEIGH_HASHMASK 0xF
53
Kees Cooke99e88a2017-10-16 14:43:17 -070054static void neigh_timer_handler(struct timer_list *t);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -070055static void __neigh_notify(struct neighbour *n, int type, int flags,
56 u32 pid);
57static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +020058static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
59 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Amos Waterland45fc3b12005-09-24 16:53:16 -070061#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +020062static const struct seq_operations neigh_stat_seq_ops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070063#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65/*
66 Neighbour hash table buckets are protected with rwlock tbl->lock.
67
68 - All the scans/updates to hash buckets MUST be made under this lock.
69 - NOTHING clever should be made under this lock: no callbacks
70 to protocol backends, no attempts to send something to network.
71 It will result in deadlocks, if backend/driver wants to use neighbour
72 cache.
73 - If the entry requires some non-trivial actions, increase
74 its reference count and release table lock.
75
76 Neighbour entries are protected:
77 - with reference count.
78 - with rwlock neigh->lock
79
80 Reference count prevents destruction.
81
82 neigh->lock mainly serializes ll address data and its validity state.
83 However, the same lock is used to protect another entry fields:
84 - timer
85 - resolution queue
86
87 Again, nothing clever shall be made under neigh->lock,
88 the most complicated procedure, which we allow is dev->hard_header.
89 It is supposed, that dev->hard_header is simplistic and does
90 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 */
92
David S. Miller8f40b162011-07-17 13:34:11 -070093static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
95 kfree_skb(skb);
96 return -ENETDOWN;
97}
98
Thomas Graf4f494552007-08-08 23:12:36 -070099static void neigh_cleanup_and_release(struct neighbour *neigh)
100{
101 if (neigh->parms->neigh_cleanup)
102 neigh->parms->neigh_cleanup(neigh);
103
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700104 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100105 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Thomas Graf4f494552007-08-08 23:12:36 -0700106 neigh_release(neigh);
107}
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/*
110 * It is random distribution in the interval (1/2)*base...(3/2)*base.
111 * It corresponds to default IPv6 settings and is not overridable,
112 * because it is really reasonable choice.
113 */
114
115unsigned long neigh_rand_reach_time(unsigned long base)
116{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500117 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900119EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700122static bool neigh_del(struct neighbour *n, __u8 state, __u8 flags,
Sowmini Varadhan50710342017-06-02 09:01:49 -0700123 struct neighbour __rcu **np, struct neigh_table *tbl)
124{
125 bool retval = false;
126
127 write_lock(&n->lock);
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700128 if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state) &&
129 !(n->flags & flags)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700130 struct neighbour *neigh;
131
132 neigh = rcu_dereference_protected(n->next,
133 lockdep_is_held(&tbl->lock));
134 rcu_assign_pointer(*np, neigh);
135 n->dead = 1;
136 retval = true;
137 }
138 write_unlock(&n->lock);
139 if (retval)
140 neigh_cleanup_and_release(n);
141 return retval;
142}
143
144bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
145{
146 struct neigh_hash_table *nht;
147 void *pkey = ndel->primary_key;
148 u32 hash_val;
149 struct neighbour *n;
150 struct neighbour __rcu **np;
151
152 nht = rcu_dereference_protected(tbl->nht,
153 lockdep_is_held(&tbl->lock));
154 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
155 hash_val = hash_val >> (32 - nht->hash_shift);
156
157 np = &nht->hash_buckets[hash_val];
158 while ((n = rcu_dereference_protected(*np,
159 lockdep_is_held(&tbl->lock)))) {
160 if (n == ndel)
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700161 return neigh_del(n, 0, 0, np, tbl);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700162 np = &n->next;
163 }
164 return false;
165}
166
Linus Torvalds1da177e2005-04-16 15:20:36 -0700167static int neigh_forced_gc(struct neigh_table *tbl)
168{
169 int shrunk = 0;
170 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000171 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
173 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
174
175 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000176 nht = rcu_dereference_protected(tbl->nht,
177 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700178 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700179 struct neighbour *n;
180 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700181
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000182 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700183 while ((n = rcu_dereference_protected(*np,
184 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185 /* Neighbour record may be discarded if:
186 * - nobody refers to it.
187 * - it is not permanent
188 */
Roopa Prabhuf6a6f202018-06-12 21:26:10 -0700189 if (neigh_del(n, NUD_PERMANENT, NTF_EXT_LEARNED, np,
190 tbl)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700191 shrunk = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 continue;
193 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 np = &n->next;
195 }
196 }
197
198 tbl->last_flush = jiffies;
199
200 write_unlock_bh(&tbl->lock);
201
202 return shrunk;
203}
204
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800205static void neigh_add_timer(struct neighbour *n, unsigned long when)
206{
207 neigh_hold(n);
208 if (unlikely(mod_timer(&n->timer, when))) {
209 printk("NEIGH: BUG, double timer add, state is %x\n",
210 n->nud_state);
211 dump_stack();
212 }
213}
214
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215static int neigh_del_timer(struct neighbour *n)
216{
217 if ((n->nud_state & NUD_IN_TIMER) &&
218 del_timer(&n->timer)) {
219 neigh_release(n);
220 return 1;
221 }
222 return 0;
223}
224
225static void pneigh_queue_purge(struct sk_buff_head *list)
226{
227 struct sk_buff *skb;
228
229 while ((skb = skb_dequeue(list)) != NULL) {
230 dev_put(skb->dev);
231 kfree_skb(skb);
232 }
233}
234
David Ahern859bd2e2018-10-11 20:33:49 -0700235static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
236 bool skip_perm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237{
238 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000239 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000241 nht = rcu_dereference_protected(tbl->nht,
242 lockdep_is_held(&tbl->lock));
243
David S. Millercd089332011-07-11 01:28:12 -0700244 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700245 struct neighbour *n;
246 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247
Eric Dumazet767e97e2010-10-06 17:49:21 -0700248 while ((n = rcu_dereference_protected(*np,
249 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700250 if (dev && n->dev != dev) {
251 np = &n->next;
252 continue;
253 }
David Ahern859bd2e2018-10-11 20:33:49 -0700254 if (skip_perm && n->nud_state & NUD_PERMANENT) {
255 np = &n->next;
256 continue;
257 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700258 rcu_assign_pointer(*np,
259 rcu_dereference_protected(n->next,
260 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261 write_lock(&n->lock);
262 neigh_del_timer(n);
263 n->dead = 1;
264
Reshetova, Elena9f237432017-06-30 13:07:55 +0300265 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 /* The most unpleasant situation.
267 We must destroy neighbour entry,
268 but someone still uses it.
269
270 The destroy will be delayed until
271 the last user releases us, but
272 we must kill timers etc. and move
273 it to safe state.
274 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700275 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000276 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 n->output = neigh_blackhole;
278 if (n->nud_state & NUD_VALID)
279 n->nud_state = NUD_NOARP;
280 else
281 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000282 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 }
284 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700285 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700286 }
287 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000288}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700289
Herbert Xu49636bb2005-10-23 17:18:00 +1000290void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
291{
292 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700293 neigh_flush_dev(tbl, dev, false);
Herbert Xu49636bb2005-10-23 17:18:00 +1000294 write_unlock_bh(&tbl->lock);
295}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900296EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000297
David Ahern859bd2e2018-10-11 20:33:49 -0700298static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
299 bool skip_perm)
Herbert Xu49636bb2005-10-23 17:18:00 +1000300{
301 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700302 neigh_flush_dev(tbl, dev, skip_perm);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200303 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304
305 del_timer_sync(&tbl->proxy_timer);
306 pneigh_queue_purge(&tbl->proxy_queue);
307 return 0;
308}
David Ahern859bd2e2018-10-11 20:33:49 -0700309
310int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev)
311{
312 __neigh_ifdown(tbl, dev, true);
313 return 0;
314}
315EXPORT_SYMBOL(neigh_carrier_down);
316
317int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
318{
319 __neigh_ifdown(tbl, dev, false);
320 return 0;
321}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900322EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323
David Miller596b9b62011-07-25 00:01:25 +0000324static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325{
326 struct neighbour *n = NULL;
327 unsigned long now = jiffies;
328 int entries;
329
330 entries = atomic_inc_return(&tbl->entries) - 1;
331 if (entries >= tbl->gc_thresh3 ||
332 (entries >= tbl->gc_thresh2 &&
333 time_after(now, tbl->last_flush + 5 * HZ))) {
334 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700335 entries >= tbl->gc_thresh3) {
336 net_info_ratelimited("%s: neighbor table overflow!\n",
337 tbl->id);
338 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700340 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 }
342
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000343 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344 if (!n)
345 goto out_entries;
346
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700347 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000349 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700350 n->updated = n->used = now;
351 n->nud_state = NUD_NONE;
352 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700353 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 n->parms = neigh_parms_clone(&tbl->parms);
Kees Cooke99e88a2017-10-16 14:43:17 -0700355 timer_setup(&n->timer, neigh_timer_handler, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 NEIGH_CACHE_STAT_INC(tbl, allocs);
358 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300359 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360 n->dead = 1;
361out:
362 return n;
363
364out_entries:
365 atomic_dec(&tbl->entries);
366 goto out;
367}
368
David S. Miller2c2aba62011-12-28 15:06:58 -0500369static void neigh_get_hash_rnd(u32 *x)
370{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400371 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500372}
373
David S. Millercd089332011-07-11 01:28:12 -0700374static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375{
David S. Millercd089332011-07-11 01:28:12 -0700376 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000377 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000378 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500379 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000381 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
382 if (!ret)
383 return NULL;
384 if (size <= PAGE_SIZE)
385 buckets = kzalloc(size, GFP_ATOMIC);
386 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000387 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000388 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
389 get_order(size));
390 if (!buckets) {
391 kfree(ret);
392 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000394 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700395 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500396 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
397 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 return ret;
399}
400
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000401static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000403 struct neigh_hash_table *nht = container_of(head,
404 struct neigh_hash_table,
405 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700406 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000407 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
409 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000410 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000412 free_pages((unsigned long)buckets, get_order(size));
413 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414}
415
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000416static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700417 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000419 unsigned int i, hash;
420 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
422 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
423
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000424 old_nht = rcu_dereference_protected(tbl->nht,
425 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700426 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 if (!new_nht)
428 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
David S. Millercd089332011-07-11 01:28:12 -0700430 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 struct neighbour *n, *next;
432
Eric Dumazet767e97e2010-10-06 17:49:21 -0700433 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
434 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000435 n != NULL;
436 n = next) {
437 hash = tbl->hash(n->primary_key, n->dev,
438 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439
David S. Millercd089332011-07-11 01:28:12 -0700440 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700441 next = rcu_dereference_protected(n->next,
442 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Eric Dumazet767e97e2010-10-06 17:49:21 -0700444 rcu_assign_pointer(n->next,
445 rcu_dereference_protected(
446 new_nht->hash_buckets[hash],
447 lockdep_is_held(&tbl->lock)));
448 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
450 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000452 rcu_assign_pointer(tbl->nht, new_nht);
453 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
454 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455}
456
457struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
458 struct net_device *dev)
459{
460 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 NEIGH_CACHE_STAT_INC(tbl, lookups);
463
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000464 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600465 n = __neigh_lookup_noref(tbl, pkey, dev);
466 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300467 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600468 n = NULL;
469 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700471
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000472 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 return n;
474}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900475EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476
Eric W. Biederman426b5302008-01-24 00:13:18 -0800477struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
478 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
480 struct neighbour *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300481 unsigned int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800482 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000483 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484
485 NEIGH_CACHE_STAT_INC(tbl, lookups);
486
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000487 rcu_read_lock_bh();
488 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700489 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700490
491 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
492 n != NULL;
493 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800494 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900495 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300496 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700497 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 NEIGH_CACHE_STAT_INC(tbl, hits);
499 break;
500 }
501 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700502
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000503 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 return n;
505}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900506EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507
David S. Millera263b302012-07-02 02:02:15 -0700508struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
509 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 u32 hash_val;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300512 unsigned int key_len = tbl->key_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 int error;
David Miller596b9b62011-07-25 00:01:25 +0000514 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000515 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516
517 if (!n) {
518 rc = ERR_PTR(-ENOBUFS);
519 goto out;
520 }
521
522 memcpy(n->primary_key, pkey, key_len);
523 n->dev = dev;
524 dev_hold(dev);
525
526 /* Protocol specific setup. */
527 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
528 rc = ERR_PTR(error);
529 goto out_neigh_release;
530 }
531
David Millerda6a8fa2011-07-25 00:01:38 +0000532 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200533 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000534 if (error < 0) {
535 rc = ERR_PTR(error);
536 goto out_neigh_release;
537 }
538 }
539
David S. Miller447f2192011-12-19 15:04:41 -0500540 /* Device specific setup. */
541 if (n->parms->neigh_setup &&
542 (error = n->parms->neigh_setup(n)) < 0) {
543 rc = ERR_PTR(error);
544 goto out_neigh_release;
545 }
546
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100547 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548
549 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000550 nht = rcu_dereference_protected(tbl->nht,
551 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552
David S. Millercd089332011-07-11 01:28:12 -0700553 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
554 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555
Jim Westfall096b9852018-01-14 04:18:50 -0800556 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557
558 if (n->parms->dead) {
559 rc = ERR_PTR(-EINVAL);
560 goto out_tbl_unlock;
561 }
562
Eric Dumazet767e97e2010-10-06 17:49:21 -0700563 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
564 lockdep_is_held(&tbl->lock));
565 n1 != NULL;
566 n1 = rcu_dereference_protected(n1->next,
567 lockdep_is_held(&tbl->lock))) {
Jim Westfall096b9852018-01-14 04:18:50 -0800568 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700569 if (want_ref)
570 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 rc = n1;
572 goto out_tbl_unlock;
573 }
574 }
575
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700577 if (want_ref)
578 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700579 rcu_assign_pointer(n->next,
580 rcu_dereference_protected(nht->hash_buckets[hash_val],
581 lockdep_is_held(&tbl->lock)));
582 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000584 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 rc = n;
586out:
587 return rc;
588out_tbl_unlock:
589 write_unlock_bh(&tbl->lock);
590out_neigh_release:
591 neigh_release(n);
592 goto out;
593}
David S. Millera263b302012-07-02 02:02:15 -0700594EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300596static u32 pneigh_hash(const void *pkey, unsigned int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700597{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700598 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700599 hash_val ^= (hash_val >> 16);
600 hash_val ^= hash_val >> 8;
601 hash_val ^= hash_val >> 4;
602 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900603 return hash_val;
604}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700605
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900606static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
607 struct net *net,
608 const void *pkey,
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300609 unsigned int key_len,
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900610 struct net_device *dev)
611{
612 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700613 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900614 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700615 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900616 return n;
617 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700618 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900619 return NULL;
620}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700621
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900622struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
623 struct net *net, const void *pkey, struct net_device *dev)
624{
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300625 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900626 u32 hash_val = pneigh_hash(pkey, key_len);
627
628 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
629 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700630}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900631EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700632
Eric W. Biederman426b5302008-01-24 00:13:18 -0800633struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
634 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 struct net_device *dev, int creat)
636{
637 struct pneigh_entry *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300638 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900639 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900642 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
643 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900645
646 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 goto out;
648
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700649 ASSERT_RTNL();
650
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
652 if (!n)
653 goto out;
654
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500655 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656 memcpy(n->key, pkey, key_len);
657 n->dev = dev;
658 if (dev)
659 dev_hold(dev);
660
661 if (tbl->pconstructor && tbl->pconstructor(n)) {
662 if (dev)
663 dev_put(dev);
664 kfree(n);
665 n = NULL;
666 goto out;
667 }
668
669 write_lock_bh(&tbl->lock);
670 n->next = tbl->phash_buckets[hash_val];
671 tbl->phash_buckets[hash_val] = n;
672 write_unlock_bh(&tbl->lock);
673out:
674 return n;
675}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900676EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
678
Eric W. Biederman426b5302008-01-24 00:13:18 -0800679int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680 struct net_device *dev)
681{
682 struct pneigh_entry *n, **np;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300683 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900684 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685
686 write_lock_bh(&tbl->lock);
687 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
688 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800689 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900690 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 *np = n->next;
692 write_unlock_bh(&tbl->lock);
693 if (tbl->pdestructor)
694 tbl->pdestructor(n);
695 if (n->dev)
696 dev_put(n->dev);
697 kfree(n);
698 return 0;
699 }
700 }
701 write_unlock_bh(&tbl->lock);
702 return -ENOENT;
703}
704
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200705static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
706 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707{
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200708 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 u32 h;
710
711 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
712 np = &tbl->phash_buckets[h];
713 while ((n = *np) != NULL) {
714 if (!dev || n->dev == dev) {
715 *np = n->next;
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200716 n->next = freelist;
717 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 continue;
719 }
720 np = &n->next;
721 }
722 }
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200723 write_unlock_bh(&tbl->lock);
724 while ((n = freelist)) {
725 freelist = n->next;
726 n->next = NULL;
727 if (tbl->pdestructor)
728 tbl->pdestructor(n);
729 if (n->dev)
730 dev_put(n->dev);
731 kfree(n);
732 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 return -ENOENT;
734}
735
Denis V. Lunev06f05112008-01-24 00:30:58 -0800736static void neigh_parms_destroy(struct neigh_parms *parms);
737
738static inline void neigh_parms_put(struct neigh_parms *parms)
739{
Reshetova, Elena63439442017-06-30 13:07:56 +0300740 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800741 neigh_parms_destroy(parms);
742}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
744/*
745 * neighbour must already be out of the table;
746 *
747 */
748void neigh_destroy(struct neighbour *neigh)
749{
David Millerda6a8fa2011-07-25 00:01:38 +0000750 struct net_device *dev = neigh->dev;
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
753
754 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000755 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 dump_stack();
757 return;
758 }
759
760 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000761 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700763 write_lock_bh(&neigh->lock);
764 __skb_queue_purge(&neigh->arp_queue);
765 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000766 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
David S. Miller447f2192011-12-19 15:04:41 -0500768 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200769 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500770
David Millerda6a8fa2011-07-25 00:01:38 +0000771 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772 neigh_parms_put(neigh->parms);
773
Joe Perchesd5d427c2013-04-15 15:17:19 +0000774 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
776 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000777 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900779EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781/* Neighbour state is suspicious;
782 disable fast path.
783
784 Called with write_locked neigh.
785 */
786static void neigh_suspect(struct neighbour *neigh)
787{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000788 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791}
792
793/* Neighbour state is OK;
794 enable fast path.
795
796 Called with write_locked neigh.
797 */
798static void neigh_connect(struct neighbour *neigh)
799{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000800 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803}
804
Eric Dumazete4c4e442009-07-30 03:15:07 +0000805static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000807 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700808 struct neighbour *n;
809 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000810 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000811 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
813 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
814
Eric Dumazete4c4e442009-07-30 03:15:07 +0000815 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000816 nht = rcu_dereference_protected(tbl->nht,
817 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818
819 /*
820 * periodically recompute ReachableTime from random function
821 */
822
Eric Dumazete4c4e442009-07-30 03:15:07 +0000823 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000825 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100826 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100828 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 }
830
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800831 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
832 goto out;
833
David S. Millercd089332011-07-11 01:28:12 -0700834 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000835 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836
Eric Dumazet767e97e2010-10-06 17:49:21 -0700837 while ((n = rcu_dereference_protected(*np,
838 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000839 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
Eric Dumazete4c4e442009-07-30 03:15:07 +0000841 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
Eric Dumazete4c4e442009-07-30 03:15:07 +0000843 state = n->nud_state;
Roopa Prabhu9ce33e42018-04-24 13:49:34 -0700844 if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
845 (n->flags & NTF_EXT_LEARNED)) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000846 write_unlock(&n->lock);
847 goto next_elt;
848 }
849
850 if (time_before(n->used, n->confirmed))
851 n->used = n->confirmed;
852
Reshetova, Elena9f237432017-06-30 13:07:55 +0300853 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000854 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100855 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000856 *np = n->next;
857 n->dead = 1;
858 write_unlock(&n->lock);
859 neigh_cleanup_and_release(n);
860 continue;
861 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000865 np = &n->next;
866 }
867 /*
868 * It's fine to release lock here, even if hash table
869 * grows while we are preempted.
870 */
871 write_unlock_bh(&tbl->lock);
872 cond_resched();
873 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500874 nht = rcu_dereference_protected(tbl->nht,
875 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000877out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100878 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
879 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
880 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881 */
viresh kumarf6180022014-01-22 12:23:33 +0530882 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100883 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000884 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885}
886
887static __inline__ int neigh_max_probes(struct neighbour *n)
888{
889 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900890 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
891 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
892 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700893}
894
Timo Teras5ef12d92009-06-11 04:16:28 -0700895static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000896 __releases(neigh->lock)
897 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700898{
899 struct sk_buff *skb;
900
901 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000902 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700903 neigh->updated = jiffies;
904
905 /* It is very thin place. report_unreachable is very complicated
906 routine. Particularly, it can hit the same neighbour entry!
907
908 So that, we try to be accurate and avoid dead loop. --ANK
909 */
910 while (neigh->nud_state == NUD_FAILED &&
911 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
912 write_unlock(&neigh->lock);
913 neigh->ops->error_report(neigh, skb);
914 write_lock(&neigh->lock);
915 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700916 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000917 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700918}
919
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000920static void neigh_probe(struct neighbour *neigh)
921 __releases(neigh->lock)
922{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200923 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000924 /* keep skb alive even if arp_queue overflows */
925 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800926 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000927 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700928 if (neigh->ops->solicit)
929 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000930 atomic_inc(&neigh->probes);
931 kfree_skb(skb);
932}
933
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934/* Called when a timer expires for a neighbour entry. */
935
Kees Cooke99e88a2017-10-16 14:43:17 -0700936static void neigh_timer_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937{
938 unsigned long now, next;
Kees Cooke99e88a2017-10-16 14:43:17 -0700939 struct neighbour *neigh = from_timer(neigh, t, timer);
Eric Dumazet95c96172012-04-15 05:58:06 +0000940 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 int notify = 0;
942
943 write_lock(&neigh->lock);
944
945 state = neigh->nud_state;
946 now = jiffies;
947 next = now + HZ;
948
David S. Miller045f7b32011-11-01 17:45:55 -0400949 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
952 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900953 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000955 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 next = neigh->confirmed + neigh->parms->reachable_time;
957 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100958 neigh->used +
959 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000960 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800962 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100964 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000966 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800968 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700970 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 }
972 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900973 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100974 neigh->confirmed +
975 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000976 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800978 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700980 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 next = neigh->confirmed + neigh->parms->reachable_time;
982 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000983 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800985 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900987 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100988 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 }
990 } else {
991 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100992 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700993 }
994
995 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
996 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997 neigh->nud_state = NUD_FAILED;
998 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700999 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +08001000 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001 }
1002
1003 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 if (time_before(next, jiffies + HZ/2))
1005 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +10001006 if (!mod_timer(&neigh->timer, next))
1007 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 }
1009 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001010 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -08001011 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -08001012out:
David S. Miller9ff56602008-02-17 18:39:54 -08001013 write_unlock(&neigh->lock);
1014 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
Thomas Grafd961db32007-08-08 23:12:56 -07001016 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001017 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -07001018
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 neigh_release(neigh);
1020}
1021
1022int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
1023{
1024 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001025 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026
1027 write_lock_bh(&neigh->lock);
1028
1029 rc = 0;
1030 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1031 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001032 if (neigh->dead)
1033 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001036 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1037 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001038 unsigned long next, now = jiffies;
1039
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001040 atomic_set(&neigh->probes,
1041 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001043 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001044 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1045 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001046 neigh_add_timer(neigh, next);
1047 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 } else {
1049 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001050 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 write_unlock_bh(&neigh->lock);
1052
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001053 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 return 1;
1055 }
1056 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001057 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001059 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001060 neigh_add_timer(neigh, jiffies +
1061 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063
1064 if (neigh->nud_state == NUD_INCOMPLETE) {
1065 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001066 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001067 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001069
David S. Millerf72051b2008-09-23 01:11:18 -07001070 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001071 if (!buff)
1072 break;
1073 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001075 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001077 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001079 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
1081 rc = 1;
1082 }
1083out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001084 if (immediate_probe)
1085 neigh_probe(neigh);
1086 else
1087 write_unlock(&neigh->lock);
1088 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001090
1091out_dead:
1092 if (neigh->nud_state & NUD_STALE)
1093 goto out_unlock_bh;
1094 write_unlock_bh(&neigh->lock);
1095 kfree_skb(skb);
1096 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001098EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
David S. Millerf6b72b622011-07-14 07:53:20 -07001100static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101{
1102 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001103 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001104 = NULL;
1105
1106 if (neigh->dev->header_ops)
1107 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108
1109 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001110 hh = &neigh->hh;
1111 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001112 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001114 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 }
1116 }
1117}
1118
1119
1120
1121/* Generic update routine.
1122 -- lladdr is new lladdr or NULL, if it is not supplied.
1123 -- new is new state.
1124 -- flags
1125 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1126 if it is different.
1127 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001128 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001129 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1131
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001132 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 NTF_ROUTER flag.
1134 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1135 a router.
1136
1137 Caller MUST hold reference count on the entry.
1138 */
1139
1140int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001141 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142{
1143 u8 old;
1144 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 struct net_device *dev;
1147 int update_isrouter = 0;
1148
1149 write_lock_bh(&neigh->lock);
1150
1151 dev = neigh->dev;
1152 old = neigh->nud_state;
1153 err = -EPERM;
1154
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001155 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 (old & (NUD_NOARP | NUD_PERMANENT)))
1157 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001158 if (neigh->dead)
1159 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001161 neigh_update_ext_learned(neigh, flags, &notify);
1162
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 if (!(new & NUD_VALID)) {
1164 neigh_del_timer(neigh);
1165 if (old & NUD_CONNECTED)
1166 neigh_suspect(neigh);
1167 neigh->nud_state = new;
1168 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 notify = old & NUD_VALID;
Roopa Prabhud2fb4fb2018-10-20 18:09:31 -07001170 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
Timo Teras5ef12d92009-06-11 04:16:28 -07001171 (new & NUD_FAILED)) {
1172 neigh_invalidate(neigh);
1173 notify = 1;
1174 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 goto out;
1176 }
1177
1178 /* Compare new lladdr with cached one */
1179 if (!dev->addr_len) {
1180 /* First case: device needs no address. */
1181 lladdr = neigh->ha;
1182 } else if (lladdr) {
1183 /* The second case: if something is already cached
1184 and a new address is proposed:
1185 - compare new & old
1186 - if they are different, check override flag
1187 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001188 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001189 !memcmp(lladdr, neigh->ha, dev->addr_len))
1190 lladdr = neigh->ha;
1191 } else {
1192 /* No address is supplied; if we know something,
1193 use it, otherwise discard the request.
1194 */
1195 err = -EINVAL;
1196 if (!(old & NUD_VALID))
1197 goto out;
1198 lladdr = neigh->ha;
1199 }
1200
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001201 /* Update confirmed timestamp for neighbour entry after we
1202 * received ARP packet even if it doesn't change IP to MAC binding.
1203 */
1204 if (new & NUD_CONNECTED)
1205 neigh->confirmed = jiffies;
1206
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207 /* If entry was valid and address is not changed,
1208 do not change entry state, if new one is STALE.
1209 */
1210 err = 0;
1211 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1212 if (old & NUD_VALID) {
1213 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1214 update_isrouter = 0;
1215 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1216 (old & NUD_CONNECTED)) {
1217 lladdr = neigh->ha;
1218 new = NUD_STALE;
1219 } else
1220 goto out;
1221 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001222 if (lladdr == neigh->ha && new == NUD_STALE &&
1223 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 new = old;
1225 }
1226 }
1227
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001228 /* Update timestamp only once we know we will make a change to the
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001229 * neighbour entry. Otherwise we risk to move the locktime window with
1230 * noop updates and ignore relevant ARP updates.
1231 */
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001232 if (new != old || lladdr != neigh->ha)
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001233 neigh->updated = jiffies;
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 if (new != old) {
1236 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001237 if (new & NUD_PROBE)
1238 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001239 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001240 neigh_add_timer(neigh, (jiffies +
1241 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001242 neigh->parms->reachable_time :
1243 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001245 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 }
1247
1248 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001249 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001250 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001251 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 neigh_update_hhs(neigh);
1253 if (!(new & NUD_CONNECTED))
1254 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001255 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257 }
1258 if (new == old)
1259 goto out;
1260 if (new & NUD_CONNECTED)
1261 neigh_connect(neigh);
1262 else
1263 neigh_suspect(neigh);
1264 if (!(old & NUD_VALID)) {
1265 struct sk_buff *skb;
1266
1267 /* Again: avoid dead loop if something went wrong */
1268
1269 while (neigh->nud_state & NUD_VALID &&
1270 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001271 struct dst_entry *dst = skb_dst(skb);
1272 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001273 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001274
1275 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001276
1277 /* Why not just use 'neigh' as-is? The problem is that
1278 * things such as shaper, eql, and sch_teql can end up
1279 * using alternative, different, neigh objects to output
1280 * the packet in the output path. So what we need to do
1281 * here is re-lookup the top-level neigh in the path so
1282 * we can reinject the packet there.
1283 */
1284 n2 = NULL;
1285 if (dst) {
1286 n2 = dst_neigh_lookup_skb(dst, skb);
1287 if (n2)
1288 n1 = n2;
1289 }
David S. Miller8f40b162011-07-17 13:34:11 -07001290 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001291 if (n2)
1292 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001293 rcu_read_unlock();
1294
Linus Torvalds1da177e2005-04-16 15:20:36 -07001295 write_lock_bh(&neigh->lock);
1296 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001297 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001298 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 }
1300out:
Roopa Prabhufc6e8072018-09-22 21:26:20 -07001301 if (update_isrouter)
1302 neigh_update_is_router(neigh, flags, &notify);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001304
1305 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001306 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308 return err;
1309}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001310EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Jiri Benc7e980562013-12-11 13:48:20 +01001312/* Update the neigh to listen temporarily for probe responses, even if it is
1313 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1314 */
1315void __neigh_set_probe_once(struct neighbour *neigh)
1316{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001317 if (neigh->dead)
1318 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001319 neigh->updated = jiffies;
1320 if (!(neigh->nud_state & NUD_FAILED))
1321 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001322 neigh->nud_state = NUD_INCOMPLETE;
1323 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001324 neigh_add_timer(neigh,
1325 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1326}
1327EXPORT_SYMBOL(__neigh_set_probe_once);
1328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1330 u8 *lladdr, void *saddr,
1331 struct net_device *dev)
1332{
1333 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1334 lladdr || !dev->addr_len);
1335 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001336 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001337 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 return neigh;
1339}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001340EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
Eric Dumazet34d101d2010-10-11 09:16:57 -07001342/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001343static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001345 struct net_device *dev = n->dev;
1346 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001347 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001348
1349 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001350
David S. Millerf6b72b622011-07-14 07:53:20 -07001351 /* Only one thread can come in here and initialize the
1352 * hh_cache entry.
1353 */
David S. Millerb23b5452011-07-16 17:45:02 -07001354 if (!hh->hh_len)
1355 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001356
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001357 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358}
1359
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360/* Slow and careful. */
1361
David S. Miller8f40b162011-07-17 13:34:11 -07001362int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364 int rc = 0;
1365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 if (!neigh_event_send(neigh, skb)) {
1367 int err;
1368 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001369 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001370
David S. Millerf6b72b622011-07-14 07:53:20 -07001371 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001372 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001373
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001374 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001375 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001376 seq = read_seqbegin(&neigh->ha_lock);
1377 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1378 neigh->ha, NULL, skb->len);
1379 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001380
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001382 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383 else
1384 goto out_kfree_skb;
1385 }
1386out:
1387 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388out_kfree_skb:
1389 rc = -EINVAL;
1390 kfree_skb(skb);
1391 goto out;
1392}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001393EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394
1395/* As fast as possible without hh cache */
1396
David S. Miller8f40b162011-07-17 13:34:11 -07001397int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001400 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001401 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001403 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001404 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001405 seq = read_seqbegin(&neigh->ha_lock);
1406 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1407 neigh->ha, NULL, skb->len);
1408 } while (read_seqretry(&neigh->ha_lock, seq));
1409
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001411 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001412 else {
1413 err = -EINVAL;
1414 kfree_skb(skb);
1415 }
1416 return err;
1417}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001418EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001419
David S. Miller8f40b162011-07-17 13:34:11 -07001420int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1421{
1422 return dev_queue_xmit(skb);
1423}
1424EXPORT_SYMBOL(neigh_direct_output);
1425
Kees Cooke99e88a2017-10-16 14:43:17 -07001426static void neigh_proxy_process(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001427{
Kees Cooke99e88a2017-10-16 14:43:17 -07001428 struct neigh_table *tbl = from_timer(tbl, t, proxy_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429 long sched_next = 0;
1430 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001431 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432
1433 spin_lock(&tbl->proxy_queue.lock);
1434
David S. Millerf72051b2008-09-23 01:11:18 -07001435 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1436 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001439 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001440
David S. Millerf72051b2008-09-23 01:11:18 -07001441 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001442 if (tbl->proxy_redo && netif_running(dev)) {
1443 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001444 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001445 rcu_read_unlock();
1446 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001447 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001448 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001449
1450 dev_put(dev);
1451 } else if (!sched_next || tdif < sched_next)
1452 sched_next = tdif;
1453 }
1454 del_timer(&tbl->proxy_timer);
1455 if (sched_next)
1456 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1457 spin_unlock(&tbl->proxy_queue.lock);
1458}
1459
1460void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1461 struct sk_buff *skb)
1462{
1463 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001464
1465 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001466 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001468 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 kfree_skb(skb);
1470 return;
1471 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001472
1473 NEIGH_CB(skb)->sched_next = sched_next;
1474 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
1476 spin_lock(&tbl->proxy_queue.lock);
1477 if (del_timer(&tbl->proxy_timer)) {
1478 if (time_before(tbl->proxy_timer.expires, sched_next))
1479 sched_next = tbl->proxy_timer.expires;
1480 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001481 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 dev_hold(skb->dev);
1483 __skb_queue_tail(&tbl->proxy_queue, skb);
1484 mod_timer(&tbl->proxy_timer, sched_next);
1485 spin_unlock(&tbl->proxy_queue.lock);
1486}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001487EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001489static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001490 struct net *net, int ifindex)
1491{
1492 struct neigh_parms *p;
1493
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001494 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001495 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001496 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001497 return p;
1498 }
1499
1500 return NULL;
1501}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
1503struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1504 struct neigh_table *tbl)
1505{
Gao fengcf89d6b2013-06-20 10:01:32 +08001506 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001507 struct net *net = dev_net(dev);
1508 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509
Gao fengcf89d6b2013-06-20 10:01:32 +08001510 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001513 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001515 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001516 dev_hold(dev);
1517 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001518 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001520
1521 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001522 dev_put(dev);
1523 kfree(p);
1524 return NULL;
1525 }
1526
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001528 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001530
1531 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 }
1533 return p;
1534}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001535EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
1537static void neigh_rcu_free_parms(struct rcu_head *head)
1538{
1539 struct neigh_parms *parms =
1540 container_of(head, struct neigh_parms, rcu_head);
1541
1542 neigh_parms_put(parms);
1543}
1544
1545void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1546{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547 if (!parms || parms == &tbl->parms)
1548 return;
1549 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001550 list_del(&parms->list);
1551 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001553 if (parms->dev)
1554 dev_put(parms->dev);
1555 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001557EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Denis V. Lunev06f05112008-01-24 00:30:58 -08001559static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560{
1561 kfree(parms);
1562}
1563
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001564static struct lock_class_key neigh_table_proxy_queue_class;
1565
WANG Congd7480fd2014-11-10 15:59:36 -08001566static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1567
1568void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569{
1570 unsigned long now = jiffies;
1571 unsigned long phsize;
1572
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001573 INIT_LIST_HEAD(&tbl->parms_list);
1574 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001575 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001576 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001578 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580 tbl->stats = alloc_percpu(struct neigh_statistics);
1581 if (!tbl->stats)
1582 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001583
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +02001585 if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat,
1586 &neigh_stat_seq_ops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588#endif
1589
David S. Millercd089332011-07-11 01:28:12 -07001590 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591
1592 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001593 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001595 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596 panic("cannot allocate neighbour cache hashes");
1597
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001598 if (!tbl->entry_size)
1599 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1600 tbl->key_len, NEIGH_PRIV_ALIGN);
1601 else
1602 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1603
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001605 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301606 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1607 tbl->parms.reachable_time);
Kees Cooke99e88a2017-10-16 14:43:17 -07001608 timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001609 skb_queue_head_init_class(&tbl->proxy_queue,
1610 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
1612 tbl->last_flush = now;
1613 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001614
WANG Congd7480fd2014-11-10 15:59:36 -08001615 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001617EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618
WANG Congd7480fd2014-11-10 15:59:36 -08001619int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620{
WANG Congd7480fd2014-11-10 15:59:36 -08001621 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001623 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624 del_timer_sync(&tbl->proxy_timer);
1625 pneigh_queue_purge(&tbl->proxy_queue);
1626 neigh_ifdown(tbl, NULL);
1627 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001628 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001630 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1631 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001632 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
1634 kfree(tbl->phash_buckets);
1635 tbl->phash_buckets = NULL;
1636
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001637 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1638
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001639 free_percpu(tbl->stats);
1640 tbl->stats = NULL;
1641
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 return 0;
1643}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001644EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645
WANG Congd7480fd2014-11-10 15:59:36 -08001646static struct neigh_table *neigh_find_table(int family)
1647{
1648 struct neigh_table *tbl = NULL;
1649
1650 switch (family) {
1651 case AF_INET:
1652 tbl = neigh_tables[NEIGH_ARP_TABLE];
1653 break;
1654 case AF_INET6:
1655 tbl = neigh_tables[NEIGH_ND_TABLE];
1656 break;
1657 case AF_DECnet:
1658 tbl = neigh_tables[NEIGH_DN_TABLE];
1659 break;
1660 }
1661
1662 return tbl;
1663}
1664
David Ahernc21ef3e2017-04-16 09:48:24 -07001665static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1666 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001668 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001669 struct ndmsg *ndm;
1670 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001672 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001674 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Eric Dumazet110b2492010-10-04 04:27:36 +00001676 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001677 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678 goto out;
1679
Thomas Grafa14a49d2006-08-07 17:53:08 -07001680 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1681 if (dst_attr == NULL)
1682 goto out;
1683
1684 ndm = nlmsg_data(nlh);
1685 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001686 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001687 if (dev == NULL) {
1688 err = -ENODEV;
1689 goto out;
1690 }
1691 }
1692
WANG Congd7480fd2014-11-10 15:59:36 -08001693 tbl = neigh_find_table(ndm->ndm_family);
1694 if (tbl == NULL)
1695 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001697 if (nla_len(dst_attr) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001698 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
WANG Congd7480fd2014-11-10 15:59:36 -08001700 if (ndm->ndm_flags & NTF_PROXY) {
1701 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001702 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 }
WANG Congd7480fd2014-11-10 15:59:36 -08001704
1705 if (dev == NULL)
1706 goto out;
1707
1708 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1709 if (neigh == NULL) {
1710 err = -ENOENT;
1711 goto out;
1712 }
1713
1714 err = neigh_update(neigh, NULL, NUD_FAILED,
1715 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001716 NEIGH_UPDATE_F_ADMIN,
1717 NETLINK_CB(skb).portid);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001718 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001719 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001720 neigh_remove_one(neigh, tbl);
1721 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001722
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723out:
1724 return err;
1725}
1726
David Ahernc21ef3e2017-04-16 09:48:24 -07001727static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1728 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729{
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001730 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE |
1731 NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001732 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001733 struct ndmsg *ndm;
1734 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001735 struct neigh_table *tbl;
1736 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001737 struct neighbour *neigh;
1738 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001739 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
Eric Dumazet110b2492010-10-04 04:27:36 +00001741 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001742 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001743 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001744 goto out;
1745
Thomas Graf5208deb2006-08-07 17:55:40 -07001746 err = -EINVAL;
1747 if (tb[NDA_DST] == NULL)
1748 goto out;
1749
1750 ndm = nlmsg_data(nlh);
1751 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001752 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001753 if (dev == NULL) {
1754 err = -ENODEV;
1755 goto out;
1756 }
1757
1758 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001759 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001760 }
1761
WANG Congd7480fd2014-11-10 15:59:36 -08001762 tbl = neigh_find_table(ndm->ndm_family);
1763 if (tbl == NULL)
1764 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001766 if (nla_len(tb[NDA_DST]) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001767 goto out;
1768 dst = nla_data(tb[NDA_DST]);
1769 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001770
WANG Congd7480fd2014-11-10 15:59:36 -08001771 if (ndm->ndm_flags & NTF_PROXY) {
1772 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773
WANG Congd7480fd2014-11-10 15:59:36 -08001774 err = -ENOBUFS;
1775 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1776 if (pn) {
1777 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001778 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001779 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001780 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 }
1782
WANG Congd7480fd2014-11-10 15:59:36 -08001783 if (dev == NULL)
1784 goto out;
1785
1786 neigh = neigh_lookup(tbl, dst, dev);
1787 if (neigh == NULL) {
1788 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1789 err = -ENOENT;
1790 goto out;
1791 }
1792
1793 neigh = __neigh_lookup_errno(tbl, dst, dev);
1794 if (IS_ERR(neigh)) {
1795 err = PTR_ERR(neigh);
1796 goto out;
1797 }
1798 } else {
1799 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1800 err = -EEXIST;
1801 neigh_release(neigh);
1802 goto out;
1803 }
1804
1805 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001806 flags &= ~(NEIGH_UPDATE_F_OVERRIDE |
1807 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
WANG Congd7480fd2014-11-10 15:59:36 -08001808 }
1809
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001810 if (ndm->ndm_flags & NTF_EXT_LEARNED)
1811 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1812
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001813 if (ndm->ndm_flags & NTF_ROUTER)
1814 flags |= NEIGH_UPDATE_F_ISROUTER;
1815
WANG Congd7480fd2014-11-10 15:59:36 -08001816 if (ndm->ndm_flags & NTF_USE) {
1817 neigh_event_send(neigh, NULL);
1818 err = 0;
1819 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001820 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1821 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001822 neigh_release(neigh);
1823
Linus Torvalds1da177e2005-04-16 15:20:36 -07001824out:
1825 return err;
1826}
1827
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001828static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1829{
Thomas Grafca860fb2006-08-07 18:00:18 -07001830 struct nlattr *nest;
1831
1832 nest = nla_nest_start(skb, NDTA_PARMS);
1833 if (nest == NULL)
1834 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001835
David S. Miller9a6308d2012-04-01 20:06:28 -04001836 if ((parms->dev &&
1837 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001838 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001839 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1840 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001841 /* approximative value for deprecated QUEUE_LEN (in packets) */
1842 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001843 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1844 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1845 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1846 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1847 NEIGH_VAR(parms, UCAST_PROBES)) ||
1848 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1849 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001850 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1851 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001852 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1853 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001854 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001855 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001856 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001857 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001858 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001859 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001860 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001861 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001862 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001863 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001864 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001865 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001866 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001867 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001868 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001869 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001870
Thomas Grafca860fb2006-08-07 18:00:18 -07001871nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001872 nla_nest_cancel(skb, nest);
1873 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001874}
1875
Thomas Grafca860fb2006-08-07 18:00:18 -07001876static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1877 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878{
1879 struct nlmsghdr *nlh;
1880 struct ndtmsg *ndtmsg;
1881
Thomas Grafca860fb2006-08-07 18:00:18 -07001882 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1883 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001884 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001885
Thomas Grafca860fb2006-08-07 18:00:18 -07001886 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887
1888 read_lock_bh(&tbl->lock);
1889 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001890 ndtmsg->ndtm_pad1 = 0;
1891 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001892
David S. Miller9a6308d2012-04-01 20:06:28 -04001893 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001894 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001895 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1896 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1897 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1898 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001899 {
1900 unsigned long now = jiffies;
1901 unsigned int flush_delta = now - tbl->last_flush;
1902 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001903 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001904 struct ndt_config ndc = {
1905 .ndtc_key_len = tbl->key_len,
1906 .ndtc_entry_size = tbl->entry_size,
1907 .ndtc_entries = atomic_read(&tbl->entries),
1908 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1909 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001910 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1911 };
1912
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001913 rcu_read_lock_bh();
1914 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001915 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001916 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001917 rcu_read_unlock_bh();
1918
David S. Miller9a6308d2012-04-01 20:06:28 -04001919 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1920 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921 }
1922
1923 {
1924 int cpu;
1925 struct ndt_stats ndst;
1926
1927 memset(&ndst, 0, sizeof(ndst));
1928
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001929 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930 struct neigh_statistics *st;
1931
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001932 st = per_cpu_ptr(tbl->stats, cpu);
1933 ndst.ndts_allocs += st->allocs;
1934 ndst.ndts_destroys += st->destroys;
1935 ndst.ndts_hash_grows += st->hash_grows;
1936 ndst.ndts_res_failed += st->res_failed;
1937 ndst.ndts_lookups += st->lookups;
1938 ndst.ndts_hits += st->hits;
1939 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1940 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1941 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1942 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001943 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944 }
1945
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001946 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1947 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001948 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949 }
1950
1951 BUG_ON(tbl->parms.dev);
1952 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001953 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001954
1955 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001956 nlmsg_end(skb, nlh);
1957 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001958
Thomas Grafca860fb2006-08-07 18:00:18 -07001959nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001960 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001961 nlmsg_cancel(skb, nlh);
1962 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001963}
1964
Thomas Grafca860fb2006-08-07 18:00:18 -07001965static int neightbl_fill_param_info(struct sk_buff *skb,
1966 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001968 u32 pid, u32 seq, int type,
1969 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001970{
1971 struct ndtmsg *ndtmsg;
1972 struct nlmsghdr *nlh;
1973
Thomas Grafca860fb2006-08-07 18:00:18 -07001974 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1975 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001976 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001977
Thomas Grafca860fb2006-08-07 18:00:18 -07001978 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001979
1980 read_lock_bh(&tbl->lock);
1981 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001982 ndtmsg->ndtm_pad1 = 0;
1983 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001984
Thomas Grafca860fb2006-08-07 18:00:18 -07001985 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1986 neightbl_fill_parms(skb, parms) < 0)
1987 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988
1989 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001990 nlmsg_end(skb, nlh);
1991 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001992errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001993 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001994 nlmsg_cancel(skb, nlh);
1995 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001996}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001997
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001998static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f86742006-08-07 17:58:53 -07001999 [NDTA_NAME] = { .type = NLA_STRING },
2000 [NDTA_THRESH1] = { .type = NLA_U32 },
2001 [NDTA_THRESH2] = { .type = NLA_U32 },
2002 [NDTA_THRESH3] = { .type = NLA_U32 },
2003 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
2004 [NDTA_PARMS] = { .type = NLA_NESTED },
2005};
2006
Patrick McHardyef7c79e2007-06-05 12:38:30 -07002007static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f86742006-08-07 17:58:53 -07002008 [NDTPA_IFINDEX] = { .type = NLA_U32 },
2009 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
2010 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
2011 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
2012 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
2013 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002014 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f86742006-08-07 17:58:53 -07002015 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
2016 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
2017 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
2018 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
2019 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
2020 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
2021 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
2022};
2023
David Ahernc21ef3e2017-04-16 09:48:24 -07002024static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
2025 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002026{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002027 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002028 struct neigh_table *tbl;
Thomas Graf6b3f86742006-08-07 17:58:53 -07002029 struct ndtmsg *ndtmsg;
2030 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08002031 bool found = false;
2032 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002033
Thomas Graf6b3f86742006-08-07 17:58:53 -07002034 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07002035 nl_neightbl_policy, extack);
Thomas Graf6b3f86742006-08-07 17:58:53 -07002036 if (err < 0)
2037 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002038
Thomas Graf6b3f86742006-08-07 17:58:53 -07002039 if (tb[NDTA_NAME] == NULL) {
2040 err = -EINVAL;
2041 goto errout;
2042 }
2043
2044 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002045
2046 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2047 tbl = neigh_tables[tidx];
2048 if (!tbl)
2049 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002050 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2051 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002052 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2053 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002054 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002055 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002056 }
2057
WANG Congd7480fd2014-11-10 15:59:36 -08002058 if (!found)
2059 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002060
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002061 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002062 * We acquire tbl->lock to be nice to the periodic timers and
2063 * make sure they always see a consistent set of values.
2064 */
2065 write_lock_bh(&tbl->lock);
2066
Thomas Graf6b3f86742006-08-07 17:58:53 -07002067 if (tb[NDTA_PARMS]) {
2068 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002069 struct neigh_parms *p;
Thomas Graf6b3f86742006-08-07 17:58:53 -07002070 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002071
Thomas Graf6b3f86742006-08-07 17:58:53 -07002072 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002073 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f86742006-08-07 17:58:53 -07002074 if (err < 0)
2075 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002076
Thomas Graf6b3f86742006-08-07 17:58:53 -07002077 if (tbp[NDTPA_IFINDEX])
2078 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002079
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002080 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002081 if (p == NULL) {
2082 err = -ENOENT;
Thomas Graf6b3f86742006-08-07 17:58:53 -07002083 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002084 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002085
Thomas Graf6b3f86742006-08-07 17:58:53 -07002086 for (i = 1; i <= NDTPA_MAX; i++) {
2087 if (tbp[i] == NULL)
2088 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002089
Thomas Graf6b3f86742006-08-07 17:58:53 -07002090 switch (i) {
2091 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002092 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2093 nla_get_u32(tbp[i]) *
2094 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002095 break;
2096 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002097 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2098 nla_get_u32(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002099 break;
2100 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002101 NEIGH_VAR_SET(p, PROXY_QLEN,
2102 nla_get_u32(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002103 break;
2104 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002105 NEIGH_VAR_SET(p, APP_PROBES,
2106 nla_get_u32(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002107 break;
2108 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002109 NEIGH_VAR_SET(p, UCAST_PROBES,
2110 nla_get_u32(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002111 break;
2112 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002113 NEIGH_VAR_SET(p, MCAST_PROBES,
2114 nla_get_u32(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002115 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002116 case NDTPA_MCAST_REPROBES:
2117 NEIGH_VAR_SET(p, MCAST_REPROBES,
2118 nla_get_u32(tbp[i]));
2119 break;
Thomas Graf6b3f86742006-08-07 17:58:53 -07002120 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002121 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2122 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002123 /* update reachable_time as well, otherwise, the change will
2124 * only be effective after the next time neigh_periodic_work
2125 * decides to recompute it (can be multiple minutes)
2126 */
2127 p->reachable_time =
2128 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002129 break;
2130 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002131 NEIGH_VAR_SET(p, GC_STALETIME,
2132 nla_get_msecs(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002133 break;
2134 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002135 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2136 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002137 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f86742006-08-07 17:58:53 -07002138 break;
2139 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002140 NEIGH_VAR_SET(p, RETRANS_TIME,
2141 nla_get_msecs(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002142 break;
2143 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002144 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2145 nla_get_msecs(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002146 break;
2147 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002148 NEIGH_VAR_SET(p, PROXY_DELAY,
2149 nla_get_msecs(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002150 break;
2151 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002152 NEIGH_VAR_SET(p, LOCKTIME,
2153 nla_get_msecs(tbp[i]));
Thomas Graf6b3f86742006-08-07 17:58:53 -07002154 break;
2155 }
2156 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002157 }
2158
Gao fengdc25c672013-06-20 10:01:34 +08002159 err = -ENOENT;
2160 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2161 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2162 !net_eq(net, &init_net))
2163 goto errout_tbl_lock;
2164
Thomas Graf6b3f86742006-08-07 17:58:53 -07002165 if (tb[NDTA_THRESH1])
2166 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2167
2168 if (tb[NDTA_THRESH2])
2169 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2170
2171 if (tb[NDTA_THRESH3])
2172 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2173
2174 if (tb[NDTA_GC_INTERVAL])
2175 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2176
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002177 err = 0;
2178
Thomas Graf6b3f86742006-08-07 17:58:53 -07002179errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f86742006-08-07 17:58:53 -07002181errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002182 return err;
2183}
2184
David Ahern9632d472018-10-07 20:16:37 -07002185static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
2186 struct netlink_ext_ack *extack)
2187{
2188 struct ndtmsg *ndtm;
2189
2190 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndtm))) {
2191 NL_SET_ERR_MSG(extack, "Invalid header for neighbor table dump request");
2192 return -EINVAL;
2193 }
2194
2195 ndtm = nlmsg_data(nlh);
2196 if (ndtm->ndtm_pad1 || ndtm->ndtm_pad2) {
2197 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor table dump request");
2198 return -EINVAL;
2199 }
2200
2201 if (nlmsg_attrlen(nlh, sizeof(*ndtm))) {
2202 NL_SET_ERR_MSG(extack, "Invalid data after header in neighbor table dump request");
2203 return -EINVAL;
2204 }
2205
2206 return 0;
2207}
2208
Thomas Grafc8822a42007-03-22 11:50:06 -07002209static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002210{
David Ahern9632d472018-10-07 20:16:37 -07002211 const struct nlmsghdr *nlh = cb->nlh;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002212 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002213 int family, tidx, nidx = 0;
2214 int tbl_skip = cb->args[0];
2215 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002216 struct neigh_table *tbl;
2217
David Ahern9632d472018-10-07 20:16:37 -07002218 if (cb->strict_check) {
2219 int err = neightbl_valid_dump_info(nlh, cb->extack);
2220
2221 if (err < 0)
2222 return err;
2223 }
2224
2225 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002226
WANG Congd7480fd2014-11-10 15:59:36 -08002227 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002228 struct neigh_parms *p;
2229
WANG Congd7480fd2014-11-10 15:59:36 -08002230 tbl = neigh_tables[tidx];
2231 if (!tbl)
2232 continue;
2233
Thomas Grafca860fb2006-08-07 18:00:18 -07002234 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002235 continue;
2236
Eric W. Biederman15e47302012-09-07 20:12:54 +00002237 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002238 nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002239 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002240 break;
2241
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002242 nidx = 0;
2243 p = list_next_entry(&tbl->parms, list);
2244 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002245 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002246 continue;
2247
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002248 if (nidx < neigh_skip)
2249 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002250
Thomas Grafca860fb2006-08-07 18:00:18 -07002251 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002252 NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002253 nlh->nlmsg_seq,
Thomas Grafca860fb2006-08-07 18:00:18 -07002254 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002255 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002256 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002257 next:
2258 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002259 }
2260
Thomas Grafca860fb2006-08-07 18:00:18 -07002261 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002262 }
2263out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002264 cb->args[0] = tidx;
2265 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002266
2267 return skb->len;
2268}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002269
Thomas Graf8b8aec52006-08-07 17:56:37 -07002270static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2271 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272{
2273 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002275 struct nlmsghdr *nlh;
2276 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277
Thomas Graf8b8aec52006-08-07 17:56:37 -07002278 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2279 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002280 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002281
2282 ndm = nlmsg_data(nlh);
2283 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002284 ndm->ndm_pad1 = 0;
2285 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002286 ndm->ndm_flags = neigh->flags;
2287 ndm->ndm_type = neigh->type;
2288 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002289
David S. Miller9a6308d2012-04-01 20:06:28 -04002290 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2291 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002292
2293 read_lock_bh(&neigh->lock);
2294 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002295 if (neigh->nud_state & NUD_VALID) {
2296 char haddr[MAX_ADDR_LEN];
2297
2298 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2299 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2300 read_unlock_bh(&neigh->lock);
2301 goto nla_put_failure;
2302 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002303 }
2304
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002305 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2306 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2307 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002308 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002309 read_unlock_bh(&neigh->lock);
2310
David S. Miller9a6308d2012-04-01 20:06:28 -04002311 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2312 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2313 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002314
Johannes Berg053c0952015-01-16 22:09:00 +01002315 nlmsg_end(skb, nlh);
2316 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002317
2318nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002319 nlmsg_cancel(skb, nlh);
2320 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321}
2322
Tony Zelenoff84920c12012-01-26 22:28:58 +00002323static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2324 u32 pid, u32 seq, int type, unsigned int flags,
2325 struct neigh_table *tbl)
2326{
2327 struct nlmsghdr *nlh;
2328 struct ndmsg *ndm;
2329
2330 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2331 if (nlh == NULL)
2332 return -EMSGSIZE;
2333
2334 ndm = nlmsg_data(nlh);
2335 ndm->ndm_family = tbl->family;
2336 ndm->ndm_pad1 = 0;
2337 ndm->ndm_pad2 = 0;
2338 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002339 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002340 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002341 ndm->ndm_state = NUD_NONE;
2342
David S. Miller9a6308d2012-04-01 20:06:28 -04002343 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2344 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002345
Johannes Berg053c0952015-01-16 22:09:00 +01002346 nlmsg_end(skb, nlh);
2347 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002348
2349nla_put_failure:
2350 nlmsg_cancel(skb, nlh);
2351 return -EMSGSIZE;
2352}
2353
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002354static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002355{
2356 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002357 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002358}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359
David Ahern21fdd092015-09-29 09:32:03 -07002360static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2361{
2362 struct net_device *master;
2363
2364 if (!master_idx)
2365 return false;
2366
Eric Dumazetaab456d2018-10-26 09:33:27 -07002367 master = dev ? netdev_master_upper_dev_get(dev) : NULL;
David Ahern21fdd092015-09-29 09:32:03 -07002368 if (!master || master->ifindex != master_idx)
2369 return true;
2370
2371 return false;
2372}
2373
David Ahern16660f02015-10-03 11:43:46 -07002374static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2375{
Eric Dumazetaab456d2018-10-26 09:33:27 -07002376 if (filter_idx && (!dev || dev->ifindex != filter_idx))
David Ahern16660f02015-10-03 11:43:46 -07002377 return true;
2378
2379 return false;
2380}
2381
David Ahern6f52f802018-10-03 15:33:12 -07002382struct neigh_dump_filter {
2383 int master_idx;
2384 int dev_idx;
2385};
2386
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002388 struct netlink_callback *cb,
2389 struct neigh_dump_filter *filter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002391 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392 struct neighbour *n;
2393 int rc, h, s_h = cb->args[1];
2394 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002395 struct neigh_hash_table *nht;
David Ahern21fdd092015-09-29 09:32:03 -07002396 unsigned int flags = NLM_F_MULTI;
David Ahern21fdd092015-09-29 09:32:03 -07002397
David Ahern6f52f802018-10-03 15:33:12 -07002398 if (filter->dev_idx || filter->master_idx)
2399 flags |= NLM_F_DUMP_FILTERED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002401 rcu_read_lock_bh();
2402 nht = rcu_dereference_bh(tbl->nht);
2403
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002404 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 if (h > s_h)
2406 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002407 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2408 n != NULL;
2409 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002410 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2411 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002412 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2413 neigh_master_filtered(n->dev, filter->master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002414 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002415 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002416 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002417 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002418 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 rc = -1;
2420 goto out;
2421 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002422next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002423 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 }
2426 rc = skb->len;
2427out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002428 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 cb->args[1] = h;
2430 cb->args[2] = idx;
2431 return rc;
2432}
2433
Tony Zelenoff84920c12012-01-26 22:28:58 +00002434static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002435 struct netlink_callback *cb,
2436 struct neigh_dump_filter *filter)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002437{
2438 struct pneigh_entry *n;
2439 struct net *net = sock_net(skb->sk);
2440 int rc, h, s_h = cb->args[3];
2441 int idx, s_idx = idx = cb->args[4];
David Ahern6f52f802018-10-03 15:33:12 -07002442 unsigned int flags = NLM_F_MULTI;
2443
2444 if (filter->dev_idx || filter->master_idx)
2445 flags |= NLM_F_DUMP_FILTERED;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002446
2447 read_lock_bh(&tbl->lock);
2448
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002449 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002450 if (h > s_h)
2451 s_idx = 0;
2452 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002453 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002454 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002455 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2456 neigh_master_filtered(n->dev, filter->master_idx))
2457 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002458 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002459 cb->nlh->nlmsg_seq,
David Ahern6f52f802018-10-03 15:33:12 -07002460 RTM_NEWNEIGH, flags, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002461 read_unlock_bh(&tbl->lock);
2462 rc = -1;
2463 goto out;
2464 }
2465 next:
2466 idx++;
2467 }
2468 }
2469
2470 read_unlock_bh(&tbl->lock);
2471 rc = skb->len;
2472out:
2473 cb->args[3] = h;
2474 cb->args[4] = idx;
2475 return rc;
2476
2477}
2478
David Ahern51183d22018-10-07 20:16:36 -07002479static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
2480 bool strict_check,
2481 struct neigh_dump_filter *filter,
2482 struct netlink_ext_ack *extack)
2483{
2484 struct nlattr *tb[NDA_MAX + 1];
2485 int err, i;
2486
2487 if (strict_check) {
2488 struct ndmsg *ndm;
2489
2490 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2491 NL_SET_ERR_MSG(extack, "Invalid header for neighbor dump request");
2492 return -EINVAL;
2493 }
2494
2495 ndm = nlmsg_data(nlh);
2496 if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_ifindex ||
2497 ndm->ndm_state || ndm->ndm_flags || ndm->ndm_type) {
2498 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor dump request");
2499 return -EINVAL;
2500 }
2501
2502 err = nlmsg_parse_strict(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
2503 NULL, extack);
2504 } else {
2505 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
2506 NULL, extack);
2507 }
2508 if (err < 0)
2509 return err;
2510
2511 for (i = 0; i <= NDA_MAX; ++i) {
2512 if (!tb[i])
2513 continue;
2514
2515 /* all new attributes should require strict_check */
2516 switch (i) {
2517 case NDA_IFINDEX:
2518 if (nla_len(tb[i]) != sizeof(u32)) {
2519 NL_SET_ERR_MSG(extack, "Invalid IFINDEX attribute in neighbor dump request");
2520 return -EINVAL;
2521 }
2522 filter->dev_idx = nla_get_u32(tb[i]);
2523 break;
2524 case NDA_MASTER:
2525 if (nla_len(tb[i]) != sizeof(u32)) {
2526 NL_SET_ERR_MSG(extack, "Invalid MASTER attribute in neighbor dump request");
2527 return -EINVAL;
2528 }
2529 filter->master_idx = nla_get_u32(tb[i]);
2530 break;
2531 default:
2532 if (strict_check) {
2533 NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor dump request");
2534 return -EINVAL;
2535 }
2536 }
2537 }
2538
2539 return 0;
2540}
2541
Thomas Grafc8822a42007-03-22 11:50:06 -07002542static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
David Ahern6f52f802018-10-03 15:33:12 -07002544 const struct nlmsghdr *nlh = cb->nlh;
2545 struct neigh_dump_filter filter = {};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 struct neigh_table *tbl;
2547 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002548 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002549 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550
David Ahern6f52f802018-10-03 15:33:12 -07002551 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002552
2553 /* check for full ndmsg structure presence, family member is
2554 * the same for both structures
2555 */
David Ahern6f52f802018-10-03 15:33:12 -07002556 if (nlmsg_len(nlh) >= sizeof(struct ndmsg) &&
2557 ((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002558 proxy = 1;
2559
David Ahern51183d22018-10-07 20:16:36 -07002560 err = neigh_valid_dump_req(nlh, cb->strict_check, &filter, cb->extack);
2561 if (err < 0 && cb->strict_check)
2562 return err;
2563
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 s_t = cb->args[0];
2565
WANG Congd7480fd2014-11-10 15:59:36 -08002566 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2567 tbl = neigh_tables[t];
2568
2569 if (!tbl)
2570 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 if (t < s_t || (family && tbl->family != family))
2572 continue;
2573 if (t > s_t)
2574 memset(&cb->args[1], 0, sizeof(cb->args) -
2575 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002576 if (proxy)
David Ahern6f52f802018-10-03 15:33:12 -07002577 err = pneigh_dump_table(tbl, skb, cb, &filter);
Tony Zelenoff84920c12012-01-26 22:28:58 +00002578 else
David Ahern6f52f802018-10-03 15:33:12 -07002579 err = neigh_dump_table(tbl, skb, cb, &filter);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002580 if (err < 0)
2581 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583
2584 cb->args[0] = t;
2585 return skb->len;
2586}
2587
2588void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2589{
2590 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002591 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002593 rcu_read_lock_bh();
2594 nht = rcu_dereference_bh(tbl->nht);
2595
Eric Dumazet767e97e2010-10-06 17:49:21 -07002596 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002597 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598 struct neighbour *n;
2599
Eric Dumazet767e97e2010-10-06 17:49:21 -07002600 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2601 n != NULL;
2602 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 cb(n, cookie);
2604 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002605 read_unlock(&tbl->lock);
2606 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607}
2608EXPORT_SYMBOL(neigh_for_each);
2609
2610/* The tbl->lock must be held as a writer and BH disabled. */
2611void __neigh_for_each_release(struct neigh_table *tbl,
2612 int (*cb)(struct neighbour *))
2613{
2614 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002615 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002617 nht = rcu_dereference_protected(tbl->nht,
2618 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002619 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002620 struct neighbour *n;
2621 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002623 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002624 while ((n = rcu_dereference_protected(*np,
2625 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002626 int release;
2627
2628 write_lock(&n->lock);
2629 release = cb(n);
2630 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002631 rcu_assign_pointer(*np,
2632 rcu_dereference_protected(n->next,
2633 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 n->dead = 1;
2635 } else
2636 np = &n->next;
2637 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002638 if (release)
2639 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640 }
2641 }
2642}
2643EXPORT_SYMBOL(__neigh_for_each_release);
2644
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002645int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002646 const void *addr, struct sk_buff *skb)
2647{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002648 int err = -EAFNOSUPPORT;
2649 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002650 struct neigh_table *tbl;
2651 struct neighbour *neigh;
2652
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002653 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002654 if (!tbl)
2655 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002656 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002657 neigh = __neigh_lookup_noref(tbl, addr, dev);
2658 if (!neigh)
2659 neigh = __neigh_create(tbl, addr, dev, false);
2660 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002661 if (IS_ERR(neigh)) {
2662 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002663 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002664 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002665 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002666 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002667 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002668 else if (index == NEIGH_LINK_TABLE) {
2669 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2670 addr, NULL, skb->len);
2671 if (err < 0)
2672 goto out_kfree_skb;
2673 err = dev_queue_xmit(skb);
2674 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002675out:
2676 return err;
2677out_kfree_skb:
2678 kfree_skb(skb);
2679 goto out;
2680}
2681EXPORT_SYMBOL(neigh_xmit);
2682
Linus Torvalds1da177e2005-04-16 15:20:36 -07002683#ifdef CONFIG_PROC_FS
2684
2685static struct neighbour *neigh_get_first(struct seq_file *seq)
2686{
2687 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002688 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002689 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690 struct neighbour *n = NULL;
2691 int bucket = state->bucket;
2692
2693 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002694 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002695 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002696
2697 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002698 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002699 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 if (state->neigh_sub_iter) {
2701 loff_t fakep = 0;
2702 void *v;
2703
2704 v = state->neigh_sub_iter(state, n, &fakep);
2705 if (!v)
2706 goto next;
2707 }
2708 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2709 break;
2710 if (n->nud_state & ~NUD_NOARP)
2711 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002712next:
2713 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714 }
2715
2716 if (n)
2717 break;
2718 }
2719 state->bucket = bucket;
2720
2721 return n;
2722}
2723
2724static struct neighbour *neigh_get_next(struct seq_file *seq,
2725 struct neighbour *n,
2726 loff_t *pos)
2727{
2728 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002729 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002730 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731
2732 if (state->neigh_sub_iter) {
2733 void *v = state->neigh_sub_iter(state, n, pos);
2734 if (v)
2735 return n;
2736 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002737 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002738
2739 while (1) {
2740 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002741 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002742 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 if (state->neigh_sub_iter) {
2744 void *v = state->neigh_sub_iter(state, n, pos);
2745 if (v)
2746 return n;
2747 goto next;
2748 }
2749 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2750 break;
2751
2752 if (n->nud_state & ~NUD_NOARP)
2753 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002754next:
2755 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002756 }
2757
2758 if (n)
2759 break;
2760
David S. Millercd089332011-07-11 01:28:12 -07002761 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002762 break;
2763
Eric Dumazet767e97e2010-10-06 17:49:21 -07002764 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002765 }
2766
2767 if (n && pos)
2768 --(*pos);
2769 return n;
2770}
2771
2772static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2773{
2774 struct neighbour *n = neigh_get_first(seq);
2775
2776 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002777 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 while (*pos) {
2779 n = neigh_get_next(seq, n, pos);
2780 if (!n)
2781 break;
2782 }
2783 }
2784 return *pos ? NULL : n;
2785}
2786
2787static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2788{
2789 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002790 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002791 struct neigh_table *tbl = state->tbl;
2792 struct pneigh_entry *pn = NULL;
2793 int bucket = state->bucket;
2794
2795 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2796 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2797 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002798 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002799 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800 if (pn)
2801 break;
2802 }
2803 state->bucket = bucket;
2804
2805 return pn;
2806}
2807
2808static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2809 struct pneigh_entry *pn,
2810 loff_t *pos)
2811{
2812 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002813 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 struct neigh_table *tbl = state->tbl;
2815
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002816 do {
2817 pn = pn->next;
2818 } while (pn && !net_eq(pneigh_net(pn), net));
2819
Linus Torvalds1da177e2005-04-16 15:20:36 -07002820 while (!pn) {
2821 if (++state->bucket > PNEIGH_HASHMASK)
2822 break;
2823 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002824 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002825 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002826 if (pn)
2827 break;
2828 }
2829
2830 if (pn && pos)
2831 --(*pos);
2832
2833 return pn;
2834}
2835
2836static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2837{
2838 struct pneigh_entry *pn = pneigh_get_first(seq);
2839
2840 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002841 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 while (*pos) {
2843 pn = pneigh_get_next(seq, pn, pos);
2844 if (!pn)
2845 break;
2846 }
2847 }
2848 return *pos ? NULL : pn;
2849}
2850
2851static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2852{
2853 struct neigh_seq_state *state = seq->private;
2854 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002855 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
Chris Larson745e2032008-08-03 01:10:55 -07002857 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002858 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002859 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860
2861 return rc;
2862}
2863
2864void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002865 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866{
2867 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868
2869 state->tbl = tbl;
2870 state->bucket = 0;
2871 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2872
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002873 rcu_read_lock_bh();
2874 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002875
Chris Larson745e2032008-08-03 01:10:55 -07002876 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002877}
2878EXPORT_SYMBOL(neigh_seq_start);
2879
2880void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2881{
2882 struct neigh_seq_state *state;
2883 void *rc;
2884
2885 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002886 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887 goto out;
2888 }
2889
2890 state = seq->private;
2891 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2892 rc = neigh_get_next(seq, v, NULL);
2893 if (rc)
2894 goto out;
2895 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2896 rc = pneigh_get_first(seq);
2897 } else {
2898 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2899 rc = pneigh_get_next(seq, v, NULL);
2900 }
2901out:
2902 ++(*pos);
2903 return rc;
2904}
2905EXPORT_SYMBOL(neigh_seq_next);
2906
2907void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002908 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002910 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911}
2912EXPORT_SYMBOL(neigh_seq_stop);
2913
2914/* statistics via seq_file */
2915
2916static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2917{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002918 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919 int cpu;
2920
2921 if (*pos == 0)
2922 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002923
Rusty Russell0f23174a2008-12-29 12:23:42 +00002924 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925 if (!cpu_possible(cpu))
2926 continue;
2927 *pos = cpu+1;
2928 return per_cpu_ptr(tbl->stats, cpu);
2929 }
2930 return NULL;
2931}
2932
2933static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2934{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002935 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002936 int cpu;
2937
Rusty Russell0f23174a2008-12-29 12:23:42 +00002938 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002939 if (!cpu_possible(cpu))
2940 continue;
2941 *pos = cpu+1;
2942 return per_cpu_ptr(tbl->stats, cpu);
2943 }
2944 return NULL;
2945}
2946
2947static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2948{
2949
2950}
2951
2952static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2953{
Christoph Hellwig71a50532018-04-15 10:16:41 +02002954 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 struct neigh_statistics *st = v;
2956
2957 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002958 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 -07002959 return 0;
2960 }
2961
2962 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002963 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002964 atomic_read(&tbl->entries),
2965
2966 st->allocs,
2967 st->destroys,
2968 st->hash_grows,
2969
2970 st->lookups,
2971 st->hits,
2972
2973 st->res_failed,
2974
2975 st->rcv_probes_mcast,
2976 st->rcv_probes_ucast,
2977
2978 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002979 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002980 st->unres_discards,
2981 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002982 );
2983
2984 return 0;
2985}
2986
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002987static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002988 .start = neigh_stat_seq_start,
2989 .next = neigh_stat_seq_next,
2990 .stop = neigh_stat_seq_stop,
2991 .show = neigh_stat_seq_show,
2992};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993#endif /* CONFIG_PROC_FS */
2994
Thomas Graf339bf982006-11-10 14:10:15 -08002995static inline size_t neigh_nlmsg_size(void)
2996{
2997 return NLMSG_ALIGN(sizeof(struct ndmsg))
2998 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2999 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
3000 + nla_total_size(sizeof(struct nda_cacheinfo))
3001 + nla_total_size(4); /* NDA_PROBES */
3002}
3003
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003004static void __neigh_notify(struct neighbour *n, int type, int flags,
3005 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003006{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003007 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003008 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07003009 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003010
Thomas Graf339bf982006-11-10 14:10:15 -08003011 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003012 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07003013 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003015 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08003016 if (err < 0) {
3017 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
3018 WARN_ON(err == -EMSGSIZE);
3019 kfree_skb(skb);
3020 goto errout;
3021 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08003022 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
3023 return;
Thomas Grafb8673312006-08-15 00:33:14 -07003024errout:
3025 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08003026 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07003027}
3028
3029void neigh_app_ns(struct neighbour *n)
3030{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003031 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003033EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034
3035#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08003036static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02003037static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08003038static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
Joe Perchesfe2c6332013-06-11 23:04:25 -07003040static int proc_unres_qlen(struct ctl_table *ctl, int write,
3041 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003042{
3043 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07003044 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003045
Shan Weice46cc62012-12-04 18:49:15 +00003046 tmp.extra1 = &zero;
3047 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003048 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00003049
3050 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
3051 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3052
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003053 if (write && !ret)
3054 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
3055 return ret;
3056}
3057
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003058static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
3059 int family)
3060{
Jiri Pirkobba24892013-12-07 19:26:57 +01003061 switch (family) {
3062 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003063 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01003064 case AF_INET6:
3065 return __in6_dev_nd_parms_get_rcu(dev);
3066 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003067 return NULL;
3068}
3069
3070static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
3071 int index)
3072{
3073 struct net_device *dev;
3074 int family = neigh_parms_family(p);
3075
3076 rcu_read_lock();
3077 for_each_netdev_rcu(net, dev) {
3078 struct neigh_parms *dst_p =
3079 neigh_get_dev_parms_rcu(dev, family);
3080
3081 if (dst_p && !test_bit(index, dst_p->data_state))
3082 dst_p->data[index] = p->data[index];
3083 }
3084 rcu_read_unlock();
3085}
3086
3087static void neigh_proc_update(struct ctl_table *ctl, int write)
3088{
3089 struct net_device *dev = ctl->extra1;
3090 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01003091 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003092 int index = (int *) ctl->data - p->data;
3093
3094 if (!write)
3095 return;
3096
3097 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01003098 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
3099 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003100 if (!dev) /* NULL dev means this is default value */
3101 neigh_copy_dflt_parms(net, p, index);
3102}
3103
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003104static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3105 void __user *buffer,
3106 size_t *lenp, loff_t *ppos)
3107{
3108 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003109 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003110
3111 tmp.extra1 = &zero;
3112 tmp.extra2 = &int_max;
3113
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003114 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3115 neigh_proc_update(ctl, write);
3116 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003117}
3118
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003119int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3120 void __user *buffer, size_t *lenp, loff_t *ppos)
3121{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003122 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3123
3124 neigh_proc_update(ctl, write);
3125 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003126}
3127EXPORT_SYMBOL(neigh_proc_dointvec);
3128
3129int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3130 void __user *buffer,
3131 size_t *lenp, loff_t *ppos)
3132{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003133 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3134
3135 neigh_proc_update(ctl, write);
3136 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003137}
3138EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3139
3140static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3141 void __user *buffer,
3142 size_t *lenp, loff_t *ppos)
3143{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003144 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3145
3146 neigh_proc_update(ctl, write);
3147 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003148}
3149
3150int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3151 void __user *buffer,
3152 size_t *lenp, loff_t *ppos)
3153{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003154 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3155
3156 neigh_proc_update(ctl, write);
3157 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003158}
3159EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3160
3161static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3162 void __user *buffer,
3163 size_t *lenp, loff_t *ppos)
3164{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003165 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3166
3167 neigh_proc_update(ctl, write);
3168 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003169}
3170
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003171static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3172 void __user *buffer,
3173 size_t *lenp, loff_t *ppos)
3174{
3175 struct neigh_parms *p = ctl->extra2;
3176 int ret;
3177
3178 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3179 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3180 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3181 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3182 else
3183 ret = -1;
3184
3185 if (write && ret == 0) {
3186 /* update reachable_time as well, otherwise, the change will
3187 * only be effective after the next time neigh_periodic_work
3188 * decides to recompute it
3189 */
3190 p->reachable_time =
3191 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3192 }
3193 return ret;
3194}
3195
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003196#define NEIGH_PARMS_DATA_OFFSET(index) \
3197 (&((struct neigh_parms *) 0)->data[index])
3198
3199#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3200 [NEIGH_VAR_ ## attr] = { \
3201 .procname = name, \
3202 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3203 .maxlen = sizeof(int), \
3204 .mode = mval, \
3205 .proc_handler = proc, \
3206 }
3207
3208#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3209 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3210
3211#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003212 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003213
3214#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003215 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003216
3217#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003218 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003219
3220#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003221 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003222
3223#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003224 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003225
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226static struct neigh_sysctl_table {
3227 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003228 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003229} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003231 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3232 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3233 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003234 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003235 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3236 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3237 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3238 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3239 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3240 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3241 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3242 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3243 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3244 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3245 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3246 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003247 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 .procname = "gc_interval",
3249 .maxlen = sizeof(int),
3250 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003251 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003252 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003253 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 .procname = "gc_thresh1",
3255 .maxlen = sizeof(int),
3256 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003257 .extra1 = &zero,
3258 .extra2 = &int_max,
3259 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003261 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 .procname = "gc_thresh2",
3263 .maxlen = sizeof(int),
3264 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003265 .extra1 = &zero,
3266 .extra2 = &int_max,
3267 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003268 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003269 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003270 .procname = "gc_thresh3",
3271 .maxlen = sizeof(int),
3272 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003273 .extra1 = &zero,
3274 .extra2 = &int_max,
3275 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003277 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003278 },
3279};
3280
3281int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003282 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003283{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003284 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003285 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003286 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003287 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003288 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003290 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003291 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003292 goto err;
3293
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003294 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003295 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003296 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003297 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299
3300 if (dev) {
3301 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003302 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003303 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3304 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003306 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003307 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003308 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3309 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3310 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3311 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003312 }
3313
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003314 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003316 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003318 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003320 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003322 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003323 } else {
3324 /* Those handlers will update p->reachable_time after
3325 * base_reachable_time(_ms) is set to ensure the new timer starts being
3326 * applied after the next neighbour update instead of waiting for
3327 * neigh_periodic_work to update its value (can be multiple minutes)
3328 * So any handler that replaces them should do this as well
3329 */
3330 /* ReachableTime */
3331 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3332 neigh_proc_base_reachable_time;
3333 /* ReachableTime (in milliseconds) */
3334 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3335 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003336 }
3337
Eric W. Biederman464dc802012-11-16 03:02:59 +00003338 /* Don't export sysctls to unprivileged users */
3339 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3340 t->neigh_vars[0].procname = NULL;
3341
Jiri Pirko73af6142013-12-07 19:26:55 +01003342 switch (neigh_parms_family(p)) {
3343 case AF_INET:
3344 p_name = "ipv4";
3345 break;
3346 case AF_INET6:
3347 p_name = "ipv6";
3348 break;
3349 default:
3350 BUG();
3351 }
3352
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003353 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3354 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003355 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003356 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003357 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003358 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003359
Linus Torvalds1da177e2005-04-16 15:20:36 -07003360 p->sysctl_table = t;
3361 return 0;
3362
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003363free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003365err:
3366 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003367}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003368EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003369
3370void neigh_sysctl_unregister(struct neigh_parms *p)
3371{
3372 if (p->sysctl_table) {
3373 struct neigh_sysctl_table *t = p->sysctl_table;
3374 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003375 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003376 kfree(t);
3377 }
3378}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003379EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003380
3381#endif /* CONFIG_SYSCTL */
3382
Thomas Grafc8822a42007-03-22 11:50:06 -07003383static int __init neigh_init(void)
3384{
Florian Westphalb97bac62017-08-09 20:41:48 +02003385 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3386 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
3387 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003388
Greg Rosec7ac8672011-06-10 01:27:09 +00003389 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003390 0);
3391 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003392
3393 return 0;
3394}
3395
3396subsys_initcall(neigh_init);