Skip to content

Commit e4400bb

Browse files
borkmanndavem330
authored andcommitted
net, neigh: Fix NTF_EXT_LEARNED in combination with NTF_USE
The NTF_EXT_LEARNED neigh flag is usually propagated back to user space upon dump of the neighbor table. However, when used in combination with NTF_USE flag this is not the case despite exempting the entry from the garbage collector. This results in inconsistent state since entries are typically marked in neigh->flags with NTF_EXT_LEARNED, but here they are not. Fix it by propagating the creation flag to ___neigh_create(). Before fix: # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn # ./ip/ip n 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a REACHABLE [...] After fix: # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn # ./ip/ip n 192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE [...] Fixes: 9ce33e4 ("neighbour: support for NTF_EXT_LEARNED flag") Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Roopa Prabhu <roopa@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7bb39a3 commit e4400bb

File tree

1 file changed

+14
-12
lines changed

1 file changed

+14
-12
lines changed

net/core/neighbour.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ EXPORT_SYMBOL(neigh_ifdown);
379379

380380
static struct neighbour *neigh_alloc(struct neigh_table *tbl,
381381
struct net_device *dev,
382-
bool exempt_from_gc)
382+
u8 flags, bool exempt_from_gc)
383383
{
384384
struct neighbour *n = NULL;
385385
unsigned long now = jiffies;
@@ -412,6 +412,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl,
412412
n->updated = n->used = now;
413413
n->nud_state = NUD_NONE;
414414
n->output = neigh_blackhole;
415+
n->flags = flags;
415416
seqlock_init(&n->hh.hh_lock);
416417
n->parms = neigh_parms_clone(&tbl->parms);
417418
timer_setup(&n->timer, neigh_timer_handler, 0);
@@ -575,19 +576,18 @@ struct neighbour *neigh_lookup_nodev(struct neigh_table *tbl, struct net *net,
575576
}
576577
EXPORT_SYMBOL(neigh_lookup_nodev);
577578

578-
static struct neighbour *___neigh_create(struct neigh_table *tbl,
579-
const void *pkey,
580-
struct net_device *dev,
581-
bool exempt_from_gc, bool want_ref)
579+
static struct neighbour *
580+
___neigh_create(struct neigh_table *tbl, const void *pkey,
581+
struct net_device *dev, u8 flags,
582+
bool exempt_from_gc, bool want_ref)
582583
{
583-
struct neighbour *n1, *rc, *n = neigh_alloc(tbl, dev, exempt_from_gc);
584-
u32 hash_val;
585-
unsigned int key_len = tbl->key_len;
586-
int error;
584+
u32 hash_val, key_len = tbl->key_len;
585+
struct neighbour *n1, *rc, *n;
587586
struct neigh_hash_table *nht;
587+
int error;
588588

589+
n = neigh_alloc(tbl, dev, flags, exempt_from_gc);
589590
trace_neigh_create(tbl, dev, pkey, n, exempt_from_gc);
590-
591591
if (!n) {
592592
rc = ERR_PTR(-ENOBUFS);
593593
goto out;
@@ -674,7 +674,7 @@ static struct neighbour *___neigh_create(struct neigh_table *tbl,
674674
struct neighbour *__neigh_create(struct neigh_table *tbl, const void *pkey,
675675
struct net_device *dev, bool want_ref)
676676
{
677-
return ___neigh_create(tbl, pkey, dev, false, want_ref);
677+
return ___neigh_create(tbl, pkey, dev, 0, false, want_ref);
678678
}
679679
EXPORT_SYMBOL(__neigh_create);
680680

@@ -1942,7 +1942,9 @@ static int neigh_add(struct sk_buff *skb, struct nlmsghdr *nlh,
19421942

19431943
exempt_from_gc = ndm->ndm_state & NUD_PERMANENT ||
19441944
ndm->ndm_flags & NTF_EXT_LEARNED;
1945-
neigh = ___neigh_create(tbl, dst, dev, exempt_from_gc, true);
1945+
neigh = ___neigh_create(tbl, dst, dev,
1946+
ndm->ndm_flags & NTF_EXT_LEARNED,
1947+
exempt_from_gc, true);
19461948
if (IS_ERR(neigh)) {
19471949
err = PTR_ERR(neigh);
19481950
goto out;

0 commit comments

Comments
 (0)