blob: 43687c9abe1dfae19bbe05d4f21f8a05a4960104 [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
Kees Cooke99e88a2017-10-16 14:43:17 -070054static void neigh_timer_handler(struct timer_list *t);
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);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +020058static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
59 struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070060
Amos Waterland45fc3b12005-09-24 16:53:16 -070061#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +020062static const struct seq_operations neigh_stat_seq_ops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070063#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070064
65/*
66 Neighbour hash table buckets are protected with rwlock tbl->lock.
67
68 - All the scans/updates to hash buckets MUST be made under this lock.
69 - NOTHING clever should be made under this lock: no callbacks
70 to protocol backends, no attempts to send something to network.
71 It will result in deadlocks, if backend/driver wants to use neighbour
72 cache.
73 - If the entry requires some non-trivial actions, increase
74 its reference count and release table lock.
75
76 Neighbour entries are protected:
77 - with reference count.
78 - with rwlock neigh->lock
79
80 Reference count prevents destruction.
81
82 neigh->lock mainly serializes ll address data and its validity state.
83 However, the same lock is used to protect another entry fields:
84 - timer
85 - resolution queue
86
87 Again, nothing clever shall be made under neigh->lock,
88 the most complicated procedure, which we allow is dev->hard_header.
89 It is supposed, that dev->hard_header is simplistic and does
90 not make callbacks to neighbour tables.
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 */
92
David S. Miller8f40b162011-07-17 13:34:11 -070093static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094{
95 kfree_skb(skb);
96 return -ENETDOWN;
97}
98
Thomas Graf4f494552007-08-08 23:12:36 -070099static void neigh_cleanup_and_release(struct neighbour *neigh)
100{
101 if (neigh->parms->neigh_cleanup)
102 neigh->parms->neigh_cleanup(neigh);
103
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700104 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100105 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Thomas Graf4f494552007-08-08 23:12:36 -0700106 neigh_release(neigh);
107}
108
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109/*
110 * It is random distribution in the interval (1/2)*base...(3/2)*base.
111 * It corresponds to default IPv6 settings and is not overridable,
112 * because it is really reasonable choice.
113 */
114
115unsigned long neigh_rand_reach_time(unsigned long base)
116{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500117 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900119EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
David Ahern58956312018-12-07 12:24:57 -0800121static void neigh_mark_dead(struct neighbour *n)
122{
123 n->dead = 1;
124 if (!list_empty(&n->gc_list)) {
125 list_del_init(&n->gc_list);
126 atomic_dec(&n->tbl->gc_entries);
127 }
128}
129
David Ahern9c29a2f2018-12-11 18:57:21 -0700130static void neigh_update_gc_list(struct neighbour *n)
David Ahern58956312018-12-07 12:24:57 -0800131{
David Aherne997f8a2018-12-11 18:57:25 -0700132 bool on_gc_list, exempt_from_gc;
David Ahern58956312018-12-07 12:24:57 -0800133
David Ahern9c29a2f2018-12-11 18:57:21 -0700134 write_lock_bh(&n->tbl->lock);
135 write_lock(&n->lock);
David Ahern58956312018-12-07 12:24:57 -0800136
David Aherne997f8a2018-12-11 18:57:25 -0700137 /* remove from the gc list if new state is permanent or if neighbor
138 * is externally learned; otherwise entry should be on the gc list
David Ahern58956312018-12-07 12:24:57 -0800139 */
David Aherne997f8a2018-12-11 18:57:25 -0700140 exempt_from_gc = n->nud_state & NUD_PERMANENT ||
141 n->flags & NTF_EXT_LEARNED;
David Ahern9c29a2f2018-12-11 18:57:21 -0700142 on_gc_list = !list_empty(&n->gc_list);
David Ahern8cc196d2018-12-10 13:54:07 -0800143
David Aherne997f8a2018-12-11 18:57:25 -0700144 if (exempt_from_gc && on_gc_list) {
David Ahern9c29a2f2018-12-11 18:57:21 -0700145 list_del_init(&n->gc_list);
David Ahern58956312018-12-07 12:24:57 -0800146 atomic_dec(&n->tbl->gc_entries);
David Aherne997f8a2018-12-11 18:57:25 -0700147 } else if (!exempt_from_gc && !on_gc_list) {
David Ahern58956312018-12-07 12:24:57 -0800148 /* add entries to the tail; cleaning removes from the front */
149 list_add_tail(&n->gc_list, &n->tbl->gc_list);
150 atomic_inc(&n->tbl->gc_entries);
151 }
David Ahern9c29a2f2018-12-11 18:57:21 -0700152
153 write_unlock(&n->lock);
154 write_unlock_bh(&n->tbl->lock);
David Ahern58956312018-12-07 12:24:57 -0800155}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
David Aherne997f8a2018-12-11 18:57:25 -0700157static bool neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
David Ahern526f1b52018-12-11 18:57:24 -0700158 int *notify)
159{
David Aherne997f8a2018-12-11 18:57:25 -0700160 bool rc = false;
David Ahern526f1b52018-12-11 18:57:24 -0700161 u8 ndm_flags;
162
163 if (!(flags & NEIGH_UPDATE_F_ADMIN))
David Aherne997f8a2018-12-11 18:57:25 -0700164 return rc;
David Ahern526f1b52018-12-11 18:57:24 -0700165
166 ndm_flags = (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0;
167 if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) {
168 if (ndm_flags & NTF_EXT_LEARNED)
169 neigh->flags |= NTF_EXT_LEARNED;
170 else
171 neigh->flags &= ~NTF_EXT_LEARNED;
David Aherne997f8a2018-12-11 18:57:25 -0700172 rc = true;
David Ahern526f1b52018-12-11 18:57:24 -0700173 *notify = 1;
174 }
David Aherne997f8a2018-12-11 18:57:25 -0700175
176 return rc;
David Ahern526f1b52018-12-11 18:57:24 -0700177}
178
David Ahern7e6f1822018-12-11 18:57:23 -0700179static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np,
180 struct neigh_table *tbl)
Sowmini Varadhan50710342017-06-02 09:01:49 -0700181{
182 bool retval = false;
183
184 write_lock(&n->lock);
David Ahern7e6f1822018-12-11 18:57:23 -0700185 if (refcount_read(&n->refcnt) == 1) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700186 struct neighbour *neigh;
187
188 neigh = rcu_dereference_protected(n->next,
189 lockdep_is_held(&tbl->lock));
190 rcu_assign_pointer(*np, neigh);
David Ahern58956312018-12-07 12:24:57 -0800191 neigh_mark_dead(n);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700192 retval = true;
193 }
194 write_unlock(&n->lock);
195 if (retval)
196 neigh_cleanup_and_release(n);
197 return retval;
198}
199
200bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
201{
202 struct neigh_hash_table *nht;
203 void *pkey = ndel->primary_key;
204 u32 hash_val;
205 struct neighbour *n;
206 struct neighbour __rcu **np;
207
208 nht = rcu_dereference_protected(tbl->nht,
209 lockdep_is_held(&tbl->lock));
210 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
211 hash_val = hash_val >> (32 - nht->hash_shift);
212
213 np = &nht->hash_buckets[hash_val];
214 while ((n = rcu_dereference_protected(*np,
215 lockdep_is_held(&tbl->lock)))) {
216 if (n == ndel)
David Ahern7e6f1822018-12-11 18:57:23 -0700217 return neigh_del(n, np, tbl);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700218 np = &n->next;
219 }
220 return false;
221}
222
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223static int neigh_forced_gc(struct neigh_table *tbl)
224{
David Ahern58956312018-12-07 12:24:57 -0800225 int max_clean = atomic_read(&tbl->gc_entries) - tbl->gc_thresh2;
226 unsigned long tref = jiffies - 5 * HZ;
David Ahern58956312018-12-07 12:24:57 -0800227 struct neighbour *n, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228 int shrunk = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229
230 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
231
232 write_lock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700233
David Ahern58956312018-12-07 12:24:57 -0800234 list_for_each_entry_safe(n, tmp, &tbl->gc_list, gc_list) {
235 if (refcount_read(&n->refcnt) == 1) {
236 bool remove = false;
237
238 write_lock(&n->lock);
David Ahern758a7f02018-12-11 18:57:22 -0700239 if ((n->nud_state == NUD_FAILED) ||
David Aherne997f8a2018-12-11 18:57:25 -0700240 time_after(tref, n->updated))
David Ahern58956312018-12-07 12:24:57 -0800241 remove = true;
242 write_unlock(&n->lock);
243
244 if (remove && neigh_remove_one(n, tbl))
245 shrunk++;
246 if (shrunk >= max_clean)
247 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700248 }
249 }
250
251 tbl->last_flush = jiffies;
252
253 write_unlock_bh(&tbl->lock);
254
255 return shrunk;
256}
257
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800258static void neigh_add_timer(struct neighbour *n, unsigned long when)
259{
260 neigh_hold(n);
261 if (unlikely(mod_timer(&n->timer, when))) {
262 printk("NEIGH: BUG, double timer add, state is %x\n",
263 n->nud_state);
264 dump_stack();
265 }
266}
267
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268static int neigh_del_timer(struct neighbour *n)
269{
270 if ((n->nud_state & NUD_IN_TIMER) &&
271 del_timer(&n->timer)) {
272 neigh_release(n);
273 return 1;
274 }
275 return 0;
276}
277
278static void pneigh_queue_purge(struct sk_buff_head *list)
279{
280 struct sk_buff *skb;
281
282 while ((skb = skb_dequeue(list)) != NULL) {
283 dev_put(skb->dev);
284 kfree_skb(skb);
285 }
286}
287
David Ahern859bd2e2018-10-11 20:33:49 -0700288static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
289 bool skip_perm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290{
291 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000292 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000294 nht = rcu_dereference_protected(tbl->nht,
295 lockdep_is_held(&tbl->lock));
296
David S. Millercd089332011-07-11 01:28:12 -0700297 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700298 struct neighbour *n;
299 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
Eric Dumazet767e97e2010-10-06 17:49:21 -0700301 while ((n = rcu_dereference_protected(*np,
302 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700303 if (dev && n->dev != dev) {
304 np = &n->next;
305 continue;
306 }
David Ahern859bd2e2018-10-11 20:33:49 -0700307 if (skip_perm && n->nud_state & NUD_PERMANENT) {
308 np = &n->next;
309 continue;
310 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700311 rcu_assign_pointer(*np,
312 rcu_dereference_protected(n->next,
313 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 write_lock(&n->lock);
315 neigh_del_timer(n);
David Ahern58956312018-12-07 12:24:57 -0800316 neigh_mark_dead(n);
Reshetova, Elena9f237432017-06-30 13:07:55 +0300317 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318 /* The most unpleasant situation.
319 We must destroy neighbour entry,
320 but someone still uses it.
321
322 The destroy will be delayed until
323 the last user releases us, but
324 we must kill timers etc. and move
325 it to safe state.
326 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700327 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000328 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700329 n->output = neigh_blackhole;
330 if (n->nud_state & NUD_VALID)
331 n->nud_state = NUD_NOARP;
332 else
333 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000334 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335 }
336 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700337 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 }
339 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000340}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341
Herbert Xu49636bb2005-10-23 17:18:00 +1000342void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
343{
344 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700345 neigh_flush_dev(tbl, dev, false);
Herbert Xu49636bb2005-10-23 17:18:00 +1000346 write_unlock_bh(&tbl->lock);
347}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900348EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000349
David Ahern859bd2e2018-10-11 20:33:49 -0700350static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
351 bool skip_perm)
Herbert Xu49636bb2005-10-23 17:18:00 +1000352{
353 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700354 neigh_flush_dev(tbl, dev, skip_perm);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200355 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356
357 del_timer_sync(&tbl->proxy_timer);
358 pneigh_queue_purge(&tbl->proxy_queue);
359 return 0;
360}
David Ahern859bd2e2018-10-11 20:33:49 -0700361
362int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev)
363{
364 __neigh_ifdown(tbl, dev, true);
365 return 0;
366}
367EXPORT_SYMBOL(neigh_carrier_down);
368
369int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
370{
371 __neigh_ifdown(tbl, dev, false);
372 return 0;
373}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900374EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375
David Ahern58956312018-12-07 12:24:57 -0800376static struct neighbour *neigh_alloc(struct neigh_table *tbl,
377 struct net_device *dev,
David Aherne997f8a2018-12-11 18:57:25 -0700378 bool exempt_from_gc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379{
380 struct neighbour *n = NULL;
381 unsigned long now = jiffies;
382 int entries;
383
David Aherne997f8a2018-12-11 18:57:25 -0700384 if (exempt_from_gc)
David Ahern58956312018-12-07 12:24:57 -0800385 goto do_alloc;
386
387 entries = atomic_inc_return(&tbl->gc_entries) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700388 if (entries >= tbl->gc_thresh3 ||
389 (entries >= tbl->gc_thresh2 &&
390 time_after(now, tbl->last_flush + 5 * HZ))) {
391 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700392 entries >= tbl->gc_thresh3) {
393 net_info_ratelimited("%s: neighbor table overflow!\n",
394 tbl->id);
395 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700397 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700398 }
399
David Ahern58956312018-12-07 12:24:57 -0800400do_alloc:
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000401 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 if (!n)
403 goto out_entries;
404
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700405 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000407 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 n->updated = n->used = now;
409 n->nud_state = NUD_NONE;
410 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700411 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700412 n->parms = neigh_parms_clone(&tbl->parms);
Kees Cooke99e88a2017-10-16 14:43:17 -0700413 timer_setup(&n->timer, neigh_timer_handler, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414
415 NEIGH_CACHE_STAT_INC(tbl, allocs);
416 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300417 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 n->dead = 1;
David Ahern8cc196d2018-12-10 13:54:07 -0800419 INIT_LIST_HEAD(&n->gc_list);
David Ahern58956312018-12-07 12:24:57 -0800420
421 atomic_inc(&tbl->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422out:
423 return n;
424
425out_entries:
David Aherne997f8a2018-12-11 18:57:25 -0700426 if (!exempt_from_gc)
David Ahern58956312018-12-07 12:24:57 -0800427 atomic_dec(&tbl->gc_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 goto out;
429}
430
David S. Miller2c2aba62011-12-28 15:06:58 -0500431static void neigh_get_hash_rnd(u32 *x)
432{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400433 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500434}
435
David S. Millercd089332011-07-11 01:28:12 -0700436static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
David S. Millercd089332011-07-11 01:28:12 -0700438 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000439 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000440 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500441 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000443 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
444 if (!ret)
445 return NULL;
446 if (size <= PAGE_SIZE)
447 buckets = kzalloc(size, GFP_ATOMIC);
448 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000449 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000450 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
451 get_order(size));
452 if (!buckets) {
453 kfree(ret);
454 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000456 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700457 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500458 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
459 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460 return ret;
461}
462
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000463static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000465 struct neigh_hash_table *nht = container_of(head,
466 struct neigh_hash_table,
467 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700468 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000469 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000472 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000474 free_pages((unsigned long)buckets, get_order(size));
475 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476}
477
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000478static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700479 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000481 unsigned int i, hash;
482 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
485
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000486 old_nht = rcu_dereference_protected(tbl->nht,
487 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700488 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000489 if (!new_nht)
490 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491
David S. Millercd089332011-07-11 01:28:12 -0700492 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 struct neighbour *n, *next;
494
Eric Dumazet767e97e2010-10-06 17:49:21 -0700495 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
496 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000497 n != NULL;
498 n = next) {
499 hash = tbl->hash(n->primary_key, n->dev,
500 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
David S. Millercd089332011-07-11 01:28:12 -0700502 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700503 next = rcu_dereference_protected(n->next,
504 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505
Eric Dumazet767e97e2010-10-06 17:49:21 -0700506 rcu_assign_pointer(n->next,
507 rcu_dereference_protected(
508 new_nht->hash_buckets[hash],
509 lockdep_is_held(&tbl->lock)));
510 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 }
512 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000514 rcu_assign_pointer(tbl->nht, new_nht);
515 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
516 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517}
518
519struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
520 struct net_device *dev)
521{
522 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 NEIGH_CACHE_STAT_INC(tbl, lookups);
525
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000526 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600527 n = __neigh_lookup_noref(tbl, pkey, dev);
528 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300529 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600530 n = NULL;
531 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700533
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000534 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 return n;
536}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900537EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
Eric W. Biederman426b5302008-01-24 00:13:18 -0800539struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
540 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541{
542 struct neighbour *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300543 unsigned int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800544 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000545 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546
547 NEIGH_CACHE_STAT_INC(tbl, lookups);
548
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000549 rcu_read_lock_bh();
550 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700551 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700552
553 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
554 n != NULL;
555 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800556 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900557 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300558 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700559 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 NEIGH_CACHE_STAT_INC(tbl, hits);
561 break;
562 }
563 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700564
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000565 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 return n;
567}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900568EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
David Ahern58956312018-12-07 12:24:57 -0800570static struct neighbour *___neigh_create(struct neigh_table *tbl,
571 const void *pkey,
572 struct net_device *dev,
David Aherne997f8a2018-12-11 18:57:25 -0700573 bool exempt_from_gc, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574{
David Aherne997f8a2018-12-11 18:57:25 -0700575 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 u32 hash_val;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300577 unsigned int key_len = tbl->key_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700578 int error;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000579 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580
581 if (!n) {
582 rc = ERR_PTR(-ENOBUFS);
583 goto out;
584 }
585
586 memcpy(n->primary_key, pkey, key_len);
587 n->dev = dev;
588 dev_hold(dev);
589
590 /* Protocol specific setup. */
591 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
592 rc = ERR_PTR(error);
593 goto out_neigh_release;
594 }
595
David Millerda6a8fa2011-07-25 00:01:38 +0000596 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200597 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000598 if (error < 0) {
599 rc = ERR_PTR(error);
600 goto out_neigh_release;
601 }
602 }
603
David S. Miller447f2192011-12-19 15:04:41 -0500604 /* Device specific setup. */
605 if (n->parms->neigh_setup &&
606 (error = n->parms->neigh_setup(n)) < 0) {
607 rc = ERR_PTR(error);
608 goto out_neigh_release;
609 }
610
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100611 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612
613 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000614 nht = rcu_dereference_protected(tbl->nht,
615 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616
David S. Millercd089332011-07-11 01:28:12 -0700617 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
618 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
Jim Westfall096b9852018-01-14 04:18:50 -0800620 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 if (n->parms->dead) {
623 rc = ERR_PTR(-EINVAL);
624 goto out_tbl_unlock;
625 }
626
Eric Dumazet767e97e2010-10-06 17:49:21 -0700627 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
628 lockdep_is_held(&tbl->lock));
629 n1 != NULL;
630 n1 = rcu_dereference_protected(n1->next,
631 lockdep_is_held(&tbl->lock))) {
Jim Westfall096b9852018-01-14 04:18:50 -0800632 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700633 if (want_ref)
634 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 rc = n1;
636 goto out_tbl_unlock;
637 }
638 }
639
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640 n->dead = 0;
David Aherne997f8a2018-12-11 18:57:25 -0700641 if (!exempt_from_gc)
David Ahern8cc196d2018-12-10 13:54:07 -0800642 list_add_tail(&n->gc_list, &n->tbl->gc_list);
643
David S. Millera263b302012-07-02 02:02:15 -0700644 if (want_ref)
645 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700646 rcu_assign_pointer(n->next,
647 rcu_dereference_protected(nht->hash_buckets[hash_val],
648 lockdep_is_held(&tbl->lock)));
649 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000651 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 rc = n;
653out:
654 return rc;
655out_tbl_unlock:
656 write_unlock_bh(&tbl->lock);
657out_neigh_release:
658 neigh_release(n);
659 goto out;
660}
David Ahern58956312018-12-07 12:24:57 -0800661
662struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
663 struct net_device *dev, bool want_ref)
664{
665 return ___neigh_create(tbl, pkey, dev, false, want_ref);
666}
David S. Millera263b302012-07-02 02:02:15 -0700667EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700668
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300669static u32 pneigh_hash(const void *pkey, unsigned int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700670{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700671 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700672 hash_val ^= (hash_val >> 16);
673 hash_val ^= hash_val >> 8;
674 hash_val ^= hash_val >> 4;
675 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900676 return hash_val;
677}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700678
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900679static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
680 struct net *net,
681 const void *pkey,
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300682 unsigned int key_len,
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900683 struct net_device *dev)
684{
685 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700686 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900687 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700688 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900689 return n;
690 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700691 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900692 return NULL;
693}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700694
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900695struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
696 struct net *net, const void *pkey, struct net_device *dev)
697{
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300698 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900699 u32 hash_val = pneigh_hash(pkey, key_len);
700
701 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
702 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700703}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900704EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700705
Eric W. Biederman426b5302008-01-24 00:13:18 -0800706struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
707 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 struct net_device *dev, int creat)
709{
710 struct pneigh_entry *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300711 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900712 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713
714 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900715 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
716 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900718
719 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 goto out;
721
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700722 ASSERT_RTNL();
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
725 if (!n)
726 goto out;
727
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500728 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 memcpy(n->key, pkey, key_len);
730 n->dev = dev;
731 if (dev)
732 dev_hold(dev);
733
734 if (tbl->pconstructor && tbl->pconstructor(n)) {
735 if (dev)
736 dev_put(dev);
737 kfree(n);
738 n = NULL;
739 goto out;
740 }
741
742 write_lock_bh(&tbl->lock);
743 n->next = tbl->phash_buckets[hash_val];
744 tbl->phash_buckets[hash_val] = n;
745 write_unlock_bh(&tbl->lock);
746out:
747 return n;
748}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900749EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751
Eric W. Biederman426b5302008-01-24 00:13:18 -0800752int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 struct net_device *dev)
754{
755 struct pneigh_entry *n, **np;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300756 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900757 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758
759 write_lock_bh(&tbl->lock);
760 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
761 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800762 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900763 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 *np = n->next;
765 write_unlock_bh(&tbl->lock);
766 if (tbl->pdestructor)
767 tbl->pdestructor(n);
768 if (n->dev)
769 dev_put(n->dev);
770 kfree(n);
771 return 0;
772 }
773 }
774 write_unlock_bh(&tbl->lock);
775 return -ENOENT;
776}
777
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200778static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
779 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780{
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200781 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700782 u32 h;
783
784 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
785 np = &tbl->phash_buckets[h];
786 while ((n = *np) != NULL) {
787 if (!dev || n->dev == dev) {
788 *np = n->next;
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200789 n->next = freelist;
790 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791 continue;
792 }
793 np = &n->next;
794 }
795 }
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200796 write_unlock_bh(&tbl->lock);
797 while ((n = freelist)) {
798 freelist = n->next;
799 n->next = NULL;
800 if (tbl->pdestructor)
801 tbl->pdestructor(n);
802 if (n->dev)
803 dev_put(n->dev);
804 kfree(n);
805 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806 return -ENOENT;
807}
808
Denis V. Lunev06f05112008-01-24 00:30:58 -0800809static void neigh_parms_destroy(struct neigh_parms *parms);
810
811static inline void neigh_parms_put(struct neigh_parms *parms)
812{
Reshetova, Elena63439442017-06-30 13:07:56 +0300813 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800814 neigh_parms_destroy(parms);
815}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817/*
818 * neighbour must already be out of the table;
819 *
820 */
821void neigh_destroy(struct neighbour *neigh)
822{
David Millerda6a8fa2011-07-25 00:01:38 +0000823 struct net_device *dev = neigh->dev;
824
Linus Torvalds1da177e2005-04-16 15:20:36 -0700825 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
826
827 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000828 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 dump_stack();
830 return;
831 }
832
833 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000834 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700836 write_lock_bh(&neigh->lock);
837 __skb_queue_purge(&neigh->arp_queue);
838 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000839 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840
David S. Miller447f2192011-12-19 15:04:41 -0500841 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200842 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500843
David Millerda6a8fa2011-07-25 00:01:38 +0000844 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845 neigh_parms_put(neigh->parms);
846
Joe Perchesd5d427c2013-04-15 15:17:19 +0000847 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848
849 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000850 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900852EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853
854/* Neighbour state is suspicious;
855 disable fast path.
856
857 Called with write_locked neigh.
858 */
859static void neigh_suspect(struct neighbour *neigh)
860{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000861 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700862
863 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864}
865
866/* Neighbour state is OK;
867 enable fast path.
868
869 Called with write_locked neigh.
870 */
871static void neigh_connect(struct neighbour *neigh)
872{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000873 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874
875 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700876}
877
Eric Dumazete4c4e442009-07-30 03:15:07 +0000878static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000880 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700881 struct neighbour *n;
882 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000883 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000884 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
886 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
887
Eric Dumazete4c4e442009-07-30 03:15:07 +0000888 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000889 nht = rcu_dereference_protected(tbl->nht,
890 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891
892 /*
893 * periodically recompute ReachableTime from random function
894 */
895
Eric Dumazete4c4e442009-07-30 03:15:07 +0000896 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000898 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100899 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100901 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 }
903
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800904 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
905 goto out;
906
David S. Millercd089332011-07-11 01:28:12 -0700907 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000908 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909
Eric Dumazet767e97e2010-10-06 17:49:21 -0700910 while ((n = rcu_dereference_protected(*np,
911 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000912 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913
Eric Dumazete4c4e442009-07-30 03:15:07 +0000914 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915
Eric Dumazete4c4e442009-07-30 03:15:07 +0000916 state = n->nud_state;
Roopa Prabhu9ce33e42018-04-24 13:49:34 -0700917 if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
918 (n->flags & NTF_EXT_LEARNED)) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000919 write_unlock(&n->lock);
920 goto next_elt;
921 }
922
923 if (time_before(n->used, n->confirmed))
924 n->used = n->confirmed;
925
Reshetova, Elena9f237432017-06-30 13:07:55 +0300926 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000927 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100928 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000929 *np = n->next;
David Ahern58956312018-12-07 12:24:57 -0800930 neigh_mark_dead(n);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000931 write_unlock(&n->lock);
932 neigh_cleanup_and_release(n);
933 continue;
934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936
937next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000938 np = &n->next;
939 }
940 /*
941 * It's fine to release lock here, even if hash table
942 * grows while we are preempted.
943 */
944 write_unlock_bh(&tbl->lock);
945 cond_resched();
946 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500947 nht = rcu_dereference_protected(tbl->nht,
948 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000950out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100951 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
952 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
953 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 */
viresh kumarf6180022014-01-22 12:23:33 +0530955 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100956 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000957 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958}
959
960static __inline__ int neigh_max_probes(struct neighbour *n)
961{
962 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900963 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
964 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
965 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966}
967
Timo Teras5ef12d92009-06-11 04:16:28 -0700968static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000969 __releases(neigh->lock)
970 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700971{
972 struct sk_buff *skb;
973
974 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000975 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700976 neigh->updated = jiffies;
977
978 /* It is very thin place. report_unreachable is very complicated
979 routine. Particularly, it can hit the same neighbour entry!
980
981 So that, we try to be accurate and avoid dead loop. --ANK
982 */
983 while (neigh->nud_state == NUD_FAILED &&
984 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
985 write_unlock(&neigh->lock);
986 neigh->ops->error_report(neigh, skb);
987 write_lock(&neigh->lock);
988 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700989 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000990 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700991}
992
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000993static void neigh_probe(struct neighbour *neigh)
994 __releases(neigh->lock)
995{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200996 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000997 /* keep skb alive even if arp_queue overflows */
998 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +0800999 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001000 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -07001001 if (neigh->ops->solicit)
1002 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001003 atomic_inc(&neigh->probes);
1004 kfree_skb(skb);
1005}
1006
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007/* Called when a timer expires for a neighbour entry. */
1008
Kees Cooke99e88a2017-10-16 14:43:17 -07001009static void neigh_timer_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010{
1011 unsigned long now, next;
Kees Cooke99e88a2017-10-16 14:43:17 -07001012 struct neighbour *neigh = from_timer(neigh, t, timer);
Eric Dumazet95c96172012-04-15 05:58:06 +00001013 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014 int notify = 0;
1015
1016 write_lock(&neigh->lock);
1017
1018 state = neigh->nud_state;
1019 now = jiffies;
1020 next = now + HZ;
1021
David S. Miller045f7b32011-11-01 17:45:55 -04001022 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024
1025 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001026 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001027 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001028 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 next = neigh->confirmed + neigh->parms->reachable_time;
1030 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001031 neigh->used +
1032 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001033 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001035 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001037 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001039 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001041 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -07001043 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 }
1045 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001046 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001047 neigh->confirmed +
1048 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001049 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001051 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -07001053 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 next = neigh->confirmed + neigh->parms->reachable_time;
1055 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001056 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001058 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +09001060 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001061 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063 } else {
1064 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001065 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 }
1067
1068 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
1069 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070 neigh->nud_state = NUD_FAILED;
1071 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -07001072 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +08001073 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074 }
1075
1076 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077 if (time_before(next, jiffies + HZ/2))
1078 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +10001079 if (!mod_timer(&neigh->timer, next))
1080 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 }
1082 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001083 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -08001084 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -08001085out:
David S. Miller9ff56602008-02-17 18:39:54 -08001086 write_unlock(&neigh->lock);
1087 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088
Thomas Grafd961db32007-08-08 23:12:56 -07001089 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001090 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -07001091
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092 neigh_release(neigh);
1093}
1094
1095int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
1096{
1097 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001098 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099
1100 write_lock_bh(&neigh->lock);
1101
1102 rc = 0;
1103 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1104 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001105 if (neigh->dead)
1106 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001109 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1110 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001111 unsigned long next, now = jiffies;
1112
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001113 atomic_set(&neigh->probes,
1114 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001116 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001117 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1118 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001119 neigh_add_timer(neigh, next);
1120 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121 } else {
1122 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001123 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 write_unlock_bh(&neigh->lock);
1125
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001126 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 return 1;
1128 }
1129 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001130 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001132 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001133 neigh_add_timer(neigh, jiffies +
1134 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }
1136
1137 if (neigh->nud_state == NUD_INCOMPLETE) {
1138 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001139 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001140 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001142
David S. Millerf72051b2008-09-23 01:11:18 -07001143 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001144 if (!buff)
1145 break;
1146 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001148 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001150 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001152 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 }
1154 rc = 1;
1155 }
1156out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001157 if (immediate_probe)
1158 neigh_probe(neigh);
1159 else
1160 write_unlock(&neigh->lock);
1161 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001162 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001163
1164out_dead:
1165 if (neigh->nud_state & NUD_STALE)
1166 goto out_unlock_bh;
1167 write_unlock_bh(&neigh->lock);
1168 kfree_skb(skb);
1169 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001171EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172
David S. Millerf6b72b622011-07-14 07:53:20 -07001173static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174{
1175 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001176 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001177 = NULL;
1178
1179 if (neigh->dev->header_ops)
1180 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181
1182 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001183 hh = &neigh->hh;
1184 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001185 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001187 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 }
1189 }
1190}
1191
1192
1193
1194/* Generic update routine.
1195 -- lladdr is new lladdr or NULL, if it is not supplied.
1196 -- new is new state.
1197 -- flags
1198 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1199 if it is different.
1200 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001201 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1204
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001205 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 NTF_ROUTER flag.
1207 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1208 a router.
1209
1210 Caller MUST hold reference count on the entry.
1211 */
1212
David Ahern7a35a502018-12-05 20:02:29 -08001213static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
1214 u8 new, u32 flags, u32 nlmsg_pid,
1215 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216{
David Aherne997f8a2018-12-11 18:57:25 -07001217 bool ext_learn_change = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 u8 old;
1219 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221 struct net_device *dev;
1222 int update_isrouter = 0;
1223
1224 write_lock_bh(&neigh->lock);
1225
1226 dev = neigh->dev;
1227 old = neigh->nud_state;
1228 err = -EPERM;
1229
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001230 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231 (old & (NUD_NOARP | NUD_PERMANENT)))
1232 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001233 if (neigh->dead) {
1234 NL_SET_ERR_MSG(extack, "Neighbor entry is now dead");
Julian Anastasov2c51a972015-06-16 22:56:39 +03001235 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001236 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001237
David Aherne997f8a2018-12-11 18:57:25 -07001238 ext_learn_change = neigh_update_ext_learned(neigh, flags, &notify);
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 if (!(new & NUD_VALID)) {
1241 neigh_del_timer(neigh);
1242 if (old & NUD_CONNECTED)
1243 neigh_suspect(neigh);
David Ahern9c29a2f2018-12-11 18:57:21 -07001244 neigh->nud_state = new;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001245 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 notify = old & NUD_VALID;
Roopa Prabhud2fb4fb2018-10-20 18:09:31 -07001247 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
Timo Teras5ef12d92009-06-11 04:16:28 -07001248 (new & NUD_FAILED)) {
1249 neigh_invalidate(neigh);
1250 notify = 1;
1251 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252 goto out;
1253 }
1254
1255 /* Compare new lladdr with cached one */
1256 if (!dev->addr_len) {
1257 /* First case: device needs no address. */
1258 lladdr = neigh->ha;
1259 } else if (lladdr) {
1260 /* The second case: if something is already cached
1261 and a new address is proposed:
1262 - compare new & old
1263 - if they are different, check override flag
1264 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001265 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001266 !memcmp(lladdr, neigh->ha, dev->addr_len))
1267 lladdr = neigh->ha;
1268 } else {
1269 /* No address is supplied; if we know something,
1270 use it, otherwise discard the request.
1271 */
1272 err = -EINVAL;
David Ahern7a35a502018-12-05 20:02:29 -08001273 if (!(old & NUD_VALID)) {
1274 NL_SET_ERR_MSG(extack, "No link layer address given");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001275 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001276 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 lladdr = neigh->ha;
1278 }
1279
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001280 /* Update confirmed timestamp for neighbour entry after we
1281 * received ARP packet even if it doesn't change IP to MAC binding.
1282 */
1283 if (new & NUD_CONNECTED)
1284 neigh->confirmed = jiffies;
1285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 /* If entry was valid and address is not changed,
1287 do not change entry state, if new one is STALE.
1288 */
1289 err = 0;
1290 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1291 if (old & NUD_VALID) {
1292 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1293 update_isrouter = 0;
1294 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1295 (old & NUD_CONNECTED)) {
1296 lladdr = neigh->ha;
1297 new = NUD_STALE;
1298 } else
1299 goto out;
1300 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001301 if (lladdr == neigh->ha && new == NUD_STALE &&
1302 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001303 new = old;
1304 }
1305 }
1306
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001307 /* Update timestamp only once we know we will make a change to the
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001308 * neighbour entry. Otherwise we risk to move the locktime window with
1309 * noop updates and ignore relevant ARP updates.
1310 */
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001311 if (new != old || lladdr != neigh->ha)
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001312 neigh->updated = jiffies;
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001313
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314 if (new != old) {
1315 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001316 if (new & NUD_PROBE)
1317 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001318 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001319 neigh_add_timer(neigh, (jiffies +
1320 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001321 neigh->parms->reachable_time :
1322 0)));
David Ahern9c29a2f2018-12-11 18:57:21 -07001323 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001324 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 }
1326
1327 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001328 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001330 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331 neigh_update_hhs(neigh);
1332 if (!(new & NUD_CONNECTED))
1333 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001334 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 }
1337 if (new == old)
1338 goto out;
1339 if (new & NUD_CONNECTED)
1340 neigh_connect(neigh);
1341 else
1342 neigh_suspect(neigh);
1343 if (!(old & NUD_VALID)) {
1344 struct sk_buff *skb;
1345
1346 /* Again: avoid dead loop if something went wrong */
1347
1348 while (neigh->nud_state & NUD_VALID &&
1349 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001350 struct dst_entry *dst = skb_dst(skb);
1351 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001353
1354 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001355
1356 /* Why not just use 'neigh' as-is? The problem is that
1357 * things such as shaper, eql, and sch_teql can end up
1358 * using alternative, different, neigh objects to output
1359 * the packet in the output path. So what we need to do
1360 * here is re-lookup the top-level neigh in the path so
1361 * we can reinject the packet there.
1362 */
1363 n2 = NULL;
1364 if (dst) {
1365 n2 = dst_neigh_lookup_skb(dst, skb);
1366 if (n2)
1367 n1 = n2;
1368 }
David S. Miller8f40b162011-07-17 13:34:11 -07001369 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001370 if (n2)
1371 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001372 rcu_read_unlock();
1373
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374 write_lock_bh(&neigh->lock);
1375 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001376 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001377 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 }
1379out:
Roopa Prabhufc6e8072018-09-22 21:26:20 -07001380 if (update_isrouter)
1381 neigh_update_is_router(neigh, flags, &notify);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001382 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001383
David Aherne997f8a2018-12-11 18:57:25 -07001384 if (((new ^ old) & NUD_PERMANENT) || ext_learn_change)
David Ahern9c29a2f2018-12-11 18:57:21 -07001385 neigh_update_gc_list(neigh);
1386
Tom Tucker8d717402006-07-30 20:43:36 -07001387 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001388 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 return err;
1391}
David Ahern7a35a502018-12-05 20:02:29 -08001392
1393int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1394 u32 flags, u32 nlmsg_pid)
1395{
1396 return __neigh_update(neigh, lladdr, new, flags, nlmsg_pid, NULL);
1397}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001398EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Jiri Benc7e980562013-12-11 13:48:20 +01001400/* Update the neigh to listen temporarily for probe responses, even if it is
1401 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1402 */
1403void __neigh_set_probe_once(struct neighbour *neigh)
1404{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001405 if (neigh->dead)
1406 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001407 neigh->updated = jiffies;
1408 if (!(neigh->nud_state & NUD_FAILED))
1409 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001410 neigh->nud_state = NUD_INCOMPLETE;
1411 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001412 neigh_add_timer(neigh,
1413 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1414}
1415EXPORT_SYMBOL(__neigh_set_probe_once);
1416
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1418 u8 *lladdr, void *saddr,
1419 struct net_device *dev)
1420{
1421 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1422 lladdr || !dev->addr_len);
1423 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001424 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001425 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 return neigh;
1427}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001428EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001429
Eric Dumazet34d101d2010-10-11 09:16:57 -07001430/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001431static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001432{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001433 struct net_device *dev = n->dev;
1434 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001435 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001436
1437 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001438
David S. Millerf6b72b622011-07-14 07:53:20 -07001439 /* Only one thread can come in here and initialize the
1440 * hh_cache entry.
1441 */
David S. Millerb23b5452011-07-16 17:45:02 -07001442 if (!hh->hh_len)
1443 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001444
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001445 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446}
1447
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448/* Slow and careful. */
1449
David S. Miller8f40b162011-07-17 13:34:11 -07001450int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 int rc = 0;
1453
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454 if (!neigh_event_send(neigh, skb)) {
1455 int err;
1456 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001457 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001458
David S. Millerf6b72b622011-07-14 07:53:20 -07001459 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001460 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001461
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001462 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001463 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001464 seq = read_seqbegin(&neigh->ha_lock);
1465 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1466 neigh->ha, NULL, skb->len);
1467 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001468
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001470 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 else
1472 goto out_kfree_skb;
1473 }
1474out:
1475 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001476out_kfree_skb:
1477 rc = -EINVAL;
1478 kfree_skb(skb);
1479 goto out;
1480}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001481EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001482
1483/* As fast as possible without hh cache */
1484
David S. Miller8f40b162011-07-17 13:34:11 -07001485int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001488 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001489 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001491 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001492 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001493 seq = read_seqbegin(&neigh->ha_lock);
1494 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1495 neigh->ha, NULL, skb->len);
1496 } while (read_seqretry(&neigh->ha_lock, seq));
1497
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001499 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 else {
1501 err = -EINVAL;
1502 kfree_skb(skb);
1503 }
1504 return err;
1505}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001506EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507
David S. Miller8f40b162011-07-17 13:34:11 -07001508int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1509{
1510 return dev_queue_xmit(skb);
1511}
1512EXPORT_SYMBOL(neigh_direct_output);
1513
Kees Cooke99e88a2017-10-16 14:43:17 -07001514static void neigh_proxy_process(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Kees Cooke99e88a2017-10-16 14:43:17 -07001516 struct neigh_table *tbl = from_timer(tbl, t, proxy_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 long sched_next = 0;
1518 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001519 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520
1521 spin_lock(&tbl->proxy_queue.lock);
1522
David S. Millerf72051b2008-09-23 01:11:18 -07001523 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1524 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001527 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001528
David S. Millerf72051b2008-09-23 01:11:18 -07001529 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001530 if (tbl->proxy_redo && netif_running(dev)) {
1531 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001532 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001533 rcu_read_unlock();
1534 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001535 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001536 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537
1538 dev_put(dev);
1539 } else if (!sched_next || tdif < sched_next)
1540 sched_next = tdif;
1541 }
1542 del_timer(&tbl->proxy_timer);
1543 if (sched_next)
1544 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1545 spin_unlock(&tbl->proxy_queue.lock);
1546}
1547
1548void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1549 struct sk_buff *skb)
1550{
1551 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001552
1553 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001554 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001556 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001557 kfree_skb(skb);
1558 return;
1559 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001560
1561 NEIGH_CB(skb)->sched_next = sched_next;
1562 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563
1564 spin_lock(&tbl->proxy_queue.lock);
1565 if (del_timer(&tbl->proxy_timer)) {
1566 if (time_before(tbl->proxy_timer.expires, sched_next))
1567 sched_next = tbl->proxy_timer.expires;
1568 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001569 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001570 dev_hold(skb->dev);
1571 __skb_queue_tail(&tbl->proxy_queue, skb);
1572 mod_timer(&tbl->proxy_timer, sched_next);
1573 spin_unlock(&tbl->proxy_queue.lock);
1574}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001575EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001577static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001578 struct net *net, int ifindex)
1579{
1580 struct neigh_parms *p;
1581
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001582 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001583 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001584 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001585 return p;
1586 }
1587
1588 return NULL;
1589}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001590
1591struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1592 struct neigh_table *tbl)
1593{
Gao fengcf89d6b2013-06-20 10:01:32 +08001594 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001595 struct net *net = dev_net(dev);
1596 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Gao fengcf89d6b2013-06-20 10:01:32 +08001598 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001599 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001601 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001602 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001603 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001604 dev_hold(dev);
1605 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001606 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001607 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001608
1609 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001610 dev_put(dev);
1611 kfree(p);
1612 return NULL;
1613 }
1614
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001616 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001618
1619 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 }
1621 return p;
1622}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001623EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001624
1625static void neigh_rcu_free_parms(struct rcu_head *head)
1626{
1627 struct neigh_parms *parms =
1628 container_of(head, struct neigh_parms, rcu_head);
1629
1630 neigh_parms_put(parms);
1631}
1632
1633void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1634{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 if (!parms || parms == &tbl->parms)
1636 return;
1637 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001638 list_del(&parms->list);
1639 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001641 if (parms->dev)
1642 dev_put(parms->dev);
1643 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001644}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001645EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
Denis V. Lunev06f05112008-01-24 00:30:58 -08001647static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001648{
1649 kfree(parms);
1650}
1651
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001652static struct lock_class_key neigh_table_proxy_queue_class;
1653
WANG Congd7480fd2014-11-10 15:59:36 -08001654static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1655
1656void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657{
1658 unsigned long now = jiffies;
1659 unsigned long phsize;
1660
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001661 INIT_LIST_HEAD(&tbl->parms_list);
David Ahern58956312018-12-07 12:24:57 -08001662 INIT_LIST_HEAD(&tbl->gc_list);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001663 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001664 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001665 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001667 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668
Linus Torvalds1da177e2005-04-16 15:20:36 -07001669 tbl->stats = alloc_percpu(struct neigh_statistics);
1670 if (!tbl->stats)
1671 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001672
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +02001674 if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat,
1675 &neigh_stat_seq_ops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677#endif
1678
David S. Millercd089332011-07-11 01:28:12 -07001679 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001680
1681 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001682 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001683
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001684 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001685 panic("cannot allocate neighbour cache hashes");
1686
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001687 if (!tbl->entry_size)
1688 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1689 tbl->key_len, NEIGH_PRIV_ALIGN);
1690 else
1691 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1692
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001694 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301695 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1696 tbl->parms.reachable_time);
Kees Cooke99e88a2017-10-16 14:43:17 -07001697 timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001698 skb_queue_head_init_class(&tbl->proxy_queue,
1699 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001700
1701 tbl->last_flush = now;
1702 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001703
WANG Congd7480fd2014-11-10 15:59:36 -08001704 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001706EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707
WANG Congd7480fd2014-11-10 15:59:36 -08001708int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001709{
WANG Congd7480fd2014-11-10 15:59:36 -08001710 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001712 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713 del_timer_sync(&tbl->proxy_timer);
1714 pneigh_queue_purge(&tbl->proxy_queue);
1715 neigh_ifdown(tbl, NULL);
1716 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001717 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001719 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1720 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001721 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722
1723 kfree(tbl->phash_buckets);
1724 tbl->phash_buckets = NULL;
1725
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001726 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1727
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001728 free_percpu(tbl->stats);
1729 tbl->stats = NULL;
1730
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 return 0;
1732}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001733EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734
WANG Congd7480fd2014-11-10 15:59:36 -08001735static struct neigh_table *neigh_find_table(int family)
1736{
1737 struct neigh_table *tbl = NULL;
1738
1739 switch (family) {
1740 case AF_INET:
1741 tbl = neigh_tables[NEIGH_ARP_TABLE];
1742 break;
1743 case AF_INET6:
1744 tbl = neigh_tables[NEIGH_ND_TABLE];
1745 break;
1746 case AF_DECnet:
1747 tbl = neigh_tables[NEIGH_DN_TABLE];
1748 break;
1749 }
1750
1751 return tbl;
1752}
1753
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08001754const struct nla_policy nda_policy[NDA_MAX+1] = {
1755 [NDA_DST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1756 [NDA_LLADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1757 [NDA_CACHEINFO] = { .len = sizeof(struct nda_cacheinfo) },
1758 [NDA_PROBES] = { .type = NLA_U32 },
1759 [NDA_VLAN] = { .type = NLA_U16 },
1760 [NDA_PORT] = { .type = NLA_U16 },
1761 [NDA_VNI] = { .type = NLA_U32 },
1762 [NDA_IFINDEX] = { .type = NLA_U32 },
1763 [NDA_MASTER] = { .type = NLA_U32 },
1764};
1765
David Ahernc21ef3e2017-04-16 09:48:24 -07001766static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1767 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001768{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001769 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001770 struct ndmsg *ndm;
1771 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001772 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001773 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001775 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001776
Eric Dumazet110b2492010-10-04 04:27:36 +00001777 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001778 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001779 goto out;
1780
Thomas Grafa14a49d2006-08-07 17:53:08 -07001781 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
David Ahern7a35a502018-12-05 20:02:29 -08001782 if (!dst_attr) {
1783 NL_SET_ERR_MSG(extack, "Network address not specified");
Thomas Grafa14a49d2006-08-07 17:53:08 -07001784 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001785 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001786
1787 ndm = nlmsg_data(nlh);
1788 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001789 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001790 if (dev == NULL) {
1791 err = -ENODEV;
1792 goto out;
1793 }
1794 }
1795
WANG Congd7480fd2014-11-10 15:59:36 -08001796 tbl = neigh_find_table(ndm->ndm_family);
1797 if (tbl == NULL)
1798 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001799
David Ahern7a35a502018-12-05 20:02:29 -08001800 if (nla_len(dst_attr) < (int)tbl->key_len) {
1801 NL_SET_ERR_MSG(extack, "Invalid network address");
WANG Congd7480fd2014-11-10 15:59:36 -08001802 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001803 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804
WANG Congd7480fd2014-11-10 15:59:36 -08001805 if (ndm->ndm_flags & NTF_PROXY) {
1806 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001807 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001808 }
WANG Congd7480fd2014-11-10 15:59:36 -08001809
1810 if (dev == NULL)
1811 goto out;
1812
1813 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1814 if (neigh == NULL) {
1815 err = -ENOENT;
1816 goto out;
1817 }
1818
David Ahern7a35a502018-12-05 20:02:29 -08001819 err = __neigh_update(neigh, NULL, NUD_FAILED,
1820 NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN,
1821 NETLINK_CB(skb).portid, extack);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001822 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001823 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001824 neigh_remove_one(neigh, tbl);
1825 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001826
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827out:
1828 return err;
1829}
1830
David Ahernc21ef3e2017-04-16 09:48:24 -07001831static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1832 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001834 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE |
1835 NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001836 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001837 struct ndmsg *ndm;
1838 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001839 struct neigh_table *tbl;
1840 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001841 struct neighbour *neigh;
1842 void *dst, *lladdr;
David Aherndf9b0e32018-12-15 14:09:06 -08001843 u8 protocol = 0;
Thomas Graf5208deb2006-08-07 17:55:40 -07001844 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001845
Eric Dumazet110b2492010-10-04 04:27:36 +00001846 ASSERT_RTNL();
David Ahernc21ef3e2017-04-16 09:48:24 -07001847 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001848 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001849 goto out;
1850
Thomas Graf5208deb2006-08-07 17:55:40 -07001851 err = -EINVAL;
David Ahern7a35a502018-12-05 20:02:29 -08001852 if (!tb[NDA_DST]) {
1853 NL_SET_ERR_MSG(extack, "Network address not specified");
Thomas Graf5208deb2006-08-07 17:55:40 -07001854 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001855 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001856
1857 ndm = nlmsg_data(nlh);
1858 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001859 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001860 if (dev == NULL) {
1861 err = -ENODEV;
1862 goto out;
1863 }
1864
David Ahern7a35a502018-12-05 20:02:29 -08001865 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) {
1866 NL_SET_ERR_MSG(extack, "Invalid link address");
Eric Dumazet110b2492010-10-04 04:27:36 +00001867 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001868 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001869 }
1870
WANG Congd7480fd2014-11-10 15:59:36 -08001871 tbl = neigh_find_table(ndm->ndm_family);
1872 if (tbl == NULL)
1873 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001874
David Ahern7a35a502018-12-05 20:02:29 -08001875 if (nla_len(tb[NDA_DST]) < (int)tbl->key_len) {
1876 NL_SET_ERR_MSG(extack, "Invalid network address");
WANG Congd7480fd2014-11-10 15:59:36 -08001877 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001878 }
1879
WANG Congd7480fd2014-11-10 15:59:36 -08001880 dst = nla_data(tb[NDA_DST]);
1881 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001882
David Aherndf9b0e32018-12-15 14:09:06 -08001883 if (tb[NDA_PROTOCOL]) {
1884 if (nla_len(tb[NDA_PROTOCOL]) != sizeof(u8)) {
1885 NL_SET_ERR_MSG(extack, "Invalid protocol attribute");
1886 goto out;
1887 }
1888 protocol = nla_get_u8(tb[NDA_PROTOCOL]);
1889 }
1890
WANG Congd7480fd2014-11-10 15:59:36 -08001891 if (ndm->ndm_flags & NTF_PROXY) {
1892 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001893
WANG Congd7480fd2014-11-10 15:59:36 -08001894 err = -ENOBUFS;
1895 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1896 if (pn) {
1897 pn->flags = ndm->ndm_flags;
David Aherndf9b0e32018-12-15 14:09:06 -08001898 if (protocol)
1899 pn->protocol = protocol;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001900 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001901 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001902 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001903 }
1904
David Ahern7a35a502018-12-05 20:02:29 -08001905 if (!dev) {
1906 NL_SET_ERR_MSG(extack, "Device not specified");
WANG Congd7480fd2014-11-10 15:59:36 -08001907 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001908 }
WANG Congd7480fd2014-11-10 15:59:36 -08001909
1910 neigh = neigh_lookup(tbl, dst, dev);
1911 if (neigh == NULL) {
David Aherne997f8a2018-12-11 18:57:25 -07001912 bool exempt_from_gc;
1913
WANG Congd7480fd2014-11-10 15:59:36 -08001914 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1915 err = -ENOENT;
1916 goto out;
1917 }
1918
David Aherne997f8a2018-12-11 18:57:25 -07001919 exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
1920 ndm->ndm_flags & NTF_EXT_LEARNED;
1921 neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true);
WANG Congd7480fd2014-11-10 15:59:36 -08001922 if (IS_ERR(neigh)) {
1923 err = PTR_ERR(neigh);
1924 goto out;
1925 }
1926 } else {
1927 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1928 err = -EEXIST;
1929 neigh_release(neigh);
1930 goto out;
1931 }
1932
1933 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001934 flags &= ~(NEIGH_UPDATE_F_OVERRIDE |
1935 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
WANG Congd7480fd2014-11-10 15:59:36 -08001936 }
1937
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001938 if (ndm->ndm_flags & NTF_EXT_LEARNED)
1939 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1940
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001941 if (ndm->ndm_flags & NTF_ROUTER)
1942 flags |= NEIGH_UPDATE_F_ISROUTER;
1943
WANG Congd7480fd2014-11-10 15:59:36 -08001944 if (ndm->ndm_flags & NTF_USE) {
1945 neigh_event_send(neigh, NULL);
1946 err = 0;
1947 } else
David Ahern7a35a502018-12-05 20:02:29 -08001948 err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1949 NETLINK_CB(skb).portid, extack);
David Aherndf9b0e32018-12-15 14:09:06 -08001950
1951 if (protocol)
1952 neigh->protocol = protocol;
1953
WANG Congd7480fd2014-11-10 15:59:36 -08001954 neigh_release(neigh);
1955
Linus Torvalds1da177e2005-04-16 15:20:36 -07001956out:
1957 return err;
1958}
1959
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001960static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1961{
Thomas Grafca860fb2006-08-07 18:00:18 -07001962 struct nlattr *nest;
1963
1964 nest = nla_nest_start(skb, NDTA_PARMS);
1965 if (nest == NULL)
1966 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001967
David S. Miller9a6308d2012-04-01 20:06:28 -04001968 if ((parms->dev &&
1969 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001970 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001971 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1972 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001973 /* approximative value for deprecated QUEUE_LEN (in packets) */
1974 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001975 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1976 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1977 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1978 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1979 NEIGH_VAR(parms, UCAST_PROBES)) ||
1980 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1981 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09001982 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
1983 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001984 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
1985 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001986 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001987 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001988 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001989 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001990 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001991 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001992 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001993 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001994 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001995 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001996 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001997 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001998 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02001999 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04002000 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07002001 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002002
Thomas Grafca860fb2006-08-07 18:00:18 -07002003nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07002004 nla_nest_cancel(skb, nest);
2005 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002006}
2007
Thomas Grafca860fb2006-08-07 18:00:18 -07002008static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
2009 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010{
2011 struct nlmsghdr *nlh;
2012 struct ndtmsg *ndtmsg;
2013
Thomas Grafca860fb2006-08-07 18:00:18 -07002014 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
2015 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002016 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002017
Thomas Grafca860fb2006-08-07 18:00:18 -07002018 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002019
2020 read_lock_bh(&tbl->lock);
2021 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002022 ndtmsg->ndtm_pad1 = 0;
2023 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002024
David S. Miller9a6308d2012-04-01 20:06:28 -04002025 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002026 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04002027 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
2028 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
2029 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
2030 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002031 {
2032 unsigned long now = jiffies;
2033 unsigned int flush_delta = now - tbl->last_flush;
2034 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002035 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002036 struct ndt_config ndc = {
2037 .ndtc_key_len = tbl->key_len,
2038 .ndtc_entry_size = tbl->entry_size,
2039 .ndtc_entries = atomic_read(&tbl->entries),
2040 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
2041 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002042 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
2043 };
2044
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002045 rcu_read_lock_bh();
2046 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05002047 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07002048 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002049 rcu_read_unlock_bh();
2050
David S. Miller9a6308d2012-04-01 20:06:28 -04002051 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
2052 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002053 }
2054
2055 {
2056 int cpu;
2057 struct ndt_stats ndst;
2058
2059 memset(&ndst, 0, sizeof(ndst));
2060
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07002061 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002062 struct neigh_statistics *st;
2063
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002064 st = per_cpu_ptr(tbl->stats, cpu);
2065 ndst.ndts_allocs += st->allocs;
2066 ndst.ndts_destroys += st->destroys;
2067 ndst.ndts_hash_grows += st->hash_grows;
2068 ndst.ndts_res_failed += st->res_failed;
2069 ndst.ndts_lookups += st->lookups;
2070 ndst.ndts_hits += st->hits;
2071 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
2072 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
2073 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
2074 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07002075 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002076 }
2077
Nicolas Dichtelb6763382016-04-26 10:06:17 +02002078 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
2079 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04002080 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002081 }
2082
2083 BUG_ON(tbl->parms.dev);
2084 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07002085 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002086
2087 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01002088 nlmsg_end(skb, nlh);
2089 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002090
Thomas Grafca860fb2006-08-07 18:00:18 -07002091nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002092 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08002093 nlmsg_cancel(skb, nlh);
2094 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002095}
2096
Thomas Grafca860fb2006-08-07 18:00:18 -07002097static int neightbl_fill_param_info(struct sk_buff *skb,
2098 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002099 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07002100 u32 pid, u32 seq, int type,
2101 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002102{
2103 struct ndtmsg *ndtmsg;
2104 struct nlmsghdr *nlh;
2105
Thomas Grafca860fb2006-08-07 18:00:18 -07002106 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
2107 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002108 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002109
Thomas Grafca860fb2006-08-07 18:00:18 -07002110 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002111
2112 read_lock_bh(&tbl->lock);
2113 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002114 ndtmsg->ndtm_pad1 = 0;
2115 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002116
Thomas Grafca860fb2006-08-07 18:00:18 -07002117 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
2118 neightbl_fill_parms(skb, parms) < 0)
2119 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002120
2121 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01002122 nlmsg_end(skb, nlh);
2123 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07002124errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002125 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08002126 nlmsg_cancel(skb, nlh);
2127 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002128}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002129
Patrick McHardyef7c79e2007-06-05 12:38:30 -07002130static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07002131 [NDTA_NAME] = { .type = NLA_STRING },
2132 [NDTA_THRESH1] = { .type = NLA_U32 },
2133 [NDTA_THRESH2] = { .type = NLA_U32 },
2134 [NDTA_THRESH3] = { .type = NLA_U32 },
2135 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
2136 [NDTA_PARMS] = { .type = NLA_NESTED },
2137};
2138
Patrick McHardyef7c79e2007-06-05 12:38:30 -07002139static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07002140 [NDTPA_IFINDEX] = { .type = NLA_U32 },
2141 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
2142 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
2143 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
2144 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
2145 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002146 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07002147 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
2148 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
2149 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
2150 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
2151 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
2152 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
2153 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
2154};
2155
David Ahernc21ef3e2017-04-16 09:48:24 -07002156static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
2157 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002158{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002159 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002160 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002161 struct ndtmsg *ndtmsg;
2162 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08002163 bool found = false;
2164 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002165
Thomas Graf6b3f8672006-08-07 17:58:53 -07002166 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
David Ahernc21ef3e2017-04-16 09:48:24 -07002167 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002168 if (err < 0)
2169 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002170
Thomas Graf6b3f8672006-08-07 17:58:53 -07002171 if (tb[NDTA_NAME] == NULL) {
2172 err = -EINVAL;
2173 goto errout;
2174 }
2175
2176 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002177
2178 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2179 tbl = neigh_tables[tidx];
2180 if (!tbl)
2181 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002182 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2183 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002184 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2185 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002186 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002187 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002188 }
2189
WANG Congd7480fd2014-11-10 15:59:36 -08002190 if (!found)
2191 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002192
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002193 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002194 * We acquire tbl->lock to be nice to the periodic timers and
2195 * make sure they always see a consistent set of values.
2196 */
2197 write_lock_bh(&tbl->lock);
2198
Thomas Graf6b3f8672006-08-07 17:58:53 -07002199 if (tb[NDTA_PARMS]) {
2200 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002201 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002202 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002203
Thomas Graf6b3f8672006-08-07 17:58:53 -07002204 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
David Ahernc21ef3e2017-04-16 09:48:24 -07002205 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002206 if (err < 0)
2207 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002208
Thomas Graf6b3f8672006-08-07 17:58:53 -07002209 if (tbp[NDTPA_IFINDEX])
2210 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002211
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002212 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002213 if (p == NULL) {
2214 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002215 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002216 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002217
Thomas Graf6b3f8672006-08-07 17:58:53 -07002218 for (i = 1; i <= NDTPA_MAX; i++) {
2219 if (tbp[i] == NULL)
2220 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002221
Thomas Graf6b3f8672006-08-07 17:58:53 -07002222 switch (i) {
2223 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002224 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2225 nla_get_u32(tbp[i]) *
2226 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002227 break;
2228 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002229 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2230 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002231 break;
2232 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002233 NEIGH_VAR_SET(p, PROXY_QLEN,
2234 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002235 break;
2236 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002237 NEIGH_VAR_SET(p, APP_PROBES,
2238 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002239 break;
2240 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002241 NEIGH_VAR_SET(p, UCAST_PROBES,
2242 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002243 break;
2244 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002245 NEIGH_VAR_SET(p, MCAST_PROBES,
2246 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002247 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002248 case NDTPA_MCAST_REPROBES:
2249 NEIGH_VAR_SET(p, MCAST_REPROBES,
2250 nla_get_u32(tbp[i]));
2251 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002252 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002253 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2254 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002255 /* update reachable_time as well, otherwise, the change will
2256 * only be effective after the next time neigh_periodic_work
2257 * decides to recompute it (can be multiple minutes)
2258 */
2259 p->reachable_time =
2260 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002261 break;
2262 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002263 NEIGH_VAR_SET(p, GC_STALETIME,
2264 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002265 break;
2266 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002267 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2268 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002269 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002270 break;
2271 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002272 NEIGH_VAR_SET(p, RETRANS_TIME,
2273 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002274 break;
2275 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002276 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2277 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002278 break;
2279 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002280 NEIGH_VAR_SET(p, PROXY_DELAY,
2281 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002282 break;
2283 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002284 NEIGH_VAR_SET(p, LOCKTIME,
2285 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002286 break;
2287 }
2288 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002289 }
2290
Gao fengdc25c672013-06-20 10:01:34 +08002291 err = -ENOENT;
2292 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2293 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2294 !net_eq(net, &init_net))
2295 goto errout_tbl_lock;
2296
Thomas Graf6b3f8672006-08-07 17:58:53 -07002297 if (tb[NDTA_THRESH1])
2298 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2299
2300 if (tb[NDTA_THRESH2])
2301 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2302
2303 if (tb[NDTA_THRESH3])
2304 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2305
2306 if (tb[NDTA_GC_INTERVAL])
2307 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2308
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002309 err = 0;
2310
Thomas Graf6b3f8672006-08-07 17:58:53 -07002311errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002312 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002313errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002314 return err;
2315}
2316
David Ahern9632d472018-10-07 20:16:37 -07002317static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
2318 struct netlink_ext_ack *extack)
2319{
2320 struct ndtmsg *ndtm;
2321
2322 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndtm))) {
2323 NL_SET_ERR_MSG(extack, "Invalid header for neighbor table dump request");
2324 return -EINVAL;
2325 }
2326
2327 ndtm = nlmsg_data(nlh);
2328 if (ndtm->ndtm_pad1 || ndtm->ndtm_pad2) {
2329 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor table dump request");
2330 return -EINVAL;
2331 }
2332
2333 if (nlmsg_attrlen(nlh, sizeof(*ndtm))) {
2334 NL_SET_ERR_MSG(extack, "Invalid data after header in neighbor table dump request");
2335 return -EINVAL;
2336 }
2337
2338 return 0;
2339}
2340
Thomas Grafc8822a42007-03-22 11:50:06 -07002341static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002342{
David Ahern9632d472018-10-07 20:16:37 -07002343 const struct nlmsghdr *nlh = cb->nlh;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002344 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002345 int family, tidx, nidx = 0;
2346 int tbl_skip = cb->args[0];
2347 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002348 struct neigh_table *tbl;
2349
David Ahern9632d472018-10-07 20:16:37 -07002350 if (cb->strict_check) {
2351 int err = neightbl_valid_dump_info(nlh, cb->extack);
2352
2353 if (err < 0)
2354 return err;
2355 }
2356
2357 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002358
WANG Congd7480fd2014-11-10 15:59:36 -08002359 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002360 struct neigh_parms *p;
2361
WANG Congd7480fd2014-11-10 15:59:36 -08002362 tbl = neigh_tables[tidx];
2363 if (!tbl)
2364 continue;
2365
Thomas Grafca860fb2006-08-07 18:00:18 -07002366 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002367 continue;
2368
Eric W. Biederman15e47302012-09-07 20:12:54 +00002369 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002370 nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002371 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002372 break;
2373
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002374 nidx = 0;
2375 p = list_next_entry(&tbl->parms, list);
2376 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002377 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002378 continue;
2379
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002380 if (nidx < neigh_skip)
2381 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002382
Thomas Grafca860fb2006-08-07 18:00:18 -07002383 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002384 NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002385 nlh->nlmsg_seq,
Thomas Grafca860fb2006-08-07 18:00:18 -07002386 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002387 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002388 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002389 next:
2390 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002391 }
2392
Thomas Grafca860fb2006-08-07 18:00:18 -07002393 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002394 }
2395out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002396 cb->args[0] = tidx;
2397 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002398
2399 return skb->len;
2400}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401
Thomas Graf8b8aec52006-08-07 17:56:37 -07002402static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2403 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404{
2405 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002407 struct nlmsghdr *nlh;
2408 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409
Thomas Graf8b8aec52006-08-07 17:56:37 -07002410 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2411 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002412 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002413
2414 ndm = nlmsg_data(nlh);
2415 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002416 ndm->ndm_pad1 = 0;
2417 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002418 ndm->ndm_flags = neigh->flags;
2419 ndm->ndm_type = neigh->type;
2420 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421
David S. Miller9a6308d2012-04-01 20:06:28 -04002422 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2423 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002424
2425 read_lock_bh(&neigh->lock);
2426 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002427 if (neigh->nud_state & NUD_VALID) {
2428 char haddr[MAX_ADDR_LEN];
2429
2430 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2431 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2432 read_unlock_bh(&neigh->lock);
2433 goto nla_put_failure;
2434 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002435 }
2436
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002437 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2438 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2439 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002440 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002441 read_unlock_bh(&neigh->lock);
2442
David S. Miller9a6308d2012-04-01 20:06:28 -04002443 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2444 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2445 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002446
David Aherndf9b0e32018-12-15 14:09:06 -08002447 if (neigh->protocol && nla_put_u8(skb, NDA_PROTOCOL, neigh->protocol))
2448 goto nla_put_failure;
2449
Johannes Berg053c0952015-01-16 22:09:00 +01002450 nlmsg_end(skb, nlh);
2451 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002452
2453nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002454 nlmsg_cancel(skb, nlh);
2455 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456}
2457
Tony Zelenoff84920c12012-01-26 22:28:58 +00002458static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2459 u32 pid, u32 seq, int type, unsigned int flags,
2460 struct neigh_table *tbl)
2461{
2462 struct nlmsghdr *nlh;
2463 struct ndmsg *ndm;
2464
2465 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2466 if (nlh == NULL)
2467 return -EMSGSIZE;
2468
2469 ndm = nlmsg_data(nlh);
2470 ndm->ndm_family = tbl->family;
2471 ndm->ndm_pad1 = 0;
2472 ndm->ndm_pad2 = 0;
2473 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002474 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002475 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002476 ndm->ndm_state = NUD_NONE;
2477
David S. Miller9a6308d2012-04-01 20:06:28 -04002478 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2479 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002480
David Aherndf9b0e32018-12-15 14:09:06 -08002481 if (pn->protocol && nla_put_u8(skb, NDA_PROTOCOL, pn->protocol))
2482 goto nla_put_failure;
2483
Johannes Berg053c0952015-01-16 22:09:00 +01002484 nlmsg_end(skb, nlh);
2485 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002486
2487nla_put_failure:
2488 nlmsg_cancel(skb, nlh);
2489 return -EMSGSIZE;
2490}
2491
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002492static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002493{
2494 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002495 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002496}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002497
David Ahern21fdd092015-09-29 09:32:03 -07002498static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2499{
2500 struct net_device *master;
2501
2502 if (!master_idx)
2503 return false;
2504
Eric Dumazetaab456d2018-10-26 09:33:27 -07002505 master = dev ? netdev_master_upper_dev_get(dev) : NULL;
David Ahern21fdd092015-09-29 09:32:03 -07002506 if (!master || master->ifindex != master_idx)
2507 return true;
2508
2509 return false;
2510}
2511
David Ahern16660f02015-10-03 11:43:46 -07002512static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2513{
Eric Dumazetaab456d2018-10-26 09:33:27 -07002514 if (filter_idx && (!dev || dev->ifindex != filter_idx))
David Ahern16660f02015-10-03 11:43:46 -07002515 return true;
2516
2517 return false;
2518}
2519
David Ahern6f52f802018-10-03 15:33:12 -07002520struct neigh_dump_filter {
2521 int master_idx;
2522 int dev_idx;
2523};
2524
Linus Torvalds1da177e2005-04-16 15:20:36 -07002525static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002526 struct netlink_callback *cb,
2527 struct neigh_dump_filter *filter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002528{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002529 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530 struct neighbour *n;
2531 int rc, h, s_h = cb->args[1];
2532 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002533 struct neigh_hash_table *nht;
David Ahern21fdd092015-09-29 09:32:03 -07002534 unsigned int flags = NLM_F_MULTI;
David Ahern21fdd092015-09-29 09:32:03 -07002535
David Ahern6f52f802018-10-03 15:33:12 -07002536 if (filter->dev_idx || filter->master_idx)
2537 flags |= NLM_F_DUMP_FILTERED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002539 rcu_read_lock_bh();
2540 nht = rcu_dereference_bh(tbl->nht);
2541
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002542 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 if (h > s_h)
2544 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002545 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2546 n != NULL;
2547 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002548 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2549 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002550 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2551 neigh_master_filtered(n->dev, filter->master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002552 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002553 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002555 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002556 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 rc = -1;
2558 goto out;
2559 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002560next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002561 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002562 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 }
2564 rc = skb->len;
2565out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002566 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567 cb->args[1] = h;
2568 cb->args[2] = idx;
2569 return rc;
2570}
2571
Tony Zelenoff84920c12012-01-26 22:28:58 +00002572static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002573 struct netlink_callback *cb,
2574 struct neigh_dump_filter *filter)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002575{
2576 struct pneigh_entry *n;
2577 struct net *net = sock_net(skb->sk);
2578 int rc, h, s_h = cb->args[3];
2579 int idx, s_idx = idx = cb->args[4];
David Ahern6f52f802018-10-03 15:33:12 -07002580 unsigned int flags = NLM_F_MULTI;
2581
2582 if (filter->dev_idx || filter->master_idx)
2583 flags |= NLM_F_DUMP_FILTERED;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002584
2585 read_lock_bh(&tbl->lock);
2586
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002587 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002588 if (h > s_h)
2589 s_idx = 0;
2590 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002591 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002592 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002593 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2594 neigh_master_filtered(n->dev, filter->master_idx))
2595 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002596 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002597 cb->nlh->nlmsg_seq,
David Ahern6f52f802018-10-03 15:33:12 -07002598 RTM_NEWNEIGH, flags, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002599 read_unlock_bh(&tbl->lock);
2600 rc = -1;
2601 goto out;
2602 }
2603 next:
2604 idx++;
2605 }
2606 }
2607
2608 read_unlock_bh(&tbl->lock);
2609 rc = skb->len;
2610out:
2611 cb->args[3] = h;
2612 cb->args[4] = idx;
2613 return rc;
2614
2615}
2616
David Ahern51183d22018-10-07 20:16:36 -07002617static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
2618 bool strict_check,
2619 struct neigh_dump_filter *filter,
2620 struct netlink_ext_ack *extack)
2621{
2622 struct nlattr *tb[NDA_MAX + 1];
2623 int err, i;
2624
2625 if (strict_check) {
2626 struct ndmsg *ndm;
2627
2628 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2629 NL_SET_ERR_MSG(extack, "Invalid header for neighbor dump request");
2630 return -EINVAL;
2631 }
2632
2633 ndm = nlmsg_data(nlh);
2634 if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_ifindex ||
2635 ndm->ndm_state || ndm->ndm_flags || ndm->ndm_type) {
2636 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor dump request");
2637 return -EINVAL;
2638 }
2639
2640 err = nlmsg_parse_strict(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
2641 NULL, extack);
2642 } else {
2643 err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
2644 NULL, extack);
2645 }
2646 if (err < 0)
2647 return err;
2648
2649 for (i = 0; i <= NDA_MAX; ++i) {
2650 if (!tb[i])
2651 continue;
2652
2653 /* all new attributes should require strict_check */
2654 switch (i) {
2655 case NDA_IFINDEX:
2656 if (nla_len(tb[i]) != sizeof(u32)) {
2657 NL_SET_ERR_MSG(extack, "Invalid IFINDEX attribute in neighbor dump request");
2658 return -EINVAL;
2659 }
2660 filter->dev_idx = nla_get_u32(tb[i]);
2661 break;
2662 case NDA_MASTER:
2663 if (nla_len(tb[i]) != sizeof(u32)) {
2664 NL_SET_ERR_MSG(extack, "Invalid MASTER attribute in neighbor dump request");
2665 return -EINVAL;
2666 }
2667 filter->master_idx = nla_get_u32(tb[i]);
2668 break;
2669 default:
2670 if (strict_check) {
2671 NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor dump request");
2672 return -EINVAL;
2673 }
2674 }
2675 }
2676
2677 return 0;
2678}
2679
Thomas Grafc8822a42007-03-22 11:50:06 -07002680static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681{
David Ahern6f52f802018-10-03 15:33:12 -07002682 const struct nlmsghdr *nlh = cb->nlh;
2683 struct neigh_dump_filter filter = {};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684 struct neigh_table *tbl;
2685 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002686 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002687 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002688
David Ahern6f52f802018-10-03 15:33:12 -07002689 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002690
2691 /* check for full ndmsg structure presence, family member is
2692 * the same for both structures
2693 */
David Ahern6f52f802018-10-03 15:33:12 -07002694 if (nlmsg_len(nlh) >= sizeof(struct ndmsg) &&
2695 ((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002696 proxy = 1;
2697
David Ahern51183d22018-10-07 20:16:36 -07002698 err = neigh_valid_dump_req(nlh, cb->strict_check, &filter, cb->extack);
2699 if (err < 0 && cb->strict_check)
2700 return err;
2701
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 s_t = cb->args[0];
2703
WANG Congd7480fd2014-11-10 15:59:36 -08002704 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2705 tbl = neigh_tables[t];
2706
2707 if (!tbl)
2708 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709 if (t < s_t || (family && tbl->family != family))
2710 continue;
2711 if (t > s_t)
2712 memset(&cb->args[1], 0, sizeof(cb->args) -
2713 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002714 if (proxy)
David Ahern6f52f802018-10-03 15:33:12 -07002715 err = pneigh_dump_table(tbl, skb, cb, &filter);
Tony Zelenoff84920c12012-01-26 22:28:58 +00002716 else
David Ahern6f52f802018-10-03 15:33:12 -07002717 err = neigh_dump_table(tbl, skb, cb, &filter);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002718 if (err < 0)
2719 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721
2722 cb->args[0] = t;
2723 return skb->len;
2724}
2725
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08002726static int neigh_valid_get_req(const struct nlmsghdr *nlh,
2727 struct neigh_table **tbl,
2728 void **dst, int *dev_idx, u8 *ndm_flags,
2729 struct netlink_ext_ack *extack)
2730{
2731 struct nlattr *tb[NDA_MAX + 1];
2732 struct ndmsg *ndm;
2733 int err, i;
2734
2735 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2736 NL_SET_ERR_MSG(extack, "Invalid header for neighbor get request");
2737 return -EINVAL;
2738 }
2739
2740 ndm = nlmsg_data(nlh);
2741 if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state ||
2742 ndm->ndm_type) {
2743 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor get request");
2744 return -EINVAL;
2745 }
2746
2747 if (ndm->ndm_flags & ~NTF_PROXY) {
2748 NL_SET_ERR_MSG(extack, "Invalid flags in header for neighbor get request");
2749 return -EINVAL;
2750 }
2751
2752 err = nlmsg_parse_strict(nlh, sizeof(struct ndmsg), tb, NDA_MAX,
2753 nda_policy, extack);
2754 if (err < 0)
2755 return err;
2756
2757 *ndm_flags = ndm->ndm_flags;
2758 *dev_idx = ndm->ndm_ifindex;
2759 *tbl = neigh_find_table(ndm->ndm_family);
2760 if (*tbl == NULL) {
2761 NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
2762 return -EAFNOSUPPORT;
2763 }
2764
2765 for (i = 0; i <= NDA_MAX; ++i) {
2766 if (!tb[i])
2767 continue;
2768
2769 switch (i) {
2770 case NDA_DST:
2771 if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
2772 NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
2773 return -EINVAL;
2774 }
2775 *dst = nla_data(tb[i]);
2776 break;
2777 default:
2778 NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor get request");
2779 return -EINVAL;
2780 }
2781 }
2782
2783 return 0;
2784}
2785
2786static inline size_t neigh_nlmsg_size(void)
2787{
2788 return NLMSG_ALIGN(sizeof(struct ndmsg))
2789 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2790 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2791 + nla_total_size(sizeof(struct nda_cacheinfo))
2792 + nla_total_size(4) /* NDA_PROBES */
2793 + nla_total_size(1); /* NDA_PROTOCOL */
2794}
2795
2796static int neigh_get_reply(struct net *net, struct neighbour *neigh,
2797 u32 pid, u32 seq)
2798{
2799 struct sk_buff *skb;
2800 int err = 0;
2801
2802 skb = nlmsg_new(neigh_nlmsg_size(), GFP_KERNEL);
2803 if (!skb)
2804 return -ENOBUFS;
2805
2806 err = neigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0);
2807 if (err) {
2808 kfree_skb(skb);
2809 goto errout;
2810 }
2811
2812 err = rtnl_unicast(skb, net, pid);
2813errout:
2814 return err;
2815}
2816
2817static inline size_t pneigh_nlmsg_size(void)
2818{
2819 return NLMSG_ALIGN(sizeof(struct ndmsg))
2820 + nla_total_size(MAX_ADDR_LEN); /* NDA_DST */
2821 + nla_total_size(1); /* NDA_PROTOCOL */
2822}
2823
2824static int pneigh_get_reply(struct net *net, struct pneigh_entry *neigh,
2825 u32 pid, u32 seq, struct neigh_table *tbl)
2826{
2827 struct sk_buff *skb;
2828 int err = 0;
2829
2830 skb = nlmsg_new(pneigh_nlmsg_size(), GFP_KERNEL);
2831 if (!skb)
2832 return -ENOBUFS;
2833
2834 err = pneigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0, tbl);
2835 if (err) {
2836 kfree_skb(skb);
2837 goto errout;
2838 }
2839
2840 err = rtnl_unicast(skb, net, pid);
2841errout:
2842 return err;
2843}
2844
2845static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2846 struct netlink_ext_ack *extack)
2847{
2848 struct net *net = sock_net(in_skb->sk);
2849 struct net_device *dev = NULL;
2850 struct neigh_table *tbl = NULL;
2851 struct neighbour *neigh;
2852 void *dst = NULL;
2853 u8 ndm_flags = 0;
2854 int dev_idx = 0;
2855 int err;
2856
2857 err = neigh_valid_get_req(nlh, &tbl, &dst, &dev_idx, &ndm_flags,
2858 extack);
2859 if (err < 0)
2860 return err;
2861
2862 if (dev_idx) {
2863 dev = __dev_get_by_index(net, dev_idx);
2864 if (!dev) {
2865 NL_SET_ERR_MSG(extack, "Unknown device ifindex");
2866 return -ENODEV;
2867 }
2868 }
2869
2870 if (!dst) {
2871 NL_SET_ERR_MSG(extack, "Network address not specified");
2872 return -EINVAL;
2873 }
2874
2875 if (ndm_flags & NTF_PROXY) {
2876 struct pneigh_entry *pn;
2877
2878 pn = pneigh_lookup(tbl, net, dst, dev, 0);
2879 if (!pn) {
2880 NL_SET_ERR_MSG(extack, "Proxy neighbour entry not found");
2881 return -ENOENT;
2882 }
2883 return pneigh_get_reply(net, pn, NETLINK_CB(in_skb).portid,
2884 nlh->nlmsg_seq, tbl);
2885 }
2886
2887 if (!dev) {
2888 NL_SET_ERR_MSG(extack, "No device specified");
2889 return -EINVAL;
2890 }
2891
2892 neigh = neigh_lookup(tbl, dst, dev);
2893 if (!neigh) {
2894 NL_SET_ERR_MSG(extack, "Neighbour entry not found");
2895 return -ENOENT;
2896 }
2897
2898 err = neigh_get_reply(net, neigh, NETLINK_CB(in_skb).portid,
2899 nlh->nlmsg_seq);
2900
2901 neigh_release(neigh);
2902
2903 return err;
2904}
2905
Linus Torvalds1da177e2005-04-16 15:20:36 -07002906void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2907{
2908 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002909 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002910
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002911 rcu_read_lock_bh();
2912 nht = rcu_dereference_bh(tbl->nht);
2913
Eric Dumazet767e97e2010-10-06 17:49:21 -07002914 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002915 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002916 struct neighbour *n;
2917
Eric Dumazet767e97e2010-10-06 17:49:21 -07002918 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2919 n != NULL;
2920 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 cb(n, cookie);
2922 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002923 read_unlock(&tbl->lock);
2924 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925}
2926EXPORT_SYMBOL(neigh_for_each);
2927
2928/* The tbl->lock must be held as a writer and BH disabled. */
2929void __neigh_for_each_release(struct neigh_table *tbl,
2930 int (*cb)(struct neighbour *))
2931{
2932 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002933 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002934
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002935 nht = rcu_dereference_protected(tbl->nht,
2936 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002937 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002938 struct neighbour *n;
2939 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002941 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002942 while ((n = rcu_dereference_protected(*np,
2943 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944 int release;
2945
2946 write_lock(&n->lock);
2947 release = cb(n);
2948 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002949 rcu_assign_pointer(*np,
2950 rcu_dereference_protected(n->next,
2951 lockdep_is_held(&tbl->lock)));
David Ahern58956312018-12-07 12:24:57 -08002952 neigh_mark_dead(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953 } else
2954 np = &n->next;
2955 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002956 if (release)
2957 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002958 }
2959 }
2960}
2961EXPORT_SYMBOL(__neigh_for_each_release);
2962
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002963int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002964 const void *addr, struct sk_buff *skb)
2965{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002966 int err = -EAFNOSUPPORT;
2967 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002968 struct neigh_table *tbl;
2969 struct neighbour *neigh;
2970
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002971 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002972 if (!tbl)
2973 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002974 rcu_read_lock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002975 neigh = __neigh_lookup_noref(tbl, addr, dev);
2976 if (!neigh)
2977 neigh = __neigh_create(tbl, addr, dev, false);
2978 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03002979 if (IS_ERR(neigh)) {
2980 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002981 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03002982 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002983 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03002984 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002985 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002986 else if (index == NEIGH_LINK_TABLE) {
2987 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
2988 addr, NULL, skb->len);
2989 if (err < 0)
2990 goto out_kfree_skb;
2991 err = dev_queue_xmit(skb);
2992 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002993out:
2994 return err;
2995out_kfree_skb:
2996 kfree_skb(skb);
2997 goto out;
2998}
2999EXPORT_SYMBOL(neigh_xmit);
3000
Linus Torvalds1da177e2005-04-16 15:20:36 -07003001#ifdef CONFIG_PROC_FS
3002
3003static struct neighbour *neigh_get_first(struct seq_file *seq)
3004{
3005 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003006 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003007 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 struct neighbour *n = NULL;
3009 int bucket = state->bucket;
3010
3011 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07003012 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07003013 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003014
3015 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003016 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003017 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018 if (state->neigh_sub_iter) {
3019 loff_t fakep = 0;
3020 void *v;
3021
3022 v = state->neigh_sub_iter(state, n, &fakep);
3023 if (!v)
3024 goto next;
3025 }
3026 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
3027 break;
3028 if (n->nud_state & ~NUD_NOARP)
3029 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07003030next:
3031 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003032 }
3033
3034 if (n)
3035 break;
3036 }
3037 state->bucket = bucket;
3038
3039 return n;
3040}
3041
3042static struct neighbour *neigh_get_next(struct seq_file *seq,
3043 struct neighbour *n,
3044 loff_t *pos)
3045{
3046 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003047 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003048 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049
3050 if (state->neigh_sub_iter) {
3051 void *v = state->neigh_sub_iter(state, n, pos);
3052 if (v)
3053 return n;
3054 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07003055 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056
3057 while (1) {
3058 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003059 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003060 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 if (state->neigh_sub_iter) {
3062 void *v = state->neigh_sub_iter(state, n, pos);
3063 if (v)
3064 return n;
3065 goto next;
3066 }
3067 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
3068 break;
3069
3070 if (n->nud_state & ~NUD_NOARP)
3071 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07003072next:
3073 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074 }
3075
3076 if (n)
3077 break;
3078
David S. Millercd089332011-07-11 01:28:12 -07003079 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003080 break;
3081
Eric Dumazet767e97e2010-10-06 17:49:21 -07003082 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003083 }
3084
3085 if (n && pos)
3086 --(*pos);
3087 return n;
3088}
3089
3090static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
3091{
3092 struct neighbour *n = neigh_get_first(seq);
3093
3094 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07003095 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 while (*pos) {
3097 n = neigh_get_next(seq, n, pos);
3098 if (!n)
3099 break;
3100 }
3101 }
3102 return *pos ? NULL : n;
3103}
3104
3105static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
3106{
3107 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003108 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003109 struct neigh_table *tbl = state->tbl;
3110 struct pneigh_entry *pn = NULL;
3111 int bucket = state->bucket;
3112
3113 state->flags |= NEIGH_SEQ_IS_PNEIGH;
3114 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
3115 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003116 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003117 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118 if (pn)
3119 break;
3120 }
3121 state->bucket = bucket;
3122
3123 return pn;
3124}
3125
3126static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
3127 struct pneigh_entry *pn,
3128 loff_t *pos)
3129{
3130 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003131 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003132 struct neigh_table *tbl = state->tbl;
3133
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05003134 do {
3135 pn = pn->next;
3136 } while (pn && !net_eq(pneigh_net(pn), net));
3137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138 while (!pn) {
3139 if (++state->bucket > PNEIGH_HASHMASK)
3140 break;
3141 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003142 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003143 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 if (pn)
3145 break;
3146 }
3147
3148 if (pn && pos)
3149 --(*pos);
3150
3151 return pn;
3152}
3153
3154static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
3155{
3156 struct pneigh_entry *pn = pneigh_get_first(seq);
3157
3158 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07003159 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 while (*pos) {
3161 pn = pneigh_get_next(seq, pn, pos);
3162 if (!pn)
3163 break;
3164 }
3165 }
3166 return *pos ? NULL : pn;
3167}
3168
3169static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
3170{
3171 struct neigh_seq_state *state = seq->private;
3172 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07003173 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174
Chris Larson745e2032008-08-03 01:10:55 -07003175 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003176 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07003177 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178
3179 return rc;
3180}
3181
3182void *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 +00003183 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184{
3185 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003186
3187 state->tbl = tbl;
3188 state->bucket = 0;
3189 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
3190
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003191 rcu_read_lock_bh();
3192 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07003193
Chris Larson745e2032008-08-03 01:10:55 -07003194 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003195}
3196EXPORT_SYMBOL(neigh_seq_start);
3197
3198void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3199{
3200 struct neigh_seq_state *state;
3201 void *rc;
3202
3203 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07003204 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003205 goto out;
3206 }
3207
3208 state = seq->private;
3209 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
3210 rc = neigh_get_next(seq, v, NULL);
3211 if (rc)
3212 goto out;
3213 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
3214 rc = pneigh_get_first(seq);
3215 } else {
3216 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
3217 rc = pneigh_get_next(seq, v, NULL);
3218 }
3219out:
3220 ++(*pos);
3221 return rc;
3222}
3223EXPORT_SYMBOL(neigh_seq_next);
3224
3225void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003226 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003228 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229}
3230EXPORT_SYMBOL(neigh_seq_stop);
3231
3232/* statistics via seq_file */
3233
3234static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
3235{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003236 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003237 int cpu;
3238
3239 if (*pos == 0)
3240 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09003241
Rusty Russell0f23174a2008-12-29 12:23:42 +00003242 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003243 if (!cpu_possible(cpu))
3244 continue;
3245 *pos = cpu+1;
3246 return per_cpu_ptr(tbl->stats, cpu);
3247 }
3248 return NULL;
3249}
3250
3251static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3252{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003253 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003254 int cpu;
3255
Rusty Russell0f23174a2008-12-29 12:23:42 +00003256 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003257 if (!cpu_possible(cpu))
3258 continue;
3259 *pos = cpu+1;
3260 return per_cpu_ptr(tbl->stats, cpu);
3261 }
3262 return NULL;
3263}
3264
3265static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
3266{
3267
3268}
3269
3270static int neigh_stat_seq_show(struct seq_file *seq, void *v)
3271{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003272 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 struct neigh_statistics *st = v;
3274
3275 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07003276 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 -07003277 return 0;
3278 }
3279
3280 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07003281 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282 atomic_read(&tbl->entries),
3283
3284 st->allocs,
3285 st->destroys,
3286 st->hash_grows,
3287
3288 st->lookups,
3289 st->hits,
3290
3291 st->res_failed,
3292
3293 st->rcv_probes_mcast,
3294 st->rcv_probes_ucast,
3295
3296 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07003297 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07003298 st->unres_discards,
3299 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07003300 );
3301
3302 return 0;
3303}
3304
Stephen Hemmingerf6908082007-03-12 14:34:29 -07003305static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003306 .start = neigh_stat_seq_start,
3307 .next = neigh_stat_seq_next,
3308 .stop = neigh_stat_seq_stop,
3309 .show = neigh_stat_seq_show,
3310};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003311#endif /* CONFIG_PROC_FS */
3312
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003313static void __neigh_notify(struct neighbour *n, int type, int flags,
3314 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003315{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003316 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003317 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07003318 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319
Thomas Graf339bf982006-11-10 14:10:15 -08003320 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003321 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07003322 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003323
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003324 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08003325 if (err < 0) {
3326 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
3327 WARN_ON(err == -EMSGSIZE);
3328 kfree_skb(skb);
3329 goto errout;
3330 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08003331 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
3332 return;
Thomas Grafb8673312006-08-15 00:33:14 -07003333errout:
3334 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08003335 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07003336}
3337
3338void neigh_app_ns(struct neighbour *n)
3339{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003340 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003342EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343
3344#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08003345static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02003346static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08003347static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003348
Joe Perchesfe2c6332013-06-11 23:04:25 -07003349static int proc_unres_qlen(struct ctl_table *ctl, int write,
3350 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003351{
3352 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07003353 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003354
Shan Weice46cc62012-12-04 18:49:15 +00003355 tmp.extra1 = &zero;
3356 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003357 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00003358
3359 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
3360 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3361
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003362 if (write && !ret)
3363 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
3364 return ret;
3365}
3366
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003367static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
3368 int family)
3369{
Jiri Pirkobba24892013-12-07 19:26:57 +01003370 switch (family) {
3371 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003372 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01003373 case AF_INET6:
3374 return __in6_dev_nd_parms_get_rcu(dev);
3375 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003376 return NULL;
3377}
3378
3379static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
3380 int index)
3381{
3382 struct net_device *dev;
3383 int family = neigh_parms_family(p);
3384
3385 rcu_read_lock();
3386 for_each_netdev_rcu(net, dev) {
3387 struct neigh_parms *dst_p =
3388 neigh_get_dev_parms_rcu(dev, family);
3389
3390 if (dst_p && !test_bit(index, dst_p->data_state))
3391 dst_p->data[index] = p->data[index];
3392 }
3393 rcu_read_unlock();
3394}
3395
3396static void neigh_proc_update(struct ctl_table *ctl, int write)
3397{
3398 struct net_device *dev = ctl->extra1;
3399 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01003400 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003401 int index = (int *) ctl->data - p->data;
3402
3403 if (!write)
3404 return;
3405
3406 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01003407 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
3408 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003409 if (!dev) /* NULL dev means this is default value */
3410 neigh_copy_dflt_parms(net, p, index);
3411}
3412
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003413static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3414 void __user *buffer,
3415 size_t *lenp, loff_t *ppos)
3416{
3417 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003418 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003419
3420 tmp.extra1 = &zero;
3421 tmp.extra2 = &int_max;
3422
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003423 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3424 neigh_proc_update(ctl, write);
3425 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003426}
3427
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003428int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3429 void __user *buffer, size_t *lenp, loff_t *ppos)
3430{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003431 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3432
3433 neigh_proc_update(ctl, write);
3434 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003435}
3436EXPORT_SYMBOL(neigh_proc_dointvec);
3437
3438int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3439 void __user *buffer,
3440 size_t *lenp, loff_t *ppos)
3441{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003442 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3443
3444 neigh_proc_update(ctl, write);
3445 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003446}
3447EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3448
3449static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3450 void __user *buffer,
3451 size_t *lenp, loff_t *ppos)
3452{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003453 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3454
3455 neigh_proc_update(ctl, write);
3456 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003457}
3458
3459int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3460 void __user *buffer,
3461 size_t *lenp, loff_t *ppos)
3462{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003463 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3464
3465 neigh_proc_update(ctl, write);
3466 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003467}
3468EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3469
3470static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3471 void __user *buffer,
3472 size_t *lenp, loff_t *ppos)
3473{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003474 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3475
3476 neigh_proc_update(ctl, write);
3477 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003478}
3479
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003480static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3481 void __user *buffer,
3482 size_t *lenp, loff_t *ppos)
3483{
3484 struct neigh_parms *p = ctl->extra2;
3485 int ret;
3486
3487 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3488 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3489 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3490 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3491 else
3492 ret = -1;
3493
3494 if (write && ret == 0) {
3495 /* update reachable_time as well, otherwise, the change will
3496 * only be effective after the next time neigh_periodic_work
3497 * decides to recompute it
3498 */
3499 p->reachable_time =
3500 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3501 }
3502 return ret;
3503}
3504
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003505#define NEIGH_PARMS_DATA_OFFSET(index) \
3506 (&((struct neigh_parms *) 0)->data[index])
3507
3508#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3509 [NEIGH_VAR_ ## attr] = { \
3510 .procname = name, \
3511 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3512 .maxlen = sizeof(int), \
3513 .mode = mval, \
3514 .proc_handler = proc, \
3515 }
3516
3517#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3518 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3519
3520#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003521 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003522
3523#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003524 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003525
3526#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003527 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003528
3529#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003530 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003531
3532#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003533 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003534
Linus Torvalds1da177e2005-04-16 15:20:36 -07003535static struct neigh_sysctl_table {
3536 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003537 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003538} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003540 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3541 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3542 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003543 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003544 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3545 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3546 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3547 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3548 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3549 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3550 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3551 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3552 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3553 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3554 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3555 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003556 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003557 .procname = "gc_interval",
3558 .maxlen = sizeof(int),
3559 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003560 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003561 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003562 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003563 .procname = "gc_thresh1",
3564 .maxlen = sizeof(int),
3565 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003566 .extra1 = &zero,
3567 .extra2 = &int_max,
3568 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003570 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003571 .procname = "gc_thresh2",
3572 .maxlen = sizeof(int),
3573 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003574 .extra1 = &zero,
3575 .extra2 = &int_max,
3576 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003578 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003579 .procname = "gc_thresh3",
3580 .maxlen = sizeof(int),
3581 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003582 .extra1 = &zero,
3583 .extra2 = &int_max,
3584 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003585 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003586 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 },
3588};
3589
3590int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003591 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003592{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003593 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003594 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003595 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003596 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003597 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003598
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003599 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003600 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003601 goto err;
3602
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003603 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003604 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003605 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003606 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003607 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003608
3609 if (dev) {
3610 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003611 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003612 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3613 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003614 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003615 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003616 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003617 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3618 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3619 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3620 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 }
3622
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003623 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003624 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003625 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003626 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003627 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003629 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003631 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003632 } else {
3633 /* Those handlers will update p->reachable_time after
3634 * base_reachable_time(_ms) is set to ensure the new timer starts being
3635 * applied after the next neighbour update instead of waiting for
3636 * neigh_periodic_work to update its value (can be multiple minutes)
3637 * So any handler that replaces them should do this as well
3638 */
3639 /* ReachableTime */
3640 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3641 neigh_proc_base_reachable_time;
3642 /* ReachableTime (in milliseconds) */
3643 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3644 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003645 }
3646
Eric W. Biederman464dc802012-11-16 03:02:59 +00003647 /* Don't export sysctls to unprivileged users */
3648 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3649 t->neigh_vars[0].procname = NULL;
3650
Jiri Pirko73af6142013-12-07 19:26:55 +01003651 switch (neigh_parms_family(p)) {
3652 case AF_INET:
3653 p_name = "ipv4";
3654 break;
3655 case AF_INET6:
3656 p_name = "ipv6";
3657 break;
3658 default:
3659 BUG();
3660 }
3661
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003662 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3663 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003664 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003665 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003666 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003667 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003668
Linus Torvalds1da177e2005-04-16 15:20:36 -07003669 p->sysctl_table = t;
3670 return 0;
3671
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003672free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003674err:
3675 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003676}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003677EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678
3679void neigh_sysctl_unregister(struct neigh_parms *p)
3680{
3681 if (p->sysctl_table) {
3682 struct neigh_sysctl_table *t = p->sysctl_table;
3683 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003684 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003685 kfree(t);
3686 }
3687}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003688EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689
3690#endif /* CONFIG_SYSCTL */
3691
Thomas Grafc8822a42007-03-22 11:50:06 -07003692static int __init neigh_init(void)
3693{
Florian Westphalb97bac62017-08-09 20:41:48 +02003694 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3695 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08003696 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003697
Greg Rosec7ac8672011-06-10 01:27:09 +00003698 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003699 0);
3700 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003701
3702 return 0;
3703}
3704
3705subsys_initcall(neigh_init);