lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 18 Feb 2019 19:21:59 +0100 (CET)
From:   Michal Kubecek <mkubecek@...e.cz>
To:     netdev@...r.kernel.org
Cc:     David Miller <davem@...emloft.net>, Andrew Lunn <andrew@...n.ch>,
        Jakub Kicinski <jakub.kicinski@...ronome.com>,
        Jiri Pirko <jiri@...nulli.us>, linux-kernel@...r.kernel.org
Subject: [RFC PATCH net-next v3 07/21] ethtool: implement EVENT notifications

Three types of netlink notifications are introduced:

  - ETHA_EVENT_NEWDEV to notify about newly registered network devices
  - ETHA_EVENT_DELDEV to notify about unregistered network devices
  - ETHA_EVENT_RENAMEDEV to notify about renamed network device

The notifications are triggered by NETDEV_REGISTER, NETDEV_UNREGISTER and
NETDEV_CHANGENAME notifiers.

These notifications are intended for applications and daemons monitoring
ethtool events to allow updating the list of existing devices without
having to open another socket for rtnetlink.

Signed-off-by: Michal Kubecek <mkubecek@...e.cz>
---
 Documentation/networking/ethtool-netlink.txt | 27 ++++++++
 include/uapi/linux/ethtool_netlink.h         | 37 +++++++++++
 net/ethtool/netlink.c                        | 65 ++++++++++++++++++++
 3 files changed, 129 insertions(+)

diff --git a/Documentation/networking/ethtool-netlink.txt b/Documentation/networking/ethtool-netlink.txt
index 205ae4462e9e..b79c26b5e92b 100644
--- a/Documentation/networking/ethtool-netlink.txt
+++ b/Documentation/networking/ethtool-netlink.txt
@@ -125,6 +125,8 @@ which the request applies.
 List of message types
 ---------------------
 
+    ETHNL_CMD_EVENT			notification only
+
 All constants use ETHNL_CMD_ prefix, usually followed by "GET", "SET" or "ACT"
 to indicate the type.
 
@@ -136,9 +138,34 @@ messages marked as "response only" in the table above. "Get" messages with
 NLM_F_DUMP flags and no device identification dump the information for all
 devices supporting the request.
 
+Type ETHNL_CMD_EVENT is special, these messages are never used in userspace
+requests or kernel replies. They are only sent by kernel to sockets listening
+to "monitor" multicast group to inform userspace about certain events.
+
 Later sections describe the format and semantics of these request messages.
 
 
