blob: 0c78c8e0409d8386eacb4daa2609f6c0fcb46562 [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);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -070055static void __neigh_notify(struct neighbour *n, int type, int flags,
56 u32 pid);
57static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Amos Waterland45fc3b12005-09-24 16:53:16 -070060#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080061static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070062#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64/*
65 Neighbour hash table buckets are protected with rwlock tbl->lock.
66
67 - All the scans/updates to hash buckets MUST be made under this lock.
68 - NOTHING clever should be made under this lock: no callbacks
69 to protocol backends, no attempts to send something to network.
70 It will result in deadlocks, if backend/driver wants to use neighbour
71 cache.
72 - If the entry requires some non-trivial actions, increase
73 its reference count and release table lock.
74
75 Neighbour entries are protected:
76 - with reference count.
77 - with rwlock neigh->lock
78
79 Reference count prevents destruction.
80
81 neigh->lock mainly serializes ll address data and its validity state.
82 However, the same lock is used to protect another entry fields:
83 - timer
84 - resolution queue
85
86 Again, nothing clever shall be made under neigh->lock,
87 the most complicated procedure, which we allow is dev->hard_header.
88 It is supposed, that dev->hard_header is simplistic and does
89 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 */
91
David S. Miller8f40b162011-07-17 13:34:11 -070092static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070093{
94 kfree_skb(skb);
95 return -ENETDOWN;
96}
97
Thomas Graf4f494552007-08-08 23:12:36 -070098static void neigh_cleanup_and_release(struct neighbour *neigh)
99{
100 if (neigh->parms->neigh_cleanup)
101 neigh->parms->neigh_cleanup(neigh);
102
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700103 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100104 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
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
Sowmini Varadhan50710342017-06-02 09:01:49 -0700121static bool neigh_del(struct neighbour *n, __u8 state,
122 struct neighbour __rcu **np, struct neigh_table *tbl)
123{
124 bool retval = false;
125
126 write_lock(&n->lock);
Reshetova, Elena9f237432017-06-30 13:07:55 +0300127 if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state)) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700128 struct neighbour *neigh;
129
130 neigh = rcu_dereference_protected(n->next,
131 lockdep_is_held(&tbl->lock));
132 rcu_assign_pointer(*np, neigh);
133 n->dead = 1;
134 retval = true;
135 }
136 write_unlock(&n->lock);
137 if (retval)
138 neigh_cleanup_and_release(n);
139 return retval;
140}
141
142bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
143{
144 struct neigh_hash_table *nht;
145 void *pkey = ndel->primary_key;
146 u32 hash_val;
147 struct neighbour *n;
148 struct neighbour __rcu **np;
149
150 nht = rcu_dereference_protected(tbl->nht,
151 lockdep_is_held(&tbl->lock));
152 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
153 hash_val = hash_val >> (32 - nht->hash_shift);
154
155 np = &nht->hash_buckets[hash_val];
156 while ((n = rcu_dereference_protected(*np,
157 lockdep_is_held(&tbl->lock)))) {
158 if (n == ndel)
159 return neigh_del(n, 0, np, tbl);
160 np = &n->next;
161 }
162 return false;
163}
164
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165static int neigh_forced_gc(struct neigh_table *tbl)
166{
167 int shrunk = 0;
168 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000169 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700170
171 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
172
173 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000174 nht = rcu_dereference_protected(tbl->nht,
175 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700176 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700177 struct neighbour *n;
178 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000180 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700181 while ((n = rcu_dereference_protected(*np,
182 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700183 /* Neighbour record may be discarded if:
184 * - nobody refers to it.
185 * - it is not permanent
186 */
Sowmini Varadhan50710342017-06-02 09:01:49 -0700187 if (neigh_del(n, NUD_PERMANENT, np, tbl)) {
188 shrunk = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700189 continue;
190 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 np = &n->next;
192 }
193 }
194
195 tbl->last_flush = jiffies;
196
197 write_unlock_bh(&tbl->lock);
198
199 return shrunk;
200}
201
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800202static void neigh_add_timer(struct neighbour *n, unsigned long when)
203{
204 neigh_hold(n);
205 if (unlikely(mod_timer(&n->timer, when))) {
206 printk("NEIGH: BUG, double timer add, state is %x\n",
207 n->nud_state);
208 dump_stack();
209 }
210}
211
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212static int neigh_del_timer(struct neighbour *n)
213{
214 if ((n->nud_state & NUD_IN_TIMER) &&
215 del_timer(&n->timer)) {
216 neigh_release(n);
217 return 1;
218 }
219 return 0;
220}
221
222static void pneigh_queue_purge(struct sk_buff_head *list)
223{
224 struct sk_buff *skb;
225
226 while ((skb = skb_dequeue(list)) != NULL) {
227 dev_put(skb->dev);
228 kfree_skb(skb);
229 }
230}
231
Herbert Xu49636bb2005-10-23 17:18:00 +1000232static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233{
234 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000235 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700236
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000237 nht = rcu_dereference_protected(tbl->nht,
238 lockdep_is_held(&tbl->lock));
239
David S. Millercd089332011-07-11 01:28:12 -0700240 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700241 struct neighbour *n;
242 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243
Eric Dumazet767e97e2010-10-06 17:49:21 -0700244 while ((n = rcu_dereference_protected(*np,
245 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 if (dev && n->dev != dev) {
247 np = &n->next;
248 continue;
249 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700250 rcu_assign_pointer(*np,
251 rcu_dereference_protected(n->next,
252 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700253 write_lock(&n->lock);
254 neigh_del_timer(n);
255 n->dead = 1;
256
Reshetova, Elena9f237432017-06-30 13:07:55 +0300257 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700258 /* The most unpleasant situation.
259 We must destroy neighbour entry,
260 but someone still uses it.
261
262 The destroy will be delayed until
263 the last user releases us, but
264 we must kill timers etc. and move
265 it to safe state.
266 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700267 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000268 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269 n->output = neigh_blackhole;
270 if (n->nud_state & NUD_VALID)
271 n->nud_state = NUD_NOARP;
272 else
273 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000274 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700275 }
276 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700277 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278 }
279 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000280}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700281
Herbert Xu49636bb2005-10-23 17:18:00 +1000282void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
283{
284 write_lock_bh(&tbl->lock);
285 neigh_flush_dev(tbl, dev);
286 write_unlock_bh(&tbl->lock);
287}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900288EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000289
290int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
291{
292 write_lock_bh(&tbl->lock);
293 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 pneigh_ifdown(tbl, dev);
295 write_unlock_bh(&tbl->lock);
296
297 del_timer_sync(&tbl->proxy_timer);
298 pneigh_queue_purge(&tbl->proxy_queue);
299 return 0;
300}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900301EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700302
David Miller596b9b62011-07-25 00:01:25 +0000303static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304{
305 struct neighbour *n = NULL;
306 unsigned long now = jiffies;
307 int entries;
308
309 entries = atomic_inc_return(&tbl->entries) - 1;
310 if (entries >= tbl->gc_thresh3 ||
311 (entries >= tbl->gc_thresh2 &&
312 time_after(now, tbl->last_flush + 5 * HZ))) {
313 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700314 entries >= tbl->gc_thresh3) {
315 net_info_ratelimited("%s: neighbor table overflow!\n",
316 tbl->id);
317 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700319 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 }
321
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000322 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 if (!n)
324 goto out_entries;
325
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700326 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000328 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 n->updated = n->used = now;
330 n->nud_state = NUD_NONE;
331 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700332 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800334 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335
336 NEIGH_CACHE_STAT_INC(tbl, allocs);
337 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300338 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 n->dead = 1;
340out:
341 return n;
342
343out_entries:
344 atomic_dec(&tbl->entries);
345 goto out;
346}
347
David S. Miller2c2aba62011-12-28 15:06:58 -0500348static void neigh_get_hash_rnd(u32 *x)
349{
350 get_random_bytes(x, sizeof(*x));
351 *x |= 1;
352}
353
David S. Millercd089332011-07-11 01:28:12 -0700354static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355{
David S. Millercd089332011-07-11 01:28:12 -0700356 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000357 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000358 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500359 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000361 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
362 if (!ret)
363 return NULL;
364 if (size <= PAGE_SIZE)
365 buckets = kzalloc(size, GFP_ATOMIC);
366 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000367 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000368 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
369 get_order(size));
370 if (!buckets) {
371 kfree(ret);
372 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000374 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700375 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500376 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
377 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700378 return ret;
379}
380
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000381static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000383 struct neigh_hash_table *nht = container_of(head,
384 struct neigh_hash_table,
385 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700386 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000387 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
389 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000390 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000392 free_pages((unsigned long)buckets, get_order(size));
393 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394}
395
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000396static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700397 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000399 unsigned int i, hash;
400 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700401
402 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
403
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000404 old_nht = rcu_dereference_protected(tbl->nht,
405 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700406 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000407 if (!new_nht)
408 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409
David S. Millercd089332011-07-11 01:28:12 -0700410 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700411 struct neighbour *n, *next;
412
Eric Dumazet767e97e2010-10-06 17:49:21 -0700413 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
414 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000415 n != NULL;
416 n = next) {
417 hash = tbl->hash(n->primary_key, n->dev,
418 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
David S. Millercd089332011-07-11 01:28:12 -0700420 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700421 next = rcu_dereference_protected(n->next,
422 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423
Eric Dumazet767e97e2010-10-06 17:49:21 -0700424 rcu_assign_pointer(n->next,
425 rcu_dereference_protected(
426 new_nht->hash_buckets[hash],
427 lockdep_is_held(&tbl->lock)));
428 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 }
430 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000432 rcu_assign_pointer(tbl->nht, new_nht);
433 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
434 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435}
436
437struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
438 struct net_device *dev)
439{
440 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 NEIGH_CACHE_STAT_INC(tbl, lookups);
443
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000444 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600445 n = __neigh_lookup_noref(tbl, pkey, dev);
446 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300447 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600448 n = NULL;
449 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700451
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000452 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 return n;
454}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900455EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456
Eric W. Biederman426b5302008-01-24 00:13:18 -0800457struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
458 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459{
460 struct neighbour *n;
461 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800462 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000463 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464
465 NEIGH_CACHE_STAT_INC(tbl, lookups);
466
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000467 rcu_read_lock_bh();
468 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700469 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700470
471 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
472 n != NULL;
473 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800474 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900475 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300476 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700477 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478 NEIGH_CACHE_STAT_INC(tbl, hits);
479 break;
480 }
481 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700482
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000483 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 return n;
485}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900486EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
David S. Millera263b302012-07-02 02:02:15 -0700488struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
489 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490{
491 u32 hash_val;
492 int key_len = tbl->key_len;
493 int error;
David Miller596b9b62011-07-25 00:01:25 +0000494 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000495 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
497 if (!n) {
498 rc = ERR_PTR(-ENOBUFS);
499 goto out;
500 }
501
502 memcpy(n->primary_key, pkey, key_len);
503 n->dev = dev;
504 dev_hold(dev);
505
506 /* Protocol specific setup. */
507 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
508 rc = ERR_PTR(error);
509 goto out_neigh_release;
510 }
511
David Millerda6a8fa2011-07-25 00:01:38 +0000512 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200513 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000514 if (error < 0) {
515 rc = ERR_PTR(error);
516 goto out_neigh_release;
517 }
518 }
519
David S. Miller447f2192011-12-19 15:04:41 -0500520 /* Device specific setup. */
521 if (n->parms->neigh_setup &&
522 (error = n->parms->neigh_setup(n)) < 0) {
523 rc = ERR_PTR(error);
524 goto out_neigh_release;
525 }
526
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100527 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528
529 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000530 nht = rcu_dereference_protected(tbl->nht,
531 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532
David S. Millercd089332011-07-11 01:28:12 -0700533 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
534 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535
David S. Millercd089332011-07-11 01:28:12 -0700536 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537
538 if (n->parms->dead) {
539 rc = ERR_PTR(-EINVAL);
540 goto out_tbl_unlock;
541 }
542
Eric Dumazet767e97e2010-10-06 17:49:21 -0700543 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
544 lockdep_is_held(&tbl->lock));
545 n1 != NULL;
546 n1 = rcu_dereference_protected(n1->next,
547 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700548 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700549 if (want_ref)
550 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 rc = n1;
552 goto out_tbl_unlock;
553 }
554 }
555
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700557 if (want_ref)
558 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700559 rcu_assign_pointer(n->next,
560 rcu_dereference_protected(nht->hash_buckets[hash_val],
561 lockdep_is_held(&tbl->lock)));
562 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000564 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 rc = n;
566out:
567 return rc;
568out_tbl_unlock:
569 write_unlock_bh(&tbl->lock);
570out_neigh_release:
571 neigh_release(n);
572 goto out;
573}
David S. Millera263b302012-07-02 02:02:15 -0700574EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900576static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700577{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700578 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700579 hash_val ^= (hash_val >> 16);
580 hash_val ^= hash_val >> 8;
581 hash_val ^= hash_val >> 4;
582 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900583 return hash_val;
584}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700585
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900586static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
587 struct net *net,
588 const void *pkey,
589 int key_len,
590 struct net_device *dev)
591{
592 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700593 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900594 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700595 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900596 return n;
597 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700598 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900599 return NULL;
600}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700601
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900602struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
603 struct net *net, const void *pkey, struct net_device *dev)
604{
605 int key_len = tbl->key_len;
606 u32 hash_val = pneigh_hash(pkey, key_len);
607
608 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
609 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700610}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900611EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700612
Eric W. Biederman426b5302008-01-24 00:13:18 -0800613struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
614 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 struct net_device *dev, int creat)
616{
617 struct pneigh_entry *n;
618 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900619 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620
621 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900622 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
623 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900625
626 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627 goto out;
628
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700629 ASSERT_RTNL();
630
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
632 if (!n)
633 goto out;
634
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500635 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 memcpy(n->key, pkey, key_len);
637 n->dev = dev;
638 if (dev)
639 dev_hold(dev);
640
641 if (tbl->pconstructor && tbl->pconstructor(n)) {
642 if (dev)
643 dev_put(dev);
644 kfree(n);
645 n = NULL;
646 goto out;
647 }
648
649 write_lock_bh(&tbl->lock);
650 n->next = tbl->phash_buckets[hash_val];
651 tbl->phash_buckets[hash_val] = n;
652 write_unlock_bh(&tbl->lock);
653out:
654 return n;
655}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900656EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657
658
Eric W. Biederman426b5302008-01-24 00:13:18 -0800659int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 struct net_device *dev)
661{
662 struct pneigh_entry *n, **np;
663 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900664 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665
666 write_lock_bh(&tbl->lock);
667 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
668 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800669 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900670 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 *np = n->next;
672 write_unlock_bh(&tbl->lock);
673 if (tbl->pdestructor)
674 tbl->pdestructor(n);
675 if (n->dev)
676 dev_put(n->dev);
677 kfree(n);
678 return 0;
679 }
680 }
681 write_unlock_bh(&tbl->lock);
682 return -ENOENT;
683}
684
685static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
686{
687 struct pneigh_entry *n, **np;
688 u32 h;
689
690 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
691 np = &tbl->phash_buckets[h];
692 while ((n = *np) != NULL) {
693 if (!dev || n->dev == dev) {
694 *np = n->next;
695 if (tbl->pdestructor)
696 tbl->pdestructor(n);
697 if (n->dev)
698 dev_put(n->dev);
699 kfree(n);
700 continue;
701 }
702 np = &n->next;
703 }
704 }
705 return -ENOENT;
706}
707
Denis V. Lunev06f05112008-01-24 00:30:58 -0800708static void neigh_parms_destroy(struct neigh_parms *parms);
709
710static inline void neigh_parms_put(struct neigh_parms *parms)
711{
712 if (atomic_dec_and_test(&parms->refcnt))
713 neigh_parms_destroy(parms);
714}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716/*
717 * neighbour must already be out of the table;
718 *
719 */
720void neigh_destroy(struct neighbour *neigh)
721{
David Millerda6a8fa2011-07-25 00:01:38 +0000722 struct net_device *dev = neigh->dev;
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
725
726 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000727 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 dump_stack();
729 return;
730 }
731
732 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000733 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700734
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700735 write_lock_bh(&neigh->lock);
736 __skb_queue_purge(&neigh->arp_queue);
737 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000738 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739
David S. Miller447f2192011-12-19 15:04:41 -0500740 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200741 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500742
David Millerda6a8fa2011-07-25 00:01:38 +0000743 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 neigh_parms_put(neigh->parms);
745
Joe Perchesd5d427c2013-04-15 15:17:19 +0000746 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
748 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000749 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900751EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753/* Neighbour state is suspicious;
754 disable fast path.
755
756 Called with write_locked neigh.
757 */
758static void neigh_suspect(struct neighbour *neigh)
759{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000760 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763}
764
765/* Neighbour state is OK;
766 enable fast path.
767
768 Called with write_locked neigh.
769 */
770static void neigh_connect(struct neighbour *neigh)
771{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000772 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
774 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775}
776
Eric Dumazete4c4e442009-07-30 03:15:07 +0000777static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000779 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700780 struct neighbour *n;
781 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000782 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000783 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784
785 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
786
Eric Dumazete4c4e442009-07-30 03:15:07 +0000787 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000788 nht = rcu_dereference_protected(tbl->nht,
789 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790
791 /*
792 * periodically recompute ReachableTime from random function
793 */
794
Eric Dumazete4c4e442009-07-30 03:15:07 +0000795 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000797 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100798 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100800 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 }
802
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800803 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
804 goto out;
805
David S. Millercd089332011-07-11 01:28:12 -0700806 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000807 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Eric Dumazet767e97e2010-10-06 17:49:21 -0700809 while ((n = rcu_dereference_protected(*np,
810 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000811 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812
Eric Dumazete4c4e442009-07-30 03:15:07 +0000813 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814
Eric Dumazete4c4e442009-07-30 03:15:07 +0000815 state = n->nud_state;
816 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
817 write_unlock(&n->lock);
818 goto next_elt;
819 }
820
821 if (time_before(n->used, n->confirmed))
822 n->used = n->confirmed;
823
Reshetova, Elena9f237432017-06-30 13:07:55 +0300824 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000825 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100826 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000827 *np = n->next;
828 n->dead = 1;
829 write_unlock(&n->lock);
830 neigh_cleanup_and_release(n);
831 continue;
832 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700834
835next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000836 np = &n->next;
837 }
838 /*
839 * It's fine to release lock here, even if hash table
840 * grows while we are preempted.
841 */
842 write_unlock_bh(&tbl->lock);
843 cond_resched();
844 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500845 nht = rcu_dereference_protected(tbl->nht,
846 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000848out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100849 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
850 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
851 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 */
viresh kumarf6180022014-01-22 12:23:33 +0530853 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100854 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000855 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856}
857
858static __inline__ int neigh_max_probes(struct neighbour *n)
859{
860 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900861 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
862 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
863 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864}
865
Timo Teras5ef12d92009-06-11 04:16:28 -0700866static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000867 __releases(neigh->lock)
868 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700869{
870 struct sk_buff *skb;
871
872 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000873 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700874 neigh->updated = jiffies;
875
876 /* It is very thin place. report_unreachable is very complicated
877 routine. Particularly, it can hit the same neighbour entry!
878
879 So that, we try to be accurate and avoid dead loop. --ANK
880 */
881 while (neigh->nud_state == NUD_FAILED &&
882 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
883 write_unlock(&neigh->lock);
884 neigh->ops->error_report(neigh, skb);
885 write_lock(&neigh->lock);
886 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700887 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000888 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700889}
890
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000891static void neigh_probe(struct neighbour *neigh)
892 __releases(neigh->lock)
893{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200894 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000895 /* keep skb alive even if arp_queue overflows */
896 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800897 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000898 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700899 if (neigh->ops->solicit)
900 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000901 atomic_inc(&neigh->probes);
902 kfree_skb(skb);
903}
904
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905/* Called when a timer expires for a neighbour entry. */
906
907static void neigh_timer_handler(unsigned long arg)
908{
909 unsigned long now, next;
910 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000911 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 int notify = 0;
913
914 write_lock(&neigh->lock);
915
916 state = neigh->nud_state;
917 now = jiffies;
918 next = now + HZ;
919
David S. Miller045f7b32011-11-01 17:45:55 -0400920 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
923 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900924 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000926 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 next = neigh->confirmed + neigh->parms->reachable_time;
928 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100929 neigh->used +
930 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000931 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800933 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100935 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000937 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700938 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800939 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700941 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 }
943 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900944 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100945 neigh->confirmed +
946 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000947 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700948 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800949 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700951 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952 next = neigh->confirmed + neigh->parms->reachable_time;
953 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000954 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800956 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900958 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100959 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
961 } else {
962 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100963 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 }
965
966 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
967 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968 neigh->nud_state = NUD_FAILED;
969 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700970 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800971 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 }
973
974 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 if (time_before(next, jiffies + HZ/2))
976 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000977 if (!mod_timer(&neigh->timer, next))
978 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 }
980 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000981 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800982 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800983out:
David S. Miller9ff56602008-02-17 18:39:54 -0800984 write_unlock(&neigh->lock);
985 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986
Thomas Grafd961db32007-08-08 23:12:56 -0700987 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700988 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -0700989
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 neigh_release(neigh);
991}
992
993int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
994{
995 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000996 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
998 write_lock_bh(&neigh->lock);
999
1000 rc = 0;
1001 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1002 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001003 if (neigh->dead)
1004 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001007 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1008 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001009 unsigned long next, now = jiffies;
1010
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001011 atomic_set(&neigh->probes,
1012 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001014 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001015 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1016 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001017 neigh_add_timer(neigh, next);
1018 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001019 } else {
1020 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001021 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 write_unlock_bh(&neigh->lock);
1023
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001024 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return 1;
1026 }
1027 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001028 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001030 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001031 neigh_add_timer(neigh, jiffies +
1032 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 }
1034
1035 if (neigh->nud_state == NUD_INCOMPLETE) {
1036 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001037 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001038 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001040
David S. Millerf72051b2008-09-23 01:11:18 -07001041 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001042 if (!buff)
1043 break;
1044 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001046 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001048 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001050 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052 rc = 1;
1053 }
1054out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001055 if (immediate_probe)
1056 neigh_probe(neigh);
1057 else
1058 write_unlock(&neigh->lock);
1059 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001061
1062out_dead:
1063 if (neigh->nud_state & NUD_STALE)
1064 goto out_unlock_bh;
1065 write_unlock_bh(&neigh->lock);
1066 kfree_skb(skb);
1067 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001069EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
David S. Millerf6b72b622011-07-14 07:53:20 -07001071static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072{
1073 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001074 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001075 = NULL;
1076
1077 if (neigh->dev->header_ops)
1078 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079
1080 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001081 hh = &neigh->hh;
1082 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001083 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001085 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001086 }
1087 }
1088}
1089
1090
1091
1092/* Generic update routine.
1093 -- lladdr is new lladdr or NULL, if it is not supplied.
1094 -- new is new state.
1095 -- flags
1096 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1097 if it is different.
1098 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001099 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001101 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1102
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001103 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 NTF_ROUTER flag.
1105 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1106 a router.
1107
1108 Caller MUST hold reference count on the entry.
1109 */
1110
1111int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001112 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113{
1114 u8 old;
1115 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001117 struct net_device *dev;
1118 int update_isrouter = 0;
1119
1120 write_lock_bh(&neigh->lock);
1121
1122 dev = neigh->dev;
1123 old = neigh->nud_state;
1124 err = -EPERM;
1125
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001126 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 (old & (NUD_NOARP | NUD_PERMANENT)))
1128 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001129 if (neigh->dead)
1130 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131
1132 if (!(new & NUD_VALID)) {
1133 neigh_del_timer(neigh);
1134 if (old & NUD_CONNECTED)
1135 neigh_suspect(neigh);
1136 neigh->nud_state = new;
1137 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001139 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1140 (new & NUD_FAILED)) {
1141 neigh_invalidate(neigh);
1142 notify = 1;
1143 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001144 goto out;
1145 }
1146
1147 /* Compare new lladdr with cached one */
1148 if (!dev->addr_len) {
1149 /* First case: device needs no address. */
1150 lladdr = neigh->ha;
1151 } else if (lladdr) {
1152 /* The second case: if something is already cached
1153 and a new address is proposed:
1154 - compare new & old
1155 - if they are different, check override flag
1156 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001157 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 !memcmp(lladdr, neigh->ha, dev->addr_len))
1159 lladdr = neigh->ha;
1160 } else {
1161 /* No address is supplied; if we know something,
1162 use it, otherwise discard the request.
1163 */
1164 err = -EINVAL;
1165 if (!(old & NUD_VALID))
1166 goto out;
1167 lladdr = neigh->ha;
1168 }
1169
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 /* If entry was valid and address is not changed,
1171 do not change entry state, if new one is STALE.
1172 */
1173 err = 0;
1174 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1175 if (old & NUD_VALID) {
1176 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1177 update_isrouter = 0;
1178 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1179 (old & NUD_CONNECTED)) {
1180 lladdr = neigh->ha;
1181 new = NUD_STALE;
1182 } else
1183 goto out;
1184 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001185 if (lladdr == neigh->ha && new == NUD_STALE &&
1186 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 new = old;
1188 }
1189 }
1190
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001191 /* Update timestamps only once we know we will make a change to the
1192 * neighbour entry. Otherwise we risk to move the locktime window with
1193 * noop updates and ignore relevant ARP updates.
1194 */
1195 if (new != old || lladdr != neigh->ha) {
1196 if (new & NUD_CONNECTED)
1197 neigh->confirmed = jiffies;
1198 neigh->updated = jiffies;
1199 }
1200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 if (new != old) {
1202 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001203 if (new & NUD_PROBE)
1204 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001205 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001206 neigh_add_timer(neigh, (jiffies +
1207 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001208 neigh->parms->reachable_time :
1209 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001211 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212 }
1213
1214 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001215 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001217 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 neigh_update_hhs(neigh);
1219 if (!(new & NUD_CONNECTED))
1220 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001221 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 }
1224 if (new == old)
1225 goto out;
1226 if (new & NUD_CONNECTED)
1227 neigh_connect(neigh);
1228 else
1229 neigh_suspect(neigh);
1230 if (!(old & NUD_VALID)) {
1231 struct sk_buff *skb;
1232
1233 /* Again: avoid dead loop if something went wrong */
1234
1235 while (neigh->nud_state & NUD_VALID &&
1236 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001237 struct dst_entry *dst = skb_dst(skb);
1238 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001240
1241 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001242
1243 /* Why not just use 'neigh' as-is? The problem is that
1244 * things such as shaper, eql, and sch_teql can end up
1245 * using alternative, different, neigh objects to output
1246 * the packet in the output path. So what we need to do
1247 * here is re-lookup the top-level neigh in the path so
1248 * we can reinject the packet there.
1249 */
1250 n2 = NULL;
1251 if (dst) {
1252 n2 = dst_neigh_lookup_skb(dst, skb);
1253 if (n2)
1254 n1 = n2;
1255 }
David S. Miller8f40b162011-07-17 13:34:11 -07001256 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001257 if (n2)
1258 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001259 rcu_read_unlock();
1260
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 write_lock_bh(&neigh->lock);
1262 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001263 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001264 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001265 }
1266out:
1267 if (update_isrouter) {
1268 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1269 (neigh->flags | NTF_ROUTER) :
1270 (neigh->flags & ~NTF_ROUTER);
1271 }
1272 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001273
1274 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001275 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001276
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 return err;
1278}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001279EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280
Jiri Benc7e980562013-12-11 13:48:20 +01001281/* Update the neigh to listen temporarily for probe responses, even if it is
1282 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1283 */
1284void __neigh_set_probe_once(struct neighbour *neigh)
1285{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001286 if (neigh->dead)
1287 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001288 neigh->updated = jiffies;
1289 if (!(neigh->nud_state & NUD_FAILED))
1290 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001291 neigh->nud_state = NUD_INCOMPLETE;
1292 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001293 neigh_add_timer(neigh,
1294 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1295}
1296EXPORT_SYMBOL(__neigh_set_probe_once);
1297
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1299 u8 *lladdr, void *saddr,
1300 struct net_device *dev)
1301{
1302 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1303 lladdr || !dev->addr_len);
1304 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001305 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001306 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 return neigh;
1308}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001309EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310
Eric Dumazet34d101d2010-10-11 09:16:57 -07001311/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001312static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001313{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001314 struct net_device *dev = n->dev;
1315 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001316 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001317
1318 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001319
David S. Millerf6b72b622011-07-14 07:53:20 -07001320 /* Only one thread can come in here and initialize the
1321 * hh_cache entry.
1322 */
David S. Millerb23b5452011-07-16 17:45:02 -07001323 if (!hh->hh_len)
1324 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001325
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001326 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327}
1328
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329/* Slow and careful. */
1330
David S. Miller8f40b162011-07-17 13:34:11 -07001331int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 int rc = 0;
1334
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 if (!neigh_event_send(neigh, skb)) {
1336 int err;
1337 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001338 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001339
David S. Millerf6b72b622011-07-14 07:53:20 -07001340 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001341 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001342
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001343 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001344 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001345 seq = read_seqbegin(&neigh->ha_lock);
1346 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1347 neigh->ha, NULL, skb->len);
1348 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001349
Linus Torvalds1da177e2005-04-16 15:20:36 -07001350 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001351 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 else
1353 goto out_kfree_skb;
1354 }
1355out:
1356 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001357out_kfree_skb:
1358 rc = -EINVAL;
1359 kfree_skb(skb);
1360 goto out;
1361}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001362EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
1364/* As fast as possible without hh cache */
1365
David S. Miller8f40b162011-07-17 13:34:11 -07001366int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001369 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001370 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001372 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001373 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001374 seq = read_seqbegin(&neigh->ha_lock);
1375 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1376 neigh->ha, NULL, skb->len);
1377 } while (read_seqretry(&neigh->ha_lock, seq));
1378
Linus Torvalds1da177e2005-04-16 15:20:36 -07001379 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001380 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 else {
1382 err = -EINVAL;
1383 kfree_skb(skb);
1384 }
1385 return err;
1386}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001387EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
David S. Miller8f40b162011-07-17 13:34:11 -07001389int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1390{
1391 return dev_queue_xmit(skb);
1392}
1393EXPORT_SYMBOL(neigh_direct_output);
1394
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395static void neigh_proxy_process(unsigned long arg)
1396{
1397 struct neigh_table *tbl = (struct neigh_table *)arg;
1398 long sched_next = 0;
1399 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001400 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
1402 spin_lock(&tbl->proxy_queue.lock);
1403
David S. Millerf72051b2008-09-23 01:11:18 -07001404 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1405 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001408 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001409
David S. Millerf72051b2008-09-23 01:11:18 -07001410 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001411 if (tbl->proxy_redo && netif_running(dev)) {
1412 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001413 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001414 rcu_read_unlock();
1415 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001416 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001417 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418
1419 dev_put(dev);
1420 } else if (!sched_next || tdif < sched_next)
1421 sched_next = tdif;
1422 }
1423 del_timer(&tbl->proxy_timer);
1424 if (sched_next)
1425 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1426 spin_unlock(&tbl->proxy_queue.lock);
1427}
1428
1429void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1430 struct sk_buff *skb)
1431{
1432 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001433
1434 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001435 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001437 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438 kfree_skb(skb);
1439 return;
1440 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001441
1442 NEIGH_CB(skb)->sched_next = sched_next;
1443 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444
1445 spin_lock(&tbl->proxy_queue.lock);
1446 if (del_timer(&tbl->proxy_timer)) {
1447 if (time_before(tbl->proxy_timer.expires, sched_next))
1448 sched_next = tbl->proxy_timer.expires;
1449 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001450 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 dev_hold(skb->dev);
1452 __skb_queue_tail(&tbl->proxy_queue, skb);
1453 mod_timer(&tbl->proxy_timer, sched_next);
1454 spin_unlock(&tbl->proxy_queue.lock);
1455}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001456EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001458static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001459 struct net *net, int ifindex)
1460{
1461 struct neigh_parms *p;
1462
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001463 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001464 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001465 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001466 return p;
1467 }
1468
1469 return NULL;
1470}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1473 struct neigh_table *tbl)
1474{
Gao fengcf89d6b2013-06-20 10:01:32 +08001475 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001476 struct net *net = dev_net(dev);
1477 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Gao fengcf89d6b2013-06-20 10:01:32 +08001479 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 p->tbl = tbl;
1482 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001483 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001484 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001485 dev_hold(dev);
1486 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001487 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001489
1490 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001491 dev_put(dev);
1492 kfree(p);
1493 return NULL;
1494 }
1495
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001497 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001499
1500 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501 }
1502 return p;
1503}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001504EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
1506static void neigh_rcu_free_parms(struct rcu_head *head)
1507{
1508 struct neigh_parms *parms =
1509 container_of(head, struct neigh_parms, rcu_head);
1510
1511 neigh_parms_put(parms);
1512}
1513
1514void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1515{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 if (!parms || parms == &tbl->parms)
1517 return;
1518 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001519 list_del(&parms->list);
1520 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001522 if (parms->dev)
1523 dev_put(parms->dev);
1524 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001526EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001527
Denis V. Lunev06f05112008-01-24 00:30:58 -08001528static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529{
1530 kfree(parms);
1531}
1532
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001533static struct lock_class_key neigh_table_proxy_queue_class;
1534
WANG Congd7480fd2014-11-10 15:59:36 -08001535static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1536
1537void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538{
1539 unsigned long now = jiffies;
1540 unsigned long phsize;
1541
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001542 INIT_LIST_HEAD(&tbl->parms_list);
1543 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001544 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001547 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 tbl->stats = alloc_percpu(struct neigh_statistics);
1550 if (!tbl->stats)
1551 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001552
Linus Torvalds1da177e2005-04-16 15:20:36 -07001553#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001554 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1555 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557#endif
1558
David S. Millercd089332011-07-11 01:28:12 -07001559 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001560
1561 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001562 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001564 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565 panic("cannot allocate neighbour cache hashes");
1566
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001567 if (!tbl->entry_size)
1568 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1569 tbl->key_len, NEIGH_PRIV_ALIGN);
1570 else
1571 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1572
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001574 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301575 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1576 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001577 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001578 skb_queue_head_init_class(&tbl->proxy_queue,
1579 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
1581 tbl->last_flush = now;
1582 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001583
WANG Congd7480fd2014-11-10 15:59:36 -08001584 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001585}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001586EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587
WANG Congd7480fd2014-11-10 15:59:36 -08001588int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001589{
WANG Congd7480fd2014-11-10 15:59:36 -08001590 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001592 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 del_timer_sync(&tbl->proxy_timer);
1594 pneigh_queue_purge(&tbl->proxy_queue);
1595 neigh_ifdown(tbl, NULL);
1596 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001597 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001599 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1600 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001601 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602
1603 kfree(tbl->phash_buckets);
1604 tbl->phash_buckets = NULL;
1605
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001606 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1607
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001608 free_percpu(tbl->stats);
1609 tbl->stats = NULL;
1610
Linus Torvalds1da177e2005-04-16 15:20:36 -07001611 return 0;
1612}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001613EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001614
WANG Congd7480fd2014-11-10 15:59:36 -08001615static struct neigh_table *neigh_find_table(int family)
1616{
1617 struct neigh_table *tbl = NULL;
1618
1619 switch (family) {
1620 case AF_INET:
1621 tbl = neigh_tables[NEIGH_ARP_TABLE];
1622 break;
1623 case AF_INET6:
1624 tbl = neigh_tables[NEIGH_ND_TABLE];
1625 break;
1626 case AF_DECnet:
1627 tbl = neigh_tables[NEIGH_DN_TABLE];
1628 break;
1629 }
1630
1631 return tbl;
1632}
1633
David Ahernc21ef3e2017-04-16 09:48:24 -07001634static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1635 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001636{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001637 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001638 struct ndmsg *ndm;
1639 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001641 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001643 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644
Eric Dumazet110b2492010-10-04 04:27:36 +00001645 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001646 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001647 goto out;
1648
Thomas Grafa14a49d2006-08-07 17:53:08 -07001649 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1650 if (dst_attr == NULL)
1651 goto out;
1652
1653 ndm = nlmsg_data(nlh);
1654 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001655 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001656 if (dev == NULL) {
1657 err = -ENODEV;
1658 goto out;
1659 }
1660 }
1661
WANG Congd7480fd2014-11-10 15:59:36 -08001662 tbl = neigh_find_table(ndm->ndm_family);
1663 if (tbl == NULL)
1664 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665
WANG Congd7480fd2014-11-10 15:59:36 -08001666 if (nla_len(dst_attr) < tbl->key_len)
1667 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
WANG Congd7480fd2014-11-10 15:59:36 -08001669 if (ndm->ndm_flags & NTF_PROXY) {
1670 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001671 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 }
WANG Congd7480fd2014-11-10 15:59:36 -08001673
1674 if (dev == NULL)
1675 goto out;
1676
1677 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1678 if (neigh == NULL) {
1679 err = -ENOENT;
1680 goto out;
1681 }
1682
1683 err = neigh_update(neigh, NULL, NUD_FAILED,
1684 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001685 NEIGH_UPDATE_F_ADMIN,
1686 NETLINK_CB(skb).portid);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001687 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001688 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001689 neigh_remove_one(neigh, tbl);
1690 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001691
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692out:
1693 return err;
1694}
1695
David Ahernc21ef3e2017-04-16 09:48:24 -07001696static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1697 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698{
WANG Congd7480fd2014-11-10 15:59:36 -08001699 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001700 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001701 struct ndmsg *ndm;
1702 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 struct neigh_table *tbl;
1704 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001705 struct neighbour *neigh;
1706 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001707 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Eric Dumazet110b2492010-10-04 04:27:36 +00001709 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001710 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001711 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001712 goto out;
1713
Thomas Graf5208deb2006-08-07 17:55:40 -07001714 err = -EINVAL;
1715 if (tb[NDA_DST] == NULL)
1716 goto out;
1717
1718 ndm = nlmsg_data(nlh);
1719 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001720 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001721 if (dev == NULL) {
1722 err = -ENODEV;
1723 goto out;
1724 }
1725
1726 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001727 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001728 }
1729
WANG Congd7480fd2014-11-10 15:59:36 -08001730 tbl = neigh_find_table(ndm->ndm_family);
1731 if (tbl == NULL)
1732 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733
WANG Congd7480fd2014-11-10 15:59:36 -08001734 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1735 goto out;
1736 dst = nla_data(tb[NDA_DST]);
1737 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
WANG Congd7480fd2014-11-10 15:59:36 -08001739 if (ndm->ndm_flags & NTF_PROXY) {
1740 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741
WANG Congd7480fd2014-11-10 15:59:36 -08001742 err = -ENOBUFS;
1743 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1744 if (pn) {
1745 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001746 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001747 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001748 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 }
1750
WANG Congd7480fd2014-11-10 15:59:36 -08001751 if (dev == NULL)
1752 goto out;
1753
1754 neigh = neigh_lookup(tbl, dst, dev);
1755 if (neigh == NULL) {
1756 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1757 err = -ENOENT;
1758 goto out;
1759 }
1760
1761 neigh = __neigh_lookup_errno(tbl, dst, dev);
1762 if (IS_ERR(neigh)) {
1763 err = PTR_ERR(neigh);
1764 goto out;
1765 }
1766 } else {
1767 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1768 err = -EEXIST;
1769 neigh_release(neigh);
1770 goto out;
1771 }
1772
1773 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1774 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1775 }
1776
1777 if (ndm->ndm_flags & NTF_USE) {
1778 neigh_event_send(neigh, NULL);
1779 err = 0;
1780 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001781 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1782 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001783 neigh_release(neigh);
1784
Linus Torvalds1da177e2005-04-16 15:20:36 -07001785out:
1786 return err;
1787}
1788
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001789static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1790{
Thomas Grafca860fb2006-08-07 18:00:18 -07001791 struct nlattr *nest;
1792
1793 nest = nla_nest_start(skb, NDTA_PARMS);
1794 if (nest == NULL)
1795 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001796
David S. Miller9a6308d2012-04-01 20:06:28 -04001797 if ((parms->dev &&
1798 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1799 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001800 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1801 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001802 /* approximative value for deprecated QUEUE_LEN (in packets) */
1803 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001804 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1805 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1806 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1807 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1808 NEIGH_VAR(parms, UCAST_PROBES)) ||
1809 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1810 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001811 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1812 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001813 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1814 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001815 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001816 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001817 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001818 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001819 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001820 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001821 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001822 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001823 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001824 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001825 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001826 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001827 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001828 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001829 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001830 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001831
Thomas Grafca860fb2006-08-07 18:00:18 -07001832nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001833 nla_nest_cancel(skb, nest);
1834 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001835}
1836
Thomas Grafca860fb2006-08-07 18:00:18 -07001837static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1838 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001839{
1840 struct nlmsghdr *nlh;
1841 struct ndtmsg *ndtmsg;
1842
Thomas Grafca860fb2006-08-07 18:00:18 -07001843 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1844 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001845 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001846
Thomas Grafca860fb2006-08-07 18:00:18 -07001847 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001848
1849 read_lock_bh(&tbl->lock);
1850 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001851 ndtmsg->ndtm_pad1 = 0;
1852 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853
David S. Miller9a6308d2012-04-01 20:06:28 -04001854 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001855 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001856 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1857 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1858 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1859 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001860 {
1861 unsigned long now = jiffies;
1862 unsigned int flush_delta = now - tbl->last_flush;
1863 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001864 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001865 struct ndt_config ndc = {
1866 .ndtc_key_len = tbl->key_len,
1867 .ndtc_entry_size = tbl->entry_size,
1868 .ndtc_entries = atomic_read(&tbl->entries),
1869 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1870 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001871 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1872 };
1873
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001874 rcu_read_lock_bh();
1875 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001876 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001877 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001878 rcu_read_unlock_bh();
1879
David S. Miller9a6308d2012-04-01 20:06:28 -04001880 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1881 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001882 }
1883
1884 {
1885 int cpu;
1886 struct ndt_stats ndst;
1887
1888 memset(&ndst, 0, sizeof(ndst));
1889
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001890 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001891 struct neigh_statistics *st;
1892
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001893 st = per_cpu_ptr(tbl->stats, cpu);
1894 ndst.ndts_allocs += st->allocs;
1895 ndst.ndts_destroys += st->destroys;
1896 ndst.ndts_hash_grows += st->hash_grows;
1897 ndst.ndts_res_failed += st->res_failed;
1898 ndst.ndts_lookups += st->lookups;
1899 ndst.ndts_hits += st->hits;
1900 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1901 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1902 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1903 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001904 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001905 }
1906
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001907 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1908 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001909 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001910 }
1911
1912 BUG_ON(tbl->parms.dev);
1913 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001914 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001915
1916 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001917 nlmsg_end(skb, nlh);
1918 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001919
Thomas Grafca860fb2006-08-07 18:00:18 -07001920nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001922 nlmsg_cancel(skb, nlh);
1923 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001924}
1925
Thomas Grafca860fb2006-08-07 18:00:18 -07001926static int neightbl_fill_param_info(struct sk_buff *skb,
1927 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001928 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001929 u32 pid, u32 seq, int type,
1930 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001931{
1932 struct ndtmsg *ndtmsg;
1933 struct nlmsghdr *nlh;
1934
Thomas Grafca860fb2006-08-07 18:00:18 -07001935 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1936 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001937 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001938
Thomas Grafca860fb2006-08-07 18:00:18 -07001939 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001940
1941 read_lock_bh(&tbl->lock);
1942 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001943 ndtmsg->ndtm_pad1 = 0;
1944 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001945
Thomas Grafca860fb2006-08-07 18:00:18 -07001946 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1947 neightbl_fill_parms(skb, parms) < 0)
1948 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949
1950 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001951 nlmsg_end(skb, nlh);
1952 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001953errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001954 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001955 nlmsg_cancel(skb, nlh);
1956 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001957}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001958
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001959static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001960 [NDTA_NAME] = { .type = NLA_STRING },
1961 [NDTA_THRESH1] = { .type = NLA_U32 },
1962 [NDTA_THRESH2] = { .type = NLA_U32 },
1963 [NDTA_THRESH3] = { .type = NLA_U32 },
1964 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1965 [NDTA_PARMS] = { .type = NLA_NESTED },
1966};
1967
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001968static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001969 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1970 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1971 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1972 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1973 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1974 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001975 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001976 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1977 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1978 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1979 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1980 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1981 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1982 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1983};
1984
David Ahernc21ef3e2017-04-16 09:48:24 -07001985static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
1986 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001987{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001988 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001989 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001990 struct ndtmsg *ndtmsg;
1991 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001992 bool found = false;
1993 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001994
Thomas Graf6b3f8672006-08-07 17:58:53 -07001995 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07001996 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001997 if (err < 0)
1998 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001999
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 if (tb[NDTA_NAME] == NULL) {
2001 err = -EINVAL;
2002 goto errout;
2003 }
2004
2005 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002006
2007 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2008 tbl = neigh_tables[tidx];
2009 if (!tbl)
2010 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002011 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2012 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002013 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2014 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002015 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002016 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002017 }
2018
WANG Congd7480fd2014-11-10 15:59:36 -08002019 if (!found)
2020 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002021
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002022 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002023 * We acquire tbl->lock to be nice to the periodic timers and
2024 * make sure they always see a consistent set of values.
2025 */
2026 write_lock_bh(&tbl->lock);
2027
Thomas Graf6b3f8672006-08-07 17:58:53 -07002028 if (tb[NDTA_PARMS]) {
2029 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002030 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002031 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002032
Thomas Graf6b3f8672006-08-07 17:58:53 -07002033 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002034 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002035 if (err < 0)
2036 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002037
Thomas Graf6b3f8672006-08-07 17:58:53 -07002038 if (tbp[NDTPA_IFINDEX])
2039 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002040
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002041 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002042 if (p == NULL) {
2043 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002044 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002045 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002046
Thomas Graf6b3f8672006-08-07 17:58:53 -07002047 for (i = 1; i <= NDTPA_MAX; i++) {
2048 if (tbp[i] == NULL)
2049 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002050
Thomas Graf6b3f8672006-08-07 17:58:53 -07002051 switch (i) {
2052 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002053 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2054 nla_get_u32(tbp[i]) *
2055 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002056 break;
2057 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002058 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2059 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002060 break;
2061 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002062 NEIGH_VAR_SET(p, PROXY_QLEN,
2063 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002064 break;
2065 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002066 NEIGH_VAR_SET(p, APP_PROBES,
2067 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002068 break;
2069 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002070 NEIGH_VAR_SET(p, UCAST_PROBES,
2071 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002072 break;
2073 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002074 NEIGH_VAR_SET(p, MCAST_PROBES,
2075 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002077 case NDTPA_MCAST_REPROBES:
2078 NEIGH_VAR_SET(p, MCAST_REPROBES,
2079 nla_get_u32(tbp[i]));
2080 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002081 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002082 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2083 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002084 /* update reachable_time as well, otherwise, the change will
2085 * only be effective after the next time neigh_periodic_work
2086 * decides to recompute it (can be multiple minutes)
2087 */
2088 p->reachable_time =
2089 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002090 break;
2091 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002092 NEIGH_VAR_SET(p, GC_STALETIME,
2093 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002094 break;
2095 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002096 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2097 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002098 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002099 break;
2100 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002101 NEIGH_VAR_SET(p, RETRANS_TIME,
2102 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002103 break;
2104 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002105 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2106 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002107 break;
2108 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002109 NEIGH_VAR_SET(p, PROXY_DELAY,
2110 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002111 break;
2112 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002113 NEIGH_VAR_SET(p, LOCKTIME,
2114 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002115 break;
2116 }
2117 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002118 }
2119
Gao fengdc25c672013-06-20 10:01:34 +08002120 err = -ENOENT;
2121 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2122 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2123 !net_eq(net, &init_net))
2124 goto errout_tbl_lock;
2125
Thomas Graf6b3f8672006-08-07 17:58:53 -07002126 if (tb[NDTA_THRESH1])
2127 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2128
2129 if (tb[NDTA_THRESH2])
2130 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2131
2132 if (tb[NDTA_THRESH3])
2133 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2134
2135 if (tb[NDTA_GC_INTERVAL])
2136 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2137
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002138 err = 0;
2139
Thomas Graf6b3f8672006-08-07 17:58:53 -07002140errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002141 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002142errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002143 return err;
2144}
2145
Thomas Grafc8822a42007-03-22 11:50:06 -07002146static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002147{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002148 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002149 int family, tidx, nidx = 0;
2150 int tbl_skip = cb->args[0];
2151 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002152 struct neigh_table *tbl;
2153
Thomas Grafca860fb2006-08-07 18:00:18 -07002154 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002155
WANG Congd7480fd2014-11-10 15:59:36 -08002156 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002157 struct neigh_parms *p;
2158
WANG Congd7480fd2014-11-10 15:59:36 -08002159 tbl = neigh_tables[tidx];
2160 if (!tbl)
2161 continue;
2162
Thomas Grafca860fb2006-08-07 18:00:18 -07002163 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002164 continue;
2165
Eric W. Biederman15e47302012-09-07 20:12:54 +00002166 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002167 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002168 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002169 break;
2170
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002171 nidx = 0;
2172 p = list_next_entry(&tbl->parms, list);
2173 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002174 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002175 continue;
2176
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002177 if (nidx < neigh_skip)
2178 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002179
Thomas Grafca860fb2006-08-07 18:00:18 -07002180 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002181 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002182 cb->nlh->nlmsg_seq,
2183 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002184 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002185 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002186 next:
2187 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002188 }
2189
Thomas Grafca860fb2006-08-07 18:00:18 -07002190 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002191 }
2192out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002193 cb->args[0] = tidx;
2194 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002195
2196 return skb->len;
2197}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2200 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201{
2202 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002203 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002204 struct nlmsghdr *nlh;
2205 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206
Thomas Graf8b8aec52006-08-07 17:56:37 -07002207 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2208 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002209 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002210
2211 ndm = nlmsg_data(nlh);
2212 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002213 ndm->ndm_pad1 = 0;
2214 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002215 ndm->ndm_flags = neigh->flags;
2216 ndm->ndm_type = neigh->type;
2217 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218
David S. Miller9a6308d2012-04-01 20:06:28 -04002219 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2220 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002221
2222 read_lock_bh(&neigh->lock);
2223 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002224 if (neigh->nud_state & NUD_VALID) {
2225 char haddr[MAX_ADDR_LEN];
2226
2227 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2228 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2229 read_unlock_bh(&neigh->lock);
2230 goto nla_put_failure;
2231 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002232 }
2233
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002234 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2235 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2236 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002237 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002238 read_unlock_bh(&neigh->lock);
2239
David S. Miller9a6308d2012-04-01 20:06:28 -04002240 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2241 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2242 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002243
Johannes Berg053c0952015-01-16 22:09:00 +01002244 nlmsg_end(skb, nlh);
2245 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002246
2247nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002248 nlmsg_cancel(skb, nlh);
2249 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250}
2251
Tony Zelenoff84920c12012-01-26 22:28:58 +00002252static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2253 u32 pid, u32 seq, int type, unsigned int flags,
2254 struct neigh_table *tbl)
2255{
2256 struct nlmsghdr *nlh;
2257 struct ndmsg *ndm;
2258
2259 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2260 if (nlh == NULL)
2261 return -EMSGSIZE;
2262
2263 ndm = nlmsg_data(nlh);
2264 ndm->ndm_family = tbl->family;
2265 ndm->ndm_pad1 = 0;
2266 ndm->ndm_pad2 = 0;
2267 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002268 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002269 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002270 ndm->ndm_state = NUD_NONE;
2271
David S. Miller9a6308d2012-04-01 20:06:28 -04002272 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2273 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002274
Johannes Berg053c0952015-01-16 22:09:00 +01002275 nlmsg_end(skb, nlh);
2276 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002277
2278nla_put_failure:
2279 nlmsg_cancel(skb, nlh);
2280 return -EMSGSIZE;
2281}
2282
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002283static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002284{
2285 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002286 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002287}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288
David Ahern21fdd092015-09-29 09:32:03 -07002289static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2290{
2291 struct net_device *master;
2292
2293 if (!master_idx)
2294 return false;
2295
2296 master = netdev_master_upper_dev_get(dev);
2297 if (!master || master->ifindex != master_idx)
2298 return true;
2299
2300 return false;
2301}
2302
David Ahern16660f02015-10-03 11:43:46 -07002303static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2304{
2305 if (filter_idx && dev->ifindex != filter_idx)
2306 return true;
2307
2308 return false;
2309}
2310
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2312 struct netlink_callback *cb)
2313{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002314 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002315 const struct nlmsghdr *nlh = cb->nlh;
2316 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 struct neighbour *n;
2318 int rc, h, s_h = cb->args[1];
2319 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002320 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002321 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002322 unsigned int flags = NLM_F_MULTI;
2323 int err;
2324
Johannes Bergfceb6432017-04-12 14:34:07 +02002325 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002326 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002327 if (tb[NDA_IFINDEX])
2328 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2329
David Ahern21fdd092015-09-29 09:32:03 -07002330 if (tb[NDA_MASTER])
2331 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2332
David Ahern16660f02015-10-03 11:43:46 -07002333 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002334 flags |= NLM_F_DUMP_FILTERED;
2335 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002337 rcu_read_lock_bh();
2338 nht = rcu_dereference_bh(tbl->nht);
2339
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002340 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 if (h > s_h)
2342 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002343 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2344 n != NULL;
2345 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002346 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2347 goto next;
2348 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2349 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002350 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002351 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002353 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002354 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 rc = -1;
2356 goto out;
2357 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002358next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002359 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361 }
2362 rc = skb->len;
2363out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002364 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365 cb->args[1] = h;
2366 cb->args[2] = idx;
2367 return rc;
2368}
2369
Tony Zelenoff84920c12012-01-26 22:28:58 +00002370static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2371 struct netlink_callback *cb)
2372{
2373 struct pneigh_entry *n;
2374 struct net *net = sock_net(skb->sk);
2375 int rc, h, s_h = cb->args[3];
2376 int idx, s_idx = idx = cb->args[4];
2377
2378 read_lock_bh(&tbl->lock);
2379
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002380 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002381 if (h > s_h)
2382 s_idx = 0;
2383 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002384 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002385 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002386 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002387 cb->nlh->nlmsg_seq,
2388 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002389 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002390 read_unlock_bh(&tbl->lock);
2391 rc = -1;
2392 goto out;
2393 }
2394 next:
2395 idx++;
2396 }
2397 }
2398
2399 read_unlock_bh(&tbl->lock);
2400 rc = skb->len;
2401out:
2402 cb->args[3] = h;
2403 cb->args[4] = idx;
2404 return rc;
2405
2406}
2407
Thomas Grafc8822a42007-03-22 11:50:06 -07002408static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409{
2410 struct neigh_table *tbl;
2411 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002412 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002413 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Thomas Graf8b8aec52006-08-07 17:56:37 -07002415 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002416
2417 /* check for full ndmsg structure presence, family member is
2418 * the same for both structures
2419 */
2420 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2421 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2422 proxy = 1;
2423
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 s_t = cb->args[0];
2425
WANG Congd7480fd2014-11-10 15:59:36 -08002426 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2427 tbl = neigh_tables[t];
2428
2429 if (!tbl)
2430 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002431 if (t < s_t || (family && tbl->family != family))
2432 continue;
2433 if (t > s_t)
2434 memset(&cb->args[1], 0, sizeof(cb->args) -
2435 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002436 if (proxy)
2437 err = pneigh_dump_table(tbl, skb, cb);
2438 else
2439 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002440 if (err < 0)
2441 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443
2444 cb->args[0] = t;
2445 return skb->len;
2446}
2447
2448void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2449{
2450 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002451 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002453 rcu_read_lock_bh();
2454 nht = rcu_dereference_bh(tbl->nht);
2455
Eric Dumazet767e97e2010-10-06 17:49:21 -07002456 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002457 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458 struct neighbour *n;
2459
Eric Dumazet767e97e2010-10-06 17:49:21 -07002460 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2461 n != NULL;
2462 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002463 cb(n, cookie);
2464 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002465 read_unlock(&tbl->lock);
2466 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002467}
2468EXPORT_SYMBOL(neigh_for_each);
2469
2470/* The tbl->lock must be held as a writer and BH disabled. */
2471void __neigh_for_each_release(struct neigh_table *tbl,
2472 int (*cb)(struct neighbour *))
2473{
2474 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002475 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002477 nht = rcu_dereference_protected(tbl->nht,
2478 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002479 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002480 struct neighbour *n;
2481 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002482
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002483 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002484 while ((n = rcu_dereference_protected(*np,
2485 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 int release;
2487
2488 write_lock(&n->lock);
2489 release = cb(n);
2490 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002491 rcu_assign_pointer(*np,
2492 rcu_dereference_protected(n->next,
2493 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 n->dead = 1;
2495 } else
2496 np = &n->next;
2497 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002498 if (release)
2499 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 }
2501 }
2502}
2503EXPORT_SYMBOL(__neigh_for_each_release);
2504
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002505int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002506 const void *addr, struct sk_buff *skb)
2507{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002508 int err = -EAFNOSUPPORT;
2509 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002510 struct neigh_table *tbl;
2511 struct neighbour *neigh;
2512
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002513 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002514 if (!tbl)
2515 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002516 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002517 neigh = __neigh_lookup_noref(tbl, addr, dev);
2518 if (!neigh)
2519 neigh = __neigh_create(tbl, addr, dev, false);
2520 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002521 if (IS_ERR(neigh)) {
2522 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002523 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002524 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002525 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002526 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002527 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002528 else if (index == NEIGH_LINK_TABLE) {
2529 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2530 addr, NULL, skb->len);
2531 if (err < 0)
2532 goto out_kfree_skb;
2533 err = dev_queue_xmit(skb);
2534 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002535out:
2536 return err;
2537out_kfree_skb:
2538 kfree_skb(skb);
2539 goto out;
2540}
2541EXPORT_SYMBOL(neigh_xmit);
2542
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543#ifdef CONFIG_PROC_FS
2544
2545static struct neighbour *neigh_get_first(struct seq_file *seq)
2546{
2547 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002548 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002549 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550 struct neighbour *n = NULL;
2551 int bucket = state->bucket;
2552
2553 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002554 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002555 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002558 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002559 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 if (state->neigh_sub_iter) {
2561 loff_t fakep = 0;
2562 void *v;
2563
2564 v = state->neigh_sub_iter(state, n, &fakep);
2565 if (!v)
2566 goto next;
2567 }
2568 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2569 break;
2570 if (n->nud_state & ~NUD_NOARP)
2571 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002572next:
2573 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 }
2575
2576 if (n)
2577 break;
2578 }
2579 state->bucket = bucket;
2580
2581 return n;
2582}
2583
2584static struct neighbour *neigh_get_next(struct seq_file *seq,
2585 struct neighbour *n,
2586 loff_t *pos)
2587{
2588 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002589 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002590 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591
2592 if (state->neigh_sub_iter) {
2593 void *v = state->neigh_sub_iter(state, n, pos);
2594 if (v)
2595 return n;
2596 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002597 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
2599 while (1) {
2600 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002601 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002602 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603 if (state->neigh_sub_iter) {
2604 void *v = state->neigh_sub_iter(state, n, pos);
2605 if (v)
2606 return n;
2607 goto next;
2608 }
2609 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2610 break;
2611
2612 if (n->nud_state & ~NUD_NOARP)
2613 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002614next:
2615 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 }
2617
2618 if (n)
2619 break;
2620
David S. Millercd089332011-07-11 01:28:12 -07002621 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 break;
2623
Eric Dumazet767e97e2010-10-06 17:49:21 -07002624 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625 }
2626
2627 if (n && pos)
2628 --(*pos);
2629 return n;
2630}
2631
2632static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2633{
2634 struct neighbour *n = neigh_get_first(seq);
2635
2636 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002637 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 while (*pos) {
2639 n = neigh_get_next(seq, n, pos);
2640 if (!n)
2641 break;
2642 }
2643 }
2644 return *pos ? NULL : n;
2645}
2646
2647static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2648{
2649 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002650 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 struct neigh_table *tbl = state->tbl;
2652 struct pneigh_entry *pn = NULL;
2653 int bucket = state->bucket;
2654
2655 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2656 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2657 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002658 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002659 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002660 if (pn)
2661 break;
2662 }
2663 state->bucket = bucket;
2664
2665 return pn;
2666}
2667
2668static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2669 struct pneigh_entry *pn,
2670 loff_t *pos)
2671{
2672 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002673 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 struct neigh_table *tbl = state->tbl;
2675
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002676 do {
2677 pn = pn->next;
2678 } while (pn && !net_eq(pneigh_net(pn), net));
2679
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 while (!pn) {
2681 if (++state->bucket > PNEIGH_HASHMASK)
2682 break;
2683 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002684 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002685 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686 if (pn)
2687 break;
2688 }
2689
2690 if (pn && pos)
2691 --(*pos);
2692
2693 return pn;
2694}
2695
2696static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2697{
2698 struct pneigh_entry *pn = pneigh_get_first(seq);
2699
2700 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002701 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 while (*pos) {
2703 pn = pneigh_get_next(seq, pn, pos);
2704 if (!pn)
2705 break;
2706 }
2707 }
2708 return *pos ? NULL : pn;
2709}
2710
2711static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2712{
2713 struct neigh_seq_state *state = seq->private;
2714 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002715 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716
Chris Larson745e2032008-08-03 01:10:55 -07002717 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002718 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002719 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720
2721 return rc;
2722}
2723
2724void *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 +00002725 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002726{
2727 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728
2729 state->tbl = tbl;
2730 state->bucket = 0;
2731 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2732
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002733 rcu_read_lock_bh();
2734 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002735
Chris Larson745e2032008-08-03 01:10:55 -07002736 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002737}
2738EXPORT_SYMBOL(neigh_seq_start);
2739
2740void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2741{
2742 struct neigh_seq_state *state;
2743 void *rc;
2744
2745 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002746 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 goto out;
2748 }
2749
2750 state = seq->private;
2751 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2752 rc = neigh_get_next(seq, v, NULL);
2753 if (rc)
2754 goto out;
2755 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2756 rc = pneigh_get_first(seq);
2757 } else {
2758 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2759 rc = pneigh_get_next(seq, v, NULL);
2760 }
2761out:
2762 ++(*pos);
2763 return rc;
2764}
2765EXPORT_SYMBOL(neigh_seq_next);
2766
2767void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002768 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002770 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771}
2772EXPORT_SYMBOL(neigh_seq_stop);
2773
2774/* statistics via seq_file */
2775
2776static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2777{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002778 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002779 int cpu;
2780
2781 if (*pos == 0)
2782 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002783
Rusty Russell0f23174a2008-12-29 12:23:42 +00002784 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002785 if (!cpu_possible(cpu))
2786 continue;
2787 *pos = cpu+1;
2788 return per_cpu_ptr(tbl->stats, cpu);
2789 }
2790 return NULL;
2791}
2792
2793static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2794{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002795 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002796 int cpu;
2797
Rusty Russell0f23174a2008-12-29 12:23:42 +00002798 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002799 if (!cpu_possible(cpu))
2800 continue;
2801 *pos = cpu+1;
2802 return per_cpu_ptr(tbl->stats, cpu);
2803 }
2804 return NULL;
2805}
2806
2807static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2808{
2809
2810}
2811
2812static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2813{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002814 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002815 struct neigh_statistics *st = v;
2816
2817 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002818 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 -07002819 return 0;
2820 }
2821
2822 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002823 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002824 atomic_read(&tbl->entries),
2825
2826 st->allocs,
2827 st->destroys,
2828 st->hash_grows,
2829
2830 st->lookups,
2831 st->hits,
2832
2833 st->res_failed,
2834
2835 st->rcv_probes_mcast,
2836 st->rcv_probes_ucast,
2837
2838 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002839 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002840 st->unres_discards,
2841 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842 );
2843
2844 return 0;
2845}
2846
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002847static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848 .start = neigh_stat_seq_start,
2849 .next = neigh_stat_seq_next,
2850 .stop = neigh_stat_seq_stop,
2851 .show = neigh_stat_seq_show,
2852};
2853
2854static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2855{
2856 int ret = seq_open(file, &neigh_stat_seq_ops);
2857
2858 if (!ret) {
2859 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002860 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002861 }
2862 return ret;
2863};
2864
Arjan van de Ven9a321442007-02-12 00:55:35 -08002865static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002866 .owner = THIS_MODULE,
2867 .open = neigh_stat_seq_open,
2868 .read = seq_read,
2869 .llseek = seq_lseek,
2870 .release = seq_release,
2871};
2872
2873#endif /* CONFIG_PROC_FS */
2874
Thomas Graf339bf982006-11-10 14:10:15 -08002875static inline size_t neigh_nlmsg_size(void)
2876{
2877 return NLMSG_ALIGN(sizeof(struct ndmsg))
2878 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2879 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2880 + nla_total_size(sizeof(struct nda_cacheinfo))
2881 + nla_total_size(4); /* NDA_PROBES */
2882}
2883
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002884static void __neigh_notify(struct neighbour *n, int type, int flags,
2885 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002886{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002887 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002888 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002889 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002890
Thomas Graf339bf982006-11-10 14:10:15 -08002891 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002892 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002893 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002894
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002895 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002896 if (err < 0) {
2897 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2898 WARN_ON(err == -EMSGSIZE);
2899 kfree_skb(skb);
2900 goto errout;
2901 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002902 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2903 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002904errout:
2905 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002906 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002907}
2908
2909void neigh_app_ns(struct neighbour *n)
2910{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002911 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002912}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002913EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002914
2915#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002916static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002917static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002918static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002919
Joe Perchesfe2c6332013-06-11 23:04:25 -07002920static int proc_unres_qlen(struct ctl_table *ctl, int write,
2921 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002922{
2923 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002924 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002925
Shan Weice46cc62012-12-04 18:49:15 +00002926 tmp.extra1 = &zero;
2927 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002928 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002929
2930 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2931 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2932
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002933 if (write && !ret)
2934 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2935 return ret;
2936}
2937
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002938static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2939 int family)
2940{
Jiri Pirkobba24892013-12-07 19:26:57 +01002941 switch (family) {
2942 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002943 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002944 case AF_INET6:
2945 return __in6_dev_nd_parms_get_rcu(dev);
2946 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002947 return NULL;
2948}
2949
2950static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2951 int index)
2952{
2953 struct net_device *dev;
2954 int family = neigh_parms_family(p);
2955
2956 rcu_read_lock();
2957 for_each_netdev_rcu(net, dev) {
2958 struct neigh_parms *dst_p =
2959 neigh_get_dev_parms_rcu(dev, family);
2960
2961 if (dst_p && !test_bit(index, dst_p->data_state))
2962 dst_p->data[index] = p->data[index];
2963 }
2964 rcu_read_unlock();
2965}
2966
2967static void neigh_proc_update(struct ctl_table *ctl, int write)
2968{
2969 struct net_device *dev = ctl->extra1;
2970 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002971 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002972 int index = (int *) ctl->data - p->data;
2973
2974 if (!write)
2975 return;
2976
2977 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002978 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2979 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002980 if (!dev) /* NULL dev means this is default value */
2981 neigh_copy_dflt_parms(net, p, index);
2982}
2983
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002984static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2985 void __user *buffer,
2986 size_t *lenp, loff_t *ppos)
2987{
2988 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002989 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002990
2991 tmp.extra1 = &zero;
2992 tmp.extra2 = &int_max;
2993
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002994 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2995 neigh_proc_update(ctl, write);
2996 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002997}
2998
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002999int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3000 void __user *buffer, size_t *lenp, loff_t *ppos)
3001{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003002 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3003
3004 neigh_proc_update(ctl, write);
3005 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003006}
3007EXPORT_SYMBOL(neigh_proc_dointvec);
3008
3009int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3010 void __user *buffer,
3011 size_t *lenp, loff_t *ppos)
3012{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003013 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3014
3015 neigh_proc_update(ctl, write);
3016 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003017}
3018EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3019
3020static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3021 void __user *buffer,
3022 size_t *lenp, loff_t *ppos)
3023{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003024 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3025
3026 neigh_proc_update(ctl, write);
3027 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003028}
3029
3030int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3031 void __user *buffer,
3032 size_t *lenp, loff_t *ppos)
3033{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003034 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3035
3036 neigh_proc_update(ctl, write);
3037 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003038}
3039EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3040
3041static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3042 void __user *buffer,
3043 size_t *lenp, loff_t *ppos)
3044{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003045 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3046
3047 neigh_proc_update(ctl, write);
3048 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003049}
3050
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003051static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3052 void __user *buffer,
3053 size_t *lenp, loff_t *ppos)
3054{
3055 struct neigh_parms *p = ctl->extra2;
3056 int ret;
3057
3058 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3059 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3060 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3061 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3062 else
3063 ret = -1;
3064
3065 if (write && ret == 0) {
3066 /* update reachable_time as well, otherwise, the change will
3067 * only be effective after the next time neigh_periodic_work
3068 * decides to recompute it
3069 */
3070 p->reachable_time =
3071 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3072 }
3073 return ret;
3074}
3075
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003076#define NEIGH_PARMS_DATA_OFFSET(index) \
3077 (&((struct neigh_parms *) 0)->data[index])
3078
3079#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3080 [NEIGH_VAR_ ## attr] = { \
3081 .procname = name, \
3082 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3083 .maxlen = sizeof(int), \
3084 .mode = mval, \
3085 .proc_handler = proc, \
3086 }
3087
3088#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3089 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3090
3091#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003092 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003093
3094#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003095 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003096
3097#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003098 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003099
3100#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003101 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003102
3103#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003104 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003105
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106static struct neigh_sysctl_table {
3107 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003108 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003109} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003111 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3112 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3113 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003114 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003115 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3116 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3117 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3118 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3119 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3120 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3121 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3122 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3123 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3124 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3125 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3126 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003127 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128 .procname = "gc_interval",
3129 .maxlen = sizeof(int),
3130 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003131 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003133 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 .procname = "gc_thresh1",
3135 .maxlen = sizeof(int),
3136 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003137 .extra1 = &zero,
3138 .extra2 = &int_max,
3139 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003140 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003141 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003142 .procname = "gc_thresh2",
3143 .maxlen = sizeof(int),
3144 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003145 .extra1 = &zero,
3146 .extra2 = &int_max,
3147 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003149 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 .procname = "gc_thresh3",
3151 .maxlen = sizeof(int),
3152 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003153 .extra1 = &zero,
3154 .extra2 = &int_max,
3155 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003156 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003157 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003158 },
3159};
3160
3161int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003162 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003164 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003165 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003166 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003167 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003168 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003170 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003171 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003172 goto err;
3173
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003174 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003175 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003176 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003177 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179
3180 if (dev) {
3181 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003182 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003183 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3184 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003186 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003187 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003188 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3189 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3190 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3191 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003192 }
3193
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003194 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003196 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003198 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003200 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003202 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003203 } else {
3204 /* Those handlers will update p->reachable_time after
3205 * base_reachable_time(_ms) is set to ensure the new timer starts being
3206 * applied after the next neighbour update instead of waiting for
3207 * neigh_periodic_work to update its value (can be multiple minutes)
3208 * So any handler that replaces them should do this as well
3209 */
3210 /* ReachableTime */
3211 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3212 neigh_proc_base_reachable_time;
3213 /* ReachableTime (in milliseconds) */
3214 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3215 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216 }
3217
Eric W. Biederman464dc802012-11-16 03:02:59 +00003218 /* Don't export sysctls to unprivileged users */
3219 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3220 t->neigh_vars[0].procname = NULL;
3221
Jiri Pirko73af6142013-12-07 19:26:55 +01003222 switch (neigh_parms_family(p)) {
3223 case AF_INET:
3224 p_name = "ipv4";
3225 break;
3226 case AF_INET6:
3227 p_name = "ipv6";
3228 break;
3229 default:
3230 BUG();
3231 }
3232
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003233 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3234 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003235 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003236 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003237 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003238 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003239
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 p->sysctl_table = t;
3241 return 0;
3242
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003243free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003245err:
3246 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003248EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249
3250void neigh_sysctl_unregister(struct neigh_parms *p)
3251{
3252 if (p->sysctl_table) {
3253 struct neigh_sysctl_table *t = p->sysctl_table;
3254 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003255 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003256 kfree(t);
3257 }
3258}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003259EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260
3261#endif /* CONFIG_SYSCTL */
3262
Thomas Grafc8822a42007-03-22 11:50:06 -07003263static int __init neigh_init(void)
3264{
Greg Rosec7ac8672011-06-10 01:27:09 +00003265 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3266 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3267 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003268
Greg Rosec7ac8672011-06-10 01:27:09 +00003269 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3270 NULL);
3271 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003272
3273 return 0;
3274}
3275
3276subsys_initcall(neigh_init);
3277