summary refs log tree commit diff
path: root/src/platform
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-06-17 14:54:10 +0200
committerMichael Biebl <biebl@debian.org>2018-06-17 14:54:10 +0200
commit069cb5c3a525ebcc19cc2927964258acaca87b13 (patch)
tree66ac6b21a44d630c0fc281c0df327239d491226a /src/platform
parent04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff)
New upstream version 1.11.90 upstream/1.11.90
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/nm-linux-platform.c9
-rw-r--r--src/platform/nm-netlink.h3
-rw-r--r--src/platform/nm-platform-utils.c62
-rw-r--r--src/platform/nm-platform.c17
-rw-r--r--src/platform/nm-platform.h4
-rw-r--r--src/platform/wifi/wifi-utils-nl80211.c42
-rw-r--r--src/platform/wifi/wifi-utils-private.h3
-rw-r--r--src/platform/wifi/wifi-utils.c9
-rw-r--r--src/platform/wifi/wifi-utils.h3
9 files changed, 151 insertions, 1 deletions
diff --git a/src/platform/nm-linux-platform.c b/src/platform/nm-linux-platform.c
index 3a671acf..9bd662a1 100644
--- a/src/platform/nm-linux-platform.c
+++ b/src/platform/nm-linux-platform.c
@@ -6092,6 +6092,14 @@ wifi_indicate_addressing_running (NMPlatform *platform, int ifindex, gboolean ru
 	wifi_utils_indicate_addressing_running (wifi_data, running);
 }
 
+static gboolean
+wifi_set_wake_on_wlan (NMPlatform *platform, int ifindex,
+                       NMSettingWirelessWakeOnWLan wowl)
+{
+	WIFI_GET_WIFI_DATA_NETNS (wifi_data, platform, ifindex, FALSE);
+	return wifi_utils_set_wake_on_wlan (wifi_data, wowl);
+}
+
 /*****************************************************************************/
 
 static gboolean
@@ -7230,6 +7238,7 @@ nm_linux_platform_class_init (NMLinuxPlatformClass *klass)
 	platform_class->wifi_set_powersave = wifi_set_powersave;
 	platform_class->wifi_find_frequency = wifi_find_frequency;
 	platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running;
+	platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan;
 
 	platform_class->mesh_get_channel = mesh_get_channel;
 	platform_class->mesh_set_channel = mesh_set_channel;
diff --git a/src/platform/nm-netlink.h b/src/platform/nm-netlink.h
index c0dc09c4..b938fa4a 100644
--- a/src/platform/nm-netlink.h
+++ b/src/platform/nm-netlink.h
@@ -244,6 +244,9 @@ nla_put_string (struct nl_msg *msg, int attrtype, const char *str)
 #define NLA_PUT_STRING(msg, attrtype, value) \
 	NLA_PUT(msg, attrtype, (int) strlen(value) + 1, value)
 
+#define NLA_PUT_FLAG(msg, attrtype) \
+	NLA_PUT(msg, attrtype, 0, NULL)
+
 struct nlattr *nla_find (const struct nlattr *head, int len, int attrtype);
 
 static inline int
diff --git a/src/platform/nm-platform-utils.c b/src/platform/nm-platform-utils.c
index 114bf4b3..0d224443 100644
--- a/src/platform/nm-platform-utils.c
+++ b/src/platform/nm-platform-utils.c
@@ -384,6 +384,40 @@ nmp_utils_ethtool_get_link_settings (int ifindex,
 	return TRUE;
 }
 
