All of lore.kernel.org
 help / color / mirror / Atom feed
From: Michal Kubecek <mkubecek@suse.cz>
To: John Linville <linville@tuxdriver.com>, netdev@vger.kernel.org
Cc: Andrew Lunn <andrew@lunn.ch>, Florian Fainelli <f.fainelli@gmail.com>
Subject: [PATCH ethtool v3 20/25] netlink: add handler for permaddr (-P)
Date: Fri,  6 Mar 2020 18:05:40 +0100 (CET)	[thread overview]
Message-ID: <f3ed37731543cb105493f3ef56d7d4299e173e3b.1583513281.git.mkubecek@suse.cz> (raw)
In-Reply-To: <cover.1583513281.git.mkubecek@suse.cz>

Implement "ethtool -P <dev>" subcommand. This retrieves and displays
information traditionally provided by ETHTOOL_GPERMADDR ioctl request.

Permanent hardware address is provided by rtnetlink RTM_GETLINK request
so that basic support for rtnetlink (which is not based on genetlink)
requests is also added.

The IFLA_PERM_ADDRESS attribute in RTM_NEWLINK message is not set if the
device driver did not set its permanent hardware address which is hard to
distinguish from ethtool running on top of an older kernel not supporting
the attribute. As IFLA_PERM_ADDRESS attribute was added to kernel shortly
before the initial portion of ethtool netlink interface, we let ethtool
initialize ethtool netlink even if it is not needed so that we can fall
back to ioctl on older kernels and assume that absence of IFLA_PERM_ADDRESS
means the permanent address is not set. This would be only wrong on some
distribution kernel which would backport ethtool netlink interface but not
IFLA_PERM_ADDRESS which is unlikely.

Permanent address is immutable (or not mutable using standard interfaces)
so that there is no related notification message.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
---
 Makefile.am        |   1 +
 ethtool.c          |   1 +
 netlink/extapi.h   |   2 +
 netlink/netlink.h  |   8 ++++
 netlink/permaddr.c | 114 +++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 126 insertions(+)
 create mode 100644 netlink/permaddr.c

diff --git a/Makefile.am b/Makefile.am
index 30cda5b1fc6f..11acdab1a65e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -30,6 +30,7 @@ ethtool_SOURCES += \
 		  netlink/nlsock.h netlink/strset.c netlink/strset.h \
 		  netlink/monitor.c netlink/bitset.c netlink/bitset.h \
 		  netlink/settings.c netlink/parser.c netlink/parser.h \
+		  netlink/permaddr.c \
 		  uapi/linux/ethtool_netlink.h \
 		  uapi/linux/netlink.h uapi/linux/genetlink.h \
 		  uapi/linux/rtnetlink.h uapi/linux/if_link.h
