about summary refs log tree commit diff
path: root/src/platform/nm-platform-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/platform/nm-platform-utils.c')
-rw-r--r--src/platform/nm-platform-utils.c62
1 files changed, 61 insertions, 1 deletions
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index d3c62bdd..b7f0947e 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -33,6 +33,7 @@
 #include "nm-utils.h"
 #include "NetworkManagerUtils.h"
 #include "nm-logging.h"
+#include "nm-setting-wired.h"
 
 
 /******************************************************************
@@ -48,8 +49,14 @@ ethtool_get (const char *name, gpointer edata)
 	if (!name || !*name)
 		return FALSE;
 
+	if (!nmp_utils_device_exists (name))
+		return FALSE;
+
+	/* nmp_utils_device_exists() already errors out if @name is invalid. */
+	nm_assert (strlen (name) < IFNAMSIZ);
+
 	memset (&ifr, 0, sizeof (ifr));
-	strncpy (ifr.ifr_name, name, IFNAMSIZ);
+	strcpy (ifr.ifr_name, name);
 	ifr.ifr_data = edata;
 
 	fd = socket (PF_INET, SOCK_DGRAM, 0);
@@ -255,6 +262,43 @@ nmp_utils_ethtool_get_link_speed (const char *ifname, guint32 *out_speed)
 	return TRUE;
 }
 
+gboolean
+nmp_utils_ethtool_set_wake_on_lan (const char *ifname,
+                                   NMSettingWiredWakeOnLan wol,
+                                   const char *wol_password)
+{
+	struct ethtool_wolinfo wol_info = { };
+
+	nm_log_dbg (LOGD_PLATFORM, "setting Wake-on-LAN options 0x%x, password '%s'",
+	            (unsigned int) wol, wol_password);
+
+	wol_info.cmd = ETHTOOL_SWOL;
+	wol_info.wolopts = 0;
+
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_PHY))
+		wol_info.wolopts |= WAKE_PHY;
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST))
+		wol_info.wolopts |= WAKE_UCAST;
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST))
+		wol_info.wolopts |= WAKE_MCAST;
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST))
+		wol_info.wolopts |= WAKE_BCAST;
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_ARP))
+		wol_info.wolopts |= WAKE_ARP;
+	if (NM_FLAGS_HAS (wol, NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC))
+		wol_info.wolopts |= WAKE_MAGIC;
+
+	if (wol_password) {
+		if (!nm_utils_hwaddr_aton (wol_password, wol_info.sopass, ETH_ALEN)) {
+			nm_log_dbg (LOGD_PLATFORM, "couldn't parse Wake-on-LAN password '%s'", wol_password);
+			return FALSE;
+		}
+		wol_info.wolopts |= WAKE_MAGICSECURE;
+	}
+
+	return ethtool_get (ifname, &wol_info);
+}
+
 /******************************************************************
  * mii
  ******************************************************************/
@@ -270,6 +314,9 @@ nmp_utils_mii_supports_carrier_detect (const char *ifname)
 	if (!ifname)
 		return FALSE;
 
+	if (!nmp_utils_device_exists (ifname))
+		return FALSE;
+
 	fd = socket (PF_INET, SOCK_DGRAM, 0);
 	if (fd < 0) {
 		nm_log_err (LOGD_PLATFORM, "mii: couldn't open control socket (%s)", ifname);
@@ -433,4 +480,17 @@ nmp_utils_lifetime_get (guint32 timestamp,
 	return TRUE;
 }
 
+gboolean
+nmp_utils_device_exists (const char *name)
+{
+#define SYS_CLASS_NET "/sys/class/net/"
+	char sysdir[STRLEN (SYS_CLASS_NET) + IFNAMSIZ] = SYS_CLASS_NET;
 
+	if (   !name
+	    || strlen (name) >= IFNAMSIZ
+	    || !nm_utils_is_valid_path_component (name))
+		g_return_val_if_reached (FALSE);
+
+	strcpy (&sysdir[STRLEN (SYS_CLASS_NET)], name);
+	return g_file_test (sysdir, G_FILE_TEST_EXISTS);
+}