blob: 58b0bcc125b5559f299dc2f195deccb5c43d0844 [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
121static int neigh_forced_gc(struct neigh_table *tbl)
122{
123 int shrunk = 0;
124 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000125 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126
127 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
128
129 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000130 nht = rcu_dereference_protected(tbl->nht,
131 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700132 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700133 struct neighbour *n;
134 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000136 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700137 while ((n = rcu_dereference_protected(*np,
138 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 /* Neighbour record may be discarded if:
140 * - nobody refers to it.
141 * - it is not permanent
142 */
143 write_lock(&n->lock);
144 if (atomic_read(&n->refcnt) == 1 &&
145 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700146 rcu_assign_pointer(*np,
147 rcu_dereference_protected(n->next,
148 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 n->dead = 1;
150 shrunk = 1;
151 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700152 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 continue;
154 }
155 write_unlock(&n->lock);
156 np = &n->next;
157 }
158 }
159
160 tbl->last_flush = jiffies;
161
162 write_unlock_bh(&tbl->lock);
163
164 return shrunk;
165}
166
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800167static void neigh_add_timer(struct neighbour *n, unsigned long when)
168{
169 neigh_hold(n);
170 if (unlikely(mod_timer(&n->timer, when))) {
171 printk("NEIGH: BUG, double timer add, state is %x\n",
172 n->nud_state);
173 dump_stack();
174 }
175}
176
Linus Torvalds1da177e2005-04-16 15:20:36 -0700177static int neigh_del_timer(struct neighbour *n)
178{
179 if ((n->nud_state & NUD_IN_TIMER) &&
180 del_timer(&n->timer)) {
181 neigh_release(n);
182 return 1;
183 }
184 return 0;
185}
186
187static void pneigh_queue_purge(struct sk_buff_head *list)
188{
189 struct sk_buff *skb;
190
191 while ((skb = skb_dequeue(list)) != NULL) {
192 dev_put(skb->dev);
193 kfree_skb(skb);
194 }
195}
196
Herbert Xu49636bb2005-10-23 17:18:00 +1000197static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700198{
199 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000200 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000202 nht = rcu_dereference_protected(tbl->nht,
203 lockdep_is_held(&tbl->lock));
204
David S. Millercd089332011-07-11 01:28:12 -0700205 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700206 struct neighbour *n;
207 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Eric Dumazet767e97e2010-10-06 17:49:21 -0700209 while ((n = rcu_dereference_protected(*np,
210 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211 if (dev && n->dev != dev) {
212 np = &n->next;
213 continue;
214 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700215 rcu_assign_pointer(*np,
216 rcu_dereference_protected(n->next,
217 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 write_lock(&n->lock);
219 neigh_del_timer(n);
220 n->dead = 1;
221
222 if (atomic_read(&n->refcnt) != 1) {
223 /* The most unpleasant situation.
224 We must destroy neighbour entry,
225 but someone still uses it.
226
227 The destroy will be delayed until
228 the last user releases us, but
229 we must kill timers etc. and move
230 it to safe state.
231 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700232 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000233 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234 n->output = neigh_blackhole;
235 if (n->nud_state & NUD_VALID)
236 n->nud_state = NUD_NOARP;
237 else
238 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000239 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700240 }
241 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700242 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
244 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000245}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Herbert Xu49636bb2005-10-23 17:18:00 +1000247void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
248{
249 write_lock_bh(&tbl->lock);
250 neigh_flush_dev(tbl, dev);
251 write_unlock_bh(&tbl->lock);
252}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900253EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000254
255int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
256{
257 write_lock_bh(&tbl->lock);
258 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259 pneigh_ifdown(tbl, dev);
260 write_unlock_bh(&tbl->lock);
261
262 del_timer_sync(&tbl->proxy_timer);
263 pneigh_queue_purge(&tbl->proxy_queue);
264 return 0;
265}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900266EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700267
David Miller596b9b62011-07-25 00:01:25 +0000268static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269{
270 struct neighbour *n = NULL;
271 unsigned long now = jiffies;
272 int entries;
273
274 entries = atomic_inc_return(&tbl->entries) - 1;
275 if (entries >= tbl->gc_thresh3 ||
276 (entries >= tbl->gc_thresh2 &&
277 time_after(now, tbl->last_flush + 5 * HZ))) {
278 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700279 entries >= tbl->gc_thresh3) {
280 net_info_ratelimited("%s: neighbor table overflow!\n",
281 tbl->id);
282 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700283 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700284 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700285 }
286
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000287 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700288 if (!n)
289 goto out_entries;
290
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700291 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700292 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000293 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294 n->updated = n->used = now;
295 n->nud_state = NUD_NONE;
296 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700297 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800299 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 NEIGH_CACHE_STAT_INC(tbl, allocs);
302 n->tbl = tbl;
303 atomic_set(&n->refcnt, 1);
304 n->dead = 1;
305out:
306 return n;
307
308out_entries:
309 atomic_dec(&tbl->entries);
310 goto out;
311}
312
David S. Miller2c2aba62011-12-28 15:06:58 -0500313static void neigh_get_hash_rnd(u32 *x)
314{
315 get_random_bytes(x, sizeof(*x));
316 *x |= 1;
317}
318
David S. Millercd089332011-07-11 01:28:12 -0700319static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320{
David S. Millercd089332011-07-11 01:28:12 -0700321 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000322 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000323 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500324 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000326 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
327 if (!ret)
328 return NULL;
329 if (size <= PAGE_SIZE)
330 buckets = kzalloc(size, GFP_ATOMIC);
331 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000332 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000333 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
334 get_order(size));
335 if (!buckets) {
336 kfree(ret);
337 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000339 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700340 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500341 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
342 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700343 return ret;
344}
345
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000346static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700347{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000348 struct neigh_hash_table *nht = container_of(head,
349 struct neigh_hash_table,
350 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700351 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000352 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700353
354 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000355 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000357 free_pages((unsigned long)buckets, get_order(size));
358 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359}
360
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000361static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700362 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000364 unsigned int i, hash;
365 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700366
367 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
368
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000369 old_nht = rcu_dereference_protected(tbl->nht,
370 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700371 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000372 if (!new_nht)
373 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
David S. Millercd089332011-07-11 01:28:12 -0700375 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 struct neighbour *n, *next;
377
Eric Dumazet767e97e2010-10-06 17:49:21 -0700378 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
379 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000380 n != NULL;
381 n = next) {
382 hash = tbl->hash(n->primary_key, n->dev,
383 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384
David S. Millercd089332011-07-11 01:28:12 -0700385 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700386 next = rcu_dereference_protected(n->next,
387 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388
Eric Dumazet767e97e2010-10-06 17:49:21 -0700389 rcu_assign_pointer(n->next,
390 rcu_dereference_protected(
391 new_nht->hash_buckets[hash],
392 lockdep_is_held(&tbl->lock)));
393 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 }
395 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000397 rcu_assign_pointer(tbl->nht, new_nht);
398 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
399 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400}
401
402struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
403 struct net_device *dev)
404{
405 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900406
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 NEIGH_CACHE_STAT_INC(tbl, lookups);
408
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000409 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600410 n = __neigh_lookup_noref(tbl, pkey, dev);
411 if (n) {
412 if (!atomic_inc_not_zero(&n->refcnt))
413 n = NULL;
414 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700416
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000417 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 return n;
419}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900420EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421
Eric W. Biederman426b5302008-01-24 00:13:18 -0800422struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
423 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424{
425 struct neighbour *n;
426 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800427 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000428 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429
430 NEIGH_CACHE_STAT_INC(tbl, lookups);
431
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000432 rcu_read_lock_bh();
433 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700434 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700435
436 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
437 n != NULL;
438 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800439 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900440 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700441 if (!atomic_inc_not_zero(&n->refcnt))
442 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 NEIGH_CACHE_STAT_INC(tbl, hits);
444 break;
445 }
446 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700447
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000448 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 return n;
450}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900451EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452
David S. Millera263b302012-07-02 02:02:15 -0700453struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
454 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
456 u32 hash_val;
457 int key_len = tbl->key_len;
458 int error;
David Miller596b9b62011-07-25 00:01:25 +0000459 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000460 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
462 if (!n) {
463 rc = ERR_PTR(-ENOBUFS);
464 goto out;
465 }
466
467 memcpy(n->primary_key, pkey, key_len);
468 n->dev = dev;
469 dev_hold(dev);
470
471 /* Protocol specific setup. */
472 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
473 rc = ERR_PTR(error);
474 goto out_neigh_release;
475 }
476
David Millerda6a8fa2011-07-25 00:01:38 +0000477 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200478 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000479 if (error < 0) {
480 rc = ERR_PTR(error);
481 goto out_neigh_release;
482 }
483 }
484
David S. Miller447f2192011-12-19 15:04:41 -0500485 /* Device specific setup. */
486 if (n->parms->neigh_setup &&
487 (error = n->parms->neigh_setup(n)) < 0) {
488 rc = ERR_PTR(error);
489 goto out_neigh_release;
490 }
491
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100492 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493
494 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000495 nht = rcu_dereference_protected(tbl->nht,
496 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497
David S. Millercd089332011-07-11 01:28:12 -0700498 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
499 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500
David S. Millercd089332011-07-11 01:28:12 -0700501 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 if (n->parms->dead) {
504 rc = ERR_PTR(-EINVAL);
505 goto out_tbl_unlock;
506 }
507
Eric Dumazet767e97e2010-10-06 17:49:21 -0700508 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
509 lockdep_is_held(&tbl->lock));
510 n1 != NULL;
511 n1 = rcu_dereference_protected(n1->next,
512 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700514 if (want_ref)
515 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 rc = n1;
517 goto out_tbl_unlock;
518 }
519 }
520
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700522 if (want_ref)
523 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700524 rcu_assign_pointer(n->next,
525 rcu_dereference_protected(nht->hash_buckets[hash_val],
526 lockdep_is_held(&tbl->lock)));
527 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000529 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 rc = n;
531out:
532 return rc;
533out_tbl_unlock:
534 write_unlock_bh(&tbl->lock);
535out_neigh_release:
536 neigh_release(n);
537 goto out;
538}
David S. Millera263b302012-07-02 02:02:15 -0700539EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900541static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700542{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700543 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700544 hash_val ^= (hash_val >> 16);
545 hash_val ^= hash_val >> 8;
546 hash_val ^= hash_val >> 4;
547 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900548 return hash_val;
549}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700550
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900551static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
552 struct net *net,
553 const void *pkey,
554 int key_len,
555 struct net_device *dev)
556{
557 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700558 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900559 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700560 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900561 return n;
562 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700563 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900564 return NULL;
565}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700566
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900567struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
568 struct net *net, const void *pkey, struct net_device *dev)
569{
570 int key_len = tbl->key_len;
571 u32 hash_val = pneigh_hash(pkey, key_len);
572
573 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
574 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700575}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900576EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700577
Eric W. Biederman426b5302008-01-24 00:13:18 -0800578struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
579 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 struct net_device *dev, int creat)
581{
582 struct pneigh_entry *n;
583 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900584 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
586 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900587 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
588 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900590
591 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 goto out;
593
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700594 ASSERT_RTNL();
595
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
597 if (!n)
598 goto out;
599
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500600 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 memcpy(n->key, pkey, key_len);
602 n->dev = dev;
603 if (dev)
604 dev_hold(dev);
605
606 if (tbl->pconstructor && tbl->pconstructor(n)) {
607 if (dev)
608 dev_put(dev);
609 kfree(n);
610 n = NULL;
611 goto out;
612 }
613
614 write_lock_bh(&tbl->lock);
615 n->next = tbl->phash_buckets[hash_val];
616 tbl->phash_buckets[hash_val] = n;
617 write_unlock_bh(&tbl->lock);
618out:
619 return n;
620}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900621EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622
623
Eric W. Biederman426b5302008-01-24 00:13:18 -0800624int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625 struct net_device *dev)
626{
627 struct pneigh_entry *n, **np;
628 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900629 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630
631 write_lock_bh(&tbl->lock);
632 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
633 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800634 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900635 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 *np = n->next;
637 write_unlock_bh(&tbl->lock);
638 if (tbl->pdestructor)
639 tbl->pdestructor(n);
640 if (n->dev)
641 dev_put(n->dev);
642 kfree(n);
643 return 0;
644 }
645 }
646 write_unlock_bh(&tbl->lock);
647 return -ENOENT;
648}
649
650static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
651{
652 struct pneigh_entry *n, **np;
653 u32 h;
654
655 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
656 np = &tbl->phash_buckets[h];
657 while ((n = *np) != NULL) {
658 if (!dev || n->dev == dev) {
659 *np = n->next;
660 if (tbl->pdestructor)
661 tbl->pdestructor(n);
662 if (n->dev)
663 dev_put(n->dev);
664 kfree(n);
665 continue;
666 }
667 np = &n->next;
668 }
669 }
670 return -ENOENT;
671}
672
Denis V. Lunev06f05112008-01-24 00:30:58 -0800673static void neigh_parms_destroy(struct neigh_parms *parms);
674
675static inline void neigh_parms_put(struct neigh_parms *parms)
676{
677 if (atomic_dec_and_test(&parms->refcnt))
678 neigh_parms_destroy(parms);
679}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
681/*
682 * neighbour must already be out of the table;
683 *
684 */
685void neigh_destroy(struct neighbour *neigh)
686{
David Millerda6a8fa2011-07-25 00:01:38 +0000687 struct net_device *dev = neigh->dev;
688
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
690
691 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000692 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 dump_stack();
694 return;
695 }
696
697 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000698 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700700 write_lock_bh(&neigh->lock);
701 __skb_queue_purge(&neigh->arp_queue);
702 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000703 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704
David S. Miller447f2192011-12-19 15:04:41 -0500705 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200706 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500707
David Millerda6a8fa2011-07-25 00:01:38 +0000708 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 neigh_parms_put(neigh->parms);
710
Joe Perchesd5d427c2013-04-15 15:17:19 +0000711 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700712
713 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000714 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900716EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717
718/* Neighbour state is suspicious;
719 disable fast path.
720
721 Called with write_locked neigh.
722 */
723static void neigh_suspect(struct neighbour *neigh)
724{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000725 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728}
729
730/* Neighbour state is OK;
731 enable fast path.
732
733 Called with write_locked neigh.
734 */
735static void neigh_connect(struct neighbour *neigh)
736{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000737 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
739 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740}
741
Eric Dumazete4c4e442009-07-30 03:15:07 +0000742static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000744 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700745 struct neighbour *n;
746 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000747 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000748 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749
750 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
751
Eric Dumazete4c4e442009-07-30 03:15:07 +0000752 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000753 nht = rcu_dereference_protected(tbl->nht,
754 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755
756 /*
757 * periodically recompute ReachableTime from random function
758 */
759
Eric Dumazete4c4e442009-07-30 03:15:07 +0000760 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000762 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100763 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100765 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 }
767
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800768 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
769 goto out;
770
David S. Millercd089332011-07-11 01:28:12 -0700771 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000772 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773
Eric Dumazet767e97e2010-10-06 17:49:21 -0700774 while ((n = rcu_dereference_protected(*np,
775 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000776 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777
Eric Dumazete4c4e442009-07-30 03:15:07 +0000778 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
Eric Dumazete4c4e442009-07-30 03:15:07 +0000780 state = n->nud_state;
781 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
782 write_unlock(&n->lock);
783 goto next_elt;
784 }
785
786 if (time_before(n->used, n->confirmed))
787 n->used = n->confirmed;
788
789 if (atomic_read(&n->refcnt) == 1 &&
790 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100791 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000792 *np = n->next;
793 n->dead = 1;
794 write_unlock(&n->lock);
795 neigh_cleanup_and_release(n);
796 continue;
797 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
800next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000801 np = &n->next;
802 }
803 /*
804 * It's fine to release lock here, even if hash table
805 * grows while we are preempted.
806 */
807 write_unlock_bh(&tbl->lock);
808 cond_resched();
809 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500810 nht = rcu_dereference_protected(tbl->nht,
811 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700812 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000813out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100814 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
815 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
816 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817 */
viresh kumarf6180022014-01-22 12:23:33 +0530818 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100819 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000820 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821}
822
823static __inline__ int neigh_max_probes(struct neighbour *n)
824{
825 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900826 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
827 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
828 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829}
830
Timo Teras5ef12d92009-06-11 04:16:28 -0700831static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000832 __releases(neigh->lock)
833 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700834{
835 struct sk_buff *skb;
836
837 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000838 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700839 neigh->updated = jiffies;
840
841 /* It is very thin place. report_unreachable is very complicated
842 routine. Particularly, it can hit the same neighbour entry!
843
844 So that, we try to be accurate and avoid dead loop. --ANK
845 */
846 while (neigh->nud_state == NUD_FAILED &&
847 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
848 write_unlock(&neigh->lock);
849 neigh->ops->error_report(neigh, skb);
850 write_lock(&neigh->lock);
851 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700852 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000853 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700854}
855
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000856static void neigh_probe(struct neighbour *neigh)
857 __releases(neigh->lock)
858{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200859 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000860 /* keep skb alive even if arp_queue overflows */
861 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800862 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000863 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -0700864 if (neigh->ops->solicit)
865 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000866 atomic_inc(&neigh->probes);
867 kfree_skb(skb);
868}
869
Linus Torvalds1da177e2005-04-16 15:20:36 -0700870/* Called when a timer expires for a neighbour entry. */
871
872static void neigh_timer_handler(unsigned long arg)
873{
874 unsigned long now, next;
875 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000876 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877 int notify = 0;
878
879 write_lock(&neigh->lock);
880
881 state = neigh->nud_state;
882 now = jiffies;
883 next = now + HZ;
884
David S. Miller045f7b32011-11-01 17:45:55 -0400885 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700887
888 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900889 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700890 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000891 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892 next = neigh->confirmed + neigh->parms->reachable_time;
893 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100894 neigh->used +
895 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000896 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800898 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100900 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000902 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800904 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700906 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 }
908 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900909 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100910 neigh->confirmed +
911 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000912 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800914 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700916 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 next = neigh->confirmed + neigh->parms->reachable_time;
918 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000919 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700920 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800921 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +0900923 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100924 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 }
926 } else {
927 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100928 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 }
930
931 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
932 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 neigh->nud_state = NUD_FAILED;
934 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700935 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +0800936 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937 }
938
939 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 if (time_before(next, jiffies + HZ/2))
941 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000942 if (!mod_timer(&neigh->timer, next))
943 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 }
945 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000946 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800947 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800948out:
David S. Miller9ff56602008-02-17 18:39:54 -0800949 write_unlock(&neigh->lock);
950 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700951
Thomas Grafd961db32007-08-08 23:12:56 -0700952 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700953 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -0700954
Linus Torvalds1da177e2005-04-16 15:20:36 -0700955 neigh_release(neigh);
956}
957
958int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
959{
960 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000961 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962
963 write_lock_bh(&neigh->lock);
964
965 rc = 0;
966 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
967 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +0300968 if (neigh->dead)
969 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100972 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
973 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000974 unsigned long next, now = jiffies;
975
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100976 atomic_set(&neigh->probes,
977 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700978 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000979 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100980 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
981 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000982 neigh_add_timer(neigh, next);
983 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 } else {
985 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800986 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 write_unlock_bh(&neigh->lock);
988
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000989 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990 return 1;
991 }
992 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000993 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800995 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100996 neigh_add_timer(neigh, jiffies +
997 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 }
999
1000 if (neigh->nud_state == NUD_INCOMPLETE) {
1001 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001002 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001003 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001005
David S. Millerf72051b2008-09-23 01:11:18 -07001006 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001007 if (!buff)
1008 break;
1009 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001011 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001013 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001015 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016 }
1017 rc = 1;
1018 }
1019out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001020 if (immediate_probe)
1021 neigh_probe(neigh);
1022 else
1023 write_unlock(&neigh->lock);
1024 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001026
1027out_dead:
1028 if (neigh->nud_state & NUD_STALE)
1029 goto out_unlock_bh;
1030 write_unlock_bh(&neigh->lock);
1031 kfree_skb(skb);
1032 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001034EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035
David S. Millerf6b72b622011-07-14 07:53:20 -07001036static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037{
1038 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001039 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001040 = NULL;
1041
1042 if (neigh->dev->header_ops)
1043 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001046 hh = &neigh->hh;
1047 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001048 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001050 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 }
1052 }
1053}
1054
1055
1056
1057/* Generic update routine.
1058 -- lladdr is new lladdr or NULL, if it is not supplied.
1059 -- new is new state.
1060 -- flags
1061 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1062 if it is different.
1063 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001064 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1067
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001068 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 NTF_ROUTER flag.
1070 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1071 a router.
1072
1073 Caller MUST hold reference count on the entry.
1074 */
1075
1076int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001077 u32 flags, u32 nlmsg_pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
1079 u8 old;
1080 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 struct net_device *dev;
1083 int update_isrouter = 0;
1084
1085 write_lock_bh(&neigh->lock);
1086
1087 dev = neigh->dev;
1088 old = neigh->nud_state;
1089 err = -EPERM;
1090
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001091 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 (old & (NUD_NOARP | NUD_PERMANENT)))
1093 goto out;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001094 if (neigh->dead)
1095 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001096
1097 if (!(new & NUD_VALID)) {
1098 neigh_del_timer(neigh);
1099 if (old & NUD_CONNECTED)
1100 neigh_suspect(neigh);
1101 neigh->nud_state = new;
1102 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001104 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1105 (new & NUD_FAILED)) {
1106 neigh_invalidate(neigh);
1107 notify = 1;
1108 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 goto out;
1110 }
1111
1112 /* Compare new lladdr with cached one */
1113 if (!dev->addr_len) {
1114 /* First case: device needs no address. */
1115 lladdr = neigh->ha;
1116 } else if (lladdr) {
1117 /* The second case: if something is already cached
1118 and a new address is proposed:
1119 - compare new & old
1120 - if they are different, check override flag
1121 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001122 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001123 !memcmp(lladdr, neigh->ha, dev->addr_len))
1124 lladdr = neigh->ha;
1125 } else {
1126 /* No address is supplied; if we know something,
1127 use it, otherwise discard the request.
1128 */
1129 err = -EINVAL;
1130 if (!(old & NUD_VALID))
1131 goto out;
1132 lladdr = neigh->ha;
1133 }
1134
1135 if (new & NUD_CONNECTED)
1136 neigh->confirmed = jiffies;
1137 neigh->updated = jiffies;
1138
1139 /* If entry was valid and address is not changed,
1140 do not change entry state, if new one is STALE.
1141 */
1142 err = 0;
1143 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1144 if (old & NUD_VALID) {
1145 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1146 update_isrouter = 0;
1147 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1148 (old & NUD_CONNECTED)) {
1149 lladdr = neigh->ha;
1150 new = NUD_STALE;
1151 } else
1152 goto out;
1153 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001154 if (lladdr == neigh->ha && new == NUD_STALE &&
1155 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 new = old;
1157 }
1158 }
1159
1160 if (new != old) {
1161 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001162 if (new & NUD_PROBE)
1163 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001164 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001165 neigh_add_timer(neigh, (jiffies +
1166 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001167 neigh->parms->reachable_time :
1168 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001170 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 }
1172
1173 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001174 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001176 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 neigh_update_hhs(neigh);
1178 if (!(new & NUD_CONNECTED))
1179 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001180 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 if (new == old)
1184 goto out;
1185 if (new & NUD_CONNECTED)
1186 neigh_connect(neigh);
1187 else
1188 neigh_suspect(neigh);
1189 if (!(old & NUD_VALID)) {
1190 struct sk_buff *skb;
1191
1192 /* Again: avoid dead loop if something went wrong */
1193
1194 while (neigh->nud_state & NUD_VALID &&
1195 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001196 struct dst_entry *dst = skb_dst(skb);
1197 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001199
1200 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001201
1202 /* Why not just use 'neigh' as-is? The problem is that
1203 * things such as shaper, eql, and sch_teql can end up
1204 * using alternative, different, neigh objects to output
1205 * the packet in the output path. So what we need to do
1206 * here is re-lookup the top-level neigh in the path so
1207 * we can reinject the packet there.
1208 */
1209 n2 = NULL;
1210 if (dst) {
1211 n2 = dst_neigh_lookup_skb(dst, skb);
1212 if (n2)
1213 n1 = n2;
1214 }
David S. Miller8f40b162011-07-17 13:34:11 -07001215 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001216 if (n2)
1217 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001218 rcu_read_unlock();
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 write_lock_bh(&neigh->lock);
1221 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001222 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001223 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225out:
1226 if (update_isrouter) {
1227 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1228 (neigh->flags | NTF_ROUTER) :
1229 (neigh->flags & ~NTF_ROUTER);
1230 }
1231 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001232
1233 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001234 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return err;
1237}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001238EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
Jiri Benc7e980562013-12-11 13:48:20 +01001240/* Update the neigh to listen temporarily for probe responses, even if it is
1241 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1242 */
1243void __neigh_set_probe_once(struct neighbour *neigh)
1244{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001245 if (neigh->dead)
1246 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001247 neigh->updated = jiffies;
1248 if (!(neigh->nud_state & NUD_FAILED))
1249 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001250 neigh->nud_state = NUD_INCOMPLETE;
1251 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001252 neigh_add_timer(neigh,
1253 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1254}
1255EXPORT_SYMBOL(__neigh_set_probe_once);
1256
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1258 u8 *lladdr, void *saddr,
1259 struct net_device *dev)
1260{
1261 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1262 lladdr || !dev->addr_len);
1263 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001264 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001265 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 return neigh;
1267}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001268EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269
Eric Dumazet34d101d2010-10-11 09:16:57 -07001270/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001271static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001273 struct net_device *dev = n->dev;
1274 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001275 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001276
1277 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001278
David S. Millerf6b72b622011-07-14 07:53:20 -07001279 /* Only one thread can come in here and initialize the
1280 * hh_cache entry.
1281 */
David S. Millerb23b5452011-07-16 17:45:02 -07001282 if (!hh->hh_len)
1283 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001284
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001285 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286}
1287
Linus Torvalds1da177e2005-04-16 15:20:36 -07001288/* Slow and careful. */
1289
David S. Miller8f40b162011-07-17 13:34:11 -07001290int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 int rc = 0;
1293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294 if (!neigh_event_send(neigh, skb)) {
1295 int err;
1296 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001297 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001298
David S. Millerf6b72b622011-07-14 07:53:20 -07001299 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001300 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001301
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001302 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001303 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001304 seq = read_seqbegin(&neigh->ha_lock);
1305 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1306 neigh->ha, NULL, skb->len);
1307 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001308
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001310 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311 else
1312 goto out_kfree_skb;
1313 }
1314out:
1315 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316out_kfree_skb:
1317 rc = -EINVAL;
1318 kfree_skb(skb);
1319 goto out;
1320}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001321EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322
1323/* As fast as possible without hh cache */
1324
David S. Miller8f40b162011-07-17 13:34:11 -07001325int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001327 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001328 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001329 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001331 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001332 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001333 seq = read_seqbegin(&neigh->ha_lock);
1334 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1335 neigh->ha, NULL, skb->len);
1336 } while (read_seqretry(&neigh->ha_lock, seq));
1337
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001339 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 else {
1341 err = -EINVAL;
1342 kfree_skb(skb);
1343 }
1344 return err;
1345}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001346EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
David S. Miller8f40b162011-07-17 13:34:11 -07001348int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1349{
1350 return dev_queue_xmit(skb);
1351}
1352EXPORT_SYMBOL(neigh_direct_output);
1353
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354static void neigh_proxy_process(unsigned long arg)
1355{
1356 struct neigh_table *tbl = (struct neigh_table *)arg;
1357 long sched_next = 0;
1358 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001359 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360
1361 spin_lock(&tbl->proxy_queue.lock);
1362
David S. Millerf72051b2008-09-23 01:11:18 -07001363 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1364 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001365
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001367 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001368
David S. Millerf72051b2008-09-23 01:11:18 -07001369 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001370 if (tbl->proxy_redo && netif_running(dev)) {
1371 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001372 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001373 rcu_read_unlock();
1374 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001375 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001376 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377
1378 dev_put(dev);
1379 } else if (!sched_next || tdif < sched_next)
1380 sched_next = tdif;
1381 }
1382 del_timer(&tbl->proxy_timer);
1383 if (sched_next)
1384 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1385 spin_unlock(&tbl->proxy_queue.lock);
1386}
1387
1388void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1389 struct sk_buff *skb)
1390{
1391 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001392
1393 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001394 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001395
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001396 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 kfree_skb(skb);
1398 return;
1399 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001400
1401 NEIGH_CB(skb)->sched_next = sched_next;
1402 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
1404 spin_lock(&tbl->proxy_queue.lock);
1405 if (del_timer(&tbl->proxy_timer)) {
1406 if (time_before(tbl->proxy_timer.expires, sched_next))
1407 sched_next = tbl->proxy_timer.expires;
1408 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001409 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410 dev_hold(skb->dev);
1411 __skb_queue_tail(&tbl->proxy_queue, skb);
1412 mod_timer(&tbl->proxy_timer, sched_next);
1413 spin_unlock(&tbl->proxy_queue.lock);
1414}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001415EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001417static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001418 struct net *net, int ifindex)
1419{
1420 struct neigh_parms *p;
1421
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001422 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001423 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001424 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001425 return p;
1426 }
1427
1428 return NULL;
1429}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001430
1431struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1432 struct neigh_table *tbl)
1433{
Gao fengcf89d6b2013-06-20 10:01:32 +08001434 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001435 struct net *net = dev_net(dev);
1436 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437
Gao fengcf89d6b2013-06-20 10:01:32 +08001438 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 p->tbl = tbl;
1441 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001443 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001444 dev_hold(dev);
1445 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001446 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001448
1449 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001450 dev_put(dev);
1451 kfree(p);
1452 return NULL;
1453 }
1454
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001456 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001457 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001458
1459 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 }
1461 return p;
1462}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001463EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464
1465static void neigh_rcu_free_parms(struct rcu_head *head)
1466{
1467 struct neigh_parms *parms =
1468 container_of(head, struct neigh_parms, rcu_head);
1469
1470 neigh_parms_put(parms);
1471}
1472
1473void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1474{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 if (!parms || parms == &tbl->parms)
1476 return;
1477 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001478 list_del(&parms->list);
1479 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001481 if (parms->dev)
1482 dev_put(parms->dev);
1483 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001485EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Denis V. Lunev06f05112008-01-24 00:30:58 -08001487static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488{
1489 kfree(parms);
1490}
1491
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001492static struct lock_class_key neigh_table_proxy_queue_class;
1493
WANG Congd7480fd2014-11-10 15:59:36 -08001494static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1495
1496void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497{
1498 unsigned long now = jiffies;
1499 unsigned long phsize;
1500
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001501 INIT_LIST_HEAD(&tbl->parms_list);
1502 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001503 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001506 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508 tbl->stats = alloc_percpu(struct neigh_statistics);
1509 if (!tbl->stats)
1510 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001511
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001513 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1514 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516#endif
1517
David S. Millercd089332011-07-11 01:28:12 -07001518 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
1520 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001521 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001523 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 panic("cannot allocate neighbour cache hashes");
1525
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001526 if (!tbl->entry_size)
1527 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1528 tbl->key_len, NEIGH_PRIV_ALIGN);
1529 else
1530 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1531
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001533 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301534 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1535 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001536 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001537 skb_queue_head_init_class(&tbl->proxy_queue,
1538 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001539
1540 tbl->last_flush = now;
1541 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001542
WANG Congd7480fd2014-11-10 15:59:36 -08001543 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001545EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001546
WANG Congd7480fd2014-11-10 15:59:36 -08001547int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548{
WANG Congd7480fd2014-11-10 15:59:36 -08001549 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001551 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 del_timer_sync(&tbl->proxy_timer);
1553 pneigh_queue_purge(&tbl->proxy_queue);
1554 neigh_ifdown(tbl, NULL);
1555 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001556 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001558 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1559 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001560 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
1562 kfree(tbl->phash_buckets);
1563 tbl->phash_buckets = NULL;
1564
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001565 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1566
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001567 free_percpu(tbl->stats);
1568 tbl->stats = NULL;
1569
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 return 0;
1571}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001572EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
WANG Congd7480fd2014-11-10 15:59:36 -08001574static struct neigh_table *neigh_find_table(int family)
1575{
1576 struct neigh_table *tbl = NULL;
1577
1578 switch (family) {
1579 case AF_INET:
1580 tbl = neigh_tables[NEIGH_ARP_TABLE];
1581 break;
1582 case AF_INET6:
1583 tbl = neigh_tables[NEIGH_ND_TABLE];
1584 break;
1585 case AF_DECnet:
1586 tbl = neigh_tables[NEIGH_DN_TABLE];
1587 break;
1588 }
1589
1590 return tbl;
1591}
1592
David Ahernc21ef3e2017-04-16 09:48:24 -07001593static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1594 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001596 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001597 struct ndmsg *ndm;
1598 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001600 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001602 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001603
Eric Dumazet110b2492010-10-04 04:27:36 +00001604 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001605 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001606 goto out;
1607
Thomas Grafa14a49d2006-08-07 17:53:08 -07001608 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1609 if (dst_attr == NULL)
1610 goto out;
1611
1612 ndm = nlmsg_data(nlh);
1613 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001614 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001615 if (dev == NULL) {
1616 err = -ENODEV;
1617 goto out;
1618 }
1619 }
1620
WANG Congd7480fd2014-11-10 15:59:36 -08001621 tbl = neigh_find_table(ndm->ndm_family);
1622 if (tbl == NULL)
1623 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
WANG Congd7480fd2014-11-10 15:59:36 -08001625 if (nla_len(dst_attr) < tbl->key_len)
1626 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001627
WANG Congd7480fd2014-11-10 15:59:36 -08001628 if (ndm->ndm_flags & NTF_PROXY) {
1629 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001630 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001631 }
WANG Congd7480fd2014-11-10 15:59:36 -08001632
1633 if (dev == NULL)
1634 goto out;
1635
1636 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1637 if (neigh == NULL) {
1638 err = -ENOENT;
1639 goto out;
1640 }
1641
1642 err = neigh_update(neigh, NULL, NUD_FAILED,
1643 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001644 NEIGH_UPDATE_F_ADMIN,
1645 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001646 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001647
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648out:
1649 return err;
1650}
1651
David Ahernc21ef3e2017-04-16 09:48:24 -07001652static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1653 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654{
WANG Congd7480fd2014-11-10 15:59:36 -08001655 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001656 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001657 struct ndmsg *ndm;
1658 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659 struct neigh_table *tbl;
1660 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001661 struct neighbour *neigh;
1662 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001663 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
Eric Dumazet110b2492010-10-04 04:27:36 +00001665 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001666 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001667 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668 goto out;
1669
Thomas Graf5208deb2006-08-07 17:55:40 -07001670 err = -EINVAL;
1671 if (tb[NDA_DST] == NULL)
1672 goto out;
1673
1674 ndm = nlmsg_data(nlh);
1675 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001676 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001677 if (dev == NULL) {
1678 err = -ENODEV;
1679 goto out;
1680 }
1681
1682 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001683 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001684 }
1685
WANG Congd7480fd2014-11-10 15:59:36 -08001686 tbl = neigh_find_table(ndm->ndm_family);
1687 if (tbl == NULL)
1688 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
WANG Congd7480fd2014-11-10 15:59:36 -08001690 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1691 goto out;
1692 dst = nla_data(tb[NDA_DST]);
1693 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694
WANG Congd7480fd2014-11-10 15:59:36 -08001695 if (ndm->ndm_flags & NTF_PROXY) {
1696 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
WANG Congd7480fd2014-11-10 15:59:36 -08001698 err = -ENOBUFS;
1699 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1700 if (pn) {
1701 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001702 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001703 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001704 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 }
1706
WANG Congd7480fd2014-11-10 15:59:36 -08001707 if (dev == NULL)
1708 goto out;
1709
1710 neigh = neigh_lookup(tbl, dst, dev);
1711 if (neigh == NULL) {
1712 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1713 err = -ENOENT;
1714 goto out;
1715 }
1716
1717 neigh = __neigh_lookup_errno(tbl, dst, dev);
1718 if (IS_ERR(neigh)) {
1719 err = PTR_ERR(neigh);
1720 goto out;
1721 }
1722 } else {
1723 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1724 err = -EEXIST;
1725 neigh_release(neigh);
1726 goto out;
1727 }
1728
1729 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1730 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1731 }
1732
1733 if (ndm->ndm_flags & NTF_USE) {
1734 neigh_event_send(neigh, NULL);
1735 err = 0;
1736 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001737 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1738 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001739 neigh_release(neigh);
1740
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741out:
1742 return err;
1743}
1744
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001745static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1746{
Thomas Grafca860fb2006-08-07 18:00:18 -07001747 struct nlattr *nest;
1748
1749 nest = nla_nest_start(skb, NDTA_PARMS);
1750 if (nest == NULL)
1751 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001752
David S. Miller9a6308d2012-04-01 20:06:28 -04001753 if ((parms->dev &&
1754 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1755 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001756 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1757 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001758 /* approximative value for deprecated QUEUE_LEN (in packets) */
1759 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001760 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1761 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1762 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1763 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1764 NEIGH_VAR(parms, UCAST_PROBES)) ||
1765 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1766 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001767 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1768 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001769 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1770 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001771 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001772 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001773 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001774 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001775 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001776 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001777 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001778 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001779 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001780 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001781 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001782 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001783 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001784 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001785 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001786 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001787
Thomas Grafca860fb2006-08-07 18:00:18 -07001788nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001789 nla_nest_cancel(skb, nest);
1790 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001791}
1792
Thomas Grafca860fb2006-08-07 18:00:18 -07001793static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1794 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001795{
1796 struct nlmsghdr *nlh;
1797 struct ndtmsg *ndtmsg;
1798
Thomas Grafca860fb2006-08-07 18:00:18 -07001799 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1800 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001801 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001802
Thomas Grafca860fb2006-08-07 18:00:18 -07001803 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001804
1805 read_lock_bh(&tbl->lock);
1806 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001807 ndtmsg->ndtm_pad1 = 0;
1808 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001809
David S. Miller9a6308d2012-04-01 20:06:28 -04001810 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001811 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001812 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1813 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1814 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1815 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001816 {
1817 unsigned long now = jiffies;
1818 unsigned int flush_delta = now - tbl->last_flush;
1819 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001820 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001821 struct ndt_config ndc = {
1822 .ndtc_key_len = tbl->key_len,
1823 .ndtc_entry_size = tbl->entry_size,
1824 .ndtc_entries = atomic_read(&tbl->entries),
1825 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1826 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001827 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1828 };
1829
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001830 rcu_read_lock_bh();
1831 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001832 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001833 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001834 rcu_read_unlock_bh();
1835
David S. Miller9a6308d2012-04-01 20:06:28 -04001836 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1837 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001838 }
1839
1840 {
1841 int cpu;
1842 struct ndt_stats ndst;
1843
1844 memset(&ndst, 0, sizeof(ndst));
1845
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001846 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001847 struct neigh_statistics *st;
1848
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001849 st = per_cpu_ptr(tbl->stats, cpu);
1850 ndst.ndts_allocs += st->allocs;
1851 ndst.ndts_destroys += st->destroys;
1852 ndst.ndts_hash_grows += st->hash_grows;
1853 ndst.ndts_res_failed += st->res_failed;
1854 ndst.ndts_lookups += st->lookups;
1855 ndst.ndts_hits += st->hits;
1856 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1857 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1858 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1859 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001860 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001861 }
1862
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001863 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1864 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001865 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001866 }
1867
1868 BUG_ON(tbl->parms.dev);
1869 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001870 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001871
1872 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001873 nlmsg_end(skb, nlh);
1874 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001875
Thomas Grafca860fb2006-08-07 18:00:18 -07001876nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001877 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001878 nlmsg_cancel(skb, nlh);
1879 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001880}
1881
Thomas Grafca860fb2006-08-07 18:00:18 -07001882static int neightbl_fill_param_info(struct sk_buff *skb,
1883 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001884 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001885 u32 pid, u32 seq, int type,
1886 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001887{
1888 struct ndtmsg *ndtmsg;
1889 struct nlmsghdr *nlh;
1890
Thomas Grafca860fb2006-08-07 18:00:18 -07001891 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1892 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001893 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001894
Thomas Grafca860fb2006-08-07 18:00:18 -07001895 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001896
1897 read_lock_bh(&tbl->lock);
1898 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001899 ndtmsg->ndtm_pad1 = 0;
1900 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001901
Thomas Grafca860fb2006-08-07 18:00:18 -07001902 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1903 neightbl_fill_parms(skb, parms) < 0)
1904 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001905
1906 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001907 nlmsg_end(skb, nlh);
1908 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001909errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001910 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001911 nlmsg_cancel(skb, nlh);
1912 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001913}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001914
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001915static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001916 [NDTA_NAME] = { .type = NLA_STRING },
1917 [NDTA_THRESH1] = { .type = NLA_U32 },
1918 [NDTA_THRESH2] = { .type = NLA_U32 },
1919 [NDTA_THRESH3] = { .type = NLA_U32 },
1920 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1921 [NDTA_PARMS] = { .type = NLA_NESTED },
1922};
1923
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001924static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001925 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1926 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1927 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1928 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1929 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1930 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001931 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001932 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1933 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1934 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1935 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1936 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1937 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1938 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1939};
1940
David Ahernc21ef3e2017-04-16 09:48:24 -07001941static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
1942 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001943{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001944 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001945 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001946 struct ndtmsg *ndtmsg;
1947 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001948 bool found = false;
1949 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001950
Thomas Graf6b3f8672006-08-07 17:58:53 -07001951 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07001952 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001953 if (err < 0)
1954 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001955
Thomas Graf6b3f8672006-08-07 17:58:53 -07001956 if (tb[NDTA_NAME] == NULL) {
1957 err = -EINVAL;
1958 goto errout;
1959 }
1960
1961 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001962
1963 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1964 tbl = neigh_tables[tidx];
1965 if (!tbl)
1966 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1968 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08001969 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1970 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001971 break;
WANG Congd7480fd2014-11-10 15:59:36 -08001972 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001973 }
1974
WANG Congd7480fd2014-11-10 15:59:36 -08001975 if (!found)
1976 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001977
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001978 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001979 * We acquire tbl->lock to be nice to the periodic timers and
1980 * make sure they always see a consistent set of values.
1981 */
1982 write_lock_bh(&tbl->lock);
1983
Thomas Graf6b3f8672006-08-07 17:58:53 -07001984 if (tb[NDTA_PARMS]) {
1985 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001987 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001988
Thomas Graf6b3f8672006-08-07 17:58:53 -07001989 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07001990 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001991 if (err < 0)
1992 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001993
Thomas Graf6b3f8672006-08-07 17:58:53 -07001994 if (tbp[NDTPA_IFINDEX])
1995 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001996
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001997 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001998 if (p == NULL) {
1999 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002001 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002
Thomas Graf6b3f8672006-08-07 17:58:53 -07002003 for (i = 1; i <= NDTPA_MAX; i++) {
2004 if (tbp[i] == NULL)
2005 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002006
Thomas Graf6b3f8672006-08-07 17:58:53 -07002007 switch (i) {
2008 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002009 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2010 nla_get_u32(tbp[i]) *
2011 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002012 break;
2013 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002014 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2015 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002016 break;
2017 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002018 NEIGH_VAR_SET(p, PROXY_QLEN,
2019 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002020 break;
2021 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002022 NEIGH_VAR_SET(p, APP_PROBES,
2023 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002024 break;
2025 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002026 NEIGH_VAR_SET(p, UCAST_PROBES,
2027 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002028 break;
2029 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002030 NEIGH_VAR_SET(p, MCAST_PROBES,
2031 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002032 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002033 case NDTPA_MCAST_REPROBES:
2034 NEIGH_VAR_SET(p, MCAST_REPROBES,
2035 nla_get_u32(tbp[i]));
2036 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002037 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002038 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2039 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002040 /* update reachable_time as well, otherwise, the change will
2041 * only be effective after the next time neigh_periodic_work
2042 * decides to recompute it (can be multiple minutes)
2043 */
2044 p->reachable_time =
2045 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 break;
2047 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002048 NEIGH_VAR_SET(p, GC_STALETIME,
2049 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002050 break;
2051 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002052 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2053 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002054 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002055 break;
2056 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002057 NEIGH_VAR_SET(p, RETRANS_TIME,
2058 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002059 break;
2060 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002061 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2062 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002063 break;
2064 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002065 NEIGH_VAR_SET(p, PROXY_DELAY,
2066 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002067 break;
2068 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002069 NEIGH_VAR_SET(p, LOCKTIME,
2070 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002071 break;
2072 }
2073 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002074 }
2075
Gao fengdc25c672013-06-20 10:01:34 +08002076 err = -ENOENT;
2077 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2078 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2079 !net_eq(net, &init_net))
2080 goto errout_tbl_lock;
2081
Thomas Graf6b3f8672006-08-07 17:58:53 -07002082 if (tb[NDTA_THRESH1])
2083 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2084
2085 if (tb[NDTA_THRESH2])
2086 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2087
2088 if (tb[NDTA_THRESH3])
2089 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2090
2091 if (tb[NDTA_GC_INTERVAL])
2092 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2093
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002094 err = 0;
2095
Thomas Graf6b3f8672006-08-07 17:58:53 -07002096errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002097 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002098errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002099 return err;
2100}
2101
Thomas Grafc8822a42007-03-22 11:50:06 -07002102static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002103{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002104 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002105 int family, tidx, nidx = 0;
2106 int tbl_skip = cb->args[0];
2107 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002108 struct neigh_table *tbl;
2109
Thomas Grafca860fb2006-08-07 18:00:18 -07002110 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002111
WANG Congd7480fd2014-11-10 15:59:36 -08002112 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002113 struct neigh_parms *p;
2114
WANG Congd7480fd2014-11-10 15:59:36 -08002115 tbl = neigh_tables[tidx];
2116 if (!tbl)
2117 continue;
2118
Thomas Grafca860fb2006-08-07 18:00:18 -07002119 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002120 continue;
2121
Eric W. Biederman15e47302012-09-07 20:12:54 +00002122 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002123 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002124 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002125 break;
2126
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002127 nidx = 0;
2128 p = list_next_entry(&tbl->parms, list);
2129 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002130 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002131 continue;
2132
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002133 if (nidx < neigh_skip)
2134 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002135
Thomas Grafca860fb2006-08-07 18:00:18 -07002136 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002137 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002138 cb->nlh->nlmsg_seq,
2139 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002140 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002141 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002142 next:
2143 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002144 }
2145
Thomas Grafca860fb2006-08-07 18:00:18 -07002146 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002147 }
2148out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002149 cb->args[0] = tidx;
2150 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002151
2152 return skb->len;
2153}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
Thomas Graf8b8aec52006-08-07 17:56:37 -07002155static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2156 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157{
2158 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002159 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002160 struct nlmsghdr *nlh;
2161 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162
Thomas Graf8b8aec52006-08-07 17:56:37 -07002163 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2164 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002165 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002166
2167 ndm = nlmsg_data(nlh);
2168 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002169 ndm->ndm_pad1 = 0;
2170 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002171 ndm->ndm_flags = neigh->flags;
2172 ndm->ndm_type = neigh->type;
2173 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002174
David S. Miller9a6308d2012-04-01 20:06:28 -04002175 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2176 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002177
2178 read_lock_bh(&neigh->lock);
2179 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002180 if (neigh->nud_state & NUD_VALID) {
2181 char haddr[MAX_ADDR_LEN];
2182
2183 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2184 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2185 read_unlock_bh(&neigh->lock);
2186 goto nla_put_failure;
2187 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002188 }
2189
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002190 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2191 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2192 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002193 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2194 read_unlock_bh(&neigh->lock);
2195
David S. Miller9a6308d2012-04-01 20:06:28 -04002196 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2197 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2198 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199
Johannes Berg053c0952015-01-16 22:09:00 +01002200 nlmsg_end(skb, nlh);
2201 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002202
2203nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002204 nlmsg_cancel(skb, nlh);
2205 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002206}
2207
Tony Zelenoff84920c12012-01-26 22:28:58 +00002208static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2209 u32 pid, u32 seq, int type, unsigned int flags,
2210 struct neigh_table *tbl)
2211{
2212 struct nlmsghdr *nlh;
2213 struct ndmsg *ndm;
2214
2215 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2216 if (nlh == NULL)
2217 return -EMSGSIZE;
2218
2219 ndm = nlmsg_data(nlh);
2220 ndm->ndm_family = tbl->family;
2221 ndm->ndm_pad1 = 0;
2222 ndm->ndm_pad2 = 0;
2223 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002224 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002225 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002226 ndm->ndm_state = NUD_NONE;
2227
David S. Miller9a6308d2012-04-01 20:06:28 -04002228 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2229 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002230
Johannes Berg053c0952015-01-16 22:09:00 +01002231 nlmsg_end(skb, nlh);
2232 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002233
2234nla_put_failure:
2235 nlmsg_cancel(skb, nlh);
2236 return -EMSGSIZE;
2237}
2238
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002239static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002240{
2241 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002242 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002243}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244
David Ahern21fdd092015-09-29 09:32:03 -07002245static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2246{
2247 struct net_device *master;
2248
2249 if (!master_idx)
2250 return false;
2251
2252 master = netdev_master_upper_dev_get(dev);
2253 if (!master || master->ifindex != master_idx)
2254 return true;
2255
2256 return false;
2257}
2258
David Ahern16660f02015-10-03 11:43:46 -07002259static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2260{
2261 if (filter_idx && dev->ifindex != filter_idx)
2262 return true;
2263
2264 return false;
2265}
2266
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2268 struct netlink_callback *cb)
2269{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002270 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002271 const struct nlmsghdr *nlh = cb->nlh;
2272 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273 struct neighbour *n;
2274 int rc, h, s_h = cb->args[1];
2275 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002276 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002277 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002278 unsigned int flags = NLM_F_MULTI;
2279 int err;
2280
Johannes Bergfceb6432017-04-12 14:34:07 +02002281 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002282 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002283 if (tb[NDA_IFINDEX])
2284 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2285
David Ahern21fdd092015-09-29 09:32:03 -07002286 if (tb[NDA_MASTER])
2287 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2288
David Ahern16660f02015-10-03 11:43:46 -07002289 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002290 flags |= NLM_F_DUMP_FILTERED;
2291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002293 rcu_read_lock_bh();
2294 nht = rcu_dereference_bh(tbl->nht);
2295
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002296 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002297 if (h > s_h)
2298 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002299 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2300 n != NULL;
2301 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002302 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2303 goto next;
2304 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2305 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002306 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002307 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002309 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002310 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002311 rc = -1;
2312 goto out;
2313 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002314next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002315 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 }
2318 rc = skb->len;
2319out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002320 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 cb->args[1] = h;
2322 cb->args[2] = idx;
2323 return rc;
2324}
2325
Tony Zelenoff84920c12012-01-26 22:28:58 +00002326static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2327 struct netlink_callback *cb)
2328{
2329 struct pneigh_entry *n;
2330 struct net *net = sock_net(skb->sk);
2331 int rc, h, s_h = cb->args[3];
2332 int idx, s_idx = idx = cb->args[4];
2333
2334 read_lock_bh(&tbl->lock);
2335
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002336 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002337 if (h > s_h)
2338 s_idx = 0;
2339 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002340 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002341 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002342 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002343 cb->nlh->nlmsg_seq,
2344 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002345 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002346 read_unlock_bh(&tbl->lock);
2347 rc = -1;
2348 goto out;
2349 }
2350 next:
2351 idx++;
2352 }
2353 }
2354
2355 read_unlock_bh(&tbl->lock);
2356 rc = skb->len;
2357out:
2358 cb->args[3] = h;
2359 cb->args[4] = idx;
2360 return rc;
2361
2362}
2363
Thomas Grafc8822a42007-03-22 11:50:06 -07002364static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002365{
2366 struct neigh_table *tbl;
2367 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002368 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002369 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370
Thomas Graf8b8aec52006-08-07 17:56:37 -07002371 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002372
2373 /* check for full ndmsg structure presence, family member is
2374 * the same for both structures
2375 */
2376 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2377 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2378 proxy = 1;
2379
Linus Torvalds1da177e2005-04-16 15:20:36 -07002380 s_t = cb->args[0];
2381
WANG Congd7480fd2014-11-10 15:59:36 -08002382 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2383 tbl = neigh_tables[t];
2384
2385 if (!tbl)
2386 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387 if (t < s_t || (family && tbl->family != family))
2388 continue;
2389 if (t > s_t)
2390 memset(&cb->args[1], 0, sizeof(cb->args) -
2391 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002392 if (proxy)
2393 err = pneigh_dump_table(tbl, skb, cb);
2394 else
2395 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002396 if (err < 0)
2397 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002399
2400 cb->args[0] = t;
2401 return skb->len;
2402}
2403
2404void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2405{
2406 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002407 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002408
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002409 rcu_read_lock_bh();
2410 nht = rcu_dereference_bh(tbl->nht);
2411
Eric Dumazet767e97e2010-10-06 17:49:21 -07002412 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002413 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414 struct neighbour *n;
2415
Eric Dumazet767e97e2010-10-06 17:49:21 -07002416 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2417 n != NULL;
2418 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002419 cb(n, cookie);
2420 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002421 read_unlock(&tbl->lock);
2422 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423}
2424EXPORT_SYMBOL(neigh_for_each);
2425
2426/* The tbl->lock must be held as a writer and BH disabled. */
2427void __neigh_for_each_release(struct neigh_table *tbl,
2428 int (*cb)(struct neighbour *))
2429{
2430 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002431 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002433 nht = rcu_dereference_protected(tbl->nht,
2434 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002435 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002436 struct neighbour *n;
2437 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002439 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002440 while ((n = rcu_dereference_protected(*np,
2441 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442 int release;
2443
2444 write_lock(&n->lock);
2445 release = cb(n);
2446 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002447 rcu_assign_pointer(*np,
2448 rcu_dereference_protected(n->next,
2449 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002450 n->dead = 1;
2451 } else
2452 np = &n->next;
2453 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002454 if (release)
2455 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 }
2457 }
2458}
2459EXPORT_SYMBOL(__neigh_for_each_release);
2460
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002461int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002462 const void *addr, struct sk_buff *skb)
2463{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002464 int err = -EAFNOSUPPORT;
2465 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002466 struct neigh_table *tbl;
2467 struct neighbour *neigh;
2468
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002469 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002470 if (!tbl)
2471 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002472 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002473 neigh = __neigh_lookup_noref(tbl, addr, dev);
2474 if (!neigh)
2475 neigh = __neigh_create(tbl, addr, dev, false);
2476 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002477 if (IS_ERR(neigh)) {
2478 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002479 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002480 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002481 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002482 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002483 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002484 else if (index == NEIGH_LINK_TABLE) {
2485 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2486 addr, NULL, skb->len);
2487 if (err < 0)
2488 goto out_kfree_skb;
2489 err = dev_queue_xmit(skb);
2490 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002491out:
2492 return err;
2493out_kfree_skb:
2494 kfree_skb(skb);
2495 goto out;
2496}
2497EXPORT_SYMBOL(neigh_xmit);
2498
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499#ifdef CONFIG_PROC_FS
2500
2501static struct neighbour *neigh_get_first(struct seq_file *seq)
2502{
2503 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002504 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002505 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506 struct neighbour *n = NULL;
2507 int bucket = state->bucket;
2508
2509 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002510 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002511 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512
2513 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002514 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002515 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 if (state->neigh_sub_iter) {
2517 loff_t fakep = 0;
2518 void *v;
2519
2520 v = state->neigh_sub_iter(state, n, &fakep);
2521 if (!v)
2522 goto next;
2523 }
2524 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2525 break;
2526 if (n->nud_state & ~NUD_NOARP)
2527 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002528next:
2529 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 }
2531
2532 if (n)
2533 break;
2534 }
2535 state->bucket = bucket;
2536
2537 return n;
2538}
2539
2540static struct neighbour *neigh_get_next(struct seq_file *seq,
2541 struct neighbour *n,
2542 loff_t *pos)
2543{
2544 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002545 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002546 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
2548 if (state->neigh_sub_iter) {
2549 void *v = state->neigh_sub_iter(state, n, pos);
2550 if (v)
2551 return n;
2552 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002553 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554
2555 while (1) {
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 void *v = state->neigh_sub_iter(state, n, pos);
2561 if (v)
2562 return n;
2563 goto next;
2564 }
2565 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2566 break;
2567
2568 if (n->nud_state & ~NUD_NOARP)
2569 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002570next:
2571 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002572 }
2573
2574 if (n)
2575 break;
2576
David S. Millercd089332011-07-11 01:28:12 -07002577 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 break;
2579
Eric Dumazet767e97e2010-10-06 17:49:21 -07002580 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 }
2582
2583 if (n && pos)
2584 --(*pos);
2585 return n;
2586}
2587
2588static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2589{
2590 struct neighbour *n = neigh_get_first(seq);
2591
2592 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002593 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 while (*pos) {
2595 n = neigh_get_next(seq, n, pos);
2596 if (!n)
2597 break;
2598 }
2599 }
2600 return *pos ? NULL : n;
2601}
2602
2603static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2604{
2605 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002606 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002607 struct neigh_table *tbl = state->tbl;
2608 struct pneigh_entry *pn = NULL;
2609 int bucket = state->bucket;
2610
2611 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2612 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2613 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002614 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002615 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 if (pn)
2617 break;
2618 }
2619 state->bucket = bucket;
2620
2621 return pn;
2622}
2623
2624static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2625 struct pneigh_entry *pn,
2626 loff_t *pos)
2627{
2628 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002629 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 struct neigh_table *tbl = state->tbl;
2631
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002632 do {
2633 pn = pn->next;
2634 } while (pn && !net_eq(pneigh_net(pn), net));
2635
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 while (!pn) {
2637 if (++state->bucket > PNEIGH_HASHMASK)
2638 break;
2639 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002640 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002641 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 if (pn)
2643 break;
2644 }
2645
2646 if (pn && pos)
2647 --(*pos);
2648
2649 return pn;
2650}
2651
2652static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2653{
2654 struct pneigh_entry *pn = pneigh_get_first(seq);
2655
2656 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002657 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002658 while (*pos) {
2659 pn = pneigh_get_next(seq, pn, pos);
2660 if (!pn)
2661 break;
2662 }
2663 }
2664 return *pos ? NULL : pn;
2665}
2666
2667static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2668{
2669 struct neigh_seq_state *state = seq->private;
2670 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002671 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002672
Chris Larson745e2032008-08-03 01:10:55 -07002673 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002675 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002676
2677 return rc;
2678}
2679
2680void *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 +00002681 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682{
2683 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
2685 state->tbl = tbl;
2686 state->bucket = 0;
2687 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2688
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002689 rcu_read_lock_bh();
2690 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002691
Chris Larson745e2032008-08-03 01:10:55 -07002692 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002693}
2694EXPORT_SYMBOL(neigh_seq_start);
2695
2696void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2697{
2698 struct neigh_seq_state *state;
2699 void *rc;
2700
2701 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002702 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 goto out;
2704 }
2705
2706 state = seq->private;
2707 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2708 rc = neigh_get_next(seq, v, NULL);
2709 if (rc)
2710 goto out;
2711 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2712 rc = pneigh_get_first(seq);
2713 } else {
2714 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2715 rc = pneigh_get_next(seq, v, NULL);
2716 }
2717out:
2718 ++(*pos);
2719 return rc;
2720}
2721EXPORT_SYMBOL(neigh_seq_next);
2722
2723void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002724 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002725{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002726 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002727}
2728EXPORT_SYMBOL(neigh_seq_stop);
2729
2730/* statistics via seq_file */
2731
2732static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2733{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002734 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735 int cpu;
2736
2737 if (*pos == 0)
2738 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002739
Rusty Russell0f23174a2008-12-29 12:23:42 +00002740 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 if (!cpu_possible(cpu))
2742 continue;
2743 *pos = cpu+1;
2744 return per_cpu_ptr(tbl->stats, cpu);
2745 }
2746 return NULL;
2747}
2748
2749static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2750{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002751 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002752 int cpu;
2753
Rusty Russell0f23174a2008-12-29 12:23:42 +00002754 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755 if (!cpu_possible(cpu))
2756 continue;
2757 *pos = cpu+1;
2758 return per_cpu_ptr(tbl->stats, cpu);
2759 }
2760 return NULL;
2761}
2762
2763static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2764{
2765
2766}
2767
2768static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2769{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002770 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771 struct neigh_statistics *st = v;
2772
2773 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002774 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 -07002775 return 0;
2776 }
2777
2778 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002779 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780 atomic_read(&tbl->entries),
2781
2782 st->allocs,
2783 st->destroys,
2784 st->hash_grows,
2785
2786 st->lookups,
2787 st->hits,
2788
2789 st->res_failed,
2790
2791 st->rcv_probes_mcast,
2792 st->rcv_probes_ucast,
2793
2794 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002795 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002796 st->unres_discards,
2797 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002798 );
2799
2800 return 0;
2801}
2802
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002803static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 .start = neigh_stat_seq_start,
2805 .next = neigh_stat_seq_next,
2806 .stop = neigh_stat_seq_stop,
2807 .show = neigh_stat_seq_show,
2808};
2809
2810static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2811{
2812 int ret = seq_open(file, &neigh_stat_seq_ops);
2813
2814 if (!ret) {
2815 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002816 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002817 }
2818 return ret;
2819};
2820
Arjan van de Ven9a321442007-02-12 00:55:35 -08002821static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002822 .owner = THIS_MODULE,
2823 .open = neigh_stat_seq_open,
2824 .read = seq_read,
2825 .llseek = seq_lseek,
2826 .release = seq_release,
2827};
2828
2829#endif /* CONFIG_PROC_FS */
2830
Thomas Graf339bf982006-11-10 14:10:15 -08002831static inline size_t neigh_nlmsg_size(void)
2832{
2833 return NLMSG_ALIGN(sizeof(struct ndmsg))
2834 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2835 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2836 + nla_total_size(sizeof(struct nda_cacheinfo))
2837 + nla_total_size(4); /* NDA_PROBES */
2838}
2839
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002840static void __neigh_notify(struct neighbour *n, int type, int flags,
2841 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002842{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002843 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002844 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002845 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002846
Thomas Graf339bf982006-11-10 14:10:15 -08002847 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002848 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002849 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002850
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002851 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002852 if (err < 0) {
2853 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2854 WARN_ON(err == -EMSGSIZE);
2855 kfree_skb(skb);
2856 goto errout;
2857 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002858 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2859 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002860errout:
2861 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002862 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002863}
2864
2865void neigh_app_ns(struct neighbour *n)
2866{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002867 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002868}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002869EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002870
2871#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002872static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002873static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002874static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002875
Joe Perchesfe2c6332013-06-11 23:04:25 -07002876static int proc_unres_qlen(struct ctl_table *ctl, int write,
2877 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002878{
2879 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002880 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002881
Shan Weice46cc62012-12-04 18:49:15 +00002882 tmp.extra1 = &zero;
2883 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002884 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002885
2886 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2887 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2888
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002889 if (write && !ret)
2890 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2891 return ret;
2892}
2893
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002894static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2895 int family)
2896{
Jiri Pirkobba24892013-12-07 19:26:57 +01002897 switch (family) {
2898 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002899 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002900 case AF_INET6:
2901 return __in6_dev_nd_parms_get_rcu(dev);
2902 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002903 return NULL;
2904}
2905
2906static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2907 int index)
2908{
2909 struct net_device *dev;
2910 int family = neigh_parms_family(p);
2911
2912 rcu_read_lock();
2913 for_each_netdev_rcu(net, dev) {
2914 struct neigh_parms *dst_p =
2915 neigh_get_dev_parms_rcu(dev, family);
2916
2917 if (dst_p && !test_bit(index, dst_p->data_state))
2918 dst_p->data[index] = p->data[index];
2919 }
2920 rcu_read_unlock();
2921}
2922
2923static void neigh_proc_update(struct ctl_table *ctl, int write)
2924{
2925 struct net_device *dev = ctl->extra1;
2926 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002927 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002928 int index = (int *) ctl->data - p->data;
2929
2930 if (!write)
2931 return;
2932
2933 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002934 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2935 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002936 if (!dev) /* NULL dev means this is default value */
2937 neigh_copy_dflt_parms(net, p, index);
2938}
2939
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002940static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2941 void __user *buffer,
2942 size_t *lenp, loff_t *ppos)
2943{
2944 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002945 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002946
2947 tmp.extra1 = &zero;
2948 tmp.extra2 = &int_max;
2949
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002950 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2951 neigh_proc_update(ctl, write);
2952 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002953}
2954
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002955int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2956 void __user *buffer, size_t *lenp, loff_t *ppos)
2957{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002958 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2959
2960 neigh_proc_update(ctl, write);
2961 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002962}
2963EXPORT_SYMBOL(neigh_proc_dointvec);
2964
2965int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2966 void __user *buffer,
2967 size_t *lenp, loff_t *ppos)
2968{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002969 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2970
2971 neigh_proc_update(ctl, write);
2972 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002973}
2974EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2975
2976static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2977 void __user *buffer,
2978 size_t *lenp, loff_t *ppos)
2979{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002980 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2981
2982 neigh_proc_update(ctl, write);
2983 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002984}
2985
2986int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2987 void __user *buffer,
2988 size_t *lenp, loff_t *ppos)
2989{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002990 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2991
2992 neigh_proc_update(ctl, write);
2993 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002994}
2995EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2996
2997static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2998 void __user *buffer,
2999 size_t *lenp, loff_t *ppos)
3000{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003001 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3002
3003 neigh_proc_update(ctl, write);
3004 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003005}
3006
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003007static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3008 void __user *buffer,
3009 size_t *lenp, loff_t *ppos)
3010{
3011 struct neigh_parms *p = ctl->extra2;
3012 int ret;
3013
3014 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3015 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3016 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3017 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3018 else
3019 ret = -1;
3020
3021 if (write && ret == 0) {
3022 /* update reachable_time as well, otherwise, the change will
3023 * only be effective after the next time neigh_periodic_work
3024 * decides to recompute it
3025 */
3026 p->reachable_time =
3027 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3028 }
3029 return ret;
3030}
3031
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003032#define NEIGH_PARMS_DATA_OFFSET(index) \
3033 (&((struct neigh_parms *) 0)->data[index])
3034
3035#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3036 [NEIGH_VAR_ ## attr] = { \
3037 .procname = name, \
3038 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3039 .maxlen = sizeof(int), \
3040 .mode = mval, \
3041 .proc_handler = proc, \
3042 }
3043
3044#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3045 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3046
3047#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003048 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003049
3050#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003051 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003052
3053#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003054 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003055
3056#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003057 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003058
3059#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003060 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003061
Linus Torvalds1da177e2005-04-16 15:20:36 -07003062static struct neigh_sysctl_table {
3063 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003064 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003065} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003067 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3068 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3069 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003070 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003071 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3072 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3073 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3074 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3075 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3076 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3077 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3078 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3079 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3080 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3081 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3082 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003083 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084 .procname = "gc_interval",
3085 .maxlen = sizeof(int),
3086 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003087 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003088 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003089 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 .procname = "gc_thresh1",
3091 .maxlen = sizeof(int),
3092 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003093 .extra1 = &zero,
3094 .extra2 = &int_max,
3095 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003097 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098 .procname = "gc_thresh2",
3099 .maxlen = sizeof(int),
3100 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003101 .extra1 = &zero,
3102 .extra2 = &int_max,
3103 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003105 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003106 .procname = "gc_thresh3",
3107 .maxlen = sizeof(int),
3108 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003109 .extra1 = &zero,
3110 .extra2 = &int_max,
3111 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003113 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003114 },
3115};
3116
3117int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003118 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003119{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003120 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003121 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003122 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003123 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003124 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003126 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003127 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003128 goto err;
3129
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003130 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003131 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003132 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003133 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003134 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003135
3136 if (dev) {
3137 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003138 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003139 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3140 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003142 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003143 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003144 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3145 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3146 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3147 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003148 }
3149
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003150 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003152 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003154 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003155 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003156 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003158 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003159 } else {
3160 /* Those handlers will update p->reachable_time after
3161 * base_reachable_time(_ms) is set to ensure the new timer starts being
3162 * applied after the next neighbour update instead of waiting for
3163 * neigh_periodic_work to update its value (can be multiple minutes)
3164 * So any handler that replaces them should do this as well
3165 */
3166 /* ReachableTime */
3167 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3168 neigh_proc_base_reachable_time;
3169 /* ReachableTime (in milliseconds) */
3170 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3171 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003172 }
3173
Eric W. Biederman464dc802012-11-16 03:02:59 +00003174 /* Don't export sysctls to unprivileged users */
3175 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3176 t->neigh_vars[0].procname = NULL;
3177
Jiri Pirko73af6142013-12-07 19:26:55 +01003178 switch (neigh_parms_family(p)) {
3179 case AF_INET:
3180 p_name = "ipv4";
3181 break;
3182 case AF_INET6:
3183 p_name = "ipv6";
3184 break;
3185 default:
3186 BUG();
3187 }
3188
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003189 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3190 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003191 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003192 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003193 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003194 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003195
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 p->sysctl_table = t;
3197 return 0;
3198
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003199free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003200 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003201err:
3202 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003204EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205
3206void neigh_sysctl_unregister(struct neigh_parms *p)
3207{
3208 if (p->sysctl_table) {
3209 struct neigh_sysctl_table *t = p->sysctl_table;
3210 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003211 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212 kfree(t);
3213 }
3214}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003215EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003216
3217#endif /* CONFIG_SYSCTL */
3218
Thomas Grafc8822a42007-03-22 11:50:06 -07003219static int __init neigh_init(void)
3220{
Greg Rosec7ac8672011-06-10 01:27:09 +00003221 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3222 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3223 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003224
Greg Rosec7ac8672011-06-10 01:27:09 +00003225 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3226 NULL);
3227 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003228
3229 return 0;
3230}
3231
3232subsys_initcall(neigh_init);
3233