+EVENT
+-----
+
+EVENT messages are only used in kernel multicast notifications. Atributes
+correspond to specific event types, the same type can appear multiple times.
+
+    ETHA_EVENT_NEWDEV		(nested)	new device was registered
+       ETHA_NEWDEV_DEV			(nested)	new device
+    ETHA_EVENT_DELDEV		(nested)	device was unregistered
+       ETHA_DELDEV_DEV			(nested)	removed device
+    ETHA_EVENT_RENAMEDEV	(nested)	device was renamed
+       ETHA_RENAMEDEV_DEV		(nested)	renamed device
+
+For ETHA_EVENT_RENAMEDEV, the name ETHA_RENAME_DEV/ETHA_DEV_NAME is the new
+name after the rename.
+
+Userspace application must expect multiple events to be present in one message
+and also multiple events of the same type (e.g. two or more newly registered
+devices).
+
+
 Request translation
 -------------------
 
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index b662d75a0636..7e192ad8ce3a 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -7,6 +7,7 @@
 
 enum {
 	ETHNL_CMD_NOOP,
+	ETHNL_CMD_EVENT,		/* only for notifications */
 
 	__ETHNL_CMD_CNT,
 	ETHNL_CMD_MAX = (__ETHNL_CMD_CNT - 1)
@@ -55,6 +56,42 @@ enum {
 	ETHA_BITSET_MAX = (__ETHA_BITSET_CNT - 1)
 };
 
+/* events */
+
+enum {
+	ETHA_NEWDEV_UNSPEC,
+	ETHA_NEWDEV_DEV,			/* nest - ETHA_DEV_* */
+
+	__ETHA_NEWDEV_CNT,
+	ETHA_NEWDEV_MAX = (__ETHA_NEWDEV_CNT - 1)
+};
+
+enum {
+	ETHA_DELDEV_UNSPEC,
+	ETHA_DELDEV_DEV,			/* nest - ETHA_DEV_* */
+
+	__ETHA_DELDEV_CNT,
+	ETHA_DELDEV_MAX = (__ETHA_DELDEV_CNT - 1)
+};
+
+enum {
+	ETHA_RENAMEDEV_UNSPEC,
+	ETHA_RENAMEDEV_DEV,			/* nest - ETHA_DEV_* */
+
+	__ETHA_RENAMEDEV_CNT,
+	ETHA_RENAMEDEV_MAX = (__ETHA_RENAMEDEV_CNT - 1)
+};
+
+enum {
+	ETHA_EVENT_UNSPEC,
+	ETHA_EVENT_NEWDEV,			/* nest - ETHA_NEWDEV_* */
+	ETHA_EVENT_DELDEV,			/* nest - ETHA_DELDEV_* */
+	ETHA_EVENT_RENAMEDEV,			/* nest - ETHA_RENAMEDEV_* */
+
+	__ETHA_EVENT_CNT,
+	ETHA_EVENT_MAX = (__ETHA_EVENT_CNT - 1)
+};
+
 /* generic netlink info */
 #define ETHTOOL_GENL_NAME "ethtool"
 #define ETHTOOL_GENL_VERSION 1
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index a5fa54c2b743..ee3424cd1f90 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -148,6 +148,67 @@ void ethtool_notify(struct net_device *dev, struct netlink_ext_ack *extack,
 }
 EXPORT_SYMBOL(ethtool_notify);
 
+/* size of NEWDEV/DELDEV notification */
+static inline unsigned int dev_notify_size(void)
+{
+	return nla_total_size(dev_ident_size());
+}
+
+static void ethnl_notify_devlist(struct netdev_notifier_info *info,
+				 u16 ev_type, u16 dev_attr)
+{
+	struct net_device *dev = netdev_notifier_info_to_dev(info);
+	struct sk_buff *skb;
+	struct nlattr *nest;
+	void *ehdr;
+	int ret;
+
+	skb = genlmsg_new(dev_notify_size(), GFP_KERNEL);
+	if (!skb)
+		return;
+	ehdr = genlmsg_put(skb, 0, ++ethnl_bcast_seq, &ethtool_genl_family, 0,
+			   ETHNL_CMD_EVENT);
+	if (!ehdr)
+		goto out_skb;
+	nest = ethnl_nest_start(skb, ev_type);
+	if (!nest)
+		goto out_skb;
+	ret = ethnl_fill_dev(skb, dev, dev_attr);
+	if (ret < 0)
+		goto out_skb;
+	nla_nest_end(skb, nest);
+	genlmsg_end(skb, ehdr);
+
+	genlmsg_multicast(&ethtool_genl_family, skb, 0, ETHNL_MCGRP_MONITOR,
+			  GFP_KERNEL);
+	return;
+out_skb:
+	nlmsg_free(skb);
+}
+
+static int ethnl_netdev_event(struct notifier_block *this, unsigned long event,
+			      void *ptr)
+{
+	switch (event) {
+	case NETDEV_REGISTER:
+		ethnl_notify_devlist(ptr, ETHA_EVENT_NEWDEV, ETHA_NEWDEV_DEV);
+		break;
+	case NETDEV_UNREGISTER:
+		ethnl_notify_devlist(ptr, ETHA_EVENT_DELDEV, ETHA_DELDEV_DEV);
+		break;
+	case NETDEV_CHANGENAME:
+		ethnl_notify_devlist(ptr, ETHA_EVENT_RENAMEDEV,
+				     ETHA_RENAMEDEV_DEV);
+		break;
+	}
+
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ethnl_netdev_notifier = {
+	.notifier_call = ethnl_netdev_event,
+};
+
 /* genetlink setup */
 
 static const struct genl_ops ethtool_genl_ops[] = {
@@ -179,6 +240,10 @@ static int __init ethnl_init(void)
 	if (ret < 0)
 		panic("ethtool: could not register genetlink family\n");
 
+	ret = register_netdevice_notifier(&ethnl_netdev_notifier);
+	if (ret < 0)
+		panic("ethtool: could not register netdev notifier\n");
+
 	return 0;
 }
 
-- 
2.20.1

Powered by blists - more mailing lists