diff --git a/ethtool.c b/ethtool.c
index baa6458bb486..1b4e08b6e60f 100644
--- a/ethtool.c
+++ b/ethtool.c
@@ -5372,6 +5372,7 @@ static const struct option args[] = {
 	{
 		.opts	= "-P|--show-permaddr",
 		.func	= do_permaddr,
+		.nlfunc	= nl_permaddr,
 		.help	= "Show permanent hardware address"
 	},
 	{
diff --git a/netlink/extapi.h b/netlink/extapi.h
index 612002e8228b..d5b3cd92d4ab 100644
--- a/netlink/extapi.h
+++ b/netlink/extapi.h
@@ -17,6 +17,7 @@ void netlink_done(struct cmd_context *ctx);
 
 int nl_gset(struct cmd_context *ctx);
 int nl_sset(struct cmd_context *ctx);
+int nl_permaddr(struct cmd_context *ctx);
 int nl_monitor(struct cmd_context *ctx);
 
 void nl_monitor_usage(void);
@@ -38,6 +39,7 @@ static inline void nl_monitor_usage(void)
 
 #define nl_gset			NULL
 #define nl_sset			NULL
+#define nl_permaddr		NULL
 
 #endif /* ETHTOOL_ENABLE_NETLINK */
 
diff --git a/netlink/netlink.h b/netlink/netlink.h
index 3ab5f2329e2f..db078d28fabb 100644
--- a/netlink/netlink.h
+++ b/netlink/netlink.h
@@ -27,6 +27,7 @@ struct nl_context {
 	uint32_t		ethnl_mongrp;
 	struct nl_socket	*ethnl_socket;
 	struct nl_socket	*ethnl2_socket;
+	struct nl_socket	*rtnl_socket;
 	bool			is_monitor;
 	uint32_t		filter_cmds[CMDMASK_WORDS];
 	const char		*filter_devname;
@@ -76,4 +77,11 @@ static inline int netlink_init_ethnl2_socket(struct nl_context *nlctx)
 	return nlsock_init(nlctx, &nlctx->ethnl2_socket, NETLINK_GENERIC);
 }
 
+static inline int netlink_init_rtnl_socket(struct nl_context *nlctx)
+{
+	if (nlctx->rtnl_socket)
+		return 0;
+	return nlsock_init(nlctx, &nlctx->rtnl_socket, NETLINK_ROUTE);
+}
+
 #endif /* ETHTOOL_NETLINK_INT_H__ */
diff --git a/netlink/permaddr.c b/netlink/permaddr.c
new file mode 100644
index 000000000000..006eac6c0094
--- /dev/null
+++ b/netlink/permaddr.c
@@ -0,0 +1,114 @@
+/*
+ * permaddr.c - netlink implementation of permanent address request
+ *
+ * Implementation of "ethtool -P <dev>"
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+
+#include "../internal.h"
+#include "../common.h"
+#include "netlink.h"
+
+/* PERMADDR_GET */
+
+static int permaddr_prep_request(struct nl_socket *nlsk)
+{
+	unsigned int nlm_flags = NLM_F_REQUEST | NLM_F_ACK;
+	struct nl_context *nlctx = nlsk->nlctx;
+	const char *devname = nlctx->ctx->devname;
+	struct nl_msg_buff *msgbuff = &nlsk->msgbuff;
+	struct ifinfomsg *ifinfo;
+	struct nlmsghdr *nlhdr;
+	int ret;
+
+	if (devname && !strcmp(devname, WILDCARD_DEVNAME)) {
+		devname = NULL;
+		nlm_flags |= NLM_F_DUMP;
+	}
+	nlctx->is_dump = !devname;
+
+        ret = msgbuff_realloc(msgbuff, MNL_SOCKET_BUFFER_SIZE);
+        if (ret < 0)
+                return ret;
+        memset(msgbuff->buff, '\0', NLMSG_HDRLEN + sizeof(*ifinfo));
+
+	nlhdr = mnl_nlmsg_put_header(msgbuff->buff);
+	nlhdr->nlmsg_type = RTM_GETLINK;
+	nlhdr->nlmsg_flags = nlm_flags;
+	msgbuff->nlhdr = nlhdr;
+	ifinfo = mnl_nlmsg_put_extra_header(nlhdr, sizeof(*ifinfo));
+
+	if (devname) {
+		uint16_t type = IFLA_IFNAME;
+
+		if (strlen(devname) >= IFNAMSIZ)
+			type = IFLA_ALT_IFNAME;
+		if (ethnla_put_strz(msgbuff, type, devname))
+			return -EMSGSIZE;
+	}
+	if (ethnla_put_u32(msgbuff, IFLA_EXT_MASK, RTEXT_FILTER_SKIP_STATS))
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+int permaddr_reply_cb(const struct nlmsghdr *nlhdr, void *data)
+{
+	const struct nlattr *tb[__IFLA_MAX] = {};
+	DECLARE_ATTR_TB_INFO(tb);
+	struct nl_context *nlctx = data;
+	const uint8_t *permaddr;
+	unsigned int i;
+	int ret;
+
+	if (nlhdr->nlmsg_type != RTM_NEWLINK)
+		goto err;
+	ret = mnl_attr_parse(nlhdr, sizeof(struct ifinfomsg), attr_cb,
+			     &tb_info);
+	if (ret < 0 || !tb[IFLA_IFNAME])
+		goto err;
+	nlctx->devname = mnl_attr_get_str(tb[IFLA_IFNAME]);
+	if (!dev_ok(nlctx))
+		goto err;
+
+	if (!tb[IFLA_PERM_ADDRESS]) {
+		if (!nlctx->is_dump)
+			printf("Permanent address: not set\n");
+		return MNL_CB_OK;
+	}
+
+	if (nlctx->is_dump)
+		printf("Permanent address of %s:", nlctx->devname);
+	else
+		printf("Permanent address:");
+	permaddr = mnl_attr_get_payload(tb[IFLA_PERM_ADDRESS]);
+	for (i = 0; i < mnl_attr_get_payload_len(tb[IFLA_PERM_ADDRESS]); i++)
+		printf("%c%02x", i ? ':' : ' ', permaddr[i]);
+	putchar('\n');
+	return MNL_CB_OK;
+
+err:
+	if (nlctx->is_dump || nlctx->is_monitor)
+		return MNL_CB_OK;
+	nlctx->exit_code = 2;
+	return MNL_CB_ERROR;
+}
+
+int nl_permaddr(struct cmd_context *ctx)
+{
+	struct nl_context *nlctx = ctx->nlctx;
+	int ret;
+
+	ret = netlink_init_rtnl_socket(nlctx);
+	if (ret < 0)
+		return ret;
+	ret = permaddr_prep_request(nlctx->rtnl_socket);
+	if (ret < 0)
+		return ret;
+	return nlsock_send_get_request(nlctx->rtnl_socket, permaddr_reply_cb);
+}
-- 
2.25.1


  parent reply	other threads:[~2020-03-06 17:05 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-06 17:03 [PATCH ethtool v3 00/25] initial netlink interface implementation for 5.6 release Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 01/25] move UAPI header copies to a separate directory Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 02/25] update UAPI header copies Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 03/25] add --debug option to control debugging messages Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 04/25] use named initializers in command line option list Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 05/25] netlink: add netlink related UAPI header files Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 06/25] netlink: introduce the netlink interface Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 07/25] netlink: message buffer and composition helpers Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 08/25] netlink: netlink socket wrapper and helpers Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 09/25] netlink: initialize ethtool netlink socket Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 10/25] netlink: add support for string sets Michal Kubecek
