git: 554907bac3b2 - main - linux: fix reporting NL_RTM_DELLINK to Netlink sockets

From: Gleb Smirnoff <glebius_at_FreeBSD.org>
Date: Fri, 22 Aug 2025 16:24:07 UTC
The branch main has been updated by glebius:

URL: https://cgit.FreeBSD.org/src/commit/?id=554907bac3b264863a051f75eedc35d180d3e18c

commit 554907bac3b264863a051f75eedc35d180d3e18c
Author:     Gleb Smirnoff <glebius@FreeBSD.org>
AuthorDate: 2025-08-22 16:23:28 +0000
Commit:     Gleb Smirnoff <glebius@FreeBSD.org>
CommitDate: 2025-08-22 16:23:28 +0000

    linux: fix reporting NL_RTM_DELLINK to Netlink sockets
    
    The problem is that ifname_bsd_to_linux_name() requires the interface to
    exist.  But when we are in the context of ifnet_departure_event
    EVENTHANDLER(9), it does not.  Instead of silently dropping the message,
    let's send the FreeBSD name verbatim.  At the moment special translation
    is done for IFT_LOOPBACK and IFT_ETHER only, and these two kinds of
    interfaces usually don't depart.  So, this is not a final fix, but
    definitely an improvement.  While here, simplify the associated code.
    
    Differential Revision:  https://reviews.freebsd.org/D51927
---
 sys/compat/linux/linux_netlink.c | 39 +++++++++++++--------------------------
 1 file changed, 13 insertions(+), 26 deletions(-)

diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c
index f51838ee00d7..d414fad375c0 100644
--- a/sys/compat/linux/linux_netlink.c
+++ b/sys/compat/linux/linux_netlink.c
@@ -241,25 +241,10 @@ nlmsg_copy_nla(const struct nlattr *nla_orig, struct nl_writer *nw)
 	return (false);
 }
 
-/*
- * Translate a FreeBSD interface name to a Linux interface name.
- */
-static bool
-nlmsg_translate_ifname_nla(struct nlattr *nla, struct nl_writer *nw)
-{
-	char ifname[LINUX_IFNAMSIZ];
-
-	if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
-	    sizeof(ifname)) <= 0)
-		return (false);
-	return (nlattr_add_string(nw, IFLA_IFNAME, ifname));
-}
-
-#define	LINUX_NLA_UNHANDLED	-1
 /*
  * Translate a FreeBSD attribute to a Linux attribute.
- * Returns LINUX_NLA_UNHANDLED when the attribute is not processed
- * and the caller must take care of it, otherwise the result is returned.
+ * Returns false when the attribute is not processed and the caller must take
+ * care of it.
  */
 static int
 nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla,
@@ -271,22 +256,27 @@ nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla,
 	case NL_RTM_DELLINK:
 	case NL_RTM_GETLINK:
 		switch (nla->nla_type) {
-		case IFLA_IFNAME:
-			return (nlmsg_translate_ifname_nla(nla, nw));
+		case IFLA_IFNAME: {
+			char ifname[LINUX_IFNAMSIZ];
+
+			if (ifname_bsd_to_linux_name((char *)(nla + 1), ifname,
+			    sizeof(ifname)) > 0)
+				return (true);
+			break;
+		}
 		default:
 			break;
 		}
 	default:
 		break;
 	}
-	return (LINUX_NLA_UNHANDLED);
+	return (false);
 }
 
 static bool
 nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw)
 {
 	struct nlattr *nla;
-	int ret;
 
 	int hdrlen = NETLINK_ALIGN(raw_hdrlen);
 	int attrs_len = hdr->nlmsg_len - sizeof(struct nlmsghdr) - hdrlen;
@@ -297,15 +287,12 @@ nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw)
 		if (nla->nla_len < sizeof(struct nlattr)) {
 			return (false);
 		}
-		ret = nlmsg_translate_all_nla(hdr, nla, nw);
-		if (ret == LINUX_NLA_UNHANDLED)
-			ret = nlmsg_copy_nla(nla, nw);
-		if (!ret)
+		if (!nlmsg_translate_all_nla(hdr, nla, nw) &&
+		    !nlmsg_copy_nla(nla, nw))
 			return (false);
 	}
 	return (true);
 }
-#undef LINUX_NLA_UNHANDLED
 
 static unsigned int
 rtnl_if_flags_to_linux(unsigned int if_flags)