blob: c4a7879bfb150c9a005c4928cdad3e6833d72623 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Generic address resolution entity
3 *
4 * Authors:
5 * Pedro Roque <roque@di.fc.ul.pt>
6 * Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version
11 * 2 of the License, or (at your option) any later version.
12 *
13 * Fixes:
14 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
15 * Harald Welte Add neighbour cache statistics like rtstat
16 */
17
Joe Perchese005d192012-05-16 19:58:40 +000018#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
19
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090020#include <linux/slab.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070021#include <linux/types.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/netdevice.h>
26#include <linux/proc_fs.h>
27#ifdef CONFIG_SYSCTL
28#include <linux/sysctl.h>
29#endif
30#include <linux/times.h>
Eric W. Biederman457c4cb2007-09-12 12:01:34 +020031#include <net/net_namespace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#include <net/neighbour.h>
33#include <net/dst.h>
34#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070035#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070036#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037#include <linux/rtnetlink.h>
38#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070039#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070040#include <linux/log2.h>
Jiri Pirko1d4c8c22013-12-07 19:26:56 +010041#include <linux/inetdevice.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042
Joe Perchesd5d427c2013-04-15 15:17:19 +000043#define DEBUG
Linus Torvalds1da177e2005-04-16 15:20:36 -070044#define NEIGH_DEBUG 1
Joe Perchesd5d427c2013-04-15 15:17:19 +000045#define neigh_dbg(level, fmt, ...) \
46do { \
47 if (level <= NEIGH_DEBUG) \
48 pr_debug(fmt, ##__VA_ARGS__); \
49} while (0)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050
51#define PNEIGH_HASHMASK 0xF
52
53static void neigh_timer_handler(unsigned long arg);
Thomas Grafd961db32007-08-08 23:12:56 -070054static void __neigh_notify(struct neighbour *n, int type, int flags);
55static void neigh_update_notify(struct neighbour *neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -070056static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
58static struct neigh_table *neigh_tables;
Amos Waterland45fc3b12005-09-24 16:53:16 -070059#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080060static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070061#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63/*
64 Neighbour hash table buckets are protected with rwlock tbl->lock.
65
66 - All the scans/updates to hash buckets MUST be made under this lock.
67 - NOTHING clever should be made under this lock: no callbacks
68 to protocol backends, no attempts to send something to network.
69 It will result in deadlocks, if backend/driver wants to use neighbour
70 cache.
71 - If the entry requires some non-trivial actions, increase
72 its reference count and release table lock.
73
74 Neighbour entries are protected:
75 - with reference count.
76 - with rwlock neigh->lock
77
78 Reference count prevents destruction.
79
80 neigh->lock mainly serializes ll address data and its validity state.
81 However, the same lock is used to protect another entry fields:
82 - timer
83 - resolution queue
84
85 Again, nothing clever shall be made under neigh->lock,
86 the most complicated procedure, which we allow is dev->hard_header.
87 It is supposed, that dev->hard_header is simplistic and does
88 not make callbacks to neighbour tables.
89
90 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
91 list of neighbour tables. This list is used only in process context,
92 */
93
94static DEFINE_RWLOCK(neigh_tbl_lock);
95
David S. Miller8f40b162011-07-17 13:34:11 -070096static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097{
98 kfree_skb(skb);
99 return -ENETDOWN;
100}
101
Thomas Graf4f494552007-08-08 23:12:36 -0700102static void neigh_cleanup_and_release(struct neighbour *neigh)
103{
104 if (neigh->parms->neigh_cleanup)
105 neigh->parms->neigh_cleanup(neigh);
106
Thomas Grafd961db32007-08-08 23:12:56 -0700107 __neigh_notify(neigh, RTM_DELNEIGH, 0);
Thomas Graf4f494552007-08-08 23:12:36 -0700108 neigh_release(neigh);
109}
110
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111/*
112 * It is random distribution in the interval (1/2)*base...(3/2)*base.
113 * It corresponds to default IPv6 settings and is not overridable,
114 * because it is really reasonable choice.
115 */
116
117unsigned long neigh_rand_reach_time(unsigned long base)
118{
Eric Dumazeta02cec22010-09-22 20:43:57 +0000119 return base ? (net_random() % base) + (base >> 1) : 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900121EXPORT_SYMBOL(neigh_rand_reach_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
123
124static int neigh_forced_gc(struct neigh_table *tbl)
125{
126 int shrunk = 0;
127 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000128 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129
130 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
131
132 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000133 nht = rcu_dereference_protected(tbl->nht,
134 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700135 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700136 struct neighbour *n;
137 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000139 np = &nht->hash_buckets[i];
Eric Dumazet767e97e2010-10-06 17:49:21 -0700140 while ((n = rcu_dereference_protected(*np,
141 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 /* Neighbour record may be discarded if:
143 * - nobody refers to it.
144 * - it is not permanent
145 */
146 write_lock(&n->lock);
147 if (atomic_read(&n->refcnt) == 1 &&
148 !(n->nud_state & NUD_PERMANENT)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700149 rcu_assign_pointer(*np,
150 rcu_dereference_protected(n->next,
151 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152 n->dead = 1;
153 shrunk = 1;
154 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700155 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156 continue;
157 }
158 write_unlock(&n->lock);
159 np = &n->next;
160 }
161 }
162
163 tbl->last_flush = jiffies;
164
165 write_unlock_bh(&tbl->lock);
166
167 return shrunk;
168}
169
Pavel Emelyanova43d8992007-12-20 15:49:05 -0800170static void neigh_add_timer(struct neighbour *n, unsigned long when)
171{
172 neigh_hold(n);
173 if (unlikely(mod_timer(&n->timer, when))) {
174 printk("NEIGH: BUG, double timer add, state is %x\n",
175 n->nud_state);
176 dump_stack();
177 }
178}
179
Linus Torvalds1da177e2005-04-16 15:20:36 -0700180static int neigh_del_timer(struct neighbour *n)
181{
182 if ((n->nud_state & NUD_IN_TIMER) &&
183 del_timer(&n->timer)) {
184 neigh_release(n);
185 return 1;
186 }
187 return 0;
188}
189
190static void pneigh_queue_purge(struct sk_buff_head *list)
191{
192 struct sk_buff *skb;
193
194 while ((skb = skb_dequeue(list)) != NULL) {
195 dev_put(skb->dev);
196 kfree_skb(skb);
197 }
198}
199
Herbert Xu49636bb2005-10-23 17:18:00 +1000200static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700201{
202 int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000203 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000205 nht = rcu_dereference_protected(tbl->nht,
206 lockdep_is_held(&tbl->lock));
207
David S. Millercd089332011-07-11 01:28:12 -0700208 for (i = 0; i < (1 << nht->hash_shift); i++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700209 struct neighbour *n;
210 struct neighbour __rcu **np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700211
Eric Dumazet767e97e2010-10-06 17:49:21 -0700212 while ((n = rcu_dereference_protected(*np,
213 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700214 if (dev && n->dev != dev) {
215 np = &n->next;
216 continue;
217 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700218 rcu_assign_pointer(*np,
219 rcu_dereference_protected(n->next,
220 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700221 write_lock(&n->lock);
222 neigh_del_timer(n);
223 n->dead = 1;
224
225 if (atomic_read(&n->refcnt) != 1) {
226 /* The most unpleasant situation.
227 We must destroy neighbour entry,
228 but someone still uses it.
229
230 The destroy will be delayed until
231 the last user releases us, but
232 we must kill timers etc. and move
233 it to safe state.
234 */
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700235 __skb_queue_purge(&n->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000236 n->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700237 n->output = neigh_blackhole;
238 if (n->nud_state & NUD_VALID)
239 n->nud_state = NUD_NOARP;
240 else
241 n->nud_state = NUD_NONE;
Joe Perchesd5d427c2013-04-15 15:17:19 +0000242 neigh_dbg(2, "neigh %p is stray\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243 }
244 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700245 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246 }
247 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000248}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700249
Herbert Xu49636bb2005-10-23 17:18:00 +1000250void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
251{
252 write_lock_bh(&tbl->lock);
253 neigh_flush_dev(tbl, dev);
254 write_unlock_bh(&tbl->lock);
255}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900256EXPORT_SYMBOL(neigh_changeaddr);
Herbert Xu49636bb2005-10-23 17:18:00 +1000257
258int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
259{
260 write_lock_bh(&tbl->lock);
261 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700262 pneigh_ifdown(tbl, dev);
263 write_unlock_bh(&tbl->lock);
264
265 del_timer_sync(&tbl->proxy_timer);
266 pneigh_queue_purge(&tbl->proxy_queue);
267 return 0;
268}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900269EXPORT_SYMBOL(neigh_ifdown);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270
David Miller596b9b62011-07-25 00:01:25 +0000271static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272{
273 struct neighbour *n = NULL;
274 unsigned long now = jiffies;
275 int entries;
276
277 entries = atomic_inc_return(&tbl->entries) - 1;
278 if (entries >= tbl->gc_thresh3 ||
279 (entries >= tbl->gc_thresh2 &&
280 time_after(now, tbl->last_flush + 5 * HZ))) {
281 if (!neigh_forced_gc(tbl) &&
282 entries >= tbl->gc_thresh3)
283 goto out_entries;
284 }
285
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +0000286 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700287 if (!n)
288 goto out_entries;
289
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700290 __skb_queue_head_init(&n->arp_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291 rwlock_init(&n->lock);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +0000292 seqlock_init(&n->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293 n->updated = n->used = now;
294 n->nud_state = NUD_NONE;
295 n->output = neigh_blackhole;
David S. Millerf6b72b62011-07-14 07:53:20 -0700296 seqlock_init(&n->hh.hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700297 n->parms = neigh_parms_clone(&tbl->parms);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800298 setup_timer(&n->timer, neigh_timer_handler, (unsigned long)n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299
300 NEIGH_CACHE_STAT_INC(tbl, allocs);
301 n->tbl = tbl;
302 atomic_set(&n->refcnt, 1);
303 n->dead = 1;
304out:
305 return n;
306
307out_entries:
308 atomic_dec(&tbl->entries);
309 goto out;
310}
311
David S. Miller2c2aba62011-12-28 15:06:58 -0500312static void neigh_get_hash_rnd(u32 *x)
313{
314 get_random_bytes(x, sizeof(*x));
315 *x |= 1;
316}
317
David S. Millercd089332011-07-11 01:28:12 -0700318static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700319{
David S. Millercd089332011-07-11 01:28:12 -0700320 size_t size = (1 << shift) * sizeof(struct neighbour *);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000321 struct neigh_hash_table *ret;
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000322 struct neighbour __rcu **buckets;
David S. Miller2c2aba62011-12-28 15:06:58 -0500323 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000325 ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
326 if (!ret)
327 return NULL;
328 if (size <= PAGE_SIZE)
329 buckets = kzalloc(size, GFP_ATOMIC);
330 else
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000331 buckets = (struct neighbour __rcu **)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000332 __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
333 get_order(size));
334 if (!buckets) {
335 kfree(ret);
336 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700337 }
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000338 ret->hash_buckets = buckets;
David S. Millercd089332011-07-11 01:28:12 -0700339 ret->hash_shift = shift;
David S. Miller2c2aba62011-12-28 15:06:58 -0500340 for (i = 0; i < NEIGH_NUM_HASH_RND; i++)
341 neigh_get_hash_rnd(&ret->hash_rnd[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 return ret;
343}
344
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000345static void neigh_hash_free_rcu(struct rcu_head *head)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000347 struct neigh_hash_table *nht = container_of(head,
348 struct neigh_hash_table,
349 rcu);
David S. Millercd089332011-07-11 01:28:12 -0700350 size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
Eric Dumazet6193d2b2011-01-19 22:02:47 +0000351 struct neighbour __rcu **buckets = nht->hash_buckets;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352
353 if (size <= PAGE_SIZE)
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000354 kfree(buckets);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 else
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000356 free_pages((unsigned long)buckets, get_order(size));
357 kfree(nht);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700358}
359
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000360static struct neigh_hash_table *neigh_hash_grow(struct neigh_table *tbl,
David S. Millercd089332011-07-11 01:28:12 -0700361 unsigned long new_shift)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362{
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000363 unsigned int i, hash;
364 struct neigh_hash_table *new_nht, *old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700365
366 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
367
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000368 old_nht = rcu_dereference_protected(tbl->nht,
369 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -0700370 new_nht = neigh_hash_alloc(new_shift);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000371 if (!new_nht)
372 return old_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373
David S. Millercd089332011-07-11 01:28:12 -0700374 for (i = 0; i < (1 << old_nht->hash_shift); i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700375 struct neighbour *n, *next;
376
Eric Dumazet767e97e2010-10-06 17:49:21 -0700377 for (n = rcu_dereference_protected(old_nht->hash_buckets[i],
378 lockdep_is_held(&tbl->lock));
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000379 n != NULL;
380 n = next) {
381 hash = tbl->hash(n->primary_key, n->dev,
382 new_nht->hash_rnd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383
David S. Millercd089332011-07-11 01:28:12 -0700384 hash >>= (32 - new_nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700385 next = rcu_dereference_protected(n->next,
386 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Eric Dumazet767e97e2010-10-06 17:49:21 -0700388 rcu_assign_pointer(n->next,
389 rcu_dereference_protected(
390 new_nht->hash_buckets[hash],
391 lockdep_is_held(&tbl->lock)));
392 rcu_assign_pointer(new_nht->hash_buckets[hash], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700393 }
394 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700395
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000396 rcu_assign_pointer(tbl->nht, new_nht);
397 call_rcu(&old_nht->rcu, neigh_hash_free_rcu);
398 return new_nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399}
400
401struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
402 struct net_device *dev)
403{
404 struct neighbour *n;
405 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800406 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000407 struct neigh_hash_table *nht;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900408
Linus Torvalds1da177e2005-04-16 15:20:36 -0700409 NEIGH_CACHE_STAT_INC(tbl, lookups);
410
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000411 rcu_read_lock_bh();
412 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700413 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700414
415 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
416 n != NULL;
417 n = rcu_dereference_bh(n->next)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700418 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700419 if (!atomic_inc_not_zero(&n->refcnt))
420 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 NEIGH_CACHE_STAT_INC(tbl, hits);
422 break;
423 }
424 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700425
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000426 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 return n;
428}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900429EXPORT_SYMBOL(neigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430
Eric W. Biederman426b5302008-01-24 00:13:18 -0800431struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
432 const void *pkey)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433{
434 struct neighbour *n;
435 int key_len = tbl->key_len;
Pavel Emelyanovbc4bf5f2008-02-23 19:57:02 -0800436 u32 hash_val;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000437 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
439 NEIGH_CACHE_STAT_INC(tbl, lookups);
440
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000441 rcu_read_lock_bh();
442 nht = rcu_dereference_bh(tbl->nht);
David S. Millercd089332011-07-11 01:28:12 -0700443 hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700444
445 for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
446 n != NULL;
447 n = rcu_dereference_bh(n->next)) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800448 if (!memcmp(n->primary_key, pkey, key_len) &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900449 net_eq(dev_net(n->dev), net)) {
Eric Dumazet767e97e2010-10-06 17:49:21 -0700450 if (!atomic_inc_not_zero(&n->refcnt))
451 n = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452 NEIGH_CACHE_STAT_INC(tbl, hits);
453 break;
454 }
455 }
Eric Dumazet767e97e2010-10-06 17:49:21 -0700456
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000457 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 return n;
459}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900460EXPORT_SYMBOL(neigh_lookup_nodev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461
David S. Millera263b302012-07-02 02:02:15 -0700462struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
463 struct net_device *dev, bool want_ref)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
465 u32 hash_val;
466 int key_len = tbl->key_len;
467 int error;
David Miller596b9b62011-07-25 00:01:25 +0000468 struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000469 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 if (!n) {
472 rc = ERR_PTR(-ENOBUFS);
473 goto out;
474 }
475
476 memcpy(n->primary_key, pkey, key_len);
477 n->dev = dev;
478 dev_hold(dev);
479
480 /* Protocol specific setup. */
481 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
482 rc = ERR_PTR(error);
483 goto out_neigh_release;
484 }
485
David Millerda6a8fa2011-07-25 00:01:38 +0000486 if (dev->netdev_ops->ndo_neigh_construct) {
487 error = dev->netdev_ops->ndo_neigh_construct(n);
488 if (error < 0) {
489 rc = ERR_PTR(error);
490 goto out_neigh_release;
491 }
492 }
493
David S. Miller447f2192011-12-19 15:04:41 -0500494 /* Device specific setup. */
495 if (n->parms->neigh_setup &&
496 (error = n->parms->neigh_setup(n)) < 0) {
497 rc = ERR_PTR(error);
498 goto out_neigh_release;
499 }
500
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100501 n->confirmed = jiffies - (NEIGH_VAR(n->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502
503 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000504 nht = rcu_dereference_protected(tbl->nht,
505 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506
David S. Millercd089332011-07-11 01:28:12 -0700507 if (atomic_read(&tbl->entries) > (1 << nht->hash_shift))
508 nht = neigh_hash_grow(tbl, nht->hash_shift + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509
David S. Millercd089332011-07-11 01:28:12 -0700510 hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511
512 if (n->parms->dead) {
513 rc = ERR_PTR(-EINVAL);
514 goto out_tbl_unlock;
515 }
516
Eric Dumazet767e97e2010-10-06 17:49:21 -0700517 for (n1 = rcu_dereference_protected(nht->hash_buckets[hash_val],
518 lockdep_is_held(&tbl->lock));
519 n1 != NULL;
520 n1 = rcu_dereference_protected(n1->next,
521 lockdep_is_held(&tbl->lock))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
David S. Millera263b302012-07-02 02:02:15 -0700523 if (want_ref)
524 neigh_hold(n1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 rc = n1;
526 goto out_tbl_unlock;
527 }
528 }
529
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 n->dead = 0;
David S. Millera263b302012-07-02 02:02:15 -0700531 if (want_ref)
532 neigh_hold(n);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700533 rcu_assign_pointer(n->next,
534 rcu_dereference_protected(nht->hash_buckets[hash_val],
535 lockdep_is_held(&tbl->lock)));
536 rcu_assign_pointer(nht->hash_buckets[hash_val], n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000538 neigh_dbg(2, "neigh %p is created\n", n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 rc = n;
540out:
541 return rc;
542out_tbl_unlock:
543 write_unlock_bh(&tbl->lock);
544out_neigh_release:
545 neigh_release(n);
546 goto out;
547}
David S. Millera263b302012-07-02 02:02:15 -0700548EXPORT_SYMBOL(__neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900550static u32 pneigh_hash(const void *pkey, int key_len)
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700551{
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700552 u32 hash_val = *(u32 *)(pkey + key_len - 4);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700553 hash_val ^= (hash_val >> 16);
554 hash_val ^= hash_val >> 8;
555 hash_val ^= hash_val >> 4;
556 hash_val &= PNEIGH_HASHMASK;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900557 return hash_val;
558}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700559
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900560static struct pneigh_entry *__pneigh_lookup_1(struct pneigh_entry *n,
561 struct net *net,
562 const void *pkey,
563 int key_len,
564 struct net_device *dev)
565{
566 while (n) {
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700567 if (!memcmp(n->key, pkey, key_len) &&
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900568 net_eq(pneigh_net(n), net) &&
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700569 (n->dev == dev || !n->dev))
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900570 return n;
571 n = n->next;
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700572 }
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900573 return NULL;
574}
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700575
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900576struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
577 struct net *net, const void *pkey, struct net_device *dev)
578{
579 int key_len = tbl->key_len;
580 u32 hash_val = pneigh_hash(pkey, key_len);
581
582 return __pneigh_lookup_1(tbl->phash_buckets[hash_val],
583 net, pkey, key_len, dev);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700584}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900585EXPORT_SYMBOL_GPL(__pneigh_lookup);
Pavel Emelyanovfa86d322008-03-24 14:48:59 -0700586
Eric W. Biederman426b5302008-01-24 00:13:18 -0800587struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
588 struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589 struct net_device *dev, int creat)
590{
591 struct pneigh_entry *n;
592 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900593 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
595 read_lock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900596 n = __pneigh_lookup_1(tbl->phash_buckets[hash_val],
597 net, pkey, key_len, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 read_unlock_bh(&tbl->lock);
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900599
600 if (n || !creat)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601 goto out;
602
Pavel Emelyanov4ae28942007-10-15 12:54:15 -0700603 ASSERT_RTNL();
604
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
606 if (!n)
607 goto out;
608
Eric Dumazete42ea982008-11-12 00:54:54 -0800609 write_pnet(&n->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 memcpy(n->key, pkey, key_len);
611 n->dev = dev;
612 if (dev)
613 dev_hold(dev);
614
615 if (tbl->pconstructor && tbl->pconstructor(n)) {
616 if (dev)
617 dev_put(dev);
Denis V. Lunevda12f732008-02-20 00:26:16 -0800618 release_net(net);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 kfree(n);
620 n = NULL;
621 goto out;
622 }
623
624 write_lock_bh(&tbl->lock);
625 n->next = tbl->phash_buckets[hash_val];
626 tbl->phash_buckets[hash_val] = n;
627 write_unlock_bh(&tbl->lock);
628out:
629 return n;
630}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900631EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632
633
Eric W. Biederman426b5302008-01-24 00:13:18 -0800634int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635 struct net_device *dev)
636{
637 struct pneigh_entry *n, **np;
638 int key_len = tbl->key_len;
YOSHIFUJI Hideakibe01d652008-03-28 12:46:53 +0900639 u32 hash_val = pneigh_hash(pkey, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700640
641 write_lock_bh(&tbl->lock);
642 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
643 np = &n->next) {
Eric W. Biederman426b5302008-01-24 00:13:18 -0800644 if (!memcmp(n->key, pkey, key_len) && n->dev == dev &&
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +0900645 net_eq(pneigh_net(n), net)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 *np = n->next;
647 write_unlock_bh(&tbl->lock);
648 if (tbl->pdestructor)
649 tbl->pdestructor(n);
650 if (n->dev)
651 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900652 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700653 kfree(n);
654 return 0;
655 }
656 }
657 write_unlock_bh(&tbl->lock);
658 return -ENOENT;
659}
660
661static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
662{
663 struct pneigh_entry *n, **np;
664 u32 h;
665
666 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
667 np = &tbl->phash_buckets[h];
668 while ((n = *np) != NULL) {
669 if (!dev || n->dev == dev) {
670 *np = n->next;
671 if (tbl->pdestructor)
672 tbl->pdestructor(n);
673 if (n->dev)
674 dev_put(n->dev);
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +0900675 release_net(pneigh_net(n));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676 kfree(n);
677 continue;
678 }
679 np = &n->next;
680 }
681 }
682 return -ENOENT;
683}
684
Denis V. Lunev06f05112008-01-24 00:30:58 -0800685static void neigh_parms_destroy(struct neigh_parms *parms);
686
687static inline void neigh_parms_put(struct neigh_parms *parms)
688{
689 if (atomic_dec_and_test(&parms->refcnt))
690 neigh_parms_destroy(parms);
691}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693/*
694 * neighbour must already be out of the table;
695 *
696 */
697void neigh_destroy(struct neighbour *neigh)
698{
David Millerda6a8fa2011-07-25 00:01:38 +0000699 struct net_device *dev = neigh->dev;
700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
702
703 if (!neigh->dead) {
Joe Perchese005d192012-05-16 19:58:40 +0000704 pr_warn("Destroying alive neighbour %p\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 dump_stack();
706 return;
707 }
708
709 if (neigh_del_timer(neigh))
Joe Perchese005d192012-05-16 19:58:40 +0000710 pr_warn("Impossible event\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700712 write_lock_bh(&neigh->lock);
713 __skb_queue_purge(&neigh->arp_queue);
714 write_unlock_bh(&neigh->lock);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000715 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
David S. Miller447f2192011-12-19 15:04:41 -0500717 if (dev->netdev_ops->ndo_neigh_destroy)
718 dev->netdev_ops->ndo_neigh_destroy(neigh);
719
David Millerda6a8fa2011-07-25 00:01:38 +0000720 dev_put(dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 neigh_parms_put(neigh->parms);
722
Joe Perchesd5d427c2013-04-15 15:17:19 +0000723 neigh_dbg(2, "neigh %p is destroyed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 atomic_dec(&neigh->tbl->entries);
David Miller5b8b0062011-07-25 00:01:22 +0000726 kfree_rcu(neigh, rcu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +0900728EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700729
730/* Neighbour state is suspicious;
731 disable fast path.
732
733 Called with write_locked neigh.
734 */
735static void neigh_suspect(struct neighbour *neigh)
736{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000737 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738
739 neigh->output = neigh->ops->output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740}
741
742/* Neighbour state is OK;
743 enable fast path.
744
745 Called with write_locked neigh.
746 */
747static void neigh_connect(struct neighbour *neigh)
748{
Joe Perchesd5d427c2013-04-15 15:17:19 +0000749 neigh_dbg(2, "neigh %p is connected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
751 neigh->output = neigh->ops->connected_output;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752}
753
Eric Dumazete4c4e442009-07-30 03:15:07 +0000754static void neigh_periodic_work(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755{
Eric Dumazete4c4e442009-07-30 03:15:07 +0000756 struct neigh_table *tbl = container_of(work, struct neigh_table, gc_work.work);
Eric Dumazet767e97e2010-10-06 17:49:21 -0700757 struct neighbour *n;
758 struct neighbour __rcu **np;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000759 unsigned int i;
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000760 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761
762 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
763
Eric Dumazete4c4e442009-07-30 03:15:07 +0000764 write_lock_bh(&tbl->lock);
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000765 nht = rcu_dereference_protected(tbl->nht,
766 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000768 if (atomic_read(&tbl->entries) < tbl->gc_thresh1)
769 goto out;
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 /*
772 * periodically recompute ReachableTime from random function
773 */
774
Eric Dumazete4c4e442009-07-30 03:15:07 +0000775 if (time_after(jiffies, tbl->last_rand + 300 * HZ)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 struct neigh_parms *p;
Eric Dumazete4c4e442009-07-30 03:15:07 +0000777 tbl->last_rand = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 for (p = &tbl->parms; p; p = p->next)
779 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100780 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 }
782
David S. Millercd089332011-07-11 01:28:12 -0700783 for (i = 0 ; i < (1 << nht->hash_shift); i++) {
Eric Dumazetd6bf7812010-10-04 06:15:44 +0000784 np = &nht->hash_buckets[i];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785
Eric Dumazet767e97e2010-10-06 17:49:21 -0700786 while ((n = rcu_dereference_protected(*np,
787 lockdep_is_held(&tbl->lock))) != NULL) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000788 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789
Eric Dumazete4c4e442009-07-30 03:15:07 +0000790 write_lock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700791
Eric Dumazete4c4e442009-07-30 03:15:07 +0000792 state = n->nud_state;
793 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
794 write_unlock(&n->lock);
795 goto next_elt;
796 }
797
798 if (time_before(n->used, n->confirmed))
799 n->used = n->confirmed;
800
801 if (atomic_read(&n->refcnt) == 1 &&
802 (state == NUD_FAILED ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100803 time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
Eric Dumazete4c4e442009-07-30 03:15:07 +0000804 *np = n->next;
805 n->dead = 1;
806 write_unlock(&n->lock);
807 neigh_cleanup_and_release(n);
808 continue;
809 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 write_unlock(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811
812next_elt:
Eric Dumazete4c4e442009-07-30 03:15:07 +0000813 np = &n->next;
814 }
815 /*
816 * It's fine to release lock here, even if hash table
817 * grows while we are preempted.
818 */
819 write_unlock_bh(&tbl->lock);
820 cond_resched();
821 write_lock_bh(&tbl->lock);
Michel Machado84338a62012-02-21 16:04:13 -0500822 nht = rcu_dereference_protected(tbl->nht,
823 lockdep_is_held(&tbl->lock));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 }
YOSHIFUJI Hideaki / 吉藤英明27246802013-01-22 05:20:05 +0000825out:
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100826 /* Cycle through all hash buckets every BASE_REACHABLE_TIME/2 ticks.
827 * ARP entry timeouts range from 1/2 BASE_REACHABLE_TIME to 3/2
828 * BASE_REACHABLE_TIME.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 */
Eric Dumazete4c4e442009-07-30 03:15:07 +0000830 schedule_delayed_work(&tbl->gc_work,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100831 NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME) >> 1);
Eric Dumazete4c4e442009-07-30 03:15:07 +0000832 write_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}
834
835static __inline__ int neigh_max_probes(struct neighbour *n)
836{
837 struct neigh_parms *p = n->parms;
Eric Dumazeta02cec22010-09-22 20:43:57 +0000838 return (n->nud_state & NUD_PROBE) ?
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100839 NEIGH_VAR(p, UCAST_PROBES) :
840 NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) +
841 NEIGH_VAR(p, MCAST_PROBES);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842}
843
Timo Teras5ef12d92009-06-11 04:16:28 -0700844static void neigh_invalidate(struct neighbour *neigh)
Eric Dumazet0a141502010-03-09 19:40:54 +0000845 __releases(neigh->lock)
846 __acquires(neigh->lock)
Timo Teras5ef12d92009-06-11 04:16:28 -0700847{
848 struct sk_buff *skb;
849
850 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
Joe Perchesd5d427c2013-04-15 15:17:19 +0000851 neigh_dbg(2, "neigh %p is failed\n", neigh);
Timo Teras5ef12d92009-06-11 04:16:28 -0700852 neigh->updated = jiffies;
853
854 /* It is very thin place. report_unreachable is very complicated
855 routine. Particularly, it can hit the same neighbour entry!
856
857 So that, we try to be accurate and avoid dead loop. --ANK
858 */
859 while (neigh->nud_state == NUD_FAILED &&
860 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
861 write_unlock(&neigh->lock);
862 neigh->ops->error_report(neigh, skb);
863 write_lock(&neigh->lock);
864 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -0700865 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +0000866 neigh->arp_queue_len_bytes = 0;
Timo Teras5ef12d92009-06-11 04:16:28 -0700867}
868
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000869static void neigh_probe(struct neighbour *neigh)
870 __releases(neigh->lock)
871{
Hannes Frederic Sowa4ed377e2013-09-21 06:32:34 +0200872 struct sk_buff *skb = skb_peek_tail(&neigh->arp_queue);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000873 /* keep skb alive even if arp_queue overflows */
874 if (skb)
875 skb = skb_copy(skb, GFP_ATOMIC);
876 write_unlock(&neigh->lock);
877 neigh->ops->solicit(neigh, skb);
878 atomic_inc(&neigh->probes);
879 kfree_skb(skb);
880}
881
Linus Torvalds1da177e2005-04-16 15:20:36 -0700882/* Called when a timer expires for a neighbour entry. */
883
884static void neigh_timer_handler(unsigned long arg)
885{
886 unsigned long now, next;
887 struct neighbour *neigh = (struct neighbour *)arg;
Eric Dumazet95c96172012-04-15 05:58:06 +0000888 unsigned int state;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700889 int notify = 0;
890
891 write_lock(&neigh->lock);
892
893 state = neigh->nud_state;
894 now = jiffies;
895 next = now + HZ;
896
David S. Miller045f7b32011-11-01 17:45:55 -0400897 if (!(state & NUD_IN_TIMER))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899
900 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900901 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 neigh->confirmed + neigh->parms->reachable_time)) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000903 neigh_dbg(2, "neigh %p is still alive\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904 next = neigh->confirmed + neigh->parms->reachable_time;
905 } else if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100906 neigh->used +
907 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000908 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800910 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 neigh_suspect(neigh);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100912 next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700913 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000914 neigh_dbg(2, "neigh %p is suspected\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800916 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700917 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700918 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700919 }
920 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900921 if (time_before_eq(now,
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100922 neigh->confirmed +
923 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000924 neigh_dbg(2, "neigh %p is now reachable\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700925 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800926 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700927 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700928 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 next = neigh->confirmed + neigh->parms->reachable_time;
930 } else {
Joe Perchesd5d427c2013-04-15 15:17:19 +0000931 neigh_dbg(2, "neigh %p is probed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800933 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934 atomic_set(&neigh->probes, 0);
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100935 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 }
937 } else {
938 /* NUD_PROBE|NUD_INCOMPLETE */
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100939 next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700940 }
941
942 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
943 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700944 neigh->nud_state = NUD_FAILED;
945 notify = 1;
Timo Teras5ef12d92009-06-11 04:16:28 -0700946 neigh_invalidate(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 }
948
949 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700950 if (time_before(next, jiffies + HZ/2))
951 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000952 if (!mod_timer(&neigh->timer, next))
953 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954 }
955 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000956 neigh_probe(neigh);
David S. Miller9ff56602008-02-17 18:39:54 -0800957 } else {
David S. Miller69cc64d2008-02-11 21:45:44 -0800958out:
David S. Miller9ff56602008-02-17 18:39:54 -0800959 write_unlock(&neigh->lock);
960 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
Thomas Grafd961db32007-08-08 23:12:56 -0700962 if (notify)
963 neigh_update_notify(neigh);
964
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 neigh_release(neigh);
966}
967
968int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
969{
970 int rc;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000971 bool immediate_probe = false;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972
973 write_lock_bh(&neigh->lock);
974
975 rc = 0;
976 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
977 goto out_unlock_bh;
978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100980 if (NEIGH_VAR(neigh->parms, MCAST_PROBES) +
981 NEIGH_VAR(neigh->parms, APP_PROBES)) {
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000982 unsigned long next, now = jiffies;
983
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100984 atomic_set(&neigh->probes,
985 NEIGH_VAR(neigh->parms, UCAST_PROBES));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986 neigh->nud_state = NUD_INCOMPLETE;
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000987 neigh->updated = now;
Jiri Pirko1f9248e2013-12-07 19:26:53 +0100988 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
989 HZ/2);
Eric Dumazetcd28ca02011-08-09 08:15:58 +0000990 neigh_add_timer(neigh, next);
991 immediate_probe = true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700992 } else {
993 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800994 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 write_unlock_bh(&neigh->lock);
996
Wei Yongjunf3fbbe02009-02-25 00:37:32 +0000997 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998 return 1;
999 }
1000 } else if (neigh->nud_state & NUD_STALE) {
Joe Perchesd5d427c2013-04-15 15:17:19 +00001001 neigh_dbg(2, "neigh %p is delayed\n", neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -08001003 neigh->updated = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001004 neigh_add_timer(neigh, jiffies +
1005 NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 }
1007
1008 if (neigh->nud_state == NUD_INCOMPLETE) {
1009 if (skb) {
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001010 while (neigh->arp_queue_len_bytes + skb->truesize >
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001011 NEIGH_VAR(neigh->parms, QUEUE_LEN_BYTES)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 struct sk_buff *buff;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001013
David S. Millerf72051b2008-09-23 01:11:18 -07001014 buff = __skb_dequeue(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001015 if (!buff)
1016 break;
1017 neigh->arp_queue_len_bytes -= buff->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 kfree_skb(buff);
Neil Horman9a6d2762008-07-16 20:50:49 -07001019 NEIGH_CACHE_STAT_INC(neigh->tbl, unres_discards);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001020 }
Eric Dumazeta4731132010-05-27 16:09:39 -07001021 skb_dst_force(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 __skb_queue_tail(&neigh->arp_queue, skb);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001023 neigh->arp_queue_len_bytes += skb->truesize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 }
1025 rc = 1;
1026 }
1027out_unlock_bh:
Eric Dumazetcd28ca02011-08-09 08:15:58 +00001028 if (immediate_probe)
1029 neigh_probe(neigh);
1030 else
1031 write_unlock(&neigh->lock);
1032 local_bh_enable();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 return rc;
1034}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001035EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036
David S. Millerf6b72b62011-07-14 07:53:20 -07001037static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001038{
1039 struct hh_cache *hh;
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001040 void (*update)(struct hh_cache*, const struct net_device*, const unsigned char *)
Doug Kehn91a72a72010-07-14 18:02:16 -07001041 = NULL;
1042
1043 if (neigh->dev->header_ops)
1044 update = neigh->dev->header_ops->cache_update;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045
1046 if (update) {
David S. Millerf6b72b62011-07-14 07:53:20 -07001047 hh = &neigh->hh;
1048 if (hh->hh_len) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001049 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001051 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 }
1053 }
1054}
1055
1056
1057
1058/* Generic update routine.
1059 -- lladdr is new lladdr or NULL, if it is not supplied.
1060 -- new is new state.
1061 -- flags
1062 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
1063 if it is different.
1064 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001065 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -07001066 if it is different.
1067 It also allows to retain current state
1068 if lladdr is unchanged.
1069 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1070
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001071 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072 NTF_ROUTER flag.
1073 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
1074 a router.
1075
1076 Caller MUST hold reference count on the entry.
1077 */
1078
1079int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1080 u32 flags)
1081{
1082 u8 old;
1083 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001085 struct net_device *dev;
1086 int update_isrouter = 0;
1087
1088 write_lock_bh(&neigh->lock);
1089
1090 dev = neigh->dev;
1091 old = neigh->nud_state;
1092 err = -EPERM;
1093
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001094 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001095 (old & (NUD_NOARP | NUD_PERMANENT)))
1096 goto out;
1097
1098 if (!(new & NUD_VALID)) {
1099 neigh_del_timer(neigh);
1100 if (old & NUD_CONNECTED)
1101 neigh_suspect(neigh);
1102 neigh->nud_state = new;
1103 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001104 notify = old & NUD_VALID;
Timo Teras5ef12d92009-06-11 04:16:28 -07001105 if ((old & (NUD_INCOMPLETE | NUD_PROBE)) &&
1106 (new & NUD_FAILED)) {
1107 neigh_invalidate(neigh);
1108 notify = 1;
1109 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 goto out;
1111 }
1112
1113 /* Compare new lladdr with cached one */
1114 if (!dev->addr_len) {
1115 /* First case: device needs no address. */
1116 lladdr = neigh->ha;
1117 } else if (lladdr) {
1118 /* The second case: if something is already cached
1119 and a new address is proposed:
1120 - compare new & old
1121 - if they are different, check override flag
1122 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001123 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001124 !memcmp(lladdr, neigh->ha, dev->addr_len))
1125 lladdr = neigh->ha;
1126 } else {
1127 /* No address is supplied; if we know something,
1128 use it, otherwise discard the request.
1129 */
1130 err = -EINVAL;
1131 if (!(old & NUD_VALID))
1132 goto out;
1133 lladdr = neigh->ha;
1134 }
1135
1136 if (new & NUD_CONNECTED)
1137 neigh->confirmed = jiffies;
1138 neigh->updated = jiffies;
1139
1140 /* If entry was valid and address is not changed,
1141 do not change entry state, if new one is STALE.
1142 */
1143 err = 0;
1144 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
1145 if (old & NUD_VALID) {
1146 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1147 update_isrouter = 0;
1148 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1149 (old & NUD_CONNECTED)) {
1150 lladdr = neigh->ha;
1151 new = NUD_STALE;
1152 } else
1153 goto out;
1154 } else {
1155 if (lladdr == neigh->ha && new == NUD_STALE &&
1156 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1157 (old & NUD_CONNECTED))
1158 )
1159 new = old;
1160 }
1161 }
1162
1163 if (new != old) {
1164 neigh_del_timer(neigh);
Pavel Emelyanova43d8992007-12-20 15:49:05 -08001165 if (new & NUD_IN_TIMER)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001166 neigh_add_timer(neigh, (jiffies +
1167 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001168 neigh->parms->reachable_time :
1169 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170 neigh->nud_state = new;
1171 }
1172
1173 if (lladdr != neigh->ha) {
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001174 write_seqlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 memcpy(&neigh->ha, lladdr, dev->addr_len);
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001176 write_sequnlock(&neigh->ha_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 neigh_update_hhs(neigh);
1178 if (!(new & NUD_CONNECTED))
1179 neigh->confirmed = jiffies -
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001180 (NEIGH_VAR(neigh->parms, BASE_REACHABLE_TIME) << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 }
1183 if (new == old)
1184 goto out;
1185 if (new & NUD_CONNECTED)
1186 neigh_connect(neigh);
1187 else
1188 neigh_suspect(neigh);
1189 if (!(old & NUD_VALID)) {
1190 struct sk_buff *skb;
1191
1192 /* Again: avoid dead loop if something went wrong */
1193
1194 while (neigh->nud_state & NUD_VALID &&
1195 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
David S. Miller69cce1d2011-07-17 23:09:49 -07001196 struct dst_entry *dst = skb_dst(skb);
1197 struct neighbour *n2, *n1 = neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198 write_unlock_bh(&neigh->lock);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001199
1200 rcu_read_lock();
David S. Miller13a43d92012-07-02 22:15:37 -07001201
1202 /* Why not just use 'neigh' as-is? The problem is that
1203 * things such as shaper, eql, and sch_teql can end up
1204 * using alternative, different, neigh objects to output
1205 * the packet in the output path. So what we need to do
1206 * here is re-lookup the top-level neigh in the path so
1207 * we can reinject the packet there.
1208 */
1209 n2 = NULL;
1210 if (dst) {
1211 n2 = dst_neigh_lookup_skb(dst, skb);
1212 if (n2)
1213 n1 = n2;
1214 }
David S. Miller8f40b162011-07-17 13:34:11 -07001215 n1->output(n1, skb);
David S. Miller13a43d92012-07-02 22:15:37 -07001216 if (n2)
1217 neigh_release(n2);
roy.qing.li@gmail.come049f282011-10-17 22:32:42 +00001218 rcu_read_unlock();
1219
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220 write_lock_bh(&neigh->lock);
1221 }
Eric Dumazetc9ab4d82013-06-28 02:37:42 -07001222 __skb_queue_purge(&neigh->arp_queue);
Eric Dumazet8b5c1712011-11-09 12:07:14 +00001223 neigh->arp_queue_len_bytes = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224 }
1225out:
1226 if (update_isrouter) {
1227 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1228 (neigh->flags | NTF_ROUTER) :
1229 (neigh->flags & ~NTF_ROUTER);
1230 }
1231 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001232
1233 if (notify)
Thomas Grafd961db32007-08-08 23:12:56 -07001234 neigh_update_notify(neigh);
1235
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 return err;
1237}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001238EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001239
1240struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1241 u8 *lladdr, void *saddr,
1242 struct net_device *dev)
1243{
1244 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1245 lladdr || !dev->addr_len);
1246 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001247 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001248 NEIGH_UPDATE_F_OVERRIDE);
1249 return neigh;
1250}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001251EXPORT_SYMBOL(neigh_event_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Eric Dumazet34d101d2010-10-11 09:16:57 -07001253/* called with read_lock_bh(&n->lock); */
David S. Millerf6b72b62011-07-14 07:53:20 -07001254static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001255{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256 struct net_device *dev = dst->dev;
David S. Millerf6b72b62011-07-14 07:53:20 -07001257 __be16 prot = dst->ops->protocol;
1258 struct hh_cache *hh = &n->hh;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001259
1260 write_lock_bh(&n->lock);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001261
David S. Millerf6b72b62011-07-14 07:53:20 -07001262 /* Only one thread can come in here and initialize the
1263 * hh_cache entry.
1264 */
David S. Millerb23b5452011-07-16 17:45:02 -07001265 if (!hh->hh_len)
1266 dev->header_ops->cache(n, hh, prot);
David S. Millerf6b72b62011-07-14 07:53:20 -07001267
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001268 write_unlock_bh(&n->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269}
1270
1271/* This function can be used in contexts, where only old dev_queue_xmit
Eric Dumazet767e97e2010-10-06 17:49:21 -07001272 * worked, f.e. if you want to override normal output path (eql, shaper),
1273 * but resolution is not made yet.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274 */
1275
David S. Miller8f40b162011-07-17 13:34:11 -07001276int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277{
1278 struct net_device *dev = skb->dev;
1279
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001280 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
Stephen Hemminger0c4e8582007-10-09 01:36:32 -07001282 if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
1283 skb->len) < 0 &&
Stephen Hemminger3b04ddd2007-10-09 01:40:57 -07001284 dev->header_ops->rebuild(skb))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 return 0;
1286
1287 return dev_queue_xmit(skb);
1288}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001289EXPORT_SYMBOL(neigh_compat_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290
1291/* Slow and careful. */
1292
David S. Miller8f40b162011-07-17 13:34:11 -07001293int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001294{
Eric Dumazetadf30902009-06-02 05:19:30 +00001295 struct dst_entry *dst = skb_dst(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296 int rc = 0;
1297
David S. Miller8f40b162011-07-17 13:34:11 -07001298 if (!dst)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 goto discard;
1300
Linus Torvalds1da177e2005-04-16 15:20:36 -07001301 if (!neigh_event_send(neigh, skb)) {
1302 int err;
1303 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001304 unsigned int seq;
Eric Dumazet34d101d2010-10-11 09:16:57 -07001305
David S. Millerf6b72b62011-07-14 07:53:20 -07001306 if (dev->header_ops->cache && !neigh->hh.hh_len)
1307 neigh_hh_init(neigh, dst);
Eric Dumazet34d101d2010-10-11 09:16:57 -07001308
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001309 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001310 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001311 seq = read_seqbegin(&neigh->ha_lock);
1312 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1313 neigh->ha, NULL, skb->len);
1314 } while (read_seqretry(&neigh->ha_lock, seq));
Eric Dumazet34d101d2010-10-11 09:16:57 -07001315
Linus Torvalds1da177e2005-04-16 15:20:36 -07001316 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001317 rc = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 else
1319 goto out_kfree_skb;
1320 }
1321out:
1322 return rc;
1323discard:
Joe Perchesd5d427c2013-04-15 15:17:19 +00001324 neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325out_kfree_skb:
1326 rc = -EINVAL;
1327 kfree_skb(skb);
1328 goto out;
1329}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001330EXPORT_SYMBOL(neigh_resolve_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001331
1332/* As fast as possible without hh cache */
1333
David S. Miller8f40b162011-07-17 13:34:11 -07001334int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001336 struct net_device *dev = neigh->dev;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001337 unsigned int seq;
David S. Miller8f40b162011-07-17 13:34:11 -07001338 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001339
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001340 do {
ramesh.nagappa@gmail.come1f16502012-10-05 19:10:15 +00001341 __skb_pull(skb, skb_network_offset(skb));
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00001342 seq = read_seqbegin(&neigh->ha_lock);
1343 err = dev_hard_header(skb, dev, ntohs(skb->protocol),
1344 neigh->ha, NULL, skb->len);
1345 } while (read_seqretry(&neigh->ha_lock, seq));
1346
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347 if (err >= 0)
David S. Miller542d4d62011-07-16 18:06:24 -07001348 err = dev_queue_xmit(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349 else {
1350 err = -EINVAL;
1351 kfree_skb(skb);
1352 }
1353 return err;
1354}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001355EXPORT_SYMBOL(neigh_connected_output);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001356
David S. Miller8f40b162011-07-17 13:34:11 -07001357int neigh_direct_output(struct neighbour *neigh, struct sk_buff *skb)
1358{
1359 return dev_queue_xmit(skb);
1360}
1361EXPORT_SYMBOL(neigh_direct_output);
1362
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363static void neigh_proxy_process(unsigned long arg)
1364{
1365 struct neigh_table *tbl = (struct neigh_table *)arg;
1366 long sched_next = 0;
1367 unsigned long now = jiffies;
David S. Millerf72051b2008-09-23 01:11:18 -07001368 struct sk_buff *skb, *n;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001369
1370 spin_lock(&tbl->proxy_queue.lock);
1371
David S. Millerf72051b2008-09-23 01:11:18 -07001372 skb_queue_walk_safe(&tbl->proxy_queue, skb, n) {
1373 long tdif = NEIGH_CB(skb)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 if (tdif <= 0) {
David S. Millerf72051b2008-09-23 01:11:18 -07001376 struct net_device *dev = skb->dev;
Eric Dumazet20e60742011-08-22 19:32:42 +00001377
David S. Millerf72051b2008-09-23 01:11:18 -07001378 __skb_unlink(skb, &tbl->proxy_queue);
Eric Dumazet20e60742011-08-22 19:32:42 +00001379 if (tbl->proxy_redo && netif_running(dev)) {
1380 rcu_read_lock();
David S. Millerf72051b2008-09-23 01:11:18 -07001381 tbl->proxy_redo(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001382 rcu_read_unlock();
1383 } else {
David S. Millerf72051b2008-09-23 01:11:18 -07001384 kfree_skb(skb);
Eric Dumazet20e60742011-08-22 19:32:42 +00001385 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386
1387 dev_put(dev);
1388 } else if (!sched_next || tdif < sched_next)
1389 sched_next = tdif;
1390 }
1391 del_timer(&tbl->proxy_timer);
1392 if (sched_next)
1393 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1394 spin_unlock(&tbl->proxy_queue.lock);
1395}
1396
1397void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1398 struct sk_buff *skb)
1399{
1400 unsigned long now = jiffies;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001401 unsigned long sched_next = now + (net_random() %
1402 NEIGH_VAR(p, PROXY_DELAY));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001404 if (tbl->proxy_queue.qlen > NEIGH_VAR(p, PROXY_QLEN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001405 kfree_skb(skb);
1406 return;
1407 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001408
1409 NEIGH_CB(skb)->sched_next = sched_next;
1410 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001411
1412 spin_lock(&tbl->proxy_queue.lock);
1413 if (del_timer(&tbl->proxy_timer)) {
1414 if (time_before(tbl->proxy_timer.expires, sched_next))
1415 sched_next = tbl->proxy_timer.expires;
1416 }
Eric Dumazetadf30902009-06-02 05:19:30 +00001417 skb_dst_drop(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 dev_hold(skb->dev);
1419 __skb_queue_tail(&tbl->proxy_queue, skb);
1420 mod_timer(&tbl->proxy_timer, sched_next);
1421 spin_unlock(&tbl->proxy_queue.lock);
1422}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001423EXPORT_SYMBOL(pneigh_enqueue);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07001425static inline struct neigh_parms *lookup_neigh_parms(struct neigh_table *tbl,
Eric W. Biederman426b5302008-01-24 00:13:18 -08001426 struct net *net, int ifindex)
1427{
1428 struct neigh_parms *p;
1429
1430 for (p = &tbl->parms; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09001431 if ((p->dev && p->dev->ifindex == ifindex && net_eq(neigh_parms_net(p), net)) ||
Gao feng170d6f92013-06-20 10:01:33 +08001432 (!p->dev && !ifindex && net_eq(net, &init_net)))
Eric W. Biederman426b5302008-01-24 00:13:18 -08001433 return p;
1434 }
1435
1436 return NULL;
1437}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001438
1439struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1440 struct neigh_table *tbl)
1441{
Gao fengcf89d6b2013-06-20 10:01:32 +08001442 struct neigh_parms *p;
Stephen Hemminger00829822008-11-20 20:14:53 -08001443 struct net *net = dev_net(dev);
1444 const struct net_device_ops *ops = dev->netdev_ops;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
Gao fengcf89d6b2013-06-20 10:01:32 +08001446 p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448 p->tbl = tbl;
1449 atomic_set(&p->refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 p->reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001451 neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
Denis V. Lunev486b51d2008-01-14 22:59:59 -08001452 dev_hold(dev);
1453 p->dev = dev;
Eric Dumazete42ea982008-11-12 00:54:54 -08001454 write_pnet(&p->net, hold_net(net));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455 p->sysctl_table = NULL;
Veaceslav Falico63134802013-08-02 19:07:38 +02001456
1457 if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
1458 release_net(net);
1459 dev_put(dev);
1460 kfree(p);
1461 return NULL;
1462 }
1463
Linus Torvalds1da177e2005-04-16 15:20:36 -07001464 write_lock_bh(&tbl->lock);
1465 p->next = tbl->parms.next;
1466 tbl->parms.next = p;
1467 write_unlock_bh(&tbl->lock);
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01001468
1469 neigh_parms_data_state_cleanall(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001470 }
1471 return p;
1472}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001473EXPORT_SYMBOL(neigh_parms_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475static void neigh_rcu_free_parms(struct rcu_head *head)
1476{
1477 struct neigh_parms *parms =
1478 container_of(head, struct neigh_parms, rcu_head);
1479
1480 neigh_parms_put(parms);
1481}
1482
1483void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1484{
1485 struct neigh_parms **p;
1486
1487 if (!parms || parms == &tbl->parms)
1488 return;
1489 write_lock_bh(&tbl->lock);
1490 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1491 if (*p == parms) {
1492 *p = parms->next;
1493 parms->dead = 1;
1494 write_unlock_bh(&tbl->lock);
David S. Millercecbb632008-01-20 16:39:03 -08001495 if (parms->dev)
1496 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1498 return;
1499 }
1500 }
1501 write_unlock_bh(&tbl->lock);
Joe Perchesd5d427c2013-04-15 15:17:19 +00001502 neigh_dbg(1, "%s: not found\n", __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001504EXPORT_SYMBOL(neigh_parms_release);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505
Denis V. Lunev06f05112008-01-24 00:30:58 -08001506static void neigh_parms_destroy(struct neigh_parms *parms)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001507{
YOSHIFUJI Hideaki57da52c2008-03-26 03:49:59 +09001508 release_net(neigh_parms_net(parms));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001509 kfree(parms);
1510}
1511
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001512static struct lock_class_key neigh_table_proxy_queue_class;
1513
Hiroaki SHIMODAdcd2ba92012-04-13 07:34:44 +00001514static void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
1516 unsigned long now = jiffies;
1517 unsigned long phsize;
1518
Eric Dumazete42ea982008-11-12 00:54:54 -08001519 write_pnet(&tbl->parms.net, &init_net);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001520 atomic_set(&tbl->parms.refcnt, 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 tbl->parms.reachable_time =
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001522 neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 tbl->stats = alloc_percpu(struct neigh_statistics);
1525 if (!tbl->stats)
1526 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001527
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528#ifdef CONFIG_PROC_FS
Alexey Dobriyan9b739ba2008-11-11 16:47:44 -08001529 if (!proc_create_data(tbl->id, 0, init_net.proc_net_stat,
1530 &neigh_stat_seq_fops, tbl))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001531 panic("cannot create neighbour proc dir entry");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532#endif
1533
David S. Millercd089332011-07-11 01:28:12 -07001534 RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc(3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535
1536 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001537 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001539 if (!tbl->nht || !tbl->phash_buckets)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 panic("cannot allocate neighbour cache hashes");
1541
YOSHIFUJI Hideaki / 吉藤英明08433ef2013-01-24 00:44:23 +00001542 if (!tbl->entry_size)
1543 tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
1544 tbl->key_len, NEIGH_PRIV_ALIGN);
1545 else
1546 WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN);
1547
Linus Torvalds1da177e2005-04-16 15:20:36 -07001548 rwlock_init(&tbl->lock);
Tejun Heo203b42f2012-08-21 13:18:23 -07001549 INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
Eric Dumazete4c4e442009-07-30 03:15:07 +00001550 schedule_delayed_work(&tbl->gc_work, tbl->parms.reachable_time);
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001551 setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001552 skb_queue_head_init_class(&tbl->proxy_queue,
1553 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 tbl->last_flush = now;
1556 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001557}
1558
1559void neigh_table_init(struct neigh_table *tbl)
1560{
1561 struct neigh_table *tmp;
1562
1563 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001565 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1566 if (tmp->family == tbl->family)
1567 break;
1568 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569 tbl->next = neigh_tables;
1570 neigh_tables = tbl;
1571 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001572
1573 if (unlikely(tmp)) {
Joe Perchese005d192012-05-16 19:58:40 +00001574 pr_err("Registering multiple tables for family %d\n",
1575 tbl->family);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001576 dump_stack();
1577 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001579EXPORT_SYMBOL(neigh_table_init);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
1581int neigh_table_clear(struct neigh_table *tbl)
1582{
1583 struct neigh_table **tp;
1584
1585 /* It is not clean... Fix it to unload IPv6 module safely */
Tejun Heoa5c30b32010-10-19 06:04:42 +00001586 cancel_delayed_work_sync(&tbl->gc_work);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001587 del_timer_sync(&tbl->proxy_timer);
1588 pneigh_queue_purge(&tbl->proxy_queue);
1589 neigh_ifdown(tbl, NULL);
1590 if (atomic_read(&tbl->entries))
Joe Perchese005d192012-05-16 19:58:40 +00001591 pr_crit("neighbour leakage\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001592 write_lock(&neigh_tbl_lock);
1593 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1594 if (*tp == tbl) {
1595 *tp = tbl->next;
1596 break;
1597 }
1598 }
1599 write_unlock(&neigh_tbl_lock);
1600
Eric Dumazet6193d2b2011-01-19 22:02:47 +00001601 call_rcu(&rcu_dereference_protected(tbl->nht, 1)->rcu,
1602 neigh_hash_free_rcu);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001603 tbl->nht = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001604
1605 kfree(tbl->phash_buckets);
1606 tbl->phash_buckets = NULL;
1607
Alexey Dobriyan3f192b52007-11-05 21:28:13 -08001608 remove_proc_entry(tbl->id, init_net.proc_net_stat);
1609
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001610 free_percpu(tbl->stats);
1611 tbl->stats = NULL;
1612
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613 return 0;
1614}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09001615EXPORT_SYMBOL(neigh_table_clear);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
Thomas Graf661d2962013-03-21 07:45:29 +00001617static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001619 struct net *net = sock_net(skb->sk);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001620 struct ndmsg *ndm;
1621 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001622 struct neigh_table *tbl;
1623 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001624 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001625
Eric Dumazet110b2492010-10-04 04:27:36 +00001626 ASSERT_RTNL();
Thomas Grafa14a49d2006-08-07 17:53:08 -07001627 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001628 goto out;
1629
Thomas Grafa14a49d2006-08-07 17:53:08 -07001630 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1631 if (dst_attr == NULL)
1632 goto out;
1633
1634 ndm = nlmsg_data(nlh);
1635 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001636 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001637 if (dev == NULL) {
1638 err = -ENODEV;
1639 goto out;
1640 }
1641 }
1642
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 read_lock(&neigh_tbl_lock);
1644 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001645 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001646
1647 if (tbl->family != ndm->ndm_family)
1648 continue;
1649 read_unlock(&neigh_tbl_lock);
1650
Thomas Grafa14a49d2006-08-07 17:53:08 -07001651 if (nla_len(dst_attr) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001652 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653
1654 if (ndm->ndm_flags & NTF_PROXY) {
Eric W. Biederman426b5302008-01-24 00:13:18 -08001655 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
Eric Dumazet110b2492010-10-04 04:27:36 +00001656 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 }
1658
Thomas Grafa14a49d2006-08-07 17:53:08 -07001659 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001660 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001661
Thomas Grafa14a49d2006-08-07 17:53:08 -07001662 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1663 if (neigh == NULL) {
1664 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001665 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001666 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001667
1668 err = neigh_update(neigh, NULL, NUD_FAILED,
1669 NEIGH_UPDATE_F_OVERRIDE |
1670 NEIGH_UPDATE_F_ADMIN);
1671 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001672 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001673 }
1674 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001675 err = -EAFNOSUPPORT;
1676
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677out:
1678 return err;
1679}
1680
Thomas Graf661d2962013-03-21 07:45:29 +00001681static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001683 struct net *net = sock_net(skb->sk);
Thomas Graf5208deb2006-08-07 17:55:40 -07001684 struct ndmsg *ndm;
1685 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686 struct neigh_table *tbl;
1687 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001688 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001689
Eric Dumazet110b2492010-10-04 04:27:36 +00001690 ASSERT_RTNL();
Thomas Graf5208deb2006-08-07 17:55:40 -07001691 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1692 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 goto out;
1694
Thomas Graf5208deb2006-08-07 17:55:40 -07001695 err = -EINVAL;
1696 if (tb[NDA_DST] == NULL)
1697 goto out;
1698
1699 ndm = nlmsg_data(nlh);
1700 if (ndm->ndm_ifindex) {
Eric Dumazet110b2492010-10-04 04:27:36 +00001701 dev = __dev_get_by_index(net, ndm->ndm_ifindex);
Thomas Graf5208deb2006-08-07 17:55:40 -07001702 if (dev == NULL) {
1703 err = -ENODEV;
1704 goto out;
1705 }
1706
1707 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001708 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001709 }
1710
Linus Torvalds1da177e2005-04-16 15:20:36 -07001711 read_lock(&neigh_tbl_lock);
1712 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001713 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1714 struct neighbour *neigh;
1715 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001716
1717 if (tbl->family != ndm->ndm_family)
1718 continue;
1719 read_unlock(&neigh_tbl_lock);
1720
Thomas Graf5208deb2006-08-07 17:55:40 -07001721 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Eric Dumazet110b2492010-10-04 04:27:36 +00001722 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001723 dst = nla_data(tb[NDA_DST]);
1724 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001725
1726 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001727 struct pneigh_entry *pn;
1728
1729 err = -ENOBUFS;
Eric W. Biederman426b5302008-01-24 00:13:18 -08001730 pn = pneigh_lookup(tbl, net, dst, dev, 1);
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001731 if (pn) {
1732 pn->flags = ndm->ndm_flags;
1733 err = 0;
1734 }
Eric Dumazet110b2492010-10-04 04:27:36 +00001735 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736 }
1737
Thomas Graf5208deb2006-08-07 17:55:40 -07001738 if (dev == NULL)
Eric Dumazet110b2492010-10-04 04:27:36 +00001739 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001740
1741 neigh = neigh_lookup(tbl, dst, dev);
1742 if (neigh == NULL) {
1743 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1744 err = -ENOENT;
Eric Dumazet110b2492010-10-04 04:27:36 +00001745 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001746 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001747
Thomas Graf5208deb2006-08-07 17:55:40 -07001748 neigh = __neigh_lookup_errno(tbl, dst, dev);
1749 if (IS_ERR(neigh)) {
1750 err = PTR_ERR(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001751 goto out;
Thomas Graf5208deb2006-08-07 17:55:40 -07001752 }
1753 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1755 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001756 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001757 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001759
1760 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1761 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001762 }
1763
Eric Biederman0c5c2d32009-03-04 00:03:08 -08001764 if (ndm->ndm_flags & NTF_USE) {
1765 neigh_event_send(neigh, NULL);
1766 err = 0;
1767 } else
1768 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
Thomas Graf5208deb2006-08-07 17:55:40 -07001769 neigh_release(neigh);
Eric Dumazet110b2492010-10-04 04:27:36 +00001770 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771 }
1772
1773 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001774 err = -EAFNOSUPPORT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001775out:
1776 return err;
1777}
1778
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001779static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1780{
Thomas Grafca860fb2006-08-07 18:00:18 -07001781 struct nlattr *nest;
1782
1783 nest = nla_nest_start(skb, NDTA_PARMS);
1784 if (nest == NULL)
1785 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001786
David S. Miller9a6308d2012-04-01 20:06:28 -04001787 if ((parms->dev &&
1788 nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
1789 nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001790 nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
1791 NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001792 /* approximative value for deprecated QUEUE_LEN (in packets) */
1793 nla_put_u32(skb, NDTPA_QUEUE_LEN,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001794 NEIGH_VAR(parms, QUEUE_LEN_BYTES) / SKB_TRUESIZE(ETH_FRAME_LEN)) ||
1795 nla_put_u32(skb, NDTPA_PROXY_QLEN, NEIGH_VAR(parms, PROXY_QLEN)) ||
1796 nla_put_u32(skb, NDTPA_APP_PROBES, NEIGH_VAR(parms, APP_PROBES)) ||
1797 nla_put_u32(skb, NDTPA_UCAST_PROBES,
1798 NEIGH_VAR(parms, UCAST_PROBES)) ||
1799 nla_put_u32(skb, NDTPA_MCAST_PROBES,
1800 NEIGH_VAR(parms, MCAST_PROBES)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001801 nla_put_msecs(skb, NDTPA_REACHABLE_TIME, parms->reachable_time) ||
1802 nla_put_msecs(skb, NDTPA_BASE_REACHABLE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001803 NEIGH_VAR(parms, BASE_REACHABLE_TIME)) ||
1804 nla_put_msecs(skb, NDTPA_GC_STALETIME,
1805 NEIGH_VAR(parms, GC_STALETIME)) ||
David S. Miller9a6308d2012-04-01 20:06:28 -04001806 nla_put_msecs(skb, NDTPA_DELAY_PROBE_TIME,
Jiri Pirko1f9248e2013-12-07 19:26:53 +01001807 NEIGH_VAR(parms, DELAY_PROBE_TIME)) ||
1808 nla_put_msecs(skb, NDTPA_RETRANS_TIME,
1809 NEIGH_VAR(parms, RETRANS_TIME)) ||
1810 nla_put_msecs(skb, NDTPA_ANYCAST_DELAY,
1811 NEIGH_VAR(parms, ANYCAST_DELAY)) ||
1812 nla_put_msecs(skb, NDTPA_PROXY_DELAY,
1813 NEIGH_VAR(parms, PROXY_DELAY)) ||
1814 nla_put_msecs(skb, NDTPA_LOCKTIME,
1815 NEIGH_VAR(parms, LOCKTIME)))
David S. Miller9a6308d2012-04-01 20:06:28 -04001816 goto nla_put_failure;
Thomas Grafca860fb2006-08-07 18:00:18 -07001817 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001818
Thomas Grafca860fb2006-08-07 18:00:18 -07001819nla_put_failure:
Thomas Grafbc3ed282008-06-03 16:36:54 -07001820 nla_nest_cancel(skb, nest);
1821 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001822}
1823
Thomas Grafca860fb2006-08-07 18:00:18 -07001824static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1825 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001826{
1827 struct nlmsghdr *nlh;
1828 struct ndtmsg *ndtmsg;
1829
Thomas Grafca860fb2006-08-07 18:00:18 -07001830 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1831 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001832 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001833
Thomas Grafca860fb2006-08-07 18:00:18 -07001834 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001835
1836 read_lock_bh(&tbl->lock);
1837 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001838 ndtmsg->ndtm_pad1 = 0;
1839 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001840
David S. Miller9a6308d2012-04-01 20:06:28 -04001841 if (nla_put_string(skb, NDTA_NAME, tbl->id) ||
1842 nla_put_msecs(skb, NDTA_GC_INTERVAL, tbl->gc_interval) ||
1843 nla_put_u32(skb, NDTA_THRESH1, tbl->gc_thresh1) ||
1844 nla_put_u32(skb, NDTA_THRESH2, tbl->gc_thresh2) ||
1845 nla_put_u32(skb, NDTA_THRESH3, tbl->gc_thresh3))
1846 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001847 {
1848 unsigned long now = jiffies;
1849 unsigned int flush_delta = now - tbl->last_flush;
1850 unsigned int rand_delta = now - tbl->last_rand;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001851 struct neigh_hash_table *nht;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852 struct ndt_config ndc = {
1853 .ndtc_key_len = tbl->key_len,
1854 .ndtc_entry_size = tbl->entry_size,
1855 .ndtc_entries = atomic_read(&tbl->entries),
1856 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1857 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001858 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1859 };
1860
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001861 rcu_read_lock_bh();
1862 nht = rcu_dereference_bh(tbl->nht);
David S. Miller2c2aba62011-12-28 15:06:58 -05001863 ndc.ndtc_hash_rnd = nht->hash_rnd[0];
David S. Millercd089332011-07-11 01:28:12 -07001864 ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00001865 rcu_read_unlock_bh();
1866
David S. Miller9a6308d2012-04-01 20:06:28 -04001867 if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc))
1868 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001869 }
1870
1871 {
1872 int cpu;
1873 struct ndt_stats ndst;
1874
1875 memset(&ndst, 0, sizeof(ndst));
1876
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001877 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001878 struct neigh_statistics *st;
1879
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001880 st = per_cpu_ptr(tbl->stats, cpu);
1881 ndst.ndts_allocs += st->allocs;
1882 ndst.ndts_destroys += st->destroys;
1883 ndst.ndts_hash_grows += st->hash_grows;
1884 ndst.ndts_res_failed += st->res_failed;
1885 ndst.ndts_lookups += st->lookups;
1886 ndst.ndts_hits += st->hits;
1887 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1888 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1889 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1890 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1891 }
1892
David S. Miller9a6308d2012-04-01 20:06:28 -04001893 if (nla_put(skb, NDTA_STATS, sizeof(ndst), &ndst))
1894 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001895 }
1896
1897 BUG_ON(tbl->parms.dev);
1898 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001899 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001900
1901 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001902 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001903
Thomas Grafca860fb2006-08-07 18:00:18 -07001904nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001905 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001906 nlmsg_cancel(skb, nlh);
1907 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001908}
1909
Thomas Grafca860fb2006-08-07 18:00:18 -07001910static int neightbl_fill_param_info(struct sk_buff *skb,
1911 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001912 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001913 u32 pid, u32 seq, int type,
1914 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001915{
1916 struct ndtmsg *ndtmsg;
1917 struct nlmsghdr *nlh;
1918
Thomas Grafca860fb2006-08-07 18:00:18 -07001919 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1920 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001921 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001922
Thomas Grafca860fb2006-08-07 18:00:18 -07001923 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001924
1925 read_lock_bh(&tbl->lock);
1926 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001927 ndtmsg->ndtm_pad1 = 0;
1928 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001929
Thomas Grafca860fb2006-08-07 18:00:18 -07001930 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1931 neightbl_fill_parms(skb, parms) < 0)
1932 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001933
1934 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001935 return nlmsg_end(skb, nlh);
1936errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001937 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001938 nlmsg_cancel(skb, nlh);
1939 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001940}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001941
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001942static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001943 [NDTA_NAME] = { .type = NLA_STRING },
1944 [NDTA_THRESH1] = { .type = NLA_U32 },
1945 [NDTA_THRESH2] = { .type = NLA_U32 },
1946 [NDTA_THRESH3] = { .type = NLA_U32 },
1947 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1948 [NDTA_PARMS] = { .type = NLA_NESTED },
1949};
1950
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001951static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001952 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1953 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1954 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1955 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1956 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1957 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1958 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1959 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1960 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1961 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1962 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1963 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1964 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1965};
1966
Thomas Graf661d2962013-03-21 07:45:29 +00001967static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001968{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09001969 struct net *net = sock_net(skb->sk);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001970 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001971 struct ndtmsg *ndtmsg;
1972 struct nlattr *tb[NDTA_MAX+1];
1973 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001974
Thomas Graf6b3f8672006-08-07 17:58:53 -07001975 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1976 nl_neightbl_policy);
1977 if (err < 0)
1978 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001979
Thomas Graf6b3f8672006-08-07 17:58:53 -07001980 if (tb[NDTA_NAME] == NULL) {
1981 err = -EINVAL;
1982 goto errout;
1983 }
1984
1985 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001986 read_lock(&neigh_tbl_lock);
1987 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1988 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1989 continue;
1990
Thomas Graf6b3f8672006-08-07 17:58:53 -07001991 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001992 break;
1993 }
1994
1995 if (tbl == NULL) {
1996 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001997 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001998 }
1999
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002000 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002001 * We acquire tbl->lock to be nice to the periodic timers and
2002 * make sure they always see a consistent set of values.
2003 */
2004 write_lock_bh(&tbl->lock);
2005
Thomas Graf6b3f8672006-08-07 17:58:53 -07002006 if (tb[NDTA_PARMS]) {
2007 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002008 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002009 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002010
Thomas Graf6b3f8672006-08-07 17:58:53 -07002011 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2012 nl_ntbl_parm_policy);
2013 if (err < 0)
2014 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002015
Thomas Graf6b3f8672006-08-07 17:58:53 -07002016 if (tbp[NDTPA_IFINDEX])
2017 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002018
Tobias Klauser97fd5bc2009-07-13 11:17:49 -07002019 p = lookup_neigh_parms(tbl, net, ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002020 if (p == NULL) {
2021 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07002022 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002023 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002024
Thomas Graf6b3f8672006-08-07 17:58:53 -07002025 for (i = 1; i <= NDTPA_MAX; i++) {
2026 if (tbp[i] == NULL)
2027 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002028
Thomas Graf6b3f8672006-08-07 17:58:53 -07002029 switch (i) {
2030 case NDTPA_QUEUE_LEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002031 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2032 nla_get_u32(tbp[i]) *
2033 SKB_TRUESIZE(ETH_FRAME_LEN));
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002034 break;
2035 case NDTPA_QUEUE_LENBYTES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002036 NEIGH_VAR_SET(p, QUEUE_LEN_BYTES,
2037 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002038 break;
2039 case NDTPA_PROXY_QLEN:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002040 NEIGH_VAR_SET(p, PROXY_QLEN,
2041 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002042 break;
2043 case NDTPA_APP_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002044 NEIGH_VAR_SET(p, APP_PROBES,
2045 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002046 break;
2047 case NDTPA_UCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002048 NEIGH_VAR_SET(p, UCAST_PROBES,
2049 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002050 break;
2051 case NDTPA_MCAST_PROBES:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002052 NEIGH_VAR_SET(p, MCAST_PROBES,
2053 nla_get_u32(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002054 break;
2055 case NDTPA_BASE_REACHABLE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002056 NEIGH_VAR_SET(p, BASE_REACHABLE_TIME,
2057 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002058 break;
2059 case NDTPA_GC_STALETIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002060 NEIGH_VAR_SET(p, GC_STALETIME,
2061 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002062 break;
2063 case NDTPA_DELAY_PROBE_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002064 NEIGH_VAR_SET(p, DELAY_PROBE_TIME,
2065 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002066 break;
2067 case NDTPA_RETRANS_TIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002068 NEIGH_VAR_SET(p, RETRANS_TIME,
2069 nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002070 break;
2071 case NDTPA_ANYCAST_DELAY:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002072 NEIGH_VAR_SET(p, ANYCAST_DELAY, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002073 break;
2074 case NDTPA_PROXY_DELAY:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002075 NEIGH_VAR_SET(p, PROXY_DELAY, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002076 break;
2077 case NDTPA_LOCKTIME:
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002078 NEIGH_VAR_SET(p, LOCKTIME, nla_get_msecs(tbp[i]));
Thomas Graf6b3f8672006-08-07 17:58:53 -07002079 break;
2080 }
2081 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002082 }
2083
Gao fengdc25c672013-06-20 10:01:34 +08002084 err = -ENOENT;
2085 if ((tb[NDTA_THRESH1] || tb[NDTA_THRESH2] ||
2086 tb[NDTA_THRESH3] || tb[NDTA_GC_INTERVAL]) &&
2087 !net_eq(net, &init_net))
2088 goto errout_tbl_lock;
2089
Thomas Graf6b3f8672006-08-07 17:58:53 -07002090 if (tb[NDTA_THRESH1])
2091 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
2092
2093 if (tb[NDTA_THRESH2])
2094 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
2095
2096 if (tb[NDTA_THRESH3])
2097 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
2098
2099 if (tb[NDTA_GC_INTERVAL])
2100 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
2101
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002102 err = 0;
2103
Thomas Graf6b3f8672006-08-07 17:58:53 -07002104errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002105 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002106errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002107 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07002108errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002109 return err;
2110}
2111
Thomas Grafc8822a42007-03-22 11:50:06 -07002112static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002113{
YOSHIFUJI Hideaki3b1e0a62008-03-26 02:26:21 +09002114 struct net *net = sock_net(skb->sk);
Thomas Grafca860fb2006-08-07 18:00:18 -07002115 int family, tidx, nidx = 0;
2116 int tbl_skip = cb->args[0];
2117 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002118 struct neigh_table *tbl;
2119
Thomas Grafca860fb2006-08-07 18:00:18 -07002120 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002121
2122 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002123 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002124 struct neigh_parms *p;
2125
Thomas Grafca860fb2006-08-07 18:00:18 -07002126 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002127 continue;
2128
Eric W. Biederman15e47302012-09-07 20:12:54 +00002129 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002130 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2131 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002132 break;
2133
Eric W. Biederman426b5302008-01-24 00:13:18 -08002134 for (nidx = 0, p = tbl->parms.next; p; p = p->next) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002135 if (!net_eq(neigh_parms_net(p), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002136 continue;
2137
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002138 if (nidx < neigh_skip)
2139 goto next;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002140
Thomas Grafca860fb2006-08-07 18:00:18 -07002141 if (neightbl_fill_param_info(skb, tbl, p,
Eric W. Biederman15e47302012-09-07 20:12:54 +00002142 NETLINK_CB(cb->skb).portid,
Thomas Grafca860fb2006-08-07 18:00:18 -07002143 cb->nlh->nlmsg_seq,
2144 RTM_NEWNEIGHTBL,
2145 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002146 goto out;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002147 next:
2148 nidx++;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002149 }
2150
Thomas Grafca860fb2006-08-07 18:00:18 -07002151 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002152 }
2153out:
2154 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07002155 cb->args[0] = tidx;
2156 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07002157
2158 return skb->len;
2159}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160
Thomas Graf8b8aec52006-08-07 17:56:37 -07002161static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
2162 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002163{
2164 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002166 struct nlmsghdr *nlh;
2167 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168
Thomas Graf8b8aec52006-08-07 17:56:37 -07002169 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2170 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08002171 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002172
2173 ndm = nlmsg_data(nlh);
2174 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07002175 ndm->ndm_pad1 = 0;
2176 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002177 ndm->ndm_flags = neigh->flags;
2178 ndm->ndm_type = neigh->type;
2179 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
David S. Miller9a6308d2012-04-01 20:06:28 -04002181 if (nla_put(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key))
2182 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002183
2184 read_lock_bh(&neigh->lock);
2185 ndm->ndm_state = neigh->nud_state;
Eric Dumazet0ed8ddf2010-10-07 10:44:07 +00002186 if (neigh->nud_state & NUD_VALID) {
2187 char haddr[MAX_ADDR_LEN];
2188
2189 neigh_ha_snapshot(haddr, neigh, neigh->dev);
2190 if (nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, haddr) < 0) {
2191 read_unlock_bh(&neigh->lock);
2192 goto nla_put_failure;
2193 }
Thomas Graf8b8aec52006-08-07 17:56:37 -07002194 }
2195
Stephen Hemmingerb9f5f522008-06-03 16:03:15 -07002196 ci.ndm_used = jiffies_to_clock_t(now - neigh->used);
2197 ci.ndm_confirmed = jiffies_to_clock_t(now - neigh->confirmed);
2198 ci.ndm_updated = jiffies_to_clock_t(now - neigh->updated);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002199 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
2200 read_unlock_bh(&neigh->lock);
2201
David S. Miller9a6308d2012-04-01 20:06:28 -04002202 if (nla_put_u32(skb, NDA_PROBES, atomic_read(&neigh->probes)) ||
2203 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
2204 goto nla_put_failure;
Thomas Graf8b8aec52006-08-07 17:56:37 -07002205
2206 return nlmsg_end(skb, nlh);
2207
2208nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002209 nlmsg_cancel(skb, nlh);
2210 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211}
2212
Tony Zelenoff84920c12012-01-26 22:28:58 +00002213static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
2214 u32 pid, u32 seq, int type, unsigned int flags,
2215 struct neigh_table *tbl)
2216{
2217 struct nlmsghdr *nlh;
2218 struct ndmsg *ndm;
2219
2220 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
2221 if (nlh == NULL)
2222 return -EMSGSIZE;
2223
2224 ndm = nlmsg_data(nlh);
2225 ndm->ndm_family = tbl->family;
2226 ndm->ndm_pad1 = 0;
2227 ndm->ndm_pad2 = 0;
2228 ndm->ndm_flags = pn->flags | NTF_PROXY;
2229 ndm->ndm_type = NDA_DST;
2230 ndm->ndm_ifindex = pn->dev->ifindex;
2231 ndm->ndm_state = NUD_NONE;
2232
David S. Miller9a6308d2012-04-01 20:06:28 -04002233 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
2234 goto nla_put_failure;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002235
2236 return nlmsg_end(skb, nlh);
2237
2238nla_put_failure:
2239 nlmsg_cancel(skb, nlh);
2240 return -EMSGSIZE;
2241}
2242
Thomas Grafd961db32007-08-08 23:12:56 -07002243static void neigh_update_notify(struct neighbour *neigh)
2244{
2245 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
2246 __neigh_notify(neigh, RTM_NEWNEIGH, 0);
2247}
Linus Torvalds1da177e2005-04-16 15:20:36 -07002248
2249static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2250 struct netlink_callback *cb)
2251{
Eric Dumazet767e97e2010-10-06 17:49:21 -07002252 struct net *net = sock_net(skb->sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253 struct neighbour *n;
2254 int rc, h, s_h = cb->args[1];
2255 int idx, s_idx = idx = cb->args[2];
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002256 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002258 rcu_read_lock_bh();
2259 nht = rcu_dereference_bh(tbl->nht);
2260
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002261 for (h = s_h; h < (1 << nht->hash_shift); h++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002262 if (h > s_h)
2263 s_idx = 0;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002264 for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0;
2265 n != NULL;
2266 n = rcu_dereference_bh(n->next)) {
Octavian Purdila09ad9bc2009-11-25 15:14:13 -08002267 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002268 continue;
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002269 if (idx < s_idx)
2270 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002271 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002272 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002273 RTM_NEWNEIGH,
2274 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002275 rc = -1;
2276 goto out;
2277 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002278next:
Gautam Kachrooefc683f2009-02-06 00:52:04 -08002279 idx++;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002281 }
2282 rc = skb->len;
2283out:
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002284 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 cb->args[1] = h;
2286 cb->args[2] = idx;
2287 return rc;
2288}
2289
Tony Zelenoff84920c12012-01-26 22:28:58 +00002290static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2291 struct netlink_callback *cb)
2292{
2293 struct pneigh_entry *n;
2294 struct net *net = sock_net(skb->sk);
2295 int rc, h, s_h = cb->args[3];
2296 int idx, s_idx = idx = cb->args[4];
2297
2298 read_lock_bh(&tbl->lock);
2299
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002300 for (h = s_h; h <= PNEIGH_HASHMASK; h++) {
Tony Zelenoff84920c12012-01-26 22:28:58 +00002301 if (h > s_h)
2302 s_idx = 0;
2303 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
2304 if (dev_net(n->dev) != net)
2305 continue;
2306 if (idx < s_idx)
2307 goto next;
Eric W. Biederman15e47302012-09-07 20:12:54 +00002308 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
Tony Zelenoff84920c12012-01-26 22:28:58 +00002309 cb->nlh->nlmsg_seq,
2310 RTM_NEWNEIGH,
2311 NLM_F_MULTI, tbl) <= 0) {
2312 read_unlock_bh(&tbl->lock);
2313 rc = -1;
2314 goto out;
2315 }
2316 next:
2317 idx++;
2318 }
2319 }
2320
2321 read_unlock_bh(&tbl->lock);
2322 rc = skb->len;
2323out:
2324 cb->args[3] = h;
2325 cb->args[4] = idx;
2326 return rc;
2327
2328}
2329
Thomas Grafc8822a42007-03-22 11:50:06 -07002330static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331{
2332 struct neigh_table *tbl;
2333 int t, family, s_t;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002334 int proxy = 0;
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002335 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002336
2337 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002338 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002339
2340 /* check for full ndmsg structure presence, family member is
2341 * the same for both structures
2342 */
2343 if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2344 ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2345 proxy = 1;
2346
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347 s_t = cb->args[0];
2348
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002349 for (tbl = neigh_tables, t = 0; tbl;
Tony Zelenoff84920c12012-01-26 22:28:58 +00002350 tbl = tbl->next, t++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 if (t < s_t || (family && tbl->family != family))
2352 continue;
2353 if (t > s_t)
2354 memset(&cb->args[1], 0, sizeof(cb->args) -
2355 sizeof(cb->args[0]));
Tony Zelenoff84920c12012-01-26 22:28:58 +00002356 if (proxy)
2357 err = pneigh_dump_table(tbl, skb, cb);
2358 else
2359 err = neigh_dump_table(tbl, skb, cb);
Eric Dumazet4bd6683b2012-06-07 04:58:35 +00002360 if (err < 0)
2361 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002362 }
2363 read_unlock(&neigh_tbl_lock);
2364
2365 cb->args[0] = t;
2366 return skb->len;
2367}
2368
2369void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2370{
2371 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002372 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002373
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002374 rcu_read_lock_bh();
2375 nht = rcu_dereference_bh(tbl->nht);
2376
Eric Dumazet767e97e2010-10-06 17:49:21 -07002377 read_lock(&tbl->lock); /* avoid resizes */
David S. Millercd089332011-07-11 01:28:12 -07002378 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002379 struct neighbour *n;
2380
Eric Dumazet767e97e2010-10-06 17:49:21 -07002381 for (n = rcu_dereference_bh(nht->hash_buckets[chain]);
2382 n != NULL;
2383 n = rcu_dereference_bh(n->next))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002384 cb(n, cookie);
2385 }
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002386 read_unlock(&tbl->lock);
2387 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388}
2389EXPORT_SYMBOL(neigh_for_each);
2390
2391/* The tbl->lock must be held as a writer and BH disabled. */
2392void __neigh_for_each_release(struct neigh_table *tbl,
2393 int (*cb)(struct neighbour *))
2394{
2395 int chain;
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002396 struct neigh_hash_table *nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002398 nht = rcu_dereference_protected(tbl->nht,
2399 lockdep_is_held(&tbl->lock));
David S. Millercd089332011-07-11 01:28:12 -07002400 for (chain = 0; chain < (1 << nht->hash_shift); chain++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002401 struct neighbour *n;
2402 struct neighbour __rcu **np;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002404 np = &nht->hash_buckets[chain];
Eric Dumazet767e97e2010-10-06 17:49:21 -07002405 while ((n = rcu_dereference_protected(*np,
2406 lockdep_is_held(&tbl->lock))) != NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002407 int release;
2408
2409 write_lock(&n->lock);
2410 release = cb(n);
2411 if (release) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002412 rcu_assign_pointer(*np,
2413 rcu_dereference_protected(n->next,
2414 lockdep_is_held(&tbl->lock)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 n->dead = 1;
2416 } else
2417 np = &n->next;
2418 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002419 if (release)
2420 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421 }
2422 }
2423}
2424EXPORT_SYMBOL(__neigh_for_each_release);
2425
2426#ifdef CONFIG_PROC_FS
2427
2428static struct neighbour *neigh_get_first(struct seq_file *seq)
2429{
2430 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002431 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002432 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 struct neighbour *n = NULL;
2434 int bucket = state->bucket;
2435
2436 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
David S. Millercd089332011-07-11 01:28:12 -07002437 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
Eric Dumazet767e97e2010-10-06 17:49:21 -07002438 n = rcu_dereference_bh(nht->hash_buckets[bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002439
2440 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002441 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002442 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002443 if (state->neigh_sub_iter) {
2444 loff_t fakep = 0;
2445 void *v;
2446
2447 v = state->neigh_sub_iter(state, n, &fakep);
2448 if (!v)
2449 goto next;
2450 }
2451 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2452 break;
2453 if (n->nud_state & ~NUD_NOARP)
2454 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002455next:
2456 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002457 }
2458
2459 if (n)
2460 break;
2461 }
2462 state->bucket = bucket;
2463
2464 return n;
2465}
2466
2467static struct neighbour *neigh_get_next(struct seq_file *seq,
2468 struct neighbour *n,
2469 loff_t *pos)
2470{
2471 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002472 struct net *net = seq_file_net(seq);
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002473 struct neigh_hash_table *nht = state->nht;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002474
2475 if (state->neigh_sub_iter) {
2476 void *v = state->neigh_sub_iter(state, n, pos);
2477 if (v)
2478 return n;
2479 }
Eric Dumazet767e97e2010-10-06 17:49:21 -07002480 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002481
2482 while (1) {
2483 while (n) {
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002484 if (!net_eq(dev_net(n->dev), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002485 goto next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 if (state->neigh_sub_iter) {
2487 void *v = state->neigh_sub_iter(state, n, pos);
2488 if (v)
2489 return n;
2490 goto next;
2491 }
2492 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2493 break;
2494
2495 if (n->nud_state & ~NUD_NOARP)
2496 break;
Eric Dumazet767e97e2010-10-06 17:49:21 -07002497next:
2498 n = rcu_dereference_bh(n->next);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002499 }
2500
2501 if (n)
2502 break;
2503
David S. Millercd089332011-07-11 01:28:12 -07002504 if (++state->bucket >= (1 << nht->hash_shift))
Linus Torvalds1da177e2005-04-16 15:20:36 -07002505 break;
2506
Eric Dumazet767e97e2010-10-06 17:49:21 -07002507 n = rcu_dereference_bh(nht->hash_buckets[state->bucket]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002508 }
2509
2510 if (n && pos)
2511 --(*pos);
2512 return n;
2513}
2514
2515static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2516{
2517 struct neighbour *n = neigh_get_first(seq);
2518
2519 if (n) {
Chris Larson745e2032008-08-03 01:10:55 -07002520 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 while (*pos) {
2522 n = neigh_get_next(seq, n, pos);
2523 if (!n)
2524 break;
2525 }
2526 }
2527 return *pos ? NULL : n;
2528}
2529
2530static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2531{
2532 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002533 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002534 struct neigh_table *tbl = state->tbl;
2535 struct pneigh_entry *pn = NULL;
2536 int bucket = state->bucket;
2537
2538 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2539 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2540 pn = tbl->phash_buckets[bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002541 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002542 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543 if (pn)
2544 break;
2545 }
2546 state->bucket = bucket;
2547
2548 return pn;
2549}
2550
2551static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2552 struct pneigh_entry *pn,
2553 loff_t *pos)
2554{
2555 struct neigh_seq_state *state = seq->private;
YOSHIFUJI Hideaki12188542008-03-26 02:36:06 +09002556 struct net *net = seq_file_net(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557 struct neigh_table *tbl = state->tbl;
2558
Jorge Boncompte [DTI2]df07a942011-11-25 13:24:49 -05002559 do {
2560 pn = pn->next;
2561 } while (pn && !net_eq(pneigh_net(pn), net));
2562
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 while (!pn) {
2564 if (++state->bucket > PNEIGH_HASHMASK)
2565 break;
2566 pn = tbl->phash_buckets[state->bucket];
YOSHIFUJI Hideaki878628f2008-03-26 03:57:35 +09002567 while (pn && !net_eq(pneigh_net(pn), net))
Eric W. Biederman426b5302008-01-24 00:13:18 -08002568 pn = pn->next;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002569 if (pn)
2570 break;
2571 }
2572
2573 if (pn && pos)
2574 --(*pos);
2575
2576 return pn;
2577}
2578
2579static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2580{
2581 struct pneigh_entry *pn = pneigh_get_first(seq);
2582
2583 if (pn) {
Chris Larson745e2032008-08-03 01:10:55 -07002584 --(*pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002585 while (*pos) {
2586 pn = pneigh_get_next(seq, pn, pos);
2587 if (!pn)
2588 break;
2589 }
2590 }
2591 return *pos ? NULL : pn;
2592}
2593
2594static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2595{
2596 struct neigh_seq_state *state = seq->private;
2597 void *rc;
Chris Larson745e2032008-08-03 01:10:55 -07002598 loff_t idxpos = *pos;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599
Chris Larson745e2032008-08-03 01:10:55 -07002600 rc = neigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
Chris Larson745e2032008-08-03 01:10:55 -07002602 rc = pneigh_get_idx(seq, &idxpos);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002603
2604 return rc;
2605}
2606
2607void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002608 __acquires(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609{
2610 struct neigh_seq_state *state = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611
2612 state->tbl = tbl;
2613 state->bucket = 0;
2614 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2615
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002616 rcu_read_lock_bh();
2617 state->nht = rcu_dereference_bh(tbl->nht);
Eric Dumazet767e97e2010-10-06 17:49:21 -07002618
Chris Larson745e2032008-08-03 01:10:55 -07002619 return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620}
2621EXPORT_SYMBOL(neigh_seq_start);
2622
2623void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2624{
2625 struct neigh_seq_state *state;
2626 void *rc;
2627
2628 if (v == SEQ_START_TOKEN) {
Chris Larsonbff69732008-08-03 01:02:41 -07002629 rc = neigh_get_first(seq);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 goto out;
2631 }
2632
2633 state = seq->private;
2634 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2635 rc = neigh_get_next(seq, v, NULL);
2636 if (rc)
2637 goto out;
2638 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2639 rc = pneigh_get_first(seq);
2640 } else {
2641 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2642 rc = pneigh_get_next(seq, v, NULL);
2643 }
2644out:
2645 ++(*pos);
2646 return rc;
2647}
2648EXPORT_SYMBOL(neigh_seq_next);
2649
2650void neigh_seq_stop(struct seq_file *seq, void *v)
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002651 __releases(rcu_bh)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652{
Eric Dumazetd6bf7812010-10-04 06:15:44 +00002653 rcu_read_unlock_bh();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654}
2655EXPORT_SYMBOL(neigh_seq_stop);
2656
2657/* statistics via seq_file */
2658
2659static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2660{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002661 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 int cpu;
2663
2664 if (*pos == 0)
2665 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002666
Rusty Russell0f23174a2008-12-29 12:23:42 +00002667 for (cpu = *pos-1; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002668 if (!cpu_possible(cpu))
2669 continue;
2670 *pos = cpu+1;
2671 return per_cpu_ptr(tbl->stats, cpu);
2672 }
2673 return NULL;
2674}
2675
2676static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2677{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002678 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 int cpu;
2680
Rusty Russell0f23174a2008-12-29 12:23:42 +00002681 for (cpu = *pos; cpu < nr_cpu_ids; ++cpu) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 if (!cpu_possible(cpu))
2683 continue;
2684 *pos = cpu+1;
2685 return per_cpu_ptr(tbl->stats, cpu);
2686 }
2687 return NULL;
2688}
2689
2690static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2691{
2692
2693}
2694
2695static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2696{
Alexey Dobriyan81c1ebf2010-01-22 10:16:05 +00002697 struct neigh_table *tbl = seq->private;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698 struct neigh_statistics *st = v;
2699
2700 if (v == SEQ_START_TOKEN) {
Neil Horman9a6d2762008-07-16 20:50:49 -07002701 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\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 return 0;
2703 }
2704
2705 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
Neil Horman9a6d2762008-07-16 20:50:49 -07002706 "%08lx %08lx %08lx %08lx %08lx\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707 atomic_read(&tbl->entries),
2708
2709 st->allocs,
2710 st->destroys,
2711 st->hash_grows,
2712
2713 st->lookups,
2714 st->hits,
2715
2716 st->res_failed,
2717
2718 st->rcv_probes_mcast,
2719 st->rcv_probes_ucast,
2720
2721 st->periodic_gc_runs,
Neil Horman9a6d2762008-07-16 20:50:49 -07002722 st->forced_gc_runs,
2723 st->unres_discards
Linus Torvalds1da177e2005-04-16 15:20:36 -07002724 );
2725
2726 return 0;
2727}
2728
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002729static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002730 .start = neigh_stat_seq_start,
2731 .next = neigh_stat_seq_next,
2732 .stop = neigh_stat_seq_stop,
2733 .show = neigh_stat_seq_show,
2734};
2735
2736static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2737{
2738 int ret = seq_open(file, &neigh_stat_seq_ops);
2739
2740 if (!ret) {
2741 struct seq_file *sf = file->private_data;
Al Virod9dda782013-03-31 18:16:14 -04002742 sf->private = PDE_DATA(inode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002743 }
2744 return ret;
2745};
2746
Arjan van de Ven9a321442007-02-12 00:55:35 -08002747static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002748 .owner = THIS_MODULE,
2749 .open = neigh_stat_seq_open,
2750 .read = seq_read,
2751 .llseek = seq_lseek,
2752 .release = seq_release,
2753};
2754
2755#endif /* CONFIG_PROC_FS */
2756
Thomas Graf339bf982006-11-10 14:10:15 -08002757static inline size_t neigh_nlmsg_size(void)
2758{
2759 return NLMSG_ALIGN(sizeof(struct ndmsg))
2760 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2761 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2762 + nla_total_size(sizeof(struct nda_cacheinfo))
2763 + nla_total_size(4); /* NDA_PROBES */
2764}
2765
Thomas Grafb8673312006-08-15 00:33:14 -07002766static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002767{
YOSHIFUJI Hideakic346dca2008-03-25 21:47:49 +09002768 struct net *net = dev_net(n->dev);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002769 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002770 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002771
Thomas Graf339bf982006-11-10 14:10:15 -08002772 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002773 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002774 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775
Thomas Grafb8673312006-08-15 00:33:14 -07002776 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002777 if (err < 0) {
2778 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2779 WARN_ON(err == -EMSGSIZE);
2780 kfree_skb(skb);
2781 goto errout;
2782 }
Pablo Neira Ayuso1ce85fe2009-02-24 23:18:28 -08002783 rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2784 return;
Thomas Grafb8673312006-08-15 00:33:14 -07002785errout:
2786 if (err < 0)
Eric W. Biederman426b5302008-01-24 00:13:18 -08002787 rtnl_set_sk_err(net, RTNLGRP_NEIGH, err);
Thomas Grafb8673312006-08-15 00:33:14 -07002788}
2789
2790void neigh_app_ns(struct neighbour *n)
2791{
2792 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002793}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09002794EXPORT_SYMBOL(neigh_app_ns);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002795
2796#ifdef CONFIG_SYSCTL
Cong Wangb93196d2012-12-06 10:04:04 +08002797static int zero;
Francesco Fusco555445c2013-07-24 10:39:06 +02002798static int int_max = INT_MAX;
Cong Wangb93196d2012-12-06 10:04:04 +08002799static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002800
Joe Perchesfe2c6332013-06-11 23:04:25 -07002801static int proc_unres_qlen(struct ctl_table *ctl, int write,
2802 void __user *buffer, size_t *lenp, loff_t *ppos)
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002803{
2804 int size, ret;
Joe Perchesfe2c6332013-06-11 23:04:25 -07002805 struct ctl_table tmp = *ctl;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002806
Shan Weice46cc62012-12-04 18:49:15 +00002807 tmp.extra1 = &zero;
2808 tmp.extra2 = &unres_qlen_max;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002809 tmp.data = &size;
Shan Weice46cc62012-12-04 18:49:15 +00002810
2811 size = *(int *)ctl->data / SKB_TRUESIZE(ETH_FRAME_LEN);
2812 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2813
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002814 if (write && !ret)
2815 *(int *)ctl->data = size * SKB_TRUESIZE(ETH_FRAME_LEN);
2816 return ret;
2817}
2818
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002819static struct neigh_parms *neigh_get_dev_parms_rcu(struct net_device *dev,
2820 int family)
2821{
2822 if (family == AF_INET)
2823 return __in_dev_arp_parms_get_rcu(dev);
2824 return NULL;
2825}
2826
2827static void neigh_copy_dflt_parms(struct net *net, struct neigh_parms *p,
2828 int index)
2829{
2830 struct net_device *dev;
2831 int family = neigh_parms_family(p);
2832
2833 rcu_read_lock();
2834 for_each_netdev_rcu(net, dev) {
2835 struct neigh_parms *dst_p =
2836 neigh_get_dev_parms_rcu(dev, family);
2837
2838 if (dst_p && !test_bit(index, dst_p->data_state))
2839 dst_p->data[index] = p->data[index];
2840 }
2841 rcu_read_unlock();
2842}
2843
2844static void neigh_proc_update(struct ctl_table *ctl, int write)
2845{
2846 struct net_device *dev = ctl->extra1;
2847 struct neigh_parms *p = ctl->extra2;
2848 struct net *net = p->net;
2849 int index = (int *) ctl->data - p->data;
2850
2851 if (!write)
2852 return;
2853
2854 set_bit(index, p->data_state);
2855 if (!dev) /* NULL dev means this is default value */
2856 neigh_copy_dflt_parms(net, p, index);
2857}
2858
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002859static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
2860 void __user *buffer,
2861 size_t *lenp, loff_t *ppos)
2862{
2863 struct ctl_table tmp = *ctl;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002864 int ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002865
2866 tmp.extra1 = &zero;
2867 tmp.extra2 = &int_max;
2868
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002869 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
2870 neigh_proc_update(ctl, write);
2871 return ret;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002872}
2873
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002874int neigh_proc_dointvec(struct ctl_table *ctl, int write,
2875 void __user *buffer, size_t *lenp, loff_t *ppos)
2876{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002877 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
2878
2879 neigh_proc_update(ctl, write);
2880 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002881}
2882EXPORT_SYMBOL(neigh_proc_dointvec);
2883
2884int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
2885 void __user *buffer,
2886 size_t *lenp, loff_t *ppos)
2887{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002888 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
2889
2890 neigh_proc_update(ctl, write);
2891 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002892}
2893EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
2894
2895static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
2896 void __user *buffer,
2897 size_t *lenp, loff_t *ppos)
2898{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002899 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
2900
2901 neigh_proc_update(ctl, write);
2902 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002903}
2904
2905int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
2906 void __user *buffer,
2907 size_t *lenp, loff_t *ppos)
2908{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002909 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
2910
2911 neigh_proc_update(ctl, write);
2912 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002913}
2914EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
2915
2916static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
2917 void __user *buffer,
2918 size_t *lenp, loff_t *ppos)
2919{
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01002920 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
2921
2922 neigh_proc_update(ctl, write);
2923 return ret;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002924}
2925
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002926#define NEIGH_PARMS_DATA_OFFSET(index) \
2927 (&((struct neigh_parms *) 0)->data[index])
2928
2929#define NEIGH_SYSCTL_ENTRY(attr, data_attr, name, mval, proc) \
2930 [NEIGH_VAR_ ## attr] = { \
2931 .procname = name, \
2932 .data = NEIGH_PARMS_DATA_OFFSET(NEIGH_VAR_ ## data_attr), \
2933 .maxlen = sizeof(int), \
2934 .mode = mval, \
2935 .proc_handler = proc, \
2936 }
2937
2938#define NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(attr, name) \
2939 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_zero_intmax)
2940
2941#define NEIGH_SYSCTL_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002942 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002943
2944#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002945 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002946
2947#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002948 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002949
2950#define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002951 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002952
2953#define NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(attr, data_attr, name) \
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01002954 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_unres_qlen)
Eric W. Biederman54716e32010-02-14 03:27:03 +00002955
Linus Torvalds1da177e2005-04-16 15:20:36 -07002956static struct neigh_sysctl_table {
2957 struct ctl_table_header *sysctl_header;
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002958 struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
Brian Haleyab32ea52006-09-22 14:15:41 -07002959} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002960 .neigh_vars = {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01002961 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(MCAST_PROBES, "mcast_solicit"),
2962 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(UCAST_PROBES, "ucast_solicit"),
2963 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(APP_PROBES, "app_solicit"),
2964 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(RETRANS_TIME, "retrans_time"),
2965 NEIGH_SYSCTL_JIFFIES_ENTRY(BASE_REACHABLE_TIME, "base_reachable_time"),
2966 NEIGH_SYSCTL_JIFFIES_ENTRY(DELAY_PROBE_TIME, "delay_first_probe_time"),
2967 NEIGH_SYSCTL_JIFFIES_ENTRY(GC_STALETIME, "gc_stale_time"),
2968 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(QUEUE_LEN_BYTES, "unres_qlen_bytes"),
2969 NEIGH_SYSCTL_ZERO_INTMAX_ENTRY(PROXY_QLEN, "proxy_qlen"),
2970 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(ANYCAST_DELAY, "anycast_delay"),
2971 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(PROXY_DELAY, "proxy_delay"),
2972 NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
2973 NEIGH_SYSCTL_UNRES_QLEN_REUSED_ENTRY(QUEUE_LEN, QUEUE_LEN_BYTES, "unres_qlen"),
2974 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(RETRANS_TIME_MS, RETRANS_TIME, "retrans_time_ms"),
2975 NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(BASE_REACHABLE_TIME_MS, BASE_REACHABLE_TIME, "base_reachable_time_ms"),
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002976 [NEIGH_VAR_GC_INTERVAL] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002977 .procname = "gc_interval",
2978 .maxlen = sizeof(int),
2979 .mode = 0644,
Alexey Dobriyan6d9f2392008-11-03 18:21:05 -08002980 .proc_handler = proc_dointvec_jiffies,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002981 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002982 [NEIGH_VAR_GC_THRESH1] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002983 .procname = "gc_thresh1",
2984 .maxlen = sizeof(int),
2985 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02002986 .extra1 = &zero,
2987 .extra2 = &int_max,
2988 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002989 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002990 [NEIGH_VAR_GC_THRESH2] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002991 .procname = "gc_thresh2",
2992 .maxlen = sizeof(int),
2993 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02002994 .extra1 = &zero,
2995 .extra2 = &int_max,
2996 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002997 },
Eric Dumazet8b5c1712011-11-09 12:07:14 +00002998 [NEIGH_VAR_GC_THRESH3] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002999 .procname = "gc_thresh3",
3000 .maxlen = sizeof(int),
3001 .mode = 0644,
Francesco Fusco555445c2013-07-24 10:39:06 +02003002 .extra1 = &zero,
3003 .extra2 = &int_max,
3004 .proc_handler = proc_dointvec_minmax,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003005 },
Pavel Emelyanovc3bac5a2007-12-02 00:08:16 +11003006 {},
Linus Torvalds1da177e2005-04-16 15:20:36 -07003007 },
3008};
3009
3010int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
Jiri Pirko73af6142013-12-07 19:26:55 +01003011 proc_handler *handler)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012{
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003013 int i;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003014 struct neigh_sysctl_table *t;
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003015 const char *dev_name_source;
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003016 char neigh_path[ sizeof("net//neigh/") + IFNAMSIZ + IFNAMSIZ ];
Jiri Pirko73af6142013-12-07 19:26:55 +01003017 char *p_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003018
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003019 t = kmemdup(&neigh_sysctl_template, sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003020 if (!t)
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003021 goto err;
3022
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003023 for (i = 0; i < ARRAY_SIZE(t->neigh_vars); i++) {
Jiri Pirko1f9248e2013-12-07 19:26:53 +01003024 t->neigh_vars[i].data += (long) p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003025 t->neigh_vars[i].extra1 = dev;
Jiri Pirko1d4c8c22013-12-07 19:26:56 +01003026 t->neigh_vars[i].extra2 = p;
Jiri Pirkocb5b09c2013-12-07 19:26:54 +01003027 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
3029 if (dev) {
3030 dev_name_source = dev->name;
Eric W. Biedermand12af672007-10-18 03:05:25 -07003031 /* Terminate the table early */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003032 memset(&t->neigh_vars[NEIGH_VAR_GC_INTERVAL], 0,
3033 sizeof(t->neigh_vars[NEIGH_VAR_GC_INTERVAL]));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003034 } else {
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003035 dev_name_source = "default";
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003036 t->neigh_vars[NEIGH_VAR_GC_INTERVAL].data = (int *)(p + 1);
3037 t->neigh_vars[NEIGH_VAR_GC_THRESH1].data = (int *)(p + 1) + 1;
3038 t->neigh_vars[NEIGH_VAR_GC_THRESH2].data = (int *)(p + 1) + 2;
3039 t->neigh_vars[NEIGH_VAR_GC_THRESH3].data = (int *)(p + 1) + 3;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003040 }
3041
Eric W. Biedermanf8572d82009-11-05 13:32:03 -08003042 if (handler) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07003043 /* RetransTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003044 t->neigh_vars[NEIGH_VAR_RETRANS_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003045 /* ReachableTime */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003046 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047 /* RetransTime (in milliseconds)*/
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003048 t->neigh_vars[NEIGH_VAR_RETRANS_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003049 /* ReachableTime (in milliseconds) */
Eric Dumazet8b5c1712011-11-09 12:07:14 +00003050 t->neigh_vars[NEIGH_VAR_BASE_REACHABLE_TIME_MS].proc_handler = handler;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003051 }
3052
Eric W. Biederman464dc802012-11-16 03:02:59 +00003053 /* Don't export sysctls to unprivileged users */
3054 if (neigh_parms_net(p)->user_ns != &init_user_ns)
3055 t->neigh_vars[0].procname = NULL;
3056
Jiri Pirko73af6142013-12-07 19:26:55 +01003057 switch (neigh_parms_family(p)) {
3058 case AF_INET:
3059 p_name = "ipv4";
3060 break;
3061 case AF_INET6:
3062 p_name = "ipv6";
3063 break;
3064 default:
3065 BUG();
3066 }
3067
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003068 snprintf(neigh_path, sizeof(neigh_path), "net/%s/neigh/%s",
3069 p_name, dev_name_source);
Denis V. Lunev4ab438f2008-02-28 20:48:01 -08003070 t->sysctl_header =
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003071 register_net_sysctl(neigh_parms_net(p), neigh_path, t->neigh_vars);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003072 if (!t->sysctl_header)
Eric W. Biederman8f40a1f2012-04-19 13:38:03 +00003073 goto free;
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003074
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075 p->sysctl_table = t;
3076 return 0;
3077
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003078free:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079 kfree(t);
Pavel Emelyanov3c607bb2007-12-02 00:06:34 +11003080err:
3081 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003083EXPORT_SYMBOL(neigh_sysctl_register);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003084
3085void neigh_sysctl_unregister(struct neigh_parms *p)
3086{
3087 if (p->sysctl_table) {
3088 struct neigh_sysctl_table *t = p->sysctl_table;
3089 p->sysctl_table = NULL;
Eric W. Biederman5dd3df12012-04-19 13:24:33 +00003090 unregister_net_sysctl_table(t->sysctl_header);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003091 kfree(t);
3092 }
3093}
YOSHIFUJI Hideaki0a204502008-03-24 18:39:10 +09003094EXPORT_SYMBOL(neigh_sysctl_unregister);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003095
3096#endif /* CONFIG_SYSCTL */
3097
Thomas Grafc8822a42007-03-22 11:50:06 -07003098static int __init neigh_init(void)
3099{
Greg Rosec7ac8672011-06-10 01:27:09 +00003100 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, NULL);
3101 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, NULL);
3102 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003103
Greg Rosec7ac8672011-06-10 01:27:09 +00003104 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
3105 NULL);
3106 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, NULL);
Thomas Grafc8822a42007-03-22 11:50:06 -07003107
3108 return 0;
3109}
3110
3111subsys_initcall(neigh_init);
3112