2020-03-06 17:04 ` [PATCH ethtool v3 11/25] netlink: add notification monitor Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 12/25] move shared code into a common file Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 13/25] netlink: add bitset helpers Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 14/25] netlink: partial netlink handler for gset (no option) Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 15/25] netlink: support getting wake-on-lan and debugging settings Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 16/25] netlink: add basic command line parsing helpers Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 17/25] netlink: add bitset command line parser handlers Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 18/25] netlink: add netlink handler for sset (-s) Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 19/25] netlink: support tests with netlink enabled Michal Kubecek
2020-03-06 17:05 ` Michal Kubecek [this message]
2020-03-06 17:05 ` [PATCH ethtool v3 21/25] netlink: support for pretty printing netlink messages Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 22/25] netlink: message format description for ethtool netlink Michal Kubecek
2020-03-06 17:05 ` [PATCH ethtool v3 23/25] netlink: message format descriptions for genetlink control Michal Kubecek
2020-03-06 17:06 ` [PATCH ethtool v3 24/25] netlink: message format descriptions for rtnetlink Michal Kubecek
2020-03-06 17:06 ` [PATCH ethtool v3 25/25] netlink: use pretty printing for ethtool netlink messages Michal Kubecek
2020-03-13 19:20 ` [PATCH ethtool v3 00/25] initial netlink interface implementation for 5.6 release John W. Linville

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=f3ed37731543cb105493f3ef56d7d4299e173e3b.1583513281.git.mkubecek@suse.cz \
    --to=mkubecek@suse.cz \
    --cc=andrew@lunn.ch \
    --cc=f.fainelli@gmail.com \
    --cc=linville@tuxdriver.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.