hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/net/core/neighbour.c
....@@ -1,14 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Generic address resolution entity
34 *
45 * Authors:
56 * Pedro Roque <roque@di.fc.ul.pt>
67 * 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.
128 *
139 * Fixes:
1410 * Vitaly E. Lavrov releasing NULL neighbor in neigh_add.
....@@ -42,6 +38,8 @@
4238 #include <linux/log2.h>
4339 #include <linux/inetdevice.h>
4440 #include <net/addrconf.h>
41
+
42
+#include <trace/events/neigh.h>
4543
4644 #define DEBUG
4745 #define NEIGH_DEBUG 1
....@@ -100,9 +98,7 @@
10098
10199 static void neigh_cleanup_and_release(struct neighbour *neigh)
102100 {
103
- if (neigh->parms->neigh_cleanup)
104
- neigh->parms->neigh_cleanup(neigh);
105
-
101
+ trace_neigh_cleanup_and_release(neigh, 0);
106102 __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
107103 call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
108104 neigh_release(neigh);
....@@ -120,21 +116,81 @@
120116 }
121117 EXPORT_SYMBOL(neigh_rand_reach_time);
122118
119
+static void neigh_mark_dead(struct neighbour *n)
120
+{
121
+ n->dead = 1;
122
+ if (!list_empty(&n->gc_list)) {
123
+ list_del_init(&n->gc_list);
124
+ atomic_dec(&n->tbl->gc_entries);
125
+ }
126
+}
123127
124
-static bool neigh_del(struct neighbour *n, __u8 state, __u8 flags,
125
- struct neighbour __rcu **np, struct neigh_table *tbl)
128
+static void neigh_update_gc_list(struct neighbour *n)
129
+{
130
+ bool on_gc_list, exempt_from_gc;
131
+
132
+ write_lock_bh(&n->tbl->lock);
133
+ write_lock(&n->lock);
134
+
135
+ if (n->dead)
136
+ goto out;
137
+
138
+ /* remove from the gc list if new state is permanent or if neighbor
139
+ * is externally learned; otherwise entry should be on the gc list
140
+ */
141
+ exempt_from_gc = n->nud_state & NUD_PERMANENT ||
142
+ n->flags & NTF_EXT_LEARNED;
143
+ on_gc_list = !list_empty(&n->gc_list);
144
+
145
+ if (exempt_from_gc && on_gc_list) {
146
+ list_del_init(&n->gc_list);
147
+ atomic_dec(&n->tbl->gc_entries);
148
+ } else if (!exempt_from_gc && !on_gc_list) {
149
+ /* add entries to the tail; cleaning removes from the front */
150
+ list_add_tail(&n->gc_list, &n->tbl->gc_list);
151
+ atomic_inc(&n->tbl->gc_entries);
152
+ }
153
+
154
+out:
155
+ write_unlock(&n->lock);
156
+ write_unlock_bh(&n->tbl->lock);
157
+}
158
+
159
+static bool neigh_update_ext_learned(struct neighbour *neigh, u32 flags,
160
+ int *notify)
161
+{
162
+ bool rc = false;
163
+ u8 ndm_flags;
164
+
165
+ if (!(flags & NEIGH_UPDATE_F_ADMIN))
166
+ return rc;
167
+
168
+ ndm_flags = (flags & NEIGH_UPDATE_F_EXT_LEARNED) ? NTF_EXT_LEARNED : 0;
169
+ if ((neigh->flags ^ ndm_flags) & NTF_EXT_LEARNED) {
170
+ if (ndm_flags & NTF_EXT_LEARNED)
171
+ neigh->flags |= NTF_EXT_LEARNED;
172
+ else
173
+ neigh->flags &= ~NTF_EXT_LEARNED;
174
+ rc = true;
175
+ *notify = 1;
176
+ }
177
+
178
+ return rc;
179
+}
180
+
181
+static bool neigh_del(struct neighbour *n, struct neighbour __rcu **np,
182
+ struct neigh_table *tbl)
126183 {
127184 bool retval = false;
128185
129186 write_lock(&n->lock);
130
- if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state) &&
131
- !(n->flags & flags)) {
187
+ if (refcount_read(&n->refcnt) == 1) {
132188 struct neighbour *neigh;
133189
134190 neigh = rcu_dereference_protected(n->next,
135191 lockdep_is_held(&tbl->lock));
136192 rcu_assign_pointer(*np, neigh);
137
- n->dead = 1;
193
+ neigh_mark_dead(n);
138194 retval = true;
139195 }
140196 write_unlock(&n->lock);
....@@ -160,7 +216,7 @@
160216 while ((n = rcu_dereference_protected(*np,
161217 lockdep_is_held(&tbl->lock)))) {
162218 if (n == ndel)
163
- return neigh_del(n, 0, 0, np, tbl);
219
+ return neigh_del(n, np, tbl);
164220 np = &n->next;
165221 }
166222 return false;
....@@ -168,32 +224,32 @@
168224
169225 static int neigh_forced_gc(struct neigh_table *tbl)
170226 {
227
+ int max_clean = atomic_read(&tbl->gc_entries) - tbl->gc_thresh2;
228
+ unsigned long tref = jiffies - 5 * HZ;
229
+ struct neighbour *n, *tmp;
171230 int shrunk = 0;
172
- int i;
173
- struct neigh_hash_table *nht;
174231
175232 NEIGH_CACHE_STAT_INC(tbl, forced_gc_runs);
176233
177234 write_lock_bh(&tbl->lock);
178
- nht = rcu_dereference_protected(tbl->nht,
179
- lockdep_is_held(&tbl->lock));
180
- for (i = 0; i < (1 << nht->hash_shift); i++) {
181
- struct neighbour *n;
182
- struct neighbour __rcu **np;
183235
184
- np = &nht->hash_buckets[i];
185
- while ((n = rcu_dereference_protected(*np,
186
- lockdep_is_held(&tbl->lock))) != NULL) {
187
- /* Neighbour record may be discarded if:
188
- * - nobody refers to it.
189
- * - it is not permanent
190
- */
191
- if (neigh_del(n, NUD_PERMANENT, NTF_EXT_LEARNED, np,
192
- tbl)) {
193
- shrunk = 1;
194
- continue;
195
- }
196
- np = &n->next;
236
+ list_for_each_entry_safe(n, tmp, &tbl->gc_list, gc_list) {
237
+ if (refcount_read(&n->refcnt) == 1) {
238
+ bool remove = false;
239
+
240
+ write_lock(&n->lock);
241
+ if ((n->nud_state == NUD_FAILED) ||
242
+ (n->nud_state == NUD_NOARP) ||
243
+ (tbl->is_multicast &&
244
+ tbl->is_multicast(n->primary_key)) ||
245
+ !time_in_range(n->updated, tref, jiffies))
246
+ remove = true;
247
+ write_unlock(&n->lock);
248
+
249
+ if (remove && neigh_remove_one(n, tbl))
250
+ shrunk++;
251
+ if (shrunk >= max_clean)
252
+ break;
197253 }
198254 }
199255
....@@ -206,7 +262,17 @@
206262
207263 static void neigh_add_timer(struct neighbour *n, unsigned long when)
208264 {
265
+ /* Use safe distance from the jiffies - LONG_MAX point while timer
266
+ * is running in DELAY/PROBE state but still show to user space
267
+ * large times in the past.
268
+ */
269
+ unsigned long mint = jiffies - (LONG_MAX - 86400 * HZ);
270
+
209271 neigh_hold(n);
272
+ if (!time_in_range(n->confirmed, mint, jiffies))
273
+ n->confirmed = mint;
274
+ if (time_before(n->used, n->confirmed))
275
+ n->used = n->confirmed;
210276 if (unlikely(mod_timer(&n->timer, when))) {
211277 printk("NEIGH: BUG, double timer add, state is %x\n",
212278 n->nud_state);
....@@ -224,17 +290,33 @@
224290 return 0;
225291 }
226292
227
-static void pneigh_queue_purge(struct sk_buff_head *list)
293
+static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net)
228294 {
295
+ struct sk_buff_head tmp;
296
+ unsigned long flags;
229297 struct sk_buff *skb;
230298
231
- while ((skb = skb_dequeue(list)) != NULL) {
299
+ skb_queue_head_init(&tmp);
300
+ spin_lock_irqsave(&list->lock, flags);
301
+ skb = skb_peek(list);
302
+ while (skb != NULL) {
303
+ struct sk_buff *skb_next = skb_peek_next(skb, list);
304
+ if (net == NULL || net_eq(dev_net(skb->dev), net)) {
305
+ __skb_unlink(skb, list);
306
+ __skb_queue_tail(&tmp, skb);
307
+ }
308
+ skb = skb_next;
309
+ }
310
+ spin_unlock_irqrestore(&list->lock, flags);
311
+
312
+ while ((skb = __skb_dequeue(&tmp))) {
232313 dev_put(skb->dev);
233314 kfree_skb(skb);
234315 }
235316 }
236317
237
-static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
318
+static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
319
+ bool skip_perm)
238320 {
239321 int i;
240322 struct neigh_hash_table *nht;
....@@ -252,13 +334,16 @@
252334 np = &n->next;
253335 continue;
254336 }
337
+ if (skip_perm && n->nud_state & NUD_PERMANENT) {
338
+ np = &n->next;
339
+ continue;
340
+ }
255341 rcu_assign_pointer(*np,
256342 rcu_dereference_protected(n->next,
257343 lockdep_is_held(&tbl->lock)));
258344 write_lock(&n->lock);
259345 neigh_del_timer(n);
260
- n->dead = 1;
261
-
346
+ neigh_mark_dead(n);
262347 if (refcount_read(&n->refcnt) != 1) {
263348 /* The most unpleasant situation.
264349 We must destroy neighbour entry,
....@@ -287,30 +372,49 @@
287372 void neigh_changeaddr(struct neigh_table *tbl, struct net_device *dev)
288373 {
289374 write_lock_bh(&tbl->lock);
290
- neigh_flush_dev(tbl, dev);
375
+ neigh_flush_dev(tbl, dev, false);
291376 write_unlock_bh(&tbl->lock);
292377 }
293378 EXPORT_SYMBOL(neigh_changeaddr);
294379
295
-int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
380
+static int __neigh_ifdown(struct neigh_table *tbl, struct net_device *dev,
381
+ bool skip_perm)
296382 {
297383 write_lock_bh(&tbl->lock);
298
- neigh_flush_dev(tbl, dev);
384
+ neigh_flush_dev(tbl, dev, skip_perm);
299385 pneigh_ifdown_and_unlock(tbl, dev);
386
+ pneigh_queue_purge(&tbl->proxy_queue, dev ? dev_net(dev) : NULL);
387
+ if (skb_queue_empty_lockless(&tbl->proxy_queue))
388
+ del_timer_sync(&tbl->proxy_timer);
389
+ return 0;
390
+}
300391
301
- del_timer_sync(&tbl->proxy_timer);
302
- pneigh_queue_purge(&tbl->proxy_queue);
392
+int neigh_carrier_down(struct neigh_table *tbl, struct net_device *dev)
393
+{
394
+ __neigh_ifdown(tbl, dev, true);
395
+ return 0;
396
+}
397
+EXPORT_SYMBOL(neigh_carrier_down);
398
+
399
+int neigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
400
+{
401
+ __neigh_ifdown(tbl, dev, false);
303402 return 0;
304403 }
305404 EXPORT_SYMBOL(neigh_ifdown);
306405
307
-static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
406
+static struct neighbour *neigh_alloc(struct neigh_table *tbl,
407
+ struct net_device *dev,
408
+ u8 flags, bool exempt_from_gc)
308409 {
309410 struct neighbour *n = NULL;
310411 unsigned long now = jiffies;
311412 int entries;
312413
313
- entries = atomic_inc_return(&tbl->entries) - 1;
414
+ if (exempt_from_gc)
415
+ goto do_alloc;
416
+
417
+ entries = atomic_inc_return(&tbl->gc_entries) - 1;
314418 if (entries >= tbl->gc_thresh3 ||
315419 (entries >= tbl->gc_thresh2 &&
316420 time_after(now, tbl->last_flush + 5 * HZ))) {
....@@ -323,6 +427,7 @@
323427 }
324428 }
325429
430
+do_alloc:
326431 n = kzalloc(tbl->entry_size + dev->neigh_priv_len, GFP_ATOMIC);
327432 if (!n)
328433 goto out_entries;
....@@ -333,6 +438,7 @@
333438 n->updated = n->used = now;
334439 n->nud_state = NUD_NONE;
335440 n->output = neigh_blackhole;
441
+ n->flags = flags;
336442 seqlock_init(&n->hh.hh_lock);
337443 n->parms = neigh_parms_clone(&tbl->parms);
338444 timer_setup(&n->timer, neigh_timer_handler, 0);
....@@ -341,11 +447,15 @@
341447 n->tbl = tbl;
342448 refcount_set(&n->refcnt, 1);
343449 n->dead = 1;
450
+ INIT_LIST_HEAD(&n->gc_list);
451
+
452
+ atomic_inc(&tbl->entries);
344453 out:
345454 return n;
346455
347456 out_entries:
348
- atomic_dec(&tbl->entries);
457
+ if (!exempt_from_gc)
458
+ atomic_dec(&tbl->gc_entries);
349459 goto out;
350460 }
351461
....@@ -461,46 +571,18 @@
461571 }
462572 EXPORT_SYMBOL(neigh_lookup);
463573
464
-struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
465
- const void *pkey)
574
+static struct neighbour *
575
+___neigh_create(struct neigh_table *tbl, const void *pkey,
576
+ struct net_device *dev, u8 flags,
577
+ bool exempt_from_gc, bool want_ref)
466578 {
467
- struct neighbour *n;
468
- unsigned int key_len = tbl->key_len;
469
- u32 hash_val;
579
+ u32 hash_val, key_len = tbl->key_len;
580
+ struct neighbour *n1, *rc, *n;
470581 struct neigh_hash_table *nht;
471
-
472
- NEIGH_CACHE_STAT_INC(tbl, lookups);
473
-
474
- rcu_read_lock_bh();
475
- nht = rcu_dereference_bh(tbl->nht);
476
- hash_val = tbl->hash(pkey, NULL, nht->hash_rnd) >> (32 - nht->hash_shift);
477
-
478
- for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
479
- n != NULL;
480
- n = rcu_dereference_bh(n->next)) {
481
- if (!memcmp(n->primary_key, pkey, key_len) &&
482
- net_eq(dev_net(n->dev), net)) {
483
- if (!refcount_inc_not_zero(&n->refcnt))
484
- n = NULL;
485
- NEIGH_CACHE_STAT_INC(tbl, hits);
486
- break;
487
- }
488
- }
489
-
490
- rcu_read_unlock_bh();
491
- return n;
492
-}
493
-EXPORT_SYMBOL(neigh_lookup_nodev);
494
-
495
-struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
496
- struct net_device *dev, bool want_ref)
497
-{
498
- u32 hash_val;
499
- unsigned int key_len = tbl->key_len;
500582 int error;
501
- struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev);
502
- struct neigh_hash_table *nht;
503583
584
+ n = neigh_alloc(tbl, dev, flags, exempt_from_gc);
585
+ trace_neigh_create(tbl, dev, pkey, n, exempt_from_gc);
504586 if (!n) {
505587 rc = ERR_PTR(-ENOBUFS);
506588 goto out;
....@@ -561,6 +643,9 @@
561643 }
562644
563645 n->dead = 0;
646
+ if (!exempt_from_gc)
647
+ list_add_tail(&n->gc_list, &n->tbl->gc_list);
648
+
564649 if (want_ref)
565650 neigh_hold(n);
566651 rcu_assign_pointer(n->next,
....@@ -575,8 +660,16 @@
575660 out_tbl_unlock:
576661 write_unlock_bh(&tbl->lock);
577662 out_neigh_release:
663
+ if (!exempt_from_gc)
664
+ atomic_dec(&tbl->gc_entries);
578665 neigh_release(n);
579666 goto out;
667
+}
668
+
669
+struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
670
+ struct net_device *dev, bool want_ref)
671
+{
672
+ return ___neigh_create(tbl, pkey, dev, 0, false, want_ref);
580673 }
581674 EXPORT_SYMBOL(__neigh_create);
582675
....@@ -834,14 +927,18 @@
834927 goto next_elt;
835928 }
836929
837
- if (time_before(n->used, n->confirmed))
930
+ if (time_before(n->used, n->confirmed) &&
931
+ time_is_before_eq_jiffies(n->confirmed))
838932 n->used = n->confirmed;
839933
840934 if (refcount_read(&n->refcnt) == 1 &&
841935 (state == NUD_FAILED ||
842
- time_after(jiffies, n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
843
- *np = n->next;
844
- n->dead = 1;
936
+ !time_in_range_open(jiffies, n->used,
937
+ n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) {
938
+ rcu_assign_pointer(*np,
939
+ rcu_dereference_protected(n->next,
940
+ lockdep_is_held(&tbl->lock)));
941
+ neigh_mark_dead(n);
845942 write_unlock(&n->lock);
846943 neigh_cleanup_and_release(n);
847944 continue;
....@@ -915,7 +1012,7 @@
9151012 if (neigh->ops->solicit)
9161013 neigh->ops->solicit(neigh, skb);
9171014 atomic_inc(&neigh->probes);
918
- kfree_skb(skb);
1015
+ consume_skb(skb);
9191016 }
9201017
9211018 /* Called when a timer expires for a neighbour entry. */
....@@ -972,11 +1069,12 @@
9721069 neigh->updated = jiffies;
9731070 atomic_set(&neigh->probes, 0);
9741071 notify = 1;
975
- next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
1072
+ next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1073
+ HZ/100);
9761074 }
9771075 } else {
9781076 /* NUD_PROBE|NUD_INCOMPLETE */
979
- next = now + NEIGH_VAR(neigh->parms, RETRANS_TIME);
1077
+ next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME), HZ/100);
9801078 }
9811079
9821080 if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) &&
....@@ -988,8 +1086,8 @@
9881086 }
9891087
9901088 if (neigh->nud_state & NUD_IN_TIMER) {
991
- if (time_before(next, jiffies + HZ/2))
992
- next = jiffies + HZ/2;
1089
+ if (time_before(next, jiffies + HZ/100))
1090
+ next = jiffies + HZ/100;
9931091 if (!mod_timer(&neigh->timer, next))
9941092 neigh_hold(neigh);
9951093 }
....@@ -1002,6 +1100,8 @@
10021100
10031101 if (notify)
10041102 neigh_update_notify(neigh, 0);
1103
+
1104
+ trace_neigh_timer_handler(neigh, 0);
10051105
10061106 neigh_release(neigh);
10071107 }
....@@ -1030,7 +1130,7 @@
10301130 neigh->nud_state = NUD_INCOMPLETE;
10311131 neigh->updated = now;
10321132 next = now + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1033
- HZ/2);
1133
+ HZ/100);
10341134 neigh_add_timer(neigh, next);
10351135 immediate_probe = true;
10361136 } else {
....@@ -1075,6 +1175,7 @@
10751175 else
10761176 write_unlock(&neigh->lock);
10771177 local_bh_enable();
1178
+ trace_neigh_event_send_done(neigh, rc);
10781179 return rc;
10791180
10801181 out_dead:
....@@ -1082,6 +1183,7 @@
10821183 goto out_unlock_bh;
10831184 write_unlock_bh(&neigh->lock);
10841185 kfree_skb(skb);
1186
+ trace_neigh_event_send_dead(neigh, 1);
10851187 return 1;
10861188 }
10871189 EXPORT_SYMBOL(__neigh_event_send);
....@@ -1117,7 +1219,7 @@
11171219 lladdr instead of overriding it
11181220 if it is different.
11191221 NEIGH_UPDATE_F_ADMIN means that the change is administrative.
1120
-
1222
+ NEIGH_UPDATE_F_USE means that the entry is user triggered.
11211223 NEIGH_UPDATE_F_OVERRIDE_ISROUTER allows to override existing
11221224 NTF_ROUTER flag.
11231225 NEIGH_UPDATE_F_ISROUTER indicates if the neighbour is known as
....@@ -1126,14 +1228,18 @@
11261228 Caller MUST hold reference count on the entry.
11271229 */
11281230
1129
-int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1130
- u32 flags, u32 nlmsg_pid)
1231
+static int __neigh_update(struct neighbour *neigh, const u8 *lladdr,
1232
+ u8 new, u32 flags, u32 nlmsg_pid,
1233
+ struct netlink_ext_ack *extack)
11311234 {
1235
+ bool ext_learn_change = false;
11321236 u8 old;
11331237 int err;
11341238 int notify = 0;
11351239 struct net_device *dev;
11361240 int update_isrouter = 0;
1241
+
1242
+ trace_neigh_update(neigh, lladdr, new, flags, nlmsg_pid);
11371243
11381244 write_lock_bh(&neigh->lock);
11391245
....@@ -1141,13 +1247,22 @@
11411247 old = neigh->nud_state;
11421248 err = -EPERM;
11431249
1250
+ if (neigh->dead) {
1251
+ NL_SET_ERR_MSG(extack, "Neighbor entry is now dead");
1252
+ new = old;
1253
+ goto out;
1254
+ }
11441255 if (!(flags & NEIGH_UPDATE_F_ADMIN) &&
11451256 (old & (NUD_NOARP | NUD_PERMANENT)))
11461257 goto out;
1147
- if (neigh->dead)
1148
- goto out;
11491258
1150
- neigh_update_ext_learned(neigh, flags, &notify);
1259
+ ext_learn_change = neigh_update_ext_learned(neigh, flags, &notify);
1260
+ if (flags & NEIGH_UPDATE_F_USE) {
1261
+ new = old & ~NUD_PERMANENT;
1262
+ neigh->nud_state = new;
1263
+ err = 0;
1264
+ goto out;
1265
+ }
11511266
11521267 if (!(new & NUD_VALID)) {
11531268 neigh_del_timer(neigh);
....@@ -1182,8 +1297,10 @@
11821297 use it, otherwise discard the request.
11831298 */
11841299 err = -EINVAL;
1185
- if (!(old & NUD_VALID))
1300
+ if (!(old & NUD_VALID)) {
1301
+ NL_SET_ERR_MSG(extack, "No link layer address given");
11861302 goto out;
1303
+ }
11871304 lladdr = neigh->ha;
11881305 }
11891306
....@@ -1287,17 +1404,25 @@
12871404 neigh->arp_queue_len_bytes = 0;
12881405 }
12891406 out:
1290
- if (update_isrouter) {
1291
- neigh->flags = (flags & NEIGH_UPDATE_F_ISROUTER) ?
1292
- (neigh->flags | NTF_ROUTER) :
1293
- (neigh->flags & ~NTF_ROUTER);
1294
- }
1407
+ if (update_isrouter)
1408
+ neigh_update_is_router(neigh, flags, &notify);
12951409 write_unlock_bh(&neigh->lock);
1410
+
1411
+ if (((new ^ old) & NUD_PERMANENT) || ext_learn_change)
1412
+ neigh_update_gc_list(neigh);
12961413
12971414 if (notify)
12981415 neigh_update_notify(neigh, nlmsg_pid);
12991416
1417
+ trace_neigh_update_done(neigh, err);
1418
+
13001419 return err;
1420
+}
1421
+
1422
+int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
1423
+ u32 flags, u32 nlmsg_pid)
1424
+{
1425
+ return __neigh_update(neigh, lladdr, new, flags, nlmsg_pid, NULL);
13011426 }
13021427 EXPORT_SYMBOL(neigh_update);
13031428
....@@ -1314,7 +1439,8 @@
13141439 neigh->nud_state = NUD_INCOMPLETE;
13151440 atomic_set(&neigh->probes, neigh_max_probes(neigh));
13161441 neigh_add_timer(neigh,
1317
- jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME));
1442
+ jiffies + max(NEIGH_VAR(neigh->parms, RETRANS_TIME),
1443
+ HZ/100));
13181444 }
13191445 EXPORT_SYMBOL(__neigh_set_probe_once);
13201446
....@@ -1563,6 +1689,7 @@
15631689 unsigned long phsize;
15641690
15651691 INIT_LIST_HEAD(&tbl->parms_list);
1692
+ INIT_LIST_HEAD(&tbl->gc_list);
15661693 list_add(&tbl->parms.list, &tbl->parms_list);
15671694 write_pnet(&tbl->parms.net, &init_net);
15681695 refcount_set(&tbl->parms.refcnt, 1);
....@@ -1614,7 +1741,7 @@
16141741 /* It is not clean... Fix it to unload IPv6 module safely */
16151742 cancel_delayed_work_sync(&tbl->gc_work);
16161743 del_timer_sync(&tbl->proxy_timer);
1617
- pneigh_queue_purge(&tbl->proxy_queue);
1744
+ pneigh_queue_purge(&tbl->proxy_queue, NULL);
16181745 neigh_ifdown(tbl, NULL);
16191746 if (atomic_read(&tbl->entries))
16201747 pr_crit("neighbour leakage\n");
....@@ -1646,13 +1773,26 @@
16461773 case AF_INET6:
16471774 tbl = neigh_tables[NEIGH_ND_TABLE];
16481775 break;
1649
- case AF_DECnet:
1650
- tbl = neigh_tables[NEIGH_DN_TABLE];
1651
- break;
16521776 }
16531777
16541778 return tbl;
16551779 }
1780
+
1781
+const struct nla_policy nda_policy[NDA_MAX+1] = {
1782
+ [NDA_UNSPEC] = { .strict_start_type = NDA_NH_ID },
1783
+ [NDA_DST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1784
+ [NDA_LLADDR] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN },
1785
+ [NDA_CACHEINFO] = { .len = sizeof(struct nda_cacheinfo) },
1786
+ [NDA_PROBES] = { .type = NLA_U32 },
1787
+ [NDA_VLAN] = { .type = NLA_U16 },
1788
+ [NDA_PORT] = { .type = NLA_U16 },
1789
+ [NDA_VNI] = { .type = NLA_U32 },
1790
+ [NDA_IFINDEX] = { .type = NLA_U32 },
1791
+ [NDA_MASTER] = { .type = NLA_U32 },
1792
+ [NDA_PROTOCOL] = { .type = NLA_U8 },
1793
+ [NDA_NH_ID] = { .type = NLA_U32 },
1794
+ [NDA_FDB_EXT_ATTRS] = { .type = NLA_NESTED },
1795
+};
16561796
16571797 static int neigh_delete(struct sk_buff *skb, struct nlmsghdr *nlh,
16581798 struct netlink_ext_ack *extack)
....@@ -1670,8 +1810,10 @@
16701810 goto out;
16711811
16721812 dst_attr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_DST);
1673
- if (dst_attr == NULL)
1813
+ if (!dst_attr) {
1814
+ NL_SET_ERR_MSG(extack, "Network address not specified");
16741815 goto out;
1816
+ }
16751817
16761818 ndm = nlmsg_data(nlh);
16771819 if (ndm->ndm_ifindex) {
....@@ -1686,8 +1828,10 @@
16861828 if (tbl == NULL)
16871829 return -EAFNOSUPPORT;
16881830
1689
- if (nla_len(dst_attr) < (int)tbl->key_len)
1831
+ if (nla_len(dst_attr) < (int)tbl->key_len) {
1832
+ NL_SET_ERR_MSG(extack, "Invalid network address");
16901833 goto out;
1834
+ }
16911835
16921836 if (ndm->ndm_flags & NTF_PROXY) {
16931837 err = pneigh_delete(tbl, net, nla_data(dst_attr), dev);
....@@ -1703,10 +1847,9 @@
17031847 goto out;
17041848 }
17051849
1706
- err = neigh_update(neigh, NULL, NUD_FAILED,
1707
- NEIGH_UPDATE_F_OVERRIDE |
1708
- NEIGH_UPDATE_F_ADMIN,
1709
- NETLINK_CB(skb).portid);
1850
+ err = __neigh_update(neigh, NULL, NUD_FAILED,
1851
+ NEIGH_UPDATE_F_OVERRIDE | NEIGH_UPDATE_F_ADMIN,
1852
+ NETLINK_CB(skb).portid, extack);
17101853 write_lock_bh(&tbl->lock);
17111854 neigh_release(neigh);
17121855 neigh_remove_one(neigh, tbl);
....@@ -1719,7 +1862,8 @@
17191862 static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
17201863 struct netlink_ext_ack *extack)
17211864 {
1722
- int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE;
1865
+ int flags = NEIGH_UPDATE_F_ADMIN | NEIGH_UPDATE_F_OVERRIDE |
1866
+ NEIGH_UPDATE_F_OVERRIDE_ISROUTER;
17231867 struct net *net = sock_net(skb->sk);
17241868 struct ndmsg *ndm;
17251869 struct nlattr *tb[NDA_MAX+1];
....@@ -1727,16 +1871,20 @@
17271871 struct net_device *dev = NULL;
17281872 struct neighbour *neigh;
17291873 void *dst, *lladdr;
1874
+ u8 protocol = 0;
17301875 int err;
17311876
17321877 ASSERT_RTNL();
1733
- err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL, extack);
1878
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ndm), tb, NDA_MAX,
1879
+ nda_policy, extack);
17341880 if (err < 0)
17351881 goto out;
17361882
17371883 err = -EINVAL;
1738
- if (tb[NDA_DST] == NULL)
1884
+ if (!tb[NDA_DST]) {
1885
+ NL_SET_ERR_MSG(extack, "Network address not specified");
17391886 goto out;
1887
+ }
17401888
17411889 ndm = nlmsg_data(nlh);
17421890 if (ndm->ndm_ifindex) {
....@@ -1746,18 +1894,26 @@
17461894 goto out;
17471895 }
17481896
1749
- if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len)
1897
+ if (tb[NDA_LLADDR] && nla_len(tb[NDA_LLADDR]) < dev->addr_len) {
1898
+ NL_SET_ERR_MSG(extack, "Invalid link address");
17501899 goto out;
1900
+ }
17511901 }
17521902
17531903 tbl = neigh_find_table(ndm->ndm_family);
17541904 if (tbl == NULL)
17551905 return -EAFNOSUPPORT;
17561906
1757
- if (nla_len(tb[NDA_DST]) < (int)tbl->key_len)
1907
+ if (nla_len(tb[NDA_DST]) < (int)tbl->key_len) {
1908
+ NL_SET_ERR_MSG(extack, "Invalid network address");
17581909 goto out;
1910
+ }
1911
+
17591912 dst = nla_data(tb[NDA_DST]);
17601913 lladdr = tb[NDA_LLADDR] ? nla_data(tb[NDA_LLADDR]) : NULL;
1914
+
1915
+ if (tb[NDA_PROTOCOL])
1916
+ protocol = nla_get_u8(tb[NDA_PROTOCOL]);
17611917
17621918 if (ndm->ndm_flags & NTF_PROXY) {
17631919 struct pneigh_entry *pn;
....@@ -1766,22 +1922,37 @@
17661922 pn = pneigh_lookup(tbl, net, dst, dev, 1);
17671923 if (pn) {
17681924 pn->flags = ndm->ndm_flags;
1925
+ if (protocol)
1926
+ pn->protocol = protocol;
17691927 err = 0;
17701928 }
17711929 goto out;
17721930 }
17731931
1774
- if (dev == NULL)
1932
+ if (!dev) {
1933
+ NL_SET_ERR_MSG(extack, "Device not specified");
17751934 goto out;
1935
+ }
1936
+
1937
+ if (tbl->allow_add && !tbl->allow_add(dev, extack)) {
1938
+ err = -EINVAL;
1939
+ goto out;
1940
+ }
17761941
17771942 neigh = neigh_lookup(tbl, dst, dev);
17781943 if (neigh == NULL) {
1944
+ bool exempt_from_gc;
1945
+
17791946 if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
17801947 err = -ENOENT;
17811948 goto out;
17821949 }
17831950
1784
- neigh = __neigh_lookup_errno(tbl, dst, dev);
1951
+ exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
1952
+ ndm->ndm_flags & NTF_EXT_LEARNED;
1953
+ neigh = ___neigh_create(tbl, dst, dev,
1954
+ ndm->ndm_flags & NTF_EXT_LEARNED,
1955
+ exempt_from_gc, true);
17851956 if (IS_ERR(neigh)) {
17861957 err = PTR_ERR(neigh);
17871958 goto out;
....@@ -1794,20 +1965,26 @@
17941965 }
17951966
17961967 if (!(nlh->nlmsg_flags & NLM_F_REPLACE))
1797
- flags &= ~NEIGH_UPDATE_F_OVERRIDE;
1968
+ flags &= ~(NEIGH_UPDATE_F_OVERRIDE |
1969
+ NEIGH_UPDATE_F_OVERRIDE_ISROUTER);
17981970 }
17991971
1972
+ if (protocol)
1973
+ neigh->protocol = protocol;
18001974 if (ndm->ndm_flags & NTF_EXT_LEARNED)
18011975 flags |= NEIGH_UPDATE_F_EXT_LEARNED;
1976
+ if (ndm->ndm_flags & NTF_ROUTER)
1977
+ flags |= NEIGH_UPDATE_F_ISROUTER;
1978
+ if (ndm->ndm_flags & NTF_USE)
1979
+ flags |= NEIGH_UPDATE_F_USE;
18021980
1803
- if (ndm->ndm_flags & NTF_USE) {
1981
+ err = __neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1982
+ NETLINK_CB(skb).portid, extack);
1983
+ if (!err && ndm->ndm_flags & NTF_USE) {
18041984 neigh_event_send(neigh, NULL);
18051985 err = 0;
1806
- } else
1807
- err = neigh_update(neigh, lladdr, ndm->ndm_state, flags,
1808
- NETLINK_CB(skb).portid);
1986
+ }
18091987 neigh_release(neigh);
1810
-
18111988 out:
18121989 return err;
18131990 }
....@@ -1816,7 +1993,7 @@
18161993 {
18171994 struct nlattr *nest;
18181995
1819
- nest = nla_nest_start(skb, NDTA_PARMS);
1996
+ nest = nla_nest_start_noflag(skb, NDTA_PARMS);
18201997 if (nest == NULL)
18211998 return -ENOBUFS;
18221999
....@@ -2018,8 +2195,8 @@
20182195 bool found = false;
20192196 int err, tidx;
20202197
2021
- err = nlmsg_parse(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
2022
- nl_neightbl_policy, extack);
2198
+ err = nlmsg_parse_deprecated(nlh, sizeof(*ndtmsg), tb, NDTA_MAX,
2199
+ nl_neightbl_policy, extack);
20232200 if (err < 0)
20242201 goto errout;
20252202
....@@ -2056,8 +2233,9 @@
20562233 struct neigh_parms *p;
20572234 int i, ifindex = 0;
20582235
2059
- err = nla_parse_nested(tbp, NDTPA_MAX, tb[NDTA_PARMS],
2060
- nl_ntbl_parm_policy, extack);
2236
+ err = nla_parse_nested_deprecated(tbp, NDTPA_MAX,
2237
+ tb[NDTA_PARMS],
2238
+ nl_ntbl_parm_policy, extack);
20612239 if (err < 0)
20622240 goto errout_tbl_lock;
20632241
....@@ -2169,15 +2347,47 @@
21692347 return err;
21702348 }
21712349
2350
+static int neightbl_valid_dump_info(const struct nlmsghdr *nlh,
2351
+ struct netlink_ext_ack *extack)
2352
+{
2353
+ struct ndtmsg *ndtm;
2354
+
2355
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndtm))) {
2356
+ NL_SET_ERR_MSG(extack, "Invalid header for neighbor table dump request");
2357
+ return -EINVAL;
2358
+ }
2359
+
2360
+ ndtm = nlmsg_data(nlh);
2361
+ if (ndtm->ndtm_pad1 || ndtm->ndtm_pad2) {
2362
+ NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor table dump request");
2363
+ return -EINVAL;
2364
+ }
2365
+
2366
+ if (nlmsg_attrlen(nlh, sizeof(*ndtm))) {
2367
+ NL_SET_ERR_MSG(extack, "Invalid data after header in neighbor table dump request");
2368
+ return -EINVAL;
2369
+ }
2370
+
2371
+ return 0;
2372
+}
2373
+
21722374 static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
21732375 {
2376
+ const struct nlmsghdr *nlh = cb->nlh;
21742377 struct net *net = sock_net(skb->sk);
21752378 int family, tidx, nidx = 0;
21762379 int tbl_skip = cb->args[0];
21772380 int neigh_skip = cb->args[1];
21782381 struct neigh_table *tbl;
21792382
2180
- family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
2383
+ if (cb->strict_check) {
2384
+ int err = neightbl_valid_dump_info(nlh, cb->extack);
2385
+
2386
+ if (err < 0)
2387
+ return err;
2388
+ }
2389
+
2390
+ family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
21812391
21822392 for (tidx = 0; tidx < NEIGH_NR_TABLES; tidx++) {
21832393 struct neigh_parms *p;
....@@ -2190,7 +2400,7 @@
21902400 continue;
21912401
21922402 if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
2193
- cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
2403
+ nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
21942404 NLM_F_MULTI) < 0)
21952405 break;
21962406
....@@ -2205,7 +2415,7 @@
22052415
22062416 if (neightbl_fill_param_info(skb, tbl, p,
22072417 NETLINK_CB(cb->skb).portid,
2208
- cb->nlh->nlmsg_seq,
2418
+ nlh->nlmsg_seq,
22092419 RTM_NEWNEIGHTBL,
22102420 NLM_F_MULTI) < 0)
22112421 goto out;
....@@ -2267,6 +2477,9 @@
22672477 nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
22682478 goto nla_put_failure;
22692479
2480
+ if (neigh->protocol && nla_put_u8(skb, NDA_PROTOCOL, neigh->protocol))
2481
+ goto nla_put_failure;
2482
+
22702483 nlmsg_end(skb, nlh);
22712484 return 0;
22722485
....@@ -2298,6 +2511,9 @@
22982511 if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
22992512 goto nla_put_failure;
23002513
2514
+ if (pn->protocol && nla_put_u8(skb, NDA_PROTOCOL, pn->protocol))
2515
+ goto nla_put_failure;
2516
+
23012517 nlmsg_end(skb, nlh);
23022518 return 0;
23032519
....@@ -2319,7 +2535,7 @@
23192535 if (!master_idx)
23202536 return false;
23212537
2322
- master = netdev_master_upper_dev_get(dev);
2538
+ master = dev ? netdev_master_upper_dev_get(dev) : NULL;
23232539 if (!master || master->ifindex != master_idx)
23242540 return true;
23252541
....@@ -2328,41 +2544,30 @@
23282544
23292545 static bool neigh_ifindex_filtered(struct net_device *dev, int filter_idx)
23302546 {
2331
- if (filter_idx && dev->ifindex != filter_idx)
2547
+ if (filter_idx && (!dev || dev->ifindex != filter_idx))
23322548 return true;
23332549
23342550 return false;
23352551 }
23362552
2553
+struct neigh_dump_filter {
2554
+ int master_idx;
2555
+ int dev_idx;
2556
+};
2557
+
23372558 static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2338
- struct netlink_callback *cb)
2559
+ struct netlink_callback *cb,
2560
+ struct neigh_dump_filter *filter)
23392561 {
23402562 struct net *net = sock_net(skb->sk);
2341
- const struct nlmsghdr *nlh = cb->nlh;
2342
- struct nlattr *tb[NDA_MAX + 1];
23432563 struct neighbour *n;
23442564 int rc, h, s_h = cb->args[1];
23452565 int idx, s_idx = idx = cb->args[2];
23462566 struct neigh_hash_table *nht;
2347
- int filter_master_idx = 0, filter_idx = 0;
23482567 unsigned int flags = NLM_F_MULTI;
2349
- int err;
23502568
2351
- err = nlmsg_parse(nlh, sizeof(struct ndmsg), tb, NDA_MAX, NULL, NULL);
2352
- if (!err) {
2353
- if (tb[NDA_IFINDEX]) {
2354
- if (nla_len(tb[NDA_IFINDEX]) != sizeof(u32))
2355
- return -EINVAL;
2356
- filter_idx = nla_get_u32(tb[NDA_IFINDEX]);
2357
- }
2358
- if (tb[NDA_MASTER]) {
2359
- if (nla_len(tb[NDA_MASTER]) != sizeof(u32))
2360
- return -EINVAL;
2361
- filter_master_idx = nla_get_u32(tb[NDA_MASTER]);
2362
- }
2363
- if (filter_idx || filter_master_idx)
2364
- flags |= NLM_F_DUMP_FILTERED;
2365
- }
2569
+ if (filter->dev_idx || filter->master_idx)
2570
+ flags |= NLM_F_DUMP_FILTERED;
23662571
23672572 rcu_read_lock_bh();
23682573 nht = rcu_dereference_bh(tbl->nht);
....@@ -2375,8 +2580,8 @@
23752580 n = rcu_dereference_bh(n->next)) {
23762581 if (idx < s_idx || !net_eq(dev_net(n->dev), net))
23772582 goto next;
2378
- if (neigh_ifindex_filtered(n->dev, filter_idx) ||
2379
- neigh_master_filtered(n->dev, filter_master_idx))
2583
+ if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2584
+ neigh_master_filtered(n->dev, filter->master_idx))
23802585 goto next;
23812586 if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
23822587 cb->nlh->nlmsg_seq,
....@@ -2398,12 +2603,17 @@
23982603 }
23992604
24002605 static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
2401
- struct netlink_callback *cb)
2606
+ struct netlink_callback *cb,
2607
+ struct neigh_dump_filter *filter)
24022608 {
24032609 struct pneigh_entry *n;
24042610 struct net *net = sock_net(skb->sk);
24052611 int rc, h, s_h = cb->args[3];
24062612 int idx, s_idx = idx = cb->args[4];
2613
+ unsigned int flags = NLM_F_MULTI;
2614
+
2615
+ if (filter->dev_idx || filter->master_idx)
2616
+ flags |= NLM_F_DUMP_FILTERED;
24072617
24082618 read_lock_bh(&tbl->lock);
24092619
....@@ -2413,10 +2623,12 @@
24132623 for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
24142624 if (idx < s_idx || pneigh_net(n) != net)
24152625 goto next;
2626
+ if (neigh_ifindex_filtered(n->dev, filter->dev_idx) ||
2627
+ neigh_master_filtered(n->dev, filter->master_idx))
2628
+ goto next;
24162629 if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
24172630 cb->nlh->nlmsg_seq,
2418
- RTM_NEWNEIGH,
2419
- NLM_F_MULTI, tbl) < 0) {
2631
+ RTM_NEWNEIGH, flags, tbl) < 0) {
24202632 read_unlock_bh(&tbl->lock);
24212633 rc = -1;
24222634 goto out;
....@@ -2435,21 +2647,88 @@
24352647
24362648 }
24372649
2650
+static int neigh_valid_dump_req(const struct nlmsghdr *nlh,
2651
+ bool strict_check,
2652
+ struct neigh_dump_filter *filter,
2653
+ struct netlink_ext_ack *extack)
2654
+{
2655
+ struct nlattr *tb[NDA_MAX + 1];
2656
+ int err, i;
2657
+
2658
+ if (strict_check) {
2659
+ struct ndmsg *ndm;
2660
+
2661
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2662
+ NL_SET_ERR_MSG(extack, "Invalid header for neighbor dump request");
2663
+ return -EINVAL;
2664
+ }
2665
+
2666
+ ndm = nlmsg_data(nlh);
2667
+ if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_ifindex ||
2668
+ ndm->ndm_state || ndm->ndm_type) {
2669
+ NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor dump request");
2670
+ return -EINVAL;
2671
+ }
2672
+
2673
+ if (ndm->ndm_flags & ~NTF_PROXY) {
2674
+ NL_SET_ERR_MSG(extack, "Invalid flags in header for neighbor dump request");
2675
+ return -EINVAL;
2676
+ }
2677
+
2678
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg),
2679
+ tb, NDA_MAX, nda_policy,
2680
+ extack);
2681
+ } else {
2682
+ err = nlmsg_parse_deprecated(nlh, sizeof(struct ndmsg), tb,
2683
+ NDA_MAX, nda_policy, extack);
2684
+ }
2685
+ if (err < 0)
2686
+ return err;
2687
+
2688
+ for (i = 0; i <= NDA_MAX; ++i) {
2689
+ if (!tb[i])
2690
+ continue;
2691
+
2692
+ /* all new attributes should require strict_check */
2693
+ switch (i) {
2694
+ case NDA_IFINDEX:
2695
+ filter->dev_idx = nla_get_u32(tb[i]);
2696
+ break;
2697
+ case NDA_MASTER:
2698
+ filter->master_idx = nla_get_u32(tb[i]);
2699
+ break;
2700
+ default:
2701
+ if (strict_check) {
2702
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor dump request");
2703
+ return -EINVAL;
2704
+ }
2705
+ }
2706
+ }
2707
+
2708
+ return 0;
2709
+}
2710
+
24382711 static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
24392712 {
2713
+ const struct nlmsghdr *nlh = cb->nlh;
2714
+ struct neigh_dump_filter filter = {};
24402715 struct neigh_table *tbl;
24412716 int t, family, s_t;
24422717 int proxy = 0;
24432718 int err;
24442719
2445
- family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family;
2720
+ family = ((struct rtgenmsg *)nlmsg_data(nlh))->rtgen_family;
24462721
24472722 /* check for full ndmsg structure presence, family member is
24482723 * the same for both structures
24492724 */
2450
- if (nlmsg_len(cb->nlh) >= sizeof(struct ndmsg) &&
2451
- ((struct ndmsg *) nlmsg_data(cb->nlh))->ndm_flags == NTF_PROXY)
2725
+ if (nlmsg_len(nlh) >= sizeof(struct ndmsg) &&
2726
+ ((struct ndmsg *)nlmsg_data(nlh))->ndm_flags == NTF_PROXY)
24522727 proxy = 1;
2728
+
2729
+ err = neigh_valid_dump_req(nlh, cb->strict_check, &filter, cb->extack);
2730
+ if (err < 0 && cb->strict_check)
2731
+ return err;
24532732
24542733 s_t = cb->args[0];
24552734
....@@ -2464,15 +2743,195 @@
24642743 memset(&cb->args[1], 0, sizeof(cb->args) -
24652744 sizeof(cb->args[0]));
24662745 if (proxy)
2467
- err = pneigh_dump_table(tbl, skb, cb);
2746
+ err = pneigh_dump_table(tbl, skb, cb, &filter);
24682747 else
2469
- err = neigh_dump_table(tbl, skb, cb);
2748
+ err = neigh_dump_table(tbl, skb, cb, &filter);
24702749 if (err < 0)
24712750 break;
24722751 }
24732752
24742753 cb->args[0] = t;
24752754 return skb->len;
2755
+}
2756
+
2757
+static int neigh_valid_get_req(const struct nlmsghdr *nlh,
2758
+ struct neigh_table **tbl,
2759
+ void **dst, int *dev_idx, u8 *ndm_flags,
2760
+ struct netlink_ext_ack *extack)
2761
+{
2762
+ struct nlattr *tb[NDA_MAX + 1];
2763
+ struct ndmsg *ndm;
2764
+ int err, i;
2765
+
2766
+ if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ndm))) {
2767
+ NL_SET_ERR_MSG(extack, "Invalid header for neighbor get request");
2768
+ return -EINVAL;
2769
+ }
2770
+
2771
+ ndm = nlmsg_data(nlh);
2772
+ if (ndm->ndm_pad1 || ndm->ndm_pad2 || ndm->ndm_state ||
2773
+ ndm->ndm_type) {
2774
+ NL_SET_ERR_MSG(extack, "Invalid values in header for neighbor get request");
2775
+ return -EINVAL;
2776
+ }
2777
+
2778
+ if (ndm->ndm_flags & ~NTF_PROXY) {
2779
+ NL_SET_ERR_MSG(extack, "Invalid flags in header for neighbor get request");
2780
+ return -EINVAL;
2781
+ }
2782
+
2783
+ err = nlmsg_parse_deprecated_strict(nlh, sizeof(struct ndmsg), tb,
2784
+ NDA_MAX, nda_policy, extack);
2785
+ if (err < 0)
2786
+ return err;
2787
+
2788
+ *ndm_flags = ndm->ndm_flags;
2789
+ *dev_idx = ndm->ndm_ifindex;
2790
+ *tbl = neigh_find_table(ndm->ndm_family);
2791
+ if (*tbl == NULL) {
2792
+ NL_SET_ERR_MSG(extack, "Unsupported family in header for neighbor get request");
2793
+ return -EAFNOSUPPORT;
2794
+ }
2795
+
2796
+ for (i = 0; i <= NDA_MAX; ++i) {
2797
+ if (!tb[i])
2798
+ continue;
2799
+
2800
+ switch (i) {
2801
+ case NDA_DST:
2802
+ if (nla_len(tb[i]) != (int)(*tbl)->key_len) {
2803
+ NL_SET_ERR_MSG(extack, "Invalid network address in neighbor get request");
2804
+ return -EINVAL;
2805
+ }
2806
+ *dst = nla_data(tb[i]);
2807
+ break;
2808
+ default:
2809
+ NL_SET_ERR_MSG(extack, "Unsupported attribute in neighbor get request");
2810
+ return -EINVAL;
2811
+ }
2812
+ }
2813
+
2814
+ return 0;
2815
+}
2816
+
2817
+static inline size_t neigh_nlmsg_size(void)
2818
+{
2819
+ return NLMSG_ALIGN(sizeof(struct ndmsg))
2820
+ + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2821
+ + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2822
+ + nla_total_size(sizeof(struct nda_cacheinfo))
2823
+ + nla_total_size(4) /* NDA_PROBES */
2824
+ + nla_total_size(1); /* NDA_PROTOCOL */
2825
+}
2826
+
2827
+static int neigh_get_reply(struct net *net, struct neighbour *neigh,
2828
+ u32 pid, u32 seq)
2829
+{
2830
+ struct sk_buff *skb;
2831
+ int err = 0;
2832
+
2833
+ skb = nlmsg_new(neigh_nlmsg_size(), GFP_KERNEL);
2834
+ if (!skb)
2835
+ return -ENOBUFS;
2836
+
2837
+ err = neigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0);
2838
+ if (err) {
2839
+ kfree_skb(skb);
2840
+ goto errout;
2841
+ }
2842
+
2843
+ err = rtnl_unicast(skb, net, pid);
2844
+errout:
2845
+ return err;
2846
+}
2847
+
2848
+static inline size_t pneigh_nlmsg_size(void)
2849
+{
2850
+ return NLMSG_ALIGN(sizeof(struct ndmsg))
2851
+ + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2852
+ + nla_total_size(1); /* NDA_PROTOCOL */
2853
+}
2854
+
2855
+static int pneigh_get_reply(struct net *net, struct pneigh_entry *neigh,
2856
+ u32 pid, u32 seq, struct neigh_table *tbl)
2857
+{
2858
+ struct sk_buff *skb;
2859
+ int err = 0;
2860
+
2861
+ skb = nlmsg_new(pneigh_nlmsg_size(), GFP_KERNEL);
2862
+ if (!skb)
2863
+ return -ENOBUFS;
2864
+
2865
+ err = pneigh_fill_info(skb, neigh, pid, seq, RTM_NEWNEIGH, 0, tbl);
2866
+ if (err) {
2867
+ kfree_skb(skb);
2868
+ goto errout;
2869
+ }
2870
+
2871
+ err = rtnl_unicast(skb, net, pid);
2872
+errout:
2873
+ return err;
2874
+}
2875
+
2876
+static int neigh_get(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2877
+ struct netlink_ext_ack *extack)
2878
+{
2879
+ struct net *net = sock_net(in_skb->sk);
2880
+ struct net_device *dev = NULL;
2881
+ struct neigh_table *tbl = NULL;
2882
+ struct neighbour *neigh;
2883
+ void *dst = NULL;
2884
+ u8 ndm_flags = 0;
2885
+ int dev_idx = 0;
2886
+ int err;
2887
+
2888
+ err = neigh_valid_get_req(nlh, &tbl, &dst, &dev_idx, &ndm_flags,
2889
+ extack);
2890
+ if (err < 0)
2891
+ return err;
2892
+
2893
+ if (dev_idx) {
2894
+ dev = __dev_get_by_index(net, dev_idx);
2895
+ if (!dev) {
2896
+ NL_SET_ERR_MSG(extack, "Unknown device ifindex");
2897
+ return -ENODEV;
2898
+ }
2899
+ }
2900
+
2901
+ if (!dst) {
2902
+ NL_SET_ERR_MSG(extack, "Network address not specified");
2903
+ return -EINVAL;
2904
+ }
2905
+
2906
+ if (ndm_flags & NTF_PROXY) {
2907
+ struct pneigh_entry *pn;
2908
+
2909
+ pn = pneigh_lookup(tbl, net, dst, dev, 0);
2910
+ if (!pn) {
2911
+ NL_SET_ERR_MSG(extack, "Proxy neighbour entry not found");
2912
+ return -ENOENT;
2913
+ }
2914
+ return pneigh_get_reply(net, pn, NETLINK_CB(in_skb).portid,
2915
+ nlh->nlmsg_seq, tbl);
2916
+ }
2917
+
2918
+ if (!dev) {
2919
+ NL_SET_ERR_MSG(extack, "No device specified");
2920
+ return -EINVAL;
2921
+ }
2922
+
2923
+ neigh = neigh_lookup(tbl, dst, dev);
2924
+ if (!neigh) {
2925
+ NL_SET_ERR_MSG(extack, "Neighbour entry not found");
2926
+ return -ENOENT;
2927
+ }
2928
+
2929
+ err = neigh_get_reply(net, neigh, NETLINK_CB(in_skb).portid,
2930
+ nlh->nlmsg_seq);
2931
+
2932
+ neigh_release(neigh);
2933
+
2934
+ return err;
24762935 }
24772936
24782937 void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void *), void *cookie)
....@@ -2521,7 +2980,7 @@
25212980 rcu_assign_pointer(*np,
25222981 rcu_dereference_protected(n->next,
25232982 lockdep_is_held(&tbl->lock)));
2524
- n->dead = 1;
2983
+ neigh_mark_dead(n);
25252984 } else
25262985 np = &n->next;
25272986 write_unlock(&n->lock);
....@@ -2584,7 +3043,7 @@
25843043 struct net *net = seq_file_net(seq);
25853044 struct neigh_hash_table *nht = state->nht;
25863045 struct neighbour *n = NULL;
2587
- int bucket = state->bucket;
3046
+ int bucket;
25883047
25893048 state->flags &= ~NEIGH_SEQ_IS_PNEIGH;
25903049 for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) {
....@@ -2896,15 +3355,6 @@
28963355 };
28973356 #endif /* CONFIG_PROC_FS */
28983357
2899
-static inline size_t neigh_nlmsg_size(void)
2900
-{
2901
- return NLMSG_ALIGN(sizeof(struct ndmsg))
2902
- + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2903
- + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2904
- + nla_total_size(sizeof(struct nda_cacheinfo))
2905
- + nla_total_size(4); /* NDA_PROBES */
2906
-}
2907
-
29083358 static void __neigh_notify(struct neighbour *n, int type, int flags,
29093359 u32 pid)
29103360 {
....@@ -2937,17 +3387,15 @@
29373387 EXPORT_SYMBOL(neigh_app_ns);
29383388
29393389 #ifdef CONFIG_SYSCTL
2940
-static int zero;
2941
-static int int_max = INT_MAX;
29423390 static int unres_qlen_max = INT_MAX / SKB_TRUESIZE(ETH_FRAME_LEN);
29433391
29443392 static int proc_unres_qlen(struct ctl_table *ctl, int write,
2945
- void __user *buffer, size_t *lenp, loff_t *ppos)
3393
+ void *buffer, size_t *lenp, loff_t *ppos)
29463394 {
29473395 int size, ret;
29483396 struct ctl_table tmp = *ctl;
29493397
2950
- tmp.extra1 = &zero;
3398
+ tmp.extra1 = SYSCTL_ZERO;
29513399 tmp.extra2 = &unres_qlen_max;
29523400 tmp.data = &size;
29533401
....@@ -3006,22 +3454,22 @@
30063454 }
30073455
30083456 static int neigh_proc_dointvec_zero_intmax(struct ctl_table *ctl, int write,
3009
- void __user *buffer,
3010
- size_t *lenp, loff_t *ppos)
3457
+ void *buffer, size_t *lenp,
3458
+ loff_t *ppos)
30113459 {
30123460 struct ctl_table tmp = *ctl;
30133461 int ret;
30143462
3015
- tmp.extra1 = &zero;
3016
- tmp.extra2 = &int_max;
3463
+ tmp.extra1 = SYSCTL_ZERO;
3464
+ tmp.extra2 = SYSCTL_INT_MAX;
30173465
30183466 ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
30193467 neigh_proc_update(ctl, write);
30203468 return ret;
30213469 }
30223470
3023
-int neigh_proc_dointvec(struct ctl_table *ctl, int write,
3024
- void __user *buffer, size_t *lenp, loff_t *ppos)
3471
+int neigh_proc_dointvec(struct ctl_table *ctl, int write, void *buffer,
3472
+ size_t *lenp, loff_t *ppos)
30253473 {
30263474 int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
30273475
....@@ -3030,8 +3478,7 @@
30303478 }
30313479 EXPORT_SYMBOL(neigh_proc_dointvec);
30323480
3033
-int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write,
3034
- void __user *buffer,
3481
+int neigh_proc_dointvec_jiffies(struct ctl_table *ctl, int write, void *buffer,
30353482 size_t *lenp, loff_t *ppos)
30363483 {
30373484 int ret = proc_dointvec_jiffies(ctl, write, buffer, lenp, ppos);
....@@ -3042,8 +3489,8 @@
30423489 EXPORT_SYMBOL(neigh_proc_dointvec_jiffies);
30433490
30443491 static int neigh_proc_dointvec_userhz_jiffies(struct ctl_table *ctl, int write,
3045
- void __user *buffer,
3046
- size_t *lenp, loff_t *ppos)
3492
+ void *buffer, size_t *lenp,
3493
+ loff_t *ppos)
30473494 {
30483495 int ret = proc_dointvec_userhz_jiffies(ctl, write, buffer, lenp, ppos);
30493496
....@@ -3052,8 +3499,7 @@
30523499 }
30533500
30543501 int neigh_proc_dointvec_ms_jiffies(struct ctl_table *ctl, int write,
3055
- void __user *buffer,
3056
- size_t *lenp, loff_t *ppos)
3502
+ void *buffer, size_t *lenp, loff_t *ppos)
30573503 {
30583504 int ret = proc_dointvec_ms_jiffies(ctl, write, buffer, lenp, ppos);
30593505
....@@ -3063,8 +3509,8 @@
30633509 EXPORT_SYMBOL(neigh_proc_dointvec_ms_jiffies);
30643510
30653511 static int neigh_proc_dointvec_unres_qlen(struct ctl_table *ctl, int write,
3066
- void __user *buffer,
3067
- size_t *lenp, loff_t *ppos)
3512
+ void *buffer, size_t *lenp,
3513
+ loff_t *ppos)
30683514 {
30693515 int ret = proc_unres_qlen(ctl, write, buffer, lenp, ppos);
30703516
....@@ -3073,8 +3519,8 @@
30733519 }
30743520
30753521 static int neigh_proc_base_reachable_time(struct ctl_table *ctl, int write,
3076
- void __user *buffer,
3077
- size_t *lenp, loff_t *ppos)
3522
+ void *buffer, size_t *lenp,
3523
+ loff_t *ppos)
30783524 {
30793525 struct neigh_parms *p = ctl->extra2;
30803526 int ret;
....@@ -3118,9 +3564,6 @@
31183564 #define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \
31193565 NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
31203566
3121
-#define NEIGH_SYSCTL_MS_JIFFIES_ENTRY(attr, name) \
3122
- NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
3123
-
31243567 #define NEIGH_SYSCTL_MS_JIFFIES_REUSED_ENTRY(attr, data_attr, name) \
31253568 NEIGH_SYSCTL_ENTRY(attr, data_attr, name, 0644, neigh_proc_dointvec_ms_jiffies)
31263569
....@@ -3158,24 +3601,24 @@
31583601 .procname = "gc_thresh1",
31593602 .maxlen = sizeof(int),
31603603 .mode = 0644,
3161
- .extra1 = &zero,
3162
- .extra2 = &int_max,
3604
+ .extra1 = SYSCTL_ZERO,
3605
+ .extra2 = SYSCTL_INT_MAX,
31633606 .proc_handler = proc_dointvec_minmax,
31643607 },
31653608 [NEIGH_VAR_GC_THRESH2] = {
31663609 .procname = "gc_thresh2",
31673610 .maxlen = sizeof(int),
31683611 .mode = 0644,
3169
- .extra1 = &zero,
3170
- .extra2 = &int_max,
3612
+ .extra1 = SYSCTL_ZERO,
3613
+ .extra2 = SYSCTL_INT_MAX,
31713614 .proc_handler = proc_dointvec_minmax,
31723615 },
31733616 [NEIGH_VAR_GC_THRESH3] = {
31743617 .procname = "gc_thresh3",
31753618 .maxlen = sizeof(int),
31763619 .mode = 0644,
3177
- .extra1 = &zero,
3178
- .extra2 = &int_max,
3620
+ .extra1 = SYSCTL_ZERO,
3621
+ .extra2 = SYSCTL_INT_MAX,
31793622 .proc_handler = proc_dointvec_minmax,
31803623 },
31813624 {},
....@@ -3288,7 +3731,7 @@
32883731 {
32893732 rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
32903733 rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
3291
- rtnl_register(PF_UNSPEC, RTM_GETNEIGH, NULL, neigh_dump_info, 0);
3734
+ rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info, 0);
32923735
32933736 rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
32943737 0);