blob: 59c1581eed02524082eca9ddc22c747ba7910f00 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010042#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070043
Joe Perchesd5d427c2013-04-15 15:17:19 +000044#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000046#define neigh_dbg(level, fmt, ...) \
47do { \
48 if (level <= NEIGH_DEBUG) \
49 pr_debug(fmt, ##__VA_ARGS__); \
50} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
52#define PNEIGH_HASHMASK 0xF
53
54static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070055static void __neigh_notify(struct neighbour *n, int type, int flags);
56static void neigh_update_notify(struct neighbour *neigh);
Wolfgang Bumiller581cb192018-04-12 10:46:55 +020057static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
58 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Ravinder Konkaa71b6682015-04-09 11:42:00 +053060static unsigned int neigh_probe_enable;
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
Thomas Grafd961db32007-08-08 23:12:56 -0700104 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700105 neigh_release(neigh);
106}
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108/*
109 * It is random distribution in the interval (1/2)*base...(3/2)*base.
110 * It corresponds to default IPv6 settings and is not overridable,
111 * because it is really reasonable choice.
112 */
113
114unsigned long neigh_rand_reach_time(unsigned long base)
115{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500116 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900118EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119
120
121static int neigh_forced_gc(struct neigh_table *tbl)
122{
123 int shrunk = 0;
124 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000125 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
128
129 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000130 nht = rcu_dereference_protected(tbl->nht,
131 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700132 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700133 struct neighbour *n;
134 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000136 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700137 while ((n = rcu_dereference_protected(*np,
138 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 /* Neighbour record may be discarded if:
140 * - nobody refers to it.
141 * - it is not permanent
142 */
143 write_lock(&n->lock);
144 if (atomic_read(&n->refcnt) == 1 &&
145 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700146 rcu_assign_pointer(*np,
147 rcu_dereference_protected(n->next,
148 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 n->dead = 1;
150 shrunk = 1;
151 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700152 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 continue;
154 }
155 write_unlock(&n->lock);
156 np = &n->next;
157 }
158 }
159
160 tbl->last_flush = jiffies;
161
162 write_unlock_bh(&tbl->lock);
163
164 return shrunk;
165}
166
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800167static void neigh_add_timer(struct neighbour *n, unsigned long when)
168{
169 neigh_hold(n);
170 if (unlikely(mod_timer(&n->timer, when))) {
171 printk("NEIGH: BUG, double timer add, state is %x\n",
172 n->nud_state);
173 dump_stack();
174 }
175}
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177static int neigh_del_timer(struct neighbour *n)
178{
179 if ((n->nud_state & NUD_IN_TIMER) &&
180 del_timer(&n->timer)) {
181 neigh_release(n);
182 return 1;
183 }
184 return 0;
185}
186
187static void pneigh_queue_purge(struct sk_buff_head *list)
188{
189 struct sk_buff *skb;
190
191 while ((skb = skb_dequeue(list)) != NULL) {
192 dev_put(skb->dev);
193 kfree_skb(skb);
194 }
195}
196
Herbert Xu49636bb2005-10-23 17:18:00 +1000197static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
199 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000200 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000202 nht = rcu_dereference_protected(tbl->nht,
203 lockdep_is_held(&tbl->lock));
204
David S. Millercd089332011-07-11 01:28:12 -0700205 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700206 struct neighbour *n;
207 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Eric Dumazet767e97e2010-10-06 17:49:21 -0700209 while ((n = rcu_dereference_protected(*np,
210 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 if (dev && n->dev != dev) {
212 np = &n->next;
213 continue;
214 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700215 rcu_assign_pointer(*np,
216 rcu_dereference_protected(n->next,
217 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 write_lock(&n->lock);
219 neigh_del_timer(n);
220 n->dead = 1;
221
222 if (atomic_read(&n->refcnt) != 1) {
223 /* The most unpleasant situation.
224 We must destroy neighbour entry,
225 but someone still uses it.
226
227 The destroy will be delayed until
228 the last user releases us, but
229 we must kill timers etc. and move
230 it to safe state.
231 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700232 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000233 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 n->output = neigh_blackhole;
235 if (n->nud_state & NUD_VALID)
236 n->nud_state = NUD_NOARP;
237 else
238 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000239 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 }
241 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700242 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
244 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000245}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Herbert Xu49636bb2005-10-23 17:18:00 +1000247void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
248{
249 write_lock_bh(&tbl->lock);
250 neigh_flush_dev(tbl, dev);
251 write_unlock_bh(&tbl->lock);
252}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900253EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000254
255int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
256{
257 write_lock_bh(&tbl->lock);
258 neigh_flush_dev(tbl, dev);
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200259 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260
261 del_timer_sync(&tbl->proxy_timer);
262 pneigh_queue_purge(&tbl->proxy_queue);
263 return 0;
264}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900265EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266
David Miller596b9b62011-07-25 00:01:25 +0000267static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268{
269 struct neighbour *n = NULL;
270 unsigned long now = jiffies;
271 int entries;
272
273 entries = atomic_inc_return(&tbl->entries) - 1;
274 if (entries >= tbl->gc_thresh3 ||
275 (entries >= tbl->gc_thresh2 &&
276 time_after(now, tbl->last_flush + 5 * HZ))) {
277 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700278 entries >= tbl->gc_thresh3) {
279 net_info_ratelimited("%s: neighbor table overflow!\n",
280 tbl->id);
281 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700283 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700284 }
285
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000286 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (!n)
288 goto out_entries;
289
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700290 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000292 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 n->updated = n->used = now;
294 n->nud_state = NUD_NONE;
295 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700296 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800298 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 NEIGH_CACHE_STAT_INC(tbl, allocs);
301 n->tbl = tbl;
302 atomic_set(&n->refcnt, 1);
303 n->dead = 1;
304out:
305 return n;
306
307out_entries:
308 atomic_dec(&tbl->entries);
309 goto out;
310}
311
David S. Miller2c2aba62011-12-28 15:06:58 -0500312static void neigh_get_hash_rnd(u32 *x)
313{
314 get_random_bytes(x, sizeof(*x));
315 *x |= 1;
316}
317
David S. Millercd089332011-07-11 01:28:12 -0700318static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
David S. Millercd089332011-07-11 01:28:12 -0700320 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000321 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000322 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500323 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000325 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
326 if (!ret)
327 return NULL;
328 if (size <= PAGE_SIZE)
329 buckets = kzalloc(size, GFP_ATOMIC);
330 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000331 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000332 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
333 get_order(size));
334 if (!buckets) {
335 kfree(ret);
336 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000338 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700339 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500340 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
341 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 return ret;
343}
344
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000345static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000347 struct neigh_hash_table *nht = container_of(head,
348 struct neigh_hash_table,
349 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700350 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000351 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000354 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 free_pages((unsigned long)buckets, get_order(size));
357 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700361 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 unsigned int i, hash;
364 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
367
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000368 old_nht = rcu_dereference_protected(tbl->nht,
369 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700370 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000371 if (!new_nht)
372 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
David S. Millercd089332011-07-11 01:28:12 -0700374 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 struct neighbour *n, *next;
376
Eric Dumazet767e97e2010-10-06 17:49:21 -0700377 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
378 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000379 n != NULL;
380 n = next) {
381 hash = tbl->hash(n->primary_key, n->dev,
382 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
David S. Millercd089332011-07-11 01:28:12 -0700384 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700385 next = rcu_dereference_protected(n->next,
386 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Eric Dumazet767e97e2010-10-06 17:49:21 -0700388 rcu_assign_pointer(n->next,
389 rcu_dereference_protected(
390 new_nht->hash_buckets[hash],
391 lockdep_is_held(&tbl->lock)));
392 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000396 rcu_assign_pointer(tbl->nht, new_nht);
397 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
398 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
401struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
402 struct net_device *dev)
403{
404 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 NEIGH_CACHE_STAT_INC(tbl, lookups);
407
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000408 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600409 n = __neigh_lookup_noref(tbl, pkey, dev);
410 if (n) {
411 if (!atomic_inc_not_zero(&n->refcnt))
412 n = NULL;
413 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700415
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000416 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417 return n;
418}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900419EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420
Eric W. Biederman426b5302008-01-24 00:13:18 -0800421struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
422 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423{
424 struct neighbour *n;
425 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800426 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000427 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428
429 NEIGH_CACHE_STAT_INC(tbl, lookups);
430
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000431 rcu_read_lock_bh();
432 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700433 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700434
435 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
436 n != NULL;
437 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800438 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900439 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700440 if (!atomic_inc_not_zero(&n->refcnt))
441 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 NEIGH_CACHE_STAT_INC(tbl, hits);
443 break;
444 }
445 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700446
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000447 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 return n;
449}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900450EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451
David S. Millera263b302012-07-02 02:02:15 -0700452struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
453 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 u32 hash_val;
456 int key_len = tbl->key_len;
457 int error;
David Miller596b9b62011-07-25 00:01:25 +0000458 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000459 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460
461 if (!n) {
462 rc = ERR_PTR(-ENOBUFS);
463 goto out;
464 }
465
466 memcpy(n->primary_key, pkey, key_len);
467 n->dev = dev;
468 dev_hold(dev);
469
470 /* Protocol specific setup. */
471 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
472 rc = ERR_PTR(error);
473 goto out_neigh_release;
474 }
475
David Millerda6a8fa2011-07-25 00:01:38 +0000476 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200477 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000478 if (error < 0) {
479 rc = ERR_PTR(error);
480 goto out_neigh_release;
481 }
482 }
483
David S. Miller447f2192011-12-19 15:04:41 -0500484 /* Device specific setup. */
485 if (n->parms->neigh_setup &&
486 (error = n->parms->neigh_setup(n)) < 0) {
487 rc = ERR_PTR(error);
488 goto out_neigh_release;
489 }
490
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100491 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492
493 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 nht = rcu_dereference_protected(tbl->nht,
495 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
David S. Millercd089332011-07-11 01:28:12 -0700497 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
498 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Jim Westfall014510b2018-01-14 04:18:50 -0800500 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
502 if (n->parms->dead) {
503 rc = ERR_PTR(-EINVAL);
504 goto out_tbl_unlock;
505 }
506
Eric Dumazet767e97e2010-10-06 17:49:21 -0700507 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
508 lockdep_is_held(&tbl->lock));
509 n1 != NULL;
510 n1 = rcu_dereference_protected(n1->next,
511 lockdep_is_held(&tbl->lock))) {
Jim Westfall014510b2018-01-14 04:18:50 -0800512 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700513 if (want_ref)
514 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 rc = n1;
516 goto out_tbl_unlock;
517 }
518 }
519
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700521 if (want_ref)
522 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700523 rcu_assign_pointer(n->next,
524 rcu_dereference_protected(nht->hash_buckets[hash_val],
525 lockdep_is_held(&tbl->lock)));
526 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000528 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 rc = n;
530out:
531 return rc;
532out_tbl_unlock:
533 write_unlock_bh(&tbl->lock);
534out_neigh_release:
535 neigh_release(n);
536 goto out;
537}
David S. Millera263b302012-07-02 02:02:15 -0700538EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900540static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700541{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700542 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700543 hash_val ^= (hash_val >> 16);
544 hash_val ^= hash_val >> 8;
545 hash_val ^= hash_val >> 4;
546 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900547 return hash_val;
548}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700549
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900550static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
551 struct net *net,
552 const void *pkey,
553 int key_len,
554 struct net_device *dev)
555{
556 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700557 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900558 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700559 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900560 return n;
561 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700562 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900563 return NULL;
564}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700565
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900566struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
567 struct net *net, const void *pkey, struct net_device *dev)
568{
569 int key_len = tbl->key_len;
570 u32 hash_val = pneigh_hash(pkey, key_len);
571
572 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
573 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700574}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900575EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576
Eric W. Biederman426b5302008-01-24 00:13:18 -0800577struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
578 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 struct net_device *dev, int creat)
580{
581 struct pneigh_entry *n;
582 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900583 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584
585 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900586 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
587 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900589
590 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 goto out;
592
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700593 ASSERT_RTNL();
594
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
596 if (!n)
597 goto out;
598
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500599 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600 memcpy(n->key, pkey, key_len);
601 n->dev = dev;
602 if (dev)
603 dev_hold(dev);
604
605 if (tbl->pconstructor && tbl->pconstructor(n)) {
606 if (dev)
607 dev_put(dev);
608 kfree(n);
609 n = NULL;
610 goto out;
611 }
612
613 write_lock_bh(&tbl->lock);
614 n->next = tbl->phash_buckets[hash_val];
615 tbl->phash_buckets[hash_val] = n;
616 write_unlock_bh(&tbl->lock);
617out:
618 return n;
619}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900620EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622
Eric W. Biederman426b5302008-01-24 00:13:18 -0800623int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 struct net_device *dev)
625{
626 struct pneigh_entry *n, **np;
627 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900628 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629
630 write_lock_bh(&tbl->lock);
631 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
632 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800633 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900634 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 *np = n->next;
636 write_unlock_bh(&tbl->lock);
637 if (tbl->pdestructor)
638 tbl->pdestructor(n);
639 if (n->dev)
640 dev_put(n->dev);
641 kfree(n);
642 return 0;
643 }
644 }
645 write_unlock_bh(&tbl->lock);
646 return -ENOENT;
647}
648
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200649static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
650 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200652 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 u32 h;
654
655 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
656 np = &tbl->phash_buckets[h];
657 while ((n = *np) != NULL) {
658 if (!dev || n->dev == dev) {
659 *np = n->next;
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200660 n->next = freelist;
661 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662 continue;
663 }
664 np = &n->next;
665 }
666 }
Wolfgang Bumiller581cb192018-04-12 10:46:55 +0200667 write_unlock_bh(&tbl->lock);
668 while ((n = freelist)) {
669 freelist = n->next;
670 n->next = NULL;
671 if (tbl->pdestructor)
672 tbl->pdestructor(n);
673 if (n->dev)
674 dev_put(n->dev);
675 kfree(n);
676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 return -ENOENT;
678}
679
Denis V. Lunev06f05112008-01-24 00:30:58 -0800680static void neigh_parms_destroy(struct neigh_parms *parms);
681
682static inline void neigh_parms_put(struct neigh_parms *parms)
683{
684 if (atomic_dec_and_test(&parms->refcnt))
685 neigh_parms_destroy(parms);
686}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687
688/*
689 * neighbour must already be out of the table;
690 *
691 */
692void neigh_destroy(struct neighbour *neigh)
693{
David Millerda6a8fa2011-07-25 00:01:38 +0000694 struct net_device *dev = neigh->dev;
695
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
697
698 if (!neigh->dead) {
Tejaswi Tanikellad40dd0f2017-07-25 13:30:09 +0530699 pr_warn("Destroying alive neighbour %pK\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700700 dump_stack();
701 return;
702 }
703
704 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000705 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700707 write_lock_bh(&neigh->lock);
708 __skb_queue_purge(&neigh->arp_queue);
709 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000710 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
David S. Miller447f2192011-12-19 15:04:41 -0500712 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200713 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500714
David Millerda6a8fa2011-07-25 00:01:38 +0000715 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716 neigh_parms_put(neigh->parms);
717
Joe Perchesd5d427c2013-04-15 15:17:19 +0000718 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
720 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000721 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900723EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725/* Neighbour state is suspicious;
726 disable fast path.
727
728 Called with write_locked neigh.
729 */
730static void neigh_suspect(struct neighbour *neigh)
731{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000732 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
734 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700735}
736
737/* Neighbour state is OK;
738 enable fast path.
739
740 Called with write_locked neigh.
741 */
742static void neigh_connect(struct neighbour *neigh)
743{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000744 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700745
746 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747}
748
Eric Dumazete4c4e442009-07-30 03:15:07 +0000749static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000751 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700752 struct neighbour *n;
753 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000754 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000755 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756
757 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
758
Eric Dumazete4c4e442009-07-30 03:15:07 +0000759 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000760 nht = rcu_dereference_protected(tbl->nht,
761 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762
763 /*
764 * periodically recompute ReachableTime from random function
765 */
766
Eric Dumazete4c4e442009-07-30 03:15:07 +0000767 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000769 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100770 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100772 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773 }
774
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800775 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
776 goto out;
777
David S. Millercd089332011-07-11 01:28:12 -0700778 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000779 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780
Eric Dumazet767e97e2010-10-06 17:49:21 -0700781 while ((n = rcu_dereference_protected(*np,
782 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000783 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
Eric Dumazete4c4e442009-07-30 03:15:07 +0000785 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Eric Dumazete4c4e442009-07-30 03:15:07 +0000787 state = n->nud_state;
788 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
789 write_unlock(&n->lock);
790 goto next_elt;
791 }
792
793 if (time_before(n->used, n->confirmed))
794 n->used = n->confirmed;
795
796 if (atomic_read(&n->refcnt) == 1 &&
797 (state == NUD_FAILED ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100798 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000799 *np = n->next;
800 n->dead = 1;
801 write_unlock(&n->lock);
802 neigh_cleanup_and_release(n);
803 continue;
804 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806
807next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000808 np = &n->next;
809 }
810 /*
811 * It's fine to release lock here, even if hash table
812 * grows while we are preempted.
813 */
814 write_unlock_bh(&tbl->lock);
815 cond_resched();
816 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500817 nht = rcu_dereference_protected(tbl->nht,
818 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000820out:
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100821 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
822 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
823 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 */
viresh kumarf6180022014-01-22 12:23:33 +0530825 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100826 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000827 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828}
829
830static __inline__ int neigh_max_probes(struct neighbour *n)
831{
832 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900833 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
834 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
835 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836}
837
Timo Teras5ef12d92009-06-11 04:16:28 -0700838static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000839 __releases(neigh->lock)
840 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700841{
842 struct sk_buff *skb;
843
844 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000845 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700846 neigh->updated = jiffies;
847
848 /* It is very thin place. report_unreachable is very complicated
849 routine. Particularly, it can hit the same neighbour entry!
850
851 So that, we try to be accurate and avoid dead loop. --ANK
852 */
853 while (neigh->nud_state == NUD_FAILED &&
854 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
855 write_unlock(&neigh->lock);
856 neigh->ops->error_report(neigh, skb);
857 write_lock(&neigh->lock);
858 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700859 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000860 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700861}
862
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000863static void neigh_probe(struct neighbour *neigh)
864 __releases(neigh->lock)
865{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200866 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000867 /* keep skb alive even if arp_queue overflows */
868 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800869 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000870 write_unlock(&neigh->lock);
Eric Dumazet4f991612017-03-23 12:39:21 -0700871 if (neigh->ops->solicit)
872 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000873 atomic_inc(&neigh->probes);
874 kfree_skb(skb);
875}
876
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877/* Called when a timer expires for a neighbour entry. */
878
879static void neigh_timer_handler(unsigned long arg)
880{
881 unsigned long now, next;
882 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000883 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884 int notify = 0;
885
886 write_lock(&neigh->lock);
887
888 state = neigh->nud_state;
889 now = jiffies;
890 next = now + HZ;
891
Mohammed Javidbead6462018-05-17 23:57:40 +0530892 if (!(state & NUD_IN_TIMER)) {
893 if (neigh_probe_enable && (state & NUD_STALE))
894 neigh_dbg(2, "neigh %pK is still alive\n", neigh);
895 else
896 goto out;
897 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900899 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000901 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 next = neigh->confirmed + neigh->parms->reachable_time;
903 } else if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100904 neigh->used +
905 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000906 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800908 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 neigh_suspect(neigh);
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100910 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000912 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800914 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700916 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 }
918 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900919 if (time_before_eq(now,
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100920 neigh->confirmed +
921 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000922 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800924 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700926 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 next = neigh->confirmed + neigh->parms->reachable_time;
928 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000929 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800931 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900933 notify = 1;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100934 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 }
936 } else {
937 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100938 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 }
940
941 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
942 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 neigh->nud_state = NUD_FAILED;
944 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700945 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800946 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 }
948
949 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (time_before(next, jiffies + HZ/2))
951 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000952 if (!mod_timer(&neigh->timer, next))
953 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
Sridhar Anchab7092162016-04-14 21:20:43 +0530955
956 if (neigh_probe_enable) {
957 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE | NUD_STALE))
958 neigh_probe(neigh);
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530959 else
960 write_unlock(&neigh->lock);
David S. Miller9ff56602008-02-17 18:39:54 -0800961 } else {
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530962 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
963 neigh_probe(neigh);
964 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800965out:
Sridhar Ancha03d25f82016-05-05 12:30:54 +0530966 write_unlock(&neigh->lock);
967 }
David S. Miller9ff56602008-02-17 18:39:54 -0800968 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700969
Thomas Grafd961db32007-08-08 23:12:56 -0700970 if (notify)
971 neigh_update_notify(neigh);
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973 neigh_release(neigh);
974}
975
976int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
977{
978 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000979 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980
981 write_lock_bh(&neigh->lock);
982
983 rc = 0;
984 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
985 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +0300986 if (neigh->dead)
987 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100990 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
991 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000992 unsigned long next, now = jiffies;
993
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100994 atomic_set(&neigh->probes,
995 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000997 neigh->updated = now;
Jiri Pirko1f9248e52013-12-07 19:26:53 +0100998 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
999 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001000 neigh_add_timer(neigh, next);
1001 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 } else {
1003 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001004 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 write_unlock_bh(&neigh->lock);
1006
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001007 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008 return 1;
1009 }
1010 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001011 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001013 neigh->updated = jiffies;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001014 neigh_add_timer(neigh, jiffies +
1015 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017
1018 if (neigh->nud_state == NUD_INCOMPLETE) {
1019 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001020 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001021 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001023
David S. Millerf72051b2008-09-23 01:11:18 -07001024 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001025 if (!buff)
1026 break;
1027 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001029 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001031 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001033 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 }
1035 rc = 1;
1036 }
1037out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001038 if (immediate_probe)
1039 neigh_probe(neigh);
1040 else
1041 write_unlock(&neigh->lock);
1042 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001044
1045out_dead:
1046 if (neigh->nud_state & NUD_STALE)
1047 goto out_unlock_bh;
1048 write_unlock_bh(&neigh->lock);
1049 kfree_skb(skb);
1050 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001052EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
David S. Millerf6b72b62011-07-14 07:53:20 -07001054static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055{
1056 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001057 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001058 = NULL;
1059
1060 if (neigh->dev->header_ops)
1061 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001064 hh = &neigh->hh;
1065 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001066 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001068 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
1070 }
1071}
1072
1073
1074
1075/* Generic update routine.
1076 -- lladdr is new lladdr or NULL, if it is not supplied.
1077 -- new is new state.
1078 -- flags
1079 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1080 if it is different.
1081 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001082 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1085
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001086 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 NTF_ROUTER flag.
1088 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1089 a router.
1090
1091 Caller MUST hold reference count on the entry.
1092 */
1093
1094int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1095 u32 flags)
1096{
1097 u8 old;
1098 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 struct net_device *dev;
1101 int update_isrouter = 0;
1102
1103 write_lock_bh(&neigh->lock);
1104
1105 dev = neigh->dev;
1106 old = neigh->nud_state;
1107 err = -EPERM;
1108
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001109 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 (old & (NUD_NOARP | NUD_PERMANENT)))
1111 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001112 if (neigh->dead)
1113 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114
1115 if (!(new & NUD_VALID)) {
1116 neigh_del_timer(neigh);
1117 if (old & NUD_CONNECTED)
1118 neigh_suspect(neigh);
1119 neigh->nud_state = new;
1120 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001122 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1123 (new & NUD_FAILED)) {
1124 neigh_invalidate(neigh);
1125 notify = 1;
1126 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 goto out;
1128 }
1129
1130 /* Compare new lladdr with cached one */
1131 if (!dev->addr_len) {
1132 /* First case: device needs no address. */
1133 lladdr = neigh->ha;
1134 } else if (lladdr) {
1135 /* The second case: if something is already cached
1136 and a new address is proposed:
1137 - compare new & old
1138 - if they are different, check override flag
1139 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001140 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 !memcmp(lladdr, neigh->ha, dev->addr_len))
1142 lladdr = neigh->ha;
1143 } else {
1144 /* No address is supplied; if we know something,
1145 use it, otherwise discard the request.
1146 */
1147 err = -EINVAL;
1148 if (!(old & NUD_VALID))
1149 goto out;
1150 lladdr = neigh->ha;
1151 }
1152
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 /* If entry was valid and address is not changed,
1154 do not change entry state, if new one is STALE.
1155 */
1156 err = 0;
1157 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1158 if (old & NUD_VALID) {
1159 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1160 update_isrouter = 0;
1161 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1162 (old & NUD_CONNECTED)) {
1163 lladdr = neigh->ha;
1164 new = NUD_STALE;
1165 } else
1166 goto out;
1167 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001168 if (lladdr == neigh->ha && new == NUD_STALE &&
1169 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 new = old;
1171 }
1172 }
1173
Ihar Hrachyshka2c260522017-05-16 08:44:24 -07001174 /* Update timestamps only once we know we will make a change to the
1175 * neighbour entry. Otherwise we risk to move the locktime window with
1176 * noop updates and ignore relevant ARP updates.
1177 */
1178 if (new != old || lladdr != neigh->ha) {
1179 if (new & NUD_CONNECTED)
1180 neigh->confirmed = jiffies;
1181 neigh->updated = jiffies;
1182 }
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 if (new != old) {
1185 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001186 if (new & NUD_PROBE)
1187 atomic_set(&neigh->probes, 0);
Mohammed Javidbead6462018-05-17 23:57:40 +05301188 if (new & NUD_IN_TIMER || (
1189 neigh_probe_enable &&
1190 (neigh->tbl->family == AF_INET6) &&
1191 (new & NUD_STALE)))
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001192 neigh_add_timer(neigh, (jiffies +
1193 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001194 neigh->parms->reachable_time :
1195 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001196 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001197 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 }
1199
1200 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001201 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001203 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 neigh_update_hhs(neigh);
1205 if (!(new & NUD_CONNECTED))
1206 neigh->confirmed = jiffies -
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001207 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 }
1210 if (new == old)
1211 goto out;
1212 if (new & NUD_CONNECTED)
1213 neigh_connect(neigh);
1214 else
1215 neigh_suspect(neigh);
1216 if (!(old & NUD_VALID)) {
1217 struct sk_buff *skb;
1218
1219 /* Again: avoid dead loop if something went wrong */
1220
1221 while (neigh->nud_state & NUD_VALID &&
1222 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001223 struct dst_entry *dst = skb_dst(skb);
1224 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001226
1227 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001228
1229 /* Why not just use 'neigh' as-is? The problem is that
1230 * things such as shaper, eql, and sch_teql can end up
1231 * using alternative, different, neigh objects to output
1232 * the packet in the output path. So what we need to do
1233 * here is re-lookup the top-level neigh in the path so
1234 * we can reinject the packet there.
1235 */
1236 n2 = NULL;
1237 if (dst) {
1238 n2 = dst_neigh_lookup_skb(dst, skb);
1239 if (n2)
1240 n1 = n2;
1241 }
David S. Miller8f40b162011-07-17 13:34:11 -07001242 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001243 if (n2)
1244 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001245 rcu_read_unlock();
1246
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 write_lock_bh(&neigh->lock);
1248 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001249 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001250 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251 }
1252out:
1253 if (update_isrouter) {
1254 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1255 (neigh->flags | NTF_ROUTER) :
1256 (neigh->flags & ~NTF_ROUTER);
1257 }
1258 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001259
1260 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001261 neigh_update_notify(neigh);
1262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263 return err;
1264}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001265EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266
Jiri Benc7e980562013-12-11 13:48:20 +01001267/* Update the neigh to listen temporarily for probe responses, even if it is
1268 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1269 */
1270void __neigh_set_probe_once(struct neighbour *neigh)
1271{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001272 if (neigh->dead)
1273 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001274 neigh->updated = jiffies;
1275 if (!(neigh->nud_state & NUD_FAILED))
1276 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001277 neigh->nud_state = NUD_INCOMPLETE;
1278 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001279 neigh_add_timer(neigh,
1280 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1281}
1282EXPORT_SYMBOL(__neigh_set_probe_once);
1283
Linus Torvalds1da177e2005-04-16 15:20:36 -07001284struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1285 u8 *lladdr, void *saddr,
1286 struct net_device *dev)
1287{
1288 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1289 lladdr || !dev->addr_len);
Ravinder Konkaa71b6682015-04-09 11:42:00 +05301290 if (neigh) {
1291 if (neigh_probe_enable) {
1292 if (!(neigh->nud_state == NUD_REACHABLE)) {
1293 neigh_update(neigh, lladdr, NUD_STALE,
1294 NEIGH_UPDATE_F_OVERRIDE);
1295 write_lock(&neigh->lock);
1296 neigh_probe(neigh);
1297 neigh_update_notify(neigh);
1298 }
1299 } else {
1300 neigh_update(neigh, lladdr, NUD_STALE,
1301 NEIGH_UPDATE_F_OVERRIDE);
1302 }
1303 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 return neigh;
1305}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001306EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307
Eric Dumazet34d101d2010-10-11 09:16:57 -07001308/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001309static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001311 struct net_device *dev = n->dev;
1312 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001313 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001314
1315 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001316
David S. Millerf6b72b62011-07-14 07:53:20 -07001317 /* Only one thread can come in here and initialize the
1318 * hh_cache entry.
1319 */
David S. Millerb23b5452011-07-16 17:45:02 -07001320 if (!hh->hh_len)
1321 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001322
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001323 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324}
1325
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326/* Slow and careful. */
1327
David S. Miller8f40b162011-07-17 13:34:11 -07001328int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 int rc = 0;
1331
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 if (!neigh_event_send(neigh, skb)) {
1333 int err;
1334 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001335 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001336
David S. Millerf6b72b62011-07-14 07:53:20 -07001337 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001338 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001339
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001340 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001341 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001342 seq = read_seqbegin(&neigh->ha_lock);
1343 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1344 neigh->ha, NULL, skb->len);
1345 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001348 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 else
1350 goto out_kfree_skb;
1351 }
1352out:
1353 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354out_kfree_skb:
1355 rc = -EINVAL;
1356 kfree_skb(skb);
1357 goto out;
1358}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001359EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361/* As fast as possible without hh cache */
1362
David S. Miller8f40b162011-07-17 13:34:11 -07001363int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001366 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001367 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001369 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001370 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001371 seq = read_seqbegin(&neigh->ha_lock);
1372 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1373 neigh->ha, NULL, skb->len);
1374 } while (read_seqretry(&neigh->ha_lock, seq));
1375
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001377 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 else {
1379 err = -EINVAL;
1380 kfree_skb(skb);
1381 }
1382 return err;
1383}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001384EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
David S. Miller8f40b162011-07-17 13:34:11 -07001386int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1387{
1388 return dev_queue_xmit(skb);
1389}
1390EXPORT_SYMBOL(neigh_direct_output);
1391
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392static void neigh_proxy_process(unsigned long arg)
1393{
1394 struct neigh_table *tbl = (struct neigh_table *)arg;
1395 long sched_next = 0;
1396 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001397 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398
1399 spin_lock(&tbl->proxy_queue.lock);
1400
David S. Millerf72051b2008-09-23 01:11:18 -07001401 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1402 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001405 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001406
David S. Millerf72051b2008-09-23 01:11:18 -07001407 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001408 if (tbl->proxy_redo && netif_running(dev)) {
1409 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001410 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001411 rcu_read_unlock();
1412 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001413 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001414 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
1416 dev_put(dev);
1417 } else if (!sched_next || tdif < sched_next)
1418 sched_next = tdif;
1419 }
1420 del_timer(&tbl->proxy_timer);
1421 if (sched_next)
1422 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1423 spin_unlock(&tbl->proxy_queue.lock);
1424}
1425
1426void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1427 struct sk_buff *skb)
1428{
1429 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001430
1431 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001432 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001434 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 kfree_skb(skb);
1436 return;
1437 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001438
1439 NEIGH_CB(skb)->sched_next = sched_next;
1440 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441
1442 spin_lock(&tbl->proxy_queue.lock);
1443 if (del_timer(&tbl->proxy_timer)) {
1444 if (time_before(tbl->proxy_timer.expires, sched_next))
1445 sched_next = tbl->proxy_timer.expires;
1446 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001447 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 dev_hold(skb->dev);
1449 __skb_queue_tail(&tbl->proxy_queue, skb);
1450 mod_timer(&tbl->proxy_timer, sched_next);
1451 spin_unlock(&tbl->proxy_queue.lock);
1452}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001453EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001455static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001456 struct net *net, int ifindex)
1457{
1458 struct neigh_parms *p;
1459
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001460 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001461 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001462 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001463 return p;
1464 }
1465
1466 return NULL;
1467}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
1469struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1470 struct neigh_table *tbl)
1471{
Gao fengcf89d6b2013-06-20 10:01:32 +08001472 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001473 struct net *net = dev_net(dev);
1474 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475
Gao fengcf89d6b2013-06-20 10:01:32 +08001476 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478 p->tbl = tbl;
1479 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 p->reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001481 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001482 dev_hold(dev);
1483 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001484 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001486
1487 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001488 dev_put(dev);
1489 kfree(p);
1490 return NULL;
1491 }
1492
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001494 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001496
1497 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 }
1499 return p;
1500}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001501EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502
1503static void neigh_rcu_free_parms(struct rcu_head *head)
1504{
1505 struct neigh_parms *parms =
1506 container_of(head, struct neigh_parms, rcu_head);
1507
1508 neigh_parms_put(parms);
1509}
1510
1511void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1512{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513 if (!parms || parms == &tbl->parms)
1514 return;
1515 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001516 list_del(&parms->list);
1517 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001519 if (parms->dev)
1520 dev_put(parms->dev);
1521 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001523EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524
Denis V. Lunev06f05112008-01-24 00:30:58 -08001525static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526{
1527 kfree(parms);
1528}
1529
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001530static struct lock_class_key neigh_table_proxy_queue_class;
1531
WANG Congd7480fd2014-11-10 15:59:36 -08001532static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1533
1534void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535{
1536 unsigned long now = jiffies;
1537 unsigned long phsize;
1538
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001539 INIT_LIST_HEAD(&tbl->parms_list);
1540 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001541 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001542 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 tbl->parms.reachable_time =
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001544 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 tbl->stats = alloc_percpu(struct neigh_statistics);
1547 if (!tbl->stats)
1548 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001549
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001551 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1552 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554#endif
1555
David S. Millercd089332011-07-11 01:28:12 -07001556 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
1558 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001559 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001561 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562 panic("cannot allocate neighbour cache hashes");
1563
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001564 if (!tbl->entry_size)
1565 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1566 tbl->key_len, NEIGH_PRIV_ALIGN);
1567 else
1568 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1569
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001571 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301572 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1573 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001574 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001575 skb_queue_head_init_class(&tbl->proxy_queue,
1576 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
1578 tbl->last_flush = now;
1579 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001580
WANG Congd7480fd2014-11-10 15:59:36 -08001581 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001582}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001583EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584
WANG Congd7480fd2014-11-10 15:59:36 -08001585int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586{
WANG Congd7480fd2014-11-10 15:59:36 -08001587 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001589 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 del_timer_sync(&tbl->proxy_timer);
1591 pneigh_queue_purge(&tbl->proxy_queue);
1592 neigh_ifdown(tbl, NULL);
1593 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001594 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001596 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1597 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001598 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599
1600 kfree(tbl->phash_buckets);
1601 tbl->phash_buckets = NULL;
1602
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001603 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1604
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001605 free_percpu(tbl->stats);
1606 tbl->stats = NULL;
1607
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 return 0;
1609}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001610EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611
WANG Congd7480fd2014-11-10 15:59:36 -08001612static struct neigh_table *neigh_find_table(int family)
1613{
1614 struct neigh_table *tbl = NULL;
1615
1616 switch (family) {
1617 case AF_INET:
1618 tbl = neigh_tables[NEIGH_ARP_TABLE];
1619 break;
1620 case AF_INET6:
1621 tbl = neigh_tables[NEIGH_ND_TABLE];
1622 break;
1623 case AF_DECnet:
1624 tbl = neigh_tables[NEIGH_DN_TABLE];
1625 break;
1626 }
1627
1628 return tbl;
1629}
1630
Thomas Graf661d2962013-03-21 07:45:29 +00001631static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001632{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001633 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001634 struct ndmsg *ndm;
1635 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001637 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001639 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640
Eric Dumazet110b2492010-10-04 04:27:36 +00001641 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001642 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 goto out;
1644
Thomas Grafa14a49d2006-08-07 17:53:08 -07001645 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1646 if (dst_attr == NULL)
1647 goto out;
1648
1649 ndm = nlmsg_data(nlh);
1650 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001651 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001652 if (dev == NULL) {
1653 err = -ENODEV;
1654 goto out;
1655 }
1656 }
1657
WANG Congd7480fd2014-11-10 15:59:36 -08001658 tbl = neigh_find_table(ndm->ndm_family);
1659 if (tbl == NULL)
1660 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
WANG Congd7480fd2014-11-10 15:59:36 -08001662 if (nla_len(dst_attr) < tbl->key_len)
1663 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
WANG Congd7480fd2014-11-10 15:59:36 -08001665 if (ndm->ndm_flags & NTF_PROXY) {
1666 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001667 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 }
WANG Congd7480fd2014-11-10 15:59:36 -08001669
1670 if (dev == NULL)
1671 goto out;
1672
1673 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1674 if (neigh == NULL) {
1675 err = -ENOENT;
1676 goto out;
1677 }
1678
1679 err = neigh_update(neigh, NULL, NUD_FAILED,
1680 NEIGH_UPDATE_F_OVERRIDE |
1681 NEIGH_UPDATE_F_ADMIN);
1682 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001683
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684out:
1685 return err;
1686}
1687
Thomas Graf661d2962013-03-21 07:45:29 +00001688static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689{
WANG Congd7480fd2014-11-10 15:59:36 -08001690 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001691 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001692 struct ndmsg *ndm;
1693 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 struct neigh_table *tbl;
1695 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001696 struct neighbour *neigh;
1697 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001698 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699
Eric Dumazet110b2492010-10-04 04:27:36 +00001700 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001701 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1702 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 goto out;
1704
Thomas Graf5208deb2006-08-07 17:55:40 -07001705 err = -EINVAL;
1706 if (tb[NDA_DST] == NULL)
1707 goto out;
1708
1709 ndm = nlmsg_data(nlh);
1710 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001711 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001712 if (dev == NULL) {
1713 err = -ENODEV;
1714 goto out;
1715 }
1716
1717 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001718 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001719 }
1720
WANG Congd7480fd2014-11-10 15:59:36 -08001721 tbl = neigh_find_table(ndm->ndm_family);
1722 if (tbl == NULL)
1723 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
WANG Congd7480fd2014-11-10 15:59:36 -08001725 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1726 goto out;
1727 dst = nla_data(tb[NDA_DST]);
1728 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729
WANG Congd7480fd2014-11-10 15:59:36 -08001730 if (ndm->ndm_flags & NTF_PROXY) {
1731 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
WANG Congd7480fd2014-11-10 15:59:36 -08001733 err = -ENOBUFS;
1734 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1735 if (pn) {
1736 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001737 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001738 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001739 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740 }
1741
WANG Congd7480fd2014-11-10 15:59:36 -08001742 if (dev == NULL)
1743 goto out;
1744
1745 neigh = neigh_lookup(tbl, dst, dev);
1746 if (neigh == NULL) {
1747 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1748 err = -ENOENT;
1749 goto out;
1750 }
1751
1752 neigh = __neigh_lookup_errno(tbl, dst, dev);
1753 if (IS_ERR(neigh)) {
1754 err = PTR_ERR(neigh);
1755 goto out;
1756 }
1757 } else {
1758 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1759 err = -EEXIST;
1760 neigh_release(neigh);
1761 goto out;
1762 }
1763
1764 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1765 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1766 }
1767
1768 if (ndm->ndm_flags & NTF_USE) {
1769 neigh_event_send(neigh, NULL);
1770 err = 0;
1771 } else
1772 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1773 neigh_release(neigh);
1774
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775out:
1776 return err;
1777}
1778
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001779static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1780{
Thomas Grafca860fb2006-08-07 18:00:18 -07001781 struct nlattr *nest;
1782
1783 nest = nla_nest_start(skb, NDTA_PARMS);
1784 if (nest == NULL)
1785 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001786
David S. Miller9a6308d2012-04-01 20:06:28 -04001787 if ((parms->dev &&
1788 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1789 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001790 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1791 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001792 /* approximative value for deprecated QUEUE_LEN (in packets) */
1793 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001794 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1795 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1796 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1797 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1798 NEIGH_VAR(parms, UCAST_PROBES)) ||
1799 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1800 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001801 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1802 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001803 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1804 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001805 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001806 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001807 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001808 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001809 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001810 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001811 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001812 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001813 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001814 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001815 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001816 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e52013-12-07 19:26:53 +01001817 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001818 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001819 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001820 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001821
Thomas Grafca860fb2006-08-07 18:00:18 -07001822nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001823 nla_nest_cancel(skb, nest);
1824 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001825}
1826
Thomas Grafca860fb2006-08-07 18:00:18 -07001827static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1828 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001829{
1830 struct nlmsghdr *nlh;
1831 struct ndtmsg *ndtmsg;
1832
Thomas Grafca860fb2006-08-07 18:00:18 -07001833 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1834 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001835 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001836
Thomas Grafca860fb2006-08-07 18:00:18 -07001837 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001838
1839 read_lock_bh(&tbl->lock);
1840 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001841 ndtmsg->ndtm_pad1 = 0;
1842 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001843
David S. Miller9a6308d2012-04-01 20:06:28 -04001844 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001845 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001846 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1847 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1848 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1849 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001850 {
1851 unsigned long now = jiffies;
1852 unsigned int flush_delta = now - tbl->last_flush;
1853 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001854 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855 struct ndt_config ndc = {
1856 .ndtc_key_len = tbl->key_len,
1857 .ndtc_entry_size = tbl->entry_size,
1858 .ndtc_entries = atomic_read(&tbl->entries),
1859 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1860 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001861 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1862 };
1863
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001864 rcu_read_lock_bh();
1865 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001866 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001867 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001868 rcu_read_unlock_bh();
1869
David S. Miller9a6308d2012-04-01 20:06:28 -04001870 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1871 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001872 }
1873
1874 {
1875 int cpu;
1876 struct ndt_stats ndst;
1877
1878 memset(&ndst, 0, sizeof(ndst));
1879
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001880 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881 struct neigh_statistics *st;
1882
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001883 st = per_cpu_ptr(tbl->stats, cpu);
1884 ndst.ndts_allocs += st->allocs;
1885 ndst.ndts_destroys += st->destroys;
1886 ndst.ndts_hash_grows += st->hash_grows;
1887 ndst.ndts_res_failed += st->res_failed;
1888 ndst.ndts_lookups += st->lookups;
1889 ndst.ndts_hits += st->hits;
1890 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1891 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1892 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1893 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001894 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001895 }
1896
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001897 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1898 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001899 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001900 }
1901
1902 BUG_ON(tbl->parms.dev);
1903 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001904 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001905
1906 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001907 nlmsg_end(skb, nlh);
1908 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001909
Thomas Grafca860fb2006-08-07 18:00:18 -07001910nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001911 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001912 nlmsg_cancel(skb, nlh);
1913 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001914}
1915
Thomas Grafca860fb2006-08-07 18:00:18 -07001916static int neightbl_fill_param_info(struct sk_buff *skb,
1917 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001918 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001919 u32 pid, u32 seq, int type,
1920 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921{
1922 struct ndtmsg *ndtmsg;
1923 struct nlmsghdr *nlh;
1924
Thomas Grafca860fb2006-08-07 18:00:18 -07001925 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1926 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001927 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001928
Thomas Grafca860fb2006-08-07 18:00:18 -07001929 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930
1931 read_lock_bh(&tbl->lock);
1932 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001933 ndtmsg->ndtm_pad1 = 0;
1934 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001935
Thomas Grafca860fb2006-08-07 18:00:18 -07001936 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1937 neightbl_fill_parms(skb, parms) < 0)
1938 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001939
1940 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001941 nlmsg_end(skb, nlh);
1942 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001943errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001945 nlmsg_cancel(skb, nlh);
1946 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001947}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001948
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001949static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001950 [NDTA_NAME] = { .type = NLA_STRING },
1951 [NDTA_THRESH1] = { .type = NLA_U32 },
1952 [NDTA_THRESH2] = { .type = NLA_U32 },
1953 [NDTA_THRESH3] = { .type = NLA_U32 },
1954 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1955 [NDTA_PARMS] = { .type = NLA_NESTED },
1956};
1957
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001958static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001959 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1960 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1961 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1962 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1963 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1964 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001965 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001966 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1967 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1968 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1969 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1970 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1971 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1972 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1973};
1974
Thomas Graf661d2962013-03-21 07:45:29 +00001975static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001976{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001977 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001978 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001979 struct ndtmsg *ndtmsg;
1980 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001981 bool found = false;
1982 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001983
Thomas Graf6b3f8672006-08-07 17:58:53 -07001984 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1985 nl_neightbl_policy);
1986 if (err < 0)
1987 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988
Thomas Graf6b3f8672006-08-07 17:58:53 -07001989 if (tb[NDTA_NAME] == NULL) {
1990 err = -EINVAL;
1991 goto errout;
1992 }
1993
1994 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001995
1996 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1997 tbl = neigh_tables[tidx];
1998 if (!tbl)
1999 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002000 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2001 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002002 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2003 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002004 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002005 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002006 }
2007
WANG Congd7480fd2014-11-10 15:59:36 -08002008 if (!found)
2009 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002011 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012 * We acquire tbl->lock to be nice to the periodic timers and
2013 * make sure they always see a consistent set of values.
2014 */
2015 write_lock_bh(&tbl->lock);
2016
Thomas Graf6b3f8672006-08-07 17:58:53 -07002017 if (tb[NDTA_PARMS]) {
2018 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002019 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002020 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002021
Thomas Graf6b3f8672006-08-07 17:58:53 -07002022 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2023 nl_ntbl_parm_policy);
2024 if (err < 0)
2025 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002026
Thomas Graf6b3f8672006-08-07 17:58:53 -07002027 if (tbp[NDTPA_IFINDEX])
2028 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002029
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002030 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002031 if (p == NULL) {
2032 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002033 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002034 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002035
Thomas Graf6b3f8672006-08-07 17:58:53 -07002036 for (i = 1; i <= NDTPA_MAX; i++) {
2037 if (tbp[i] == NULL)
2038 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002039
Thomas Graf6b3f8672006-08-07 17:58:53 -07002040 switch (i) {
2041 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002042 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2043 nla_get_u32(tbp[i]) *
2044 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002045 break;
2046 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002047 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2048 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002049 break;
2050 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002051 NEIGH_VAR_SET(p, PROXY_QLEN,
2052 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002053 break;
2054 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002055 NEIGH_VAR_SET(p, APP_PROBES,
2056 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002057 break;
2058 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002059 NEIGH_VAR_SET(p, UCAST_PROBES,
2060 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002061 break;
2062 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002063 NEIGH_VAR_SET(p, MCAST_PROBES,
2064 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002065 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002066 case NDTPA_MCAST_REPROBES:
2067 NEIGH_VAR_SET(p, MCAST_REPROBES,
2068 nla_get_u32(tbp[i]));
2069 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002070 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002071 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2072 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002073 /* update reachable_time as well, otherwise, the change will
2074 * only be effective after the next time neigh_periodic_work
2075 * decides to recompute it (can be multiple minutes)
2076 */
2077 p->reachable_time =
2078 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002079 break;
2080 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002081 NEIGH_VAR_SET(p, GC_STALETIME,
2082 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002083 break;
2084 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002085 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2086 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002087 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002088 break;
2089 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002090 NEIGH_VAR_SET(p, RETRANS_TIME,
2091 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002092 break;
2093 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002094 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2095 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002096 break;
2097 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002098 NEIGH_VAR_SET(p, PROXY_DELAY,
2099 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002100 break;
2101 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002102 NEIGH_VAR_SET(p, LOCKTIME,
2103 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002104 break;
2105 }
2106 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002107 }
2108
Gao fengdc25c672013-06-20 10:01:34 +08002109 err = -ENOENT;
2110 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2111 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2112 !net_eq(net, &init_net))
2113 goto errout_tbl_lock;
2114
Thomas Graf6b3f8672006-08-07 17:58:53 -07002115 if (tb[NDTA_THRESH1])
2116 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2117
2118 if (tb[NDTA_THRESH2])
2119 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2120
2121 if (tb[NDTA_THRESH3])
2122 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2123
2124 if (tb[NDTA_GC_INTERVAL])
2125 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2126
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002127 err = 0;
2128
Thomas Graf6b3f8672006-08-07 17:58:53 -07002129errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002130 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002131errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002132 return err;
2133}
2134
Thomas Grafc8822a42007-03-22 11:50:06 -07002135static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002136{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002137 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002138 int family, tidx, nidx = 0;
2139 int tbl_skip = cb->args[0];
2140 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002141 struct neigh_table *tbl;
2142
Thomas Grafca860fb2006-08-07 18:00:18 -07002143 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144
WANG Congd7480fd2014-11-10 15:59:36 -08002145 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146 struct neigh_parms *p;
2147
WANG Congd7480fd2014-11-10 15:59:36 -08002148 tbl = neigh_tables[tidx];
2149 if (!tbl)
2150 continue;
2151
Thomas Grafca860fb2006-08-07 18:00:18 -07002152 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002153 continue;
2154
Eric W. Biederman15e47302012-09-07 20:12:54 +00002155 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002156 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002157 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002158 break;
2159
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002160 nidx = 0;
2161 p = list_next_entry(&tbl->parms, list);
2162 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002163 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002164 continue;
2165
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002166 if (nidx < neigh_skip)
2167 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002168
Thomas Grafca860fb2006-08-07 18:00:18 -07002169 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002170 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002171 cb->nlh->nlmsg_seq,
2172 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002173 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002174 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002175 next:
2176 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002177 }
2178
Thomas Grafca860fb2006-08-07 18:00:18 -07002179 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180 }
2181out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002182 cb->args[0] = tidx;
2183 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002184
2185 return skb->len;
2186}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187
Thomas Graf8b8aec52006-08-07 17:56:37 -07002188static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2189 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190{
2191 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002193 struct nlmsghdr *nlh;
2194 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002195
Thomas Graf8b8aec52006-08-07 17:56:37 -07002196 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2197 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002198 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199
2200 ndm = nlmsg_data(nlh);
2201 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002202 ndm->ndm_pad1 = 0;
2203 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002204 ndm->ndm_flags = neigh->flags;
2205 ndm->ndm_type = neigh->type;
2206 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207
David S. Miller9a6308d2012-04-01 20:06:28 -04002208 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2209 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002210
2211 read_lock_bh(&neigh->lock);
2212 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002213 if (neigh->nud_state & NUD_VALID) {
2214 char haddr[MAX_ADDR_LEN];
2215
2216 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2217 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2218 read_unlock_bh(&neigh->lock);
2219 goto nla_put_failure;
2220 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002221 }
2222
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002223 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2224 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2225 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002226 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2227 read_unlock_bh(&neigh->lock);
2228
David S. Miller9a6308d2012-04-01 20:06:28 -04002229 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2230 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2231 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002232
Johannes Berg053c0952015-01-16 22:09:00 +01002233 nlmsg_end(skb, nlh);
2234 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002235
2236nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002237 nlmsg_cancel(skb, nlh);
2238 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002239}
2240
Tony Zelenoff84920c12012-01-26 22:28:58 +00002241static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2242 u32 pid, u32 seq, int type, unsigned int flags,
2243 struct neigh_table *tbl)
2244{
2245 struct nlmsghdr *nlh;
2246 struct ndmsg *ndm;
2247
2248 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2249 if (nlh == NULL)
2250 return -EMSGSIZE;
2251
2252 ndm = nlmsg_data(nlh);
2253 ndm->ndm_family = tbl->family;
2254 ndm->ndm_pad1 = 0;
2255 ndm->ndm_pad2 = 0;
2256 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002257 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002258 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002259 ndm->ndm_state = NUD_NONE;
2260
David S. Miller9a6308d2012-04-01 20:06:28 -04002261 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2262 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002263
Johannes Berg053c0952015-01-16 22:09:00 +01002264 nlmsg_end(skb, nlh);
2265 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002266
2267nla_put_failure:
2268 nlmsg_cancel(skb, nlh);
2269 return -EMSGSIZE;
2270}
2271
Thomas Grafd961db32007-08-08 23:12:56 -07002272static void neigh_update_notify(struct neighbour *neigh)
2273{
2274 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2275 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2276}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002277
David Ahern21fdd092015-09-29 09:32:03 -07002278static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2279{
2280 struct net_device *master;
2281
2282 if (!master_idx)
2283 return false;
2284
2285 master = netdev_master_upper_dev_get(dev);
2286 if (!master || master->ifindex != master_idx)
2287 return true;
2288
2289 return false;
2290}
2291
David Ahern16660f02015-10-03 11:43:46 -07002292static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2293{
2294 if (filter_idx && dev->ifindex != filter_idx)
2295 return true;
2296
2297 return false;
2298}
2299
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2301 struct netlink_callback *cb)
2302{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002303 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002304 const struct nlmsghdr *nlh = cb->nlh;
2305 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002306 struct neighbour *n;
2307 int rc, h, s_h = cb->args[1];
2308 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002309 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002310 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002311 unsigned int flags = NLM_F_MULTI;
2312 int err;
2313
2314 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL);
2315 if (!err) {
Eric Dumazet0e770d22018-04-11 14:46:00 -07002316 if (tb[NDA_IFINDEX]) {
2317 if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
2318 return -EINVAL;
David Ahern16660f02015-10-03 11:43:46 -07002319 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
Eric Dumazet0e770d22018-04-11 14:46:00 -07002320 }
2321 if (tb[NDA_MASTER]) {
2322 if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
2323 return -EINVAL;
David Ahern21fdd092015-09-29 09:32:03 -07002324 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
Eric Dumazet0e770d22018-04-11 14:46:00 -07002325 }
David Ahern16660f02015-10-03 11:43:46 -07002326 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002327 flags |= NLM_F_DUMP_FILTERED;
2328 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002329
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002330 rcu_read_lock_bh();
2331 nht = rcu_dereference_bh(tbl->nht);
2332
Eric Dumazet4bd66832012-06-07 04:58:35 +00002333 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 if (h > s_h)
2335 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002336 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2337 n != NULL;
2338 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002339 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002340 continue;
David Ahern16660f02015-10-03 11:43:46 -07002341 if (neigh_ifindex_filtered(n->dev, filter_idx))
2342 continue;
David Ahern21fdd092015-09-29 09:32:03 -07002343 if (neigh_master_filtered(n->dev, filter_master_idx))
2344 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002345 if (idx < s_idx)
2346 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002347 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002348 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002349 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002350 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 rc = -1;
2352 goto out;
2353 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002354next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002355 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 }
2358 rc = skb->len;
2359out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002360 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 cb->args[1] = h;
2362 cb->args[2] = idx;
2363 return rc;
2364}
2365
Tony Zelenoff84920c12012-01-26 22:28:58 +00002366static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2367 struct netlink_callback *cb)
2368{
2369 struct pneigh_entry *n;
2370 struct net *net = sock_net(skb->sk);
2371 int rc, h, s_h = cb->args[3];
2372 int idx, s_idx = idx = cb->args[4];
2373
2374 read_lock_bh(&tbl->lock);
2375
Eric Dumazet4bd66832012-06-07 04:58:35 +00002376 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002377 if (h > s_h)
2378 s_idx = 0;
2379 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002380 if (pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002381 continue;
2382 if (idx < s_idx)
2383 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002384 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002385 cb->nlh->nlmsg_seq,
2386 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002387 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002388 read_unlock_bh(&tbl->lock);
2389 rc = -1;
2390 goto out;
2391 }
2392 next:
2393 idx++;
2394 }
2395 }
2396
2397 read_unlock_bh(&tbl->lock);
2398 rc = skb->len;
2399out:
2400 cb->args[3] = h;
2401 cb->args[4] = idx;
2402 return rc;
2403
2404}
2405
Thomas Grafc8822a42007-03-22 11:50:06 -07002406static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407{
2408 struct neigh_table *tbl;
2409 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002410 int proxy = 0;
Eric Dumazet4bd66832012-06-07 04:58:35 +00002411 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412
Thomas Graf8b8aec52006-08-07 17:56:37 -07002413 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002414
2415 /* check for full ndmsg structure presence, family member is
2416 * the same for both structures
2417 */
2418 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2419 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2420 proxy = 1;
2421
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 s_t = cb->args[0];
2423
WANG Congd7480fd2014-11-10 15:59:36 -08002424 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2425 tbl = neigh_tables[t];
2426
2427 if (!tbl)
2428 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429 if (t < s_t || (family && tbl->family != family))
2430 continue;
2431 if (t > s_t)
2432 memset(&cb->args[1], 0, sizeof(cb->args) -
2433 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002434 if (proxy)
2435 err = pneigh_dump_table(tbl, skb, cb);
2436 else
2437 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd66832012-06-07 04:58:35 +00002438 if (err < 0)
2439 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002440 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441
2442 cb->args[0] = t;
2443 return skb->len;
2444}
2445
2446void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2447{
2448 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002449 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002451 rcu_read_lock_bh();
2452 nht = rcu_dereference_bh(tbl->nht);
2453
Eric Dumazet767e97e2010-10-06 17:49:21 -07002454 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002455 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 struct neighbour *n;
2457
Eric Dumazet767e97e2010-10-06 17:49:21 -07002458 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2459 n != NULL;
2460 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002461 cb(n, cookie);
2462 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002463 read_unlock(&tbl->lock);
2464 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465}
2466EXPORT_SYMBOL(neigh_for_each);
2467
2468/* The tbl->lock must be held as a writer and BH disabled. */
2469void __neigh_for_each_release(struct neigh_table *tbl,
2470 int (*cb)(struct neighbour *))
2471{
2472 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002473 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002475 nht = rcu_dereference_protected(tbl->nht,
2476 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002477 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002478 struct neighbour *n;
2479 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002480
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002481 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002482 while ((n = rcu_dereference_protected(*np,
2483 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484 int release;
2485
2486 write_lock(&n->lock);
2487 release = cb(n);
2488 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002489 rcu_assign_pointer(*np,
2490 rcu_dereference_protected(n->next,
2491 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002492 n->dead = 1;
2493 } else
2494 np = &n->next;
2495 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002496 if (release)
2497 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498 }
2499 }
2500}
2501EXPORT_SYMBOL(__neigh_for_each_release);
2502
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002503int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002504 const void *addr, struct sk_buff *skb)
2505{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002506 int err = -EAFNOSUPPORT;
2507 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002508 struct neigh_table *tbl;
2509 struct neighbour *neigh;
2510
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002511 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002512 if (!tbl)
2513 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002514 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002515 neigh = __neigh_lookup_noref(tbl, addr, dev);
2516 if (!neigh)
2517 neigh = __neigh_create(tbl, addr, dev, false);
2518 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002519 if (IS_ERR(neigh)) {
2520 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002521 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002522 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002523 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002524 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002525 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002526 else if (index == NEIGH_LINK_TABLE) {
2527 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2528 addr, NULL, skb->len);
2529 if (err < 0)
2530 goto out_kfree_skb;
2531 err = dev_queue_xmit(skb);
2532 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002533out:
2534 return err;
2535out_kfree_skb:
2536 kfree_skb(skb);
2537 goto out;
2538}
2539EXPORT_SYMBOL(neigh_xmit);
2540
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541#ifdef CONFIG_PROC_FS
2542
2543static struct neighbour *neigh_get_first(struct seq_file *seq)
2544{
2545 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002546 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002547 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002548 struct neighbour *n = NULL;
2549 int bucket = state->bucket;
2550
2551 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002552 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002553 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002556 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002557 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 if (state->neigh_sub_iter) {
2559 loff_t fakep = 0;
2560 void *v;
2561
2562 v = state->neigh_sub_iter(state, n, &fakep);
2563 if (!v)
2564 goto next;
2565 }
2566 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2567 break;
2568 if (n->nud_state & ~NUD_NOARP)
2569 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002570next:
2571 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 }
2573
2574 if (n)
2575 break;
2576 }
2577 state->bucket = bucket;
2578
2579 return n;
2580}
2581
2582static struct neighbour *neigh_get_next(struct seq_file *seq,
2583 struct neighbour *n,
2584 loff_t *pos)
2585{
2586 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002587 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002588 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589
2590 if (state->neigh_sub_iter) {
2591 void *v = state->neigh_sub_iter(state, n, pos);
2592 if (v)
2593 return n;
2594 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002595 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002596
2597 while (1) {
2598 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002599 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002600 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if (state->neigh_sub_iter) {
2602 void *v = state->neigh_sub_iter(state, n, pos);
2603 if (v)
2604 return n;
2605 goto next;
2606 }
2607 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2608 break;
2609
2610 if (n->nud_state & ~NUD_NOARP)
2611 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002612next:
2613 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002614 }
2615
2616 if (n)
2617 break;
2618
David S. Millercd089332011-07-11 01:28:12 -07002619 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620 break;
2621
Eric Dumazet767e97e2010-10-06 17:49:21 -07002622 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623 }
2624
2625 if (n && pos)
2626 --(*pos);
2627 return n;
2628}
2629
2630static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2631{
2632 struct neighbour *n = neigh_get_first(seq);
2633
2634 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002635 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 while (*pos) {
2637 n = neigh_get_next(seq, n, pos);
2638 if (!n)
2639 break;
2640 }
2641 }
2642 return *pos ? NULL : n;
2643}
2644
2645static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2646{
2647 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002648 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 struct neigh_table *tbl = state->tbl;
2650 struct pneigh_entry *pn = NULL;
2651 int bucket = state->bucket;
2652
2653 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2654 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2655 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002656 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002657 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 if (pn)
2659 break;
2660 }
2661 state->bucket = bucket;
2662
2663 return pn;
2664}
2665
2666static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2667 struct pneigh_entry *pn,
2668 loff_t *pos)
2669{
2670 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002671 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672 struct neigh_table *tbl = state->tbl;
2673
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002674 do {
2675 pn = pn->next;
2676 } while (pn && !net_eq(pneigh_net(pn), net));
2677
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678 while (!pn) {
2679 if (++state->bucket > PNEIGH_HASHMASK)
2680 break;
2681 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002682 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002683 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 if (pn)
2685 break;
2686 }
2687
2688 if (pn && pos)
2689 --(*pos);
2690
2691 return pn;
2692}
2693
2694static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2695{
2696 struct pneigh_entry *pn = pneigh_get_first(seq);
2697
2698 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002699 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 while (*pos) {
2701 pn = pneigh_get_next(seq, pn, pos);
2702 if (!pn)
2703 break;
2704 }
2705 }
2706 return *pos ? NULL : pn;
2707}
2708
2709static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2710{
2711 struct neigh_seq_state *state = seq->private;
2712 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002713 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002714
Chris Larson745e2032008-08-03 01:10:55 -07002715 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002717 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718
2719 return rc;
2720}
2721
2722void *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 +00002723 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724{
2725 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726
2727 state->tbl = tbl;
2728 state->bucket = 0;
2729 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2730
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002731 rcu_read_lock_bh();
2732 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002733
Chris Larson745e2032008-08-03 01:10:55 -07002734 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735}
2736EXPORT_SYMBOL(neigh_seq_start);
2737
2738void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2739{
2740 struct neigh_seq_state *state;
2741 void *rc;
2742
2743 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002744 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002745 goto out;
2746 }
2747
2748 state = seq->private;
2749 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2750 rc = neigh_get_next(seq, v, NULL);
2751 if (rc)
2752 goto out;
2753 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2754 rc = pneigh_get_first(seq);
2755 } else {
2756 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2757 rc = pneigh_get_next(seq, v, NULL);
2758 }
2759out:
2760 ++(*pos);
2761 return rc;
2762}
2763EXPORT_SYMBOL(neigh_seq_next);
2764
2765void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002766 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002768 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769}
2770EXPORT_SYMBOL(neigh_seq_stop);
2771
2772/* statistics via seq_file */
2773
2774static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2775{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002776 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 int cpu;
2778
2779 if (*pos == 0)
2780 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002781
Rusty Russell0f23174a2008-12-29 12:23:42 +00002782 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783 if (!cpu_possible(cpu))
2784 continue;
2785 *pos = cpu+1;
2786 return per_cpu_ptr(tbl->stats, cpu);
2787 }
2788 return NULL;
2789}
2790
2791static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2792{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002793 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002794 int cpu;
2795
Rusty Russell0f23174a2008-12-29 12:23:42 +00002796 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002797 if (!cpu_possible(cpu))
2798 continue;
2799 *pos = cpu+1;
2800 return per_cpu_ptr(tbl->stats, cpu);
2801 }
2802 return NULL;
2803}
2804
2805static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2806{
2807
2808}
2809
2810static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2811{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002812 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002813 struct neigh_statistics *st = v;
2814
2815 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002816 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 -07002817 return 0;
2818 }
2819
2820 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002821 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 atomic_read(&tbl->entries),
2823
2824 st->allocs,
2825 st->destroys,
2826 st->hash_grows,
2827
2828 st->lookups,
2829 st->hits,
2830
2831 st->res_failed,
2832
2833 st->rcv_probes_mcast,
2834 st->rcv_probes_ucast,
2835
2836 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002837 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002838 st->unres_discards,
2839 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002840 );
2841
2842 return 0;
2843}
2844
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002845static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846 .start = neigh_stat_seq_start,
2847 .next = neigh_stat_seq_next,
2848 .stop = neigh_stat_seq_stop,
2849 .show = neigh_stat_seq_show,
2850};
2851
2852static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2853{
2854 int ret = seq_open(file, &neigh_stat_seq_ops);
2855
2856 if (!ret) {
2857 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002858 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002859 }
2860 return ret;
2861};
2862
Arjan van de Ven9a321442007-02-12 00:55:35 -08002863static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002864 .owner = THIS_MODULE,
2865 .open = neigh_stat_seq_open,
2866 .read = seq_read,
2867 .llseek = seq_lseek,
2868 .release = seq_release,
2869};
2870
2871#endif /* CONFIG_PROC_FS */
2872
Thomas Graf339bf982006-11-10 14:10:15 -08002873static inline size_t neigh_nlmsg_size(void)
2874{
2875 return NLMSG_ALIGN(sizeof(struct ndmsg))
2876 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2877 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2878 + nla_total_size(sizeof(struct nda_cacheinfo))
2879 + nla_total_size(4); /* NDA_PROBES */
2880}
2881
Thomas Grafb8673312006-08-15 00:33:14 -07002882static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002883{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002884 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002885 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002886 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002887
Thomas Graf339bf982006-11-10 14:10:15 -08002888 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002889 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002890 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002891
Thomas Grafb8673312006-08-15 00:33:14 -07002892 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002893 if (err < 0) {
2894 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2895 WARN_ON(err == -EMSGSIZE);
2896 kfree_skb(skb);
2897 goto errout;
2898 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002899 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2900 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002901errout:
2902 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002903 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002904}
2905
2906void neigh_app_ns(struct neighbour *n)
2907{
2908 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002909}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002910EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911
2912#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002913static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002914static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002915static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916
Joe Perchesfe2c6332013-06-11 23:04:25 -07002917static int proc_unres_qlen(struct ctl_table *ctl, int write,
2918 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002919{
2920 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002921 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002922
Shan Weice46cc62012-12-04 18:49:15 +00002923 tmp.extra1 = &zero;
2924 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002925 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002926
2927 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2928 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2929
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002930 if (write && !ret)
2931 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2932 return ret;
2933}
2934
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002935static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2936 int family)
2937{
Jiri Pirkobba24892013-12-07 19:26:57 +01002938 switch (family) {
2939 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002940 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002941 case AF_INET6:
2942 return __in6_dev_nd_parms_get_rcu(dev);
2943 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002944 return NULL;
2945}
2946
2947static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2948 int index)
2949{
2950 struct net_device *dev;
2951 int family = neigh_parms_family(p);
2952
2953 rcu_read_lock();
2954 for_each_netdev_rcu(net, dev) {
2955 struct neigh_parms *dst_p =
2956 neigh_get_dev_parms_rcu(dev, family);
2957
2958 if (dst_p && !test_bit(index, dst_p->data_state))
2959 dst_p->data[index] = p->data[index];
2960 }
2961 rcu_read_unlock();
2962}
2963
2964static void neigh_proc_update(struct ctl_table *ctl, int write)
2965{
2966 struct net_device *dev = ctl->extra1;
2967 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002968 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002969 int index = (int *) ctl->data - p->data;
2970
2971 if (!write)
2972 return;
2973
2974 set_bit(index, p->data_state);
Marcus Huewe6c854af2017-02-15 01:00:36 +01002975 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2976 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002977 if (!dev) /* NULL dev means this is default value */
2978 neigh_copy_dflt_parms(net, p, index);
2979}
2980
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002981static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2982 void __user *buffer,
2983 size_t *lenp, loff_t *ppos)
2984{
2985 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002986 int ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002987
2988 tmp.extra1 = &zero;
2989 tmp.extra2 = &int_max;
2990
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002991 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2992 neigh_proc_update(ctl, write);
2993 return ret;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01002994}
2995
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002996int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2997 void __user *buffer, size_t *lenp, loff_t *ppos)
2998{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002999 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3000
3001 neigh_proc_update(ctl, write);
3002 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003003}
3004EXPORT_SYMBOL(neigh_proc_dointvec);
3005
3006int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3007 void __user *buffer,
3008 size_t *lenp, loff_t *ppos)
3009{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003010 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3011
3012 neigh_proc_update(ctl, write);
3013 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003014}
3015EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3016
3017static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3018 void __user *buffer,
3019 size_t *lenp, loff_t *ppos)
3020{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003021 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3022
3023 neigh_proc_update(ctl, write);
3024 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003025}
3026
3027int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3028 void __user *buffer,
3029 size_t *lenp, loff_t *ppos)
3030{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003031 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3032
3033 neigh_proc_update(ctl, write);
3034 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003035}
3036EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3037
3038static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3039 void __user *buffer,
3040 size_t *lenp, loff_t *ppos)
3041{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003042 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3043
3044 neigh_proc_update(ctl, write);
3045 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003046}
3047
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003048static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3049 void __user *buffer,
3050 size_t *lenp, loff_t *ppos)
3051{
3052 struct neigh_parms *p = ctl->extra2;
3053 int ret;
3054
3055 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3056 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3057 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3058 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3059 else
3060 ret = -1;
3061
3062 if (write && ret == 0) {
3063 /* update reachable_time as well, otherwise, the change will
3064 * only be effective after the next time neigh_periodic_work
3065 * decides to recompute it
3066 */
3067 p->reachable_time =
3068 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3069 }
3070 return ret;
3071}
3072
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003073#define NEIGH_PARMS_DATA_OFFSET(index) \
3074 (&((struct neigh_parms *) 0)->data[index])
3075
3076#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3077 [NEIGH_VAR_ ## attr] = { \
3078 .procname = name, \
3079 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3080 .maxlen = sizeof(int), \
3081 .mode = mval, \
3082 .proc_handler = proc, \
3083 }
3084
3085#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3086 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3087
3088#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003089 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003090
3091#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003092 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003093
3094#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003095 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003096
3097#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003098 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003099
3100#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003101 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003102
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103static struct neigh_sysctl_table {
3104 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003105 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003106} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003107 .neigh_vars = {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003108 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3109 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3110 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003111 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003112 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3113 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3114 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3115 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3116 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3117 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3118 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3119 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3120 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3121 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3122 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3123 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003124 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 .procname = "gc_interval",
3126 .maxlen = sizeof(int),
3127 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003128 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003130 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 .procname = "gc_thresh1",
3132 .maxlen = sizeof(int),
3133 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003134 .extra1 = &zero,
3135 .extra2 = &int_max,
3136 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003138 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 .procname = "gc_thresh2",
3140 .maxlen = sizeof(int),
3141 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003142 .extra1 = &zero,
3143 .extra2 = &int_max,
3144 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003145 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003146 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 .procname = "gc_thresh3",
3148 .maxlen = sizeof(int),
3149 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003150 .extra1 = &zero,
3151 .extra2 = &int_max,
3152 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 },
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303154 [NEIGH_VAR_PROBE] = {
3155 .procname = "neigh_probe",
3156 .maxlen = sizeof(int),
3157 .mode = 0644,
3158 .proc_handler = proc_dointvec,
3159 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003160 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 },
3162};
3163
3164int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003165 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003166{
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003167 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003168 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003169 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003170 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003171 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003173 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003175 goto err;
3176
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003177 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e52013-12-07 19:26:53 +01003178 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003179 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003180 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003181 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
3183 if (dev) {
3184 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003185 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003186 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3187 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003188 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003189 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003190 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003191 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3192 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3193 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3194 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Ravinder Konkaa71b6682015-04-09 11:42:00 +05303195 t->neigh_vars[NEIGH_VAR_PROBE].data = &neigh_probe_enable;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 }
3197
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003198 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003200 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003202 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003204 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003206 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003207 } else {
3208 /* Those handlers will update p->reachable_time after
3209 * base_reachable_time(_ms) is set to ensure the new timer starts being
3210 * applied after the next neighbour update instead of waiting for
3211 * neigh_periodic_work to update its value (can be multiple minutes)
3212 * So any handler that replaces them should do this as well
3213 */
3214 /* ReachableTime */
3215 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3216 neigh_proc_base_reachable_time;
3217 /* ReachableTime (in milliseconds) */
3218 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3219 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003220 }
3221
Eric W. Biederman464dc802012-11-16 03:02:59 +00003222 /* Don't export sysctls to unprivileged users */
3223 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3224 t->neigh_vars[0].procname = NULL;
3225
Jiri Pirko73af6142013-12-07 19:26:55 +01003226 switch (neigh_parms_family(p)) {
3227 case AF_INET:
3228 p_name = "ipv4";
3229 break;
3230 case AF_INET6:
3231 p_name = "ipv6";
3232 break;
3233 default:
3234 BUG();
3235 }
3236
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003237 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3238 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003239 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003240 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003241 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003242 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003243
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 p->sysctl_table = t;
3245 return 0;
3246
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003247free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003249err:
3250 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003251}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003252EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003253
3254void neigh_sysctl_unregister(struct neigh_parms *p)
3255{
3256 if (p->sysctl_table) {
3257 struct neigh_sysctl_table *t = p->sysctl_table;
3258 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003259 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260 kfree(t);
3261 }
3262}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003263EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264
3265#endif /* CONFIG_SYSCTL */
3266
Thomas Grafc8822a42007-03-22 11:50:06 -07003267static int __init neigh_init(void)
3268{
Greg Rosec7ac8672011-06-10 01:27:09 +00003269 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3270 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3271 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003272
Greg Rosec7ac8672011-06-10 01:27:09 +00003273 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3274 NULL);
3275 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003276
3277 return 0;
3278}
3279
3280subsys_initcall(neigh_init);
3281