From f062ebcb42ea230a488fb0a510ffe4fbd5a5b74c Mon Sep 17 00:00:00 2001
From: Ronan Dalton <ronan.dalton@alliedtelesis.co.nz>
Date: Fri, 13 Sep 2024 17:01:14 +1200
Subject: [PATCH] lib/route: unset locked ext flag in neigh msg

The kernel does not allow setting the NTF_EXT_LOCKED neigh ext flag from
userspace, so unset it in requests. This would avoid the error that
would occur when an FDB entry with the locked flag is retrieved from the
kernel, modified, and accidentally send back to the kernel without
unsetting the locked flag first.

In addition, only send the ext flags if at least one is set.
---
 lib/route/neigh.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index aec988c9..fd883ec3 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -777,8 +777,15 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
 	if (tmpl->ce_mask & NEIGH_ATTR_NHID)
 		NLA_PUT_U32(msg, NDA_NH_ID, tmpl->n_nhid);
 
-	if (tmpl->ce_mask & NEIGH_ATTR_EXT_FLAGS)
-		NLA_PUT_U32(msg, NDA_FLAGS_EXT, tmpl->n_ext_flags);
+	if (tmpl->ce_mask & NEIGH_ATTR_EXT_FLAGS) {
+		/* The kernel does not allow setting the locked flag from
+		 * userspace, so unset it in the request. */
+		uint32_t ext_flags = tmpl->n_ext_flags &
+				     ~(uint32_t)NTF_EXT_LOCKED;
+
+		if (ext_flags)
+			NLA_PUT_U32(msg, NDA_FLAGS_EXT, ext_flags);
+	}
 
 	*result = msg;
 	return 0;