blob: d274f81fcc2c08f1e85df4ed00b9a034f3ae0739 [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. Millerf6b72b62011-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. Millerf6b72b62011-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. Millerf6b72b62011-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
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 /* If entry was valid and address is not changed,
1136 do not change entry state, if new one is STALE.
1137 */
1138 err = 0;
1139 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1140 if (old & NUD_VALID) {
1141 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1142 update_isrouter = 0;
1143 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1144 (old & NUD_CONNECTED)) {
1145 lladdr = neigh->ha;
1146 new = NUD_STALE;
1147 } else
1148 goto out;
1149 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001150 if (lladdr == neigh->ha && new == NUD_STALE &&
1151 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 new = old;
1153 }
1154 }
1155
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001156 /* Update timestamps only once we know we will make a change to the
1157 * neighbour entry. Otherwise we risk to move the locktime window with
1158 * noop updates and ignore relevant ARP updates.
1159 */
1160 if (new != old || lladdr != neigh->ha) {
1161 if (new & NUD_CONNECTED)
1162 neigh->confirmed = jiffies;
1163 neigh->updated = jiffies;
1164 }
1165
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 if (new != old) {
1167 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001168 if (new & NUD_PROBE)
1169 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001170 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001171 neigh_add_timer(neigh, (jiffies +
1172 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001173 neigh->parms->reachable_time :
1174 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001176 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
1178
1179 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001180 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001182 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183 neigh_update_hhs(neigh);
1184 if (!(new & NUD_CONNECTED))
1185 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001186 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001187 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189 if (new == old)
1190 goto out;
1191 if (new & NUD_CONNECTED)
1192 neigh_connect(neigh);
1193 else
1194 neigh_suspect(neigh);
1195 if (!(old & NUD_VALID)) {
1196 struct sk_buff *skb;
1197
1198 /* Again: avoid dead loop if something went wrong */
1199
1200 while (neigh->nud_state & NUD_VALID &&
1201 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001202 struct dst_entry *dst = skb_dst(skb);
1203 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001205
1206 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001207
1208 /* Why not just use 'neigh' as-is? The problem is that
1209 * things such as shaper, eql, and sch_teql can end up
1210 * using alternative, different, neigh objects to output
1211 * the packet in the output path. So what we need to do
1212 * here is re-lookup the top-level neigh in the path so
1213 * we can reinject the packet there.
1214 */
1215 n2 = NULL;
1216 if (dst) {
1217 n2 = dst_neigh_lookup_skb(dst, skb);
1218 if (n2)
1219 n1 = n2;
1220 }
David S. Miller8f40b162011-07-17 13:34:11 -07001221 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001222 if (n2)
1223 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001224 rcu_read_unlock();
1225
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226 write_lock_bh(&neigh->lock);
1227 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001228 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001229 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 }
1231out:
1232 if (update_isrouter) {
1233 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1234 (neigh->flags | NTF_ROUTER) :
1235 (neigh->flags & ~NTF_ROUTER);
1236 }
1237 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001238
1239 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001240 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001241
Linus Torvalds1da177e2005-04-16 15:20:36 -07001242 return err;
1243}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001244EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245
Jiri Benc7e980562013-12-11 13:48:20 +01001246/* Update the neigh to listen temporarily for probe responses, even if it is
1247 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1248 */
1249void __neigh_set_probe_once(struct neighbour *neigh)
1250{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001251 if (neigh->dead)
1252 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001253 neigh->updated = jiffies;
1254 if (!(neigh->nud_state & NUD_FAILED))
1255 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001256 neigh->nud_state = NUD_INCOMPLETE;
1257 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001258 neigh_add_timer(neigh,
1259 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1260}
1261EXPORT_SYMBOL(__neigh_set_probe_once);
1262
Linus Torvalds1da177e2005-04-16 15:20:36 -07001263struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1264 u8 *lladdr, void *saddr,
1265 struct net_device *dev)
1266{
1267 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1268 lladdr || !dev->addr_len);
1269 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001270 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001271 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272 return neigh;
1273}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001274EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275
Eric Dumazet34d101d2010-10-11 09:16:57 -07001276/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001277static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001278{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001279 struct net_device *dev = n->dev;
1280 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b62011-07-14 07:53:20 -07001281 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001282
1283 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001284
David S. Millerf6b72b62011-07-14 07:53:20 -07001285 /* Only one thread can come in here and initialize the
1286 * hh_cache entry.
1287 */
David S. Millerb23b5452011-07-16 17:45:02 -07001288 if (!hh->hh_len)
1289 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001290
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001291 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292}
1293
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294/* Slow and careful. */
1295
David S. Miller8f40b162011-07-17 13:34:11 -07001296int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001297{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001298 int rc = 0;
1299
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 if (!neigh_event_send(neigh, skb)) {
1301 int err;
1302 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001303 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001304
David S. Millerf6b72b62011-07-14 07:53:20 -07001305 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001306 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001307
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001308 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001309 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001310 seq = read_seqbegin(&neigh->ha_lock);
1311 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1312 neigh->ha, NULL, skb->len);
1313 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001314
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001316 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317 else
1318 goto out_kfree_skb;
1319 }
1320out:
1321 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001322out_kfree_skb:
1323 rc = -EINVAL;
1324 kfree_skb(skb);
1325 goto out;
1326}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001327EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
1329/* As fast as possible without hh cache */
1330
David S. Miller8f40b162011-07-17 13:34:11 -07001331int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001332{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001334 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001335 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001337 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001338 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001339 seq = read_seqbegin(&neigh->ha_lock);
1340 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1341 neigh->ha, NULL, skb->len);
1342 } while (read_seqretry(&neigh->ha_lock, seq));
1343
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001345 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346 else {
1347 err = -EINVAL;
1348 kfree_skb(skb);
1349 }
1350 return err;
1351}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001352EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001353
David S. Miller8f40b162011-07-17 13:34:11 -07001354int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1355{
1356 return dev_queue_xmit(skb);
1357}
1358EXPORT_SYMBOL(neigh_direct_output);
1359
Linus Torvalds1da177e2005-04-16 15:20:36 -07001360static void neigh_proxy_process(unsigned long arg)
1361{
1362 struct neigh_table *tbl = (struct neigh_table *)arg;
1363 long sched_next = 0;
1364 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001365 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001366
1367 spin_lock(&tbl->proxy_queue.lock);
1368
David S. Millerf72051b2008-09-23 01:11:18 -07001369 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1370 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001373 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001374
David S. Millerf72051b2008-09-23 01:11:18 -07001375 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001376 if (tbl->proxy_redo && netif_running(dev)) {
1377 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001378 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001379 rcu_read_unlock();
1380 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001381 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001382 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383
1384 dev_put(dev);
1385 } else if (!sched_next || tdif < sched_next)
1386 sched_next = tdif;
1387 }
1388 del_timer(&tbl->proxy_timer);
1389 if (sched_next)
1390 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1391 spin_unlock(&tbl->proxy_queue.lock);
1392}
1393
1394void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1395 struct sk_buff *skb)
1396{
1397 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001398
1399 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001400 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001402 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403 kfree_skb(skb);
1404 return;
1405 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001406
1407 NEIGH_CB(skb)->sched_next = sched_next;
1408 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001409
1410 spin_lock(&tbl->proxy_queue.lock);
1411 if (del_timer(&tbl->proxy_timer)) {
1412 if (time_before(tbl->proxy_timer.expires, sched_next))
1413 sched_next = tbl->proxy_timer.expires;
1414 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001415 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001416 dev_hold(skb->dev);
1417 __skb_queue_tail(&tbl->proxy_queue, skb);
1418 mod_timer(&tbl->proxy_timer, sched_next);
1419 spin_unlock(&tbl->proxy_queue.lock);
1420}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001421EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001422
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001423static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001424 struct net *net, int ifindex)
1425{
1426 struct neigh_parms *p;
1427
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001428 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001429 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001430 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001431 return p;
1432 }
1433
1434 return NULL;
1435}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001436
1437struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1438 struct neigh_table *tbl)
1439{
Gao fengcf89d6b2013-06-20 10:01:32 +08001440 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001441 struct net *net = dev_net(dev);
1442 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Gao fengcf89d6b2013-06-20 10:01:32 +08001444 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 p->tbl = tbl;
1447 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001449 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001450 dev_hold(dev);
1451 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001452 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001454
1455 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001456 dev_put(dev);
1457 kfree(p);
1458 return NULL;
1459 }
1460
Linus Torvalds1da177e2005-04-16 15:20:36 -07001461 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001462 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001463 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001464
1465 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466 }
1467 return p;
1468}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001469EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470
1471static void neigh_rcu_free_parms(struct rcu_head *head)
1472{
1473 struct neigh_parms *parms =
1474 container_of(head, struct neigh_parms, rcu_head);
1475
1476 neigh_parms_put(parms);
1477}
1478
1479void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1480{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 if (!parms || parms == &tbl->parms)
1482 return;
1483 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001484 list_del(&parms->list);
1485 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001487 if (parms->dev)
1488 dev_put(parms->dev);
1489 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001491EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492
Denis V. Lunev06f05112008-01-24 00:30:58 -08001493static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494{
1495 kfree(parms);
1496}
1497
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001498static struct lock_class_key neigh_table_proxy_queue_class;
1499
WANG Congd7480fd2014-11-10 15:59:36 -08001500static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1501
1502void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503{
1504 unsigned long now = jiffies;
1505 unsigned long phsize;
1506
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001507 INIT_LIST_HEAD(&tbl->parms_list);
1508 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001509 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001511 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001512 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513
Linus Torvalds1da177e2005-04-16 15:20:36 -07001514 tbl->stats = alloc_percpu(struct neigh_statistics);
1515 if (!tbl->stats)
1516 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001517
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001519 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1520 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522#endif
1523
David S. Millercd089332011-07-11 01:28:12 -07001524 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
1526 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001527 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001529 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001530 panic("cannot allocate neighbour cache hashes");
1531
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001532 if (!tbl->entry_size)
1533 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1534 tbl->key_len, NEIGH_PRIV_ALIGN);
1535 else
1536 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1537
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001539 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301540 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1541 tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001542 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001543 skb_queue_head_init_class(&tbl->proxy_queue,
1544 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 tbl->last_flush = now;
1547 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001548
WANG Congd7480fd2014-11-10 15:59:36 -08001549 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001551EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552
WANG Congd7480fd2014-11-10 15:59:36 -08001553int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554{
WANG Congd7480fd2014-11-10 15:59:36 -08001555 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001557 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558 del_timer_sync(&tbl->proxy_timer);
1559 pneigh_queue_purge(&tbl->proxy_queue);
1560 neigh_ifdown(tbl, NULL);
1561 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001562 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001564 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1565 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001566 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567
1568 kfree(tbl->phash_buckets);
1569 tbl->phash_buckets = NULL;
1570
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001571 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1572
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001573 free_percpu(tbl->stats);
1574 tbl->stats = NULL;
1575
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 return 0;
1577}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001578EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001579
WANG Congd7480fd2014-11-10 15:59:36 -08001580static struct neigh_table *neigh_find_table(int family)
1581{
1582 struct neigh_table *tbl = NULL;
1583
1584 switch (family) {
1585 case AF_INET:
1586 tbl = neigh_tables[NEIGH_ARP_TABLE];
1587 break;
1588 case AF_INET6:
1589 tbl = neigh_tables[NEIGH_ND_TABLE];
1590 break;
1591 case AF_DECnet:
1592 tbl = neigh_tables[NEIGH_DN_TABLE];
1593 break;
1594 }
1595
1596 return tbl;
1597}
1598
David Ahernc21ef3e2017-04-16 09:48:24 -07001599static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1600 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001602 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001603 struct ndmsg *ndm;
1604 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001605 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001606 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001608 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001609
Eric Dumazet110b2492010-10-04 04:27:36 +00001610 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001611 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612 goto out;
1613
Thomas Grafa14a49d2006-08-07 17:53:08 -07001614 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1615 if (dst_attr == NULL)
1616 goto out;
1617
1618 ndm = nlmsg_data(nlh);
1619 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001620 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001621 if (dev == NULL) {
1622 err = -ENODEV;
1623 goto out;
1624 }
1625 }
1626
WANG Congd7480fd2014-11-10 15:59:36 -08001627 tbl = neigh_find_table(ndm->ndm_family);
1628 if (tbl == NULL)
1629 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630
WANG Congd7480fd2014-11-10 15:59:36 -08001631 if (nla_len(dst_attr) < tbl->key_len)
1632 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633
WANG Congd7480fd2014-11-10 15:59:36 -08001634 if (ndm->ndm_flags & NTF_PROXY) {
1635 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001636 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637 }
WANG Congd7480fd2014-11-10 15:59:36 -08001638
1639 if (dev == NULL)
1640 goto out;
1641
1642 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1643 if (neigh == NULL) {
1644 err = -ENOENT;
1645 goto out;
1646 }
1647
1648 err = neigh_update(neigh, NULL, NUD_FAILED,
1649 NEIGH_UPDATE_F_OVERRIDE |
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001650 NEIGH_UPDATE_F_ADMIN,
1651 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001652 neigh_release(neigh);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001653
Linus Torvalds1da177e2005-04-16 15:20:36 -07001654out:
1655 return err;
1656}
1657
David Ahernc21ef3e2017-04-16 09:48:24 -07001658static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1659 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001660{
WANG Congd7480fd2014-11-10 15:59:36 -08001661 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001662 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001663 struct ndmsg *ndm;
1664 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 struct neigh_table *tbl;
1666 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001667 struct neighbour *neigh;
1668 void *dst, *lladdr;
Thomas Graf5208deb2006-08-07 17:55:40 -07001669 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670
Eric Dumazet110b2492010-10-04 04:27:36 +00001671 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001672 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001673 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674 goto out;
1675
Thomas Graf5208deb2006-08-07 17:55:40 -07001676 err = -EINVAL;
1677 if (tb[NDA_DST] == NULL)
1678 goto out;
1679
1680 ndm = nlmsg_data(nlh);
1681 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001682 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001683 if (dev == NULL) {
1684 err = -ENODEV;
1685 goto out;
1686 }
1687
1688 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001689 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001690 }
1691
WANG Congd7480fd2014-11-10 15:59:36 -08001692 tbl = neigh_find_table(ndm->ndm_family);
1693 if (tbl == NULL)
1694 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695
WANG Congd7480fd2014-11-10 15:59:36 -08001696 if (nla_len(tb[NDA_DST]) < tbl->key_len)
1697 goto out;
1698 dst = nla_data(tb[NDA_DST]);
1699 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
WANG Congd7480fd2014-11-10 15:59:36 -08001701 if (ndm->ndm_flags & NTF_PROXY) {
1702 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703
WANG Congd7480fd2014-11-10 15:59:36 -08001704 err = -ENOBUFS;
1705 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1706 if (pn) {
1707 pn->flags = ndm->ndm_flags;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001708 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001709 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001710 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 }
1712
WANG Congd7480fd2014-11-10 15:59:36 -08001713 if (dev == NULL)
1714 goto out;
1715
1716 neigh = neigh_lookup(tbl, dst, dev);
1717 if (neigh == NULL) {
1718 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1719 err = -ENOENT;
1720 goto out;
1721 }
1722
1723 neigh = __neigh_lookup_errno(tbl, dst, dev);
1724 if (IS_ERR(neigh)) {
1725 err = PTR_ERR(neigh);
1726 goto out;
1727 }
1728 } else {
1729 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1730 err = -EEXIST;
1731 neigh_release(neigh);
1732 goto out;
1733 }
1734
1735 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1736 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1737 }
1738
1739 if (ndm->ndm_flags & NTF_USE) {
1740 neigh_event_send(neigh, NULL);
1741 err = 0;
1742 } else
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001743 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1744 NETLINK_CB(skb).portid);
WANG Congd7480fd2014-11-10 15:59:36 -08001745 neigh_release(neigh);
1746
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747out:
1748 return err;
1749}
1750
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001751static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1752{
Thomas Grafca860fb2006-08-07 18:00:18 -07001753 struct nlattr *nest;
1754
1755 nest = nla_nest_start(skb, NDTA_PARMS);
1756 if (nest == NULL)
1757 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001758
David S. Miller9a6308d2012-04-01 20:06:28 -04001759 if ((parms->dev &&
1760 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1761 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001762 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1763 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001764 /* approximative value for deprecated QUEUE_LEN (in packets) */
1765 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001766 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1767 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1768 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1769 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1770 NEIGH_VAR(parms, UCAST_PROBES)) ||
1771 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1772 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001773 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1774 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001775 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1776 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001777 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001778 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001779 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001780 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001781 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001782 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001783 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001784 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001785 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001786 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001787 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001788 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001789 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001790 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001791 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001792 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001793
Thomas Grafca860fb2006-08-07 18:00:18 -07001794nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001795 nla_nest_cancel(skb, nest);
1796 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001797}
1798
Thomas Grafca860fb2006-08-07 18:00:18 -07001799static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1800 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001801{
1802 struct nlmsghdr *nlh;
1803 struct ndtmsg *ndtmsg;
1804
Thomas Grafca860fb2006-08-07 18:00:18 -07001805 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1806 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001807 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001808
Thomas Grafca860fb2006-08-07 18:00:18 -07001809 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001810
1811 read_lock_bh(&tbl->lock);
1812 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001813 ndtmsg->ndtm_pad1 = 0;
1814 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001815
David S. Miller9a6308d2012-04-01 20:06:28 -04001816 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001817 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001818 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1819 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1820 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1821 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001822 {
1823 unsigned long now = jiffies;
1824 unsigned int flush_delta = now - tbl->last_flush;
1825 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001826 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001827 struct ndt_config ndc = {
1828 .ndtc_key_len = tbl->key_len,
1829 .ndtc_entry_size = tbl->entry_size,
1830 .ndtc_entries = atomic_read(&tbl->entries),
1831 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1832 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001833 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1834 };
1835
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001836 rcu_read_lock_bh();
1837 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001838 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001839 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001840 rcu_read_unlock_bh();
1841
David S. Miller9a6308d2012-04-01 20:06:28 -04001842 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1843 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001844 }
1845
1846 {
1847 int cpu;
1848 struct ndt_stats ndst;
1849
1850 memset(&ndst, 0, sizeof(ndst));
1851
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001852 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001853 struct neigh_statistics *st;
1854
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001855 st = per_cpu_ptr(tbl->stats, cpu);
1856 ndst.ndts_allocs += st->allocs;
1857 ndst.ndts_destroys += st->destroys;
1858 ndst.ndts_hash_grows += st->hash_grows;
1859 ndst.ndts_res_failed += st->res_failed;
1860 ndst.ndts_lookups += st->lookups;
1861 ndst.ndts_hits += st->hits;
1862 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1863 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1864 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1865 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07001866 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001867 }
1868
Nicolas Dichtelb6763382016-04-26 10:06:17 +02001869 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
1870 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04001871 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001872 }
1873
1874 BUG_ON(tbl->parms.dev);
1875 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001876 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001877
1878 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001879 nlmsg_end(skb, nlh);
1880 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001881
Thomas Grafca860fb2006-08-07 18:00:18 -07001882nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001883 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001884 nlmsg_cancel(skb, nlh);
1885 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001886}
1887
Thomas Grafca860fb2006-08-07 18:00:18 -07001888static int neightbl_fill_param_info(struct sk_buff *skb,
1889 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001890 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001891 u32 pid, u32 seq, int type,
1892 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001893{
1894 struct ndtmsg *ndtmsg;
1895 struct nlmsghdr *nlh;
1896
Thomas Grafca860fb2006-08-07 18:00:18 -07001897 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1898 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001899 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001900
Thomas Grafca860fb2006-08-07 18:00:18 -07001901 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001902
1903 read_lock_bh(&tbl->lock);
1904 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001905 ndtmsg->ndtm_pad1 = 0;
1906 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001907
Thomas Grafca860fb2006-08-07 18:00:18 -07001908 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1909 neightbl_fill_parms(skb, parms) < 0)
1910 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001911
1912 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01001913 nlmsg_end(skb, nlh);
1914 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07001915errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001916 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001917 nlmsg_cancel(skb, nlh);
1918 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001919}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001920
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001921static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001922 [NDTA_NAME] = { .type = NLA_STRING },
1923 [NDTA_THRESH1] = { .type = NLA_U32 },
1924 [NDTA_THRESH2] = { .type = NLA_U32 },
1925 [NDTA_THRESH3] = { .type = NLA_U32 },
1926 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1927 [NDTA_PARMS] = { .type = NLA_NESTED },
1928};
1929
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001930static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001931 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1932 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1933 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1934 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1935 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1936 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001937 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07001938 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1939 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1940 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1941 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1942 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1943 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1944 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1945};
1946
David Ahernc21ef3e2017-04-16 09:48:24 -07001947static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
1948 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001949{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001950 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001951 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001952 struct ndtmsg *ndtmsg;
1953 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08001954 bool found = false;
1955 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001956
Thomas Graf6b3f8672006-08-07 17:58:53 -07001957 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07001958 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001959 if (err < 0)
1960 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001961
Thomas Graf6b3f8672006-08-07 17:58:53 -07001962 if (tb[NDTA_NAME] == NULL) {
1963 err = -EINVAL;
1964 goto errout;
1965 }
1966
1967 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08001968
1969 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
1970 tbl = neigh_tables[tidx];
1971 if (!tbl)
1972 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001973 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1974 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08001975 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
1976 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001977 break;
WANG Congd7480fd2014-11-10 15:59:36 -08001978 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001979 }
1980
WANG Congd7480fd2014-11-10 15:59:36 -08001981 if (!found)
1982 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001983
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001984 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001985 * We acquire tbl->lock to be nice to the periodic timers and
1986 * make sure they always see a consistent set of values.
1987 */
1988 write_lock_bh(&tbl->lock);
1989
Thomas Graf6b3f8672006-08-07 17:58:53 -07001990 if (tb[NDTA_PARMS]) {
1991 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001992 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001993 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001994
Thomas Graf6b3f8672006-08-07 17:58:53 -07001995 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07001996 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001997 if (err < 0)
1998 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001999
Thomas Graf6b3f8672006-08-07 17:58:53 -07002000 if (tbp[NDTPA_IFINDEX])
2001 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002003 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002004 if (p == NULL) {
2005 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002006 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002007 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002008
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 for (i = 1; i <= NDTPA_MAX; i++) {
2010 if (tbp[i] == NULL)
2011 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002012
Thomas Graf6b3f8672006-08-07 17:58:53 -07002013 switch (i) {
2014 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002015 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2016 nla_get_u32(tbp[i]) *
2017 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002018 break;
2019 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002020 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2021 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002022 break;
2023 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002024 NEIGH_VAR_SET(p, PROXY_QLEN,
2025 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002026 break;
2027 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002028 NEIGH_VAR_SET(p, APP_PROBES,
2029 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002030 break;
2031 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002032 NEIGH_VAR_SET(p, UCAST_PROBES,
2033 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002034 break;
2035 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002036 NEIGH_VAR_SET(p, MCAST_PROBES,
2037 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002038 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002039 case NDTPA_MCAST_REPROBES:
2040 NEIGH_VAR_SET(p, MCAST_REPROBES,
2041 nla_get_u32(tbp[i]));
2042 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002043 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002044 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2045 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002046 /* update reachable_time as well, otherwise, the change will
2047 * only be effective after the next time neigh_periodic_work
2048 * decides to recompute it (can be multiple minutes)
2049 */
2050 p->reachable_time =
2051 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002052 break;
2053 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002054 NEIGH_VAR_SET(p, GC_STALETIME,
2055 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002056 break;
2057 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002058 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2059 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002060 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002061 break;
2062 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002063 NEIGH_VAR_SET(p, RETRANS_TIME,
2064 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002065 break;
2066 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002067 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2068 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002069 break;
2070 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002071 NEIGH_VAR_SET(p, PROXY_DELAY,
2072 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002073 break;
2074 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002075 NEIGH_VAR_SET(p, LOCKTIME,
2076 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002077 break;
2078 }
2079 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002080 }
2081
Gao fengdc25c672013-06-20 10:01:34 +08002082 err = -ENOENT;
2083 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2084 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2085 !net_eq(net, &init_net))
2086 goto errout_tbl_lock;
2087
Thomas Graf6b3f8672006-08-07 17:58:53 -07002088 if (tb[NDTA_THRESH1])
2089 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2090
2091 if (tb[NDTA_THRESH2])
2092 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2093
2094 if (tb[NDTA_THRESH3])
2095 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2096
2097 if (tb[NDTA_GC_INTERVAL])
2098 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2099
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002100 err = 0;
2101
Thomas Graf6b3f8672006-08-07 17:58:53 -07002102errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002103 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002104errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002105 return err;
2106}
2107
Thomas Grafc8822a42007-03-22 11:50:06 -07002108static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002109{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002110 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002111 int family, tidx, nidx = 0;
2112 int tbl_skip = cb->args[0];
2113 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002114 struct neigh_table *tbl;
2115
Thomas Grafca860fb2006-08-07 18:00:18 -07002116 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002117
WANG Congd7480fd2014-11-10 15:59:36 -08002118 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002119 struct neigh_parms *p;
2120
WANG Congd7480fd2014-11-10 15:59:36 -08002121 tbl = neigh_tables[tidx];
2122 if (!tbl)
2123 continue;
2124
Thomas Grafca860fb2006-08-07 18:00:18 -07002125 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002126 continue;
2127
Eric W. Biederman15e47302012-09-07 20:12:54 +00002128 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002129 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002130 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002131 break;
2132
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002133 nidx = 0;
2134 p = list_next_entry(&tbl->parms, list);
2135 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002136 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002137 continue;
2138
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002139 if (nidx < neigh_skip)
2140 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002141
Thomas Grafca860fb2006-08-07 18:00:18 -07002142 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002143 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002144 cb->nlh->nlmsg_seq,
2145 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002146 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002147 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002148 next:
2149 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002150 }
2151
Thomas Grafca860fb2006-08-07 18:00:18 -07002152 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002153 }
2154out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002155 cb->args[0] = tidx;
2156 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002157
2158 return skb->len;
2159}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Thomas Graf8b8aec52006-08-07 17:56:37 -07002161static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2162 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
2164 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002166 struct nlmsghdr *nlh;
2167 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Thomas Graf8b8aec52006-08-07 17:56:37 -07002169 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2170 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002171 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002172
2173 ndm = nlmsg_data(nlh);
2174 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002175 ndm->ndm_pad1 = 0;
2176 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002177 ndm->ndm_flags = neigh->flags;
2178 ndm->ndm_type = neigh->type;
2179 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
David S. Miller9a6308d2012-04-01 20:06:28 -04002181 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2182 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002183
2184 read_lock_bh(&neigh->lock);
2185 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002186 if (neigh->nud_state & NUD_VALID) {
2187 char haddr[MAX_ADDR_LEN];
2188
2189 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2190 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2191 read_unlock_bh(&neigh->lock);
2192 goto nla_put_failure;
2193 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002194 }
2195
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002196 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2197 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2198 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2200 read_unlock_bh(&neigh->lock);
2201
David S. Miller9a6308d2012-04-01 20:06:28 -04002202 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2203 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2204 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002205
Johannes Berg053c0952015-01-16 22:09:00 +01002206 nlmsg_end(skb, nlh);
2207 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002208
2209nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002210 nlmsg_cancel(skb, nlh);
2211 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212}
2213
Tony Zelenoff84920c12012-01-26 22:28:58 +00002214static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2215 u32 pid, u32 seq, int type, unsigned int flags,
2216 struct neigh_table *tbl)
2217{
2218 struct nlmsghdr *nlh;
2219 struct ndmsg *ndm;
2220
2221 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2222 if (nlh == NULL)
2223 return -EMSGSIZE;
2224
2225 ndm = nlmsg_data(nlh);
2226 ndm->ndm_family = tbl->family;
2227 ndm->ndm_pad1 = 0;
2228 ndm->ndm_pad2 = 0;
2229 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002230 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002231 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002232 ndm->ndm_state = NUD_NONE;
2233
David S. Miller9a6308d2012-04-01 20:06:28 -04002234 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2235 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002236
Johannes Berg053c0952015-01-16 22:09:00 +01002237 nlmsg_end(skb, nlh);
2238 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002239
2240nla_put_failure:
2241 nlmsg_cancel(skb, nlh);
2242 return -EMSGSIZE;
2243}
2244
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002245static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002246{
2247 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002248 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002249}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250
David Ahern21fdd092015-09-29 09:32:03 -07002251static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2252{
2253 struct net_device *master;
2254
2255 if (!master_idx)
2256 return false;
2257
2258 master = netdev_master_upper_dev_get(dev);
2259 if (!master || master->ifindex != master_idx)
2260 return true;
2261
2262 return false;
2263}
2264
David Ahern16660f02015-10-03 11:43:46 -07002265static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2266{
2267 if (filter_idx && dev->ifindex != filter_idx)
2268 return true;
2269
2270 return false;
2271}
2272
Linus Torvalds1da177e2005-04-16 15:20:36 -07002273static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2274 struct netlink_callback *cb)
2275{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002276 struct net *net = sock_net(skb->sk);
David Ahern21fdd092015-09-29 09:32:03 -07002277 const struct nlmsghdr *nlh = cb->nlh;
2278 struct nlattr *tb[NDA_MAX + 1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279 struct neighbour *n;
2280 int rc, h, s_h = cb->args[1];
2281 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002282 struct neigh_hash_table *nht;
David Ahern16660f02015-10-03 11:43:46 -07002283 int filter_master_idx = 0, filter_idx = 0;
David Ahern21fdd092015-09-29 09:32:03 -07002284 unsigned int flags = NLM_F_MULTI;
2285 int err;
2286
Johannes Bergfceb6432017-04-12 14:34:07 +02002287 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
David Ahern21fdd092015-09-29 09:32:03 -07002288 if (!err) {
David Ahern16660f02015-10-03 11:43:46 -07002289 if (tb[NDA_IFINDEX])
2290 filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2291
David Ahern21fdd092015-09-29 09:32:03 -07002292 if (tb[NDA_MASTER])
2293 filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2294
David Ahern16660f02015-10-03 11:43:46 -07002295 if (filter_idx || filter_master_idx)
David Ahern21fdd092015-09-29 09:32:03 -07002296 flags |= NLM_F_DUMP_FILTERED;
2297 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002299 rcu_read_lock_bh();
2300 nht = rcu_dereference_bh(tbl->nht);
2301
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002302 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303 if (h > s_h)
2304 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002305 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2306 n != NULL;
2307 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002308 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2309 goto next;
2310 if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2311 neigh_master_filtered(n->dev, filter_master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002312 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002313 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002315 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002316 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 rc = -1;
2318 goto out;
2319 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002320next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002321 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 }
2324 rc = skb->len;
2325out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002326 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002327 cb->args[1] = h;
2328 cb->args[2] = idx;
2329 return rc;
2330}
2331
Tony Zelenoff84920c12012-01-26 22:28:58 +00002332static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2333 struct netlink_callback *cb)
2334{
2335 struct pneigh_entry *n;
2336 struct net *net = sock_net(skb->sk);
2337 int rc, h, s_h = cb->args[3];
2338 int idx, s_idx = idx = cb->args[4];
2339
2340 read_lock_bh(&tbl->lock);
2341
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002342 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002343 if (h > s_h)
2344 s_idx = 0;
2345 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002346 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002347 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002348 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002349 cb->nlh->nlmsg_seq,
2350 RTM_NEWNEIGH,
David S. Miller7b46a642015-01-18 23:36:08 -05002351 NLM_F_MULTI, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002352 read_unlock_bh(&tbl->lock);
2353 rc = -1;
2354 goto out;
2355 }
2356 next:
2357 idx++;
2358 }
2359 }
2360
2361 read_unlock_bh(&tbl->lock);
2362 rc = skb->len;
2363out:
2364 cb->args[3] = h;
2365 cb->args[4] = idx;
2366 return rc;
2367
2368}
2369
Thomas Grafc8822a42007-03-22 11:50:06 -07002370static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371{
2372 struct neigh_table *tbl;
2373 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002374 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002375 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002376
Thomas Graf8b8aec52006-08-07 17:56:37 -07002377 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002378
2379 /* check for full ndmsg structure presence, family member is
2380 * the same for both structures
2381 */
2382 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2383 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2384 proxy = 1;
2385
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 s_t = cb->args[0];
2387
WANG Congd7480fd2014-11-10 15:59:36 -08002388 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2389 tbl = neigh_tables[t];
2390
2391 if (!tbl)
2392 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002393 if (t < s_t || (family && tbl->family != family))
2394 continue;
2395 if (t > s_t)
2396 memset(&cb->args[1], 0, sizeof(cb->args) -
2397 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002398 if (proxy)
2399 err = pneigh_dump_table(tbl, skb, cb);
2400 else
2401 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002402 if (err < 0)
2403 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
2406 cb->args[0] = t;
2407 return skb->len;
2408}
2409
2410void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2411{
2412 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002413 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002415 rcu_read_lock_bh();
2416 nht = rcu_dereference_bh(tbl->nht);
2417
Eric Dumazet767e97e2010-10-06 17:49:21 -07002418 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002419 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420 struct neighbour *n;
2421
Eric Dumazet767e97e2010-10-06 17:49:21 -07002422 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2423 n != NULL;
2424 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425 cb(n, cookie);
2426 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002427 read_unlock(&tbl->lock);
2428 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429}
2430EXPORT_SYMBOL(neigh_for_each);
2431
2432/* The tbl->lock must be held as a writer and BH disabled. */
2433void __neigh_for_each_release(struct neigh_table *tbl,
2434 int (*cb)(struct neighbour *))
2435{
2436 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002437 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002439 nht = rcu_dereference_protected(tbl->nht,
2440 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002441 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002442 struct neighbour *n;
2443 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002445 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002446 while ((n = rcu_dereference_protected(*np,
2447 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448 int release;
2449
2450 write_lock(&n->lock);
2451 release = cb(n);
2452 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002453 rcu_assign_pointer(*np,
2454 rcu_dereference_protected(n->next,
2455 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456 n->dead = 1;
2457 } else
2458 np = &n->next;
2459 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002460 if (release)
2461 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002462 }
2463 }
2464}
2465EXPORT_SYMBOL(__neigh_for_each_release);
2466
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002467int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002468 const void *addr, struct sk_buff *skb)
2469{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002470 int err = -EAFNOSUPPORT;
2471 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002472 struct neigh_table *tbl;
2473 struct neighbour *neigh;
2474
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002475 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002476 if (!tbl)
2477 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002478 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002479 neigh = __neigh_lookup_noref(tbl, addr, dev);
2480 if (!neigh)
2481 neigh = __neigh_create(tbl, addr, dev, false);
2482 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002483 if (IS_ERR(neigh)) {
2484 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002485 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002486 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002487 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002488 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002489 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002490 else if (index == NEIGH_LINK_TABLE) {
2491 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2492 addr, NULL, skb->len);
2493 if (err < 0)
2494 goto out_kfree_skb;
2495 err = dev_queue_xmit(skb);
2496 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002497out:
2498 return err;
2499out_kfree_skb:
2500 kfree_skb(skb);
2501 goto out;
2502}
2503EXPORT_SYMBOL(neigh_xmit);
2504
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505#ifdef CONFIG_PROC_FS
2506
2507static struct neighbour *neigh_get_first(struct seq_file *seq)
2508{
2509 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002510 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002511 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002512 struct neighbour *n = NULL;
2513 int bucket = state->bucket;
2514
2515 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002516 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002517 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518
2519 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002520 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002521 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 if (state->neigh_sub_iter) {
2523 loff_t fakep = 0;
2524 void *v;
2525
2526 v = state->neigh_sub_iter(state, n, &fakep);
2527 if (!v)
2528 goto next;
2529 }
2530 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2531 break;
2532 if (n->nud_state & ~NUD_NOARP)
2533 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002534next:
2535 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536 }
2537
2538 if (n)
2539 break;
2540 }
2541 state->bucket = bucket;
2542
2543 return n;
2544}
2545
2546static struct neighbour *neigh_get_next(struct seq_file *seq,
2547 struct neighbour *n,
2548 loff_t *pos)
2549{
2550 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002551 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002552 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553
2554 if (state->neigh_sub_iter) {
2555 void *v = state->neigh_sub_iter(state, n, pos);
2556 if (v)
2557 return n;
2558 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002559 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560
2561 while (1) {
2562 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002563 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002564 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 if (state->neigh_sub_iter) {
2566 void *v = state->neigh_sub_iter(state, n, pos);
2567 if (v)
2568 return n;
2569 goto next;
2570 }
2571 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2572 break;
2573
2574 if (n->nud_state & ~NUD_NOARP)
2575 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002576next:
2577 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 }
2579
2580 if (n)
2581 break;
2582
David S. Millercd089332011-07-11 01:28:12 -07002583 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 break;
2585
Eric Dumazet767e97e2010-10-06 17:49:21 -07002586 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 }
2588
2589 if (n && pos)
2590 --(*pos);
2591 return n;
2592}
2593
2594static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2595{
2596 struct neighbour *n = neigh_get_first(seq);
2597
2598 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002599 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600 while (*pos) {
2601 n = neigh_get_next(seq, n, pos);
2602 if (!n)
2603 break;
2604 }
2605 }
2606 return *pos ? NULL : n;
2607}
2608
2609static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2610{
2611 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002612 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613 struct neigh_table *tbl = state->tbl;
2614 struct pneigh_entry *pn = NULL;
2615 int bucket = state->bucket;
2616
2617 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2618 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2619 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002620 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002621 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002622 if (pn)
2623 break;
2624 }
2625 state->bucket = bucket;
2626
2627 return pn;
2628}
2629
2630static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2631 struct pneigh_entry *pn,
2632 loff_t *pos)
2633{
2634 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002635 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636 struct neigh_table *tbl = state->tbl;
2637
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002638 do {
2639 pn = pn->next;
2640 } while (pn && !net_eq(pneigh_net(pn), net));
2641
Linus Torvalds1da177e2005-04-16 15:20:36 -07002642 while (!pn) {
2643 if (++state->bucket > PNEIGH_HASHMASK)
2644 break;
2645 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002646 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002647 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 if (pn)
2649 break;
2650 }
2651
2652 if (pn && pos)
2653 --(*pos);
2654
2655 return pn;
2656}
2657
2658static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2659{
2660 struct pneigh_entry *pn = pneigh_get_first(seq);
2661
2662 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002663 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 while (*pos) {
2665 pn = pneigh_get_next(seq, pn, pos);
2666 if (!pn)
2667 break;
2668 }
2669 }
2670 return *pos ? NULL : pn;
2671}
2672
2673static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2674{
2675 struct neigh_seq_state *state = seq->private;
2676 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002677 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678
Chris Larson745e2032008-08-03 01:10:55 -07002679 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002681 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
2683 return rc;
2684}
2685
2686void *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 +00002687 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688{
2689 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
2691 state->tbl = tbl;
2692 state->bucket = 0;
2693 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2694
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002695 rcu_read_lock_bh();
2696 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002697
Chris Larson745e2032008-08-03 01:10:55 -07002698 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002699}
2700EXPORT_SYMBOL(neigh_seq_start);
2701
2702void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2703{
2704 struct neigh_seq_state *state;
2705 void *rc;
2706
2707 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002708 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 goto out;
2710 }
2711
2712 state = seq->private;
2713 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2714 rc = neigh_get_next(seq, v, NULL);
2715 if (rc)
2716 goto out;
2717 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2718 rc = pneigh_get_first(seq);
2719 } else {
2720 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2721 rc = pneigh_get_next(seq, v, NULL);
2722 }
2723out:
2724 ++(*pos);
2725 return rc;
2726}
2727EXPORT_SYMBOL(neigh_seq_next);
2728
2729void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002730 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002731{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002732 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002733}
2734EXPORT_SYMBOL(neigh_seq_stop);
2735
2736/* statistics via seq_file */
2737
2738static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2739{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002740 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002741 int cpu;
2742
2743 if (*pos == 0)
2744 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002745
Rusty Russell0f23174a2008-12-29 12:23:42 +00002746 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002747 if (!cpu_possible(cpu))
2748 continue;
2749 *pos = cpu+1;
2750 return per_cpu_ptr(tbl->stats, cpu);
2751 }
2752 return NULL;
2753}
2754
2755static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2756{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002757 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 int cpu;
2759
Rusty Russell0f23174a2008-12-29 12:23:42 +00002760 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002761 if (!cpu_possible(cpu))
2762 continue;
2763 *pos = cpu+1;
2764 return per_cpu_ptr(tbl->stats, cpu);
2765 }
2766 return NULL;
2767}
2768
2769static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2770{
2771
2772}
2773
2774static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2775{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002776 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002777 struct neigh_statistics *st = v;
2778
2779 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07002780 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 -07002781 return 0;
2782 }
2783
2784 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07002785 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 atomic_read(&tbl->entries),
2787
2788 st->allocs,
2789 st->destroys,
2790 st->hash_grows,
2791
2792 st->lookups,
2793 st->hits,
2794
2795 st->res_failed,
2796
2797 st->rcv_probes_mcast,
2798 st->rcv_probes_ucast,
2799
2800 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002801 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07002802 st->unres_discards,
2803 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07002804 );
2805
2806 return 0;
2807}
2808
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002809static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002810 .start = neigh_stat_seq_start,
2811 .next = neigh_stat_seq_next,
2812 .stop = neigh_stat_seq_stop,
2813 .show = neigh_stat_seq_show,
2814};
2815
2816static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2817{
2818 int ret = seq_open(file, &neigh_stat_seq_ops);
2819
2820 if (!ret) {
2821 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002822 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002823 }
2824 return ret;
2825};
2826
Arjan van de Ven9a321442007-02-12 00:55:35 -08002827static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002828 .owner = THIS_MODULE,
2829 .open = neigh_stat_seq_open,
2830 .read = seq_read,
2831 .llseek = seq_lseek,
2832 .release = seq_release,
2833};
2834
2835#endif /* CONFIG_PROC_FS */
2836
Thomas Graf339bf982006-11-10 14:10:15 -08002837static inline size_t neigh_nlmsg_size(void)
2838{
2839 return NLMSG_ALIGN(sizeof(struct ndmsg))
2840 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2841 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2842 + nla_total_size(sizeof(struct nda_cacheinfo))
2843 + nla_total_size(4); /* NDA_PROBES */
2844}
2845
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002846static void __neigh_notify(struct neighbour *n, int type, int flags,
2847 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002849 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002850 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002851 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002852
Thomas Graf339bf982006-11-10 14:10:15 -08002853 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002854 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002855 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002856
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002857 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002858 if (err < 0) {
2859 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2860 WARN_ON(err == -EMSGSIZE);
2861 kfree_skb(skb);
2862 goto errout;
2863 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002864 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2865 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002866errout:
2867 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002868 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002869}
2870
2871void neigh_app_ns(struct neighbour *n)
2872{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002873 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002874}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002875EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002876
2877#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002878static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002879static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002880static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002881
Joe Perchesfe2c6332013-06-11 23:04:25 -07002882static int proc_unres_qlen(struct ctl_table *ctl, int write,
2883 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002884{
2885 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002886 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002887
Shan Weice46cc62012-12-04 18:49:15 +00002888 tmp.extra1 = &zero;
2889 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002890 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002891
2892 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2893 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2894
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002895 if (write && !ret)
2896 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2897 return ret;
2898}
2899
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002900static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2901 int family)
2902{
Jiri Pirkobba24892013-12-07 19:26:57 +01002903 switch (family) {
2904 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002905 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01002906 case AF_INET6:
2907 return __in6_dev_nd_parms_get_rcu(dev);
2908 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002909 return NULL;
2910}
2911
2912static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2913 int index)
2914{
2915 struct net_device *dev;
2916 int family = neigh_parms_family(p);
2917
2918 rcu_read_lock();
2919 for_each_netdev_rcu(net, dev) {
2920 struct neigh_parms *dst_p =
2921 neigh_get_dev_parms_rcu(dev, family);
2922
2923 if (dst_p && !test_bit(index, dst_p->data_state))
2924 dst_p->data[index] = p->data[index];
2925 }
2926 rcu_read_unlock();
2927}
2928
2929static void neigh_proc_update(struct ctl_table *ctl, int write)
2930{
2931 struct net_device *dev = ctl->extra1;
2932 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01002933 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002934 int index = (int *) ctl->data - p->data;
2935
2936 if (!write)
2937 return;
2938
2939 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01002940 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
2941 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002942 if (!dev) /* NULL dev means this is default value */
2943 neigh_copy_dflt_parms(net, p, index);
2944}
2945
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002946static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2947 void __user *buffer,
2948 size_t *lenp, loff_t *ppos)
2949{
2950 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002951 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002952
2953 tmp.extra1 = &zero;
2954 tmp.extra2 = &int_max;
2955
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002956 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2957 neigh_proc_update(ctl, write);
2958 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002959}
2960
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002961int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2962 void __user *buffer, size_t *lenp, loff_t *ppos)
2963{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002964 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2965
2966 neigh_proc_update(ctl, write);
2967 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002968}
2969EXPORT_SYMBOL(neigh_proc_dointvec);
2970
2971int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2972 void __user *buffer,
2973 size_t *lenp, loff_t *ppos)
2974{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002975 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2976
2977 neigh_proc_update(ctl, write);
2978 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002979}
2980EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2981
2982static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2983 void __user *buffer,
2984 size_t *lenp, loff_t *ppos)
2985{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002986 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2987
2988 neigh_proc_update(ctl, write);
2989 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002990}
2991
2992int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2993 void __user *buffer,
2994 size_t *lenp, loff_t *ppos)
2995{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002996 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2997
2998 neigh_proc_update(ctl, write);
2999 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003000}
3001EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3002
3003static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3004 void __user *buffer,
3005 size_t *lenp, loff_t *ppos)
3006{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003007 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3008
3009 neigh_proc_update(ctl, write);
3010 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003011}
3012
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003013static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3014 void __user *buffer,
3015 size_t *lenp, loff_t *ppos)
3016{
3017 struct neigh_parms *p = ctl->extra2;
3018 int ret;
3019
3020 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3021 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3022 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3023 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3024 else
3025 ret = -1;
3026
3027 if (write && ret == 0) {
3028 /* update reachable_time as well, otherwise, the change will
3029 * only be effective after the next time neigh_periodic_work
3030 * decides to recompute it
3031 */
3032 p->reachable_time =
3033 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3034 }
3035 return ret;
3036}
3037
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003038#define NEIGH_PARMS_DATA_OFFSET(index) \
3039 (&((struct neigh_parms *) 0)->data[index])
3040
3041#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3042 [NEIGH_VAR_ ## attr] = { \
3043 .procname = name, \
3044 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3045 .maxlen = sizeof(int), \
3046 .mode = mval, \
3047 .proc_handler = proc, \
3048 }
3049
3050#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3051 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3052
3053#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003054 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003055
3056#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003057 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003058
3059#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003060 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003061
3062#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003063 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003064
3065#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003066 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003067
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068static struct neigh_sysctl_table {
3069 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003070 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003071} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003072 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003073 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3074 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3075 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003076 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003077 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3078 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3079 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3080 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3081 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3082 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3083 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3084 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3085 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3086 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3087 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3088 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003089 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003090 .procname = "gc_interval",
3091 .maxlen = sizeof(int),
3092 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003093 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003095 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 .procname = "gc_thresh1",
3097 .maxlen = sizeof(int),
3098 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003099 .extra1 = &zero,
3100 .extra2 = &int_max,
3101 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003103 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 .procname = "gc_thresh2",
3105 .maxlen = sizeof(int),
3106 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003107 .extra1 = &zero,
3108 .extra2 = &int_max,
3109 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003111 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003112 .procname = "gc_thresh3",
3113 .maxlen = sizeof(int),
3114 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003115 .extra1 = &zero,
3116 .extra2 = &int_max,
3117 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003119 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003120 },
3121};
3122
3123int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003124 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003126 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003127 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003128 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003129 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003130 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003131
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003132 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003134 goto err;
3135
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003136 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003137 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003138 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003139 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141
3142 if (dev) {
3143 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003144 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003145 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3146 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003147 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003148 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003149 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003150 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3151 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3152 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3153 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003154 }
3155
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003156 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003158 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003159 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003160 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003162 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003164 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003165 } else {
3166 /* Those handlers will update p->reachable_time after
3167 * base_reachable_time(_ms) is set to ensure the new timer starts being
3168 * applied after the next neighbour update instead of waiting for
3169 * neigh_periodic_work to update its value (can be multiple minutes)
3170 * So any handler that replaces them should do this as well
3171 */
3172 /* ReachableTime */
3173 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3174 neigh_proc_base_reachable_time;
3175 /* ReachableTime (in milliseconds) */
3176 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3177 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 }
3179
Eric W. Biederman464dc802012-11-16 03:02:59 +00003180 /* Don't export sysctls to unprivileged users */
3181 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3182 t->neigh_vars[0].procname = NULL;
3183
Jiri Pirko73af6142013-12-07 19:26:55 +01003184 switch (neigh_parms_family(p)) {
3185 case AF_INET:
3186 p_name = "ipv4";
3187 break;
3188 case AF_INET6:
3189 p_name = "ipv6";
3190 break;
3191 default:
3192 BUG();
3193 }
3194
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003195 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3196 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003197 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003198 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003199 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003200 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003201
Linus Torvalds1da177e2005-04-16 15:20:36 -07003202 p->sysctl_table = t;
3203 return 0;
3204
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003205free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003206 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003207err:
3208 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003209}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003210EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003211
3212void neigh_sysctl_unregister(struct neigh_parms *p)
3213{
3214 if (p->sysctl_table) {
3215 struct neigh_sysctl_table *t = p->sysctl_table;
3216 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003217 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003218 kfree(t);
3219 }
3220}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003221EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222
3223#endif /* CONFIG_SYSCTL */
3224
Thomas Grafc8822a42007-03-22 11:50:06 -07003225static int __init neigh_init(void)
3226{
Greg Rosec7ac8672011-06-10 01:27:09 +00003227 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3228 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3229 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003230
Greg Rosec7ac8672011-06-10 01:27:09 +00003231 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3232 NULL);
3233 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003234
3235 return 0;
3236}
3237
3238subsys_initcall(neigh_init);
3239