blob: 4b815db94b6b2264e9f2b3c8a550854f59c90332 [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070018#include <linux/types.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/socket.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070022#include <linux/netdevice.h>
23#include <linux/proc_fs.h>
24#ifdef CONFIG_SYSCTL
25#include <linux/sysctl.h>
26#endif
27#include <linux/times.h>
28#include <net/neighbour.h>
29#include <net/dst.h>
30#include <net/sock.h>
Tom Tucker8d717402006-07-30 20:43:36 -070031#include <net/netevent.h>
Thomas Grafa14a49d2006-08-07 17:53:08 -070032#include <net/netlink.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/rtnetlink.h>
34#include <linux/random.h>
Paulo Marques543537b2005-06-23 00:09:02 -070035#include <linux/string.h>
vignesh babuc3609d52007-08-24 22:27:55 -070036#include <linux/log2.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070037
38#define NEIGH_DEBUG 1
39
40#define NEIGH_PRINTK(x...) printk(x)
41#define NEIGH_NOPRINTK(x...) do { ; } while(0)
42#define NEIGH_PRINTK0 NEIGH_PRINTK
43#define NEIGH_PRINTK1 NEIGH_NOPRINTK
44#define NEIGH_PRINTK2 NEIGH_NOPRINTK
45
46#if NEIGH_DEBUG >= 1
47#undef NEIGH_PRINTK1
48#define NEIGH_PRINTK1 NEIGH_PRINTK
49#endif
50#if NEIGH_DEBUG >= 2
51#undef NEIGH_PRINTK2
52#define NEIGH_PRINTK2 NEIGH_PRINTK
53#endif
54
55#define PNEIGH_HASHMASK 0xF
56
57static void neigh_timer_handler(unsigned long arg);
58#ifdef CONFIG_ARPD
59static void neigh_app_notify(struct neighbour *n);
60#endif
61static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev);
62void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev);
63
64static struct neigh_table *neigh_tables;
Amos Waterland45fc3b12005-09-24 16:53:16 -070065#ifdef CONFIG_PROC_FS
Arjan van de Ven9a321442007-02-12 00:55:35 -080066static const struct file_operations neigh_stat_seq_fops;
Amos Waterland45fc3b12005-09-24 16:53:16 -070067#endif
Linus Torvalds1da177e2005-04-16 15:20:36 -070068
69/*
70 Neighbour hash table buckets are protected with rwlock tbl->lock.
71
72 - All the scans/updates to hash buckets MUST be made under this lock.
73 - NOTHING clever should be made under this lock: no callbacks
74 to protocol backends, no attempts to send something to network.
75 It will result in deadlocks, if backend/driver wants to use neighbour
76 cache.
77 - If the entry requires some non-trivial actions, increase
78 its reference count and release table lock.
79
80 Neighbour entries are protected:
81 - with reference count.
82 - with rwlock neigh->lock
83
84 Reference count prevents destruction.
85
86 neigh->lock mainly serializes ll address data and its validity state.
87 However, the same lock is used to protect another entry fields:
88 - timer
89 - resolution queue
90
91 Again, nothing clever shall be made under neigh->lock,
92 the most complicated procedure, which we allow is dev->hard_header.
93 It is supposed, that dev->hard_header is simplistic and does
94 not make callbacks to neighbour tables.
95
96 The last lock is neigh_tbl_lock. It is pure SMP lock, protecting
97 list of neighbour tables. This list is used only in process context,
98 */
99
100static DEFINE_RWLOCK(neigh_tbl_lock);
101
102static int neigh_blackhole(struct sk_buff *skb)
103{
104 kfree_skb(skb);
105 return -ENETDOWN;
106}
107
Thomas Graf4f494552007-08-08 23:12:36 -0700108static void neigh_cleanup_and_release(struct neighbour *neigh)
109{
110 if (neigh->parms->neigh_cleanup)
111 neigh->parms->neigh_cleanup(neigh);
112
113 neigh_release(neigh);
114}
115
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116/*
117 * It is random distribution in the interval (1/2)*base...(3/2)*base.
118 * It corresponds to default IPv6 settings and is not overridable,
119 * because it is really reasonable choice.
120 */
121
122unsigned long neigh_rand_reach_time(unsigned long base)
123{
124 return (base ? (net_random() % base) + (base >> 1) : 0);
125}
126
127
128static int neigh_forced_gc(struct neigh_table *tbl)
129{
130 int shrunk = 0;
131 int i;
132
133 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
134
135 write_lock_bh(&tbl->lock);
136 for (i = 0; i <= tbl->hash_mask; i++) {
137 struct neighbour *n, **np;
138
139 np = &tbl->hash_buckets[i];
140 while ((n = *np) != NULL) {
141 /* Neighbour record may be discarded if:
142 * - nobody refers to it.
143 * - it is not permanent
144 */
145 write_lock(&n->lock);
146 if (atomic_read(&n->refcnt) == 1 &&
147 !(n->nud_state & NUD_PERMANENT)) {
148 *np = n->next;
149 n->dead = 1;
150 shrunk = 1;
151 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700152 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 continue;
154 }
155 write_unlock(&n->lock);
156 np = &n->next;
157 }
158 }
159
160 tbl->last_flush = jiffies;
161
162 write_unlock_bh(&tbl->lock);
163
164 return shrunk;
165}
166
167static int neigh_del_timer(struct neighbour *n)
168{
169 if ((n->nud_state & NUD_IN_TIMER) &&
170 del_timer(&n->timer)) {
171 neigh_release(n);
172 return 1;
173 }
174 return 0;
175}
176
177static void pneigh_queue_purge(struct sk_buff_head *list)
178{
179 struct sk_buff *skb;
180
181 while ((skb = skb_dequeue(list)) != NULL) {
182 dev_put(skb->dev);
183 kfree_skb(skb);
184 }
185}
186
Herbert Xu49636bb2005-10-23 17:18:00 +1000187static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700188{
189 int i;
190
Linus Torvalds1da177e2005-04-16 15:20:36 -0700191 for (i = 0; i <= tbl->hash_mask; i++) {
192 struct neighbour *n, **np = &tbl->hash_buckets[i];
193
194 while ((n = *np) != NULL) {
195 if (dev && n->dev != dev) {
196 np = &n->next;
197 continue;
198 }
199 *np = n->next;
200 write_lock(&n->lock);
201 neigh_del_timer(n);
202 n->dead = 1;
203
204 if (atomic_read(&n->refcnt) != 1) {
205 /* The most unpleasant situation.
206 We must destroy neighbour entry,
207 but someone still uses it.
208
209 The destroy will be delayed until
210 the last user releases us, but
211 we must kill timers etc. and move
212 it to safe state.
213 */
214 skb_queue_purge(&n->arp_queue);
215 n->output = neigh_blackhole;
216 if (n->nud_state & NUD_VALID)
217 n->nud_state = NUD_NOARP;
218 else
219 n->nud_state = NUD_NONE;
220 NEIGH_PRINTK2("neigh %p is stray.\n", n);
221 }
222 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700223 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 }
225 }
Herbert Xu49636bb2005-10-23 17:18:00 +1000226}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Herbert Xu49636bb2005-10-23 17:18:00 +1000228void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
229{
230 write_lock_bh(&tbl->lock);
231 neigh_flush_dev(tbl, dev);
232 write_unlock_bh(&tbl->lock);
233}
234
235int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
236{
237 write_lock_bh(&tbl->lock);
238 neigh_flush_dev(tbl, dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 pneigh_ifdown(tbl, dev);
240 write_unlock_bh(&tbl->lock);
241
242 del_timer_sync(&tbl->proxy_timer);
243 pneigh_queue_purge(&tbl->proxy_queue);
244 return 0;
245}
246
247static struct neighbour *neigh_alloc(struct neigh_table *tbl)
248{
249 struct neighbour *n = NULL;
250 unsigned long now = jiffies;
251 int entries;
252
253 entries = atomic_inc_return(&tbl->entries) - 1;
254 if (entries >= tbl->gc_thresh3 ||
255 (entries >= tbl->gc_thresh2 &&
256 time_after(now, tbl->last_flush + 5 * HZ))) {
257 if (!neigh_forced_gc(tbl) &&
258 entries >= tbl->gc_thresh3)
259 goto out_entries;
260 }
261
Robert P. J. Dayc3762222007-02-10 01:45:03 -0800262 n = kmem_cache_zalloc(tbl->kmem_cachep, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263 if (!n)
264 goto out_entries;
265
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266 skb_queue_head_init(&n->arp_queue);
267 rwlock_init(&n->lock);
268 n->updated = n->used = now;
269 n->nud_state = NUD_NONE;
270 n->output = neigh_blackhole;
271 n->parms = neigh_parms_clone(&tbl->parms);
272 init_timer(&n->timer);
273 n->timer.function = neigh_timer_handler;
274 n->timer.data = (unsigned long)n;
275
276 NEIGH_CACHE_STAT_INC(tbl, allocs);
277 n->tbl = tbl;
278 atomic_set(&n->refcnt, 1);
279 n->dead = 1;
280out:
281 return n;
282
283out_entries:
284 atomic_dec(&tbl->entries);
285 goto out;
286}
287
288static struct neighbour **neigh_hash_alloc(unsigned int entries)
289{
290 unsigned long size = entries * sizeof(struct neighbour *);
291 struct neighbour **ret;
292
293 if (size <= PAGE_SIZE) {
Andrew Morton77d04bd2006-04-07 14:52:59 -0700294 ret = kzalloc(size, GFP_ATOMIC);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700295 } else {
296 ret = (struct neighbour **)
Andrew Morton77d04bd2006-04-07 14:52:59 -0700297 __get_free_pages(GFP_ATOMIC|__GFP_ZERO, get_order(size));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700298 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700299 return ret;
300}
301
302static void neigh_hash_free(struct neighbour **hash, unsigned int entries)
303{
304 unsigned long size = entries * sizeof(struct neighbour *);
305
306 if (size <= PAGE_SIZE)
307 kfree(hash);
308 else
309 free_pages((unsigned long)hash, get_order(size));
310}
311
312static void neigh_hash_grow(struct neigh_table *tbl, unsigned long new_entries)
313{
314 struct neighbour **new_hash, **old_hash;
315 unsigned int i, new_hash_mask, old_entries;
316
317 NEIGH_CACHE_STAT_INC(tbl, hash_grows);
318
vignesh babuc3609d52007-08-24 22:27:55 -0700319 BUG_ON(!is_power_of_2(new_entries));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 new_hash = neigh_hash_alloc(new_entries);
321 if (!new_hash)
322 return;
323
324 old_entries = tbl->hash_mask + 1;
325 new_hash_mask = new_entries - 1;
326 old_hash = tbl->hash_buckets;
327
328 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
329 for (i = 0; i < old_entries; i++) {
330 struct neighbour *n, *next;
331
332 for (n = old_hash[i]; n; n = next) {
333 unsigned int hash_val = tbl->hash(n->primary_key, n->dev);
334
335 hash_val &= new_hash_mask;
336 next = n->next;
337
338 n->next = new_hash[hash_val];
339 new_hash[hash_val] = n;
340 }
341 }
342 tbl->hash_buckets = new_hash;
343 tbl->hash_mask = new_hash_mask;
344
345 neigh_hash_free(old_hash, old_entries);
346}
347
348struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
349 struct net_device *dev)
350{
351 struct neighbour *n;
352 int key_len = tbl->key_len;
Julian Anastasovc5e29462006-10-03 15:49:46 -0700353 u32 hash_val = tbl->hash(pkey, dev);
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900354
Linus Torvalds1da177e2005-04-16 15:20:36 -0700355 NEIGH_CACHE_STAT_INC(tbl, lookups);
356
357 read_lock_bh(&tbl->lock);
Julian Anastasovc5e29462006-10-03 15:49:46 -0700358 for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
360 neigh_hold(n);
361 NEIGH_CACHE_STAT_INC(tbl, hits);
362 break;
363 }
364 }
365 read_unlock_bh(&tbl->lock);
366 return n;
367}
368
369struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, const void *pkey)
370{
371 struct neighbour *n;
372 int key_len = tbl->key_len;
Julian Anastasovc5e29462006-10-03 15:49:46 -0700373 u32 hash_val = tbl->hash(pkey, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374
375 NEIGH_CACHE_STAT_INC(tbl, lookups);
376
377 read_lock_bh(&tbl->lock);
Julian Anastasovc5e29462006-10-03 15:49:46 -0700378 for (n = tbl->hash_buckets[hash_val & tbl->hash_mask]; n; n = n->next) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 if (!memcmp(n->primary_key, pkey, key_len)) {
380 neigh_hold(n);
381 NEIGH_CACHE_STAT_INC(tbl, hits);
382 break;
383 }
384 }
385 read_unlock_bh(&tbl->lock);
386 return n;
387}
388
389struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey,
390 struct net_device *dev)
391{
392 u32 hash_val;
393 int key_len = tbl->key_len;
394 int error;
395 struct neighbour *n1, *rc, *n = neigh_alloc(tbl);
396
397 if (!n) {
398 rc = ERR_PTR(-ENOBUFS);
399 goto out;
400 }
401
402 memcpy(n->primary_key, pkey, key_len);
403 n->dev = dev;
404 dev_hold(dev);
405
406 /* Protocol specific setup. */
407 if (tbl->constructor && (error = tbl->constructor(n)) < 0) {
408 rc = ERR_PTR(error);
409 goto out_neigh_release;
410 }
411
412 /* Device specific setup. */
413 if (n->parms->neigh_setup &&
414 (error = n->parms->neigh_setup(n)) < 0) {
415 rc = ERR_PTR(error);
416 goto out_neigh_release;
417 }
418
419 n->confirmed = jiffies - (n->parms->base_reachable_time << 1);
420
421 write_lock_bh(&tbl->lock);
422
423 if (atomic_read(&tbl->entries) > (tbl->hash_mask + 1))
424 neigh_hash_grow(tbl, (tbl->hash_mask + 1) << 1);
425
426 hash_val = tbl->hash(pkey, dev) & tbl->hash_mask;
427
428 if (n->parms->dead) {
429 rc = ERR_PTR(-EINVAL);
430 goto out_tbl_unlock;
431 }
432
433 for (n1 = tbl->hash_buckets[hash_val]; n1; n1 = n1->next) {
434 if (dev == n1->dev && !memcmp(n1->primary_key, pkey, key_len)) {
435 neigh_hold(n1);
436 rc = n1;
437 goto out_tbl_unlock;
438 }
439 }
440
441 n->next = tbl->hash_buckets[hash_val];
442 tbl->hash_buckets[hash_val] = n;
443 n->dead = 0;
444 neigh_hold(n);
445 write_unlock_bh(&tbl->lock);
446 NEIGH_PRINTK2("neigh %p is created.\n", n);
447 rc = n;
448out:
449 return rc;
450out_tbl_unlock:
451 write_unlock_bh(&tbl->lock);
452out_neigh_release:
453 neigh_release(n);
454 goto out;
455}
456
457struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl, const void *pkey,
458 struct net_device *dev, int creat)
459{
460 struct pneigh_entry *n;
461 int key_len = tbl->key_len;
462 u32 hash_val = *(u32 *)(pkey + key_len - 4);
463
464 hash_val ^= (hash_val >> 16);
465 hash_val ^= hash_val >> 8;
466 hash_val ^= hash_val >> 4;
467 hash_val &= PNEIGH_HASHMASK;
468
469 read_lock_bh(&tbl->lock);
470
471 for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
472 if (!memcmp(n->key, pkey, key_len) &&
473 (n->dev == dev || !n->dev)) {
474 read_unlock_bh(&tbl->lock);
475 goto out;
476 }
477 }
478 read_unlock_bh(&tbl->lock);
479 n = NULL;
480 if (!creat)
481 goto out;
482
483 n = kmalloc(sizeof(*n) + key_len, GFP_KERNEL);
484 if (!n)
485 goto out;
486
487 memcpy(n->key, pkey, key_len);
488 n->dev = dev;
489 if (dev)
490 dev_hold(dev);
491
492 if (tbl->pconstructor && tbl->pconstructor(n)) {
493 if (dev)
494 dev_put(dev);
495 kfree(n);
496 n = NULL;
497 goto out;
498 }
499
500 write_lock_bh(&tbl->lock);
501 n->next = tbl->phash_buckets[hash_val];
502 tbl->phash_buckets[hash_val] = n;
503 write_unlock_bh(&tbl->lock);
504out:
505 return n;
506}
507
508
509int pneigh_delete(struct neigh_table *tbl, const void *pkey,
510 struct net_device *dev)
511{
512 struct pneigh_entry *n, **np;
513 int key_len = tbl->key_len;
514 u32 hash_val = *(u32 *)(pkey + key_len - 4);
515
516 hash_val ^= (hash_val >> 16);
517 hash_val ^= hash_val >> 8;
518 hash_val ^= hash_val >> 4;
519 hash_val &= PNEIGH_HASHMASK;
520
521 write_lock_bh(&tbl->lock);
522 for (np = &tbl->phash_buckets[hash_val]; (n = *np) != NULL;
523 np = &n->next) {
524 if (!memcmp(n->key, pkey, key_len) && n->dev == dev) {
525 *np = n->next;
526 write_unlock_bh(&tbl->lock);
527 if (tbl->pdestructor)
528 tbl->pdestructor(n);
529 if (n->dev)
530 dev_put(n->dev);
531 kfree(n);
532 return 0;
533 }
534 }
535 write_unlock_bh(&tbl->lock);
536 return -ENOENT;
537}
538
539static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
540{
541 struct pneigh_entry *n, **np;
542 u32 h;
543
544 for (h = 0; h <= PNEIGH_HASHMASK; h++) {
545 np = &tbl->phash_buckets[h];
546 while ((n = *np) != NULL) {
547 if (!dev || n->dev == dev) {
548 *np = n->next;
549 if (tbl->pdestructor)
550 tbl->pdestructor(n);
551 if (n->dev)
552 dev_put(n->dev);
553 kfree(n);
554 continue;
555 }
556 np = &n->next;
557 }
558 }
559 return -ENOENT;
560}
561
562
563/*
564 * neighbour must already be out of the table;
565 *
566 */
567void neigh_destroy(struct neighbour *neigh)
568{
569 struct hh_cache *hh;
570
571 NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
572
573 if (!neigh->dead) {
574 printk(KERN_WARNING
575 "Destroying alive neighbour %p\n", neigh);
576 dump_stack();
577 return;
578 }
579
580 if (neigh_del_timer(neigh))
581 printk(KERN_WARNING "Impossible event.\n");
582
583 while ((hh = neigh->hh) != NULL) {
584 neigh->hh = hh->hh_next;
585 hh->hh_next = NULL;
Stephen Hemminger3644f0c2006-12-07 15:08:17 -0800586
587 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 hh->hh_output = neigh_blackhole;
Stephen Hemminger3644f0c2006-12-07 15:08:17 -0800589 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 if (atomic_dec_and_test(&hh->hh_refcnt))
591 kfree(hh);
592 }
593
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 skb_queue_purge(&neigh->arp_queue);
595
596 dev_put(neigh->dev);
597 neigh_parms_put(neigh->parms);
598
599 NEIGH_PRINTK2("neigh %p is destroyed.\n", neigh);
600
601 atomic_dec(&neigh->tbl->entries);
602 kmem_cache_free(neigh->tbl->kmem_cachep, neigh);
603}
604
605/* Neighbour state is suspicious;
606 disable fast path.
607
608 Called with write_locked neigh.
609 */
610static void neigh_suspect(struct neighbour *neigh)
611{
612 struct hh_cache *hh;
613
614 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
615
616 neigh->output = neigh->ops->output;
617
618 for (hh = neigh->hh; hh; hh = hh->hh_next)
619 hh->hh_output = neigh->ops->output;
620}
621
622/* Neighbour state is OK;
623 enable fast path.
624
625 Called with write_locked neigh.
626 */
627static void neigh_connect(struct neighbour *neigh)
628{
629 struct hh_cache *hh;
630
631 NEIGH_PRINTK2("neigh %p is connected.\n", neigh);
632
633 neigh->output = neigh->ops->connected_output;
634
635 for (hh = neigh->hh; hh; hh = hh->hh_next)
636 hh->hh_output = neigh->ops->hh_output;
637}
638
639static void neigh_periodic_timer(unsigned long arg)
640{
641 struct neigh_table *tbl = (struct neigh_table *)arg;
642 struct neighbour *n, **np;
643 unsigned long expire, now = jiffies;
644
645 NEIGH_CACHE_STAT_INC(tbl, periodic_gc_runs);
646
647 write_lock(&tbl->lock);
648
649 /*
650 * periodically recompute ReachableTime from random function
651 */
652
653 if (time_after(now, tbl->last_rand + 300 * HZ)) {
654 struct neigh_parms *p;
655 tbl->last_rand = now;
656 for (p = &tbl->parms; p; p = p->next)
657 p->reachable_time =
658 neigh_rand_reach_time(p->base_reachable_time);
659 }
660
661 np = &tbl->hash_buckets[tbl->hash_chain_gc];
662 tbl->hash_chain_gc = ((tbl->hash_chain_gc + 1) & tbl->hash_mask);
663
664 while ((n = *np) != NULL) {
665 unsigned int state;
666
667 write_lock(&n->lock);
668
669 state = n->nud_state;
670 if (state & (NUD_PERMANENT | NUD_IN_TIMER)) {
671 write_unlock(&n->lock);
672 goto next_elt;
673 }
674
675 if (time_before(n->used, n->confirmed))
676 n->used = n->confirmed;
677
678 if (atomic_read(&n->refcnt) == 1 &&
679 (state == NUD_FAILED ||
680 time_after(now, n->used + n->parms->gc_staletime))) {
681 *np = n->next;
682 n->dead = 1;
683 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -0700684 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 continue;
686 }
687 write_unlock(&n->lock);
688
689next_elt:
690 np = &n->next;
691 }
692
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900693 /* Cycle through all hash buckets every base_reachable_time/2 ticks.
694 * ARP entry timeouts range from 1/2 base_reachable_time to 3/2
695 * base_reachable_time.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 */
697 expire = tbl->parms.base_reachable_time >> 1;
698 expire /= (tbl->hash_mask + 1);
699 if (!expire)
700 expire = 1;
701
Arjan van de Venf5a6e012007-02-05 17:59:51 -0800702 if (expire>HZ)
703 mod_timer(&tbl->gc_timer, round_jiffies(now + expire));
704 else
705 mod_timer(&tbl->gc_timer, now + expire);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 write_unlock(&tbl->lock);
708}
709
710static __inline__ int neigh_max_probes(struct neighbour *n)
711{
712 struct neigh_parms *p = n->parms;
713 return (n->nud_state & NUD_PROBE ?
714 p->ucast_probes :
715 p->ucast_probes + p->app_probes + p->mcast_probes);
716}
717
David S. Miller667347f2005-09-27 12:07:44 -0700718static inline void neigh_add_timer(struct neighbour *n, unsigned long when)
719{
720 if (unlikely(mod_timer(&n->timer, when))) {
721 printk("NEIGH: BUG, double timer add, state is %x\n",
722 n->nud_state);
Herbert Xu20375502005-10-23 16:11:39 +1000723 dump_stack();
David S. Miller667347f2005-09-27 12:07:44 -0700724 }
725}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726
727/* Called when a timer expires for a neighbour entry. */
728
729static void neigh_timer_handler(unsigned long arg)
730{
731 unsigned long now, next;
732 struct neighbour *neigh = (struct neighbour *)arg;
733 unsigned state;
734 int notify = 0;
735
736 write_lock(&neigh->lock);
737
738 state = neigh->nud_state;
739 now = jiffies;
740 next = now + HZ;
741
742 if (!(state & NUD_IN_TIMER)) {
743#ifndef CONFIG_SMP
744 printk(KERN_WARNING "neigh: timer & !nud_in_timer\n");
745#endif
746 goto out;
747 }
748
749 if (state & NUD_REACHABLE) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900750 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 neigh->confirmed + neigh->parms->reachable_time)) {
752 NEIGH_PRINTK2("neigh %p is still alive.\n", neigh);
753 next = neigh->confirmed + neigh->parms->reachable_time;
754 } else if (time_before_eq(now,
755 neigh->used + neigh->parms->delay_probe_time)) {
756 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
757 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800758 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 neigh_suspect(neigh);
760 next = now + neigh->parms->delay_probe_time;
761 } else {
762 NEIGH_PRINTK2("neigh %p is suspected.\n", neigh);
763 neigh->nud_state = NUD_STALE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800764 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 neigh_suspect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700766 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700767 }
768 } else if (state & NUD_DELAY) {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900769 if (time_before_eq(now,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 neigh->confirmed + neigh->parms->delay_probe_time)) {
771 NEIGH_PRINTK2("neigh %p is now reachable.\n", neigh);
772 neigh->nud_state = NUD_REACHABLE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800773 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 neigh_connect(neigh);
Tom Tucker8d717402006-07-30 20:43:36 -0700775 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 next = neigh->confirmed + neigh->parms->reachable_time;
777 } else {
778 NEIGH_PRINTK2("neigh %p is probed.\n", neigh);
779 neigh->nud_state = NUD_PROBE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800780 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 atomic_set(&neigh->probes, 0);
782 next = now + neigh->parms->retrans_time;
783 }
784 } else {
785 /* NUD_PROBE|NUD_INCOMPLETE */
786 next = now + neigh->parms->retrans_time;
787 }
788
789 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
790 atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) {
791 struct sk_buff *skb;
792
793 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800794 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 notify = 1;
796 NEIGH_CACHE_STAT_INC(neigh->tbl, res_failed);
797 NEIGH_PRINTK2("neigh %p is failed.\n", neigh);
798
799 /* It is very thin place. report_unreachable is very complicated
800 routine. Particularly, it can hit the same neighbour entry!
801
802 So that, we try to be accurate and avoid dead loop. --ANK
803 */
804 while (neigh->nud_state == NUD_FAILED &&
805 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
806 write_unlock(&neigh->lock);
807 neigh->ops->error_report(neigh, skb);
808 write_lock(&neigh->lock);
809 }
810 skb_queue_purge(&neigh->arp_queue);
811 }
812
813 if (neigh->nud_state & NUD_IN_TIMER) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 if (time_before(next, jiffies + HZ/2))
815 next = jiffies + HZ/2;
Herbert Xu6fb99742005-10-23 16:37:48 +1000816 if (!mod_timer(&neigh->timer, next))
817 neigh_hold(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700818 }
819 if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
820 struct sk_buff *skb = skb_peek(&neigh->arp_queue);
821 /* keep skb alive even if arp_queue overflows */
822 if (skb)
823 skb_get(skb);
824 write_unlock(&neigh->lock);
825 neigh->ops->solicit(neigh, skb);
826 atomic_inc(&neigh->probes);
827 if (skb)
828 kfree_skb(skb);
829 } else {
830out:
831 write_unlock(&neigh->lock);
832 }
Tom Tucker8d717402006-07-30 20:43:36 -0700833 if (notify)
834 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700835
836#ifdef CONFIG_ARPD
837 if (notify && neigh->parms->app_probes)
838 neigh_app_notify(neigh);
839#endif
840 neigh_release(neigh);
841}
842
843int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
844{
845 int rc;
846 unsigned long now;
847
848 write_lock_bh(&neigh->lock);
849
850 rc = 0;
851 if (neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))
852 goto out_unlock_bh;
853
854 now = jiffies;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900855
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 if (!(neigh->nud_state & (NUD_STALE | NUD_INCOMPLETE))) {
857 if (neigh->parms->mcast_probes + neigh->parms->app_probes) {
858 atomic_set(&neigh->probes, neigh->parms->ucast_probes);
859 neigh->nud_state = NUD_INCOMPLETE;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800860 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861 neigh_hold(neigh);
David S. Miller667347f2005-09-27 12:07:44 -0700862 neigh_add_timer(neigh, now + 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863 } else {
864 neigh->nud_state = NUD_FAILED;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800865 neigh->updated = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 write_unlock_bh(&neigh->lock);
867
868 if (skb)
869 kfree_skb(skb);
870 return 1;
871 }
872 } else if (neigh->nud_state & NUD_STALE) {
873 NEIGH_PRINTK2("neigh %p is delayed.\n", neigh);
874 neigh_hold(neigh);
875 neigh->nud_state = NUD_DELAY;
YOSHIFUJI Hideaki955aaa22006-03-20 16:52:52 -0800876 neigh->updated = jiffies;
David S. Miller667347f2005-09-27 12:07:44 -0700877 neigh_add_timer(neigh,
878 jiffies + neigh->parms->delay_probe_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879 }
880
881 if (neigh->nud_state == NUD_INCOMPLETE) {
882 if (skb) {
883 if (skb_queue_len(&neigh->arp_queue) >=
884 neigh->parms->queue_len) {
885 struct sk_buff *buff;
886 buff = neigh->arp_queue.next;
887 __skb_unlink(buff, &neigh->arp_queue);
888 kfree_skb(buff);
889 }
890 __skb_queue_tail(&neigh->arp_queue, skb);
891 }
892 rc = 1;
893 }
894out_unlock_bh:
895 write_unlock_bh(&neigh->lock);
896 return rc;
897}
898
Stephen Hemmingere92b43a2006-08-17 18:17:37 -0700899static void neigh_update_hhs(struct neighbour *neigh)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700900{
901 struct hh_cache *hh;
902 void (*update)(struct hh_cache*, struct net_device*, unsigned char *) =
903 neigh->dev->header_cache_update;
904
905 if (update) {
906 for (hh = neigh->hh; hh; hh = hh->hh_next) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -0800907 write_seqlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700908 update(hh, neigh->dev, neigh->ha);
Stephen Hemminger3644f0c2006-12-07 15:08:17 -0800909 write_sequnlock_bh(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 }
911 }
912}
913
914
915
916/* Generic update routine.
917 -- lladdr is new lladdr or NULL, if it is not supplied.
918 -- new is new state.
919 -- flags
920 NEIGH_UPDATE_F_OVERRIDE allows to override existing lladdr,
921 if it is different.
922 NEIGH_UPDATE_F_WEAK_OVERRIDE will suspect existing "connected"
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900923 lladdr instead of overriding it
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924 if it is different.
925 It also allows to retain current state
926 if lladdr is unchanged.
927 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
928
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900929 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 NTF_ROUTER flag.
931 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
932 a router.
933
934 Caller MUST hold reference count on the entry.
935 */
936
937int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
938 u32 flags)
939{
940 u8 old;
941 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 int notify = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943 struct net_device *dev;
944 int update_isrouter = 0;
945
946 write_lock_bh(&neigh->lock);
947
948 dev = neigh->dev;
949 old = neigh->nud_state;
950 err = -EPERM;
951
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900952 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953 (old & (NUD_NOARP | NUD_PERMANENT)))
954 goto out;
955
956 if (!(new & NUD_VALID)) {
957 neigh_del_timer(neigh);
958 if (old & NUD_CONNECTED)
959 neigh_suspect(neigh);
960 neigh->nud_state = new;
961 err = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 notify = old & NUD_VALID;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700963 goto out;
964 }
965
966 /* Compare new lladdr with cached one */
967 if (!dev->addr_len) {
968 /* First case: device needs no address. */
969 lladdr = neigh->ha;
970 } else if (lladdr) {
971 /* The second case: if something is already cached
972 and a new address is proposed:
973 - compare new & old
974 - if they are different, check override flag
975 */
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +0900976 if ((old & NUD_VALID) &&
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 !memcmp(lladdr, neigh->ha, dev->addr_len))
978 lladdr = neigh->ha;
979 } else {
980 /* No address is supplied; if we know something,
981 use it, otherwise discard the request.
982 */
983 err = -EINVAL;
984 if (!(old & NUD_VALID))
985 goto out;
986 lladdr = neigh->ha;
987 }
988
989 if (new & NUD_CONNECTED)
990 neigh->confirmed = jiffies;
991 neigh->updated = jiffies;
992
993 /* If entry was valid and address is not changed,
994 do not change entry state, if new one is STALE.
995 */
996 err = 0;
997 update_isrouter = flags & NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
998 if (old & NUD_VALID) {
999 if (lladdr != neigh->ha && !(flags & NEIGH_UPDATE_F_OVERRIDE)) {
1000 update_isrouter = 0;
1001 if ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) &&
1002 (old & NUD_CONNECTED)) {
1003 lladdr = neigh->ha;
1004 new = NUD_STALE;
1005 } else
1006 goto out;
1007 } else {
1008 if (lladdr == neigh->ha && new == NUD_STALE &&
1009 ((flags & NEIGH_UPDATE_F_WEAK_OVERRIDE) ||
1010 (old & NUD_CONNECTED))
1011 )
1012 new = old;
1013 }
1014 }
1015
1016 if (new != old) {
1017 neigh_del_timer(neigh);
1018 if (new & NUD_IN_TIMER) {
1019 neigh_hold(neigh);
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001020 neigh_add_timer(neigh, (jiffies +
1021 ((new & NUD_REACHABLE) ?
David S. Miller667347f2005-09-27 12:07:44 -07001022 neigh->parms->reachable_time :
1023 0)));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 }
1025 neigh->nud_state = new;
1026 }
1027
1028 if (lladdr != neigh->ha) {
1029 memcpy(&neigh->ha, lladdr, dev->addr_len);
1030 neigh_update_hhs(neigh);
1031 if (!(new & NUD_CONNECTED))
1032 neigh->confirmed = jiffies -
1033 (neigh->parms->base_reachable_time << 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001034 notify = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 }
1036 if (new == old)
1037 goto out;
1038 if (new & NUD_CONNECTED)
1039 neigh_connect(neigh);
1040 else
1041 neigh_suspect(neigh);
1042 if (!(old & NUD_VALID)) {
1043 struct sk_buff *skb;
1044
1045 /* Again: avoid dead loop if something went wrong */
1046
1047 while (neigh->nud_state & NUD_VALID &&
1048 (skb = __skb_dequeue(&neigh->arp_queue)) != NULL) {
1049 struct neighbour *n1 = neigh;
1050 write_unlock_bh(&neigh->lock);
1051 /* On shaper/eql skb->dst->neighbour != neigh :( */
1052 if (skb->dst && skb->dst->neighbour)
1053 n1 = skb->dst->neighbour;
1054 n1->output(skb);
1055 write_lock_bh(&neigh->lock);
1056 }
1057 skb_queue_purge(&neigh->arp_queue);
1058 }
1059out:
1060 if (update_isrouter) {
1061 neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1062 (neigh->flags | NTF_ROUTER) :
1063 (neigh->flags & ~NTF_ROUTER);
1064 }
1065 write_unlock_bh(&neigh->lock);
Tom Tucker8d717402006-07-30 20:43:36 -07001066
1067 if (notify)
1068 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069#ifdef CONFIG_ARPD
1070 if (notify && neigh->parms->app_probes)
1071 neigh_app_notify(neigh);
1072#endif
1073 return err;
1074}
1075
1076struct neighbour *neigh_event_ns(struct neigh_table *tbl,
1077 u8 *lladdr, void *saddr,
1078 struct net_device *dev)
1079{
1080 struct neighbour *neigh = __neigh_lookup(tbl, saddr, dev,
1081 lladdr || !dev->addr_len);
1082 if (neigh)
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001083 neigh_update(neigh, lladdr, NUD_STALE,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084 NEIGH_UPDATE_F_OVERRIDE);
1085 return neigh;
1086}
1087
1088static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst,
Al Virod77072e2006-09-28 14:20:34 -07001089 __be16 protocol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090{
1091 struct hh_cache *hh;
1092 struct net_device *dev = dst->dev;
1093
1094 for (hh = n->hh; hh; hh = hh->hh_next)
1095 if (hh->hh_type == protocol)
1096 break;
1097
Andrew Morton77d04bd2006-04-07 14:52:59 -07001098 if (!hh && (hh = kzalloc(sizeof(*hh), GFP_ATOMIC)) != NULL) {
Stephen Hemminger3644f0c2006-12-07 15:08:17 -08001099 seqlock_init(&hh->hh_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 hh->hh_type = protocol;
1101 atomic_set(&hh->hh_refcnt, 0);
1102 hh->hh_next = NULL;
1103 if (dev->hard_header_cache(n, hh)) {
1104 kfree(hh);
1105 hh = NULL;
1106 } else {
1107 atomic_inc(&hh->hh_refcnt);
1108 hh->hh_next = n->hh;
1109 n->hh = hh;
1110 if (n->nud_state & NUD_CONNECTED)
1111 hh->hh_output = n->ops->hh_output;
1112 else
1113 hh->hh_output = n->ops->output;
1114 }
1115 }
1116 if (hh) {
1117 atomic_inc(&hh->hh_refcnt);
1118 dst->hh = hh;
1119 }
1120}
1121
1122/* This function can be used in contexts, where only old dev_queue_xmit
1123 worked, f.e. if you want to override normal output path (eql, shaper),
1124 but resolution is not made yet.
1125 */
1126
1127int neigh_compat_output(struct sk_buff *skb)
1128{
1129 struct net_device *dev = skb->dev;
1130
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001131 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132
1133 if (dev->hard_header &&
1134 dev->hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001135 skb->len) < 0 &&
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 dev->rebuild_header(skb))
1137 return 0;
1138
1139 return dev_queue_xmit(skb);
1140}
1141
1142/* Slow and careful. */
1143
1144int neigh_resolve_output(struct sk_buff *skb)
1145{
1146 struct dst_entry *dst = skb->dst;
1147 struct neighbour *neigh;
1148 int rc = 0;
1149
1150 if (!dst || !(neigh = dst->neighbour))
1151 goto discard;
1152
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001153 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154
1155 if (!neigh_event_send(neigh, skb)) {
1156 int err;
1157 struct net_device *dev = neigh->dev;
1158 if (dev->hard_header_cache && !dst->hh) {
1159 write_lock_bh(&neigh->lock);
1160 if (!dst->hh)
1161 neigh_hh_init(neigh, dst, dst->ops->protocol);
1162 err = dev->hard_header(skb, dev, ntohs(skb->protocol),
1163 neigh->ha, NULL, skb->len);
1164 write_unlock_bh(&neigh->lock);
1165 } else {
1166 read_lock_bh(&neigh->lock);
1167 err = dev->hard_header(skb, dev, ntohs(skb->protocol),
1168 neigh->ha, NULL, skb->len);
1169 read_unlock_bh(&neigh->lock);
1170 }
1171 if (err >= 0)
1172 rc = neigh->ops->queue_xmit(skb);
1173 else
1174 goto out_kfree_skb;
1175 }
1176out:
1177 return rc;
1178discard:
1179 NEIGH_PRINTK1("neigh_resolve_output: dst=%p neigh=%p\n",
1180 dst, dst ? dst->neighbour : NULL);
1181out_kfree_skb:
1182 rc = -EINVAL;
1183 kfree_skb(skb);
1184 goto out;
1185}
1186
1187/* As fast as possible without hh cache */
1188
1189int neigh_connected_output(struct sk_buff *skb)
1190{
1191 int err;
1192 struct dst_entry *dst = skb->dst;
1193 struct neighbour *neigh = dst->neighbour;
1194 struct net_device *dev = neigh->dev;
1195
Arnaldo Carvalho de Melobbe735e2007-03-10 22:16:10 -03001196 __skb_pull(skb, skb_network_offset(skb));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197
1198 read_lock_bh(&neigh->lock);
1199 err = dev->hard_header(skb, dev, ntohs(skb->protocol),
1200 neigh->ha, NULL, skb->len);
1201 read_unlock_bh(&neigh->lock);
1202 if (err >= 0)
1203 err = neigh->ops->queue_xmit(skb);
1204 else {
1205 err = -EINVAL;
1206 kfree_skb(skb);
1207 }
1208 return err;
1209}
1210
1211static void neigh_proxy_process(unsigned long arg)
1212{
1213 struct neigh_table *tbl = (struct neigh_table *)arg;
1214 long sched_next = 0;
1215 unsigned long now = jiffies;
1216 struct sk_buff *skb;
1217
1218 spin_lock(&tbl->proxy_queue.lock);
1219
1220 skb = tbl->proxy_queue.next;
1221
1222 while (skb != (struct sk_buff *)&tbl->proxy_queue) {
1223 struct sk_buff *back = skb;
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001224 long tdif = NEIGH_CB(back)->sched_next - now;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225
1226 skb = skb->next;
1227 if (tdif <= 0) {
1228 struct net_device *dev = back->dev;
1229 __skb_unlink(back, &tbl->proxy_queue);
1230 if (tbl->proxy_redo && netif_running(dev))
1231 tbl->proxy_redo(back);
1232 else
1233 kfree_skb(back);
1234
1235 dev_put(dev);
1236 } else if (!sched_next || tdif < sched_next)
1237 sched_next = tdif;
1238 }
1239 del_timer(&tbl->proxy_timer);
1240 if (sched_next)
1241 mod_timer(&tbl->proxy_timer, jiffies + sched_next);
1242 spin_unlock(&tbl->proxy_queue.lock);
1243}
1244
1245void pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
1246 struct sk_buff *skb)
1247{
1248 unsigned long now = jiffies;
1249 unsigned long sched_next = now + (net_random() % p->proxy_delay);
1250
1251 if (tbl->proxy_queue.qlen > p->proxy_qlen) {
1252 kfree_skb(skb);
1253 return;
1254 }
Patrick McHardya61bbcf2005-08-14 17:24:31 -07001255
1256 NEIGH_CB(skb)->sched_next = sched_next;
1257 NEIGH_CB(skb)->flags |= LOCALLY_ENQUEUED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001258
1259 spin_lock(&tbl->proxy_queue.lock);
1260 if (del_timer(&tbl->proxy_timer)) {
1261 if (time_before(tbl->proxy_timer.expires, sched_next))
1262 sched_next = tbl->proxy_timer.expires;
1263 }
1264 dst_release(skb->dst);
1265 skb->dst = NULL;
1266 dev_hold(skb->dev);
1267 __skb_queue_tail(&tbl->proxy_queue, skb);
1268 mod_timer(&tbl->proxy_timer, sched_next);
1269 spin_unlock(&tbl->proxy_queue.lock);
1270}
1271
1272
1273struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
1274 struct neigh_table *tbl)
1275{
Arnaldo Carvalho de Melob1a98bf2006-11-21 01:15:32 -02001276 struct neigh_parms *p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277
1278 if (p) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 p->tbl = tbl;
1280 atomic_set(&p->refcnt, 1);
1281 INIT_RCU_HEAD(&p->rcu_head);
1282 p->reachable_time =
1283 neigh_rand_reach_time(p->base_reachable_time);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001284 if (dev) {
1285 if (dev->neigh_setup && dev->neigh_setup(dev, p)) {
1286 kfree(p);
1287 return NULL;
1288 }
1289
1290 dev_hold(dev);
1291 p->dev = dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001292 }
1293 p->sysctl_table = NULL;
1294 write_lock_bh(&tbl->lock);
1295 p->next = tbl->parms.next;
1296 tbl->parms.next = p;
1297 write_unlock_bh(&tbl->lock);
1298 }
1299 return p;
1300}
1301
1302static void neigh_rcu_free_parms(struct rcu_head *head)
1303{
1304 struct neigh_parms *parms =
1305 container_of(head, struct neigh_parms, rcu_head);
1306
1307 neigh_parms_put(parms);
1308}
1309
1310void neigh_parms_release(struct neigh_table *tbl, struct neigh_parms *parms)
1311{
1312 struct neigh_parms **p;
1313
1314 if (!parms || parms == &tbl->parms)
1315 return;
1316 write_lock_bh(&tbl->lock);
1317 for (p = &tbl->parms.next; *p; p = &(*p)->next) {
1318 if (*p == parms) {
1319 *p = parms->next;
1320 parms->dead = 1;
1321 write_unlock_bh(&tbl->lock);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001322 if (parms->dev)
1323 dev_put(parms->dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001324 call_rcu(&parms->rcu_head, neigh_rcu_free_parms);
1325 return;
1326 }
1327 }
1328 write_unlock_bh(&tbl->lock);
1329 NEIGH_PRINTK1("neigh_parms_release: not found\n");
1330}
1331
1332void neigh_parms_destroy(struct neigh_parms *parms)
1333{
1334 kfree(parms);
1335}
1336
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001337static struct lock_class_key neigh_table_proxy_queue_class;
1338
Simon Kelleybd89efc2006-05-12 14:56:08 -07001339void neigh_table_init_no_netlink(struct neigh_table *tbl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340{
1341 unsigned long now = jiffies;
1342 unsigned long phsize;
1343
1344 atomic_set(&tbl->parms.refcnt, 1);
1345 INIT_RCU_HEAD(&tbl->parms.rcu_head);
1346 tbl->parms.reachable_time =
1347 neigh_rand_reach_time(tbl->parms.base_reachable_time);
1348
1349 if (!tbl->kmem_cachep)
Alexey Dobriyane5d679f2006-08-26 19:25:52 -07001350 tbl->kmem_cachep =
1351 kmem_cache_create(tbl->id, tbl->entry_size, 0,
1352 SLAB_HWCACHE_ALIGN|SLAB_PANIC,
Paul Mundt20c2df82007-07-20 10:11:58 +09001353 NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001354 tbl->stats = alloc_percpu(struct neigh_statistics);
1355 if (!tbl->stats)
1356 panic("cannot create neighbour cache statistics");
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001357
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358#ifdef CONFIG_PROC_FS
1359 tbl->pde = create_proc_entry(tbl->id, 0, proc_net_stat);
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001360 if (!tbl->pde)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361 panic("cannot create neighbour proc dir entry");
1362 tbl->pde->proc_fops = &neigh_stat_seq_fops;
1363 tbl->pde->data = tbl;
1364#endif
1365
1366 tbl->hash_mask = 1;
1367 tbl->hash_buckets = neigh_hash_alloc(tbl->hash_mask + 1);
1368
1369 phsize = (PNEIGH_HASHMASK + 1) * sizeof(struct pneigh_entry *);
Andrew Morton77d04bd2006-04-07 14:52:59 -07001370 tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371
1372 if (!tbl->hash_buckets || !tbl->phash_buckets)
1373 panic("cannot allocate neighbour cache hashes");
1374
Linus Torvalds1da177e2005-04-16 15:20:36 -07001375 get_random_bytes(&tbl->hash_rnd, sizeof(tbl->hash_rnd));
1376
1377 rwlock_init(&tbl->lock);
1378 init_timer(&tbl->gc_timer);
1379 tbl->gc_timer.data = (unsigned long)tbl;
1380 tbl->gc_timer.function = neigh_periodic_timer;
1381 tbl->gc_timer.expires = now + 1;
1382 add_timer(&tbl->gc_timer);
1383
1384 init_timer(&tbl->proxy_timer);
1385 tbl->proxy_timer.data = (unsigned long)tbl;
1386 tbl->proxy_timer.function = neigh_proxy_process;
Pavel Emelianovc2ecba72007-04-17 12:45:31 -07001387 skb_queue_head_init_class(&tbl->proxy_queue,
1388 &neigh_table_proxy_queue_class);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001389
1390 tbl->last_flush = now;
1391 tbl->last_rand = now + tbl->parms.reachable_time * 20;
Simon Kelleybd89efc2006-05-12 14:56:08 -07001392}
1393
1394void neigh_table_init(struct neigh_table *tbl)
1395{
1396 struct neigh_table *tmp;
1397
1398 neigh_table_init_no_netlink(tbl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399 write_lock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001400 for (tmp = neigh_tables; tmp; tmp = tmp->next) {
1401 if (tmp->family == tbl->family)
1402 break;
1403 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001404 tbl->next = neigh_tables;
1405 neigh_tables = tbl;
1406 write_unlock(&neigh_tbl_lock);
Simon Kelleybd89efc2006-05-12 14:56:08 -07001407
1408 if (unlikely(tmp)) {
1409 printk(KERN_ERR "NEIGH: Registering multiple tables for "
1410 "family %d\n", tbl->family);
1411 dump_stack();
1412 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413}
1414
1415int neigh_table_clear(struct neigh_table *tbl)
1416{
1417 struct neigh_table **tp;
1418
1419 /* It is not clean... Fix it to unload IPv6 module safely */
1420 del_timer_sync(&tbl->gc_timer);
1421 del_timer_sync(&tbl->proxy_timer);
1422 pneigh_queue_purge(&tbl->proxy_queue);
1423 neigh_ifdown(tbl, NULL);
1424 if (atomic_read(&tbl->entries))
1425 printk(KERN_CRIT "neighbour leakage\n");
1426 write_lock(&neigh_tbl_lock);
1427 for (tp = &neigh_tables; *tp; tp = &(*tp)->next) {
1428 if (*tp == tbl) {
1429 *tp = tbl->next;
1430 break;
1431 }
1432 }
1433 write_unlock(&neigh_tbl_lock);
1434
1435 neigh_hash_free(tbl->hash_buckets, tbl->hash_mask + 1);
1436 tbl->hash_buckets = NULL;
1437
1438 kfree(tbl->phash_buckets);
1439 tbl->phash_buckets = NULL;
1440
Kirill Korotaev3fcde742006-09-01 01:34:10 -07001441 free_percpu(tbl->stats);
1442 tbl->stats = NULL;
1443
Linus Torvalds1da177e2005-04-16 15:20:36 -07001444 return 0;
1445}
1446
Thomas Grafc8822a42007-03-22 11:50:06 -07001447static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001448{
Thomas Grafa14a49d2006-08-07 17:53:08 -07001449 struct ndmsg *ndm;
1450 struct nlattr *dst_attr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 struct neigh_table *tbl;
1452 struct net_device *dev = NULL;
Thomas Grafa14a49d2006-08-07 17:53:08 -07001453 int err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001454
Thomas Grafa14a49d2006-08-07 17:53:08 -07001455 if (nlmsg_len(nlh) < sizeof(*ndm))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456 goto out;
1457
Thomas Grafa14a49d2006-08-07 17:53:08 -07001458 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1459 if (dst_attr == NULL)
1460 goto out;
1461
1462 ndm = nlmsg_data(nlh);
1463 if (ndm->ndm_ifindex) {
1464 dev = dev_get_by_index(ndm->ndm_ifindex);
1465 if (dev == NULL) {
1466 err = -ENODEV;
1467 goto out;
1468 }
1469 }
1470
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 read_lock(&neigh_tbl_lock);
1472 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001473 struct neighbour *neigh;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001474
1475 if (tbl->family != ndm->ndm_family)
1476 continue;
1477 read_unlock(&neigh_tbl_lock);
1478
Thomas Grafa14a49d2006-08-07 17:53:08 -07001479 if (nla_len(dst_attr) < tbl->key_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001480 goto out_dev_put;
1481
1482 if (ndm->ndm_flags & NTF_PROXY) {
Thomas Grafa14a49d2006-08-07 17:53:08 -07001483 err = pneigh_delete(tbl, nla_data(dst_attr), dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484 goto out_dev_put;
1485 }
1486
Thomas Grafa14a49d2006-08-07 17:53:08 -07001487 if (dev == NULL)
1488 goto out_dev_put;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001489
Thomas Grafa14a49d2006-08-07 17:53:08 -07001490 neigh = neigh_lookup(tbl, nla_data(dst_attr), dev);
1491 if (neigh == NULL) {
1492 err = -ENOENT;
1493 goto out_dev_put;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 }
Thomas Grafa14a49d2006-08-07 17:53:08 -07001495
1496 err = neigh_update(neigh, NULL, NUD_FAILED,
1497 NEIGH_UPDATE_F_OVERRIDE |
1498 NEIGH_UPDATE_F_ADMIN);
1499 neigh_release(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 goto out_dev_put;
1501 }
1502 read_unlock(&neigh_tbl_lock);
Thomas Grafa14a49d2006-08-07 17:53:08 -07001503 err = -EAFNOSUPPORT;
1504
Linus Torvalds1da177e2005-04-16 15:20:36 -07001505out_dev_put:
1506 if (dev)
1507 dev_put(dev);
1508out:
1509 return err;
1510}
1511
Thomas Grafc8822a42007-03-22 11:50:06 -07001512static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001513{
Thomas Graf5208deb2006-08-07 17:55:40 -07001514 struct ndmsg *ndm;
1515 struct nlattr *tb[NDA_MAX+1];
Linus Torvalds1da177e2005-04-16 15:20:36 -07001516 struct neigh_table *tbl;
1517 struct net_device *dev = NULL;
Thomas Graf5208deb2006-08-07 17:55:40 -07001518 int err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Thomas Graf5208deb2006-08-07 17:55:40 -07001520 err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
1521 if (err < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522 goto out;
1523
Thomas Graf5208deb2006-08-07 17:55:40 -07001524 err = -EINVAL;
1525 if (tb[NDA_DST] == NULL)
1526 goto out;
1527
1528 ndm = nlmsg_data(nlh);
1529 if (ndm->ndm_ifindex) {
1530 dev = dev_get_by_index(ndm->ndm_ifindex);
1531 if (dev == NULL) {
1532 err = -ENODEV;
1533 goto out;
1534 }
1535
1536 if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
1537 goto out_dev_put;
1538 }
1539
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 read_lock(&neigh_tbl_lock);
1541 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
Thomas Graf5208deb2006-08-07 17:55:40 -07001542 int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1543 struct neighbour *neigh;
1544 void *dst, *lladdr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
1546 if (tbl->family != ndm->ndm_family)
1547 continue;
1548 read_unlock(&neigh_tbl_lock);
1549
Thomas Graf5208deb2006-08-07 17:55:40 -07001550 if (nla_len(tb[NDA_DST]) < tbl->key_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551 goto out_dev_put;
Thomas Graf5208deb2006-08-07 17:55:40 -07001552 dst = nla_data(tb[NDA_DST]);
1553 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554
1555 if (ndm->ndm_flags & NTF_PROXY) {
Ville Nuorvala62dd9312006-09-22 14:43:19 -07001556 struct pneigh_entry *pn;
1557
1558 err = -ENOBUFS;
1559 pn = pneigh_lookup(tbl, dst, dev, 1);
1560 if (pn) {
1561 pn->flags = ndm->ndm_flags;
1562 err = 0;
1563 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564 goto out_dev_put;
1565 }
1566
Thomas Graf5208deb2006-08-07 17:55:40 -07001567 if (dev == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 goto out_dev_put;
Thomas Graf5208deb2006-08-07 17:55:40 -07001569
1570 neigh = neigh_lookup(tbl, dst, dev);
1571 if (neigh == NULL) {
1572 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
1573 err = -ENOENT;
1574 goto out_dev_put;
1575 }
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001576
Thomas Graf5208deb2006-08-07 17:55:40 -07001577 neigh = __neigh_lookup_errno(tbl, dst, dev);
1578 if (IS_ERR(neigh)) {
1579 err = PTR_ERR(neigh);
1580 goto out_dev_put;
1581 }
1582 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 if (nlh->nlmsg_flags & NLM_F_EXCL) {
1584 err = -EEXIST;
Thomas Graf5208deb2006-08-07 17:55:40 -07001585 neigh_release(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 goto out_dev_put;
1587 }
Thomas Graf5208deb2006-08-07 17:55:40 -07001588
1589 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1590 flags &= ~NEIGH_UPDATE_F_OVERRIDE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 }
1592
Thomas Graf5208deb2006-08-07 17:55:40 -07001593 err = neigh_update(neigh, lladdr, ndm->ndm_state, flags);
1594 neigh_release(neigh);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001595 goto out_dev_put;
1596 }
1597
1598 read_unlock(&neigh_tbl_lock);
Thomas Graf5208deb2006-08-07 17:55:40 -07001599 err = -EAFNOSUPPORT;
1600
Linus Torvalds1da177e2005-04-16 15:20:36 -07001601out_dev_put:
1602 if (dev)
1603 dev_put(dev);
1604out:
1605 return err;
1606}
1607
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001608static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
1609{
Thomas Grafca860fb2006-08-07 18:00:18 -07001610 struct nlattr *nest;
1611
1612 nest = nla_nest_start(skb, NDTA_PARMS);
1613 if (nest == NULL)
1614 return -ENOBUFS;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001615
1616 if (parms->dev)
Thomas Grafca860fb2006-08-07 18:00:18 -07001617 NLA_PUT_U32(skb, NDTPA_IFINDEX, parms->dev->ifindex);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001618
Thomas Grafca860fb2006-08-07 18:00:18 -07001619 NLA_PUT_U32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt));
1620 NLA_PUT_U32(skb, NDTPA_QUEUE_LEN, parms->queue_len);
1621 NLA_PUT_U32(skb, NDTPA_PROXY_QLEN, parms->proxy_qlen);
1622 NLA_PUT_U32(skb, NDTPA_APP_PROBES, parms->app_probes);
1623 NLA_PUT_U32(skb, NDTPA_UCAST_PROBES, parms->ucast_probes);
1624 NLA_PUT_U32(skb, NDTPA_MCAST_PROBES, parms->mcast_probes);
1625 NLA_PUT_MSECS(skb, NDTPA_REACHABLE_TIME, parms->reachable_time);
1626 NLA_PUT_MSECS(skb, NDTPA_BASE_REACHABLE_TIME,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001627 parms->base_reachable_time);
Thomas Grafca860fb2006-08-07 18:00:18 -07001628 NLA_PUT_MSECS(skb, NDTPA_GC_STALETIME, parms->gc_staletime);
1629 NLA_PUT_MSECS(skb, NDTPA_DELAY_PROBE_TIME, parms->delay_probe_time);
1630 NLA_PUT_MSECS(skb, NDTPA_RETRANS_TIME, parms->retrans_time);
1631 NLA_PUT_MSECS(skb, NDTPA_ANYCAST_DELAY, parms->anycast_delay);
1632 NLA_PUT_MSECS(skb, NDTPA_PROXY_DELAY, parms->proxy_delay);
1633 NLA_PUT_MSECS(skb, NDTPA_LOCKTIME, parms->locktime);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001634
Thomas Grafca860fb2006-08-07 18:00:18 -07001635 return nla_nest_end(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001636
Thomas Grafca860fb2006-08-07 18:00:18 -07001637nla_put_failure:
1638 return nla_nest_cancel(skb, nest);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001639}
1640
Thomas Grafca860fb2006-08-07 18:00:18 -07001641static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
1642 u32 pid, u32 seq, int type, int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001643{
1644 struct nlmsghdr *nlh;
1645 struct ndtmsg *ndtmsg;
1646
Thomas Grafca860fb2006-08-07 18:00:18 -07001647 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1648 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001649 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001650
Thomas Grafca860fb2006-08-07 18:00:18 -07001651 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001652
1653 read_lock_bh(&tbl->lock);
1654 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001655 ndtmsg->ndtm_pad1 = 0;
1656 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001657
Thomas Grafca860fb2006-08-07 18:00:18 -07001658 NLA_PUT_STRING(skb, NDTA_NAME, tbl->id);
1659 NLA_PUT_MSECS(skb, NDTA_GC_INTERVAL, tbl->gc_interval);
1660 NLA_PUT_U32(skb, NDTA_THRESH1, tbl->gc_thresh1);
1661 NLA_PUT_U32(skb, NDTA_THRESH2, tbl->gc_thresh2);
1662 NLA_PUT_U32(skb, NDTA_THRESH3, tbl->gc_thresh3);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001663
1664 {
1665 unsigned long now = jiffies;
1666 unsigned int flush_delta = now - tbl->last_flush;
1667 unsigned int rand_delta = now - tbl->last_rand;
1668
1669 struct ndt_config ndc = {
1670 .ndtc_key_len = tbl->key_len,
1671 .ndtc_entry_size = tbl->entry_size,
1672 .ndtc_entries = atomic_read(&tbl->entries),
1673 .ndtc_last_flush = jiffies_to_msecs(flush_delta),
1674 .ndtc_last_rand = jiffies_to_msecs(rand_delta),
1675 .ndtc_hash_rnd = tbl->hash_rnd,
1676 .ndtc_hash_mask = tbl->hash_mask,
1677 .ndtc_hash_chain_gc = tbl->hash_chain_gc,
1678 .ndtc_proxy_qlen = tbl->proxy_queue.qlen,
1679 };
1680
Thomas Grafca860fb2006-08-07 18:00:18 -07001681 NLA_PUT(skb, NDTA_CONFIG, sizeof(ndc), &ndc);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001682 }
1683
1684 {
1685 int cpu;
1686 struct ndt_stats ndst;
1687
1688 memset(&ndst, 0, sizeof(ndst));
1689
KAMEZAWA Hiroyuki6f912042006-04-10 22:52:50 -07001690 for_each_possible_cpu(cpu) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001691 struct neigh_statistics *st;
1692
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001693 st = per_cpu_ptr(tbl->stats, cpu);
1694 ndst.ndts_allocs += st->allocs;
1695 ndst.ndts_destroys += st->destroys;
1696 ndst.ndts_hash_grows += st->hash_grows;
1697 ndst.ndts_res_failed += st->res_failed;
1698 ndst.ndts_lookups += st->lookups;
1699 ndst.ndts_hits += st->hits;
1700 ndst.ndts_rcv_probes_mcast += st->rcv_probes_mcast;
1701 ndst.ndts_rcv_probes_ucast += st->rcv_probes_ucast;
1702 ndst.ndts_periodic_gc_runs += st->periodic_gc_runs;
1703 ndst.ndts_forced_gc_runs += st->forced_gc_runs;
1704 }
1705
Thomas Grafca860fb2006-08-07 18:00:18 -07001706 NLA_PUT(skb, NDTA_STATS, sizeof(ndst), &ndst);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001707 }
1708
1709 BUG_ON(tbl->parms.dev);
1710 if (neightbl_fill_parms(skb, &tbl->parms) < 0)
Thomas Grafca860fb2006-08-07 18:00:18 -07001711 goto nla_put_failure;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001712
1713 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001714 return nlmsg_end(skb, nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001715
Thomas Grafca860fb2006-08-07 18:00:18 -07001716nla_put_failure:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001717 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001718 nlmsg_cancel(skb, nlh);
1719 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001720}
1721
Thomas Grafca860fb2006-08-07 18:00:18 -07001722static int neightbl_fill_param_info(struct sk_buff *skb,
1723 struct neigh_table *tbl,
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001724 struct neigh_parms *parms,
Thomas Grafca860fb2006-08-07 18:00:18 -07001725 u32 pid, u32 seq, int type,
1726 unsigned int flags)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001727{
1728 struct ndtmsg *ndtmsg;
1729 struct nlmsghdr *nlh;
1730
Thomas Grafca860fb2006-08-07 18:00:18 -07001731 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
1732 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001733 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001734
Thomas Grafca860fb2006-08-07 18:00:18 -07001735 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001736
1737 read_lock_bh(&tbl->lock);
1738 ndtmsg->ndtm_family = tbl->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001739 ndtmsg->ndtm_pad1 = 0;
1740 ndtmsg->ndtm_pad2 = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001741
Thomas Grafca860fb2006-08-07 18:00:18 -07001742 if (nla_put_string(skb, NDTA_NAME, tbl->id) < 0 ||
1743 neightbl_fill_parms(skb, parms) < 0)
1744 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001745
1746 read_unlock_bh(&tbl->lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001747 return nlmsg_end(skb, nlh);
1748errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001749 read_unlock_bh(&tbl->lock);
Patrick McHardy26932562007-01-31 23:16:40 -08001750 nlmsg_cancel(skb, nlh);
1751 return -EMSGSIZE;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001752}
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001753
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001754static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
1755 int ifindex)
1756{
1757 struct neigh_parms *p;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001758
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001759 for (p = &tbl->parms; p; p = p->next)
1760 if ((p->dev && p->dev->ifindex == ifindex) ||
1761 (!p->dev && !ifindex))
1762 return p;
1763
1764 return NULL;
1765}
1766
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001767static const struct nla_policy nl_neightbl_policy[NDTA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001768 [NDTA_NAME] = { .type = NLA_STRING },
1769 [NDTA_THRESH1] = { .type = NLA_U32 },
1770 [NDTA_THRESH2] = { .type = NLA_U32 },
1771 [NDTA_THRESH3] = { .type = NLA_U32 },
1772 [NDTA_GC_INTERVAL] = { .type = NLA_U64 },
1773 [NDTA_PARMS] = { .type = NLA_NESTED },
1774};
1775
Patrick McHardyef7c79e2007-06-05 12:38:30 -07001776static const struct nla_policy nl_ntbl_parm_policy[NDTPA_MAX+1] = {
Thomas Graf6b3f8672006-08-07 17:58:53 -07001777 [NDTPA_IFINDEX] = { .type = NLA_U32 },
1778 [NDTPA_QUEUE_LEN] = { .type = NLA_U32 },
1779 [NDTPA_PROXY_QLEN] = { .type = NLA_U32 },
1780 [NDTPA_APP_PROBES] = { .type = NLA_U32 },
1781 [NDTPA_UCAST_PROBES] = { .type = NLA_U32 },
1782 [NDTPA_MCAST_PROBES] = { .type = NLA_U32 },
1783 [NDTPA_BASE_REACHABLE_TIME] = { .type = NLA_U64 },
1784 [NDTPA_GC_STALETIME] = { .type = NLA_U64 },
1785 [NDTPA_DELAY_PROBE_TIME] = { .type = NLA_U64 },
1786 [NDTPA_RETRANS_TIME] = { .type = NLA_U64 },
1787 [NDTPA_ANYCAST_DELAY] = { .type = NLA_U64 },
1788 [NDTPA_PROXY_DELAY] = { .type = NLA_U64 },
1789 [NDTPA_LOCKTIME] = { .type = NLA_U64 },
1790};
1791
Thomas Grafc8822a42007-03-22 11:50:06 -07001792static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001793{
1794 struct neigh_table *tbl;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001795 struct ndtmsg *ndtmsg;
1796 struct nlattr *tb[NDTA_MAX+1];
1797 int err;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001798
Thomas Graf6b3f8672006-08-07 17:58:53 -07001799 err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
1800 nl_neightbl_policy);
1801 if (err < 0)
1802 goto errout;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001803
Thomas Graf6b3f8672006-08-07 17:58:53 -07001804 if (tb[NDTA_NAME] == NULL) {
1805 err = -EINVAL;
1806 goto errout;
1807 }
1808
1809 ndtmsg = nlmsg_data(nlh);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001810 read_lock(&neigh_tbl_lock);
1811 for (tbl = neigh_tables; tbl; tbl = tbl->next) {
1812 if (ndtmsg->ndtm_family && tbl->family != ndtmsg->ndtm_family)
1813 continue;
1814
Thomas Graf6b3f8672006-08-07 17:58:53 -07001815 if (nla_strcmp(tb[NDTA_NAME], tbl->id) == 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001816 break;
1817 }
1818
1819 if (tbl == NULL) {
1820 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001821 goto errout_locked;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001822 }
1823
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09001824 /*
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001825 * We acquire tbl->lock to be nice to the periodic timers and
1826 * make sure they always see a consistent set of values.
1827 */
1828 write_lock_bh(&tbl->lock);
1829
Thomas Graf6b3f8672006-08-07 17:58:53 -07001830 if (tb[NDTA_PARMS]) {
1831 struct nlattr *tbp[NDTPA_MAX+1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001832 struct neigh_parms *p;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001833 int i, ifindex = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001834
Thomas Graf6b3f8672006-08-07 17:58:53 -07001835 err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
1836 nl_ntbl_parm_policy);
1837 if (err < 0)
1838 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001839
Thomas Graf6b3f8672006-08-07 17:58:53 -07001840 if (tbp[NDTPA_IFINDEX])
1841 ifindex = nla_get_u32(tbp[NDTPA_IFINDEX]);
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001842
1843 p = lookup_neigh_params(tbl, ifindex);
1844 if (p == NULL) {
1845 err = -ENOENT;
Thomas Graf6b3f8672006-08-07 17:58:53 -07001846 goto errout_tbl_lock;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001847 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001848
Thomas Graf6b3f8672006-08-07 17:58:53 -07001849 for (i = 1; i <= NDTPA_MAX; i++) {
1850 if (tbp[i] == NULL)
1851 continue;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001852
Thomas Graf6b3f8672006-08-07 17:58:53 -07001853 switch (i) {
1854 case NDTPA_QUEUE_LEN:
1855 p->queue_len = nla_get_u32(tbp[i]);
1856 break;
1857 case NDTPA_PROXY_QLEN:
1858 p->proxy_qlen = nla_get_u32(tbp[i]);
1859 break;
1860 case NDTPA_APP_PROBES:
1861 p->app_probes = nla_get_u32(tbp[i]);
1862 break;
1863 case NDTPA_UCAST_PROBES:
1864 p->ucast_probes = nla_get_u32(tbp[i]);
1865 break;
1866 case NDTPA_MCAST_PROBES:
1867 p->mcast_probes = nla_get_u32(tbp[i]);
1868 break;
1869 case NDTPA_BASE_REACHABLE_TIME:
1870 p->base_reachable_time = nla_get_msecs(tbp[i]);
1871 break;
1872 case NDTPA_GC_STALETIME:
1873 p->gc_staletime = nla_get_msecs(tbp[i]);
1874 break;
1875 case NDTPA_DELAY_PROBE_TIME:
1876 p->delay_probe_time = nla_get_msecs(tbp[i]);
1877 break;
1878 case NDTPA_RETRANS_TIME:
1879 p->retrans_time = nla_get_msecs(tbp[i]);
1880 break;
1881 case NDTPA_ANYCAST_DELAY:
1882 p->anycast_delay = nla_get_msecs(tbp[i]);
1883 break;
1884 case NDTPA_PROXY_DELAY:
1885 p->proxy_delay = nla_get_msecs(tbp[i]);
1886 break;
1887 case NDTPA_LOCKTIME:
1888 p->locktime = nla_get_msecs(tbp[i]);
1889 break;
1890 }
1891 }
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001892 }
1893
Thomas Graf6b3f8672006-08-07 17:58:53 -07001894 if (tb[NDTA_THRESH1])
1895 tbl->gc_thresh1 = nla_get_u32(tb[NDTA_THRESH1]);
1896
1897 if (tb[NDTA_THRESH2])
1898 tbl->gc_thresh2 = nla_get_u32(tb[NDTA_THRESH2]);
1899
1900 if (tb[NDTA_THRESH3])
1901 tbl->gc_thresh3 = nla_get_u32(tb[NDTA_THRESH3]);
1902
1903 if (tb[NDTA_GC_INTERVAL])
1904 tbl->gc_interval = nla_get_msecs(tb[NDTA_GC_INTERVAL]);
1905
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001906 err = 0;
1907
Thomas Graf6b3f8672006-08-07 17:58:53 -07001908errout_tbl_lock:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001909 write_unlock_bh(&tbl->lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001910errout_locked:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001911 read_unlock(&neigh_tbl_lock);
Thomas Graf6b3f8672006-08-07 17:58:53 -07001912errout:
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001913 return err;
1914}
1915
Thomas Grafc8822a42007-03-22 11:50:06 -07001916static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001917{
Thomas Grafca860fb2006-08-07 18:00:18 -07001918 int family, tidx, nidx = 0;
1919 int tbl_skip = cb->args[0];
1920 int neigh_skip = cb->args[1];
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001921 struct neigh_table *tbl;
1922
Thomas Grafca860fb2006-08-07 18:00:18 -07001923 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001924
1925 read_lock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001926 for (tbl = neigh_tables, tidx = 0; tbl; tbl = tbl->next, tidx++) {
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001927 struct neigh_parms *p;
1928
Thomas Grafca860fb2006-08-07 18:00:18 -07001929 if (tidx < tbl_skip || (family && tbl->family != family))
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001930 continue;
1931
Thomas Grafca860fb2006-08-07 18:00:18 -07001932 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).pid,
1933 cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
1934 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001935 break;
1936
Thomas Grafca860fb2006-08-07 18:00:18 -07001937 for (nidx = 0, p = tbl->parms.next; p; p = p->next, nidx++) {
1938 if (nidx < neigh_skip)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001939 continue;
1940
Thomas Grafca860fb2006-08-07 18:00:18 -07001941 if (neightbl_fill_param_info(skb, tbl, p,
1942 NETLINK_CB(cb->skb).pid,
1943 cb->nlh->nlmsg_seq,
1944 RTM_NEWNEIGHTBL,
1945 NLM_F_MULTI) <= 0)
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001946 goto out;
1947 }
1948
Thomas Grafca860fb2006-08-07 18:00:18 -07001949 neigh_skip = 0;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001950 }
1951out:
1952 read_unlock(&neigh_tbl_lock);
Thomas Grafca860fb2006-08-07 18:00:18 -07001953 cb->args[0] = tidx;
1954 cb->args[1] = nidx;
Thomas Grafc7fb64d2005-06-18 22:50:55 -07001955
1956 return skb->len;
1957}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958
Thomas Graf8b8aec52006-08-07 17:56:37 -07001959static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
1960 u32 pid, u32 seq, int type, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001961{
1962 unsigned long now = jiffies;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001963 struct nda_cacheinfo ci;
Thomas Graf8b8aec52006-08-07 17:56:37 -07001964 struct nlmsghdr *nlh;
1965 struct ndmsg *ndm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001966
Thomas Graf8b8aec52006-08-07 17:56:37 -07001967 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
1968 if (nlh == NULL)
Patrick McHardy26932562007-01-31 23:16:40 -08001969 return -EMSGSIZE;
Thomas Graf8b8aec52006-08-07 17:56:37 -07001970
1971 ndm = nlmsg_data(nlh);
1972 ndm->ndm_family = neigh->ops->family;
Patrick McHardy9ef1d4c2005-06-28 12:55:30 -07001973 ndm->ndm_pad1 = 0;
1974 ndm->ndm_pad2 = 0;
Thomas Graf8b8aec52006-08-07 17:56:37 -07001975 ndm->ndm_flags = neigh->flags;
1976 ndm->ndm_type = neigh->type;
1977 ndm->ndm_ifindex = neigh->dev->ifindex;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
Thomas Graf8b8aec52006-08-07 17:56:37 -07001979 NLA_PUT(skb, NDA_DST, neigh->tbl->key_len, neigh->primary_key);
1980
1981 read_lock_bh(&neigh->lock);
1982 ndm->ndm_state = neigh->nud_state;
1983 if ((neigh->nud_state & NUD_VALID) &&
1984 nla_put(skb, NDA_LLADDR, neigh->dev->addr_len, neigh->ha) < 0) {
1985 read_unlock_bh(&neigh->lock);
1986 goto nla_put_failure;
1987 }
1988
1989 ci.ndm_used = now - neigh->used;
1990 ci.ndm_confirmed = now - neigh->confirmed;
1991 ci.ndm_updated = now - neigh->updated;
1992 ci.ndm_refcnt = atomic_read(&neigh->refcnt) - 1;
1993 read_unlock_bh(&neigh->lock);
1994
1995 NLA_PUT_U32(skb, NDA_PROBES, atomic_read(&neigh->probes));
1996 NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
1997
1998 return nlmsg_end(skb, nlh);
1999
2000nla_put_failure:
Patrick McHardy26932562007-01-31 23:16:40 -08002001 nlmsg_cancel(skb, nlh);
2002 return -EMSGSIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002003}
2004
2005
2006static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2007 struct netlink_callback *cb)
2008{
2009 struct neighbour *n;
2010 int rc, h, s_h = cb->args[1];
2011 int idx, s_idx = idx = cb->args[2];
2012
Julian Anastasovc5e29462006-10-03 15:49:46 -07002013 read_lock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002014 for (h = 0; h <= tbl->hash_mask; h++) {
2015 if (h < s_h)
2016 continue;
2017 if (h > s_h)
2018 s_idx = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002019 for (n = tbl->hash_buckets[h], idx = 0; n; n = n->next, idx++) {
2020 if (idx < s_idx)
2021 continue;
2022 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).pid,
2023 cb->nlh->nlmsg_seq,
Jamal Hadi Salimb6544c02005-06-18 22:54:12 -07002024 RTM_NEWNEIGH,
2025 NLM_F_MULTI) <= 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002026 read_unlock_bh(&tbl->lock);
2027 rc = -1;
2028 goto out;
2029 }
2030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
Julian Anastasovc5e29462006-10-03 15:49:46 -07002032 read_unlock_bh(&tbl->lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033 rc = skb->len;
2034out:
2035 cb->args[1] = h;
2036 cb->args[2] = idx;
2037 return rc;
2038}
2039
Thomas Grafc8822a42007-03-22 11:50:06 -07002040static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002041{
2042 struct neigh_table *tbl;
2043 int t, family, s_t;
2044
2045 read_lock(&neigh_tbl_lock);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002046 family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002047 s_t = cb->args[0];
2048
2049 for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) {
2050 if (t < s_t || (family && tbl->family != family))
2051 continue;
2052 if (t > s_t)
2053 memset(&cb->args[1], 0, sizeof(cb->args) -
2054 sizeof(cb->args[0]));
2055 if (neigh_dump_table(tbl, skb, cb) < 0)
2056 break;
2057 }
2058 read_unlock(&neigh_tbl_lock);
2059
2060 cb->args[0] = t;
2061 return skb->len;
2062}
2063
2064void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
2065{
2066 int chain;
2067
2068 read_lock_bh(&tbl->lock);
2069 for (chain = 0; chain <= tbl->hash_mask; chain++) {
2070 struct neighbour *n;
2071
2072 for (n = tbl->hash_buckets[chain]; n; n = n->next)
2073 cb(n, cookie);
2074 }
2075 read_unlock_bh(&tbl->lock);
2076}
2077EXPORT_SYMBOL(neigh_for_each);
2078
2079/* The tbl->lock must be held as a writer and BH disabled. */
2080void __neigh_for_each_release(struct neigh_table *tbl,
2081 int (*cb)(struct neighbour *))
2082{
2083 int chain;
2084
2085 for (chain = 0; chain <= tbl->hash_mask; chain++) {
2086 struct neighbour *n, **np;
2087
2088 np = &tbl->hash_buckets[chain];
2089 while ((n = *np) != NULL) {
2090 int release;
2091
2092 write_lock(&n->lock);
2093 release = cb(n);
2094 if (release) {
2095 *np = n->next;
2096 n->dead = 1;
2097 } else
2098 np = &n->next;
2099 write_unlock(&n->lock);
Thomas Graf4f494552007-08-08 23:12:36 -07002100 if (release)
2101 neigh_cleanup_and_release(n);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102 }
2103 }
2104}
2105EXPORT_SYMBOL(__neigh_for_each_release);
2106
2107#ifdef CONFIG_PROC_FS
2108
2109static struct neighbour *neigh_get_first(struct seq_file *seq)
2110{
2111 struct neigh_seq_state *state = seq->private;
2112 struct neigh_table *tbl = state->tbl;
2113 struct neighbour *n = NULL;
2114 int bucket = state->bucket;
2115
2116 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
2117 for (bucket = 0; bucket <= tbl->hash_mask; bucket++) {
2118 n = tbl->hash_buckets[bucket];
2119
2120 while (n) {
2121 if (state->neigh_sub_iter) {
2122 loff_t fakep = 0;
2123 void *v;
2124
2125 v = state->neigh_sub_iter(state, n, &fakep);
2126 if (!v)
2127 goto next;
2128 }
2129 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2130 break;
2131 if (n->nud_state & ~NUD_NOARP)
2132 break;
2133 next:
2134 n = n->next;
2135 }
2136
2137 if (n)
2138 break;
2139 }
2140 state->bucket = bucket;
2141
2142 return n;
2143}
2144
2145static struct neighbour *neigh_get_next(struct seq_file *seq,
2146 struct neighbour *n,
2147 loff_t *pos)
2148{
2149 struct neigh_seq_state *state = seq->private;
2150 struct neigh_table *tbl = state->tbl;
2151
2152 if (state->neigh_sub_iter) {
2153 void *v = state->neigh_sub_iter(state, n, pos);
2154 if (v)
2155 return n;
2156 }
2157 n = n->next;
2158
2159 while (1) {
2160 while (n) {
2161 if (state->neigh_sub_iter) {
2162 void *v = state->neigh_sub_iter(state, n, pos);
2163 if (v)
2164 return n;
2165 goto next;
2166 }
2167 if (!(state->flags & NEIGH_SEQ_SKIP_NOARP))
2168 break;
2169
2170 if (n->nud_state & ~NUD_NOARP)
2171 break;
2172 next:
2173 n = n->next;
2174 }
2175
2176 if (n)
2177 break;
2178
2179 if (++state->bucket > tbl->hash_mask)
2180 break;
2181
2182 n = tbl->hash_buckets[state->bucket];
2183 }
2184
2185 if (n && pos)
2186 --(*pos);
2187 return n;
2188}
2189
2190static struct neighbour *neigh_get_idx(struct seq_file *seq, loff_t *pos)
2191{
2192 struct neighbour *n = neigh_get_first(seq);
2193
2194 if (n) {
2195 while (*pos) {
2196 n = neigh_get_next(seq, n, pos);
2197 if (!n)
2198 break;
2199 }
2200 }
2201 return *pos ? NULL : n;
2202}
2203
2204static struct pneigh_entry *pneigh_get_first(struct seq_file *seq)
2205{
2206 struct neigh_seq_state *state = seq->private;
2207 struct neigh_table *tbl = state->tbl;
2208 struct pneigh_entry *pn = NULL;
2209 int bucket = state->bucket;
2210
2211 state->flags |= NEIGH_SEQ_IS_PNEIGH;
2212 for (bucket = 0; bucket <= PNEIGH_HASHMASK; bucket++) {
2213 pn = tbl->phash_buckets[bucket];
2214 if (pn)
2215 break;
2216 }
2217 state->bucket = bucket;
2218
2219 return pn;
2220}
2221
2222static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
2223 struct pneigh_entry *pn,
2224 loff_t *pos)
2225{
2226 struct neigh_seq_state *state = seq->private;
2227 struct neigh_table *tbl = state->tbl;
2228
2229 pn = pn->next;
2230 while (!pn) {
2231 if (++state->bucket > PNEIGH_HASHMASK)
2232 break;
2233 pn = tbl->phash_buckets[state->bucket];
2234 if (pn)
2235 break;
2236 }
2237
2238 if (pn && pos)
2239 --(*pos);
2240
2241 return pn;
2242}
2243
2244static struct pneigh_entry *pneigh_get_idx(struct seq_file *seq, loff_t *pos)
2245{
2246 struct pneigh_entry *pn = pneigh_get_first(seq);
2247
2248 if (pn) {
2249 while (*pos) {
2250 pn = pneigh_get_next(seq, pn, pos);
2251 if (!pn)
2252 break;
2253 }
2254 }
2255 return *pos ? NULL : pn;
2256}
2257
2258static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos)
2259{
2260 struct neigh_seq_state *state = seq->private;
2261 void *rc;
2262
2263 rc = neigh_get_idx(seq, pos);
2264 if (!rc && !(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2265 rc = pneigh_get_idx(seq, pos);
2266
2267 return rc;
2268}
2269
2270void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags)
2271{
2272 struct neigh_seq_state *state = seq->private;
2273 loff_t pos_minus_one;
2274
2275 state->tbl = tbl;
2276 state->bucket = 0;
2277 state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH);
2278
2279 read_lock_bh(&tbl->lock);
2280
2281 pos_minus_one = *pos - 1;
2282 return *pos ? neigh_get_idx_any(seq, &pos_minus_one) : SEQ_START_TOKEN;
2283}
2284EXPORT_SYMBOL(neigh_seq_start);
2285
2286void *neigh_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2287{
2288 struct neigh_seq_state *state;
2289 void *rc;
2290
2291 if (v == SEQ_START_TOKEN) {
2292 rc = neigh_get_idx(seq, pos);
2293 goto out;
2294 }
2295
2296 state = seq->private;
2297 if (!(state->flags & NEIGH_SEQ_IS_PNEIGH)) {
2298 rc = neigh_get_next(seq, v, NULL);
2299 if (rc)
2300 goto out;
2301 if (!(state->flags & NEIGH_SEQ_NEIGH_ONLY))
2302 rc = pneigh_get_first(seq);
2303 } else {
2304 BUG_ON(state->flags & NEIGH_SEQ_NEIGH_ONLY);
2305 rc = pneigh_get_next(seq, v, NULL);
2306 }
2307out:
2308 ++(*pos);
2309 return rc;
2310}
2311EXPORT_SYMBOL(neigh_seq_next);
2312
2313void neigh_seq_stop(struct seq_file *seq, void *v)
2314{
2315 struct neigh_seq_state *state = seq->private;
2316 struct neigh_table *tbl = state->tbl;
2317
2318 read_unlock_bh(&tbl->lock);
2319}
2320EXPORT_SYMBOL(neigh_seq_stop);
2321
2322/* statistics via seq_file */
2323
2324static void *neigh_stat_seq_start(struct seq_file *seq, loff_t *pos)
2325{
2326 struct proc_dir_entry *pde = seq->private;
2327 struct neigh_table *tbl = pde->data;
2328 int cpu;
2329
2330 if (*pos == 0)
2331 return SEQ_START_TOKEN;
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002332
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 for (cpu = *pos-1; cpu < NR_CPUS; ++cpu) {
2334 if (!cpu_possible(cpu))
2335 continue;
2336 *pos = cpu+1;
2337 return per_cpu_ptr(tbl->stats, cpu);
2338 }
2339 return NULL;
2340}
2341
2342static void *neigh_stat_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2343{
2344 struct proc_dir_entry *pde = seq->private;
2345 struct neigh_table *tbl = pde->data;
2346 int cpu;
2347
2348 for (cpu = *pos; cpu < NR_CPUS; ++cpu) {
2349 if (!cpu_possible(cpu))
2350 continue;
2351 *pos = cpu+1;
2352 return per_cpu_ptr(tbl->stats, cpu);
2353 }
2354 return NULL;
2355}
2356
2357static void neigh_stat_seq_stop(struct seq_file *seq, void *v)
2358{
2359
2360}
2361
2362static int neigh_stat_seq_show(struct seq_file *seq, void *v)
2363{
2364 struct proc_dir_entry *pde = seq->private;
2365 struct neigh_table *tbl = pde->data;
2366 struct neigh_statistics *st = v;
2367
2368 if (v == SEQ_START_TOKEN) {
Olaf Rempel5bec0032005-04-28 12:16:08 -07002369 seq_printf(seq, "entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002370 return 0;
2371 }
2372
2373 seq_printf(seq, "%08x %08lx %08lx %08lx %08lx %08lx %08lx "
2374 "%08lx %08lx %08lx %08lx\n",
2375 atomic_read(&tbl->entries),
2376
2377 st->allocs,
2378 st->destroys,
2379 st->hash_grows,
2380
2381 st->lookups,
2382 st->hits,
2383
2384 st->res_failed,
2385
2386 st->rcv_probes_mcast,
2387 st->rcv_probes_ucast,
2388
2389 st->periodic_gc_runs,
2390 st->forced_gc_runs
2391 );
2392
2393 return 0;
2394}
2395
Stephen Hemmingerf6908082007-03-12 14:34:29 -07002396static const struct seq_operations neigh_stat_seq_ops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002397 .start = neigh_stat_seq_start,
2398 .next = neigh_stat_seq_next,
2399 .stop = neigh_stat_seq_stop,
2400 .show = neigh_stat_seq_show,
2401};
2402
2403static int neigh_stat_seq_open(struct inode *inode, struct file *file)
2404{
2405 int ret = seq_open(file, &neigh_stat_seq_ops);
2406
2407 if (!ret) {
2408 struct seq_file *sf = file->private_data;
2409 sf->private = PDE(inode);
2410 }
2411 return ret;
2412};
2413
Arjan van de Ven9a321442007-02-12 00:55:35 -08002414static const struct file_operations neigh_stat_seq_fops = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 .owner = THIS_MODULE,
2416 .open = neigh_stat_seq_open,
2417 .read = seq_read,
2418 .llseek = seq_lseek,
2419 .release = seq_release,
2420};
2421
2422#endif /* CONFIG_PROC_FS */
2423
2424#ifdef CONFIG_ARPD
Thomas Graf339bf982006-11-10 14:10:15 -08002425static inline size_t neigh_nlmsg_size(void)
2426{
2427 return NLMSG_ALIGN(sizeof(struct ndmsg))
2428 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2429 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2430 + nla_total_size(sizeof(struct nda_cacheinfo))
2431 + nla_total_size(4); /* NDA_PROBES */
2432}
2433
Thomas Grafb8673312006-08-15 00:33:14 -07002434static void __neigh_notify(struct neighbour *n, int type, int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435{
Thomas Graf8b8aec52006-08-07 17:56:37 -07002436 struct sk_buff *skb;
Thomas Grafb8673312006-08-15 00:33:14 -07002437 int err = -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002438
Thomas Graf339bf982006-11-10 14:10:15 -08002439 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
Thomas Graf8b8aec52006-08-07 17:56:37 -07002440 if (skb == NULL)
Thomas Grafb8673312006-08-15 00:33:14 -07002441 goto errout;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002442
Thomas Grafb8673312006-08-15 00:33:14 -07002443 err = neigh_fill_info(skb, n, 0, 0, type, flags);
Patrick McHardy26932562007-01-31 23:16:40 -08002444 if (err < 0) {
2445 /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
2446 WARN_ON(err == -EMSGSIZE);
2447 kfree_skb(skb);
2448 goto errout;
2449 }
Thomas Grafb8673312006-08-15 00:33:14 -07002450 err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2451errout:
2452 if (err < 0)
2453 rtnl_set_sk_err(RTNLGRP_NEIGH, err);
2454}
2455
2456void neigh_app_ns(struct neighbour *n)
2457{
2458 __neigh_notify(n, RTM_GETNEIGH, NLM_F_REQUEST);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002459}
2460
2461static void neigh_app_notify(struct neighbour *n)
2462{
Thomas Grafb8673312006-08-15 00:33:14 -07002463 __neigh_notify(n, RTM_NEWNEIGH, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002464}
2465
2466#endif /* CONFIG_ARPD */
2467
2468#ifdef CONFIG_SYSCTL
2469
2470static struct neigh_sysctl_table {
2471 struct ctl_table_header *sysctl_header;
2472 ctl_table neigh_vars[__NET_NEIGH_MAX];
2473 ctl_table neigh_dev[2];
2474 ctl_table neigh_neigh_dir[2];
2475 ctl_table neigh_proto_dir[2];
2476 ctl_table neigh_root_dir[2];
Brian Haleyab32ea52006-09-22 14:15:41 -07002477} neigh_sysctl_template __read_mostly = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 .neigh_vars = {
2479 {
2480 .ctl_name = NET_NEIGH_MCAST_SOLICIT,
2481 .procname = "mcast_solicit",
2482 .maxlen = sizeof(int),
2483 .mode = 0644,
2484 .proc_handler = &proc_dointvec,
2485 },
2486 {
2487 .ctl_name = NET_NEIGH_UCAST_SOLICIT,
2488 .procname = "ucast_solicit",
2489 .maxlen = sizeof(int),
2490 .mode = 0644,
2491 .proc_handler = &proc_dointvec,
2492 },
2493 {
2494 .ctl_name = NET_NEIGH_APP_SOLICIT,
2495 .procname = "app_solicit",
2496 .maxlen = sizeof(int),
2497 .mode = 0644,
2498 .proc_handler = &proc_dointvec,
2499 },
2500 {
2501 .ctl_name = NET_NEIGH_RETRANS_TIME,
2502 .procname = "retrans_time",
2503 .maxlen = sizeof(int),
2504 .mode = 0644,
2505 .proc_handler = &proc_dointvec_userhz_jiffies,
2506 },
2507 {
2508 .ctl_name = NET_NEIGH_REACHABLE_TIME,
2509 .procname = "base_reachable_time",
2510 .maxlen = sizeof(int),
2511 .mode = 0644,
2512 .proc_handler = &proc_dointvec_jiffies,
2513 .strategy = &sysctl_jiffies,
2514 },
2515 {
2516 .ctl_name = NET_NEIGH_DELAY_PROBE_TIME,
2517 .procname = "delay_first_probe_time",
2518 .maxlen = sizeof(int),
2519 .mode = 0644,
2520 .proc_handler = &proc_dointvec_jiffies,
2521 .strategy = &sysctl_jiffies,
2522 },
2523 {
2524 .ctl_name = NET_NEIGH_GC_STALE_TIME,
2525 .procname = "gc_stale_time",
2526 .maxlen = sizeof(int),
2527 .mode = 0644,
2528 .proc_handler = &proc_dointvec_jiffies,
2529 .strategy = &sysctl_jiffies,
2530 },
2531 {
2532 .ctl_name = NET_NEIGH_UNRES_QLEN,
2533 .procname = "unres_qlen",
2534 .maxlen = sizeof(int),
2535 .mode = 0644,
2536 .proc_handler = &proc_dointvec,
2537 },
2538 {
2539 .ctl_name = NET_NEIGH_PROXY_QLEN,
2540 .procname = "proxy_qlen",
2541 .maxlen = sizeof(int),
2542 .mode = 0644,
2543 .proc_handler = &proc_dointvec,
2544 },
2545 {
2546 .ctl_name = NET_NEIGH_ANYCAST_DELAY,
2547 .procname = "anycast_delay",
2548 .maxlen = sizeof(int),
2549 .mode = 0644,
2550 .proc_handler = &proc_dointvec_userhz_jiffies,
2551 },
2552 {
2553 .ctl_name = NET_NEIGH_PROXY_DELAY,
2554 .procname = "proxy_delay",
2555 .maxlen = sizeof(int),
2556 .mode = 0644,
2557 .proc_handler = &proc_dointvec_userhz_jiffies,
2558 },
2559 {
2560 .ctl_name = NET_NEIGH_LOCKTIME,
2561 .procname = "locktime",
2562 .maxlen = sizeof(int),
2563 .mode = 0644,
2564 .proc_handler = &proc_dointvec_userhz_jiffies,
2565 },
2566 {
2567 .ctl_name = NET_NEIGH_GC_INTERVAL,
2568 .procname = "gc_interval",
2569 .maxlen = sizeof(int),
2570 .mode = 0644,
2571 .proc_handler = &proc_dointvec_jiffies,
2572 .strategy = &sysctl_jiffies,
2573 },
2574 {
2575 .ctl_name = NET_NEIGH_GC_THRESH1,
2576 .procname = "gc_thresh1",
2577 .maxlen = sizeof(int),
2578 .mode = 0644,
2579 .proc_handler = &proc_dointvec,
2580 },
2581 {
2582 .ctl_name = NET_NEIGH_GC_THRESH2,
2583 .procname = "gc_thresh2",
2584 .maxlen = sizeof(int),
2585 .mode = 0644,
2586 .proc_handler = &proc_dointvec,
2587 },
2588 {
2589 .ctl_name = NET_NEIGH_GC_THRESH3,
2590 .procname = "gc_thresh3",
2591 .maxlen = sizeof(int),
2592 .mode = 0644,
2593 .proc_handler = &proc_dointvec,
2594 },
2595 {
2596 .ctl_name = NET_NEIGH_RETRANS_TIME_MS,
2597 .procname = "retrans_time_ms",
2598 .maxlen = sizeof(int),
2599 .mode = 0644,
2600 .proc_handler = &proc_dointvec_ms_jiffies,
2601 .strategy = &sysctl_ms_jiffies,
2602 },
2603 {
2604 .ctl_name = NET_NEIGH_REACHABLE_TIME_MS,
2605 .procname = "base_reachable_time_ms",
2606 .maxlen = sizeof(int),
2607 .mode = 0644,
2608 .proc_handler = &proc_dointvec_ms_jiffies,
2609 .strategy = &sysctl_ms_jiffies,
2610 },
2611 },
2612 .neigh_dev = {
2613 {
2614 .ctl_name = NET_PROTO_CONF_DEFAULT,
2615 .procname = "default",
2616 .mode = 0555,
2617 },
2618 },
2619 .neigh_neigh_dir = {
2620 {
2621 .procname = "neigh",
2622 .mode = 0555,
2623 },
2624 },
2625 .neigh_proto_dir = {
2626 {
2627 .mode = 0555,
2628 },
2629 },
2630 .neigh_root_dir = {
2631 {
2632 .ctl_name = CTL_NET,
2633 .procname = "net",
2634 .mode = 0555,
2635 },
2636 },
2637};
2638
2639int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002640 int p_id, int pdev_id, char *p_name,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002641 proc_handler *handler, ctl_handler *strategy)
2642{
Arnaldo Carvalho de Melob1a98bf2006-11-21 01:15:32 -02002643 struct neigh_sysctl_table *t = kmemdup(&neigh_sysctl_template,
2644 sizeof(*t), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645 const char *dev_name_source = NULL;
2646 char *dev_name = NULL;
2647 int err = 0;
2648
2649 if (!t)
2650 return -ENOBUFS;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651 t->neigh_vars[0].data = &p->mcast_probes;
2652 t->neigh_vars[1].data = &p->ucast_probes;
2653 t->neigh_vars[2].data = &p->app_probes;
2654 t->neigh_vars[3].data = &p->retrans_time;
2655 t->neigh_vars[4].data = &p->base_reachable_time;
2656 t->neigh_vars[5].data = &p->delay_probe_time;
2657 t->neigh_vars[6].data = &p->gc_staletime;
2658 t->neigh_vars[7].data = &p->queue_len;
2659 t->neigh_vars[8].data = &p->proxy_qlen;
2660 t->neigh_vars[9].data = &p->anycast_delay;
2661 t->neigh_vars[10].data = &p->proxy_delay;
2662 t->neigh_vars[11].data = &p->locktime;
2663
2664 if (dev) {
2665 dev_name_source = dev->name;
2666 t->neigh_dev[0].ctl_name = dev->ifindex;
2667 t->neigh_vars[12].procname = NULL;
2668 t->neigh_vars[13].procname = NULL;
2669 t->neigh_vars[14].procname = NULL;
2670 t->neigh_vars[15].procname = NULL;
2671 } else {
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002672 dev_name_source = t->neigh_dev[0].procname;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002673 t->neigh_vars[12].data = (int *)(p + 1);
2674 t->neigh_vars[13].data = (int *)(p + 1) + 1;
2675 t->neigh_vars[14].data = (int *)(p + 1) + 2;
2676 t->neigh_vars[15].data = (int *)(p + 1) + 3;
2677 }
2678
2679 t->neigh_vars[16].data = &p->retrans_time;
2680 t->neigh_vars[17].data = &p->base_reachable_time;
2681
2682 if (handler || strategy) {
2683 /* RetransTime */
2684 t->neigh_vars[3].proc_handler = handler;
2685 t->neigh_vars[3].strategy = strategy;
2686 t->neigh_vars[3].extra1 = dev;
2687 /* ReachableTime */
2688 t->neigh_vars[4].proc_handler = handler;
2689 t->neigh_vars[4].strategy = strategy;
2690 t->neigh_vars[4].extra1 = dev;
2691 /* RetransTime (in milliseconds)*/
2692 t->neigh_vars[16].proc_handler = handler;
2693 t->neigh_vars[16].strategy = strategy;
2694 t->neigh_vars[16].extra1 = dev;
2695 /* ReachableTime (in milliseconds) */
2696 t->neigh_vars[17].proc_handler = handler;
2697 t->neigh_vars[17].strategy = strategy;
2698 t->neigh_vars[17].extra1 = dev;
2699 }
2700
Paulo Marques543537b2005-06-23 00:09:02 -07002701 dev_name = kstrdup(dev_name_source, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002702 if (!dev_name) {
2703 err = -ENOBUFS;
2704 goto free;
2705 }
2706
YOSHIFUJI Hideaki4ec93ed2007-02-09 23:24:36 +09002707 t->neigh_dev[0].procname = dev_name;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002708
2709 t->neigh_neigh_dir[0].ctl_name = pdev_id;
2710
2711 t->neigh_proto_dir[0].procname = p_name;
2712 t->neigh_proto_dir[0].ctl_name = p_id;
2713
2714 t->neigh_dev[0].child = t->neigh_vars;
2715 t->neigh_neigh_dir[0].child = t->neigh_dev;
2716 t->neigh_proto_dir[0].child = t->neigh_neigh_dir;
2717 t->neigh_root_dir[0].child = t->neigh_proto_dir;
2718
Eric W. Biederman0b4d4142007-02-14 00:34:09 -08002719 t->sysctl_header = register_sysctl_table(t->neigh_root_dir);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002720 if (!t->sysctl_header) {
2721 err = -ENOBUFS;
2722 goto free_procname;
2723 }
2724 p->sysctl_table = t;
2725 return 0;
2726
2727 /* error path */
2728 free_procname:
2729 kfree(dev_name);
2730 free:
2731 kfree(t);
2732
2733 return err;
2734}
2735
2736void neigh_sysctl_unregister(struct neigh_parms *p)
2737{
2738 if (p->sysctl_table) {
2739 struct neigh_sysctl_table *t = p->sysctl_table;
2740 p->sysctl_table = NULL;
2741 unregister_sysctl_table(t->sysctl_header);
2742 kfree(t->neigh_dev[0].procname);
2743 kfree(t);
2744 }
2745}
2746
2747#endif /* CONFIG_SYSCTL */
2748
Thomas Grafc8822a42007-03-22 11:50:06 -07002749static int __init neigh_init(void)
2750{
2751 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL);
2752 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL);
2753 rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info);
2754
2755 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info);
2756 rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL);
2757
2758 return 0;
2759}
2760
2761subsys_initcall(neigh_init);
2762
Linus Torvalds1da177e2005-04-16 15:20:36 -07002763EXPORT_SYMBOL(__neigh_event_send);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002764EXPORT_SYMBOL(neigh_changeaddr);
2765EXPORT_SYMBOL(neigh_compat_output);
2766EXPORT_SYMBOL(neigh_connected_output);
2767EXPORT_SYMBOL(neigh_create);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002768EXPORT_SYMBOL(neigh_destroy);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769EXPORT_SYMBOL(neigh_event_ns);
2770EXPORT_SYMBOL(neigh_ifdown);
2771EXPORT_SYMBOL(neigh_lookup);
2772EXPORT_SYMBOL(neigh_lookup_nodev);
2773EXPORT_SYMBOL(neigh_parms_alloc);
2774EXPORT_SYMBOL(neigh_parms_release);
2775EXPORT_SYMBOL(neigh_rand_reach_time);
2776EXPORT_SYMBOL(neigh_resolve_output);
2777EXPORT_SYMBOL(neigh_table_clear);
2778EXPORT_SYMBOL(neigh_table_init);
Simon Kelleybd89efc2006-05-12 14:56:08 -07002779EXPORT_SYMBOL(neigh_table_init_no_netlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002780EXPORT_SYMBOL(neigh_update);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002781EXPORT_SYMBOL(pneigh_enqueue);
2782EXPORT_SYMBOL(pneigh_lookup);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002783
2784#ifdef CONFIG_ARPD
2785EXPORT_SYMBOL(neigh_app_ns);
2786#endif
2787#ifdef CONFIG_SYSCTL
2788EXPORT_SYMBOL(neigh_sysctl_register);
2789EXPORT_SYMBOL(neigh_sysctl_unregister);
2790#endif