blob: 16a1a4c4eb57fa1147f230916e2e62e18ef89562 [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{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400350 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500351}
352
David S. Millercd089332011-07-11 01:28:12 -0700353static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
David S. Millercd089332011-07-11 01:28:12 -0700355 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000357 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500358 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
361 if (!ret)
362 return NULL;
363 if (size <= PAGE_SIZE)
364 buckets = kzalloc(size, GFP_ATOMIC);
365 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000366 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000367 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
368 get_order(size));
369 if (!buckets) {
370 kfree(ret);
371 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700372 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000373 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700374 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500375 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
376 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 return ret;
378}
379
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000380static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000382 struct neigh_hash_table *nht = container_of(head,
383 struct neigh_hash_table,
384 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700385 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000386 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
388 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000389 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000391 free_pages((unsigned long)buckets, get_order(size));
392 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393}
394
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000395static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700396 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000398 unsigned int i, hash;
399 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400
401 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
402
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000403 old_nht = rcu_dereference_protected(tbl->nht,
404 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700405 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000406 if (!new_nht)
407 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408
David S. Millercd089332011-07-11 01:28:12 -0700409 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 struct neighbour *n, *next;
411
Eric Dumazet767e97e2010-10-06 17:49:21 -0700412 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
413 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000414 n != NULL;
415 n = next) {
416 hash = tbl->hash(n->primary_key, n->dev,
417 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418
David S. Millercd089332011-07-11 01:28:12 -0700419 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700420 next = rcu_dereference_protected(n->next,
421 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
Eric Dumazet767e97e2010-10-06 17:49:21 -0700423 rcu_assign_pointer(n->next,
424 rcu_dereference_protected(
425 new_nht->hash_buckets[hash],
426 lockdep_is_held(&tbl->lock)));
427 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 }
429 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000431 rcu_assign_pointer(tbl->nht, new_nht);
432 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
433 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434}
435
436struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
437 struct net_device *dev)
438{
439 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 NEIGH_CACHE_STAT_INC(tbl, lookups);
442
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000443 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600444 n = __neigh_lookup_noref(tbl, pkey, dev);
445 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300446 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600447 n = NULL;
448 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700450
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000451 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 return n;
453}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900454EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455
Eric W. Biederman426b5302008-01-24 00:13:18 -0800456struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
457 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458{
459 struct neighbour *n;
460 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800461 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000462 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463
464 NEIGH_CACHE_STAT_INC(tbl, lookups);
465
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000466 rcu_read_lock_bh();
467 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700468 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700469
470 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
471 n != NULL;
472 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800473 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900474 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300475 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700476 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 NEIGH_CACHE_STAT_INC(tbl, hits);
478 break;
479 }
480 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700481
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000482 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483 return n;
484}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900485EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486
David S. Millera263b302012-07-02 02:02:15 -0700487struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
488 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489{
490 u32 hash_val;
491 int key_len = tbl->key_len;
492 int error;
David Miller596b9b62011-07-25 00:01:25 +0000493 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495
496 if (!n) {
497 rc = ERR_PTR(-ENOBUFS);
498 goto out;
499 }
500
501 memcpy(n->primary_key, pkey, key_len);
502 n->dev = dev;
503 dev_hold(dev);
504
505 /* Protocol specific setup. */
506 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
507 rc = ERR_PTR(error);
508 goto out_neigh_release;
509 }
510
David Millerda6a8fa2011-07-25 00:01:38 +0000511 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200512 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000513 if (error < 0) {
514 rc = ERR_PTR(error);
515 goto out_neigh_release;
516 }
517 }
518
David S. Miller447f2192011-12-19 15:04:41 -0500519 /* Device specific setup. */
520 if (n->parms->neigh_setup &&
521 (error = n->parms->neigh_setup(n)) < 0) {
522 rc = ERR_PTR(error);
523 goto out_neigh_release;
524 }
525
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100526 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527
528 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000529 nht = rcu_dereference_protected(tbl->nht,
530 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531
David S. Millercd089332011-07-11 01:28:12 -0700532 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
533 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
David S. Millercd089332011-07-11 01:28:12 -0700535 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536
537 if (n->parms->dead) {
538 rc = ERR_PTR(-EINVAL);
539 goto out_tbl_unlock;
540 }
541
Eric Dumazet767e97e2010-10-06 17:49:21 -0700542 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
543 lockdep_is_held(&tbl->lock));
544 n1 != NULL;
545 n1 = rcu_dereference_protected(n1->next,
546 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700548 if (want_ref)
549 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550 rc = n1;
551 goto out_tbl_unlock;
552 }
553 }
554
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700556 if (want_ref)
557 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700558 rcu_assign_pointer(n->next,
559 rcu_dereference_protected(nht->hash_buckets[hash_val],
560 lockdep_is_held(&tbl->lock)));
561 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000563 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564 rc = n;
565out:
566 return rc;
567out_tbl_unlock:
568 write_unlock_bh(&tbl->lock);
569out_neigh_release:
570 neigh_release(n);
571 goto out;
572}
David S. Millera263b302012-07-02 02:02:15 -0700573EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900575static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700576{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700577 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700578 hash_val ^= (hash_val >> 16);
579 hash_val ^= hash_val >> 8;
580 hash_val ^= hash_val >> 4;
581 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900582 return hash_val;
583}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700584
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900585static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
586 struct net *net,
587 const void *pkey,
588 int key_len,
589 struct net_device *dev)
590{
591 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700592 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900593 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700594 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900595 return n;
596 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700597 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900598 return NULL;
599}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700600
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900601struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
602 struct net *net, const void *pkey, struct net_device *dev)
603{
604 int key_len = tbl->key_len;
605 u32 hash_val = pneigh_hash(pkey, key_len);
606
607 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
608 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700609}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900610EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700611
Eric W. Biederman426b5302008-01-24 00:13:18 -0800612struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
613 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 struct net_device *dev, int creat)
615{
616 struct pneigh_entry *n;
617 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900618 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900621 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
622 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900624
625 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626 goto out;
627
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700628 ASSERT_RTNL();
629
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
631 if (!n)
632 goto out;
633
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500634 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 memcpy(n->key, pkey, key_len);
636 n->dev = dev;
637 if (dev)
638 dev_hold(dev);
639
640 if (tbl->pconstructor && tbl->pconstructor(n)) {
641 if (dev)
642 dev_put(dev);
643 kfree(n);
644 n = NULL;
645 goto out;
646 }
647
648 write_lock_bh(&tbl->lock);
649 n->next = tbl->phash_buckets[hash_val];
650 tbl->phash_buckets[hash_val] = n;
651 write_unlock_bh(&tbl->lock);
652out:
653 return n;
654}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900655EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700656
657
Eric W. Biederman426b5302008-01-24 00:13:18 -0800658int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 struct net_device *dev)
660{
661 struct pneigh_entry *n, **np;
662 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900663 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664
665 write_lock_bh(&tbl->lock);
666 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
667 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800668 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900669 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700670 *np = n->next;
671 write_unlock_bh(&tbl->lock);
672 if (tbl->pdestructor)
673 tbl->pdestructor(n);
674 if (n->dev)
675 dev_put(n->dev);
676 kfree(n);
677 return 0;
678 }
679 }
680 write_unlock_bh(&tbl->lock);
681 return -ENOENT;
682}
683
684static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
685{
686 struct pneigh_entry *n, **np;
687 u32 h;
688
689 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
690 np = &tbl->phash_buckets[h];
691 while ((n = *np) != NULL) {
692 if (!dev || n->dev == dev) {
693 *np = n->next;
694 if (tbl->pdestructor)
695 tbl->pdestructor(n);
696 if (n->dev)
697 dev_put(n->dev);
698 kfree(n);
699 continue;
700 }
701 np = &n->next;
702 }
703 }
704 return -ENOENT;
705}
706
Denis V. Lunev06f05112008-01-24 00:30:58 -0800707static void neigh_parms_destroy(struct neigh_parms *parms);
708
709static inline void neigh_parms_put(struct neigh_parms *parms)
710{
Reshetova, Elena63439442017-06-30 13:07:56 +0300711 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800712 neigh_parms_destroy(parms);
713}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714
715/*
716 * neighbour must already be out of the table;
717 *
718 */
719void neigh_destroy(struct neighbour *neigh)
720{
David Millerda6a8fa2011-07-25 00:01:38 +0000721 struct net_device *dev = neigh->dev;
722
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
724
725 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000726 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 dump_stack();
728 return;
729 }
730
731 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000732 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700734 write_lock_bh(&neigh->lock);
735 __skb_queue_purge(&neigh->arp_queue);
736 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000737 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
David S. Miller447f2192011-12-19 15:04:41 -0500739 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200740 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500741
David Millerda6a8fa2011-07-25 00:01:38 +0000742 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 neigh_parms_put(neigh->parms);
744
Joe Perchesd5d427c2013-04-15 15:17:19 +0000745 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746
747 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000748 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900750EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751
752/* Neighbour state is suspicious;
753 disable fast path.
754
755 Called with write_locked neigh.
756 */
757static void neigh_suspect(struct neighbour *neigh)
758{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000759 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762}
763
764/* Neighbour state is OK;
765 enable fast path.
766
767 Called with write_locked neigh.
768 */
769static void neigh_connect(struct neighbour *neigh)
770{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000771 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
773 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774}
775
Eric Dumazete4c4e442009-07-30 03:15:07 +0000776static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000778 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700779 struct neighbour *n;
780 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000781 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000782 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783
784 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
785
Eric Dumazete4c4e442009-07-30 03:15:07 +0000786 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000787 nht = rcu_dereference_protected(tbl->nht,
788 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
790 /*
791 * periodically recompute ReachableTime from random function
792 */
793
Eric Dumazete4c4e442009-07-30 03:15:07 +0000794 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000796 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100797 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100799 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800 }
801
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800802 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
803 goto out;
804
David S. Millercd089332011-07-11 01:28:12 -0700805 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000806 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Eric Dumazet767e97e2010-10-06 17:49:21 -0700808 while ((n = rcu_dereference_protected(*np,
809 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000810 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
Eric Dumazete4c4e442009-07-30 03:15:07 +0000812 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Eric Dumazete4c4e442009-07-30 03:15:07 +0000814 state = n->nud_state;
815 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
816 write_unlock(&n->lock);
817 goto next_elt;
818 }
819
820 if (time_before(n->used, n->confirmed))
821 n->used = n->confirmed;
822
Reshetova, Elena9f237432017-06-30 13:07:55 +0300823 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000824 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100825 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000826 *np = n->next;
827 n->dead = 1;
828 write_unlock(&n->lock);
829 neigh_cleanup_and_release(n);
830 continue;
831 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833
834next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000835 np = &n->next;
836 }
837 /*
838 * It's fine to release lock here, even if hash table
839 * grows while we are preempted.
840 */
841 write_unlock_bh(&tbl->lock);
842 cond_resched();
843 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500844 nht = rcu_dereference_protected(tbl->nht,
845 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000847out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100848 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
849 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
850 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 */
viresh kumarf6180022014-01-22 12:23:33 +0530852 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100853 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000854 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855}
856
857static __inline__ int neigh_max_probes(struct neighbour *n)
858{
859 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900860 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
861 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
862 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863}
864
Timo Teras5ef12d92009-06-11 04:16:28 -0700865static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000866 __releases(neigh->lock)
867 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700868{
869 struct sk_buff *skb;
870
871 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000872 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700873 neigh->updated = jiffies;
874
875 /* It is very thin place. report_unreachable is very complicated
876 routine. Particularly, it can hit the same neighbour entry!
877
878 So that, we try to be accurate and avoid dead loop. --ANK
879 */
880 while (neigh->nud_state == NUD_FAILED &&
881 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
882 write_unlock(&neigh->lock);
883 neigh->ops->error_report(neigh, skb);
884 write_lock(&neigh->lock);
885 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700886 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000887 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700888}
889
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000890static void neigh_probe(struct neighbour *neigh)
891 __releases(neigh->lock)
892{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200893 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000894 /* keep skb alive even if arp_queue overflows */
895 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800896 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000897 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700898 if (neigh->ops->solicit)
899 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000900 atomic_inc(&neigh->probes);
901 kfree_skb(skb);
902}
903
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904/* Called when a timer expires for a neighbour entry. */
905
906static void neigh_timer_handler(unsigned long arg)
907{
908 unsigned long now, next;
909 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000910 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 int notify = 0;
912
913 write_lock(&neigh->lock);
914
915 state = neigh->nud_state;
916 now = jiffies;
917 next = now + HZ;
918
David S. Miller045f7b32011-11-01 17:45:55 -0400919 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700921
922 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900923 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000925 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 next = neigh->confirmed + neigh->parms->reachable_time;
927 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100928 neigh->used +
929 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000930 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800932 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100934 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000936 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800938 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700939 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700940 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700941 }
942 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900943 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100944 neigh->confirmed +
945 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000946 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800948 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700950 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951 next = neigh->confirmed + neigh->parms->reachable_time;
952 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000953 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800955 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700956 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900957 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100958 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 }
960 } else {
961 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100962 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 }
964
965 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
966 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 neigh->nud_state = NUD_FAILED;
968 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700969 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800970 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 }
972
973 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 if (time_before(next, jiffies + HZ/2))
975 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000976 if (!mod_timer(&neigh->timer, next))
977 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 }
979 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000980 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800981 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800982out:
David S. Miller9ff56602008-02-17 18:39:54 -0800983 write_unlock(&neigh->lock);
984 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Thomas Grafd961db32007-08-08 23:12:56 -0700986 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700987 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -0700988
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 neigh_release(neigh);
990}
991
992int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
993{
994 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000995 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996
997 write_lock_bh(&neigh->lock);
998
999 rc = 0;
1000 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1001 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001002 if (neigh->dead)
1003 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001006 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1007 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001008 unsigned long next, now = jiffies;
1009
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001010 atomic_set(&neigh->probes,
1011 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001013 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001014 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1015 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001016 neigh_add_timer(neigh, next);
1017 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 } else {
1019 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001020 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 write_unlock_bh(&neigh->lock);
1022
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001023 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 return 1;
1025 }
1026 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001027 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001029 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001030 neigh_add_timer(neigh, jiffies +
1031 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001032 }
1033
1034 if (neigh->nud_state == NUD_INCOMPLETE) {
1035 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001036 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001037 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001039
David S. Millerf72051b2008-09-23 01:11:18 -07001040 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001041 if (!buff)
1042 break;
1043 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001045 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001047 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001049 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 }
1051 rc = 1;
1052 }
1053out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001054 if (immediate_probe)
1055 neigh_probe(neigh);
1056 else
1057 write_unlock(&neigh->lock);
1058 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001060
1061out_dead:
1062 if (neigh->nud_state & NUD_STALE)
1063 goto out_unlock_bh;
1064 write_unlock_bh(&neigh->lock);
1065 kfree_skb(skb);
1066 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001068EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069
David S. Millerf6b72b622011-07-14 07:53:20 -07001070static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071{
1072 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001073 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001074 = NULL;
1075
1076 if (neigh->dev->header_ops)
1077 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078
1079 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001080 hh = &neigh->hh;
1081 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001082 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001083 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001084 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 }
1086 }
1087}
1088
1089
1090
1091/* Generic update routine.
1092 -- lladdr is new lladdr or NULL, if it is not supplied.
1093 -- new is new state.
1094 -- flags
1095 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1096 if it is different.
1097 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001098 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1101
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001102 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 NTF_ROUTER flag.
1104 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1105 a router.
1106
1107 Caller MUST hold reference count on the entry.
1108 */
1109
1110int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001111 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112{
1113 u8 old;
1114 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116 struct net_device *dev;
1117 int update_isrouter = 0;
1118
1119 write_lock_bh(&neigh->lock);
1120
1121 dev = neigh->dev;
1122 old = neigh->nud_state;
1123 err = -EPERM;
1124
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001125 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 (old & (NUD_NOARP | NUD_PERMANENT)))
1127 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001128 if (neigh->dead)
1129 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130
1131 if (!(new & NUD_VALID)) {
1132 neigh_del_timer(neigh);
1133 if (old & NUD_CONNECTED)
1134 neigh_suspect(neigh);
1135 neigh->nud_state = new;
1136 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001138 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1139 (new & NUD_FAILED)) {
1140 neigh_invalidate(neigh);
1141 notify = 1;
1142 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 goto out;
1144 }
1145
1146 /* Compare new lladdr with cached one */
1147 if (!dev->addr_len) {
1148 /* First case: device needs no address. */
1149 lladdr = neigh->ha;
1150 } else if (lladdr) {
1151 /* The second case: if something is already cached
1152 and a new address is proposed:
1153 - compare new & old
1154 - if they are different, check override flag
1155 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001156 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 !memcmp(lladdr, neigh->ha, dev->addr_len))
1158 lladdr = neigh->ha;
1159 } else {
1160 /* No address is supplied; if we know something,
1161 use it, otherwise discard the request.
1162 */
1163 err = -EINVAL;
1164 if (!(old & NUD_VALID))
1165 goto out;
1166 lladdr = neigh->ha;
1167 }
1168
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 /* If entry was valid and address is not changed,
1170 do not change entry state, if new one is STALE.
1171 */
1172 err = 0;
1173 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1174 if (old & NUD_VALID) {
1175 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1176 update_isrouter = 0;
1177 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1178 (old & NUD_CONNECTED)) {
1179 lladdr = neigh->ha;
1180 new = NUD_STALE;
1181 } else
1182 goto out;
1183 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001184 if (lladdr == neigh->ha && new == NUD_STALE &&
1185 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 new = old;
1187 }
1188 }
1189
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001190 /* Update timestamps only once we know we will make a change to the
1191 * neighbour entry. Otherwise we risk to move the locktime window with
1192 * noop updates and ignore relevant ARP updates.
1193 */
1194 if (new != old || lladdr != neigh->ha) {
1195 if (new & NUD_CONNECTED)
1196 neigh->confirmed = jiffies;
1197 neigh->updated = jiffies;
1198 }
1199
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 if (new != old) {
1201 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001202 if (new & NUD_PROBE)
1203 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001204 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001205 neigh_add_timer(neigh, (jiffies +
1206 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001207 neigh->parms->reachable_time :
1208 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001209 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001210 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 }
1212
1213 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001214 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001216 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 neigh_update_hhs(neigh);
1218 if (!(new & NUD_CONNECTED))
1219 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001220 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222 }
1223 if (new == old)
1224 goto out;
1225 if (new & NUD_CONNECTED)
1226 neigh_connect(neigh);
1227 else
1228 neigh_suspect(neigh);
1229 if (!(old & NUD_VALID)) {
1230 struct sk_buff *skb;
1231
1232 /* Again: avoid dead loop if something went wrong */
1233
1234 while (neigh->nud_state & NUD_VALID &&
1235 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001236 struct dst_entry *dst = skb_dst(skb);
1237 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001238 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001239
1240 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001241
1242 /* Why not just use 'neigh' as-is? The problem is that
1243 * things such as shaper, eql, and sch_teql can end up
1244 * using alternative, different, neigh objects to output
1245 * the packet in the output path. So what we need to do
1246 * here is re-lookup the top-level neigh in the path so
1247 * we can reinject the packet there.
1248 */
1249 n2 = NULL;
1250 if (dst) {
1251 n2 = dst_neigh_lookup_skb(dst, skb);
1252 if (n2)
1253 n1 = n2;
1254 }
David S. Miller8f40b162011-07-17 13:34:11 -07001255 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001256 if (n2)
1257 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001258 rcu_read_unlock();
1259
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260 write_lock_bh(&neigh->lock);
1261 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001262 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001263 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264 }
1265out:
1266 if (update_isrouter) {
1267 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1268 (neigh->flags | NTF_ROUTER) :
1269 (neigh->flags & ~NTF_ROUTER);
1270 }
1271 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001272
1273 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001274 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001275
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276 return err;
1277}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001278EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Jiri Benc7e980562013-12-11 13:48:20 +01001280/* Update the neigh to listen temporarily for probe responses, even if it is
1281 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1282 */
1283void __neigh_set_probe_once(struct neighbour *neigh)
1284{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001285 if (neigh->dead)
1286 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001287 neigh->updated = jiffies;
1288 if (!(neigh->nud_state & NUD_FAILED))
1289 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001290 neigh->nud_state = NUD_INCOMPLETE;
1291 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001292 neigh_add_timer(neigh,
1293 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1294}
1295EXPORT_SYMBOL(__neigh_set_probe_once);
1296
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1298 u8 *lladdr, void *saddr,
1299 struct net_device *dev)
1300{
1301 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1302 lladdr || !dev->addr_len);
1303 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001304 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001305 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306 return neigh;
1307}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001308EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309
Eric Dumazet34d101d2010-10-11 09:16:57 -07001310/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001311static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001313 struct net_device *dev = n->dev;
1314 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001315 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001316
1317 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001318
David S. Millerf6b72b622011-07-14 07:53:20 -07001319 /* Only one thread can come in here and initialize the
1320 * hh_cache entry.
1321 */
David S. Millerb23b5452011-07-16 17:45:02 -07001322 if (!hh->hh_len)
1323 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001324
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001325 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326}
1327
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328/* Slow and careful. */
1329
David S. Miller8f40b162011-07-17 13:34:11 -07001330int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332 int rc = 0;
1333
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334 if (!neigh_event_send(neigh, skb)) {
1335 int err;
1336 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001337 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001338
David S. Millerf6b72b622011-07-14 07:53:20 -07001339 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001340 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001341
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001342 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001343 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001344 seq = read_seqbegin(&neigh->ha_lock);
1345 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1346 neigh->ha, NULL, skb->len);
1347 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001348
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001350 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 else
1352 goto out_kfree_skb;
1353 }
1354out:
1355 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356out_kfree_skb:
1357 rc = -EINVAL;
1358 kfree_skb(skb);
1359 goto out;
1360}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001361EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001362
1363/* As fast as possible without hh cache */
1364
David S. Miller8f40b162011-07-17 13:34:11 -07001365int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001368 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001369 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001371 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001372 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001373 seq = read_seqbegin(&neigh->ha_lock);
1374 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1375 neigh->ha, NULL, skb->len);
1376 } while (read_seqretry(&neigh->ha_lock, seq));
1377
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001379 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380 else {
1381 err = -EINVAL;
1382 kfree_skb(skb);
1383 }
1384 return err;
1385}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001386EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001387
David S. Miller8f40b162011-07-17 13:34:11 -07001388int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1389{
1390 return dev_queue_xmit(skb);
1391}
1392EXPORT_SYMBOL(neigh_direct_output);
1393
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394static void neigh_proxy_process(unsigned long arg)
1395{
1396 struct neigh_table *tbl = (struct neigh_table *)arg;
1397 long sched_next = 0;
1398 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001399 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001400
1401 spin_lock(&tbl->proxy_queue.lock);
1402
David S. Millerf72051b2008-09-23 01:11:18 -07001403 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1404 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001407 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001408
David S. Millerf72051b2008-09-23 01:11:18 -07001409 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001410 if (tbl->proxy_redo && netif_running(dev)) {
1411 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001412 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001413 rcu_read_unlock();
1414 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001415 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001416 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
1418 dev_put(dev);
1419 } else if (!sched_next || tdif < sched_next)
1420 sched_next = tdif;
1421 }
1422 del_timer(&tbl->proxy_timer);
1423 if (sched_next)
1424 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1425 spin_unlock(&tbl->proxy_queue.lock);
1426}
1427
1428void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1429 struct sk_buff *skb)
1430{
1431 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001432
1433 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001434 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001436 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 kfree_skb(skb);
1438 return;
1439 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001440
1441 NEIGH_CB(skb)->sched_next = sched_next;
1442 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
1444 spin_lock(&tbl->proxy_queue.lock);
1445 if (del_timer(&tbl->proxy_timer)) {
1446 if (time_before(tbl->proxy_timer.expires, sched_next))
1447 sched_next = tbl->proxy_timer.expires;
1448 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001449 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 dev_hold(skb->dev);
1451 __skb_queue_tail(&tbl->proxy_queue, skb);
1452 mod_timer(&tbl->proxy_timer, sched_next);
1453 spin_unlock(&tbl->proxy_queue.lock);
1454}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001455EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001457static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001458 struct net *net, int ifindex)
1459{
1460 struct neigh_parms *p;
1461
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001462 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001463 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001464 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001465 return p;
1466 }
1467
1468 return NULL;
1469}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1472 struct neigh_table *tbl)
1473{
Gao fengcf89d6b2013-06-20 10:01:32 +08001474 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001475 struct net *net = dev_net(dev);
1476 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Gao fengcf89d6b2013-06-20 10:01:32 +08001478 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001481 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001483 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001484 dev_hold(dev);
1485 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001486 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001488
1489 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001490 dev_put(dev);
1491 kfree(p);
1492 return NULL;
1493 }
1494
Linus Torvalds1da177e2005-04-16 15:20:36 -07001495 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001496 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001498
1499 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 }
1501 return p;
1502}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001503EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504
1505static void neigh_rcu_free_parms(struct rcu_head *head)
1506{
1507 struct neigh_parms *parms =
1508 container_of(head, struct neigh_parms, rcu_head);
1509
1510 neigh_parms_put(parms);
1511}
1512
1513void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1514{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 if (!parms || parms == &tbl->parms)
1516 return;
1517 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001518 list_del(&parms->list);
1519 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001521 if (parms->dev)
1522 dev_put(parms->dev);
1523 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001525EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526
Denis V. Lunev06f05112008-01-24 00:30:58 -08001527static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
1529 kfree(parms);
1530}
1531
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001532static struct lock_class_key neigh_table_proxy_queue_class;
1533
WANG Congd7480fd2014-11-10 15:59:36 -08001534static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1535
1536void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537{
1538 unsigned long now = jiffies;
1539 unsigned long phsize;
1540
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001541 INIT_LIST_HEAD(&tbl->parms_list);
1542 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001543 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001544 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001546 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 tbl->stats = alloc_percpu(struct neigh_statistics);
1549 if (!tbl->stats)
1550 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001551
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001553 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1554 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556#endif
1557
David S. Millercd089332011-07-11 01:28:12 -07001558 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559
1560 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001561 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001562
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001563 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 panic("cannot allocate neighbour cache hashes");
1565
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001566 if (!tbl->entry_size)
1567 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1568 tbl->key_len, NEIGH_PRIV_ALIGN);
1569 else
1570 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1571
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001573 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301574 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1575 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001576 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001577 skb_queue_head_init_class(&tbl->proxy_queue,
1578 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
1580 tbl->last_flush = now;
1581 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001582
WANG Congd7480fd2014-11-10 15:59:36 -08001583 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001585EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
WANG Congd7480fd2014-11-10 15:59:36 -08001587int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588{
WANG Congd7480fd2014-11-10 15:59:36 -08001589 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001591 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 del_timer_sync(&tbl->proxy_timer);
1593 pneigh_queue_purge(&tbl->proxy_queue);
1594 neigh_ifdown(tbl, NULL);
1595 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001596 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001598 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1599 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001600 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601
1602 kfree(tbl->phash_buckets);
1603 tbl->phash_buckets = NULL;
1604
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001605 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1606
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001607 free_percpu(tbl->stats);
1608 tbl->stats = NULL;
1609
Linus Torvalds1da177e2005-04-16 15:20:36 -07001610 return 0;
1611}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001612EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
WANG Congd7480fd2014-11-10 15:59:36 -08001614static struct neigh_table *neigh_find_table(int family)
1615{
1616 struct neigh_table *tbl = NULL;
1617
1618 switch (family) {
1619 case AF_INET:
1620 tbl = neigh_tables[NEIGH_ARP_TABLE];
1621 break;
1622 case AF_INET6:
1623 tbl = neigh_tables[NEIGH_ND_TABLE];
1624 break;
1625 case AF_DECnet:
1626 tbl = neigh_tables[NEIGH_DN_TABLE];
1627 break;
1628 }
1629
1630 return tbl;
1631}
1632
David Ahernc21ef3e2017-04-16 09:48:24 -07001633static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1634 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001636 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001637 struct ndmsg *ndm;
1638 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001640 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001641 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001642 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643
Eric Dumazet110b2492010-10-04 04:27:36 +00001644 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001645 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646 goto out;
1647
Thomas Grafa14a49d2006-08-07 17:53:08 -07001648 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1649 if (dst_attr == NULL)
1650 goto out;
1651
1652 ndm = nlmsg_data(nlh);
1653 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001654 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001655 if (dev == NULL) {
1656 err = -ENODEV;
1657 goto out;
1658 }
1659 }
1660
WANG Congd7480fd2014-11-10 15:59:36 -08001661 tbl = neigh_find_table(ndm->ndm_family);
1662 if (tbl == NULL)
1663 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
WANG Congd7480fd2014-11-10 15:59:36 -08001665 if (nla_len(dst_attr) < tbl->key_len)
1666 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667
WANG Congd7480fd2014-11-10 15:59:36 -08001668 if (ndm->ndm_flags & NTF_PROXY) {
1669 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001670 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 }
WANG Congd7480fd2014-11-10 15:59:36 -08001672
1673 if (dev == NULL)
1674 goto out;
1675
1676 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1677 if (neigh == NULL) {
1678 err = -ENOENT;
1679 goto out;
1680 }
1681
1682 err = neigh_update(neigh, NULL, NUD_FAILED,
1683 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001684 NEIGH_UPDATE_F_ADMIN,
1685 NETLINK_CB(skb).portid);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001686 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001687 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001688 neigh_remove_one(neigh, tbl);
1689 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691out:
1692 return err;
1693}
1694
David Ahernc21ef3e2017-04-16 09:48:24 -07001695static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1696 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697{
WANG Congd7480fd2014-11-10 15:59:36 -08001698 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001699 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001700 struct ndmsg *ndm;
1701 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001702 struct neigh_table *tbl;
1703 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001704 struct neighbour *neigh;
1705 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001706 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
Eric Dumazet110b2492010-10-04 04:27:36 +00001708 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001709 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001710 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 goto out;
1712
Thomas Graf5208deb2006-08-07 17:55:40 -07001713 err = -EINVAL;
1714 if (tb[NDA_DST] == NULL)
1715 goto out;
1716
1717 ndm = nlmsg_data(nlh);
1718 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001719 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001720 if (dev == NULL) {
1721 err = -ENODEV;
1722 goto out;
1723 }
1724
1725 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001726 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001727 }
1728
WANG Congd7480fd2014-11-10 15:59:36 -08001729 tbl = neigh_find_table(ndm->ndm_family);
1730 if (tbl == NULL)
1731 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
WANG Congd7480fd2014-11-10 15:59:36 -08001733 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1734 goto out;
1735 dst = nla_data(tb[NDA_DST]);
1736 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737
WANG Congd7480fd2014-11-10 15:59:36 -08001738 if (ndm->ndm_flags & NTF_PROXY) {
1739 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
WANG Congd7480fd2014-11-10 15:59:36 -08001741 err = -ENOBUFS;
1742 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1743 if (pn) {
1744 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001745 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001746 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001747 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 }
1749
WANG Congd7480fd2014-11-10 15:59:36 -08001750 if (dev == NULL)
1751 goto out;
1752
1753 neigh = neigh_lookup(tbl, dst, dev);
1754 if (neigh == NULL) {
1755 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1756 err = -ENOENT;
1757 goto out;
1758 }
1759
1760 neigh = __neigh_lookup_errno(tbl, dst, dev);
1761 if (IS_ERR(neigh)) {
1762 err = PTR_ERR(neigh);
1763 goto out;
1764 }
1765 } else {
1766 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1767 err = -EEXIST;
1768 neigh_release(neigh);
1769 goto out;
1770 }
1771
1772 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1773 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1774 }
1775
1776 if (ndm->ndm_flags & NTF_USE) {
1777 neigh_event_send(neigh, NULL);
1778 err = 0;
1779 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001780 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1781 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001782 neigh_release(neigh);
1783
Linus Torvalds1da177e2005-04-16 15:20:36 -07001784out:
1785 return err;
1786}
1787
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001788static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1789{
Thomas Grafca860fb2006-08-07 18:00:18 -07001790 struct nlattr *nest;
1791
1792 nest = nla_nest_start(skb, NDTA_PARMS);
1793 if (nest == NULL)
1794 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001795
David S. Miller9a6308d2012-04-01 20:06:28 -04001796 if ((parms->dev &&
1797 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001798 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001799 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1800 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001801 /* approximative value for deprecated QUEUE_LEN (in packets) */
1802 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001803 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1804 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1805 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1806 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1807 NEIGH_VAR(parms, UCAST_PROBES)) ||
1808 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1809 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001810 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1811 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001812 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1813 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001814 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001815 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001816 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001817 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001818 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001819 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001820 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001821 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001822 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001823 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001824 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001825 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001826 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001827 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001828 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001829 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001830
Thomas Grafca860fb2006-08-07 18:00:18 -07001831nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001832 nla_nest_cancel(skb, nest);
1833 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001834}
1835
Thomas Grafca860fb2006-08-07 18:00:18 -07001836static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1837 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001838{
1839 struct nlmsghdr *nlh;
1840 struct ndtmsg *ndtmsg;
1841
Thomas Grafca860fb2006-08-07 18:00:18 -07001842 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1843 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001844 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001845
Thomas Grafca860fb2006-08-07 18:00:18 -07001846 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001847
1848 read_lock_bh(&tbl->lock);
1849 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001850 ndtmsg->ndtm_pad1 = 0;
1851 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852
David S. Miller9a6308d2012-04-01 20:06:28 -04001853 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001854 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001855 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1856 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1857 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1858 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001859 {
1860 unsigned long now = jiffies;
1861 unsigned int flush_delta = now - tbl->last_flush;
1862 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001863 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001864 struct ndt_config ndc = {
1865 .ndtc_key_len = tbl->key_len,
1866 .ndtc_entry_size = tbl->entry_size,
1867 .ndtc_entries = atomic_read(&tbl->entries),
1868 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1869 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001870 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1871 };
1872
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001873 rcu_read_lock_bh();
1874 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001875 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001876 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001877 rcu_read_unlock_bh();
1878
David S. Miller9a6308d2012-04-01 20:06:28 -04001879 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1880 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881 }
1882
1883 {
1884 int cpu;
1885 struct ndt_stats ndst;
1886
1887 memset(&ndst, 0, sizeof(ndst));
1888
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001889 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001890 struct neigh_statistics *st;
1891
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001892 st = per_cpu_ptr(tbl->stats, cpu);
1893 ndst.ndts_allocs += st->allocs;
1894 ndst.ndts_destroys += st->destroys;
1895 ndst.ndts_hash_grows += st->hash_grows;
1896 ndst.ndts_res_failed += st->res_failed;
1897 ndst.ndts_lookups += st->lookups;
1898 ndst.ndts_hits += st->hits;
1899 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1900 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1901 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1902 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001903 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001904 }
1905
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001906 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1907 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001908 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001909 }
1910
1911 BUG_ON(tbl->parms.dev);
1912 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001913 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001914
1915 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001916 nlmsg_end(skb, nlh);
1917 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001918
Thomas Grafca860fb2006-08-07 18:00:18 -07001919nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001920 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001921 nlmsg_cancel(skb, nlh);
1922 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001923}
1924
Thomas Grafca860fb2006-08-07 18:00:18 -07001925static int neightbl_fill_param_info(struct sk_buff *skb,
1926 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001927 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001928 u32 pid, u32 seq, int type,
1929 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930{
1931 struct ndtmsg *ndtmsg;
1932 struct nlmsghdr *nlh;
1933
Thomas Grafca860fb2006-08-07 18:00:18 -07001934 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1935 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001936 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937
Thomas Grafca860fb2006-08-07 18:00:18 -07001938 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001939
1940 read_lock_bh(&tbl->lock);
1941 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001942 ndtmsg->ndtm_pad1 = 0;
1943 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001944
Thomas Grafca860fb2006-08-07 18:00:18 -07001945 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1946 neightbl_fill_parms(skb, parms) < 0)
1947 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001948
1949 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001950 nlmsg_end(skb, nlh);
1951 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001952errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001953 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001954 nlmsg_cancel(skb, nlh);
1955 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001956}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001957
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001958static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001959 [NDTA_NAME] = { .type = NLA_STRING },
1960 [NDTA_THRESH1] = { .type = NLA_U32 },
1961 [NDTA_THRESH2] = { .type = NLA_U32 },
1962 [NDTA_THRESH3] = { .type = NLA_U32 },
1963 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1964 [NDTA_PARMS] = { .type = NLA_NESTED },
1965};
1966
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001967static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001968 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1969 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1970 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1971 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1972 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1973 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001974 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001975 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1976 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1977 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1978 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1979 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1980 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1981 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1982};
1983
David Ahernc21ef3e2017-04-16 09:48:24 -07001984static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
1985 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001987 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001989 struct ndtmsg *ndtmsg;
1990 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001991 bool found = false;
1992 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001993
Thomas Graf6b3f8672006-08-07 17:58:53 -07001994 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07001995 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001996 if (err < 0)
1997 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001998
Thomas Graf6b3f8672006-08-07 17:58:53 -07001999 if (tb[NDTA_NAME] == NULL) {
2000 err = -EINVAL;
2001 goto errout;
2002 }
2003
2004 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002005
2006 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2007 tbl = neigh_tables[tidx];
2008 if (!tbl)
2009 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2011 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002012 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2013 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002014 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002015 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002016 }
2017
WANG Congd7480fd2014-11-10 15:59:36 -08002018 if (!found)
2019 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002020
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002021 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002022 * We acquire tbl->lock to be nice to the periodic timers and
2023 * make sure they always see a consistent set of values.
2024 */
2025 write_lock_bh(&tbl->lock);
2026
Thomas Graf6b3f8672006-08-07 17:58:53 -07002027 if (tb[NDTA_PARMS]) {
2028 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002029 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002030 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002031
Thomas Graf6b3f8672006-08-07 17:58:53 -07002032 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002033 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002034 if (err < 0)
2035 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002036
Thomas Graf6b3f8672006-08-07 17:58:53 -07002037 if (tbp[NDTPA_IFINDEX])
2038 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002039
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002040 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002041 if (p == NULL) {
2042 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002044 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002045
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 for (i = 1; i <= NDTPA_MAX; i++) {
2047 if (tbp[i] == NULL)
2048 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002049
Thomas Graf6b3f8672006-08-07 17:58:53 -07002050 switch (i) {
2051 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002052 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2053 nla_get_u32(tbp[i]) *
2054 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002055 break;
2056 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002057 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2058 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 break;
2060 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002061 NEIGH_VAR_SET(p, PROXY_QLEN,
2062 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 break;
2064 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002065 NEIGH_VAR_SET(p, APP_PROBES,
2066 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067 break;
2068 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002069 NEIGH_VAR_SET(p, UCAST_PROBES,
2070 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002071 break;
2072 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002073 NEIGH_VAR_SET(p, MCAST_PROBES,
2074 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002075 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002076 case NDTPA_MCAST_REPROBES:
2077 NEIGH_VAR_SET(p, MCAST_REPROBES,
2078 nla_get_u32(tbp[i]));
2079 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002080 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002081 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2082 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002083 /* update reachable_time as well, otherwise, the change will
2084 * only be effective after the next time neigh_periodic_work
2085 * decides to recompute it (can be multiple minutes)
2086 */
2087 p->reachable_time =
2088 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002089 break;
2090 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002091 NEIGH_VAR_SET(p, GC_STALETIME,
2092 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002093 break;
2094 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002095 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2096 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002097 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002098 break;
2099 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002100 NEIGH_VAR_SET(p, RETRANS_TIME,
2101 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002102 break;
2103 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002104 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2105 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002106 break;
2107 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002108 NEIGH_VAR_SET(p, PROXY_DELAY,
2109 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002110 break;
2111 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002112 NEIGH_VAR_SET(p, LOCKTIME,
2113 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002114 break;
2115 }
2116 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002117 }
2118
Gao fengdc25c672013-06-20 10:01:34 +08002119 err = -ENOENT;
2120 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2121 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2122 !net_eq(net, &init_net))
2123 goto errout_tbl_lock;
2124
Thomas Graf6b3f8672006-08-07 17:58:53 -07002125 if (tb[NDTA_THRESH1])
2126 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2127
2128 if (tb[NDTA_THRESH2])
2129 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2130
2131 if (tb[NDTA_THRESH3])
2132 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2133
2134 if (tb[NDTA_GC_INTERVAL])
2135 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2136
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002137 err = 0;
2138
Thomas Graf6b3f8672006-08-07 17:58:53 -07002139errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002140 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002141errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002142 return err;
2143}
2144
Thomas Grafc8822a42007-03-22 11:50:06 -07002145static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002147 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002148 int family, tidx, nidx = 0;
2149 int tbl_skip = cb->args[0];
2150 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002151 struct neigh_table *tbl;
2152
Thomas Grafca860fb2006-08-07 18:00:18 -07002153 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002154
WANG Congd7480fd2014-11-10 15:59:36 -08002155 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002156 struct neigh_parms *p;
2157
WANG Congd7480fd2014-11-10 15:59:36 -08002158 tbl = neigh_tables[tidx];
2159 if (!tbl)
2160 continue;
2161
Thomas Grafca860fb2006-08-07 18:00:18 -07002162 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002163 continue;
2164
Eric W. Biederman15e47302012-09-07 20:12:54 +00002165 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002166 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002167 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002168 break;
2169
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002170 nidx = 0;
2171 p = list_next_entry(&tbl->parms, list);
2172 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002173 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002174 continue;
2175
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002176 if (nidx < neigh_skip)
2177 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002178
Thomas Grafca860fb2006-08-07 18:00:18 -07002179 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002180 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002181 cb->nlh->nlmsg_seq,
2182 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002183 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002184 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002185 next:
2186 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002187 }
2188
Thomas Grafca860fb2006-08-07 18:00:18 -07002189 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002190 }
2191out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002192 cb->args[0] = tidx;
2193 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002194
2195 return skb->len;
2196}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197
Thomas Graf8b8aec52006-08-07 17:56:37 -07002198static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2199 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200{
2201 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002202 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002203 struct nlmsghdr *nlh;
2204 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205
Thomas Graf8b8aec52006-08-07 17:56:37 -07002206 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2207 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002208 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002209
2210 ndm = nlmsg_data(nlh);
2211 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002212 ndm->ndm_pad1 = 0;
2213 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002214 ndm->ndm_flags = neigh->flags;
2215 ndm->ndm_type = neigh->type;
2216 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002217
David S. Miller9a6308d2012-04-01 20:06:28 -04002218 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2219 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002220
2221 read_lock_bh(&neigh->lock);
2222 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002223 if (neigh->nud_state & NUD_VALID) {
2224 char haddr[MAX_ADDR_LEN];
2225
2226 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2227 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2228 read_unlock_bh(&neigh->lock);
2229 goto nla_put_failure;
2230 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002231 }
2232
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002233 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2234 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2235 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002236 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002237 read_unlock_bh(&neigh->lock);
2238
David S. Miller9a6308d2012-04-01 20:06:28 -04002239 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2240 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2241 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002242
Johannes Berg053c0952015-01-16 22:09:00 +01002243 nlmsg_end(skb, nlh);
2244 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002245
2246nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002247 nlmsg_cancel(skb, nlh);
2248 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002249}
2250
Tony Zelenoff84920c12012-01-26 22:28:58 +00002251static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2252 u32 pid, u32 seq, int type, unsigned int flags,
2253 struct neigh_table *tbl)
2254{
2255 struct nlmsghdr *nlh;
2256 struct ndmsg *ndm;
2257
2258 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2259 if (nlh == NULL)
2260 return -EMSGSIZE;
2261
2262 ndm = nlmsg_data(nlh);
2263 ndm->ndm_family = tbl->family;
2264 ndm->ndm_pad1 = 0;
2265 ndm->ndm_pad2 = 0;
2266 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002267 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002268 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002269 ndm->ndm_state = NUD_NONE;
2270
David S. Miller9a6308d2012-04-01 20:06:28 -04002271 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2272 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002273
Johannes Berg053c0952015-01-16 22:09:00 +01002274 nlmsg_end(skb, nlh);
2275 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002276
2277nla_put_failure:
2278 nlmsg_cancel(skb, nlh);
2279 return -EMSGSIZE;
2280}
2281
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002282static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002283{
2284 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002285 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002286}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002287
David Ahern21fdd092015-09-29 09:32:03 -07002288static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2289{
2290 struct net_device *master;
2291
2292 if (!master_idx)
2293 return false;
2294
2295 master = netdev_master_upper_dev_get(dev);
2296 if (!master || master->ifindex != master_idx)
2297 return true;
2298
2299 return false;
2300}
2301
David Ahern16660f02015-10-03 11:43:46 -07002302static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2303{
2304 if (filter_idx && dev->ifindex != filter_idx)
2305 return true;
2306
2307 return false;
2308}
2309
Linus Torvalds1da177e2005-04-16 15:20:36 -07002310static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2311 struct netlink_callback *cb)
2312{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002313 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002314 const struct nlmsghdr *nlh = cb->nlh;
2315 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 struct neighbour *n;
2317 int rc, h, s_h = cb->args[1];
2318 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002319 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002320 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002321 unsigned int flags = NLM_F_MULTI;
2322 int err;
2323
Johannes Bergfceb6432017-04-12 14:34:07 +02002324 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002325 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002326 if (tb[NDA_IFINDEX])
2327 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2328
David Ahern21fdd092015-09-29 09:32:03 -07002329 if (tb[NDA_MASTER])
2330 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2331
David Ahern16660f02015-10-03 11:43:46 -07002332 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002333 flags |= NLM_F_DUMP_FILTERED;
2334 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002335
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002336 rcu_read_lock_bh();
2337 nht = rcu_dereference_bh(tbl->nht);
2338
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002339 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 if (h > s_h)
2341 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002342 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2343 n != NULL;
2344 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002345 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2346 goto next;
2347 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2348 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002349 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002350 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002352 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002353 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 rc = -1;
2355 goto out;
2356 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002357next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002358 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002359 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002360 }
2361 rc = skb->len;
2362out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002363 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364 cb->args[1] = h;
2365 cb->args[2] = idx;
2366 return rc;
2367}
2368
Tony Zelenoff84920c12012-01-26 22:28:58 +00002369static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2370 struct netlink_callback *cb)
2371{
2372 struct pneigh_entry *n;
2373 struct net *net = sock_net(skb->sk);
2374 int rc, h, s_h = cb->args[3];
2375 int idx, s_idx = idx = cb->args[4];
2376
2377 read_lock_bh(&tbl->lock);
2378
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002379 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002380 if (h > s_h)
2381 s_idx = 0;
2382 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002383 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002384 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002385 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002386 cb->nlh->nlmsg_seq,
2387 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002388 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002389 read_unlock_bh(&tbl->lock);
2390 rc = -1;
2391 goto out;
2392 }
2393 next:
2394 idx++;
2395 }
2396 }
2397
2398 read_unlock_bh(&tbl->lock);
2399 rc = skb->len;
2400out:
2401 cb->args[3] = h;
2402 cb->args[4] = idx;
2403 return rc;
2404
2405}
2406
Thomas Grafc8822a42007-03-22 11:50:06 -07002407static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408{
2409 struct neigh_table *tbl;
2410 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002411 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002412 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002413
Thomas Graf8b8aec52006-08-07 17:56:37 -07002414 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002415
2416 /* check for full ndmsg structure presence, family member is
2417 * the same for both structures
2418 */
2419 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2420 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2421 proxy = 1;
2422
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 s_t = cb->args[0];
2424
WANG Congd7480fd2014-11-10 15:59:36 -08002425 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2426 tbl = neigh_tables[t];
2427
2428 if (!tbl)
2429 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 if (t < s_t || (family && tbl->family != family))
2431 continue;
2432 if (t > s_t)
2433 memset(&cb->args[1], 0, sizeof(cb->args) -
2434 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002435 if (proxy)
2436 err = pneigh_dump_table(tbl, skb, cb);
2437 else
2438 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002439 if (err < 0)
2440 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
2443 cb->args[0] = t;
2444 return skb->len;
2445}
2446
2447void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2448{
2449 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002450 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002452 rcu_read_lock_bh();
2453 nht = rcu_dereference_bh(tbl->nht);
2454
Eric Dumazet767e97e2010-10-06 17:49:21 -07002455 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002456 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 struct neighbour *n;
2458
Eric Dumazet767e97e2010-10-06 17:49:21 -07002459 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2460 n != NULL;
2461 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 cb(n, cookie);
2463 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002464 read_unlock(&tbl->lock);
2465 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466}
2467EXPORT_SYMBOL(neigh_for_each);
2468
2469/* The tbl->lock must be held as a writer and BH disabled. */
2470void __neigh_for_each_release(struct neigh_table *tbl,
2471 int (*cb)(struct neighbour *))
2472{
2473 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002474 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002476 nht = rcu_dereference_protected(tbl->nht,
2477 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002478 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002479 struct neighbour *n;
2480 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002482 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002483 while ((n = rcu_dereference_protected(*np,
2484 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485 int release;
2486
2487 write_lock(&n->lock);
2488 release = cb(n);
2489 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002490 rcu_assign_pointer(*np,
2491 rcu_dereference_protected(n->next,
2492 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002493 n->dead = 1;
2494 } else
2495 np = &n->next;
2496 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002497 if (release)
2498 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 }
2500 }
2501}
2502EXPORT_SYMBOL(__neigh_for_each_release);
2503
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002504int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002505 const void *addr, struct sk_buff *skb)
2506{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002507 int err = -EAFNOSUPPORT;
2508 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002509 struct neigh_table *tbl;
2510 struct neighbour *neigh;
2511
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002512 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002513 if (!tbl)
2514 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002515 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002516 neigh = __neigh_lookup_noref(tbl, addr, dev);
2517 if (!neigh)
2518 neigh = __neigh_create(tbl, addr, dev, false);
2519 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002520 if (IS_ERR(neigh)) {
2521 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002522 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002523 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002524 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002525 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002526 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002527 else if (index == NEIGH_LINK_TABLE) {
2528 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2529 addr, NULL, skb->len);
2530 if (err < 0)
2531 goto out_kfree_skb;
2532 err = dev_queue_xmit(skb);
2533 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002534out:
2535 return err;
2536out_kfree_skb:
2537 kfree_skb(skb);
2538 goto out;
2539}
2540EXPORT_SYMBOL(neigh_xmit);
2541
Linus Torvalds1da177e2005-04-16 15:20:36 -07002542#ifdef CONFIG_PROC_FS
2543
2544static struct neighbour *neigh_get_first(struct seq_file *seq)
2545{
2546 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002547 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002548 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549 struct neighbour *n = NULL;
2550 int bucket = state->bucket;
2551
2552 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002553 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002554 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555
2556 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002557 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002558 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559 if (state->neigh_sub_iter) {
2560 loff_t fakep = 0;
2561 void *v;
2562
2563 v = state->neigh_sub_iter(state, n, &fakep);
2564 if (!v)
2565 goto next;
2566 }
2567 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2568 break;
2569 if (n->nud_state & ~NUD_NOARP)
2570 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002571next:
2572 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002573 }
2574
2575 if (n)
2576 break;
2577 }
2578 state->bucket = bucket;
2579
2580 return n;
2581}
2582
2583static struct neighbour *neigh_get_next(struct seq_file *seq,
2584 struct neighbour *n,
2585 loff_t *pos)
2586{
2587 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002588 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002589 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002590
2591 if (state->neigh_sub_iter) {
2592 void *v = state->neigh_sub_iter(state, n, pos);
2593 if (v)
2594 return n;
2595 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002596 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597
2598 while (1) {
2599 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002600 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002601 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602 if (state->neigh_sub_iter) {
2603 void *v = state->neigh_sub_iter(state, n, pos);
2604 if (v)
2605 return n;
2606 goto next;
2607 }
2608 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2609 break;
2610
2611 if (n->nud_state & ~NUD_NOARP)
2612 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002613next:
2614 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615 }
2616
2617 if (n)
2618 break;
2619
David S. Millercd089332011-07-11 01:28:12 -07002620 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 break;
2622
Eric Dumazet767e97e2010-10-06 17:49:21 -07002623 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002624 }
2625
2626 if (n && pos)
2627 --(*pos);
2628 return n;
2629}
2630
2631static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2632{
2633 struct neighbour *n = neigh_get_first(seq);
2634
2635 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002636 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002637 while (*pos) {
2638 n = neigh_get_next(seq, n, pos);
2639 if (!n)
2640 break;
2641 }
2642 }
2643 return *pos ? NULL : n;
2644}
2645
2646static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2647{
2648 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002649 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 struct neigh_table *tbl = state->tbl;
2651 struct pneigh_entry *pn = NULL;
2652 int bucket = state->bucket;
2653
2654 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2655 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2656 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002657 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002658 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002659 if (pn)
2660 break;
2661 }
2662 state->bucket = bucket;
2663
2664 return pn;
2665}
2666
2667static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2668 struct pneigh_entry *pn,
2669 loff_t *pos)
2670{
2671 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002672 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 struct neigh_table *tbl = state->tbl;
2674
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002675 do {
2676 pn = pn->next;
2677 } while (pn && !net_eq(pneigh_net(pn), net));
2678
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 while (!pn) {
2680 if (++state->bucket > PNEIGH_HASHMASK)
2681 break;
2682 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002683 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002684 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685 if (pn)
2686 break;
2687 }
2688
2689 if (pn && pos)
2690 --(*pos);
2691
2692 return pn;
2693}
2694
2695static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2696{
2697 struct pneigh_entry *pn = pneigh_get_first(seq);
2698
2699 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002700 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002701 while (*pos) {
2702 pn = pneigh_get_next(seq, pn, pos);
2703 if (!pn)
2704 break;
2705 }
2706 }
2707 return *pos ? NULL : pn;
2708}
2709
2710static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2711{
2712 struct neigh_seq_state *state = seq->private;
2713 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002714 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715
Chris Larson745e2032008-08-03 01:10:55 -07002716 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002717 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002718 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002719
2720 return rc;
2721}
2722
2723void *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 +00002724 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725{
2726 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727
2728 state->tbl = tbl;
2729 state->bucket = 0;
2730 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2731
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002732 rcu_read_lock_bh();
2733 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002734
Chris Larson745e2032008-08-03 01:10:55 -07002735 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002736}
2737EXPORT_SYMBOL(neigh_seq_start);
2738
2739void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2740{
2741 struct neigh_seq_state *state;
2742 void *rc;
2743
2744 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002745 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002746 goto out;
2747 }
2748
2749 state = seq->private;
2750 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2751 rc = neigh_get_next(seq, v, NULL);
2752 if (rc)
2753 goto out;
2754 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2755 rc = pneigh_get_first(seq);
2756 } else {
2757 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2758 rc = pneigh_get_next(seq, v, NULL);
2759 }
2760out:
2761 ++(*pos);
2762 return rc;
2763}
2764EXPORT_SYMBOL(neigh_seq_next);
2765
2766void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002767 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002769 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002770}
2771EXPORT_SYMBOL(neigh_seq_stop);
2772
2773/* statistics via seq_file */
2774
2775static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2776{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002777 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002778 int cpu;
2779
2780 if (*pos == 0)
2781 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002782
Rusty Russell0f23174a2008-12-29 12:23:42 +00002783 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002784 if (!cpu_possible(cpu))
2785 continue;
2786 *pos = cpu+1;
2787 return per_cpu_ptr(tbl->stats, cpu);
2788 }
2789 return NULL;
2790}
2791
2792static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2793{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002794 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795 int cpu;
2796
Rusty Russell0f23174a2008-12-29 12:23:42 +00002797 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 if (!cpu_possible(cpu))
2799 continue;
2800 *pos = cpu+1;
2801 return per_cpu_ptr(tbl->stats, cpu);
2802 }
2803 return NULL;
2804}
2805
2806static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2807{
2808
2809}
2810
2811static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2812{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002813 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002814 struct neigh_statistics *st = v;
2815
2816 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002817 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 -07002818 return 0;
2819 }
2820
2821 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002822 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 atomic_read(&tbl->entries),
2824
2825 st->allocs,
2826 st->destroys,
2827 st->hash_grows,
2828
2829 st->lookups,
2830 st->hits,
2831
2832 st->res_failed,
2833
2834 st->rcv_probes_mcast,
2835 st->rcv_probes_ucast,
2836
2837 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002838 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002839 st->unres_discards,
2840 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002841 );
2842
2843 return 0;
2844}
2845
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002846static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 .start = neigh_stat_seq_start,
2848 .next = neigh_stat_seq_next,
2849 .stop = neigh_stat_seq_stop,
2850 .show = neigh_stat_seq_show,
2851};
2852
2853static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2854{
2855 int ret = seq_open(file, &neigh_stat_seq_ops);
2856
2857 if (!ret) {
2858 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002859 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002860 }
2861 return ret;
2862};
2863
Arjan van de Ven9a321442007-02-12 00:55:35 -08002864static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002865 .owner = THIS_MODULE,
2866 .open = neigh_stat_seq_open,
2867 .read = seq_read,
2868 .llseek = seq_lseek,
2869 .release = seq_release,
2870};
2871
2872#endif /* CONFIG_PROC_FS */
2873
Thomas Graf339bf982006-11-10 14:10:15 -08002874static inline size_t neigh_nlmsg_size(void)
2875{
2876 return NLMSG_ALIGN(sizeof(struct ndmsg))
2877 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2878 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2879 + nla_total_size(sizeof(struct nda_cacheinfo))
2880 + nla_total_size(4); /* NDA_PROBES */
2881}
2882
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002883static void __neigh_notify(struct neighbour *n, int type, int flags,
2884 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002885{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002886 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002887 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002888 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002889
Thomas Graf339bf982006-11-10 14:10:15 -08002890 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002891 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002892 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002893
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002894 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002895 if (err < 0) {
2896 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2897 WARN_ON(err == -EMSGSIZE);
2898 kfree_skb(skb);
2899 goto errout;
2900 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002901 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2902 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002903errout:
2904 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002905 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002906}
2907
2908void neigh_app_ns(struct neighbour *n)
2909{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002910 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002911}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002912EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002913
2914#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002915static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002916static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002917static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918
Joe Perchesfe2c6332013-06-11 23:04:25 -07002919static int proc_unres_qlen(struct ctl_table *ctl, int write,
2920 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002921{
2922 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002923 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002924
Shan Weice46cc62012-12-04 18:49:15 +00002925 tmp.extra1 = &zero;
2926 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002927 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002928
2929 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2930 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2931
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002932 if (write && !ret)
2933 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2934 return ret;
2935}
2936
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002937static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2938 int family)
2939{
Jiri Pirkobba24892013-12-07 19:26:57 +01002940 switch (family) {
2941 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002942 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002943 case AF_INET6:
2944 return __in6_dev_nd_parms_get_rcu(dev);
2945 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002946 return NULL;
2947}
2948
2949static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2950 int index)
2951{
2952 struct net_device *dev;
2953 int family = neigh_parms_family(p);
2954
2955 rcu_read_lock();
2956 for_each_netdev_rcu(net, dev) {
2957 struct neigh_parms *dst_p =
2958 neigh_get_dev_parms_rcu(dev, family);
2959
2960 if (dst_p && !test_bit(index, dst_p->data_state))
2961 dst_p->data[index] = p->data[index];
2962 }
2963 rcu_read_unlock();
2964}
2965
2966static void neigh_proc_update(struct ctl_table *ctl, int write)
2967{
2968 struct net_device *dev = ctl->extra1;
2969 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002970 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002971 int index = (int *) ctl->data - p->data;
2972
2973 if (!write)
2974 return;
2975
2976 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002977 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2978 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002979 if (!dev) /* NULL dev means this is default value */
2980 neigh_copy_dflt_parms(net, p, index);
2981}
2982
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002983static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2984 void __user *buffer,
2985 size_t *lenp, loff_t *ppos)
2986{
2987 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002988 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002989
2990 tmp.extra1 = &zero;
2991 tmp.extra2 = &int_max;
2992
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002993 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2994 neigh_proc_update(ctl, write);
2995 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002996}
2997
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002998int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2999 void __user *buffer, size_t *lenp, loff_t *ppos)
3000{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003001 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3002
3003 neigh_proc_update(ctl, write);
3004 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003005}
3006EXPORT_SYMBOL(neigh_proc_dointvec);
3007
3008int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3009 void __user *buffer,
3010 size_t *lenp, loff_t *ppos)
3011{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003012 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3013
3014 neigh_proc_update(ctl, write);
3015 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003016}
3017EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3018
3019static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3020 void __user *buffer,
3021 size_t *lenp, loff_t *ppos)
3022{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003023 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3024
3025 neigh_proc_update(ctl, write);
3026 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003027}
3028
3029int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3030 void __user *buffer,
3031 size_t *lenp, loff_t *ppos)
3032{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003033 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3034
3035 neigh_proc_update(ctl, write);
3036 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003037}
3038EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3039
3040static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3041 void __user *buffer,
3042 size_t *lenp, loff_t *ppos)
3043{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003044 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3045
3046 neigh_proc_update(ctl, write);
3047 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003048}
3049
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003050static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3051 void __user *buffer,
3052 size_t *lenp, loff_t *ppos)
3053{
3054 struct neigh_parms *p = ctl->extra2;
3055 int ret;
3056
3057 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3058 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3059 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3060 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3061 else
3062 ret = -1;
3063
3064 if (write && ret == 0) {
3065 /* update reachable_time as well, otherwise, the change will
3066 * only be effective after the next time neigh_periodic_work
3067 * decides to recompute it
3068 */
3069 p->reachable_time =
3070 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3071 }
3072 return ret;
3073}
3074
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003075#define NEIGH_PARMS_DATA_OFFSET(index) \
3076 (&((struct neigh_parms *) 0)->data[index])
3077
3078#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3079 [NEIGH_VAR_ ## attr] = { \
3080 .procname = name, \
3081 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3082 .maxlen = sizeof(int), \
3083 .mode = mval, \
3084 .proc_handler = proc, \
3085 }
3086
3087#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3088 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3089
3090#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003091 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003092
3093#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003094 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003095
3096#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003097 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003098
3099#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003100 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003101
3102#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003103 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003104
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105static struct neigh_sysctl_table {
3106 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003107 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003108} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003110 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3111 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3112 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003113 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003114 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3115 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3116 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3117 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3118 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3119 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3120 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3121 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3122 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3123 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3124 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3125 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003126 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 .procname = "gc_interval",
3128 .maxlen = sizeof(int),
3129 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003130 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003132 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 .procname = "gc_thresh1",
3134 .maxlen = sizeof(int),
3135 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003136 .extra1 = &zero,
3137 .extra2 = &int_max,
3138 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003139 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003140 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 .procname = "gc_thresh2",
3142 .maxlen = sizeof(int),
3143 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003144 .extra1 = &zero,
3145 .extra2 = &int_max,
3146 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003148 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149 .procname = "gc_thresh3",
3150 .maxlen = sizeof(int),
3151 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003152 .extra1 = &zero,
3153 .extra2 = &int_max,
3154 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003156 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 },
3158};
3159
3160int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003161 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003163 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003164 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003165 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003166 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003167 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003168
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003169 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003171 goto err;
3172
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003173 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003174 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003175 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003176 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003177 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
3179 if (dev) {
3180 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003181 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003182 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3183 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003185 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003186 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003187 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3188 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3189 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3190 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 }
3192
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003193 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003195 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003197 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003199 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003201 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003202 } else {
3203 /* Those handlers will update p->reachable_time after
3204 * base_reachable_time(_ms) is set to ensure the new timer starts being
3205 * applied after the next neighbour update instead of waiting for
3206 * neigh_periodic_work to update its value (can be multiple minutes)
3207 * So any handler that replaces them should do this as well
3208 */
3209 /* ReachableTime */
3210 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3211 neigh_proc_base_reachable_time;
3212 /* ReachableTime (in milliseconds) */
3213 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3214 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215 }
3216
Eric W. Biederman464dc802012-11-16 03:02:59 +00003217 /* Don't export sysctls to unprivileged users */
3218 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3219 t->neigh_vars[0].procname = NULL;
3220
Jiri Pirko73af6142013-12-07 19:26:55 +01003221 switch (neigh_parms_family(p)) {
3222 case AF_INET:
3223 p_name = "ipv4";
3224 break;
3225 case AF_INET6:
3226 p_name = "ipv6";
3227 break;
3228 default:
3229 BUG();
3230 }
3231
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003232 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3233 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003234 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003235 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003236 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003237 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003238
Linus Torvalds1da177e2005-04-16 15:20:36 -07003239 p->sysctl_table = t;
3240 return 0;
3241
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003242free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003244err:
3245 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003246}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003247EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003248
3249void neigh_sysctl_unregister(struct neigh_parms *p)
3250{
3251 if (p->sysctl_table) {
3252 struct neigh_sysctl_table *t = p->sysctl_table;
3253 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003254 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255 kfree(t);
3256 }
3257}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003258EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003259
3260#endif /* CONFIG_SYSCTL */
3261
Thomas Grafc8822a42007-03-22 11:50:06 -07003262static int __init neigh_init(void)
3263{
Florian Westphalb97bac62017-08-09 20:41:48 +02003264 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3265 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
3266 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003267
Greg Rosec7ac8672011-06-10 01:27:09 +00003268 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003269 0);
3270 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003271
3272 return 0;
3273}
3274
3275subsys_initcall(neigh_init);
3276