Wake on LAN support. NetworkManager?



Hi,

I'm currently looking for a place to integrate Wake On LAN
capabilities/enablement. As a logical result, NetworkManager came to my
mind.

When talking about Wake On LAN, I'm talking about the functionality
ethtool provides, and about the network drivers which implement ethtool
support. I've already created a proof-of-concept patch. The current work
is based on NetworkManager-0.6.5, just because it's the most recent stable
release.

I've added three new D-Bus methods:

  getWakeOnLanEnabled
  getWakeOnLanSupported
  setWakeOnLanEnabled

So this mail is not a "please commit", but rather a question if it makes
sense to integrate into NetworkManager at all. The other possibility would
be to add to HAL if it doesn't fit into the NetworkManager concept.

Comments?

  - Holger
Index: include/NetworkManager.h
===================================================================
--- include/NetworkManager.h	(revision 2617)
+++ include/NetworkManager.h	(working copy)
@@ -89,6 +89,7 @@
 #define NM_DEVICE_CAP_NM_SUPPORTED		0x00000001
 #define NM_DEVICE_CAP_CARRIER_DETECT	0x00000002
 #define NM_DEVICE_CAP_WIRELESS_SCAN	0x00000004
+#define NM_DEVICE_CAP_WAKE_ON_LAN	0x00000008
 
 
 /* 802.11 wireless-specific device capability bits */
Index: src/nm-dbus-nm.c
===================================================================
--- src/nm-dbus-nm.c	(revision 2617)
+++ src/nm-dbus-nm.c	(working copy)
@@ -37,6 +37,7 @@
 #include "nm-ap-security.h"
 #include "nm-device-802-3-ethernet.h"
 #include "nm-device-802-11-wireless.h"
