aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Chagin <dchagin@FreeBSD.org>2023-02-23 08:01:18 +0000
committerDmitry Chagin <dchagin@FreeBSD.org>2023-02-26 08:10:44 +0000
commit123ca9ab11896f356245537ee41207fb6943fccd (patch)
tree0fc6d70244f2b0301a6a1e9ec2beada9cb9f4377
parenta83551a52d1cfa8a756ef8dd298cab8042e27437 (diff)
downloadsrc-123ca9ab11896f356245537ee41207fb6943fccd.tar.gz
src-123ca9ab11896f356245537ee41207fb6943fccd.zip
linux(4): Fixup the interface name translation in netlink
Netlink should translate a FreeBSD interface name to a Linux interface name. Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D38715 MFC after: 3 days (cherry picked from commit e55e4a6ba3f4cd31d47b74574ea7370d5ab14b48)
-rw-r--r--sys/compat/linux/linux_netlink.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/sys/compat/linux/linux_netlink.c b/sys/compat/linux/linux_netlink.c
index bcbf39cdcb85..4fc962c7ea0b 100644
--- a/sys/compat/linux/linux_netlink.c
+++ b/sys/compat/linux/linux_netlink.c
@@ -220,10 +220,52 @@ 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.
+ */
+static int
+nlmsg_translate_all_nla(struct nlmsghdr *hdr, struct nlattr *nla,
+ struct nl_writer *nw)
+{
+
+ switch (hdr->nlmsg_type) {
+ case NL_RTM_NEWLINK:
+ case NL_RTM_DELLINK:
+ case NL_RTM_GETLINK:
+ switch (nla->nla_type) {
+ case IFLA_IFNAME:
+ return (nlmsg_translate_ifname_nla(nla, nw));
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ return (LINUX_NLA_UNHANDLED);
+}
+
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;
@@ -234,11 +276,15 @@ nlmsg_copy_all_nla(struct nlmsghdr *hdr, int raw_hdrlen, struct nl_writer *nw)
if (nla->nla_len < sizeof(struct nlattr)) {
return (false);
}
- if (!nlmsg_copy_nla(nla, nw))
+ ret = nlmsg_translate_all_nla(hdr, nla, nw);
+ if (ret == LINUX_NLA_UNHANDLED)
+ ret = nlmsg_copy_nla(nla, nw);
+ if (!ret)
return (false);
}
return (true);
}
+#undef LINUX_NLA_UNHANDLED
static unsigned int
rtnl_if_flags_to_linux(unsigned int if_flags)