+
+#define ADVERTISED_INVALID 0
+#define BASET_ALL_MODES (  ADVERTISED_10baseT_Half \
+                         | ADVERTISED_10baseT_Full \
+                         | ADVERTISED_100baseT_Half \
+                         | ADVERTISED_100baseT_Full \
+                         | ADVERTISED_1000baseT_Half \
+                         | ADVERTISED_1000baseT_Full \
+                         | ADVERTISED_10000baseT_Full )
+
+static inline guint32
+get_baset_mode (guint32 speed, NMPlatformLinkDuplexType duplex)
+{
+	if (duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
+		return ADVERTISED_INVALID;
+
+	if (duplex == NM_PLATFORM_LINK_DUPLEX_HALF) {
+		switch (speed) {
+		case 10: return ADVERTISED_10baseT_Half;
+		case 100: return ADVERTISED_100baseT_Half;
+		case 1000: return ADVERTISED_1000baseT_Half;
+		default: return ADVERTISED_INVALID;
+		}
+	} else {
+		switch (speed) {
+		case 10: return ADVERTISED_10baseT_Full;
+		case 100: return ADVERTISED_100baseT_Full;
+		case 1000: return ADVERTISED_1000baseT_Full;
+		case 10000: return ADVERTISED_10000baseT_Full;
+		default: return ADVERTISED_INVALID;
+		}
+	}
+}
+
 gboolean
 nmp_utils_ethtool_set_link_settings (int ifindex,
                                      gboolean autoneg,
@@ -395,6 +429,8 @@ nmp_utils_ethtool_set_link_settings (int ifindex,
 	};
 
 	g_return_val_if_fail (ifindex > 0, FALSE);
+	g_return_val_if_fail (   (speed && duplex != NM_PLATFORM_LINK_DUPLEX_UNKNOWN)
+	                      || (!speed && duplex == NM_PLATFORM_LINK_DUPLEX_UNKNOWN), FALSE);
 
 	/* retrieve first current settings */
 	if (!ethtool_get (ifindex, &edata))
@@ -404,7 +440,31 @@ nmp_utils_ethtool_set_link_settings (int ifindex,
 	edata.cmd = ETHTOOL_SSET;
 	if (autoneg) {
 		edata.autoneg = AUTONEG_ENABLE;
-		edata.advertising = edata.supported;
+		if (!speed)
+			edata.advertising = edata.supported;
+		else {
+			guint32 mode;
+
+			mode = get_baset_mode (speed, duplex);
+
+			if (!mode) {
+				nm_log_trace (LOGD_PLATFORM,
+				              "ethtool[%d]: %uBASE-T %s duplex mode cannot be advertised",
+				              ifindex,
+				              speed,
+				              nm_platform_link_duplex_type_to_string (duplex));
+				return FALSE;
+			}
+			if (!(edata.supported & mode)) {
+				nm_log_trace (LOGD_PLATFORM,
+				              "ethtool[%d]: device does not support %uBASE-T %s duplex mode",
+				              ifindex,
+				              speed,
+				              nm_platform_link_duplex_type_to_string (duplex));
+				return FALSE;
+			}
+			edata.advertising = (edata.supported & ~BASET_ALL_MODES) | mode;
+		}
 	} else {
 		edata.autoneg = AUTONEG_DISABLE;
 
diff --git a/src/platform/nm-platform.c b/src/platform/nm-platform.c
index 1a94ce28..f75019e8 100644
--- a/src/platform/nm-platform.c
+++ b/src/platform/nm-platform.c
@@ -2888,6 +2888,16 @@ nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gbo
 	klass->wifi_indicate_addressing_running (self, ifindex, running);
 }
 
+gboolean
+nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl)
+{
+	_CHECK_SELF (self, klass, FALSE);
+
+	g_return_val_if_fail (ifindex > 0, FALSE);
+
+	return klass->wifi_set_wake_on_wlan (self, ifindex, wowl);
+}
+
 guint32
 nm_platform_mesh_get_channel (NMPlatform *self, int ifindex)
 {
@@ -2995,6 +3005,13 @@ nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *
 	return nmp_utils_ethtool_get_link_settings (ifindex, out_autoneg, out_speed, out_duplex);
 }
 
+NM_UTILS_LOOKUP_STR_DEFINE (nm_platform_link_duplex_type_to_string, NMPlatformLinkDuplexType,
+	NM_UTILS_LOOKUP_DEFAULT_WARN (NULL),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_UNKNOWN, "unknown"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_FULL,    "full"),
+	NM_UTILS_LOOKUP_STR_ITEM (NM_PLATFORM_LINK_DUPLEX_HALF,    "half"),
+);
+
 /*****************************************************************************/
 
 const NMDedupMultiHeadEntry *
diff --git a/src/platform/nm-platform.h b/src/platform/nm-platform.h
index 2d2bfaab..866df736 100644
--- a/src/platform/nm-platform.h
+++ b/src/platform/nm-platform.h
@@ -33,6 +33,7 @@
 #include "nm-core-utils.h"
 #include "nm-setting-vlan.h"
 #include "nm-setting-wired.h"
+#include "nm-setting-wireless.h"
 #include "nm-setting-ip-tunnel.h"
 
 #define NM_TYPE_PLATFORM            (nm_platform_get_type ())
@@ -867,6 +868,7 @@ typedef struct {
 	void        (*wifi_set_powersave)    (NMPlatform *, int ifindex, guint32 powersave);
 	guint32     (*wifi_find_frequency)   (NMPlatform *, int ifindex, const guint32 *freqs);
 	void        (*wifi_indicate_addressing_running) (NMPlatform *, int ifindex, gboolean running);
+	gboolean    (*wifi_set_wake_on_wlan) (NMPlatform *, int ifindex, NMSettingWirelessWakeOnWLan wowl);
 
 	guint32     (*mesh_get_channel)      (NMPlatform *, int ifindex);
 	gboolean    (*mesh_set_channel)      (NMPlatform *, int ifindex, guint32 channel);
@@ -1245,6 +1247,7 @@ void        nm_platform_wifi_set_mode         (NMPlatform *self, int ifindex, NM
 void        nm_platform_wifi_set_powersave    (NMPlatform *self, int ifindex, guint32 powersave);
 guint32     nm_platform_wifi_find_frequency   (NMPlatform *self, int ifindex, const guint32 *freqs);
 void        nm_platform_wifi_indicate_addressing_running (NMPlatform *self, int ifindex, gboolean running);
+gboolean    nm_platform_wifi_set_wake_on_wlan (NMPlatform *self, int ifindex, NMSettingWirelessWakeOnWLan wowl);
 
 guint32     nm_platform_mesh_get_channel      (NMPlatform *self, int ifindex);
 gboolean    nm_platform_mesh_set_channel      (NMPlatform *self, int ifindex, guint32 channel);
@@ -1449,6 +1452,7 @@ int nm_platform_ip_address_cmp_expiry (const NMPlatformIPAddress *a, const NMPla
 gboolean nm_platform_ethtool_set_wake_on_lan (NMPlatform *self, int ifindex, NMSettingWiredWakeOnLan wol, const char *wol_password);
 gboolean nm_platform_ethtool_set_link_settings (NMPlatform *self, int ifindex, gboolean autoneg, guint32 speed, NMPlatformLinkDuplexType duplex);
 gboolean nm_platform_ethtool_get_link_settings (NMPlatform *self, int ifindex, gboolean *out_autoneg, guint32 *out_speed, NMPlatformLinkDuplexType *out_duplex);
+const char * nm_platform_link_duplex_type_to_string (NMPlatformLinkDuplexType duplex);
 
 void nm_platform_ip4_dev_route_blacklist_set (NMPlatform *self,
                                               int ifindex,
diff --git a/src/platform/wifi/wifi-utils-nl80211.c b/src/platform/wifi/wifi-utils-nl80211.c
index 767e23a9..6c2ff3f5 100644
--- a/src/platform/wifi/wifi-utils-nl80211.c
+++ b/src/platform/wifi/wifi-utils-nl80211.c
@@ -271,6 +271,47 @@ nla_put_failure:
 	return FALSE;
 }
 
+static gboolean
+wifi_nl80211_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl)
+{
+	WifiDataNl80211 *nl80211 = (WifiDataNl80211 *) data;
+	nm_auto_nlmsg struct nl_msg *msg = NULL;
+	struct nlattr *triggers;
+	int err;
+
+	if (wowl == NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE)
+		return TRUE;
+
+	msg = nl80211_alloc_msg(nl80211, NL80211_CMD_SET_WOWLAN, 0);
+	if (!msg)
+		return FALSE;
+
+	triggers = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);
+
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_ANY);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_DISCONNECT);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_MAGIC_PKT);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE);
+	if (NM_FLAGS_HAS (wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE))
+		NLA_PUT_FLAG (msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE);
+
+	nla_nest_end(msg, triggers);
+
+	err = nl80211_send_and_recv (nl80211, msg, NULL, NULL);
+	return err ? FALSE : TRUE;
+
+nla_put_failure:
+	return FALSE;
+}
+
 /* @divisor: pass what value @xbm should be divided by to get dBm */
 static guint32
 nl80211_xbm_to_percent (gint32 xbm, guint32 divisor)
