blob: 5afae29367c1b75b80b7cdb4194b66a0fd49b487 [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
Arjan van de Ven9a321442007-02-12 00:55:35 -080062static const struct file_operations neigh_stat_seq_fops;
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
Sowmini Varadhan50710342017-06-02 09:01:49 -0700122static bool neigh_del(struct neighbour *n, __u8 state,
123 struct neighbour __rcu **np, struct neigh_table *tbl)
124{
125 bool retval = false;
126
127 write_lock(&n->lock);
Reshetova, Elena9f237432017-06-30 13:07:55 +0300128 if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700129 struct neighbour *neigh;
130
131 neigh = rcu_dereference_protected(n->next,
132 lockdep_is_held(&tbl->lock));
133 rcu_assign_pointer(*np, neigh);
134 n->dead = 1;
135 retval = true;
136 }
137 write_unlock(&n->lock);
138 if (retval)
139 neigh_cleanup_and_release(n);
140 return retval;
141}
142
143bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
144{
145 struct neigh_hash_table *nht;
146 void *pkey = ndel->primary_key;
147 u32 hash_val;
148 struct neighbour *n;
149 struct neighbour __rcu **np;
150
151 nht = rcu_dereference_protected(tbl->nht,
152 lockdep_is_held(&tbl->lock));
153 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
154 hash_val = hash_val >> (32 - nht->hash_shift);
155
156 np = &nht->hash_buckets[hash_val];
157 while ((n = rcu_dereference_protected(*np,
158 lockdep_is_held(&tbl->lock)))) {
159 if (n == ndel)
160 return neigh_del(n, 0, np, tbl);
161 np = &n->next;
162 }
163 return false;
164}
165
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166static int neigh_forced_gc(struct neigh_table *tbl)
167{
168 int shrunk = 0;
169 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000170 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
173
174 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000175 nht = rcu_dereference_protected(tbl->nht,
176 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700177 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700178 struct neighbour *n;
179 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000181 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700182 while ((n = rcu_dereference_protected(*np,
183 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 /* Neighbour record may be discarded if:
185 * - nobody refers to it.
186 * - it is not permanent
187 */
Sowmini Varadhan50710342017-06-02 09:01:49 -0700188 if (neigh_del(n, NUD_PERMANENT, np, tbl)) {
189 shrunk = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 continue;
191 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 np = &n->next;
193 }
194 }
195
196 tbl->last_flush = jiffies;
197
198 write_unlock_bh(&tbl->lock);
199
200 return shrunk;
201}
202
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800203static void neigh_add_timer(struct neighbour *n, unsigned long when)
204{
205 neigh_hold(n);
206 if (unlikely(mod_timer(&n->timer, when))) {
207 printk("NEIGH: BUG, double timer add, state is %x\n",
208 n->nud_state);
209 dump_stack();
210 }
211}
212
Linus Torvalds1da177e2005-04-16 15:20:36 -0700213static int neigh_del_timer(struct neighbour *n)
214{
215 if ((n->nud_state & NUD_IN_TIMER) &&
216 del_timer(&n->timer)) {
217 neigh_release(n);
218 return 1;
219 }
220 return 0;
221}
222
223static void pneigh_queue_purge(struct sk_buff_head *list)
224{
225 struct sk_buff *skb;
226
227 while ((skb = skb_dequeue(list)) != NULL) {
228 dev_put(skb->dev);
229 kfree_skb(skb);
230 }
231}
232
Herbert Xu49636bb2005-10-23 17:18:00 +1000233static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234{
235 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000236 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000238 nht = rcu_dereference_protected(tbl->nht,
239 lockdep_is_held(&tbl->lock));
240
David S. Millercd089332011-07-11 01:28:12 -0700241 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700242 struct neighbour *n;
243 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700244
Eric Dumazet767e97e2010-10-06 17:49:21 -0700245 while ((n = rcu_dereference_protected(*np,
246 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700247 if (dev && n->dev != dev) {
248 np = &n->next;
249 continue;
250 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700251 rcu_assign_pointer(*np,
252 rcu_dereference_protected(n->next,
253 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700254 write_lock(&n->lock);
255 neigh_del_timer(n);
256 n->dead = 1;
257
Reshetova, Elena9f237432017-06-30 13:07:55 +0300258 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 /* The most unpleasant situation.
260 We must destroy neighbour entry,
261 but someone still uses it.
262
263 The destroy will be delayed until
264 the last user releases us, but
265 we must kill timers etc. and move
266 it to safe state.
267 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700268 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000269 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 n->output = neigh_blackhole;
271 if (n->nud_state & NUD_VALID)
272 n->nud_state = NUD_NOARP;
273 else
274 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000275 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700276 }
277 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700278 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700279 }
280 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000281}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282
Herbert Xu49636bb2005-10-23 17:18:00 +1000283void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
284{
285 write_lock_bh(&tbl->lock);
286 neigh_flush_dev(tbl, dev);
287 write_unlock_bh(&tbl->lock);
288}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900289EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000290
291int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
292{
293 write_lock_bh(&tbl->lock);
294 neigh_flush_dev(tbl, dev);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200295 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700296
297 del_timer_sync(&tbl->proxy_timer);
298 pneigh_queue_purge(&tbl->proxy_queue);
299 return 0;
300}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900301EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
David Miller596b9b62011-07-25 00:01:25 +0000303static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
305 struct neighbour *n = NULL;
306 unsigned long now = jiffies;
307 int entries;
308
309 entries = atomic_inc_return(&tbl->entries) - 1;
310 if (entries >= tbl->gc_thresh3 ||
311 (entries >= tbl->gc_thresh2 &&
312 time_after(now, tbl->last_flush + 5 * HZ))) {
313 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700314 entries >= tbl->gc_thresh3) {
315 net_info_ratelimited("%s: neighbor table overflow!\n",
316 tbl->id);
317 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 }
321
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000322 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 if (!n)
324 goto out_entries;
325
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700326 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000328 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 n->updated = n->used = now;
330 n->nud_state = NUD_NONE;
331 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700332 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 n->parms = neigh_parms_clone(&tbl->parms);
Kees Cooke99e88a2017-10-16 14:43:17 -0700334 timer_setup(&n->timer, neigh_timer_handler, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 NEIGH_CACHE_STAT_INC(tbl, allocs);
337 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300338 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 n->dead = 1;
340out:
341 return n;
342
343out_entries:
344 atomic_dec(&tbl->entries);
345 goto out;
346}
347
David S. Miller2c2aba62011-12-28 15:06:58 -0500348static void neigh_get_hash_rnd(u32 *x)
349{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400350 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500351}
352
David S. Millercd089332011-07-11 01:28:12 -0700353static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
David S. Millercd089332011-07-11 01:28:12 -0700355 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000357 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500358 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
361 if (!ret)
362 return NULL;
363 if (size <= PAGE_SIZE)
364 buckets = kzalloc(size, GFP_ATOMIC);
365 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000366 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000367 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
368 get_order(size));
369 if (!buckets) {
370 kfree(ret);
371 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000373 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700374 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500375 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
376 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return ret;
378}
379
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000380static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000382 struct neigh_hash_table *nht = container_of(head,
383 struct neigh_hash_table,
384 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700385 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000386 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000389 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000391 free_pages((unsigned long)buckets, get_order(size));
392 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393}
394
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000395static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700396 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000398 unsigned int i, hash;
399 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
402
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000403 old_nht = rcu_dereference_protected(tbl->nht,
404 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700405 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000406 if (!new_nht)
407 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
David S. Millercd089332011-07-11 01:28:12 -0700409 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 struct neighbour *n, *next;
411
Eric Dumazet767e97e2010-10-06 17:49:21 -0700412 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
413 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000414 n != NULL;
415 n = next) {
416 hash = tbl->hash(n->primary_key, n->dev,
417 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
David S. Millercd089332011-07-11 01:28:12 -0700419 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700420 next = rcu_dereference_protected(n->next,
421 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Eric Dumazet767e97e2010-10-06 17:49:21 -0700423 rcu_assign_pointer(n->next,
424 rcu_dereference_protected(
425 new_nht->hash_buckets[hash],
426 lockdep_is_held(&tbl->lock)));
427 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 }
429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000431 rcu_assign_pointer(tbl->nht, new_nht);
432 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
433 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
436struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
437 struct net_device *dev)
438{
439 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 NEIGH_CACHE_STAT_INC(tbl, lookups);
442
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000443 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600444 n = __neigh_lookup_noref(tbl, pkey, dev);
445 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300446 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600447 n = NULL;
448 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700450
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000451 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 return n;
453}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900454EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
Eric W. Biederman426b5302008-01-24 00:13:18 -0800456struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
457 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
459 struct neighbour *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300460 unsigned int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800461 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000462 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 NEIGH_CACHE_STAT_INC(tbl, lookups);
465
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000466 rcu_read_lock_bh();
467 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700468 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700469
470 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
471 n != NULL;
472 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800473 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900474 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300475 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700476 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 NEIGH_CACHE_STAT_INC(tbl, hits);
478 break;
479 }
480 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700481
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000482 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 return n;
484}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900485EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
David S. Millera263b302012-07-02 02:02:15 -0700487struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
488 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 u32 hash_val;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300491 unsigned int key_len = tbl->key_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 int error;
David Miller596b9b62011-07-25 00:01:25 +0000493 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 if (!n) {
497 rc = ERR_PTR(-ENOBUFS);
498 goto out;
499 }
500
501 memcpy(n->primary_key, pkey, key_len);
502 n->dev = dev;
503 dev_hold(dev);
504
505 /* Protocol specific setup. */
506 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
507 rc = ERR_PTR(error);
508 goto out_neigh_release;
509 }
510
David Millerda6a8fa2011-07-25 00:01:38 +0000511 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200512 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000513 if (error < 0) {
514 rc = ERR_PTR(error);
515 goto out_neigh_release;
516 }
517 }
518
David S. Miller447f2192011-12-19 15:04:41 -0500519 /* Device specific setup. */
520 if (n->parms->neigh_setup &&
521 (error = n->parms->neigh_setup(n)) < 0) {
522 rc = ERR_PTR(error);
523 goto out_neigh_release;
524 }
525
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100526 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000529 nht = rcu_dereference_protected(tbl->nht,
530 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
David S. Millercd089332011-07-11 01:28:12 -0700532 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
533 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Jim Westfall096b9852018-01-14 04:18:50 -0800535 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 if (n->parms->dead) {
538 rc = ERR_PTR(-EINVAL);
539 goto out_tbl_unlock;
540 }
541
Eric Dumazet767e97e2010-10-06 17:49:21 -0700542 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
543 lockdep_is_held(&tbl->lock));
544 n1 != NULL;
545 n1 = rcu_dereference_protected(n1->next,
546 lockdep_is_held(&tbl->lock))) {
Jim Westfall096b9852018-01-14 04:18:50 -0800547 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700548 if (want_ref)
549 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 rc = n1;
551 goto out_tbl_unlock;
552 }
553 }
554
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700556 if (want_ref)
557 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700558 rcu_assign_pointer(n->next,
559 rcu_dereference_protected(nht->hash_buckets[hash_val],
560 lockdep_is_held(&tbl->lock)));
561 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000563 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 rc = n;
565out:
566 return rc;
567out_tbl_unlock:
568 write_unlock_bh(&tbl->lock);
569out_neigh_release:
570 neigh_release(n);
571 goto out;
572}
David S. Millera263b302012-07-02 02:02:15 -0700573EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300575static u32 pneigh_hash(const void *pkey, unsigned int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700577 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700578 hash_val ^= (hash_val >> 16);
579 hash_val ^= hash_val >> 8;
580 hash_val ^= hash_val >> 4;
581 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900582 return hash_val;
583}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700584
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900585static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
586 struct net *net,
587 const void *pkey,
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300588 unsigned int key_len,
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900589 struct net_device *dev)
590{
591 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700592 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900593 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700594 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900595 return n;
596 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700597 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900598 return NULL;
599}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700600
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900601struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
602 struct net *net, const void *pkey, struct net_device *dev)
603{
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300604 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900605 u32 hash_val = pneigh_hash(pkey, key_len);
606
607 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
608 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700609}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900610EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700611
Eric W. Biederman426b5302008-01-24 00:13:18 -0800612struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
613 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 struct net_device *dev, int creat)
615{
616 struct pneigh_entry *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300617 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900618 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900621 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
622 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900624
625 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 goto out;
627
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700628 ASSERT_RTNL();
629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
631 if (!n)
632 goto out;
633
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500634 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 memcpy(n->key, pkey, key_len);
636 n->dev = dev;
637 if (dev)
638 dev_hold(dev);
639
640 if (tbl->pconstructor && tbl->pconstructor(n)) {
641 if (dev)
642 dev_put(dev);
643 kfree(n);
644 n = NULL;
645 goto out;
646 }
647
648 write_lock_bh(&tbl->lock);
649 n->next = tbl->phash_buckets[hash_val];
650 tbl->phash_buckets[hash_val] = n;
651 write_unlock_bh(&tbl->lock);
652out:
653 return n;
654}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900655EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657
Eric W. Biederman426b5302008-01-24 00:13:18 -0800658int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 struct net_device *dev)
660{
661 struct pneigh_entry *n, **np;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300662 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900663 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665 write_lock_bh(&tbl->lock);
666 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
667 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800668 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900669 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 *np = n->next;
671 write_unlock_bh(&tbl->lock);
672 if (tbl->pdestructor)
673 tbl->pdestructor(n);
674 if (n->dev)
675 dev_put(n->dev);
676 kfree(n);
677 return 0;
678 }
679 }
680 write_unlock_bh(&tbl->lock);
681 return -ENOENT;
682}
683
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200684static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
685 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686{
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200687 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 u32 h;
689
690 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
691 np = &tbl->phash_buckets[h];
692 while ((n = *np) != NULL) {
693 if (!dev || n->dev == dev) {
694 *np = n->next;
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200695 n->next = freelist;
696 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 continue;
698 }
699 np = &n->next;
700 }
701 }
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200702 write_unlock_bh(&tbl->lock);
703 while ((n = freelist)) {
704 freelist = n->next;
705 n->next = NULL;
706 if (tbl->pdestructor)
707 tbl->pdestructor(n);
708 if (n->dev)
709 dev_put(n->dev);
710 kfree(n);
711 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712 return -ENOENT;
713}
714
Denis V. Lunev06f05112008-01-24 00:30:58 -0800715static void neigh_parms_destroy(struct neigh_parms *parms);
716
717static inline void neigh_parms_put(struct neigh_parms *parms)
718{
Reshetova, Elena63439442017-06-30 13:07:56 +0300719 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800720 neigh_parms_destroy(parms);
721}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723/*
724 * neighbour must already be out of the table;
725 *
726 */
727void neigh_destroy(struct neighbour *neigh)
728{
David Millerda6a8fa2011-07-25 00:01:38 +0000729 struct net_device *dev = neigh->dev;
730
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
732
733 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000734 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735 dump_stack();
736 return;
737 }
738
739 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000740 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700742 write_lock_bh(&neigh->lock);
743 __skb_queue_purge(&neigh->arp_queue);
744 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000745 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
David S. Miller447f2192011-12-19 15:04:41 -0500747 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200748 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500749
David Millerda6a8fa2011-07-25 00:01:38 +0000750 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 neigh_parms_put(neigh->parms);
752
Joe Perchesd5d427c2013-04-15 15:17:19 +0000753 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000756 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700757}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900758EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759
760/* Neighbour state is suspicious;
761 disable fast path.
762
763 Called with write_locked neigh.
764 */
765static void neigh_suspect(struct neighbour *neigh)
766{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000767 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770}
771
772/* Neighbour state is OK;
773 enable fast path.
774
775 Called with write_locked neigh.
776 */
777static void neigh_connect(struct neighbour *neigh)
778{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000779 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
781 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782}
783
Eric Dumazete4c4e442009-07-30 03:15:07 +0000784static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000786 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700787 struct neighbour *n;
788 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000789 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000790 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
792 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
793
Eric Dumazete4c4e442009-07-30 03:15:07 +0000794 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000795 nht = rcu_dereference_protected(tbl->nht,
796 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797
798 /*
799 * periodically recompute ReachableTime from random function
800 */
801
Eric Dumazete4c4e442009-07-30 03:15:07 +0000802 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700803 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000804 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100805 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100807 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808 }
809
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800810 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
811 goto out;
812
David S. Millercd089332011-07-11 01:28:12 -0700813 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000814 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700815
Eric Dumazet767e97e2010-10-06 17:49:21 -0700816 while ((n = rcu_dereference_protected(*np,
817 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000818 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819
Eric Dumazete4c4e442009-07-30 03:15:07 +0000820 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Eric Dumazete4c4e442009-07-30 03:15:07 +0000822 state = n->nud_state;
Roopa Prabhu9ce33e42018-04-24 13:49:34 -0700823 if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
824 (n->flags & NTF_EXT_LEARNED)) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000825 write_unlock(&n->lock);
826 goto next_elt;
827 }
828
829 if (time_before(n->used, n->confirmed))
830 n->used = n->confirmed;
831
Reshetova, Elena9f237432017-06-30 13:07:55 +0300832 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000833 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100834 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000835 *np = n->next;
836 n->dead = 1;
837 write_unlock(&n->lock);
838 neigh_cleanup_and_release(n);
839 continue;
840 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842
843next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000844 np = &n->next;
845 }
846 /*
847 * It's fine to release lock here, even if hash table
848 * grows while we are preempted.
849 */
850 write_unlock_bh(&tbl->lock);
851 cond_resched();
852 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500853 nht = rcu_dereference_protected(tbl->nht,
854 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000856out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100857 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
858 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
859 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 */
viresh kumarf6180022014-01-22 12:23:33 +0530861 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100862 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000863 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864}
865
866static __inline__ int neigh_max_probes(struct neighbour *n)
867{
868 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900869 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
870 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
871 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872}
873
Timo Teras5ef12d92009-06-11 04:16:28 -0700874static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000875 __releases(neigh->lock)
876 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700877{
878 struct sk_buff *skb;
879
880 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000881 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700882 neigh->updated = jiffies;
883
884 /* It is very thin place. report_unreachable is very complicated
885 routine. Particularly, it can hit the same neighbour entry!
886
887 So that, we try to be accurate and avoid dead loop. --ANK
888 */
889 while (neigh->nud_state == NUD_FAILED &&
890 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
891 write_unlock(&neigh->lock);
892 neigh->ops->error_report(neigh, skb);
893 write_lock(&neigh->lock);
894 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700895 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000896 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700897}
898
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000899static void neigh_probe(struct neighbour *neigh)
900 __releases(neigh->lock)
901{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200902 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000903 /* keep skb alive even if arp_queue overflows */
904 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800905 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000906 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700907 if (neigh->ops->solicit)
908 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000909 atomic_inc(&neigh->probes);
910 kfree_skb(skb);
911}
912
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913/* Called when a timer expires for a neighbour entry. */
914
Kees Cooke99e88a2017-10-16 14:43:17 -0700915static void neigh_timer_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700916{
917 unsigned long now, next;
Kees Cooke99e88a2017-10-16 14:43:17 -0700918 struct neighbour *neigh = from_timer(neigh, t, timer);
Eric Dumazet95c96172012-04-15 05:58:06 +0000919 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 int notify = 0;
921
922 write_lock(&neigh->lock);
923
924 state = neigh->nud_state;
925 now = jiffies;
926 next = now + HZ;
927
David S. Miller045f7b32011-11-01 17:45:55 -0400928 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930
931 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900932 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000934 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 next = neigh->confirmed + neigh->parms->reachable_time;
936 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100937 neigh->used +
938 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000939 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800941 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100943 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000945 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800947 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700949 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 }
951 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900952 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100953 neigh->confirmed +
954 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000955 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800957 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700959 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 next = neigh->confirmed + neigh->parms->reachable_time;
961 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000962 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800964 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900966 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100967 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 }
969 } else {
970 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100971 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 }
973
974 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
975 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976 neigh->nud_state = NUD_FAILED;
977 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700978 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800979 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980 }
981
982 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 if (time_before(next, jiffies + HZ/2))
984 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000985 if (!mod_timer(&neigh->timer, next))
986 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 }
988 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000989 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800990 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800991out:
David S. Miller9ff56602008-02-17 18:39:54 -0800992 write_unlock(&neigh->lock);
993 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994
Thomas Grafd961db32007-08-08 23:12:56 -0700995 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700996 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -0700997
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 neigh_release(neigh);
999}
1000
1001int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
1002{
1003 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001004 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 write_lock_bh(&neigh->lock);
1007
1008 rc = 0;
1009 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1010 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001011 if (neigh->dead)
1012 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001015 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1016 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001017 unsigned long next, now = jiffies;
1018
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001019 atomic_set(&neigh->probes,
1020 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001022 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001023 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1024 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001025 neigh_add_timer(neigh, next);
1026 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 } else {
1028 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001029 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 write_unlock_bh(&neigh->lock);
1031
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001032 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return 1;
1034 }
1035 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001036 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001038 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001039 neigh_add_timer(neigh, jiffies +
1040 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 }
1042
1043 if (neigh->nud_state == NUD_INCOMPLETE) {
1044 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001045 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001046 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001048
David S. Millerf72051b2008-09-23 01:11:18 -07001049 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001050 if (!buff)
1051 break;
1052 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001054 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001056 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001058 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
1060 rc = 1;
1061 }
1062out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001063 if (immediate_probe)
1064 neigh_probe(neigh);
1065 else
1066 write_unlock(&neigh->lock);
1067 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001069
1070out_dead:
1071 if (neigh->nud_state & NUD_STALE)
1072 goto out_unlock_bh;
1073 write_unlock_bh(&neigh->lock);
1074 kfree_skb(skb);
1075 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001077EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
David S. Millerf6b72b622011-07-14 07:53:20 -07001079static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080{
1081 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001082 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001083 = NULL;
1084
1085 if (neigh->dev->header_ops)
1086 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087
1088 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001089 hh = &neigh->hh;
1090 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001091 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001093 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 }
1095 }
1096}
1097
1098
1099
1100/* Generic update routine.
1101 -- lladdr is new lladdr or NULL, if it is not supplied.
1102 -- new is new state.
1103 -- flags
1104 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1105 if it is different.
1106 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001107 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1110
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001111 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 NTF_ROUTER flag.
1113 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1114 a router.
1115
1116 Caller MUST hold reference count on the entry.
1117 */
1118
1119int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001120 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
1122 u8 old;
1123 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 struct net_device *dev;
1126 int update_isrouter = 0;
1127
1128 write_lock_bh(&neigh->lock);
1129
1130 dev = neigh->dev;
1131 old = neigh->nud_state;
1132 err = -EPERM;
1133
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001134 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 (old & (NUD_NOARP | NUD_PERMANENT)))
1136 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001137 if (neigh->dead)
1138 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001140 neigh_update_ext_learned(neigh, flags, &notify);
1141
Linus Torvalds1da177e2005-04-16 15:20:36 -07001142 if (!(new & NUD_VALID)) {
1143 neigh_del_timer(neigh);
1144 if (old & NUD_CONNECTED)
1145 neigh_suspect(neigh);
1146 neigh->nud_state = new;
1147 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001149 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1150 (new & NUD_FAILED)) {
1151 neigh_invalidate(neigh);
1152 notify = 1;
1153 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 goto out;
1155 }
1156
1157 /* Compare new lladdr with cached one */
1158 if (!dev->addr_len) {
1159 /* First case: device needs no address. */
1160 lladdr = neigh->ha;
1161 } else if (lladdr) {
1162 /* The second case: if something is already cached
1163 and a new address is proposed:
1164 - compare new & old
1165 - if they are different, check override flag
1166 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001167 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 !memcmp(lladdr, neigh->ha, dev->addr_len))
1169 lladdr = neigh->ha;
1170 } else {
1171 /* No address is supplied; if we know something,
1172 use it, otherwise discard the request.
1173 */
1174 err = -EINVAL;
1175 if (!(old & NUD_VALID))
1176 goto out;
1177 lladdr = neigh->ha;
1178 }
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180 /* If entry was valid and address is not changed,
1181 do not change entry state, if new one is STALE.
1182 */
1183 err = 0;
1184 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1185 if (old & NUD_VALID) {
1186 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1187 update_isrouter = 0;
1188 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1189 (old & NUD_CONNECTED)) {
1190 lladdr = neigh->ha;
1191 new = NUD_STALE;
1192 } else
1193 goto out;
1194 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001195 if (lladdr == neigh->ha && new == NUD_STALE &&
1196 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 new = old;
1198 }
1199 }
1200
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001201 /* Update timestamps only once we know we will make a change to the
1202 * neighbour entry. Otherwise we risk to move the locktime window with
1203 * noop updates and ignore relevant ARP updates.
1204 */
1205 if (new != old || lladdr != neigh->ha) {
1206 if (new & NUD_CONNECTED)
1207 neigh->confirmed = jiffies;
1208 neigh->updated = jiffies;
1209 }
1210
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 if (new != old) {
1212 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001213 if (new & NUD_PROBE)
1214 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001215 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001216 neigh_add_timer(neigh, (jiffies +
1217 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001218 neigh->parms->reachable_time :
1219 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001221 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 }
1223
1224 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001225 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001227 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 neigh_update_hhs(neigh);
1229 if (!(new & NUD_CONNECTED))
1230 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001231 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001233 }
1234 if (new == old)
1235 goto out;
1236 if (new & NUD_CONNECTED)
1237 neigh_connect(neigh);
1238 else
1239 neigh_suspect(neigh);
1240 if (!(old & NUD_VALID)) {
1241 struct sk_buff *skb;
1242
1243 /* Again: avoid dead loop if something went wrong */
1244
1245 while (neigh->nud_state & NUD_VALID &&
1246 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001247 struct dst_entry *dst = skb_dst(skb);
1248 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001249 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001250
1251 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001252
1253 /* Why not just use 'neigh' as-is? The problem is that
1254 * things such as shaper, eql, and sch_teql can end up
1255 * using alternative, different, neigh objects to output
1256 * the packet in the output path. So what we need to do
1257 * here is re-lookup the top-level neigh in the path so
1258 * we can reinject the packet there.
1259 */
1260 n2 = NULL;
1261 if (dst) {
1262 n2 = dst_neigh_lookup_skb(dst, skb);
1263 if (n2)
1264 n1 = n2;
1265 }
David S. Miller8f40b162011-07-17 13:34:11 -07001266 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001267 if (n2)
1268 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001269 rcu_read_unlock();
1270
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271 write_lock_bh(&neigh->lock);
1272 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001273 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001274 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 }
1276out:
1277 if (update_isrouter) {
1278 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1279 (neigh->flags | NTF_ROUTER) :
1280 (neigh->flags & ~NTF_ROUTER);
1281 }
1282 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001283
1284 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001285 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001286
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287 return err;
1288}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001289EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
Jiri Benc7e980562013-12-11 13:48:20 +01001291/* Update the neigh to listen temporarily for probe responses, even if it is
1292 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1293 */
1294void __neigh_set_probe_once(struct neighbour *neigh)
1295{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001296 if (neigh->dead)
1297 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001298 neigh->updated = jiffies;
1299 if (!(neigh->nud_state & NUD_FAILED))
1300 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001301 neigh->nud_state = NUD_INCOMPLETE;
1302 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001303 neigh_add_timer(neigh,
1304 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1305}
1306EXPORT_SYMBOL(__neigh_set_probe_once);
1307
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1309 u8 *lladdr, void *saddr,
1310 struct net_device *dev)
1311{
1312 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1313 lladdr || !dev->addr_len);
1314 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001315 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001316 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 return neigh;
1318}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001319EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001320
Eric Dumazet34d101d2010-10-11 09:16:57 -07001321/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001322static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001323{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001324 struct net_device *dev = n->dev;
1325 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001326 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001327
1328 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001329
David S. Millerf6b72b622011-07-14 07:53:20 -07001330 /* Only one thread can come in here and initialize the
1331 * hh_cache entry.
1332 */
David S. Millerb23b5452011-07-16 17:45:02 -07001333 if (!hh->hh_len)
1334 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001335
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001336 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001337}
1338
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339/* Slow and careful. */
1340
David S. Miller8f40b162011-07-17 13:34:11 -07001341int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001343 int rc = 0;
1344
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 if (!neigh_event_send(neigh, skb)) {
1346 int err;
1347 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001348 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001349
David S. Millerf6b72b622011-07-14 07:53:20 -07001350 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001351 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001352
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001353 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001354 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001355 seq = read_seqbegin(&neigh->ha_lock);
1356 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1357 neigh->ha, NULL, skb->len);
1358 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001359
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001361 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362 else
1363 goto out_kfree_skb;
1364 }
1365out:
1366 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367out_kfree_skb:
1368 rc = -EINVAL;
1369 kfree_skb(skb);
1370 goto out;
1371}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001372EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
1374/* As fast as possible without hh cache */
1375
David S. Miller8f40b162011-07-17 13:34:11 -07001376int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001379 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001380 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001382 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001383 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001384 seq = read_seqbegin(&neigh->ha_lock);
1385 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1386 neigh->ha, NULL, skb->len);
1387 } while (read_seqretry(&neigh->ha_lock, seq));
1388
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001390 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001391 else {
1392 err = -EINVAL;
1393 kfree_skb(skb);
1394 }
1395 return err;
1396}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001397EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
David S. Miller8f40b162011-07-17 13:34:11 -07001399int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1400{
1401 return dev_queue_xmit(skb);
1402}
1403EXPORT_SYMBOL(neigh_direct_output);
1404
Kees Cooke99e88a2017-10-16 14:43:17 -07001405static void neigh_proxy_process(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406{
Kees Cooke99e88a2017-10-16 14:43:17 -07001407 struct neigh_table *tbl = from_timer(tbl, t, proxy_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 long sched_next = 0;
1409 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001410 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 spin_lock(&tbl->proxy_queue.lock);
1413
David S. Millerf72051b2008-09-23 01:11:18 -07001414 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1415 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001418 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001419
David S. Millerf72051b2008-09-23 01:11:18 -07001420 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001421 if (tbl->proxy_redo && netif_running(dev)) {
1422 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001423 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001424 rcu_read_unlock();
1425 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001426 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001427 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001428
1429 dev_put(dev);
1430 } else if (!sched_next || tdif < sched_next)
1431 sched_next = tdif;
1432 }
1433 del_timer(&tbl->proxy_timer);
1434 if (sched_next)
1435 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1436 spin_unlock(&tbl->proxy_queue.lock);
1437}
1438
1439void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1440 struct sk_buff *skb)
1441{
1442 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001443
1444 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001445 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001447 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 kfree_skb(skb);
1449 return;
1450 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001451
1452 NEIGH_CB(skb)->sched_next = sched_next;
1453 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
1455 spin_lock(&tbl->proxy_queue.lock);
1456 if (del_timer(&tbl->proxy_timer)) {
1457 if (time_before(tbl->proxy_timer.expires, sched_next))
1458 sched_next = tbl->proxy_timer.expires;
1459 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001460 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 dev_hold(skb->dev);
1462 __skb_queue_tail(&tbl->proxy_queue, skb);
1463 mod_timer(&tbl->proxy_timer, sched_next);
1464 spin_unlock(&tbl->proxy_queue.lock);
1465}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001466EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001468static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001469 struct net *net, int ifindex)
1470{
1471 struct neigh_parms *p;
1472
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001473 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001474 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001475 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001476 return p;
1477 }
1478
1479 return NULL;
1480}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481
1482struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1483 struct neigh_table *tbl)
1484{
Gao fengcf89d6b2013-06-20 10:01:32 +08001485 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001486 struct net *net = dev_net(dev);
1487 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488
Gao fengcf89d6b2013-06-20 10:01:32 +08001489 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001491 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001492 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001494 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001495 dev_hold(dev);
1496 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001497 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001499
1500 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001501 dev_put(dev);
1502 kfree(p);
1503 return NULL;
1504 }
1505
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001507 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001509
1510 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 }
1512 return p;
1513}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001514EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516static void neigh_rcu_free_parms(struct rcu_head *head)
1517{
1518 struct neigh_parms *parms =
1519 container_of(head, struct neigh_parms, rcu_head);
1520
1521 neigh_parms_put(parms);
1522}
1523
1524void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1525{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (!parms || parms == &tbl->parms)
1527 return;
1528 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001529 list_del(&parms->list);
1530 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001532 if (parms->dev)
1533 dev_put(parms->dev);
1534 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001536EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
Denis V. Lunev06f05112008-01-24 00:30:58 -08001538static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539{
1540 kfree(parms);
1541}
1542
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001543static struct lock_class_key neigh_table_proxy_queue_class;
1544
WANG Congd7480fd2014-11-10 15:59:36 -08001545static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1546
1547void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
1549 unsigned long now = jiffies;
1550 unsigned long phsize;
1551
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001552 INIT_LIST_HEAD(&tbl->parms_list);
1553 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001554 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001555 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001557 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559 tbl->stats = alloc_percpu(struct neigh_statistics);
1560 if (!tbl->stats)
1561 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001562
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001564 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1565 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567#endif
1568
David S. Millercd089332011-07-11 01:28:12 -07001569 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570
1571 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001572 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001574 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 panic("cannot allocate neighbour cache hashes");
1576
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001577 if (!tbl->entry_size)
1578 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1579 tbl->key_len, NEIGH_PRIV_ALIGN);
1580 else
1581 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1582
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001584 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301585 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1586 tbl->parms.reachable_time);
Kees Cooke99e88a2017-10-16 14:43:17 -07001587 timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001588 skb_queue_head_init_class(&tbl->proxy_queue,
1589 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
1591 tbl->last_flush = now;
1592 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001593
WANG Congd7480fd2014-11-10 15:59:36 -08001594 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001596EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
WANG Congd7480fd2014-11-10 15:59:36 -08001598int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599{
WANG Congd7480fd2014-11-10 15:59:36 -08001600 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001602 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603 del_timer_sync(&tbl->proxy_timer);
1604 pneigh_queue_purge(&tbl->proxy_queue);
1605 neigh_ifdown(tbl, NULL);
1606 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001607 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001609 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1610 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001611 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
1613 kfree(tbl->phash_buckets);
1614 tbl->phash_buckets = NULL;
1615
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001616 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1617
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001618 free_percpu(tbl->stats);
1619 tbl->stats = NULL;
1620
Linus Torvalds1da177e2005-04-16 15:20:36 -07001621 return 0;
1622}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001623EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
WANG Congd7480fd2014-11-10 15:59:36 -08001625static struct neigh_table *neigh_find_table(int family)
1626{
1627 struct neigh_table *tbl = NULL;
1628
1629 switch (family) {
1630 case AF_INET:
1631 tbl = neigh_tables[NEIGH_ARP_TABLE];
1632 break;
1633 case AF_INET6:
1634 tbl = neigh_tables[NEIGH_ND_TABLE];
1635 break;
1636 case AF_DECnet:
1637 tbl = neigh_tables[NEIGH_DN_TABLE];
1638 break;
1639 }
1640
1641 return tbl;
1642}
1643
David Ahernc21ef3e2017-04-16 09:48:24 -07001644static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1645 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001647 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001648 struct ndmsg *ndm;
1649 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001650 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001651 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001653 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654
Eric Dumazet110b2492010-10-04 04:27:36 +00001655 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001656 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 goto out;
1658
Thomas Grafa14a49d2006-08-07 17:53:08 -07001659 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1660 if (dst_attr == NULL)
1661 goto out;
1662
1663 ndm = nlmsg_data(nlh);
1664 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001665 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001666 if (dev == NULL) {
1667 err = -ENODEV;
1668 goto out;
1669 }
1670 }
1671
WANG Congd7480fd2014-11-10 15:59:36 -08001672 tbl = neigh_find_table(ndm->ndm_family);
1673 if (tbl == NULL)
1674 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001676 if (nla_len(dst_attr) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001677 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001678
WANG Congd7480fd2014-11-10 15:59:36 -08001679 if (ndm->ndm_flags & NTF_PROXY) {
1680 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001681 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 }
WANG Congd7480fd2014-11-10 15:59:36 -08001683
1684 if (dev == NULL)
1685 goto out;
1686
1687 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1688 if (neigh == NULL) {
1689 err = -ENOENT;
1690 goto out;
1691 }
1692
1693 err = neigh_update(neigh, NULL, NUD_FAILED,
1694 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001695 NEIGH_UPDATE_F_ADMIN,
1696 NETLINK_CB(skb).portid);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001697 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001698 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001699 neigh_remove_one(neigh, tbl);
1700 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001701
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702out:
1703 return err;
1704}
1705
David Ahernc21ef3e2017-04-16 09:48:24 -07001706static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1707 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708{
WANG Congd7480fd2014-11-10 15:59:36 -08001709 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001710 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001711 struct ndmsg *ndm;
1712 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 struct neigh_table *tbl;
1714 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001715 struct neighbour *neigh;
1716 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001717 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Eric Dumazet110b2492010-10-04 04:27:36 +00001719 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001720 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001721 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722 goto out;
1723
Thomas Graf5208deb2006-08-07 17:55:40 -07001724 err = -EINVAL;
1725 if (tb[NDA_DST] == NULL)
1726 goto out;
1727
1728 ndm = nlmsg_data(nlh);
1729 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001730 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001731 if (dev == NULL) {
1732 err = -ENODEV;
1733 goto out;
1734 }
1735
1736 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001737 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001738 }
1739
WANG Congd7480fd2014-11-10 15:59:36 -08001740 tbl = neigh_find_table(ndm->ndm_family);
1741 if (tbl == NULL)
1742 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +03001744 if (nla_len(tb[NDA_DST]) < (int)tbl->key_len)
WANG Congd7480fd2014-11-10 15:59:36 -08001745 goto out;
1746 dst = nla_data(tb[NDA_DST]);
1747 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748
WANG Congd7480fd2014-11-10 15:59:36 -08001749 if (ndm->ndm_flags & NTF_PROXY) {
1750 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751
WANG Congd7480fd2014-11-10 15:59:36 -08001752 err = -ENOBUFS;
1753 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1754 if (pn) {
1755 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001756 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001757 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001758 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759 }
1760
WANG Congd7480fd2014-11-10 15:59:36 -08001761 if (dev == NULL)
1762 goto out;
1763
1764 neigh = neigh_lookup(tbl, dst, dev);
1765 if (neigh == NULL) {
1766 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1767 err = -ENOENT;
1768 goto out;
1769 }
1770
1771 neigh = __neigh_lookup_errno(tbl, dst, dev);
1772 if (IS_ERR(neigh)) {
1773 err = PTR_ERR(neigh);
1774 goto out;
1775 }
1776 } else {
1777 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1778 err = -EEXIST;
1779 neigh_release(neigh);
1780 goto out;
1781 }
1782
1783 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1784 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1785 }
1786
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001787 if (ndm->ndm_flags & NTF_EXT_LEARNED)
1788 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1789
WANG Congd7480fd2014-11-10 15:59:36 -08001790 if (ndm->ndm_flags & NTF_USE) {
1791 neigh_event_send(neigh, NULL);
1792 err = 0;
1793 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001794 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1795 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001796 neigh_release(neigh);
1797
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798out:
1799 return err;
1800}
1801
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001802static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1803{
Thomas Grafca860fb2006-08-07 18:00:18 -07001804 struct nlattr *nest;
1805
1806 nest = nla_nest_start(skb, NDTA_PARMS);
1807 if (nest == NULL)
1808 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001809
David S. Miller9a6308d2012-04-01 20:06:28 -04001810 if ((parms->dev &&
1811 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001812 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001813 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1814 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001815 /* approximative value for deprecated QUEUE_LEN (in packets) */
1816 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001817 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1818 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1819 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1820 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1821 NEIGH_VAR(parms, UCAST_PROBES)) ||
1822 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1823 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001824 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1825 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001826 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1827 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001828 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001829 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001830 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001831 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001832 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001833 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001834 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001835 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001836 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001837 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001838 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001839 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001840 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001841 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001842 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001843 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844
Thomas Grafca860fb2006-08-07 18:00:18 -07001845nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001846 nla_nest_cancel(skb, nest);
1847 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001848}
1849
Thomas Grafca860fb2006-08-07 18:00:18 -07001850static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1851 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852{
1853 struct nlmsghdr *nlh;
1854 struct ndtmsg *ndtmsg;
1855
Thomas Grafca860fb2006-08-07 18:00:18 -07001856 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1857 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001858 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001859
Thomas Grafca860fb2006-08-07 18:00:18 -07001860 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001861
1862 read_lock_bh(&tbl->lock);
1863 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001864 ndtmsg->ndtm_pad1 = 0;
1865 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001866
David S. Miller9a6308d2012-04-01 20:06:28 -04001867 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001868 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001869 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1870 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1871 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1872 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001873 {
1874 unsigned long now = jiffies;
1875 unsigned int flush_delta = now - tbl->last_flush;
1876 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001877 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878 struct ndt_config ndc = {
1879 .ndtc_key_len = tbl->key_len,
1880 .ndtc_entry_size = tbl->entry_size,
1881 .ndtc_entries = atomic_read(&tbl->entries),
1882 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1883 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001884 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1885 };
1886
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001887 rcu_read_lock_bh();
1888 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001889 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001890 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001891 rcu_read_unlock_bh();
1892
David S. Miller9a6308d2012-04-01 20:06:28 -04001893 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1894 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001895 }
1896
1897 {
1898 int cpu;
1899 struct ndt_stats ndst;
1900
1901 memset(&ndst, 0, sizeof(ndst));
1902
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001903 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001904 struct neigh_statistics *st;
1905
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001906 st = per_cpu_ptr(tbl->stats, cpu);
1907 ndst.ndts_allocs += st->allocs;
1908 ndst.ndts_destroys += st->destroys;
1909 ndst.ndts_hash_grows += st->hash_grows;
1910 ndst.ndts_res_failed += st->res_failed;
1911 ndst.ndts_lookups += st->lookups;
1912 ndst.ndts_hits += st->hits;
1913 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1914 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1915 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1916 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001917 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001918 }
1919
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001920 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1921 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001922 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001923 }
1924
1925 BUG_ON(tbl->parms.dev);
1926 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001927 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001928
1929 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001930 nlmsg_end(skb, nlh);
1931 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001932
Thomas Grafca860fb2006-08-07 18:00:18 -07001933nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001934 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001935 nlmsg_cancel(skb, nlh);
1936 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937}
1938
Thomas Grafca860fb2006-08-07 18:00:18 -07001939static int neightbl_fill_param_info(struct sk_buff *skb,
1940 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001941 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001942 u32 pid, u32 seq, int type,
1943 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944{
1945 struct ndtmsg *ndtmsg;
1946 struct nlmsghdr *nlh;
1947
Thomas Grafca860fb2006-08-07 18:00:18 -07001948 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1949 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001950 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001951
Thomas Grafca860fb2006-08-07 18:00:18 -07001952 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001953
1954 read_lock_bh(&tbl->lock);
1955 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001956 ndtmsg->ndtm_pad1 = 0;
1957 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001958
Thomas Grafca860fb2006-08-07 18:00:18 -07001959 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1960 neightbl_fill_parms(skb, parms) < 0)
1961 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001962
1963 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001964 nlmsg_end(skb, nlh);
1965 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001966errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001968 nlmsg_cancel(skb, nlh);
1969 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001970}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001971
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001972static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001973 [NDTA_NAME] = { .type = NLA_STRING },
1974 [NDTA_THRESH1] = { .type = NLA_U32 },
1975 [NDTA_THRESH2] = { .type = NLA_U32 },
1976 [NDTA_THRESH3] = { .type = NLA_U32 },
1977 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1978 [NDTA_PARMS] = { .type = NLA_NESTED },
1979};
1980
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001981static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001982 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1983 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1984 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1985 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1986 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1987 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001988 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001989 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1990 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1991 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1992 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1993 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1994 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1995 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1996};
1997
David Ahernc21ef3e2017-04-16 09:48:24 -07001998static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
1999 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002000{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002001 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002003 struct ndtmsg *ndtmsg;
2004 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08002005 bool found = false;
2006 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002007
Thomas Graf6b3f8672006-08-07 17:58:53 -07002008 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07002009 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002010 if (err < 0)
2011 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 if (tb[NDTA_NAME] == NULL) {
2014 err = -EINVAL;
2015 goto errout;
2016 }
2017
2018 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002019
2020 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2021 tbl = neigh_tables[tidx];
2022 if (!tbl)
2023 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002024 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2025 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002026 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2027 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002028 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002029 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002030 }
2031
WANG Congd7480fd2014-11-10 15:59:36 -08002032 if (!found)
2033 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002034
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002035 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002036 * We acquire tbl->lock to be nice to the periodic timers and
2037 * make sure they always see a consistent set of values.
2038 */
2039 write_lock_bh(&tbl->lock);
2040
Thomas Graf6b3f8672006-08-07 17:58:53 -07002041 if (tb[NDTA_PARMS]) {
2042 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002043 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002044 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002045
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002047 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002048 if (err < 0)
2049 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002050
Thomas Graf6b3f8672006-08-07 17:58:53 -07002051 if (tbp[NDTPA_IFINDEX])
2052 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002053
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002054 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002055 if (p == NULL) {
2056 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002057 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002058 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002059
Thomas Graf6b3f8672006-08-07 17:58:53 -07002060 for (i = 1; i <= NDTPA_MAX; i++) {
2061 if (tbp[i] == NULL)
2062 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002063
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064 switch (i) {
2065 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002066 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2067 nla_get_u32(tbp[i]) *
2068 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002069 break;
2070 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002071 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2072 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002073 break;
2074 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002075 NEIGH_VAR_SET(p, PROXY_QLEN,
2076 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002077 break;
2078 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002079 NEIGH_VAR_SET(p, APP_PROBES,
2080 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002081 break;
2082 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002083 NEIGH_VAR_SET(p, UCAST_PROBES,
2084 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002085 break;
2086 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002087 NEIGH_VAR_SET(p, MCAST_PROBES,
2088 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002089 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002090 case NDTPA_MCAST_REPROBES:
2091 NEIGH_VAR_SET(p, MCAST_REPROBES,
2092 nla_get_u32(tbp[i]));
2093 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002094 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002095 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2096 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002097 /* update reachable_time as well, otherwise, the change will
2098 * only be effective after the next time neigh_periodic_work
2099 * decides to recompute it (can be multiple minutes)
2100 */
2101 p->reachable_time =
2102 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002103 break;
2104 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002105 NEIGH_VAR_SET(p, GC_STALETIME,
2106 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002107 break;
2108 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002109 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2110 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002111 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002112 break;
2113 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002114 NEIGH_VAR_SET(p, RETRANS_TIME,
2115 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002116 break;
2117 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002118 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2119 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002120 break;
2121 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002122 NEIGH_VAR_SET(p, PROXY_DELAY,
2123 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002124 break;
2125 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002126 NEIGH_VAR_SET(p, LOCKTIME,
2127 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002128 break;
2129 }
2130 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002131 }
2132
Gao fengdc25c672013-06-20 10:01:34 +08002133 err = -ENOENT;
2134 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2135 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2136 !net_eq(net, &init_net))
2137 goto errout_tbl_lock;
2138
Thomas Graf6b3f8672006-08-07 17:58:53 -07002139 if (tb[NDTA_THRESH1])
2140 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2141
2142 if (tb[NDTA_THRESH2])
2143 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2144
2145 if (tb[NDTA_THRESH3])
2146 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2147
2148 if (tb[NDTA_GC_INTERVAL])
2149 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2150
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002151 err = 0;
2152
Thomas Graf6b3f8672006-08-07 17:58:53 -07002153errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002154 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002155errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002156 return err;
2157}
2158
Thomas Grafc8822a42007-03-22 11:50:06 -07002159static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002160{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002161 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002162 int family, tidx, nidx = 0;
2163 int tbl_skip = cb->args[0];
2164 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002165 struct neigh_table *tbl;
2166
Thomas Grafca860fb2006-08-07 18:00:18 -07002167 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002168
WANG Congd7480fd2014-11-10 15:59:36 -08002169 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002170 struct neigh_parms *p;
2171
WANG Congd7480fd2014-11-10 15:59:36 -08002172 tbl = neigh_tables[tidx];
2173 if (!tbl)
2174 continue;
2175
Thomas Grafca860fb2006-08-07 18:00:18 -07002176 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002177 continue;
2178
Eric W. Biederman15e47302012-09-07 20:12:54 +00002179 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002180 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002181 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002182 break;
2183
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002184 nidx = 0;
2185 p = list_next_entry(&tbl->parms, list);
2186 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002187 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002188 continue;
2189
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002190 if (nidx < neigh_skip)
2191 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002192
Thomas Grafca860fb2006-08-07 18:00:18 -07002193 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002194 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002195 cb->nlh->nlmsg_seq,
2196 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002197 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002198 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002199 next:
2200 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002201 }
2202
Thomas Grafca860fb2006-08-07 18:00:18 -07002203 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002204 }
2205out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002206 cb->args[0] = tidx;
2207 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002208
2209 return skb->len;
2210}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211
Thomas Graf8b8aec52006-08-07 17:56:37 -07002212static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2213 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002214{
2215 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002217 struct nlmsghdr *nlh;
2218 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002219
Thomas Graf8b8aec52006-08-07 17:56:37 -07002220 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2221 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002222 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002223
2224 ndm = nlmsg_data(nlh);
2225 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002226 ndm->ndm_pad1 = 0;
2227 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002228 ndm->ndm_flags = neigh->flags;
2229 ndm->ndm_type = neigh->type;
2230 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002231
David S. Miller9a6308d2012-04-01 20:06:28 -04002232 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2233 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002234
2235 read_lock_bh(&neigh->lock);
2236 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002237 if (neigh->nud_state & NUD_VALID) {
2238 char haddr[MAX_ADDR_LEN];
2239
2240 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2241 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2242 read_unlock_bh(&neigh->lock);
2243 goto nla_put_failure;
2244 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002245 }
2246
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002247 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2248 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2249 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002250 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002251 read_unlock_bh(&neigh->lock);
2252
David S. Miller9a6308d2012-04-01 20:06:28 -04002253 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2254 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2255 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002256
Johannes Berg053c0952015-01-16 22:09:00 +01002257 nlmsg_end(skb, nlh);
2258 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002259
2260nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002261 nlmsg_cancel(skb, nlh);
2262 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263}
2264
Tony Zelenoff84920c12012-01-26 22:28:58 +00002265static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2266 u32 pid, u32 seq, int type, unsigned int flags,
2267 struct neigh_table *tbl)
2268{
2269 struct nlmsghdr *nlh;
2270 struct ndmsg *ndm;
2271
2272 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2273 if (nlh == NULL)
2274 return -EMSGSIZE;
2275
2276 ndm = nlmsg_data(nlh);
2277 ndm->ndm_family = tbl->family;
2278 ndm->ndm_pad1 = 0;
2279 ndm->ndm_pad2 = 0;
2280 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002281 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002282 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002283 ndm->ndm_state = NUD_NONE;
2284
David S. Miller9a6308d2012-04-01 20:06:28 -04002285 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2286 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002287
Johannes Berg053c0952015-01-16 22:09:00 +01002288 nlmsg_end(skb, nlh);
2289 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002290
2291nla_put_failure:
2292 nlmsg_cancel(skb, nlh);
2293 return -EMSGSIZE;
2294}
2295
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002296static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002297{
2298 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002299 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002300}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002301
David Ahern21fdd092015-09-29 09:32:03 -07002302static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2303{
2304 struct net_device *master;
2305
2306 if (!master_idx)
2307 return false;
2308
2309 master = netdev_master_upper_dev_get(dev);
2310 if (!master || master->ifindex != master_idx)
2311 return true;
2312
2313 return false;
2314}
2315
David Ahern16660f02015-10-03 11:43:46 -07002316static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2317{
2318 if (filter_idx && dev->ifindex != filter_idx)
2319 return true;
2320
2321 return false;
2322}
2323
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2325 struct netlink_callback *cb)
2326{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002327 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002328 const struct nlmsghdr *nlh = cb->nlh;
2329 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330 struct neighbour *n;
2331 int rc, h, s_h = cb->args[1];
2332 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002333 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002334 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002335 unsigned int flags = NLM_F_MULTI;
2336 int err;
2337
Johannes Bergfceb6432017-04-12 14:34:07 +02002338 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002339 if (!err) {
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002340 if (tb[NDA_IFINDEX]) {
2341 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
2342 return -EINVAL;
David Ahern16660f02015-10-03 11:43:46 -07002343 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002344 }
2345 if (tb[NDA_MASTER]) {
2346 if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
2347 return -EINVAL;
David Ahern21fdd092015-09-29 09:32:03 -07002348 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
Eric Dumazet7dd07c12018-04-11 14:46:00 -07002349 }
David Ahern16660f02015-10-03 11:43:46 -07002350 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002351 flags |= NLM_F_DUMP_FILTERED;
2352 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002354 rcu_read_lock_bh();
2355 nht = rcu_dereference_bh(tbl->nht);
2356
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002357 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 if (h > s_h)
2359 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002360 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2361 n != NULL;
2362 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002363 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2364 goto next;
2365 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2366 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002367 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002368 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002370 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002371 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 rc = -1;
2373 goto out;
2374 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002375next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002376 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378 }
2379 rc = skb->len;
2380out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002381 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382 cb->args[1] = h;
2383 cb->args[2] = idx;
2384 return rc;
2385}
2386
Tony Zelenoff84920c12012-01-26 22:28:58 +00002387static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2388 struct netlink_callback *cb)
2389{
2390 struct pneigh_entry *n;
2391 struct net *net = sock_net(skb->sk);
2392 int rc, h, s_h = cb->args[3];
2393 int idx, s_idx = idx = cb->args[4];
2394
2395 read_lock_bh(&tbl->lock);
2396
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002397 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002398 if (h > s_h)
2399 s_idx = 0;
2400 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002401 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002402 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002403 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002404 cb->nlh->nlmsg_seq,
2405 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002406 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002407 read_unlock_bh(&tbl->lock);
2408 rc = -1;
2409 goto out;
2410 }
2411 next:
2412 idx++;
2413 }
2414 }
2415
2416 read_unlock_bh(&tbl->lock);
2417 rc = skb->len;
2418out:
2419 cb->args[3] = h;
2420 cb->args[4] = idx;
2421 return rc;
2422
2423}
2424
Thomas Grafc8822a42007-03-22 11:50:06 -07002425static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002426{
2427 struct neigh_table *tbl;
2428 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002429 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002430 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431
Thomas Graf8b8aec52006-08-07 17:56:37 -07002432 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002433
2434 /* check for full ndmsg structure presence, family member is
2435 * the same for both structures
2436 */
2437 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2438 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2439 proxy = 1;
2440
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 s_t = cb->args[0];
2442
WANG Congd7480fd2014-11-10 15:59:36 -08002443 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2444 tbl = neigh_tables[t];
2445
2446 if (!tbl)
2447 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 if (t < s_t || (family && tbl->family != family))
2449 continue;
2450 if (t > s_t)
2451 memset(&cb->args[1], 0, sizeof(cb->args) -
2452 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002453 if (proxy)
2454 err = pneigh_dump_table(tbl, skb, cb);
2455 else
2456 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002457 if (err < 0)
2458 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002460
2461 cb->args[0] = t;
2462 return skb->len;
2463}
2464
2465void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2466{
2467 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002468 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002470 rcu_read_lock_bh();
2471 nht = rcu_dereference_bh(tbl->nht);
2472
Eric Dumazet767e97e2010-10-06 17:49:21 -07002473 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002474 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475 struct neighbour *n;
2476
Eric Dumazet767e97e2010-10-06 17:49:21 -07002477 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2478 n != NULL;
2479 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480 cb(n, cookie);
2481 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002482 read_unlock(&tbl->lock);
2483 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484}
2485EXPORT_SYMBOL(neigh_for_each);
2486
2487/* The tbl->lock must be held as a writer and BH disabled. */
2488void __neigh_for_each_release(struct neigh_table *tbl,
2489 int (*cb)(struct neighbour *))
2490{
2491 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002492 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002494 nht = rcu_dereference_protected(tbl->nht,
2495 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002496 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002497 struct neighbour *n;
2498 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002500 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002501 while ((n = rcu_dereference_protected(*np,
2502 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002503 int release;
2504
2505 write_lock(&n->lock);
2506 release = cb(n);
2507 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002508 rcu_assign_pointer(*np,
2509 rcu_dereference_protected(n->next,
2510 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002511 n->dead = 1;
2512 } else
2513 np = &n->next;
2514 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002515 if (release)
2516 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002517 }
2518 }
2519}
2520EXPORT_SYMBOL(__neigh_for_each_release);
2521
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002522int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002523 const void *addr, struct sk_buff *skb)
2524{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002525 int err = -EAFNOSUPPORT;
2526 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002527 struct neigh_table *tbl;
2528 struct neighbour *neigh;
2529
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002530 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002531 if (!tbl)
2532 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002533 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002534 neigh = __neigh_lookup_noref(tbl, addr, dev);
2535 if (!neigh)
2536 neigh = __neigh_create(tbl, addr, dev, false);
2537 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002538 if (IS_ERR(neigh)) {
2539 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002540 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002541 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002542 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002543 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002544 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002545 else if (index == NEIGH_LINK_TABLE) {
2546 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2547 addr, NULL, skb->len);
2548 if (err < 0)
2549 goto out_kfree_skb;
2550 err = dev_queue_xmit(skb);
2551 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002552out:
2553 return err;
2554out_kfree_skb:
2555 kfree_skb(skb);
2556 goto out;
2557}
2558EXPORT_SYMBOL(neigh_xmit);
2559
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560#ifdef CONFIG_PROC_FS
2561
2562static struct neighbour *neigh_get_first(struct seq_file *seq)
2563{
2564 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002565 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002566 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 struct neighbour *n = NULL;
2568 int bucket = state->bucket;
2569
2570 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002571 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002572 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573
2574 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002575 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002576 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 if (state->neigh_sub_iter) {
2578 loff_t fakep = 0;
2579 void *v;
2580
2581 v = state->neigh_sub_iter(state, n, &fakep);
2582 if (!v)
2583 goto next;
2584 }
2585 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2586 break;
2587 if (n->nud_state & ~NUD_NOARP)
2588 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002589next:
2590 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 }
2592
2593 if (n)
2594 break;
2595 }
2596 state->bucket = bucket;
2597
2598 return n;
2599}
2600
2601static struct neighbour *neigh_get_next(struct seq_file *seq,
2602 struct neighbour *n,
2603 loff_t *pos)
2604{
2605 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002606 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002607 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608
2609 if (state->neigh_sub_iter) {
2610 void *v = state->neigh_sub_iter(state, n, pos);
2611 if (v)
2612 return n;
2613 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002614 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615
2616 while (1) {
2617 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002618 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002619 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 if (state->neigh_sub_iter) {
2621 void *v = state->neigh_sub_iter(state, n, pos);
2622 if (v)
2623 return n;
2624 goto next;
2625 }
2626 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2627 break;
2628
2629 if (n->nud_state & ~NUD_NOARP)
2630 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002631next:
2632 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633 }
2634
2635 if (n)
2636 break;
2637
David S. Millercd089332011-07-11 01:28:12 -07002638 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639 break;
2640
Eric Dumazet767e97e2010-10-06 17:49:21 -07002641 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 }
2643
2644 if (n && pos)
2645 --(*pos);
2646 return n;
2647}
2648
2649static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2650{
2651 struct neighbour *n = neigh_get_first(seq);
2652
2653 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002654 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655 while (*pos) {
2656 n = neigh_get_next(seq, n, pos);
2657 if (!n)
2658 break;
2659 }
2660 }
2661 return *pos ? NULL : n;
2662}
2663
2664static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2665{
2666 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002667 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 struct neigh_table *tbl = state->tbl;
2669 struct pneigh_entry *pn = NULL;
2670 int bucket = state->bucket;
2671
2672 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2673 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2674 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002675 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002676 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002677 if (pn)
2678 break;
2679 }
2680 state->bucket = bucket;
2681
2682 return pn;
2683}
2684
2685static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2686 struct pneigh_entry *pn,
2687 loff_t *pos)
2688{
2689 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002690 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002691 struct neigh_table *tbl = state->tbl;
2692
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002693 do {
2694 pn = pn->next;
2695 } while (pn && !net_eq(pneigh_net(pn), net));
2696
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 while (!pn) {
2698 if (++state->bucket > PNEIGH_HASHMASK)
2699 break;
2700 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002701 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002702 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 if (pn)
2704 break;
2705 }
2706
2707 if (pn && pos)
2708 --(*pos);
2709
2710 return pn;
2711}
2712
2713static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2714{
2715 struct pneigh_entry *pn = pneigh_get_first(seq);
2716
2717 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002718 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719 while (*pos) {
2720 pn = pneigh_get_next(seq, pn, pos);
2721 if (!pn)
2722 break;
2723 }
2724 }
2725 return *pos ? NULL : pn;
2726}
2727
2728static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2729{
2730 struct neigh_seq_state *state = seq->private;
2731 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002732 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733
Chris Larson745e2032008-08-03 01:10:55 -07002734 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002736 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737
2738 return rc;
2739}
2740
2741void *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 +00002742 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743{
2744 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745
2746 state->tbl = tbl;
2747 state->bucket = 0;
2748 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2749
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002750 rcu_read_lock_bh();
2751 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002752
Chris Larson745e2032008-08-03 01:10:55 -07002753 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002754}
2755EXPORT_SYMBOL(neigh_seq_start);
2756
2757void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2758{
2759 struct neigh_seq_state *state;
2760 void *rc;
2761
2762 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002763 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764 goto out;
2765 }
2766
2767 state = seq->private;
2768 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2769 rc = neigh_get_next(seq, v, NULL);
2770 if (rc)
2771 goto out;
2772 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2773 rc = pneigh_get_first(seq);
2774 } else {
2775 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2776 rc = pneigh_get_next(seq, v, NULL);
2777 }
2778out:
2779 ++(*pos);
2780 return rc;
2781}
2782EXPORT_SYMBOL(neigh_seq_next);
2783
2784void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002785 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002787 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002788}
2789EXPORT_SYMBOL(neigh_seq_stop);
2790
2791/* statistics via seq_file */
2792
2793static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2794{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002795 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 int cpu;
2797
2798 if (*pos == 0)
2799 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002800
Rusty Russell0f23174a2008-12-29 12:23:42 +00002801 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002802 if (!cpu_possible(cpu))
2803 continue;
2804 *pos = cpu+1;
2805 return per_cpu_ptr(tbl->stats, cpu);
2806 }
2807 return NULL;
2808}
2809
2810static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2811{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002812 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 int cpu;
2814
Rusty Russell0f23174a2008-12-29 12:23:42 +00002815 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002816 if (!cpu_possible(cpu))
2817 continue;
2818 *pos = cpu+1;
2819 return per_cpu_ptr(tbl->stats, cpu);
2820 }
2821 return NULL;
2822}
2823
2824static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2825{
2826
2827}
2828
2829static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2830{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002831 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002832 struct neigh_statistics *st = v;
2833
2834 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002835 seq_printf(seq, "entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002836 return 0;
2837 }
2838
2839 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002840 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 atomic_read(&tbl->entries),
2842
2843 st->allocs,
2844 st->destroys,
2845 st->hash_grows,
2846
2847 st->lookups,
2848 st->hits,
2849
2850 st->res_failed,
2851
2852 st->rcv_probes_mcast,
2853 st->rcv_probes_ucast,
2854
2855 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002856 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002857 st->unres_discards,
2858 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 );
2860
2861 return 0;
2862}
2863
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002864static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 .start = neigh_stat_seq_start,
2866 .next = neigh_stat_seq_next,
2867 .stop = neigh_stat_seq_stop,
2868 .show = neigh_stat_seq_show,
2869};
2870
2871static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2872{
2873 int ret = seq_open(file, &neigh_stat_seq_ops);
2874
2875 if (!ret) {
2876 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002877 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002878 }
2879 return ret;
2880};
2881
Arjan van de Ven9a321442007-02-12 00:55:35 -08002882static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883 .open = neigh_stat_seq_open,
2884 .read = seq_read,
2885 .llseek = seq_lseek,
2886 .release = seq_release,
2887};
2888
2889#endif /* CONFIG_PROC_FS */
2890
Thomas Graf339bf982006-11-10 14:10:15 -08002891static inline size_t neigh_nlmsg_size(void)
2892{
2893 return NLMSG_ALIGN(sizeof(struct ndmsg))
2894 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2895 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2896 + nla_total_size(sizeof(struct nda_cacheinfo))
2897 + nla_total_size(4); /* NDA_PROBES */
2898}
2899
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002900static void __neigh_notify(struct neighbour *n, int type, int flags,
2901 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002902{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002903 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002904 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002905 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906
Thomas Graf339bf982006-11-10 14:10:15 -08002907 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002908 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002909 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002911 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002912 if (err < 0) {
2913 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2914 WARN_ON(err == -EMSGSIZE);
2915 kfree_skb(skb);
2916 goto errout;
2917 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002918 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2919 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002920errout:
2921 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002922 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002923}
2924
2925void neigh_app_ns(struct neighbour *n)
2926{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002927 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002928}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002929EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002930
2931#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002932static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002933static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002934static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935
Joe Perchesfe2c6332013-06-11 23:04:25 -07002936static int proc_unres_qlen(struct ctl_table *ctl, int write,
2937 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002938{
2939 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002940 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002941
Shan Weice46cc62012-12-04 18:49:15 +00002942 tmp.extra1 = &zero;
2943 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002944 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002945
2946 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2947 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2948
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002949 if (write && !ret)
2950 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2951 return ret;
2952}
2953
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002954static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2955 int family)
2956{
Jiri Pirkobba24892013-12-07 19:26:57 +01002957 switch (family) {
2958 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002959 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002960 case AF_INET6:
2961 return __in6_dev_nd_parms_get_rcu(dev);
2962 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002963 return NULL;
2964}
2965
2966static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2967 int index)
2968{
2969 struct net_device *dev;
2970 int family = neigh_parms_family(p);
2971
2972 rcu_read_lock();
2973 for_each_netdev_rcu(net, dev) {
2974 struct neigh_parms *dst_p =
2975 neigh_get_dev_parms_rcu(dev, family);
2976
2977 if (dst_p && !test_bit(index, dst_p->data_state))
2978 dst_p->data[index] = p->data[index];
2979 }
2980 rcu_read_unlock();
2981}
2982
2983static void neigh_proc_update(struct ctl_table *ctl, int write)
2984{
2985 struct net_device *dev = ctl->extra1;
2986 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002987 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002988 int index = (int *) ctl->data - p->data;
2989
2990 if (!write)
2991 return;
2992
2993 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002994 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2995 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002996 if (!dev) /* NULL dev means this is default value */
2997 neigh_copy_dflt_parms(net, p, index);
2998}
2999
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003000static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3001 void __user *buffer,
3002 size_t *lenp, loff_t *ppos)
3003{
3004 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003005 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003006
3007 tmp.extra1 = &zero;
3008 tmp.extra2 = &int_max;
3009
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003010 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3011 neigh_proc_update(ctl, write);
3012 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003013}
3014
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003015int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3016 void __user *buffer, size_t *lenp, loff_t *ppos)
3017{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003018 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3019
3020 neigh_proc_update(ctl, write);
3021 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003022}
3023EXPORT_SYMBOL(neigh_proc_dointvec);
3024
3025int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3026 void __user *buffer,
3027 size_t *lenp, loff_t *ppos)
3028{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003029 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3030
3031 neigh_proc_update(ctl, write);
3032 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003033}
3034EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3035
3036static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3037 void __user *buffer,
3038 size_t *lenp, loff_t *ppos)
3039{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003040 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3041
3042 neigh_proc_update(ctl, write);
3043 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003044}
3045
3046int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3047 void __user *buffer,
3048 size_t *lenp, loff_t *ppos)
3049{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003050 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3051
3052 neigh_proc_update(ctl, write);
3053 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003054}
3055EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3056
3057static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3058 void __user *buffer,
3059 size_t *lenp, loff_t *ppos)
3060{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003061 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3062
3063 neigh_proc_update(ctl, write);
3064 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003065}
3066
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003067static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3068 void __user *buffer,
3069 size_t *lenp, loff_t *ppos)
3070{
3071 struct neigh_parms *p = ctl->extra2;
3072 int ret;
3073
3074 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3075 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3076 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3077 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3078 else
3079 ret = -1;
3080
3081 if (write && ret == 0) {
3082 /* update reachable_time as well, otherwise, the change will
3083 * only be effective after the next time neigh_periodic_work
3084 * decides to recompute it
3085 */
3086 p->reachable_time =
3087 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3088 }
3089 return ret;
3090}
3091
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003092#define NEIGH_PARMS_DATA_OFFSET(index) \
3093 (&((struct neigh_parms *) 0)->data[index])
3094
3095#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3096 [NEIGH_VAR_ ## attr] = { \
3097 .procname = name, \
3098 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3099 .maxlen = sizeof(int), \
3100 .mode = mval, \
3101 .proc_handler = proc, \
3102 }
3103
3104#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3105 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3106
3107#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003108 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003109
3110#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003111 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003112
3113#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003114 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003115
3116#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003117 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003118
3119#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003120 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003121
Linus Torvalds1da177e2005-04-16 15:20:36 -07003122static struct neigh_sysctl_table {
3123 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003124 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003125} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003126 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003127 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3128 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3129 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003130 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003131 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3132 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3133 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3134 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3135 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3136 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3137 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3138 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3139 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3140 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3141 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3142 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003143 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 .procname = "gc_interval",
3145 .maxlen = sizeof(int),
3146 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003147 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003149 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 .procname = "gc_thresh1",
3151 .maxlen = sizeof(int),
3152 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003153 .extra1 = &zero,
3154 .extra2 = &int_max,
3155 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003157 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 .procname = "gc_thresh2",
3159 .maxlen = sizeof(int),
3160 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003161 .extra1 = &zero,
3162 .extra2 = &int_max,
3163 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003164 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003165 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166 .procname = "gc_thresh3",
3167 .maxlen = sizeof(int),
3168 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003169 .extra1 = &zero,
3170 .extra2 = &int_max,
3171 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003173 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 },
3175};
3176
3177int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003178 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003180 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003181 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003182 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003183 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003184 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003186 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003187 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003188 goto err;
3189
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003190 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003191 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003192 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003193 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003194 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195
3196 if (dev) {
3197 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003198 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003199 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3200 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003202 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003203 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003204 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3205 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3206 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3207 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 }
3209
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003210 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003212 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003213 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003214 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003216 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003217 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003218 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003219 } else {
3220 /* Those handlers will update p->reachable_time after
3221 * base_reachable_time(_ms) is set to ensure the new timer starts being
3222 * applied after the next neighbour update instead of waiting for
3223 * neigh_periodic_work to update its value (can be multiple minutes)
3224 * So any handler that replaces them should do this as well
3225 */
3226 /* ReachableTime */
3227 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3228 neigh_proc_base_reachable_time;
3229 /* ReachableTime (in milliseconds) */
3230 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3231 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 }
3233
Eric W. Biederman464dc802012-11-16 03:02:59 +00003234 /* Don't export sysctls to unprivileged users */
3235 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3236 t->neigh_vars[0].procname = NULL;
3237
Jiri Pirko73af6142013-12-07 19:26:55 +01003238 switch (neigh_parms_family(p)) {
3239 case AF_INET:
3240 p_name = "ipv4";
3241 break;
3242 case AF_INET6:
3243 p_name = "ipv6";
3244 break;
3245 default:
3246 BUG();
3247 }
3248
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003249 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3250 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003251 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003252 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003253 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003254 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003255
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 p->sysctl_table = t;
3257 return 0;
3258
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003259free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003261err:
3262 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003263}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003264EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265
3266void neigh_sysctl_unregister(struct neigh_parms *p)
3267{
3268 if (p->sysctl_table) {
3269 struct neigh_sysctl_table *t = p->sysctl_table;
3270 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003271 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272 kfree(t);
3273 }
3274}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003275EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003276
3277#endif /* CONFIG_SYSCTL */
3278
Thomas Grafc8822a42007-03-22 11:50:06 -07003279static int __init neigh_init(void)
3280{
Florian Westphalb97bac62017-08-09 20:41:48 +02003281 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3282 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
3283 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003284
Greg Rosec7ac8672011-06-10 01:27:09 +00003285 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003286 0);
3287 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003288
3289 return 0;
3290}
3291
3292subsys_initcall(neigh_init);
3293