blob: 26da97359d5b55b0f3c4d018420c3944dbdf4908 [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/*
3 * Generic address resolution entity
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
8 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * Fixes:
10 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
11 * Harald Welte Add neighbour cache statistics like rtstat
12 */
13
Joe Perchese005d192012-05-16 19:58:40 +000014#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090016#include <linux/slab.h>
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +030017#include <linux/kmemleak.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/netdevice.h>
23#include <linux/proc_fs.h>
24#ifdef CONFIG_SYSCTL
25#include <linux/sysctl.h>
26#endif
27#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020028#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070029#include <net/neighbour.h>
David Ahern4b2a2bf2019-05-01 18:18:42 -070030#include <net/arp.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <net/dst.h>
32#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070033#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070034#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070035#include <linux/rtnetlink.h>
36#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070037#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070038#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010039#include <linux/inetdevice.h>
Jiri Pirkobba24892013-12-07 19:26:57 +010040#include <net/addrconf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Roopa Prabhu56dd18a2019-02-14 09:15:11 -080042#include <trace/events/neigh.h>
43
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 Prabhu56dd18a2019-02-14 09:15:11 -0800104 trace_neigh_cleanup_and_release(neigh, 0);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -0700105 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
Ido Schimmel53f800e2016-12-23 09:32:48 +0100106 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Thomas Graf4f494552007-08-08 23:12:36 -0700107 neigh_release(neigh);
108}
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110/*
111 * It is random distribution in the interval (1/2)*base...(3/2)*base.
112 * It corresponds to default IPv6 settings and is not overridable,
113 * because it is really reasonable choice.
114 */
115
116unsigned long neigh_rand_reach_time(unsigned long base)
117{
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -0500118 return base ? (prandom_u32() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900120EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
David Ahern58956312018-12-07 12:24:57 -0800122static void neigh_mark_dead(struct neighbour *n)
123{
124 n->dead = 1;
125 if (!list_empty(&n->gc_list)) {
126 list_del_init(&n->gc_list);
127 atomic_dec(&n->tbl->gc_entries);
128 }
129}
130
David Ahern9c29a2f2018-12-11 18:57:21 -0700131static void neigh_update_gc_list(struct neighbour *n)
David Ahern58956312018-12-07 12:24:57 -0800132{
David Aherne997f8a2018-12-11 18:57:25 -0700133 bool on_gc_list, exempt_from_gc;
David Ahern58956312018-12-07 12:24:57 -0800134
David Ahern9c29a2f2018-12-11 18:57:21 -0700135 write_lock_bh(&n->tbl->lock);
136 write_lock(&n->lock);
David Ahern58956312018-12-07 12:24:57 -0800137
David Aherne997f8a2018-12-11 18:57:25 -0700138 /* remove from the gc list if new state is permanent or if neighbor
139 * is externally learned; otherwise entry should be on the gc list
David Ahern58956312018-12-07 12:24:57 -0800140 */
David Aherne997f8a2018-12-11 18:57:25 -0700141 exempt_from_gc = n->nud_state & NUD_PERMANENT ||
142 n->flags & NTF_EXT_LEARNED;
David Ahern9c29a2f2018-12-11 18:57:21 -0700143 on_gc_list = !list_empty(&n->gc_list);
David Ahern8cc196d2018-12-10 13:54:07 -0800144
David Aherne997f8a2018-12-11 18:57:25 -0700145 if (exempt_from_gc && on_gc_list) {
David Ahern9c29a2f2018-12-11 18:57:21 -0700146 list_del_init(&n->gc_list);
David Ahern58956312018-12-07 12:24:57 -0800147 atomic_dec(&n->tbl->gc_entries);
David Aherne997f8a2018-12-11 18:57:25 -0700148 } else if (!exempt_from_gc && !on_gc_list) {
David Ahern58956312018-12-07 12:24:57 -0800149 /* add entries to the tail; cleaning removes from the front */
150 list_add_tail(&n->gc_list, &n->tbl->gc_list);
151 atomic_inc(&n->tbl->gc_entries);
152 }
David Ahern9c29a2f2018-12-11 18:57:21 -0700153
154 write_unlock(&n->lock);
155 write_unlock_bh(&n->tbl->lock);
David Ahern58956312018-12-07 12:24:57 -0800156}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157
David Aherne997f8a2018-12-11 18:57:25 -0700158static bool neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
David Ahern526f1b52018-12-11 18:57:24 -0700159 int *notify)
160{
David Aherne997f8a2018-12-11 18:57:25 -0700161 bool rc = false;
David Ahern526f1b52018-12-11 18:57:24 -0700162 u8 ndm_flags;
163
164 if (!(flags & NEIGH_UPDATE_F_ADMIN))
David Aherne997f8a2018-12-11 18:57:25 -0700165 return rc;
David Ahern526f1b52018-12-11 18:57:24 -0700166
167 ndm_flags = (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0;
168 if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) {
169 if (ndm_flags & NTF_EXT_LEARNED)
170 neigh->flags |= NTF_EXT_LEARNED;
171 else
172 neigh->flags &= ~NTF_EXT_LEARNED;
David Aherne997f8a2018-12-11 18:57:25 -0700173 rc = true;
David Ahern526f1b52018-12-11 18:57:24 -0700174 *notify = 1;
175 }
David Aherne997f8a2018-12-11 18:57:25 -0700176
177 return rc;
David Ahern526f1b52018-12-11 18:57:24 -0700178}
179
David Ahern7e6f1822018-12-11 18:57:23 -0700180static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np,
181 struct neigh_table *tbl)
Sowmini Varadhan50710342017-06-02 09:01:49 -0700182{
183 bool retval = false;
184
185 write_lock(&n->lock);
David Ahern7e6f1822018-12-11 18:57:23 -0700186 if (refcount_read(&n->refcnt) == 1) {
Sowmini Varadhan50710342017-06-02 09:01:49 -0700187 struct neighbour *neigh;
188
189 neigh = rcu_dereference_protected(n->next,
190 lockdep_is_held(&tbl->lock));
191 rcu_assign_pointer(*np, neigh);
David Ahern58956312018-12-07 12:24:57 -0800192 neigh_mark_dead(n);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700193 retval = true;
194 }
195 write_unlock(&n->lock);
196 if (retval)
197 neigh_cleanup_and_release(n);
198 return retval;
199}
200
201bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
202{
203 struct neigh_hash_table *nht;
204 void *pkey = ndel->primary_key;
205 u32 hash_val;
206 struct neighbour *n;
207 struct neighbour __rcu **np;
208
209 nht = rcu_dereference_protected(tbl->nht,
210 lockdep_is_held(&tbl->lock));
211 hash_val = tbl->hash(pkey, ndel->dev, nht->hash_rnd);
212 hash_val = hash_val >> (32 - nht->hash_shift);
213
214 np = &nht->hash_buckets[hash_val];
215 while ((n = rcu_dereference_protected(*np,
216 lockdep_is_held(&tbl->lock)))) {
217 if (n == ndel)
David Ahern7e6f1822018-12-11 18:57:23 -0700218 return neigh_del(n, np, tbl);
Sowmini Varadhan50710342017-06-02 09:01:49 -0700219 np = &n->next;
220 }
221 return false;
222}
223
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224static int neigh_forced_gc(struct neigh_table *tbl)
225{
David Ahern58956312018-12-07 12:24:57 -0800226 int max_clean = atomic_read(&tbl->gc_entries) - tbl->gc_thresh2;
227 unsigned long tref = jiffies - 5 * HZ;
David Ahern58956312018-12-07 12:24:57 -0800228 struct neighbour *n, *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229 int shrunk = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230
231 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
232
233 write_lock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700234
David Ahern58956312018-12-07 12:24:57 -0800235 list_for_each_entry_safe(n, tmp, &tbl->gc_list, gc_list) {
236 if (refcount_read(&n->refcnt) == 1) {
237 bool remove = false;
238
239 write_lock(&n->lock);
David Ahern758a7f02018-12-11 18:57:22 -0700240 if ((n->nud_state == NUD_FAILED) ||
David Aherne997f8a2018-12-11 18:57:25 -0700241 time_after(tref, n->updated))
David Ahern58956312018-12-07 12:24:57 -0800242 remove = true;
243 write_unlock(&n->lock);
244
245 if (remove && neigh_remove_one(n, tbl))
246 shrunk++;
247 if (shrunk >= max_clean)
248 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249 }
250 }
251
252 tbl->last_flush = jiffies;
253
254 write_unlock_bh(&tbl->lock);
255
256 return shrunk;
257}
258
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800259static void neigh_add_timer(struct neighbour *n, unsigned long when)
260{
261 neigh_hold(n);
262 if (unlikely(mod_timer(&n->timer, when))) {
263 printk("NEIGH: BUG, double timer add, state is %x\n",
264 n->nud_state);
265 dump_stack();
266 }
267}
268
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269static int neigh_del_timer(struct neighbour *n)
270{
271 if ((n->nud_state & NUD_IN_TIMER) &&
272 del_timer(&n->timer)) {
273 neigh_release(n);
274 return 1;
275 }
276 return 0;
277}
278
279static void pneigh_queue_purge(struct sk_buff_head *list)
280{
281 struct sk_buff *skb;
282
283 while ((skb = skb_dequeue(list)) != NULL) {
284 dev_put(skb->dev);
285 kfree_skb(skb);
286 }
287}
288
David Ahern859bd2e2018-10-11 20:33:49 -0700289static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
290 bool skip_perm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291{
292 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000293 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700294
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000295 nht = rcu_dereference_protected(tbl->nht,
296 lockdep_is_held(&tbl->lock));
297
David S. Millercd089332011-07-11 01:28:12 -0700298 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700299 struct neighbour *n;
300 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700301
Eric Dumazet767e97e2010-10-06 17:49:21 -0700302 while ((n = rcu_dereference_protected(*np,
303 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700304 if (dev && n->dev != dev) {
305 np = &n->next;
306 continue;
307 }
David Ahern859bd2e2018-10-11 20:33:49 -0700308 if (skip_perm && n->nud_state & NUD_PERMANENT) {
309 np = &n->next;
310 continue;
311 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700312 rcu_assign_pointer(*np,
313 rcu_dereference_protected(n->next,
314 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700315 write_lock(&n->lock);
316 neigh_del_timer(n);
David Ahern58956312018-12-07 12:24:57 -0800317 neigh_mark_dead(n);
Reshetova, Elena9f237432017-06-30 13:07:55 +0300318 if (refcount_read(&n->refcnt) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319 /* The most unpleasant situation.
320 We must destroy neighbour entry,
321 but someone still uses it.
322
323 The destroy will be delayed until
324 the last user releases us, but
325 we must kill timers etc. and move
326 it to safe state.
327 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700328 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000329 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330 n->output = neigh_blackhole;
331 if (n->nud_state & NUD_VALID)
332 n->nud_state = NUD_NOARP;
333 else
334 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000335 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 }
337 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700338 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339 }
340 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000341}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342
Herbert Xu49636bb2005-10-23 17:18:00 +1000343void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
344{
345 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700346 neigh_flush_dev(tbl, dev, false);
Herbert Xu49636bb2005-10-23 17:18:00 +1000347 write_unlock_bh(&tbl->lock);
348}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900349EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000350
David Ahern859bd2e2018-10-11 20:33:49 -0700351static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
352 bool skip_perm)
Herbert Xu49636bb2005-10-23 17:18:00 +1000353{
354 write_lock_bh(&tbl->lock);
David Ahern859bd2e2018-10-11 20:33:49 -0700355 neigh_flush_dev(tbl, dev, skip_perm);
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200356 pneigh_ifdown_and_unlock(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700357
358 del_timer_sync(&tbl->proxy_timer);
359 pneigh_queue_purge(&tbl->proxy_queue);
360 return 0;
361}
David Ahern859bd2e2018-10-11 20:33:49 -0700362
363int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev)
364{
365 __neigh_ifdown(tbl, dev, true);
366 return 0;
367}
368EXPORT_SYMBOL(neigh_carrier_down);
369
370int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
371{
372 __neigh_ifdown(tbl, dev, false);
373 return 0;
374}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900375EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376
David Ahern58956312018-12-07 12:24:57 -0800377static struct neighbour *neigh_alloc(struct neigh_table *tbl,
378 struct net_device *dev,
David Aherne997f8a2018-12-11 18:57:25 -0700379 bool exempt_from_gc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380{
381 struct neighbour *n = NULL;
382 unsigned long now = jiffies;
383 int entries;
384
David Aherne997f8a2018-12-11 18:57:25 -0700385 if (exempt_from_gc)
David Ahern58956312018-12-07 12:24:57 -0800386 goto do_alloc;
387
388 entries = atomic_inc_return(&tbl->gc_entries) - 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700389 if (entries >= tbl->gc_thresh3 ||
390 (entries >= tbl->gc_thresh2 &&
391 time_after(now, tbl->last_flush + 5 * HZ))) {
392 if (!neigh_forced_gc(tbl) &&
Rick Jonesfb811392015-08-07 11:10:37 -0700393 entries >= tbl->gc_thresh3) {
394 net_info_ratelimited("%s: neighbor table overflow!\n",
395 tbl->id);
396 NEIGH_CACHE_STAT_INC(tbl, table_fulls);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 goto out_entries;
Rick Jonesfb811392015-08-07 11:10:37 -0700398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 }
400
David Ahern58956312018-12-07 12:24:57 -0800401do_alloc:
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000402 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700403 if (!n)
404 goto out_entries;
405
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700406 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700407 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000408 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 n->updated = n->used = now;
410 n->nud_state = NUD_NONE;
411 n->output = neigh_blackhole;
David S. Millerf6b72b622011-07-14 07:53:20 -0700412 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700413 n->parms = neigh_parms_clone(&tbl->parms);
Kees Cooke99e88a2017-10-16 14:43:17 -0700414 timer_setup(&n->timer, neigh_timer_handler, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700415
416 NEIGH_CACHE_STAT_INC(tbl, allocs);
417 n->tbl = tbl;
Reshetova, Elena9f237432017-06-30 13:07:55 +0300418 refcount_set(&n->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419 n->dead = 1;
David Ahern8cc196d2018-12-10 13:54:07 -0800420 INIT_LIST_HEAD(&n->gc_list);
David Ahern58956312018-12-07 12:24:57 -0800421
422 atomic_inc(&tbl->entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423out:
424 return n;
425
426out_entries:
David Aherne997f8a2018-12-11 18:57:25 -0700427 if (!exempt_from_gc)
David Ahern58956312018-12-07 12:24:57 -0800428 atomic_dec(&tbl->gc_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429 goto out;
430}
431
David S. Miller2c2aba62011-12-28 15:06:58 -0500432static void neigh_get_hash_rnd(u32 *x)
433{
Jason A. Donenfeldb3d0f782017-06-07 23:00:05 -0400434 *x = get_random_u32() | 1;
David S. Miller2c2aba62011-12-28 15:06:58 -0500435}
436
David S. Millercd089332011-07-11 01:28:12 -0700437static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438{
David S. Millercd089332011-07-11 01:28:12 -0700439 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000440 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000441 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500442 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000444 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
445 if (!ret)
446 return NULL;
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300447 if (size <= PAGE_SIZE) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000448 buckets = kzalloc(size, GFP_ATOMIC);
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300449 } else {
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000450 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000451 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
452 get_order(size));
Konstantin Khlebnikov01b833a2019-01-14 13:38:43 +0300453 kmemleak_alloc(buckets, size, 1, GFP_ATOMIC);
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300454 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000455 if (!buckets) {
456 kfree(ret);
457 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000459 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700460 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500461 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
462 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 return ret;
464}
465
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000466static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000468 struct neigh_hash_table *nht = container_of(head,
469 struct neigh_hash_table,
470 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700471 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000472 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300474 if (size <= PAGE_SIZE) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000475 kfree(buckets);
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300476 } else {
477 kmemleak_free(buckets);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000478 free_pages((unsigned long)buckets, get_order(size));
Konstantin Khlebnikov85704cb2019-01-08 12:30:00 +0300479 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000480 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481}
482
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000483static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700484 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000486 unsigned int i, hash;
487 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
490
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000491 old_nht = rcu_dereference_protected(tbl->nht,
492 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700493 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000494 if (!new_nht)
495 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496
David S. Millercd089332011-07-11 01:28:12 -0700497 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 struct neighbour *n, *next;
499
Eric Dumazet767e97e2010-10-06 17:49:21 -0700500 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
501 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000502 n != NULL;
503 n = next) {
504 hash = tbl->hash(n->primary_key, n->dev,
505 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
David S. Millercd089332011-07-11 01:28:12 -0700507 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700508 next = rcu_dereference_protected(n->next,
509 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510
Eric Dumazet767e97e2010-10-06 17:49:21 -0700511 rcu_assign_pointer(n->next,
512 rcu_dereference_protected(
513 new_nht->hash_buckets[hash],
514 lockdep_is_held(&tbl->lock)));
515 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 }
517 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700518
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000519 rcu_assign_pointer(tbl->nht, new_nht);
520 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
521 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522}
523
524struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
525 struct net_device *dev)
526{
527 struct neighbour *n;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900528
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 NEIGH_CACHE_STAT_INC(tbl, lookups);
530
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000531 rcu_read_lock_bh();
Eric W. Biederman60395a22015-03-03 17:10:44 -0600532 n = __neigh_lookup_noref(tbl, pkey, dev);
533 if (n) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300534 if (!refcount_inc_not_zero(&n->refcnt))
Eric W. Biederman60395a22015-03-03 17:10:44 -0600535 n = NULL;
536 NEIGH_CACHE_STAT_INC(tbl, hits);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700538
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000539 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 return n;
541}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900542EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543
Eric W. Biederman426b5302008-01-24 00:13:18 -0800544struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
545 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546{
547 struct neighbour *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300548 unsigned int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800549 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000550 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
552 NEIGH_CACHE_STAT_INC(tbl, lookups);
553
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000554 rcu_read_lock_bh();
555 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700556 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700557
558 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
559 n != NULL;
560 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800561 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900562 net_eq(dev_net(n->dev), net)) {
Reshetova, Elena9f237432017-06-30 13:07:55 +0300563 if (!refcount_inc_not_zero(&n->refcnt))
Eric Dumazet767e97e2010-10-06 17:49:21 -0700564 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 NEIGH_CACHE_STAT_INC(tbl, hits);
566 break;
567 }
568 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700569
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000570 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 return n;
572}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900573EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
David Ahern58956312018-12-07 12:24:57 -0800575static struct neighbour *___neigh_create(struct neigh_table *tbl,
576 const void *pkey,
577 struct net_device *dev,
David Aherne997f8a2018-12-11 18:57:25 -0700578 bool exempt_from_gc, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579{
David Aherne997f8a2018-12-11 18:57:25 -0700580 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 u32 hash_val;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300582 unsigned int key_len = tbl->key_len;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 int error;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000584 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585
David Ahernfc651002019-05-22 12:22:21 -0700586 trace_neigh_create(tbl, dev, pkey, n, exempt_from_gc);
587
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 if (!n) {
589 rc = ERR_PTR(-ENOBUFS);
590 goto out;
591 }
592
593 memcpy(n->primary_key, pkey, key_len);
594 n->dev = dev;
595 dev_hold(dev);
596
597 /* Protocol specific setup. */
598 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
599 rc = ERR_PTR(error);
600 goto out_neigh_release;
601 }
602
David Millerda6a8fa2011-07-25 00:01:38 +0000603 if (dev->netdev_ops->ndo_neigh_construct) {
Jiri Pirko503eebc2016-07-05 11:27:37 +0200604 error = dev->netdev_ops->ndo_neigh_construct(dev, n);
David Millerda6a8fa2011-07-25 00:01:38 +0000605 if (error < 0) {
606 rc = ERR_PTR(error);
607 goto out_neigh_release;
608 }
609 }
610
David S. Miller447f2192011-12-19 15:04:41 -0500611 /* Device specific setup. */
612 if (n->parms->neigh_setup &&
613 (error = n->parms->neigh_setup(n)) < 0) {
614 rc = ERR_PTR(error);
615 goto out_neigh_release;
616 }
617
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100618 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619
620 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000621 nht = rcu_dereference_protected(tbl->nht,
622 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623
David S. Millercd089332011-07-11 01:28:12 -0700624 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
625 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626
Jim Westfall096b9852018-01-14 04:18:50 -0800627 hash_val = tbl->hash(n->primary_key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
629 if (n->parms->dead) {
630 rc = ERR_PTR(-EINVAL);
631 goto out_tbl_unlock;
632 }
633
Eric Dumazet767e97e2010-10-06 17:49:21 -0700634 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
635 lockdep_is_held(&tbl->lock));
636 n1 != NULL;
637 n1 = rcu_dereference_protected(n1->next,
638 lockdep_is_held(&tbl->lock))) {
Jim Westfall096b9852018-01-14 04:18:50 -0800639 if (dev == n1->dev && !memcmp(n1->primary_key, n->primary_key, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700640 if (want_ref)
641 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642 rc = n1;
643 goto out_tbl_unlock;
644 }
645 }
646
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647 n->dead = 0;
David Aherne997f8a2018-12-11 18:57:25 -0700648 if (!exempt_from_gc)
David Ahern8cc196d2018-12-10 13:54:07 -0800649 list_add_tail(&n->gc_list, &n->tbl->gc_list);
650
David S. Millera263b302012-07-02 02:02:15 -0700651 if (want_ref)
652 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700653 rcu_assign_pointer(n->next,
654 rcu_dereference_protected(nht->hash_buckets[hash_val],
655 lockdep_is_held(&tbl->lock)));
656 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000658 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700659 rc = n;
660out:
661 return rc;
662out_tbl_unlock:
663 write_unlock_bh(&tbl->lock);
664out_neigh_release:
David Ahern64c6f4b2019-05-01 18:08:34 -0700665 if (!exempt_from_gc)
666 atomic_dec(&tbl->gc_entries);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667 neigh_release(n);
668 goto out;
669}
David Ahern58956312018-12-07 12:24:57 -0800670
671struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
672 struct net_device *dev, bool want_ref)
673{
674 return ___neigh_create(tbl, pkey, dev, false, want_ref);
675}
David S. Millera263b302012-07-02 02:02:15 -0700676EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300678static u32 pneigh_hash(const void *pkey, unsigned int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700679{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700680 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700681 hash_val ^= (hash_val >> 16);
682 hash_val ^= hash_val >> 8;
683 hash_val ^= hash_val >> 4;
684 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900685 return hash_val;
686}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700687
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900688static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
689 struct net *net,
690 const void *pkey,
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300691 unsigned int key_len,
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900692 struct net_device *dev)
693{
694 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700695 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900696 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700697 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900698 return n;
699 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700700 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900701 return NULL;
702}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700703
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900704struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
705 struct net *net, const void *pkey, struct net_device *dev)
706{
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300707 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900708 u32 hash_val = pneigh_hash(pkey, key_len);
709
710 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
711 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700712}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900713EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700714
Eric W. Biederman426b5302008-01-24 00:13:18 -0800715struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
716 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 struct net_device *dev, int creat)
718{
719 struct pneigh_entry *n;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300720 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900721 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722
723 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900724 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
725 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900727
728 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729 goto out;
730
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700731 ASSERT_RTNL();
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
734 if (!n)
735 goto out;
736
David Ahern754d5da2018-12-19 15:53:22 -0800737 n->protocol = 0;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -0500738 write_pnet(&n->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 memcpy(n->key, pkey, key_len);
740 n->dev = dev;
741 if (dev)
742 dev_hold(dev);
743
744 if (tbl->pconstructor && tbl->pconstructor(n)) {
745 if (dev)
746 dev_put(dev);
747 kfree(n);
748 n = NULL;
749 goto out;
750 }
751
752 write_lock_bh(&tbl->lock);
753 n->next = tbl->phash_buckets[hash_val];
754 tbl->phash_buckets[hash_val] = n;
755 write_unlock_bh(&tbl->lock);
756out:
757 return n;
758}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900759EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760
761
Eric W. Biederman426b5302008-01-24 00:13:18 -0800762int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 struct net_device *dev)
764{
765 struct pneigh_entry *n, **np;
Alexey Dobriyan01ccdf12017-09-23 23:03:04 +0300766 unsigned int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900767 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768
769 write_lock_bh(&tbl->lock);
770 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
771 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800772 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900773 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 *np = n->next;
775 write_unlock_bh(&tbl->lock);
776 if (tbl->pdestructor)
777 tbl->pdestructor(n);
778 if (n->dev)
779 dev_put(n->dev);
780 kfree(n);
781 return 0;
782 }
783 }
784 write_unlock_bh(&tbl->lock);
785 return -ENOENT;
786}
787
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200788static int pneigh_ifdown_and_unlock(struct neigh_table *tbl,
789 struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790{
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200791 struct pneigh_entry *n, **np, *freelist = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 u32 h;
793
794 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
795 np = &tbl->phash_buckets[h];
796 while ((n = *np) != NULL) {
797 if (!dev || n->dev == dev) {
798 *np = n->next;
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200799 n->next = freelist;
800 freelist = n;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 continue;
802 }
803 np = &n->next;
804 }
805 }
Wolfgang Bumiller53b76cd2018-04-12 10:46:55 +0200806 write_unlock_bh(&tbl->lock);
807 while ((n = freelist)) {
808 freelist = n->next;
809 n->next = NULL;
810 if (tbl->pdestructor)
811 tbl->pdestructor(n);
812 if (n->dev)
813 dev_put(n->dev);
814 kfree(n);
815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 return -ENOENT;
817}
818
Denis V. Lunev06f05112008-01-24 00:30:58 -0800819static void neigh_parms_destroy(struct neigh_parms *parms);
820
821static inline void neigh_parms_put(struct neigh_parms *parms)
822{
Reshetova, Elena63439442017-06-30 13:07:56 +0300823 if (refcount_dec_and_test(&parms->refcnt))
Denis V. Lunev06f05112008-01-24 00:30:58 -0800824 neigh_parms_destroy(parms);
825}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826
827/*
828 * neighbour must already be out of the table;
829 *
830 */
831void neigh_destroy(struct neighbour *neigh)
832{
David Millerda6a8fa2011-07-25 00:01:38 +0000833 struct net_device *dev = neigh->dev;
834
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
836
837 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000838 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 dump_stack();
840 return;
841 }
842
843 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000844 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700845
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700846 write_lock_bh(&neigh->lock);
847 __skb_queue_purge(&neigh->arp_queue);
848 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000849 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700850
David S. Miller447f2192011-12-19 15:04:41 -0500851 if (dev->netdev_ops->ndo_neigh_destroy)
Jiri Pirko503eebc2016-07-05 11:27:37 +0200852 dev->netdev_ops->ndo_neigh_destroy(dev, neigh);
David S. Miller447f2192011-12-19 15:04:41 -0500853
David Millerda6a8fa2011-07-25 00:01:38 +0000854 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855 neigh_parms_put(neigh->parms);
856
Joe Perchesd5d427c2013-04-15 15:17:19 +0000857 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858
859 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000860 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900862EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863
864/* Neighbour state is suspicious;
865 disable fast path.
866
867 Called with write_locked neigh.
868 */
869static void neigh_suspect(struct neighbour *neigh)
870{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000871 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700872
873 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700874}
875
876/* Neighbour state is OK;
877 enable fast path.
878
879 Called with write_locked neigh.
880 */
881static void neigh_connect(struct neighbour *neigh)
882{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000883 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
885 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886}
887
Eric Dumazete4c4e442009-07-30 03:15:07 +0000888static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000890 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700891 struct neighbour *n;
892 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000893 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000894 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700895
896 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
897
Eric Dumazete4c4e442009-07-30 03:15:07 +0000898 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000899 nht = rcu_dereference_protected(tbl->nht,
900 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901
902 /*
903 * periodically recompute ReachableTime from random function
904 */
905
Eric Dumazete4c4e442009-07-30 03:15:07 +0000906 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700907 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000908 tbl->last_rand = jiffies;
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +0100909 list_for_each_entry(p, &tbl->parms_list, list)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100911 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 }
913
Duan Jiongfeff9ab2014-02-27 17:14:41 +0800914 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
915 goto out;
916
David S. Millercd089332011-07-11 01:28:12 -0700917 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000918 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919
Eric Dumazet767e97e2010-10-06 17:49:21 -0700920 while ((n = rcu_dereference_protected(*np,
921 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000922 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923
Eric Dumazete4c4e442009-07-30 03:15:07 +0000924 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925
Eric Dumazete4c4e442009-07-30 03:15:07 +0000926 state = n->nud_state;
Roopa Prabhu9ce33e42018-04-24 13:49:34 -0700927 if ((state & (NUD_PERMANENT | NUD_IN_TIMER)) ||
928 (n->flags & NTF_EXT_LEARNED)) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000929 write_unlock(&n->lock);
930 goto next_elt;
931 }
932
933 if (time_before(n->used, n->confirmed))
934 n->used = n->confirmed;
935
Reshetova, Elena9f237432017-06-30 13:07:55 +0300936 if (refcount_read(&n->refcnt) == 1 &&
Eric Dumazete4c4e442009-07-30 03:15:07 +0000937 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100938 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000939 *np = n->next;
David Ahern58956312018-12-07 12:24:57 -0800940 neigh_mark_dead(n);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000941 write_unlock(&n->lock);
942 neigh_cleanup_and_release(n);
943 continue;
944 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700946
947next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000948 np = &n->next;
949 }
950 /*
951 * It's fine to release lock here, even if hash table
952 * grows while we are preempted.
953 */
954 write_unlock_bh(&tbl->lock);
955 cond_resched();
956 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500957 nht = rcu_dereference_protected(tbl->nht,
958 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000960out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100961 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
962 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
963 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 */
viresh kumarf6180022014-01-22 12:23:33 +0530965 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100966 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000967 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968}
969
970static __inline__ int neigh_max_probes(struct neighbour *n)
971{
972 struct neigh_parms *p = n->parms;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +0900973 return NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
974 (n->nud_state & NUD_PROBE ? NEIGH_VAR(p, MCAST_REPROBES) :
975 NEIGH_VAR(p, MCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976}
977
Timo Teras5ef12d92009-06-11 04:16:28 -0700978static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000979 __releases(neigh->lock)
980 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700981{
982 struct sk_buff *skb;
983
984 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000985 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700986 neigh->updated = jiffies;
987
988 /* It is very thin place. report_unreachable is very complicated
989 routine. Particularly, it can hit the same neighbour entry!
990
991 So that, we try to be accurate and avoid dead loop. --ANK
992 */
993 while (neigh->nud_state == NUD_FAILED &&
994 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
995 write_unlock(&neigh->lock);
996 neigh->ops->error_report(neigh, skb);
997 write_lock(&neigh->lock);
998 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700999 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001000 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -07001001}
1002
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001003static void neigh_probe(struct neighbour *neigh)
1004 __releases(neigh->lock)
1005{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +02001006 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001007 /* keep skb alive even if arp_queue overflows */
1008 if (skb)
Martin Zhang19125c12015-11-17 20:49:30 +08001009 skb = skb_clone(skb, GFP_ATOMIC);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001010 write_unlock(&neigh->lock);
Eric Dumazet48481c82017-03-23 12:39:21 -07001011 if (neigh->ops->solicit)
1012 neigh->ops->solicit(neigh, skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001013 atomic_inc(&neigh->probes);
Yang Wei87fff3ca2019-01-17 23:11:30 +08001014 consume_skb(skb);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001015}
1016
Linus Torvalds1da177e2005-04-16 15:20:36 -07001017/* Called when a timer expires for a neighbour entry. */
1018
Kees Cooke99e88a2017-10-16 14:43:17 -07001019static void neigh_timer_handler(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020{
1021 unsigned long now, next;
Kees Cooke99e88a2017-10-16 14:43:17 -07001022 struct neighbour *neigh = from_timer(neigh, t, timer);
Eric Dumazet95c96172012-04-15 05:58:06 +00001023 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 int notify = 0;
1025
1026 write_lock(&neigh->lock);
1027
1028 state = neigh->nud_state;
1029 now = jiffies;
1030 next = now + HZ;
1031
David S. Miller045f7b32011-11-01 17:45:55 -04001032 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034
1035 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001036 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001038 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 next = neigh->confirmed + neigh->parms->reachable_time;
1040 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001041 neigh->used +
1042 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001043 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001045 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001047 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001048 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001049 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001051 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -07001053 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001056 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001057 neigh->confirmed +
1058 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001059 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001061 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -07001063 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064 next = neigh->confirmed + neigh->parms->reachable_time;
1065 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001066 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001068 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 atomic_set(&neigh->probes, 0);
Erik Kline765c9c62015-05-18 19:44:41 +09001070 notify = 1;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001071 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 }
1073 } else {
1074 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001075 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076 }
1077
1078 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
1079 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 neigh->nud_state = NUD_FAILED;
1081 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -07001082 neigh_invalidate(neigh);
Duan Jiong5e2c21d2014-02-27 17:03:03 +08001083 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 }
1085
1086 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001087 if (time_before(next, jiffies + HZ/2))
1088 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +10001089 if (!mod_timer(&neigh->timer, next))
1090 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 }
1092 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001093 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -08001094 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -08001095out:
David S. Miller9ff56602008-02-17 18:39:54 -08001096 write_unlock(&neigh->lock);
1097 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001098
Thomas Grafd961db32007-08-08 23:12:56 -07001099 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001100 neigh_update_notify(neigh, 0);
Thomas Grafd961db32007-08-08 23:12:56 -07001101
Roopa Prabhu56dd18a2019-02-14 09:15:11 -08001102 trace_neigh_timer_handler(neigh, 0);
1103
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 neigh_release(neigh);
1105}
1106
1107int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
1108{
1109 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001110 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001111
1112 write_lock_bh(&neigh->lock);
1113
1114 rc = 0;
1115 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
1116 goto out_unlock_bh;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001117 if (neigh->dead)
1118 goto out_dead;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001121 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
1122 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001123 unsigned long next, now = jiffies;
1124
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001125 atomic_set(&neigh->probes,
1126 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001127 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001128 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001129 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1130 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001131 neigh_add_timer(neigh, next);
1132 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 } else {
1134 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001135 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 write_unlock_bh(&neigh->lock);
1137
Wei Yongjunf3fbbe02009-02-25 00:37:32 +00001138 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 return 1;
1140 }
1141 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001142 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001144 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001145 neigh_add_timer(neigh, jiffies +
1146 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147 }
1148
1149 if (neigh->nud_state == NUD_INCOMPLETE) {
1150 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001151 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001152 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001154
David S. Millerf72051b2008-09-23 01:11:18 -07001155 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001156 if (!buff)
1157 break;
1158 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001160 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001162 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001164 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165 }
1166 rc = 1;
1167 }
1168out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001169 if (immediate_probe)
1170 neigh_probe(neigh);
1171 else
1172 write_unlock(&neigh->lock);
1173 local_bh_enable();
Roopa Prabhu56dd18a2019-02-14 09:15:11 -08001174 trace_neigh_event_send_done(neigh, rc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 return rc;
Julian Anastasov2c51a972015-06-16 22:56:39 +03001176
1177out_dead:
1178 if (neigh->nud_state & NUD_STALE)
1179 goto out_unlock_bh;
1180 write_unlock_bh(&neigh->lock);
1181 kfree_skb(skb);
Roopa Prabhu56dd18a2019-02-14 09:15:11 -08001182 trace_neigh_event_send_dead(neigh, 1);
Julian Anastasov2c51a972015-06-16 22:56:39 +03001183 return 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001185EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186
David S. Millerf6b72b622011-07-14 07:53:20 -07001187static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188{
1189 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001190 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001191 = NULL;
1192
1193 if (neigh->dev->header_ops)
1194 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195
1196 if (update) {
David S. Millerf6b72b622011-07-14 07:53:20 -07001197 hh = &neigh->hh;
1198 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001199 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001201 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202 }
1203 }
1204}
1205
1206
1207
1208/* Generic update routine.
1209 -- lladdr is new lladdr or NULL, if it is not supplied.
1210 -- new is new state.
1211 -- flags
1212 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1213 if it is different.
1214 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001215 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216 if it is different.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001217 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1218
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001219 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 NTF_ROUTER flag.
1221 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1222 a router.
1223
1224 Caller MUST hold reference count on the entry.
1225 */
1226
David Ahern7a35a502018-12-05 20:02:29 -08001227static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
1228 u8 new, u32 flags, u32 nlmsg_pid,
1229 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230{
David Aherne997f8a2018-12-11 18:57:25 -07001231 bool ext_learn_change = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001232 u8 old;
1233 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 struct net_device *dev;
1236 int update_isrouter = 0;
1237
Roopa Prabhu56dd18a2019-02-14 09:15:11 -08001238 trace_neigh_update(neigh, lladdr, new, flags, nlmsg_pid);
1239
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240 write_lock_bh(&neigh->lock);
1241
1242 dev = neigh->dev;
1243 old = neigh->nud_state;
1244 err = -EPERM;
1245
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001246 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247 (old & (NUD_NOARP | NUD_PERMANENT)))
1248 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001249 if (neigh->dead) {
1250 NL_SET_ERR_MSG(extack, "Neighbor entry is now dead");
Julian Anastasov2c51a972015-06-16 22:56:39 +03001251 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001252 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001253
David Aherne997f8a2018-12-11 18:57:25 -07001254 ext_learn_change = neigh_update_ext_learned(neigh, flags, &notify);
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001255
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 if (!(new & NUD_VALID)) {
1257 neigh_del_timer(neigh);
1258 if (old & NUD_CONNECTED)
1259 neigh_suspect(neigh);
David Ahern9c29a2f2018-12-11 18:57:21 -07001260 neigh->nud_state = new;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001261 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262 notify = old & NUD_VALID;
Roopa Prabhud2fb4fb2018-10-20 18:09:31 -07001263 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
Timo Teras5ef12d92009-06-11 04:16:28 -07001264 (new & NUD_FAILED)) {
1265 neigh_invalidate(neigh);
1266 notify = 1;
1267 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001268 goto out;
1269 }
1270
1271 /* Compare new lladdr with cached one */
1272 if (!dev->addr_len) {
1273 /* First case: device needs no address. */
1274 lladdr = neigh->ha;
1275 } else if (lladdr) {
1276 /* The second case: if something is already cached
1277 and a new address is proposed:
1278 - compare new & old
1279 - if they are different, check override flag
1280 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001281 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001282 !memcmp(lladdr, neigh->ha, dev->addr_len))
1283 lladdr = neigh->ha;
1284 } else {
1285 /* No address is supplied; if we know something,
1286 use it, otherwise discard the request.
1287 */
1288 err = -EINVAL;
David Ahern7a35a502018-12-05 20:02:29 -08001289 if (!(old & NUD_VALID)) {
1290 NL_SET_ERR_MSG(extack, "No link layer address given");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001291 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001292 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293 lladdr = neigh->ha;
1294 }
1295
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001296 /* Update confirmed timestamp for neighbour entry after we
1297 * received ARP packet even if it doesn't change IP to MAC binding.
1298 */
1299 if (new & NUD_CONNECTED)
1300 neigh->confirmed = jiffies;
1301
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302 /* If entry was valid and address is not changed,
1303 do not change entry state, if new one is STALE.
1304 */
1305 err = 0;
1306 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1307 if (old & NUD_VALID) {
1308 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1309 update_isrouter = 0;
1310 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1311 (old & NUD_CONNECTED)) {
1312 lladdr = neigh->ha;
1313 new = NUD_STALE;
1314 } else
1315 goto out;
1316 } else {
Julian Anastasov0e7bbcc2016-07-27 09:56:50 +03001317 if (lladdr == neigh->ha && new == NUD_STALE &&
1318 !(flags & NEIGH_UPDATE_F_ADMIN))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 new = old;
1320 }
1321 }
1322
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001323 /* Update timestamp only once we know we will make a change to the
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001324 * neighbour entry. Otherwise we risk to move the locktime window with
1325 * noop updates and ignore relevant ARP updates.
1326 */
Vasily Khoruzhickf0e0d042018-09-13 11:12:03 -07001327 if (new != old || lladdr != neigh->ha)
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001328 neigh->updated = jiffies;
Ihar Hrachyshka77d71232017-05-16 08:44:24 -07001329
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330 if (new != old) {
1331 neigh_del_timer(neigh);
Erik Kline765c9c62015-05-18 19:44:41 +09001332 if (new & NUD_PROBE)
1333 atomic_set(&neigh->probes, 0);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001334 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001335 neigh_add_timer(neigh, (jiffies +
1336 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001337 neigh->parms->reachable_time :
1338 0)));
David Ahern9c29a2f2018-12-11 18:57:21 -07001339 neigh->nud_state = new;
Bob Gilligan53385d22013-12-15 13:39:56 -08001340 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
1342
1343 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001344 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001346 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 neigh_update_hhs(neigh);
1348 if (!(new & NUD_CONNECTED))
1349 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001350 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 }
1353 if (new == old)
1354 goto out;
1355 if (new & NUD_CONNECTED)
1356 neigh_connect(neigh);
1357 else
1358 neigh_suspect(neigh);
1359 if (!(old & NUD_VALID)) {
1360 struct sk_buff *skb;
1361
1362 /* Again: avoid dead loop if something went wrong */
1363
1364 while (neigh->nud_state & NUD_VALID &&
1365 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001366 struct dst_entry *dst = skb_dst(skb);
1367 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001369
1370 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001371
1372 /* Why not just use 'neigh' as-is? The problem is that
1373 * things such as shaper, eql, and sch_teql can end up
1374 * using alternative, different, neigh objects to output
1375 * the packet in the output path. So what we need to do
1376 * here is re-lookup the top-level neigh in the path so
1377 * we can reinject the packet there.
1378 */
1379 n2 = NULL;
1380 if (dst) {
1381 n2 = dst_neigh_lookup_skb(dst, skb);
1382 if (n2)
1383 n1 = n2;
1384 }
David S. Miller8f40b162011-07-17 13:34:11 -07001385 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001386 if (n2)
1387 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001388 rcu_read_unlock();
1389
Linus Torvalds1da177e2005-04-16 15:20:36 -07001390 write_lock_bh(&neigh->lock);
1391 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001392 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001393 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 }
1395out:
Roopa Prabhufc6e8072018-09-22 21:26:20 -07001396 if (update_isrouter)
1397 neigh_update_is_router(neigh, flags, &notify);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001398 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001399
David Aherne997f8a2018-12-11 18:57:25 -07001400 if (((new ^ old) & NUD_PERMANENT) || ext_learn_change)
David Ahern9c29a2f2018-12-11 18:57:21 -07001401 neigh_update_gc_list(neigh);
1402
Tom Tucker8d717402006-07-30 20:43:36 -07001403 if (notify)
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001404 neigh_update_notify(neigh, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07001405
Roopa Prabhu56dd18a2019-02-14 09:15:11 -08001406 trace_neigh_update_done(neigh, err);
1407
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 return err;
1409}
David Ahern7a35a502018-12-05 20:02:29 -08001410
1411int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1412 u32 flags, u32 nlmsg_pid)
1413{
1414 return __neigh_update(neigh, lladdr, new, flags, nlmsg_pid, NULL);
1415}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001416EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417
Jiri Benc7e980562013-12-11 13:48:20 +01001418/* Update the neigh to listen temporarily for probe responses, even if it is
1419 * in a NUD_FAILED state. The caller has to hold neigh->lock for writing.
1420 */
1421void __neigh_set_probe_once(struct neighbour *neigh)
1422{
Julian Anastasov2c51a972015-06-16 22:56:39 +03001423 if (neigh->dead)
1424 return;
Jiri Benc7e980562013-12-11 13:48:20 +01001425 neigh->updated = jiffies;
1426 if (!(neigh->nud_state & NUD_FAILED))
1427 return;
Duan Jiong2176d5d2014-05-09 13:16:48 +08001428 neigh->nud_state = NUD_INCOMPLETE;
1429 atomic_set(&neigh->probes, neigh_max_probes(neigh));
Jiri Benc7e980562013-12-11 13:48:20 +01001430 neigh_add_timer(neigh,
1431 jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1432}
1433EXPORT_SYMBOL(__neigh_set_probe_once);
1434
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1436 u8 *lladdr, void *saddr,
1437 struct net_device *dev)
1438{
1439 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1440 lladdr || !dev->addr_len);
1441 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001442 neigh_update(neigh, lladdr, NUD_STALE,
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07001443 NEIGH_UPDATE_F_OVERRIDE, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 return neigh;
1445}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001446EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447
Eric Dumazet34d101d2010-10-11 09:16:57 -07001448/* called with read_lock_bh(&n->lock); */
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001449static void neigh_hh_init(struct neighbour *n)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450{
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001451 struct net_device *dev = n->dev;
1452 __be16 prot = n->tbl->protocol;
David S. Millerf6b72b622011-07-14 07:53:20 -07001453 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001454
1455 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001456
David S. Millerf6b72b622011-07-14 07:53:20 -07001457 /* Only one thread can come in here and initialize the
1458 * hh_cache entry.
1459 */
David S. Millerb23b5452011-07-16 17:45:02 -07001460 if (!hh->hh_len)
1461 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b622011-07-14 07:53:20 -07001462
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001463 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464}
1465
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466/* Slow and careful. */
1467
David S. Miller8f40b162011-07-17 13:34:11 -07001468int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001469{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 int rc = 0;
1471
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 if (!neigh_event_send(neigh, skb)) {
1473 int err;
1474 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001475 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001476
David S. Millerf6b72b622011-07-14 07:53:20 -07001477 if (dev->header_ops->cache && !neigh->hh.hh_len)
Eric W. Biedermanbdf53c52015-03-02 00:13:22 -06001478 neigh_hh_init(neigh);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001479
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001480 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001481 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001482 seq = read_seqbegin(&neigh->ha_lock);
1483 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1484 neigh->ha, NULL, skb->len);
1485 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001486
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001488 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489 else
1490 goto out_kfree_skb;
1491 }
1492out:
1493 return rc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494out_kfree_skb:
1495 rc = -EINVAL;
1496 kfree_skb(skb);
1497 goto out;
1498}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001499EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500
1501/* As fast as possible without hh cache */
1502
David S. Miller8f40b162011-07-17 13:34:11 -07001503int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001506 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001507 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001509 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001510 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001511 seq = read_seqbegin(&neigh->ha_lock);
1512 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1513 neigh->ha, NULL, skb->len);
1514 } while (read_seqretry(&neigh->ha_lock, seq));
1515
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001517 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001518 else {
1519 err = -EINVAL;
1520 kfree_skb(skb);
1521 }
1522 return err;
1523}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001524EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
David S. Miller8f40b162011-07-17 13:34:11 -07001526int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1527{
1528 return dev_queue_xmit(skb);
1529}
1530EXPORT_SYMBOL(neigh_direct_output);
1531
Kees Cooke99e88a2017-10-16 14:43:17 -07001532static void neigh_proxy_process(struct timer_list *t)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533{
Kees Cooke99e88a2017-10-16 14:43:17 -07001534 struct neigh_table *tbl = from_timer(tbl, t, proxy_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535 long sched_next = 0;
1536 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001537 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
1539 spin_lock(&tbl->proxy_queue.lock);
1540
David S. Millerf72051b2008-09-23 01:11:18 -07001541 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1542 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001545 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001546
David S. Millerf72051b2008-09-23 01:11:18 -07001547 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001548 if (tbl->proxy_redo && netif_running(dev)) {
1549 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001550 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001551 rcu_read_unlock();
1552 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001553 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001554 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001555
1556 dev_put(dev);
1557 } else if (!sched_next || tdif < sched_next)
1558 sched_next = tdif;
1559 }
1560 del_timer(&tbl->proxy_timer);
1561 if (sched_next)
1562 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1563 spin_unlock(&tbl->proxy_queue.lock);
1564}
1565
1566void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1567 struct sk_buff *skb)
1568{
1569 unsigned long now = jiffies;
Aruna-Hewapathirane63862b52014-01-11 07:15:59 -05001570
1571 unsigned long sched_next = now + (prandom_u32() %
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001572 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001573
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001574 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575 kfree_skb(skb);
1576 return;
1577 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001578
1579 NEIGH_CB(skb)->sched_next = sched_next;
1580 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001581
1582 spin_lock(&tbl->proxy_queue.lock);
1583 if (del_timer(&tbl->proxy_timer)) {
1584 if (time_before(tbl->proxy_timer.expires, sched_next))
1585 sched_next = tbl->proxy_timer.expires;
1586 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001587 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001588 dev_hold(skb->dev);
1589 __skb_queue_tail(&tbl->proxy_queue, skb);
1590 mod_timer(&tbl->proxy_timer, sched_next);
1591 spin_unlock(&tbl->proxy_queue.lock);
1592}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001593EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001594
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001595static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001596 struct net *net, int ifindex)
1597{
1598 struct neigh_parms *p;
1599
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001600 list_for_each_entry(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001601 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001602 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001603 return p;
1604 }
1605
1606 return NULL;
1607}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608
1609struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1610 struct neigh_table *tbl)
1611{
Gao fengcf89d6b2013-06-20 10:01:32 +08001612 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001613 struct net *net = dev_net(dev);
1614 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615
Gao fengcf89d6b2013-06-20 10:01:32 +08001616 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618 p->tbl = tbl;
Reshetova, Elena63439442017-06-30 13:07:56 +03001619 refcount_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001621 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001622 dev_hold(dev);
1623 p->dev = dev;
Eric W. Biedermanefd7ef12015-03-11 23:04:08 -05001624 write_pnet(&p->net, net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001626
1627 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
Veaceslav Falico63134802013-08-02 19:07:38 +02001628 dev_put(dev);
1629 kfree(p);
1630 return NULL;
1631 }
1632
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001634 list_add(&p->list, &tbl->parms.list);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001636
1637 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001638 }
1639 return p;
1640}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001641EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642
1643static void neigh_rcu_free_parms(struct rcu_head *head)
1644{
1645 struct neigh_parms *parms =
1646 container_of(head, struct neigh_parms, rcu_head);
1647
1648 neigh_parms_put(parms);
1649}
1650
1651void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1652{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 if (!parms || parms == &tbl->parms)
1654 return;
1655 write_lock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001656 list_del(&parms->list);
1657 parms->dead = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001658 write_unlock_bh(&tbl->lock);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001659 if (parms->dev)
1660 dev_put(parms->dev);
1661 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001663EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001664
Denis V. Lunev06f05112008-01-24 00:30:58 -08001665static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666{
1667 kfree(parms);
1668}
1669
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001670static struct lock_class_key neigh_table_proxy_queue_class;
1671
WANG Congd7480fd2014-11-10 15:59:36 -08001672static struct neigh_table *neigh_tables[NEIGH_NR_TABLES] __read_mostly;
1673
1674void neigh_table_init(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001675{
1676 unsigned long now = jiffies;
1677 unsigned long phsize;
1678
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001679 INIT_LIST_HEAD(&tbl->parms_list);
David Ahern58956312018-12-07 12:24:57 -08001680 INIT_LIST_HEAD(&tbl->gc_list);
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01001681 list_add(&tbl->parms.list, &tbl->parms_list);
Eric Dumazete42ea982008-11-12 00:54:54 -08001682 write_pnet(&tbl->parms.net, &init_net);
Reshetova, Elena63439442017-06-30 13:07:56 +03001683 refcount_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001685 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 tbl->stats = alloc_percpu(struct neigh_statistics);
1688 if (!tbl->stats)
1689 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001690
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691#ifdef CONFIG_PROC_FS
Christoph Hellwig71a50532018-04-15 10:16:41 +02001692 if (!proc_create_seq_data(tbl->id, 0, init_net.proc_net_stat,
1693 &neigh_stat_seq_ops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001695#endif
1696
David S. Millercd089332011-07-11 01:28:12 -07001697 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
1699 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001700 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001702 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703 panic("cannot allocate neighbour cache hashes");
1704
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001705 if (!tbl->entry_size)
1706 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1707 tbl->key_len, NEIGH_PRIV_ALIGN);
1708 else
1709 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001712 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
viresh kumarf6180022014-01-22 12:23:33 +05301713 queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
1714 tbl->parms.reachable_time);
Kees Cooke99e88a2017-10-16 14:43:17 -07001715 timer_setup(&tbl->proxy_timer, neigh_proxy_process, 0);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001716 skb_queue_head_init_class(&tbl->proxy_queue,
1717 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
1719 tbl->last_flush = now;
1720 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001721
WANG Congd7480fd2014-11-10 15:59:36 -08001722 neigh_tables[index] = tbl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001723}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001724EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
WANG Congd7480fd2014-11-10 15:59:36 -08001726int neigh_table_clear(int index, struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727{
WANG Congd7480fd2014-11-10 15:59:36 -08001728 neigh_tables[index] = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001730 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001731 del_timer_sync(&tbl->proxy_timer);
1732 pneigh_queue_purge(&tbl->proxy_queue);
1733 neigh_ifdown(tbl, NULL);
1734 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001735 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001737 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1738 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001739 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740
1741 kfree(tbl->phash_buckets);
1742 tbl->phash_buckets = NULL;
1743
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001744 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1745
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001746 free_percpu(tbl->stats);
1747 tbl->stats = NULL;
1748
Linus Torvalds1da177e2005-04-16 15:20:36 -07001749 return 0;
1750}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001751EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001752
WANG Congd7480fd2014-11-10 15:59:36 -08001753static struct neigh_table *neigh_find_table(int family)
1754{
1755 struct neigh_table *tbl = NULL;
1756
1757 switch (family) {
1758 case AF_INET:
1759 tbl = neigh_tables[NEIGH_ARP_TABLE];
1760 break;
1761 case AF_INET6:
1762 tbl = neigh_tables[NEIGH_ND_TABLE];
1763 break;
1764 case AF_DECnet:
1765 tbl = neigh_tables[NEIGH_DN_TABLE];
1766 break;
1767 }
1768
1769 return tbl;
1770}
1771
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08001772const struct nla_policy nda_policy[NDA_MAX+1] = {
1773 [NDA_DST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1774 [NDA_LLADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1775 [NDA_CACHEINFO] = { .len = sizeof(struct nda_cacheinfo) },
1776 [NDA_PROBES] = { .type = NLA_U32 },
1777 [NDA_VLAN] = { .type = NLA_U16 },
1778 [NDA_PORT] = { .type = NLA_U16 },
1779 [NDA_VNI] = { .type = NLA_U32 },
1780 [NDA_IFINDEX] = { .type = NLA_U32 },
1781 [NDA_MASTER] = { .type = NLA_U32 },
David Aherna9cd3432018-12-19 20:02:36 -08001782 [NDA_PROTOCOL] = { .type = NLA_U8 },
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08001783};
1784
David Ahernc21ef3e2017-04-16 09:48:24 -07001785static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
1786 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001787{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001788 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001789 struct ndmsg *ndm;
1790 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001791 struct neigh_table *tbl;
WANG Congd7480fd2014-11-10 15:59:36 -08001792 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001793 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001794 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795
Eric Dumazet110b2492010-10-04 04:27:36 +00001796 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001797 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798 goto out;
1799
Thomas Grafa14a49d2006-08-07 17:53:08 -07001800 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
David Ahern7a35a502018-12-05 20:02:29 -08001801 if (!dst_attr) {
1802 NL_SET_ERR_MSG(extack, "Network address not specified");
Thomas Grafa14a49d2006-08-07 17:53:08 -07001803 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001804 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001805
1806 ndm = nlmsg_data(nlh);
1807 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001808 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001809 if (dev == NULL) {
1810 err = -ENODEV;
1811 goto out;
1812 }
1813 }
1814
WANG Congd7480fd2014-11-10 15:59:36 -08001815 tbl = neigh_find_table(ndm->ndm_family);
1816 if (tbl == NULL)
1817 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001818
David Ahern7a35a502018-12-05 20:02:29 -08001819 if (nla_len(dst_attr) < (int)tbl->key_len) {
1820 NL_SET_ERR_MSG(extack, "Invalid network address");
WANG Congd7480fd2014-11-10 15:59:36 -08001821 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001822 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001823
WANG Congd7480fd2014-11-10 15:59:36 -08001824 if (ndm->ndm_flags & NTF_PROXY) {
1825 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001826 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001827 }
WANG Congd7480fd2014-11-10 15:59:36 -08001828
1829 if (dev == NULL)
1830 goto out;
1831
1832 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1833 if (neigh == NULL) {
1834 err = -ENOENT;
1835 goto out;
1836 }
1837
David Ahern7a35a502018-12-05 20:02:29 -08001838 err = __neigh_update(neigh, NULL, NUD_FAILED,
1839 NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN,
1840 NETLINK_CB(skb).portid, extack);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001841 write_lock_bh(&tbl->lock);
WANG Congd7480fd2014-11-10 15:59:36 -08001842 neigh_release(neigh);
Sowmini Varadhan50710342017-06-02 09:01:49 -07001843 neigh_remove_one(neigh, tbl);
1844 write_unlock_bh(&tbl->lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001845
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846out:
1847 return err;
1848}
1849
David Ahernc21ef3e2017-04-16 09:48:24 -07001850static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
1851 struct netlink_ext_ack *extack)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001853 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE |
1854 NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001855 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001856 struct ndmsg *ndm;
1857 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001858 struct neigh_table *tbl;
1859 struct net_device *dev = NULL;
WANG Congd7480fd2014-11-10 15:59:36 -08001860 struct neighbour *neigh;
1861 void *dst, *lladdr;
David Aherndf9b0e32018-12-15 14:09:06 -08001862 u8 protocol = 0;
Thomas Graf5208deb2006-08-07 17:55:40 -07001863 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001864
Eric Dumazet110b2492010-10-04 04:27:36 +00001865 ASSERT_RTNL();
Johannes Berg8cb08172019-04-26 14:07:28 +02001866 err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX,
1867 nda_policy, extack);
Thomas Graf5208deb2006-08-07 17:55:40 -07001868 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001869 goto out;
1870
Thomas Graf5208deb2006-08-07 17:55:40 -07001871 err = -EINVAL;
David Ahern7a35a502018-12-05 20:02:29 -08001872 if (!tb[NDA_DST]) {
1873 NL_SET_ERR_MSG(extack, "Network address not specified");
Thomas Graf5208deb2006-08-07 17:55:40 -07001874 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001875 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001876
1877 ndm = nlmsg_data(nlh);
1878 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001879 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001880 if (dev == NULL) {
1881 err = -ENODEV;
1882 goto out;
1883 }
1884
David Ahern7a35a502018-12-05 20:02:29 -08001885 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) {
1886 NL_SET_ERR_MSG(extack, "Invalid link address");
Eric Dumazet110b2492010-10-04 04:27:36 +00001887 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001888 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001889 }
1890
WANG Congd7480fd2014-11-10 15:59:36 -08001891 tbl = neigh_find_table(ndm->ndm_family);
1892 if (tbl == NULL)
1893 return -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001894
David Ahern7a35a502018-12-05 20:02:29 -08001895 if (nla_len(tb[NDA_DST]) < (int)tbl->key_len) {
1896 NL_SET_ERR_MSG(extack, "Invalid network address");
WANG Congd7480fd2014-11-10 15:59:36 -08001897 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001898 }
1899
WANG Congd7480fd2014-11-10 15:59:36 -08001900 dst = nla_data(tb[NDA_DST]);
1901 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001902
David Aherna9cd3432018-12-19 20:02:36 -08001903 if (tb[NDA_PROTOCOL])
David Aherndf9b0e32018-12-15 14:09:06 -08001904 protocol = nla_get_u8(tb[NDA_PROTOCOL]);
David Aherndf9b0e32018-12-15 14:09:06 -08001905
WANG Congd7480fd2014-11-10 15:59:36 -08001906 if (ndm->ndm_flags & NTF_PROXY) {
1907 struct pneigh_entry *pn;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908
WANG Congd7480fd2014-11-10 15:59:36 -08001909 err = -ENOBUFS;
1910 pn = pneigh_lookup(tbl, net, dst, dev, 1);
1911 if (pn) {
1912 pn->flags = ndm->ndm_flags;
David Aherndf9b0e32018-12-15 14:09:06 -08001913 if (protocol)
1914 pn->protocol = protocol;
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001915 err = 0;
WANG Congd7480fd2014-11-10 15:59:36 -08001916 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001917 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 }
1919
David Ahern7a35a502018-12-05 20:02:29 -08001920 if (!dev) {
1921 NL_SET_ERR_MSG(extack, "Device not specified");
WANG Congd7480fd2014-11-10 15:59:36 -08001922 goto out;
David Ahern7a35a502018-12-05 20:02:29 -08001923 }
WANG Congd7480fd2014-11-10 15:59:36 -08001924
David Ahernb8fb1ab2019-04-16 17:31:43 -07001925 if (tbl->allow_add && !tbl->allow_add(dev, extack)) {
1926 err = -EINVAL;
1927 goto out;
1928 }
1929
WANG Congd7480fd2014-11-10 15:59:36 -08001930 neigh = neigh_lookup(tbl, dst, dev);
1931 if (neigh == NULL) {
David Aherne997f8a2018-12-11 18:57:25 -07001932 bool exempt_from_gc;
1933
WANG Congd7480fd2014-11-10 15:59:36 -08001934 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1935 err = -ENOENT;
1936 goto out;
1937 }
1938
David Aherne997f8a2018-12-11 18:57:25 -07001939 exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
1940 ndm->ndm_flags & NTF_EXT_LEARNED;
1941 neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true);
WANG Congd7480fd2014-11-10 15:59:36 -08001942 if (IS_ERR(neigh)) {
1943 err = PTR_ERR(neigh);
1944 goto out;
1945 }
1946 } else {
1947 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1948 err = -EEXIST;
1949 neigh_release(neigh);
1950 goto out;
1951 }
1952
1953 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001954 flags &= ~(NEIGH_UPDATE_F_OVERRIDE |
1955 NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
WANG Congd7480fd2014-11-10 15:59:36 -08001956 }
1957
Roopa Prabhu9ce33e42018-04-24 13:49:34 -07001958 if (ndm->ndm_flags & NTF_EXT_LEARNED)
1959 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1960
Roopa Prabhuf7aa74e2018-09-22 21:26:19 -07001961 if (ndm->ndm_flags & NTF_ROUTER)
1962 flags |= NEIGH_UPDATE_F_ISROUTER;
1963
WANG Congd7480fd2014-11-10 15:59:36 -08001964 if (ndm->ndm_flags & NTF_USE) {
1965 neigh_event_send(neigh, NULL);
1966 err = 0;
1967 } else
David Ahern7a35a502018-12-05 20:02:29 -08001968 err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1969 NETLINK_CB(skb).portid, extack);
David Aherndf9b0e32018-12-15 14:09:06 -08001970
1971 if (protocol)
1972 neigh->protocol = protocol;
1973
WANG Congd7480fd2014-11-10 15:59:36 -08001974 neigh_release(neigh);
1975
Linus Torvalds1da177e2005-04-16 15:20:36 -07001976out:
1977 return err;
1978}
1979
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001980static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1981{
Thomas Grafca860fb2006-08-07 18:00:18 -07001982 struct nlattr *nest;
1983
Michal Kubecekae0be8d2019-04-26 11:13:06 +02001984 nest = nla_nest_start_noflag(skb, NDTA_PARMS);
Thomas Grafca860fb2006-08-07 18:00:18 -07001985 if (nest == NULL)
1986 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001987
David S. Miller9a6308d2012-04-01 20:06:28 -04001988 if ((parms->dev &&
1989 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
Reshetova, Elena63439442017-06-30 13:07:56 +03001990 nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001991 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1992 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001993 /* approximative value for deprecated QUEUE_LEN (in packets) */
1994 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001995 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1996 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1997 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1998 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1999 NEIGH_VAR(parms, UCAST_PROBES)) ||
2000 nla_put_u32(skb, NDTPA_MCAST_PROBES,
2001 NEIGH_VAR(parms, MCAST_PROBES)) ||
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002002 nla_put_u32(skb, NDTPA_MCAST_REPROBES,
2003 NEIGH_VAR(parms, MCAST_REPROBES)) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002004 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time,
2005 NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04002006 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002007 NEIGH_VAR(parms, BASE_REACHABLE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002008 nla_put_msecs(skb, NDTPA_GC_STALETIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002009 NEIGH_VAR(parms, GC_STALETIME), NDTPA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04002010 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002011 NEIGH_VAR(parms, DELAY_PROBE_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002012 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002013 NEIGH_VAR(parms, RETRANS_TIME), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002014 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002015 NEIGH_VAR(parms, ANYCAST_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002016 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002017 NEIGH_VAR(parms, PROXY_DELAY), NDTPA_PAD) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002018 nla_put_msecs(skb, NDTPA_LOCKTIME,
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002019 NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04002020 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07002021 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002022
Thomas Grafca860fb2006-08-07 18:00:18 -07002023nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07002024 nla_nest_cancel(skb, nest);
2025 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002026}
2027
Thomas Grafca860fb2006-08-07 18:00:18 -07002028static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
2029 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002030{
2031 struct nlmsghdr *nlh;
2032 struct ndtmsg *ndtmsg;
2033
Thomas Grafca860fb2006-08-07 18:00:18 -07002034 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
2035 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002036 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002037
Thomas Grafca860fb2006-08-07 18:00:18 -07002038 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002039
2040 read_lock_bh(&tbl->lock);
2041 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002042 ndtmsg->ndtm_pad1 = 0;
2043 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002044
David S. Miller9a6308d2012-04-01 20:06:28 -04002045 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
Nicolas Dichtel2175d872016-04-22 17:31:21 +02002046 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval, NDTA_PAD) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04002047 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
2048 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
2049 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
2050 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002051 {
2052 unsigned long now = jiffies;
2053 unsigned int flush_delta = now - tbl->last_flush;
2054 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002055 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002056 struct ndt_config ndc = {
2057 .ndtc_key_len = tbl->key_len,
2058 .ndtc_entry_size = tbl->entry_size,
2059 .ndtc_entries = atomic_read(&tbl->entries),
2060 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
2061 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002062 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
2063 };
2064
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002065 rcu_read_lock_bh();
2066 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05002067 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07002068 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002069 rcu_read_unlock_bh();
2070
David S. Miller9a6308d2012-04-01 20:06:28 -04002071 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
2072 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002073 }
2074
2075 {
2076 int cpu;
2077 struct ndt_stats ndst;
2078
2079 memset(&ndst, 0, sizeof(ndst));
2080
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07002081 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002082 struct neigh_statistics *st;
2083
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002084 st = per_cpu_ptr(tbl->stats, cpu);
2085 ndst.ndts_allocs += st->allocs;
2086 ndst.ndts_destroys += st->destroys;
2087 ndst.ndts_hash_grows += st->hash_grows;
2088 ndst.ndts_res_failed += st->res_failed;
2089 ndst.ndts_lookups += st->lookups;
2090 ndst.ndts_hits += st->hits;
2091 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
2092 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
2093 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
2094 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
Rick Jonesfb811392015-08-07 11:10:37 -07002095 ndst.ndts_table_fulls += st->table_fulls;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002096 }
2097
Nicolas Dichtelb6763382016-04-26 10:06:17 +02002098 if (nla_put_64bit(skb, NDTA_STATS, sizeof(ndst), &ndst,
2099 NDTA_PAD))
David S. Miller9a6308d2012-04-01 20:06:28 -04002100 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002101 }
2102
2103 BUG_ON(tbl->parms.dev);
2104 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07002105 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002106
2107 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01002108 nlmsg_end(skb, nlh);
2109 return 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002110
Thomas Grafca860fb2006-08-07 18:00:18 -07002111nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002112 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08002113 nlmsg_cancel(skb, nlh);
2114 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002115}
2116
Thomas Grafca860fb2006-08-07 18:00:18 -07002117static int neightbl_fill_param_info(struct sk_buff *skb,
2118 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002119 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07002120 u32 pid, u32 seq, int type,
2121 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002122{
2123 struct ndtmsg *ndtmsg;
2124 struct nlmsghdr *nlh;
2125
Thomas Grafca860fb2006-08-07 18:00:18 -07002126 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
2127 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002128 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002129
Thomas Grafca860fb2006-08-07 18:00:18 -07002130 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002131
2132 read_lock_bh(&tbl->lock);
2133 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002134 ndtmsg->ndtm_pad1 = 0;
2135 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002136
Thomas Grafca860fb2006-08-07 18:00:18 -07002137 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
2138 neightbl_fill_parms(skb, parms) < 0)
2139 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002140
2141 read_unlock_bh(&tbl->lock);
Johannes Berg053c0952015-01-16 22:09:00 +01002142 nlmsg_end(skb, nlh);
2143 return 0;
Thomas Grafca860fb2006-08-07 18:00:18 -07002144errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002145 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08002146 nlmsg_cancel(skb, nlh);
2147 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002148}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002149
Patrick McHardyef7c79e2007-06-05 12:38:30 -07002150static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07002151 [NDTA_NAME] = { .type = NLA_STRING },
2152 [NDTA_THRESH1] = { .type = NLA_U32 },
2153 [NDTA_THRESH2] = { .type = NLA_U32 },
2154 [NDTA_THRESH3] = { .type = NLA_U32 },
2155 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
2156 [NDTA_PARMS] = { .type = NLA_NESTED },
2157};
2158
Patrick McHardyef7c79e2007-06-05 12:38:30 -07002159static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07002160 [NDTPA_IFINDEX] = { .type = NLA_U32 },
2161 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
2162 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
2163 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
2164 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
2165 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002166 [NDTPA_MCAST_REPROBES] = { .type = NLA_U32 },
Thomas Graf6b3f8672006-08-07 17:58:53 -07002167 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
2168 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
2169 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
2170 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
2171 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
2172 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
2173 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
2174};
2175
David Ahernc21ef3e2017-04-16 09:48:24 -07002176static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh,
2177 struct netlink_ext_ack *extack)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002178{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002179 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002180 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002181 struct ndtmsg *ndtmsg;
2182 struct nlattr *tb[NDTA_MAX+1];
WANG Congd7480fd2014-11-10 15:59:36 -08002183 bool found = false;
2184 int err, tidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002185
Johannes Berg8cb08172019-04-26 14:07:28 +02002186 err = nlmsg_parse_deprecated(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
2187 nl_neightbl_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002188 if (err < 0)
2189 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002190
Thomas Graf6b3f8672006-08-07 17:58:53 -07002191 if (tb[NDTA_NAME] == NULL) {
2192 err = -EINVAL;
2193 goto errout;
2194 }
2195
2196 ndtmsg = nlmsg_data(nlh);
WANG Congd7480fd2014-11-10 15:59:36 -08002197
2198 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
2199 tbl = neigh_tables[tidx];
2200 if (!tbl)
2201 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002202 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
2203 continue;
WANG Congd7480fd2014-11-10 15:59:36 -08002204 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0) {
2205 found = true;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002206 break;
WANG Congd7480fd2014-11-10 15:59:36 -08002207 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002208 }
2209
WANG Congd7480fd2014-11-10 15:59:36 -08002210 if (!found)
2211 return -ENOENT;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002212
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002213 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002214 * We acquire tbl->lock to be nice to the periodic timers and
2215 * make sure they always see a consistent set of values.
2216 */
2217 write_lock_bh(&tbl->lock);
2218
Thomas Graf6b3f8672006-08-07 17:58:53 -07002219 if (tb[NDTA_PARMS]) {
2220 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002221 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002222 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002223
Johannes Berg8cb08172019-04-26 14:07:28 +02002224 err = nla_parse_nested_deprecated(tbp, NDTPA_MAX,
2225 tb[NDTA_PARMS],
2226 nl_ntbl_parm_policy, extack);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002227 if (err < 0)
2228 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002229
Thomas Graf6b3f8672006-08-07 17:58:53 -07002230 if (tbp[NDTPA_IFINDEX])
2231 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002232
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002233 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002234 if (p == NULL) {
2235 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002236 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002237 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002238
Thomas Graf6b3f8672006-08-07 17:58:53 -07002239 for (i = 1; i <= NDTPA_MAX; i++) {
2240 if (tbp[i] == NULL)
2241 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002242
Thomas Graf6b3f8672006-08-07 17:58:53 -07002243 switch (i) {
2244 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002245 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2246 nla_get_u32(tbp[i]) *
2247 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002248 break;
2249 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002250 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2251 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002252 break;
2253 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002254 NEIGH_VAR_SET(p, PROXY_QLEN,
2255 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002256 break;
2257 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002258 NEIGH_VAR_SET(p, APP_PROBES,
2259 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002260 break;
2261 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002262 NEIGH_VAR_SET(p, UCAST_PROBES,
2263 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002264 break;
2265 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002266 NEIGH_VAR_SET(p, MCAST_PROBES,
2267 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002268 break;
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09002269 case NDTPA_MCAST_REPROBES:
2270 NEIGH_VAR_SET(p, MCAST_REPROBES,
2271 nla_get_u32(tbp[i]));
2272 break;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002273 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002274 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2275 nla_get_msecs(tbp[i]));
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01002276 /* update reachable_time as well, otherwise, the change will
2277 * only be effective after the next time neigh_periodic_work
2278 * decides to recompute it (can be multiple minutes)
2279 */
2280 p->reachable_time =
2281 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002282 break;
2283 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002284 NEIGH_VAR_SET(p, GC_STALETIME,
2285 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002286 break;
2287 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002288 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2289 nla_get_msecs(tbp[i]));
Ido Schimmel2a4501a2016-07-05 11:27:42 +02002290 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002291 break;
2292 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002293 NEIGH_VAR_SET(p, RETRANS_TIME,
2294 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002295 break;
2296 case NDTPA_ANYCAST_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002297 NEIGH_VAR_SET(p, ANYCAST_DELAY,
2298 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002299 break;
2300 case NDTPA_PROXY_DELAY:
Jiri Pirko39774582014-01-14 15:46:07 +01002301 NEIGH_VAR_SET(p, PROXY_DELAY,
2302 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002303 break;
2304 case NDTPA_LOCKTIME:
Jiri Pirko39774582014-01-14 15:46:07 +01002305 NEIGH_VAR_SET(p, LOCKTIME,
2306 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002307 break;
2308 }
2309 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002310 }
2311
Gao fengdc25c672013-06-20 10:01:34 +08002312 err = -ENOENT;
2313 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2314 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2315 !net_eq(net, &init_net))
2316 goto errout_tbl_lock;
2317
Thomas Graf6b3f8672006-08-07 17:58:53 -07002318 if (tb[NDTA_THRESH1])
2319 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2320
2321 if (tb[NDTA_THRESH2])
2322 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2323
2324 if (tb[NDTA_THRESH3])
2325 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2326
2327 if (tb[NDTA_GC_INTERVAL])
2328 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2329
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002330 err = 0;
2331
Thomas Graf6b3f8672006-08-07 17:58:53 -07002332errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002333 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002334errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002335 return err;
2336}
2337
David Ahern9632d472018-10-07 20:16:37 -07002338static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
2339 struct netlink_ext_ack *extack)
2340{
2341 struct ndtmsg *ndtm;
2342
2343 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndtm))) {
2344 NL_SET_ERR_MSG(extack, "Invalid header for neighbor table dump request");
2345 return -EINVAL;
2346 }
2347
2348 ndtm = nlmsg_data(nlh);
2349 if (ndtm->ndtm_pad1 || ndtm->ndtm_pad2) {
2350 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor table dump request");
2351 return -EINVAL;
2352 }
2353
2354 if (nlmsg_attrlen(nlh, sizeof(*ndtm))) {
2355 NL_SET_ERR_MSG(extack, "Invalid data after header in neighbor table dump request");
2356 return -EINVAL;
2357 }
2358
2359 return 0;
2360}
2361
Thomas Grafc8822a42007-03-22 11:50:06 -07002362static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002363{
David Ahern9632d472018-10-07 20:16:37 -07002364 const struct nlmsghdr *nlh = cb->nlh;
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002365 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002366 int family, tidx, nidx = 0;
2367 int tbl_skip = cb->args[0];
2368 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002369 struct neigh_table *tbl;
2370
David Ahern9632d472018-10-07 20:16:37 -07002371 if (cb->strict_check) {
2372 int err = neightbl_valid_dump_info(nlh, cb->extack);
2373
2374 if (err < 0)
2375 return err;
2376 }
2377
2378 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002379
WANG Congd7480fd2014-11-10 15:59:36 -08002380 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002381 struct neigh_parms *p;
2382
WANG Congd7480fd2014-11-10 15:59:36 -08002383 tbl = neigh_tables[tidx];
2384 if (!tbl)
2385 continue;
2386
Thomas Grafca860fb2006-08-07 18:00:18 -07002387 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002388 continue;
2389
Eric W. Biederman15e47302012-09-07 20:12:54 +00002390 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002391 nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002392 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002393 break;
2394
Nicolas Dichtel75fbfd32014-10-29 19:29:31 +01002395 nidx = 0;
2396 p = list_next_entry(&tbl->parms, list);
2397 list_for_each_entry_from(p, &tbl->parms_list, list) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002398 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002399 continue;
2400
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002401 if (nidx < neigh_skip)
2402 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002403
Thomas Grafca860fb2006-08-07 18:00:18 -07002404 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002405 NETLINK_CB(cb->skb).portid,
David Ahern9632d472018-10-07 20:16:37 -07002406 nlh->nlmsg_seq,
Thomas Grafca860fb2006-08-07 18:00:18 -07002407 RTM_NEWNEIGHTBL,
David S. Miller7b46a642015-01-18 23:36:08 -05002408 NLM_F_MULTI) < 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002409 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002410 next:
2411 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002412 }
2413
Thomas Grafca860fb2006-08-07 18:00:18 -07002414 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002415 }
2416out:
Thomas Grafca860fb2006-08-07 18:00:18 -07002417 cb->args[0] = tidx;
2418 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002419
2420 return skb->len;
2421}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422
Thomas Graf8b8aec52006-08-07 17:56:37 -07002423static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2424 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425{
2426 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002428 struct nlmsghdr *nlh;
2429 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430
Thomas Graf8b8aec52006-08-07 17:56:37 -07002431 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2432 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002433 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002434
2435 ndm = nlmsg_data(nlh);
2436 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002437 ndm->ndm_pad1 = 0;
2438 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002439 ndm->ndm_flags = neigh->flags;
2440 ndm->ndm_type = neigh->type;
2441 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
David S. Miller9a6308d2012-04-01 20:06:28 -04002443 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2444 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002445
2446 read_lock_bh(&neigh->lock);
2447 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002448 if (neigh->nud_state & NUD_VALID) {
2449 char haddr[MAX_ADDR_LEN];
2450
2451 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2452 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2453 read_unlock_bh(&neigh->lock);
2454 goto nla_put_failure;
2455 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002456 }
2457
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002458 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2459 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2460 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Reshetova, Elena9f237432017-06-30 13:07:55 +03002461 ci.ndm_refcnt = refcount_read(&neigh->refcnt) - 1;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002462 read_unlock_bh(&neigh->lock);
2463
David S. Miller9a6308d2012-04-01 20:06:28 -04002464 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2465 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2466 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002467
David Aherndf9b0e32018-12-15 14:09:06 -08002468 if (neigh->protocol && nla_put_u8(skb, NDA_PROTOCOL, neigh->protocol))
2469 goto nla_put_failure;
2470
Johannes Berg053c0952015-01-16 22:09:00 +01002471 nlmsg_end(skb, nlh);
2472 return 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002473
2474nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002475 nlmsg_cancel(skb, nlh);
2476 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477}
2478
Tony Zelenoff84920c12012-01-26 22:28:58 +00002479static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2480 u32 pid, u32 seq, int type, unsigned int flags,
2481 struct neigh_table *tbl)
2482{
2483 struct nlmsghdr *nlh;
2484 struct ndmsg *ndm;
2485
2486 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2487 if (nlh == NULL)
2488 return -EMSGSIZE;
2489
2490 ndm = nlmsg_data(nlh);
2491 ndm->ndm_family = tbl->family;
2492 ndm->ndm_pad1 = 0;
2493 ndm->ndm_pad2 = 0;
2494 ndm->ndm_flags = pn->flags | NTF_PROXY;
Jun Zhao545469f2014-07-26 00:38:59 +08002495 ndm->ndm_type = RTN_UNICAST;
Konstantin Khlebnikov6adc5fd2015-12-01 01:14:48 +03002496 ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002497 ndm->ndm_state = NUD_NONE;
2498
David S. Miller9a6308d2012-04-01 20:06:28 -04002499 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2500 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002501
David Aherndf9b0e32018-12-15 14:09:06 -08002502 if (pn->protocol && nla_put_u8(skb, NDA_PROTOCOL, pn->protocol))
2503 goto nla_put_failure;
2504
Johannes Berg053c0952015-01-16 22:09:00 +01002505 nlmsg_end(skb, nlh);
2506 return 0;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002507
2508nla_put_failure:
2509 nlmsg_cancel(skb, nlh);
2510 return -EMSGSIZE;
2511}
2512
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002513static void neigh_update_notify(struct neighbour *neigh, u32 nlmsg_pid)
Thomas Grafd961db32007-08-08 23:12:56 -07002514{
2515 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07002516 __neigh_notify(neigh, RTM_NEWNEIGH, 0, nlmsg_pid);
Thomas Grafd961db32007-08-08 23:12:56 -07002517}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002518
David Ahern21fdd092015-09-29 09:32:03 -07002519static bool neigh_master_filtered(struct net_device *dev, int master_idx)
2520{
2521 struct net_device *master;
2522
2523 if (!master_idx)
2524 return false;
2525
Eric Dumazetaab456d2018-10-26 09:33:27 -07002526 master = dev ? netdev_master_upper_dev_get(dev) : NULL;
David Ahern21fdd092015-09-29 09:32:03 -07002527 if (!master || master->ifindex != master_idx)
2528 return true;
2529
2530 return false;
2531}
2532
David Ahern16660f02015-10-03 11:43:46 -07002533static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
2534{
Eric Dumazetaab456d2018-10-26 09:33:27 -07002535 if (filter_idx && (!dev || dev->ifindex != filter_idx))
David Ahern16660f02015-10-03 11:43:46 -07002536 return true;
2537
2538 return false;
2539}
2540
David Ahern6f52f802018-10-03 15:33:12 -07002541struct neigh_dump_filter {
2542 int master_idx;
2543 int dev_idx;
2544};
2545
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002547 struct netlink_callback *cb,
2548 struct neigh_dump_filter *filter)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002549{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002550 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 struct neighbour *n;
2552 int rc, h, s_h = cb->args[1];
2553 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002554 struct neigh_hash_table *nht;
David Ahern21fdd092015-09-29 09:32:03 -07002555 unsigned int flags = NLM_F_MULTI;
David Ahern21fdd092015-09-29 09:32:03 -07002556
David Ahern6f52f802018-10-03 15:33:12 -07002557 if (filter->dev_idx || filter->master_idx)
2558 flags |= NLM_F_DUMP_FILTERED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002559
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002560 rcu_read_lock_bh();
2561 nht = rcu_dereference_bh(tbl->nht);
2562
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002563 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564 if (h > s_h)
2565 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002566 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2567 n != NULL;
2568 n = rcu_dereference_bh(n->next)) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002569 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
2570 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002571 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2572 neigh_master_filtered(n->dev, filter->master_idx))
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002573 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002574 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002576 RTM_NEWNEIGH,
David Ahern21fdd092015-09-29 09:32:03 -07002577 flags) < 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 rc = -1;
2579 goto out;
2580 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002581next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002582 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002583 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584 }
2585 rc = skb->len;
2586out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002587 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002588 cb->args[1] = h;
2589 cb->args[2] = idx;
2590 return rc;
2591}
2592
Tony Zelenoff84920c12012-01-26 22:28:58 +00002593static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
David Ahern6f52f802018-10-03 15:33:12 -07002594 struct netlink_callback *cb,
2595 struct neigh_dump_filter *filter)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002596{
2597 struct pneigh_entry *n;
2598 struct net *net = sock_net(skb->sk);
2599 int rc, h, s_h = cb->args[3];
2600 int idx, s_idx = idx = cb->args[4];
David Ahern6f52f802018-10-03 15:33:12 -07002601 unsigned int flags = NLM_F_MULTI;
2602
2603 if (filter->dev_idx || filter->master_idx)
2604 flags |= NLM_F_DUMP_FILTERED;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002605
2606 read_lock_bh(&tbl->lock);
2607
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002608 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002609 if (h > s_h)
2610 s_idx = 0;
2611 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
Zhang Shengju18502ac2016-11-30 11:24:42 +08002612 if (idx < s_idx || pneigh_net(n) != net)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002613 goto next;
David Ahern6f52f802018-10-03 15:33:12 -07002614 if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2615 neigh_master_filtered(n->dev, filter->master_idx))
2616 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002617 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002618 cb->nlh->nlmsg_seq,
David Ahern6f52f802018-10-03 15:33:12 -07002619 RTM_NEWNEIGH, flags, tbl) < 0) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002620 read_unlock_bh(&tbl->lock);
2621 rc = -1;
2622 goto out;
2623 }
2624 next:
2625 idx++;
2626 }
2627 }
2628
2629 read_unlock_bh(&tbl->lock);
2630 rc = skb->len;
2631out:
2632 cb->args[3] = h;
2633 cb->args[4] = idx;
2634 return rc;
2635
2636}
2637
David Ahern51183d22018-10-07 20:16:36 -07002638static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
2639 bool strict_check,
2640 struct neigh_dump_filter *filter,
2641 struct netlink_ext_ack *extack)
2642{
2643 struct nlattr *tb[NDA_MAX + 1];
2644 int err, i;
2645
2646 if (strict_check) {
2647 struct ndmsg *ndm;
2648
2649 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2650 NL_SET_ERR_MSG(extack, "Invalid header for neighbor dump request");
2651 return -EINVAL;
2652 }
2653
2654 ndm = nlmsg_data(nlh);
2655 if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_ifindex ||
David Ahernc0fde872018-12-19 16:54:38 -08002656 ndm->ndm_state || ndm->ndm_type) {
David Ahern51183d22018-10-07 20:16:36 -07002657 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor dump request");
2658 return -EINVAL;
2659 }
2660
David Ahernc0fde872018-12-19 16:54:38 -08002661 if (ndm->ndm_flags & ~NTF_PROXY) {
2662 NL_SET_ERR_MSG(extack, "Invalid flags in header for neighbor dump request");
2663 return -EINVAL;
2664 }
2665
Johannes Berg8cb08172019-04-26 14:07:28 +02002666 err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg),
2667 tb, NDA_MAX, nda_policy,
2668 extack);
David Ahern51183d22018-10-07 20:16:36 -07002669 } else {
Johannes Berg8cb08172019-04-26 14:07:28 +02002670 err = nlmsg_parse_deprecated(nlh, sizeof(struct ndmsg), tb,
2671 NDA_MAX, nda_policy, extack);
David Ahern51183d22018-10-07 20:16:36 -07002672 }
2673 if (err < 0)
2674 return err;
2675
2676 for (i = 0; i <= NDA_MAX; ++i) {
2677 if (!tb[i])
2678 continue;
2679
2680 /* all new attributes should require strict_check */
2681 switch (i) {
2682 case NDA_IFINDEX:
David Ahern51183d22018-10-07 20:16:36 -07002683 filter->dev_idx = nla_get_u32(tb[i]);
2684 break;
2685 case NDA_MASTER:
David Ahern51183d22018-10-07 20:16:36 -07002686 filter->master_idx = nla_get_u32(tb[i]);
2687 break;
2688 default:
2689 if (strict_check) {
2690 NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor dump request");
2691 return -EINVAL;
2692 }
2693 }
2694 }
2695
2696 return 0;
2697}
2698
Thomas Grafc8822a42007-03-22 11:50:06 -07002699static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700{
David Ahern6f52f802018-10-03 15:33:12 -07002701 const struct nlmsghdr *nlh = cb->nlh;
2702 struct neigh_dump_filter filter = {};
Linus Torvalds1da177e2005-04-16 15:20:36 -07002703 struct neigh_table *tbl;
2704 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002705 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002706 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707
David Ahern6f52f802018-10-03 15:33:12 -07002708 family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002709
2710 /* check for full ndmsg structure presence, family member is
2711 * the same for both structures
2712 */
David Ahern6f52f802018-10-03 15:33:12 -07002713 if (nlmsg_len(nlh) >= sizeof(struct ndmsg) &&
2714 ((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY)
Tony Zelenoff84920c12012-01-26 22:28:58 +00002715 proxy = 1;
2716
David Ahern51183d22018-10-07 20:16:36 -07002717 err = neigh_valid_dump_req(nlh, cb->strict_check, &filter, cb->extack);
2718 if (err < 0 && cb->strict_check)
2719 return err;
2720
Linus Torvalds1da177e2005-04-16 15:20:36 -07002721 s_t = cb->args[0];
2722
WANG Congd7480fd2014-11-10 15:59:36 -08002723 for (t = 0; t < NEIGH_NR_TABLES; t++) {
2724 tbl = neigh_tables[t];
2725
2726 if (!tbl)
2727 continue;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002728 if (t < s_t || (family && tbl->family != family))
2729 continue;
2730 if (t > s_t)
2731 memset(&cb->args[1], 0, sizeof(cb->args) -
2732 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002733 if (proxy)
David Ahern6f52f802018-10-03 15:33:12 -07002734 err = pneigh_dump_table(tbl, skb, cb, &filter);
Tony Zelenoff84920c12012-01-26 22:28:58 +00002735 else
David Ahern6f52f802018-10-03 15:33:12 -07002736 err = neigh_dump_table(tbl, skb, cb, &filter);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002737 if (err < 0)
2738 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002739 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002740
2741 cb->args[0] = t;
2742 return skb->len;
2743}
2744
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08002745static int neigh_valid_get_req(const struct nlmsghdr *nlh,
2746 struct neigh_table **tbl,
2747 void **dst, int *dev_idx, u8 *ndm_flags,
2748 struct netlink_ext_ack *extack)
2749{
2750 struct nlattr *tb[NDA_MAX + 1];
2751 struct ndmsg *ndm;
2752 int err, i;
2753
2754 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2755 NL_SET_ERR_MSG(extack, "Invalid header for neighbor get request");
2756 return -EINVAL;
2757 }
2758
2759 ndm = nlmsg_data(nlh);
2760 if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state ||
2761 ndm->ndm_type) {
2762 NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor get request");
2763 return -EINVAL;
2764 }
2765
2766 if (ndm->ndm_flags & ~NTF_PROXY) {
2767 NL_SET_ERR_MSG(extack, "Invalid flags in header for neighbor get request");
2768 return -EINVAL;
2769 }
2770
Johannes Berg8cb08172019-04-26 14:07:28 +02002771 err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg), tb,
2772 NDA_MAX, nda_policy, extack);
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08002773 if (err < 0)
2774 return err;
2775
2776 *ndm_flags = ndm->ndm_flags;
2777 *dev_idx = ndm->ndm_ifindex;
2778 *tbl = neigh_find_table(ndm->ndm_family);
2779 if (*tbl == NULL) {
2780 NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
2781 return -EAFNOSUPPORT;
2782 }
2783
2784 for (i = 0; i <= NDA_MAX; ++i) {
2785 if (!tb[i])
2786 continue;
2787
2788 switch (i) {
2789 case NDA_DST:
2790 if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
2791 NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
2792 return -EINVAL;
2793 }
2794 *dst = nla_data(tb[i]);
2795 break;
2796 default:
2797 NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor get request");
2798 return -EINVAL;
2799 }
2800 }
2801
2802 return 0;
2803}
2804
2805static inline size_t neigh_nlmsg_size(void)
2806{
2807 return NLMSG_ALIGN(sizeof(struct ndmsg))
2808 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2809 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2810 + nla_total_size(sizeof(struct nda_cacheinfo))
2811 + nla_total_size(4) /* NDA_PROBES */
2812 + nla_total_size(1); /* NDA_PROTOCOL */
2813}
2814
2815static int neigh_get_reply(struct net *net, struct neighbour *neigh,
2816 u32 pid, u32 seq)
2817{
2818 struct sk_buff *skb;
2819 int err = 0;
2820
2821 skb = nlmsg_new(neigh_nlmsg_size(), GFP_KERNEL);
2822 if (!skb)
2823 return -ENOBUFS;
2824
2825 err = neigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0);
2826 if (err) {
2827 kfree_skb(skb);
2828 goto errout;
2829 }
2830
2831 err = rtnl_unicast(skb, net, pid);
2832errout:
2833 return err;
2834}
2835
2836static inline size_t pneigh_nlmsg_size(void)
2837{
2838 return NLMSG_ALIGN(sizeof(struct ndmsg))
Colin Ian King463561e2018-12-20 16:50:50 +00002839 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08002840 + nla_total_size(1); /* NDA_PROTOCOL */
2841}
2842
2843static int pneigh_get_reply(struct net *net, struct pneigh_entry *neigh,
2844 u32 pid, u32 seq, struct neigh_table *tbl)
2845{
2846 struct sk_buff *skb;
2847 int err = 0;
2848
2849 skb = nlmsg_new(pneigh_nlmsg_size(), GFP_KERNEL);
2850 if (!skb)
2851 return -ENOBUFS;
2852
2853 err = pneigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0, tbl);
2854 if (err) {
2855 kfree_skb(skb);
2856 goto errout;
2857 }
2858
2859 err = rtnl_unicast(skb, net, pid);
2860errout:
2861 return err;
2862}
2863
2864static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2865 struct netlink_ext_ack *extack)
2866{
2867 struct net *net = sock_net(in_skb->sk);
2868 struct net_device *dev = NULL;
2869 struct neigh_table *tbl = NULL;
2870 struct neighbour *neigh;
2871 void *dst = NULL;
2872 u8 ndm_flags = 0;
2873 int dev_idx = 0;
2874 int err;
2875
2876 err = neigh_valid_get_req(nlh, &tbl, &dst, &dev_idx, &ndm_flags,
2877 extack);
2878 if (err < 0)
2879 return err;
2880
2881 if (dev_idx) {
2882 dev = __dev_get_by_index(net, dev_idx);
2883 if (!dev) {
2884 NL_SET_ERR_MSG(extack, "Unknown device ifindex");
2885 return -ENODEV;
2886 }
2887 }
2888
2889 if (!dst) {
2890 NL_SET_ERR_MSG(extack, "Network address not specified");
2891 return -EINVAL;
2892 }
2893
2894 if (ndm_flags & NTF_PROXY) {
2895 struct pneigh_entry *pn;
2896
2897 pn = pneigh_lookup(tbl, net, dst, dev, 0);
2898 if (!pn) {
2899 NL_SET_ERR_MSG(extack, "Proxy neighbour entry not found");
2900 return -ENOENT;
2901 }
2902 return pneigh_get_reply(net, pn, NETLINK_CB(in_skb).portid,
2903 nlh->nlmsg_seq, tbl);
2904 }
2905
2906 if (!dev) {
2907 NL_SET_ERR_MSG(extack, "No device specified");
2908 return -EINVAL;
2909 }
2910
2911 neigh = neigh_lookup(tbl, dst, dev);
2912 if (!neigh) {
2913 NL_SET_ERR_MSG(extack, "Neighbour entry not found");
2914 return -ENOENT;
2915 }
2916
2917 err = neigh_get_reply(net, neigh, NETLINK_CB(in_skb).portid,
2918 nlh->nlmsg_seq);
2919
2920 neigh_release(neigh);
2921
2922 return err;
2923}
2924
Linus Torvalds1da177e2005-04-16 15:20:36 -07002925void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2926{
2927 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002928 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002929
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002930 rcu_read_lock_bh();
2931 nht = rcu_dereference_bh(tbl->nht);
2932
Eric Dumazet767e97e2010-10-06 17:49:21 -07002933 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002934 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002935 struct neighbour *n;
2936
Eric Dumazet767e97e2010-10-06 17:49:21 -07002937 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2938 n != NULL;
2939 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002940 cb(n, cookie);
2941 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002942 read_unlock(&tbl->lock);
2943 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002944}
2945EXPORT_SYMBOL(neigh_for_each);
2946
2947/* The tbl->lock must be held as a writer and BH disabled. */
2948void __neigh_for_each_release(struct neigh_table *tbl,
2949 int (*cb)(struct neighbour *))
2950{
2951 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002952 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002953
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002954 nht = rcu_dereference_protected(tbl->nht,
2955 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002956 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002957 struct neighbour *n;
2958 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002959
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002960 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002961 while ((n = rcu_dereference_protected(*np,
2962 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002963 int release;
2964
2965 write_lock(&n->lock);
2966 release = cb(n);
2967 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002968 rcu_assign_pointer(*np,
2969 rcu_dereference_protected(n->next,
2970 lockdep_is_held(&tbl->lock)));
David Ahern58956312018-12-07 12:24:57 -08002971 neigh_mark_dead(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 } else
2973 np = &n->next;
2974 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002975 if (release)
2976 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 }
2978 }
2979}
2980EXPORT_SYMBOL(__neigh_for_each_release);
2981
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002982int neigh_xmit(int index, struct net_device *dev,
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002983 const void *addr, struct sk_buff *skb)
2984{
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002985 int err = -EAFNOSUPPORT;
2986 if (likely(index < NEIGH_NR_TABLES)) {
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002987 struct neigh_table *tbl;
2988 struct neighbour *neigh;
2989
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06002990 tbl = neigh_tables[index];
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06002991 if (!tbl)
2992 goto out;
David Barrosob560f032016-06-28 11:16:43 +03002993 rcu_read_lock_bh();
David Ahern4b2a2bf2019-05-01 18:18:42 -07002994 if (index == NEIGH_ARP_TABLE) {
2995 u32 key = *((u32 *)addr);
2996
2997 neigh = __ipv4_neigh_lookup_noref(dev, key);
2998 } else {
2999 neigh = __neigh_lookup_noref(tbl, addr, dev);
3000 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06003001 if (!neigh)
3002 neigh = __neigh_create(tbl, addr, dev, false);
3003 err = PTR_ERR(neigh);
David Barrosob560f032016-06-28 11:16:43 +03003004 if (IS_ERR(neigh)) {
3005 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06003006 goto out_kfree_skb;
David Barrosob560f032016-06-28 11:16:43 +03003007 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06003008 err = neigh->output(neigh, skb);
David Barrosob560f032016-06-28 11:16:43 +03003009 rcu_read_unlock_bh();
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06003010 }
Eric W. Biedermanb79bda32015-03-07 16:25:56 -06003011 else if (index == NEIGH_LINK_TABLE) {
3012 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
3013 addr, NULL, skb->len);
3014 if (err < 0)
3015 goto out_kfree_skb;
3016 err = dev_queue_xmit(skb);
3017 }
Eric W. Biederman4fd3d7d2015-03-03 17:11:16 -06003018out:
3019 return err;
3020out_kfree_skb:
3021 kfree_skb(skb);
3022 goto out;
3023}
3024EXPORT_SYMBOL(neigh_xmit);
3025
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026#ifdef CONFIG_PROC_FS
3027
3028static struct neighbour *neigh_get_first(struct seq_file *seq)
3029{
3030 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003031 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003032 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003033 struct neighbour *n = NULL;
3034 int bucket = state->bucket;
3035
3036 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07003037 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07003038 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003039
3040 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003041 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003042 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 if (state->neigh_sub_iter) {
3044 loff_t fakep = 0;
3045 void *v;
3046
3047 v = state->neigh_sub_iter(state, n, &fakep);
3048 if (!v)
3049 goto next;
3050 }
3051 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
3052 break;
3053 if (n->nud_state & ~NUD_NOARP)
3054 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07003055next:
3056 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057 }
3058
3059 if (n)
3060 break;
3061 }
3062 state->bucket = bucket;
3063
3064 return n;
3065}
3066
3067static struct neighbour *neigh_get_next(struct seq_file *seq,
3068 struct neighbour *n,
3069 loff_t *pos)
3070{
3071 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003072 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003073 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074
3075 if (state->neigh_sub_iter) {
3076 void *v = state->neigh_sub_iter(state, n, pos);
3077 if (v)
3078 return n;
3079 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07003080 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003081
3082 while (1) {
3083 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003084 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003085 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003086 if (state->neigh_sub_iter) {
3087 void *v = state->neigh_sub_iter(state, n, pos);
3088 if (v)
3089 return n;
3090 goto next;
3091 }
3092 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
3093 break;
3094
3095 if (n->nud_state & ~NUD_NOARP)
3096 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07003097next:
3098 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 }
3100
3101 if (n)
3102 break;
3103
David S. Millercd089332011-07-11 01:28:12 -07003104 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07003105 break;
3106
Eric Dumazet767e97e2010-10-06 17:49:21 -07003107 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108 }
3109
3110 if (n && pos)
3111 --(*pos);
3112 return n;
3113}
3114
3115static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
3116{
3117 struct neighbour *n = neigh_get_first(seq);
3118
3119 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07003120 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003121 while (*pos) {
3122 n = neigh_get_next(seq, n, pos);
3123 if (!n)
3124 break;
3125 }
3126 }
3127 return *pos ? NULL : n;
3128}
3129
3130static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
3131{
3132 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003133 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 struct neigh_table *tbl = state->tbl;
3135 struct pneigh_entry *pn = NULL;
3136 int bucket = state->bucket;
3137
3138 state->flags |= NEIGH_SEQ_IS_PNEIGH;
3139 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
3140 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003141 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003142 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003143 if (pn)
3144 break;
3145 }
3146 state->bucket = bucket;
3147
3148 return pn;
3149}
3150
3151static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
3152 struct pneigh_entry *pn,
3153 loff_t *pos)
3154{
3155 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09003156 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 struct neigh_table *tbl = state->tbl;
3158
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05003159 do {
3160 pn = pn->next;
3161 } while (pn && !net_eq(pneigh_net(pn), net));
3162
Linus Torvalds1da177e2005-04-16 15:20:36 -07003163 while (!pn) {
3164 if (++state->bucket > PNEIGH_HASHMASK)
3165 break;
3166 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09003167 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08003168 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003169 if (pn)
3170 break;
3171 }
3172
3173 if (pn && pos)
3174 --(*pos);
3175
3176 return pn;
3177}
3178
3179static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
3180{
3181 struct pneigh_entry *pn = pneigh_get_first(seq);
3182
3183 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07003184 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185 while (*pos) {
3186 pn = pneigh_get_next(seq, pn, pos);
3187 if (!pn)
3188 break;
3189 }
3190 }
3191 return *pos ? NULL : pn;
3192}
3193
3194static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
3195{
3196 struct neigh_seq_state *state = seq->private;
3197 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07003198 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003199
Chris Larson745e2032008-08-03 01:10:55 -07003200 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003201 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07003202 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203
3204 return rc;
3205}
3206
3207void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetf3e92cb2019-06-15 16:28:48 -07003208 __acquires(tbl->lock)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003209 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003210{
3211 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003212
3213 state->tbl = tbl;
3214 state->bucket = 0;
3215 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
3216
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003217 rcu_read_lock_bh();
3218 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazetf3e92cb2019-06-15 16:28:48 -07003219 read_lock(&tbl->lock);
Eric Dumazet767e97e2010-10-06 17:49:21 -07003220
Chris Larson745e2032008-08-03 01:10:55 -07003221 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003222}
3223EXPORT_SYMBOL(neigh_seq_start);
3224
3225void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3226{
3227 struct neigh_seq_state *state;
3228 void *rc;
3229
3230 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07003231 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003232 goto out;
3233 }
3234
3235 state = seq->private;
3236 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
3237 rc = neigh_get_next(seq, v, NULL);
3238 if (rc)
3239 goto out;
3240 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
3241 rc = pneigh_get_first(seq);
3242 } else {
3243 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
3244 rc = pneigh_get_next(seq, v, NULL);
3245 }
3246out:
3247 ++(*pos);
3248 return rc;
3249}
3250EXPORT_SYMBOL(neigh_seq_next);
3251
3252void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetf3e92cb2019-06-15 16:28:48 -07003253 __releases(tbl->lock)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003254 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255{
Eric Dumazetf3e92cb2019-06-15 16:28:48 -07003256 struct neigh_seq_state *state = seq->private;
3257 struct neigh_table *tbl = state->tbl;
3258
3259 read_unlock(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00003260 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07003261}
3262EXPORT_SYMBOL(neigh_seq_stop);
3263
3264/* statistics via seq_file */
3265
3266static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
3267{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003268 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269 int cpu;
3270
3271 if (*pos == 0)
3272 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09003273
Rusty Russell0f23174a2008-12-29 12:23:42 +00003274 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 if (!cpu_possible(cpu))
3276 continue;
3277 *pos = cpu+1;
3278 return per_cpu_ptr(tbl->stats, cpu);
3279 }
3280 return NULL;
3281}
3282
3283static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
3284{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003285 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286 int cpu;
3287
Rusty Russell0f23174a2008-12-29 12:23:42 +00003288 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 if (!cpu_possible(cpu))
3290 continue;
3291 *pos = cpu+1;
3292 return per_cpu_ptr(tbl->stats, cpu);
3293 }
3294 return NULL;
3295}
3296
3297static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
3298{
3299
3300}
3301
3302static int neigh_stat_seq_show(struct seq_file *seq, void *v)
3303{
Christoph Hellwig71a50532018-04-15 10:16:41 +02003304 struct neigh_table *tbl = PDE_DATA(file_inode(seq->file));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305 struct neigh_statistics *st = v;
3306
3307 if (v == SEQ_START_TOKEN) {
Rick Jonesfb811392015-08-07 11:10:37 -07003308 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 -07003309 return 0;
3310 }
3311
3312 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Rick Jonesfb811392015-08-07 11:10:37 -07003313 "%08lx %08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314 atomic_read(&tbl->entries),
3315
3316 st->allocs,
3317 st->destroys,
3318 st->hash_grows,
3319
3320 st->lookups,
3321 st->hits,
3322
3323 st->res_failed,
3324
3325 st->rcv_probes_mcast,
3326 st->rcv_probes_ucast,
3327
3328 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07003329 st->forced_gc_runs,
Rick Jonesfb811392015-08-07 11:10:37 -07003330 st->unres_discards,
3331 st->table_fulls
Linus Torvalds1da177e2005-04-16 15:20:36 -07003332 );
3333
3334 return 0;
3335}
3336
Stephen Hemmingerf6908082007-03-12 14:34:29 -07003337static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003338 .start = neigh_stat_seq_start,
3339 .next = neigh_stat_seq_next,
3340 .stop = neigh_stat_seq_stop,
3341 .show = neigh_stat_seq_show,
3342};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343#endif /* CONFIG_PROC_FS */
3344
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003345static void __neigh_notify(struct neighbour *n, int type, int flags,
3346 u32 pid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09003348 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003349 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07003350 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003351
Thomas Graf339bf982006-11-10 14:10:15 -08003352 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07003353 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07003354 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003356 err = neigh_fill_info(skb, n, pid, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08003357 if (err < 0) {
3358 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
3359 WARN_ON(err == -EMSGSIZE);
3360 kfree_skb(skb);
3361 goto errout;
3362 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08003363 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
3364 return;
Thomas Grafb8673312006-08-15 00:33:14 -07003365errout:
3366 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08003367 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07003368}
3369
3370void neigh_app_ns(struct neighbour *n)
3371{
Roopa Prabhu7b8f7a42017-03-19 22:01:28 -07003372 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003373}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003374EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003375
3376#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08003377static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003378
Joe Perchesfe2c6332013-06-11 23:04:25 -07003379static int proc_unres_qlen(struct ctl_table *ctl, int write,
3380 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003381{
3382 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07003383 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003384
Matteo Croceeec48442019-07-18 15:58:50 -07003385 tmp.extra1 = SYSCTL_ZERO;
Shan Weice46cc62012-12-04 18:49:15 +00003386 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003387 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00003388
3389 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
3390 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3391
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003392 if (write && !ret)
3393 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
3394 return ret;
3395}
3396
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003397static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
3398 int family)
3399{
Jiri Pirkobba24892013-12-07 19:26:57 +01003400 switch (family) {
3401 case AF_INET:
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003402 return __in_dev_arp_parms_get_rcu(dev);
Jiri Pirkobba24892013-12-07 19:26:57 +01003403 case AF_INET6:
3404 return __in6_dev_nd_parms_get_rcu(dev);
3405 }
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003406 return NULL;
3407}
3408
3409static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
3410 int index)
3411{
3412 struct net_device *dev;
3413 int family = neigh_parms_family(p);
3414
3415 rcu_read_lock();
3416 for_each_netdev_rcu(net, dev) {
3417 struct neigh_parms *dst_p =
3418 neigh_get_dev_parms_rcu(dev, family);
3419
3420 if (dst_p && !test_bit(index, dst_p->data_state))
3421 dst_p->data[index] = p->data[index];
3422 }
3423 rcu_read_unlock();
3424}
3425
3426static void neigh_proc_update(struct ctl_table *ctl, int write)
3427{
3428 struct net_device *dev = ctl->extra1;
3429 struct neigh_parms *p = ctl->extra2;
Jiri Pirko77d47af2013-12-10 23:55:07 +01003430 struct net *net = neigh_parms_net(p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003431 int index = (int *) ctl->data - p->data;
3432
3433 if (!write)
3434 return;
3435
3436 set_bit(index, p->data_state);
Marcus Huewe7627ae62017-02-15 01:00:36 +01003437 if (index == NEIGH_VAR_DELAY_PROBE_TIME)
3438 call_netevent_notifiers(NETEVENT_DELAY_PROBE_TIME_UPDATE, p);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003439 if (!dev) /* NULL dev means this is default value */
3440 neigh_copy_dflt_parms(net, p, index);
3441}
3442
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003443static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3444 void __user *buffer,
3445 size_t *lenp, loff_t *ppos)
3446{
3447 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003448 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003449
Matteo Croceeec48442019-07-18 15:58:50 -07003450 tmp.extra1 = SYSCTL_ZERO;
3451 tmp.extra2 = SYSCTL_INT_MAX;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003452
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003453 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
3454 neigh_proc_update(ctl, write);
3455 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003456}
3457
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003458int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3459 void __user *buffer, size_t *lenp, loff_t *ppos)
3460{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003461 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
3462
3463 neigh_proc_update(ctl, write);
3464 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003465}
3466EXPORT_SYMBOL(neigh_proc_dointvec);
3467
3468int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3469 void __user *buffer,
3470 size_t *lenp, loff_t *ppos)
3471{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003472 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3473
3474 neigh_proc_update(ctl, write);
3475 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003476}
3477EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
3478
3479static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3480 void __user *buffer,
3481 size_t *lenp, loff_t *ppos)
3482{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003483 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
3484
3485 neigh_proc_update(ctl, write);
3486 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003487}
3488
3489int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3490 void __user *buffer,
3491 size_t *lenp, loff_t *ppos)
3492{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003493 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3494
3495 neigh_proc_update(ctl, write);
3496 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003497}
3498EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
3499
3500static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3501 void __user *buffer,
3502 size_t *lenp, loff_t *ppos)
3503{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003504 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
3505
3506 neigh_proc_update(ctl, write);
3507 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003508}
3509
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003510static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3511 void __user *buffer,
3512 size_t *lenp, loff_t *ppos)
3513{
3514 struct neigh_parms *p = ctl->extra2;
3515 int ret;
3516
3517 if (strcmp(ctl->procname, "base_reachable_time") == 0)
3518 ret = neigh_proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
3519 else if (strcmp(ctl->procname, "base_reachable_time_ms") == 0)
3520 ret = neigh_proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
3521 else
3522 ret = -1;
3523
3524 if (write && ret == 0) {
3525 /* update reachable_time as well, otherwise, the change will
3526 * only be effective after the next time neigh_periodic_work
3527 * decides to recompute it
3528 */
3529 p->reachable_time =
3530 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
3531 }
3532 return ret;
3533}
3534
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003535#define NEIGH_PARMS_DATA_OFFSET(index) \
3536 (&((struct neigh_parms *) 0)->data[index])
3537
3538#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
3539 [NEIGH_VAR_ ## attr] = { \
3540 .procname = name, \
3541 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
3542 .maxlen = sizeof(int), \
3543 .mode = mval, \
3544 .proc_handler = proc, \
3545 }
3546
3547#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
3548 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
3549
3550#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003551 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003552
3553#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003554 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003555
3556#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003557 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003558
3559#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003560 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003561
3562#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003563 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00003564
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565static struct neigh_sysctl_table {
3566 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003567 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07003568} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003570 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
3571 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
3572 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
YOSHIFUJI Hideaki/吉藤英明8da86462015-03-19 22:41:46 +09003573 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_REPROBES, "mcast_resolicit"),
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003574 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
3575 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
3576 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
3577 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
3578 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
3579 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
3580 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
3581 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
3582 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
3583 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
3584 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
3585 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003586 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003587 .procname = "gc_interval",
3588 .maxlen = sizeof(int),
3589 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08003590 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003592 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003593 .procname = "gc_thresh1",
3594 .maxlen = sizeof(int),
3595 .mode = 0644,
Matteo Croceeec48442019-07-18 15:58:50 -07003596 .extra1 = SYSCTL_ZERO,
3597 .extra2 = SYSCTL_INT_MAX,
Francesco Fusco555445c2013-07-24 10:39:06 +02003598 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003599 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003600 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003601 .procname = "gc_thresh2",
3602 .maxlen = sizeof(int),
3603 .mode = 0644,
Matteo Croceeec48442019-07-18 15:58:50 -07003604 .extra1 = SYSCTL_ZERO,
3605 .extra2 = SYSCTL_INT_MAX,
Francesco Fusco555445c2013-07-24 10:39:06 +02003606 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003607 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003608 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003609 .procname = "gc_thresh3",
3610 .maxlen = sizeof(int),
3611 .mode = 0644,
Matteo Croceeec48442019-07-18 15:58:50 -07003612 .extra1 = SYSCTL_ZERO,
3613 .extra2 = SYSCTL_INT_MAX,
Francesco Fusco555445c2013-07-24 10:39:06 +02003614 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003615 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003616 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003617 },
3618};
3619
3620int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003621 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003622{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003623 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003624 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003625 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003626 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003627 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003628
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003629 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003630 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003631 goto err;
3632
Jiri Pirkob194c1f2014-02-21 14:52:57 +01003633 for (i = 0; i < NEIGH_VAR_GC_INTERVAL; i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003634 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003635 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003636 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003637 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003638
3639 if (dev) {
3640 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003641 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003642 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3643 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003644 } else {
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003645 struct neigh_table *tbl = p->tbl;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003646 dev_name_source = "default";
Mathias Krause9ecf07a2014-07-12 22:36:44 +02003647 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = &tbl->gc_interval;
3648 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = &tbl->gc_thresh1;
3649 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = &tbl->gc_thresh2;
3650 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = &tbl->gc_thresh3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 }
3652
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003653 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003654 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003655 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003656 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003657 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003658 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003659 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003660 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003661 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Jean-Francois Remy4bf69802015-01-14 04:22:39 +01003662 } else {
3663 /* Those handlers will update p->reachable_time after
3664 * base_reachable_time(_ms) is set to ensure the new timer starts being
3665 * applied after the next neighbour update instead of waiting for
3666 * neigh_periodic_work to update its value (can be multiple minutes)
3667 * So any handler that replaces them should do this as well
3668 */
3669 /* ReachableTime */
3670 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler =
3671 neigh_proc_base_reachable_time;
3672 /* ReachableTime (in milliseconds) */
3673 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler =
3674 neigh_proc_base_reachable_time;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003675 }
3676
Eric W. Biederman464dc802012-11-16 03:02:59 +00003677 /* Don't export sysctls to unprivileged users */
3678 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3679 t->neigh_vars[0].procname = NULL;
3680
Jiri Pirko73af6142013-12-07 19:26:55 +01003681 switch (neigh_parms_family(p)) {
3682 case AF_INET:
3683 p_name = "ipv4";
3684 break;
3685 case AF_INET6:
3686 p_name = "ipv6";
3687 break;
3688 default:
3689 BUG();
3690 }
3691
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003692 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3693 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003694 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003695 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003696 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003697 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003698
Linus Torvalds1da177e2005-04-16 15:20:36 -07003699 p->sysctl_table = t;
3700 return 0;
3701
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003702free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003704err:
3705 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003706}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003707EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003708
3709void neigh_sysctl_unregister(struct neigh_parms *p)
3710{
3711 if (p->sysctl_table) {
3712 struct neigh_sysctl_table *t = p->sysctl_table;
3713 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003714 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003715 kfree(t);
3716 }
3717}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003718EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003719
3720#endif /* CONFIG_SYSCTL */
3721
Thomas Grafc8822a42007-03-22 11:50:06 -07003722static int __init neigh_init(void)
3723{
Florian Westphalb97bac62017-08-09 20:41:48 +02003724 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
3725 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
Roopa Prabhu82cbb5c2018-12-19 12:51:38 -08003726 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003727
Greg Rosec7ac8672011-06-10 01:27:09 +00003728 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
Florian Westphalb97bac62017-08-09 20:41:48 +02003729 0);
3730 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
Thomas Grafc8822a42007-03-22 11:50:06 -07003731
3732 return 0;
3733}
3734
3735subsys_initcall(neigh_init);