@@ -846,6 +887,7 @@ wifi_nl80211_init (int ifindex)
 		.get_mode = wifi_nl80211_get_mode,
 		.set_mode = wifi_nl80211_set_mode,
 		.set_powersave = wifi_nl80211_set_powersave,
+		.set_wake_on_wlan = wifi_nl80211_set_wake_on_wlan,
 		.get_freq = wifi_nl80211_get_freq,
 		.find_freq = wifi_nl80211_find_freq,
 		.get_bssid = wifi_nl80211_get_bssid,
diff --git a/src/platform/wifi/wifi-utils-private.h b/src/platform/wifi/wifi-utils-private.h
index 59386514..627108cb 100644
--- a/src/platform/wifi/wifi-utils-private.h
+++ b/src/platform/wifi/wifi-utils-private.h
@@ -34,6 +34,9 @@ typedef struct {
 	/* Set power saving mode on an interface */
 	gboolean (*set_powersave) (WifiData *data, guint32 powersave);
 
+	/* Set WakeOnWLAN mode on an interface */
+	gboolean (*set_wake_on_wlan) (WifiData *data, NMSettingWirelessWakeOnWLan wowl);
+
 	/* Return current frequency in MHz (really associated BSS frequency) */
 	guint32 (*get_freq) (WifiData *data);
 
diff --git a/src/platform/wifi/wifi-utils.c b/src/platform/wifi/wifi-utils.c
index 8818dc9d..b3dd92ba 100644
--- a/src/platform/wifi/wifi-utils.c
+++ b/src/platform/wifi/wifi-utils.c
@@ -112,6 +112,15 @@ wifi_utils_set_powersave (WifiData *data, guint32 powersave)
 	return data->klass->set_powersave ? data->klass->set_powersave (data, powersave) : TRUE;
 }
 
+gboolean
+wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl)
+{
+	g_return_val_if_fail (data != NULL, FALSE);
+
+	return data->klass->set_wake_on_wlan ?
+	       data->klass->set_wake_on_wlan (data, wowl) : FALSE;
+}
+
 guint32
 wifi_utils_get_freq (WifiData *data)
 {
diff --git a/src/platform/wifi/wifi-utils.h b/src/platform/wifi/wifi-utils.h
index 8acc35fc..c69561de 100644
--- a/src/platform/wifi/wifi-utils.h
+++ b/src/platform/wifi/wifi-utils.h
@@ -25,6 +25,7 @@
 #include <net/ethernet.h>
 
 #include "nm-dbus-interface.h"
+#include "nm-setting-wireless.h"
 
 typedef struct WifiData WifiData;
 
@@ -66,6 +67,8 @@ gboolean wifi_utils_get_wowlan (WifiData *data);
 
 gboolean wifi_utils_set_powersave (WifiData *data, guint32 powersave);
 
+gboolean wifi_utils_set_wake_on_wlan (WifiData *data, NMSettingWirelessWakeOnWLan wowl);
+
 /* OLPC Mesh-only functions */
 guint32 wifi_utils_get_mesh_channel (WifiData *data);