+#include "nm-ethtool-wol.h"
 
 
 /*
@@ -533,6 +534,109 @@
 	return reply;
 }
 
+static DBusMessage *nm_dbus_nm_set_wol_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+	DBusMessage	*reply = NULL;
+	DBusError		 err;
+	char			*dev_path;
+	int			enable;
+	NMDevice		*dev;
+
+	g_return_val_if_fail (data && data->data && connection && message, NULL);
+
+	dbus_error_init (&err);
+
+	if (!dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &dev_path,
+				    DBUS_TYPE_BOOLEAN, &enable, DBUS_TYPE_INVALID))
+	{
+		reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "InvalidArguments",
+						      "NetworkManager::setWakeOnLanEnabled called with invalid arguments.");
+		goto out;
+	}
+
+	if ((dev = nm_dbus_get_device_from_escaped_object_path (data->data, dev_path)))
+	{
+		int ret;
+
+		if (enable == 1)
+			ret = nm_ethtool_wol_enable(nm_device_get_iface (dev))
+		else
+			ret = nm_ethtool_wol_disable(nm_device_get_iface (dev));
+		if (ret < 0)
+			reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "RequestFailed",
+							      "Could not enable wake on LAN.");
+	}
+	else
+	{
+		reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound",
+						      "The requested network device does not exist.");
+	}
+
+out:
+	if (dbus_error_is_set (&err))
+		dbus_error_free (&err);
+
+	return (reply);
+}
+
+static DBusMessage *nm_dbus_nm_get_wol_status (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data,
+			                       int supported)
+{
+	DBusMessage	*reply = NULL;
+	DBusError		 err;
+	char			*dev_path;
+
+	g_return_val_if_fail (data && data->data && connection && message, NULL);
+
+	dbus_error_init (&err);
+	if (dbus_message_get_args (message, &err, DBUS_TYPE_STRING, &dev_path, DBUS_TYPE_INVALID))
+	{
+		NMDevice	*dev;
+
+		if ((dev = nm_dbus_get_device_from_escaped_object_path (data->data, dev_path)))
+		{
+			int value;
+
+			if (supported) {
+				value = nm_ethtool_wol_supported (nm_device_get_iface (dev));
+			} else
+				value = nm_ethtool_wol_enabled (nm_device_get_iface (dev));
+
+			if (value < 0)
+				reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "NoWakeOnLan",
+								      "Could not get wake on LAN capability.");
+			else 
+				if ((reply = dbus_message_new_method_return (message)))
+					dbus_message_append_args (reply, DBUS_TYPE_BOOLEAN, &value, DBUS_TYPE_INVALID);
+		}
+		else
+		{
+			reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceNotFound",
+							"The requested network device does not exist.");
+		}
+	}
+	else
+	{
+		reply = nm_dbus_create_error_message (message, NM_DBUS_INTERFACE, "DeviceBad",
+					"The device ID was bad.");
+	}
+
+	if (dbus_error_is_set (&err))
+		dbus_error_free (&err);
+
+	return (reply);
+}
+
+static DBusMessage *nm_dbus_nm_get_wol_enabled (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+	return nm_dbus_nm_get_wol_status (connection, message, data, 0);
+}
+
+static DBusMessage *nm_dbus_nm_get_wol_supported (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
+{
+	return nm_dbus_nm_get_wol_status (connection, message, data, 1);
+}
+
 static DBusMessage *nm_dbus_nm_sleep (DBusConnection *connection, DBusMessage *message, NMDbusCBData *data)
 {
 	NMData	*app_data;
@@ -676,6 +780,9 @@
 	nm_dbus_method_list_add_method (list, "createWirelessNetwork",	nm_dbus_nm_create_wireless_network);
 	nm_dbus_method_list_add_method (list, "setWirelessEnabled",		nm_dbus_nm_set_wireless_enabled);
 	nm_dbus_method_list_add_method (list, "getWirelessEnabled",		nm_dbus_nm_get_wireless_enabled);
+	nm_dbus_method_list_add_method (list, "getWakeOnLanEnabled",		nm_dbus_nm_get_wol_enabled);
+	nm_dbus_method_list_add_method (list, "getWakeOnLanSupported",		nm_dbus_nm_get_wol_supported);
+	nm_dbus_method_list_add_method (list, "setWakeOnLanEnabled",		nm_dbus_nm_set_wol_enabled);
 	nm_dbus_method_list_add_method (list, "sleep",				nm_dbus_nm_sleep);
 	nm_dbus_method_list_add_method (list, "wake",				nm_dbus_nm_wake);
 	nm_dbus_method_list_add_method (list, "state",				nm_dbus_nm_get_state);
Index: src/nm-device-802-3-ethernet.c
===================================================================
--- src/nm-device-802-3-ethernet.c	(revision 2617)
+++ src/nm-device-802-3-ethernet.c	(working copy)
@@ -34,6 +34,7 @@
 #include "NetworkManagerPolicy.h"
 #include "nm-utils.h"
 #include "kernel-types.h"
+#include "nm-ethtool-wol.h"
 
 #define NM_DEVICE_802_3_ETHERNET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_802_3_ETHERNET, NMDevice8023EthernetPrivate))
 
Index: src/nm-ethtool-wol.c
===================================================================
--- src/nm-ethtool-wol.c	(revision 0)
+++ src/nm-ethtool-wol.c	(revision 0)
@@ -0,0 +1,110 @@
+/*
+ * Author Holger Macht <holger homac de> 
+ *
+ * Released under GPLv2
+ *
+ * Based on code from ethtool
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <net/if.h>
+#include <getopt.h>
+#include <linux/sockios.h>
+
+#include "nm-ethtool-wol.h"
+
+#define SIOCETHTOOL	0x8946
+#define WAKE_MAGIC	(1 << 5)
+#define ETHTOOL_GWOL	0x00000005 /* Get wake-on-lan options. */
+#define ETHTOOL_SWOL	0x00000006 /* Set wake-on-lan options, priv. */
+
+#define SOPASS_MAX	6
+/* wake-on-lan settings */
+struct wolinfo {
+	int	cmd;
+	int	supported;
+	int	wolopts;
+	int	sopass[SOPASS_MAX]; /* SecureOn(tm) password */
+};
+
+static int wol_request (const char *dev, struct wolinfo *wol)
+{
+	struct ifreq	ifr;
+	int		fd;
+	int		ret;
+
+	/* Setup our control structures. */
+	memset(&ifr, 0, sizeof(ifr));
+	strcpy(ifr.ifr_name, dev);
+
+	fd = socket(AF_INET, SOCK_DGRAM, 0);
+	if (fd < 0) {
+		perror("Cannot get control socket");
+		return -1;
+	}
+
+	ifr.ifr_data = (caddr_t)wol;
+	if (ioctl(fd, SIOCETHTOOL, &ifr)) {
+		perror("Cannot get wake-on-lan settings");
+		ret = -1;
+		goto out;
+	}
+
+	if (wol->supported & WAKE_MAGIC)
+		ret = 1;
+	else
+		ret = 0;
+
+out:
+	close(fd);
+
+	return ret;
+}
+
+/* get one of 'supported' or 'enabled' capabilites */
+int nm_ethtool_wol_status (const char *dev, enum NM_ETHTOOL_WOL_STATUS request)
+{
+	struct wolinfo wol;
+
+	if (request != NM_ETHTOOL_WOL_SUPPORTED && request != NM_ETHTOOL_WOL_SUPPORTED)
+		return -1;
+
+	wol.cmd = ETHTOOL_GWOL;
+	if (wol_request(dev, &wol) < 0)
+		return -1;
+
+	if (request == NM_ETHTOOL_WOL_SUPPORTED && (wol.supported & WAKE_MAGIC))
+		return 1;
+	else if (request == NM_ETHTOOL_WOL_ENABLED && (wol.wolopts & WAKE_MAGIC))
+		return 1;
+	else
+		return 0;
+}
+
+/* enables or disables WOL depending on the arg enable */
+int nm_ethtool_wol_change (const char *dev, int enable)
+{
+	struct wolinfo	     wol;
+	int		data = 0;
+
+	wol.cmd = ETHTOOL_SWOL;
+	if (enable == 1)
+		data |= WAKE_MAGIC;
+	wol.wolopts = data;
+	if (wol_request(dev, &wol) < 0) {
+		fprintf(stderr, "Cannot enable WOL\n");
+		return -1;
+	}
+
+	if (wol.wolopts & WAKE_MAGIC) {
+		return 1;
+	} else
+		return 0;
+
+	return 0;
+}
Index: src/nm-ethtool-wol.h
===================================================================
--- src/nm-ethtool-wol.h	(revision 0)
+++ src/nm-ethtool-wol.h	(revision 0)
@@ -0,0 +1,20 @@
+/*
+ * Author Holger Macht <holger homac de> 
+ *
+ * Released under GPLv2
+ *
+ * Based on code from ethtool
+ */
+
+#ifndef NM_ETHTOOL_WOL_H
+#define NM_ETHTOOL_WOL_H
+
+enum NM_ETHTOOL_WOL_STATUS { NM_ETHTOOL_WOL_SUPPORTED, NM_ETHTOOL_WOL_ENABLED };
+
+#define nm_ethtool_wol_enable(dev)	nm_ethtool_wol_change(dev,NM_ETHTOOL_WOL_SUPPORTED);
+#define nm_ethtool_wol_disable(dev)	nm_ethtool_wol_change(dev,NM_ETHTOOL_WOL_ENABLED);
+
+#define nm_ethtool_wol_supported(dev)	nm_ethtool_wol_status(dev,1);
+#define nm_ethtool_wol_enabled(dev)	nm_ethtool_wol_status(dev,0);
+
+#endif
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(revision 2617)
+++ src/Makefile.am	(working copy)
@@ -29,6 +29,8 @@
 		NetworkManagerDbusUtils.h	\
 		nm-dbus-nm.c				\
 		nm-dbus-nm.h				\
+		nm-ethtool-wol.c			\
+		nm-ethtool-wol.h			\
 		nm-dbus-device.c			\
 		nm-dbus-device.h			\
 		nm-dbus-net.c				\


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]