summary refs log tree commit diff
path: root/libnm-core
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 /libnm-core
parent04bc9e1cd3544445d883ad29ea108c1645c8e7b7 (diff)
New upstream version 1.11.90 upstream/1.11.90
Diffstat (limited to 'libnm-core')
-rw-r--r--libnm-core/nm-connection.c6
-rw-r--r--libnm-core/nm-core-internal.h3
-rw-r--r--libnm-core/nm-setting-connection.c3
-rw-r--r--libnm-core/nm-setting-ip6-config.c93
-rw-r--r--libnm-core/nm-setting-ip6-config.h4
-rw-r--r--libnm-core/nm-setting-macsec.c40
-rw-r--r--libnm-core/nm-setting-macsec.h3
-rw-r--r--libnm-core/nm-setting-team.c2
-rw-r--r--libnm-core/nm-setting-wired.c71
-rw-r--r--libnm-core/nm-setting-wireless.c72
-rw-r--r--libnm-core/nm-setting-wireless.h46
-rw-r--r--libnm-core/nm-utils.c75
-rw-r--r--libnm-core/nm-utils.h5
13 files changed, 383 insertions, 40 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index 790e98b8..0c4d7ce1 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -791,13 +791,11 @@ _normalize_ethernet_link_neg (NMConnection *self)
 	NMSettingWired *s_wired = nm_connection_get_setting_wired (self);
 
 	if (s_wired) {
-		gboolean autoneg = nm_setting_wired_get_auto_negotiate (s_wired);
 		guint32 speed = nm_setting_wired_get_speed (s_wired);
 		const char *duplex = nm_setting_wired_get_duplex (s_wired);
 
-		if (   (autoneg && (speed || duplex))
-		    || (!autoneg && (   (speed && !duplex)
-		                     || (!speed && duplex)))) {
+		if (   (speed && !duplex)
+		    || (!speed && duplex)) {
 			speed = 0;
 			duplex = NULL;
 			g_object_set (s_wired,
diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h
index cace423a..2a2045e6 100644
--- a/libnm-core/nm-core-internal.h
+++ b/libnm-core/nm-core-internal.h
@@ -508,4 +508,7 @@ _nm_connection_type_is_master (const char *type)
 
 /*****************************************************************************/
 
+gboolean _nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin);
+
+/*****************************************************************************/
 #endif
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index f8f1b017..2649838c 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -1544,7 +1544,8 @@ nm_setting_connection_class_init (NMSettingConnectionClass *setting_class)
 	 * with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the
 	 * generated cloned MAC address for ethernet.cloned-mac-address=stable
 	 * and wifi.cloned-mac-address=stable. It is also used as DHCP client
-	 * identifier with ipv4.dhcp-client-id=stable.
+	 * identifier with ipv4.dhcp-client-id=stable and to derive the DHCP
+	 * DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid].
 	 *
 	 * Note that depending on the context where it is used, other parameters are
 	 * also seeded into the generation algorithm. For example, a per-host key
diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c
index 7c2b45f2..808c88a7 100644
--- a/libnm-core/nm-setting-ip6-config.c
+++ b/libnm-core/nm-setting-ip6-config.c
@@ -28,6 +28,7 @@
 
 #include "nm-setting-private.h"
 #include "nm-core-enum-types.h"
+#include "nm-core-internal.h"
 
 /**
  * SECTION:nm-setting-ip6-config
@@ -61,6 +62,7 @@ typedef struct {
 	NMSettingIP6ConfigPrivacy ip6_privacy;
 	NMSettingIP6ConfigAddrGenMode addr_gen_mode;
 	char *token;
+	char *dhcp_duid;
 } NMSettingIP6ConfigPrivate;
 
 enum {
@@ -68,6 +70,7 @@ enum {
 	PROP_IP6_PRIVACY,
 	PROP_ADDR_GEN_MODE,
 	PROP_TOKEN,
+	PROP_DHCP_DUID,
 
 	LAST_PROP
 };
@@ -141,6 +144,26 @@ nm_setting_ip6_config_get_token (NMSettingIP6Config *setting)
 	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->token;
 }
 
+/**
+ * nm_setting_ip6_config_get_dhcp_duid:
+ * @setting: the #NMSettingIP6Config
+ *
+ * Returns the value contained in the #NMSettingIP6Config:dhcp-duid
+ * property.
+ *
+ * Returns: The configured DUID value to be included in the DHCPv6 requests
+ * sent to the DHCPv6 servers.
+ *
+ * Since: 1.12
+ **/
+const char *
+nm_setting_ip6_config_get_dhcp_duid (NMSettingIP6Config *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_IP6_CONFIG (setting), NULL);
+
+	return NM_SETTING_IP6_CONFIG_GET_PRIVATE (setting)->dhcp_duid;
+}
+
 static gboolean
 verify (NMSetting *setting, NMConnection *connection, GError **error)
 {
@@ -254,6 +277,17 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		}
 	}
 
+	if (priv->dhcp_duid) {
+		if (!_nm_utils_dhcp_duid_valid (priv->dhcp_duid, NULL)) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("invalid DUID"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_IP6_CONFIG_SETTING_NAME, NM_SETTING_IP6_CONFIG_DHCP_DUID);
+			return FALSE;
+		}
+	}
+
 	/* Failures from here on, are NORMALIZABLE_ERROR... */
 
 	if (token_needs_normalization) {
@@ -467,6 +501,10 @@ set_property (GObject *object, guint prop_id,
 		g_free (priv->token);
 		priv->token = g_value_dup_string (value);
 		break;
+	case PROP_DHCP_DUID:
+		g_free (priv->dhcp_duid);
+		priv->dhcp_duid = g_value_dup_string (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -489,6 +527,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_TOKEN:
 		g_value_set_string (value, priv->token);
 		break;
+	case PROP_DHCP_DUID:
+		g_value_set_string (value, priv->dhcp_duid);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -502,6 +543,7 @@ finalize (GObject *object)
 	NMSettingIP6ConfigPrivate *priv = NM_SETTING_IP6_CONFIG_GET_PRIVATE (self);
 
 	g_free (priv->token);
+	g_free (priv->dhcp_duid);
 
 	G_OBJECT_CLASS (nm_setting_ip6_config_parent_class)->finalize (object);
 }
@@ -790,6 +832,57 @@ nm_setting_ip6_config_class_init (NMSettingIP6ConfigClass *ip6_class)
 		                      NM_SETTING_PARAM_INFERRABLE |
 		                      G_PARAM_STATIC_STRINGS));
 
+	/**
+	 * NMSettingIP6Config:dhcp-duid:
+	 *
+	 * A string containing the DHCPv6 Unique Identifier (DUID) used by the dhcp
+	 * client to identify itself to DHCPv6 servers (RFC 3315). The DUID is carried
+	 * in the Client Identifier option.
+	 * If the property is a hex string ('aa:bb:cc') it is interpreted as a binary
+	 * DUID and filled as an opaque value in the Client Identifier option.
+	 *
+	 * The special value "lease" will retrieve the DUID previously used from the
+	 * lease file belonging to the connection. If no DUID is found and "dhclient"
+	 * is the configured dhcp client, the DUID is searched in the system-wide
+	 * dhclient lease file. If still no DUID is found, or another dhcp client is
+	 * used, a global and permanent DUID-UUID (RFC 6355) will be generated based
+	 * on the machine-id.
+	 *
+	 * The special values "llt" and "ll" will generate a DUID of type LLT or LL
+	 * (see RFC 3315) based on the current MAC address of the device. In order to
+	 * try providing a stable DUID-LLT, the time field will contain a constant
+	 * timestamp that is used globally (for all profiles) and persisted to disk.
+	 *
+	 * The special values "stable-llt", "stable-ll" and "stable-uuid" will generate
+	 * a DUID of the corresponding type, derived from the connection's stable-id and
+	 * a per-host unique key.
+	 * So, the link-layer address of "stable-ll" and "stable-llt" will be a generated
+	 * address derived from the stable id. The DUID-LLT time value in the "stable-llt"
+	 * option will be picked among a static timespan of three years (the upper bound
+	 * of the interval is the same constant timestamp used in "llt").
+	 *
+	 * When the property is unset, the global value provided for "ipv6.dhcp-duid" is
+	 * used. If no global value is provided, the default "lease" value is assumed.
+	 *
+	 * Since: 1.12
+	 **/
+	/* ---ifcfg-rh---
+	 * property: dhcp-duid
+	 * variable: DHCPV6_DUID(+)
+	 * description: A string sent to the DHCPv6 server to identify the local machine.
+	 *   Apart from the special values "lease", "stable-llt", "stable-ll", "stable-uuid",
+	 *   "llt" and "ll" a binary value in hex format is expected. An hex string where
+	 *   each octet is separated by a colon is also accepted.
+	 * example: DHCPV6_DUID=LL; DHCPV6_DUID=0301deadbeef0001; DHCPV6_DUID=03:01:de:ad:be:ef:00:01
+	 * ---end---
+	 */
+	g_object_class_install_property
+		(object_class, PROP_DHCP_DUID,
+		 g_param_spec_string (NM_SETTING_IP6_CONFIG_DHCP_DUID, "", "",
+		                      NULL,
+		                      G_PARAM_READWRITE |
+		                      G_PARAM_STATIC_STRINGS));
+
 	/* IP6-specific property overrides */
 
 	/* ---dbus---
diff --git a/libnm-core/nm-setting-ip6-config.h b/libnm-core/nm-setting-ip6-config.h
index e01a36b7..ae8ab1a2 100644
--- a/libnm-core/nm-setting-ip6-config.h
+++ b/libnm-core/nm-setting-ip6-config.h
@@ -45,6 +45,8 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_IP6_CONFIG_TOKEN "token"
 
+#define NM_SETTING_IP6_CONFIG_DHCP_DUID "dhcp-duid"
+
 /**
  * NM_SETTING_IP6_CONFIG_METHOD_IGNORE:
  *
@@ -162,6 +164,8 @@ NM_AVAILABLE_IN_1_2
 NMSettingIP6ConfigAddrGenMode nm_setting_ip6_config_get_addr_gen_mode (NMSettingIP6Config *setting);
 NM_AVAILABLE_IN_1_4
 const char *nm_setting_ip6_config_get_token (NMSettingIP6Config *setting);
+NM_AVAILABLE_IN_1_12
+const char *nm_setting_ip6_config_get_dhcp_duid (NMSettingIP6Config *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-macsec.c b/libnm-core/nm-setting-macsec.c
index 7a8a5a34..92ebafa6 100644
--- a/libnm-core/nm-setting-macsec.c
+++ b/libnm-core/nm-setting-macsec.c
@@ -49,7 +49,8 @@ NM_SETTING_REGISTER_TYPE (NM_TYPE_SETTING_MACSEC)
 typedef struct {
 	char *parent;
 	NMSettingMacsecMode mode;
-	gboolean encrypt;
+	bool encrypt:1;
+	bool send_sci:1;
 	char *mka_cak;
 	NMSettingSecretFlags mka_cak_flags;
 	char *mka_ckn;
@@ -66,6 +67,7 @@ NM_GOBJECT_PROPERTIES_DEFINE_BASE (
 	PROP_MKA_CKN,
 	PROP_PORT,
 	PROP_VALIDATION,
+	PROP_SEND_SCI,
 );
 
 /**
@@ -204,6 +206,21 @@ nm_setting_macsec_get_validation (NMSettingMacsec *setting)
 	return NM_SETTING_MACSEC_GET_PRIVATE (setting)->validation;
 }
 
+/**
+ * nm_setting_macsec_get_send_sci:
+ * @setting: the #NMSettingMacsec
+ *
+ * Returns: the #NMSettingMacsec:send-sci property of the setting
+ *
+ * Since: 1.12
+ **/
+gboolean
+nm_setting_macsec_get_send_sci (NMSettingMacsec *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_MACSEC (setting), TRUE);
+	return NM_SETTING_MACSEC_GET_PRIVATE (setting)->send_sci;
+}
+
 static GPtrArray *
 need_secrets (NMSetting *setting)
 {
@@ -390,6 +407,9 @@ set_property (GObject *object, guint prop_id,
 	case PROP_VALIDATION:
 		priv->validation = g_value_get_int (value);
 		break;
+	case PROP_SEND_SCI:
+		priv->send_sci = g_value_get_boolean (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -428,6 +448,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_VALIDATION:
 		g_value_set_int (value, priv->validation);
 		break;
+	case PROP_SEND_SCI:
+		g_value_set_boolean (value, priv->send_sci);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -588,5 +611,20 @@ nm_setting_macsec_class_init (NMSettingMacsecClass *setting_class)
 	                      NM_SETTING_PARAM_INFERRABLE |
 	                      G_PARAM_STATIC_STRINGS);
 
+	/**
+	 * NMSettingMacsec:send-sci:
+	 *
+	 * Specifies whether the SCI (Secure Channel Identifier) is included
+	 * in every packet.
+	 *
+	 * Since: 1.12
+	 **/
+	obj_properties[PROP_SEND_SCI] =
+	    g_param_spec_boolean (NM_SETTING_MACSEC_SEND_SCI, "", "",
+	                          TRUE,
+	                          G_PARAM_READWRITE |
+	                          G_PARAM_CONSTRUCT |
+	                          G_PARAM_STATIC_STRINGS);
+
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }
diff --git a/libnm-core/nm-setting-macsec.h b/libnm-core/nm-setting-macsec.h
index 6a524faa..0f545007 100644
--- a/libnm-core/nm-setting-macsec.h
+++ b/libnm-core/nm-setting-macsec.h
@@ -47,6 +47,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_MACSEC_MKA_CKN              "mka-ckn"
 #define NM_SETTING_MACSEC_PORT                 "port"
 #define NM_SETTING_MACSEC_VALIDATION           "validation"
+#define NM_SETTING_MACSEC_SEND_SCI             "send-sci"
 
 /**
  * NMSettingMacsec:
@@ -122,6 +123,8 @@ NM_AVAILABLE_IN_1_6
 int         nm_setting_macsec_get_port           (NMSettingMacsec *setting);
 NM_AVAILABLE_IN_1_6
 NMSettingMacsecValidation nm_setting_macsec_get_validation (NMSettingMacsec *setting);
+NM_AVAILABLE_IN_1_12
+gboolean nm_setting_macsec_get_send_sci          (NMSettingMacsec *setting);
 
 G_END_DECLS
 
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
index f49a04da..195e509c 100644
--- a/libnm-core/nm-setting-team.c
+++ b/libnm-core/nm-setting-team.c
@@ -1655,7 +1655,7 @@ nm_setting_team_class_init (NMSettingTeamClass *setting_class)
 	 *
 	 * Corresponds to the teamd runner.name.
 	 * Permitted values are: "roundrobin", "broadcast", "activebackup",
-	 * "loadbalance", "lacp".
+	 * "loadbalance", "lacp", "random".
 	 * When setting the runner, all the properties specific to the runner
 	 * will be reset to the default value; all the properties specific to
 	 * other runners will be set to an empty value (or if not possible to
diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c
index 3ad312e5..5da9ce7d 100644
--- a/libnm-core/nm-setting-wired.c
+++ b/libnm-core/nm-setting-wired.c
@@ -762,32 +762,16 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 	 * with legacy nm-connection-editor which used to save "full" duplex connection as default
 	 */
 
-	if (priv->auto_negotiate) {
-		if (priv->duplex) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("when link autonegotiation is enabled no duplex value is accepted"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_DUPLEX);
-			return NM_SETTING_VERIFY_NORMALIZABLE;
-		}
-		if (priv->speed) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("when link autonegotiation is enabled speed should be 0"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_SPEED);
-			return NM_SETTING_VERIFY_NORMALIZABLE;
-		}
-	} else {
-		if (   ((priv->speed) && (!priv->duplex))
-		    || ((!priv->speed) && (priv->duplex))) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("both speed and duplex are required for static link configuration"));
-			return NM_SETTING_VERIFY_NORMALIZABLE;
-		}
+	if (   ((priv->speed) && (!priv->duplex))
+	    || ((!priv->speed) && (priv->duplex))) {
+
+		g_set_error_literal (error,
+				     NM_CONNECTION_ERROR,
+				     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     priv->auto_negotiate ?
+		                       _("both speed and duplex should have a valid value or both should be unset")
+		                     : _("both speed and duplex are required for static link configuration"));
+		return NM_SETTING_VERIFY_NORMALIZABLE;
 	}
 
 	return TRUE;
@@ -1033,8 +1017,16 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class)
 	/**
 	 * NMSettingWired:speed:
 	 *
-	 * Can be set to a value greater than zero only when "auto-negotiate" is "off".
-	 * In that case, statically configures the device to use that specified speed.
+	 * When a value grater than 0 is set, configures the device to use
+	 * the specified speed. If "auto-negotiate" is "yes" the specified
+	 * speed will be the only one advertised during link negotiation:
+	 * this works only for BASE-T 802.3 specifications and is useful for
+	 * enforcing gigabit speeds, as in this case link negotiation is
+	 * mandatory.
+	 * If the value is unset (0, the default), the link configuration will be
+	 * either skipped (if "auto-negotiate" is "no", the default) or will
+	 * be auto-negotiated (if "auto-negotiate" is "yes") and the local device
+	 * will advertise all the supported speeds.
 	 * In Mbit/s, ie 100 == 100Mbit/s.
 	 * Must be set together with the "duplex" property when non-zero.
 	 * Before specifying a speed value be sure your device supports it.
@@ -1057,8 +1049,16 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class)
 	/**
 	 * NMSettingWired:duplex:
 	 *
-	 * Can be specified only when "auto-negotiate" is "off". In that case, statically
-	 * configures the device to use that specified duplex mode, either "half" or "full".
+	 * When a value is set, either "half" or "full", configures the device
+	 * to use the specified duplex mode. If "auto-negotiate" is "yes" the
+	 * specified duplex mode will be the only one advertised during link
+	 * negotiation: this works only for BASE-T 802.3 specifications and is
+	 * useful for enforcing gigabits modes, as in these cases link negotiation
+	 * is mandatory.
+	 * If the value is unset (the default), the link configuration will be
+	 * either skipped (if "auto-negotiate" is "no", the default) or will
+	 * be auto-negotiated (if "auto-negotiate" is "yes") and the local device
+	 * will advertise all the supported duplex modes.
 	 * Must be set together with the "speed" property if specified.
 	 * Before specifying a duplex mode be sure your device supports it.
 	 **/
@@ -1079,9 +1079,14 @@ nm_setting_wired_class_init (NMSettingWiredClass *setting_wired_class)
 	/**
 	 * NMSettingWired:auto-negotiate:
 	 *
-	 * If %TRUE, enforce auto-negotiation of port speed and duplex mode.  If
-	 * %FALSE, "speed" and "duplex" properties should be both set or link configuration
-	 * will be skipped.
+	 * When %TRUE, enforce auto-negotiation of speed and duplex mode.
+	 * If "speed" and "duplex" properties are both specified, only that
+	 * single mode will be advertised and accepted during the link
+	 * auto-negotiation process: this works only for BASE-T 802.3 specifications
+	 * and is useful for enforcing gigabits modes, as in these cases link
+	 * negotiation is mandatory.
+	 * When %FALSE, "speed" and "duplex" properties should be both set or
+	 * link configuration will be skipped.
 	 **/
 	/* ---ifcfg-rh---
 	 * property: auto-negotiate
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
index 38948dee..89a2df8e 100644
--- a/libnm-core/nm-setting-wireless.c
+++ b/libnm-core/nm-setting-wireless.c
@@ -63,6 +63,7 @@ typedef struct {
 	gboolean hidden;
 	guint32 powersave;
 	NMSettingMacRandomization mac_address_randomization;
+	guint32 wowl;
 } NMSettingWirelessPrivate;
 
 enum {
@@ -83,6 +84,7 @@ enum {
 	PROP_HIDDEN,
 	PROP_POWERSAVE,
 	PROP_MAC_ADDRESS_RANDOMIZATION,
+	PROP_WAKE_ON_WLAN,
 
 	LAST_PROP
 };
@@ -885,6 +887,26 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
 		return FALSE;
 	}
 
+	if (NM_FLAGS_ANY (priv->wowl, NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS)) {
+		if (!nm_utils_is_power_of_two (priv->wowl)) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("Wake-on-WLAN mode 'default' and 'ignore' are exclusive flags"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME,
+			                NM_SETTING_WIRELESS_WAKE_ON_WLAN);
+			return FALSE;
+		}
+	} else if (NM_FLAGS_ANY (priv->wowl, ~NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("Wake-on-WLAN trying to set unknown flag"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME,
+		                NM_SETTING_WIRELESS_WAKE_ON_WLAN);
+		return FALSE;
+	}
+
 	/* from here on, check for NM_SETTING_VERIFY_NORMALIZABLE conditions. */
 
 	if (priv->cloned_mac_address) {
@@ -939,6 +961,24 @@ nm_setting_wireless_get_security (NMSetting    *setting,
 		return NULL;
 }
 
+/**
+ * nm_setting_wireless_get_wake_on_wlan:
+ * @setting: the #NMSettingWireless
+ *
+ * Returns the Wake-on-WLAN options enabled for the connection
+ *
+ * Returns: the Wake-on-WLAN options
+ *
+ * Since: 1.12
+ */
+NMSettingWirelessWakeOnWLan
+nm_setting_wireless_get_wake_on_wlan (NMSettingWireless *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_WIRELESS (setting), NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE);
+
+	return NM_SETTING_WIRELESS_GET_PRIVATE (setting)->wowl;
+}
+
 static void
 clear_blacklist_item (char **item_p)
 {
@@ -1061,6 +1101,9 @@ set_property (GObject *object, guint prop_id,
 	case PROP_MAC_ADDRESS_RANDOMIZATION:
 		priv->mac_address_randomization = g_value_get_uint (value);
 		break;
+	case PROP_WAKE_ON_WLAN:
+		priv->wowl = g_value_get_uint (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1123,6 +1166,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_MAC_ADDRESS_RANDOMIZATION:
 		g_value_set_uint (value, nm_setting_wireless_get_mac_address_randomization (setting));
 		break;
+	case PROP_WAKE_ON_WLAN:
+		g_value_set_uint (value, nm_setting_wireless_get_wake_on_wlan (setting));
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -1636,4 +1682,30 @@ nm_setting_wireless_class_init (NMSettingWirelessClass *setting_wireless_class)
 	_nm_setting_class_add_dbus_only_property (setting_class, "security",
 	                                          G_VARIANT_TYPE_STRING,
 	                                          nm_setting_wireless_get_security, NULL);
+
+	/**
+	 * NMSettingWireless:wake-on-wlan:
+	 *
+	 * The #NMSettingWirelessWakeOnWLan options to enable. Not all devices support all options.
+	 * May be any combination of %NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE,
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP or the special values
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT (to use global settings) and
+	 * %NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE (to disable management of Wake-on-LAN in
+	 * NetworkManager).
+	 *
+	 * Since: 1.12
+	 **/
+	g_object_class_install_property
+		(object_class, PROP_WAKE_ON_WLAN,
+		 g_param_spec_uint (NM_SETTING_WIRELESS_WAKE_ON_WLAN, "", "",
+		                    0, G_MAXUINT32, NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT,
+		                    G_PARAM_CONSTRUCT |
+		                    G_PARAM_READWRITE |
+		                    G_PARAM_STATIC_STRINGS));
 }
diff --git a/libnm-core/nm-setting-wireless.h b/libnm-core/nm-setting-wireless.h
index b0ef4756..e9afe2c6 100644
--- a/libnm-core/nm-setting-wireless.h
+++ b/libnm-core/nm-setting-wireless.h
@@ -41,6 +41,48 @@ G_BEGIN_DECLS
 
 #define NM_SETTING_WIRELESS_SETTING_NAME "802-11-wireless"
 
+/**
+ * NMSettingWirelessWakeOnWLan:
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE: Wake-on-WLAN disabled
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY: Wake on any activity
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT: Wake on disconnect
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC: Wake on magic packet
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE: Wake on GTK rekey failure
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST: Wake on EAP identity request
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE: Wake on 4way hanshake
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE: Wake on rfkill release
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL: Wake on all events. This does not
+ *   include the exclusive flags @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT or
+ *   @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE.
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT: Use the default value
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE: Don't change configured settings
+ * @NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS: Mask of flags that are
+ *   incompatible with other flags
+ *
+ * Options for #NMSettingWireless:wake-on-wlan. Note that not all options
+ * are supported by all devices.
+ *
+ * Since: 1.12
+ */
+typedef enum { /*< flags >*/
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_NONE                 = 0, /*< skip >*/
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_ANY                  = (1 << 1),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_DISCONNECT           = (1 << 2),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_MAGIC                = (1 << 3),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_GTK_REKEY_FAILURE    = (1 << 4),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_EAP_IDENTITY_REQUEST = (1 << 5),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_4WAY_HANDSHAKE       = (1 << 6),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_RFKILL_RELEASE       = (1 << 7),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_TCP                  = (1 << 8),
+	_NM_SETTING_WIRELESS_WAKE_ON_WLAN_NUM, /*< skip >*/
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_LAST                 = _NM_SETTING_WIRELESS_WAKE_ON_WLAN_NUM - 1, /*< skip >*/
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_ALL                  = ((NM_SETTING_WIRELESS_WAKE_ON_WLAN_LAST << 1) - 1) - (1 << 0 /*DEFAULT*/), /*< skip >*/
+
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT              = (1 << 0),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE               = (1 << 15),
+	NM_SETTING_WIRELESS_WAKE_ON_WLAN_EXCLUSIVE_FLAGS = NM_SETTING_WIRELESS_WAKE_ON_WLAN_DEFAULT | NM_SETTING_WIRELESS_WAKE_ON_WLAN_IGNORE, /*< skip >*/
+} NMSettingWirelessWakeOnWLan;
+
 #define NM_SETTING_WIRELESS_SSID        "ssid"
 #define NM_SETTING_WIRELESS_MODE        "mode"
 #define NM_SETTING_WIRELESS_BAND        "band"
@@ -57,6 +99,7 @@ G_BEGIN_DECLS
 #define NM_SETTING_WIRELESS_HIDDEN      "hidden"
 #define NM_SETTING_WIRELESS_POWERSAVE   "powersave"
 #define NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION   "mac-address-randomization"
+#define NM_SETTING_WIRELESS_WAKE_ON_WLAN "wake-on-wlan"
 
 /**
  * NM_SETTING_WIRELESS_MODE_ADHOC:
@@ -166,6 +209,9 @@ gboolean          nm_setting_wireless_ap_security_compatible (NMSettingWireless
                                                               NM80211ApSecurityFlags ap_rsn,
                                                               NM80211Mode ap_mode);
 
+NM_AVAILABLE_IN_1_12
+NMSettingWirelessWakeOnWLan  nm_setting_wireless_get_wake_on_wlan (NMSettingWireless *setting);
+
 G_END_DECLS
 
 #endif /* __NM_SETTING_WIRELESS_H__ */
diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c
index eb65f8db..b700c7f5 100644
--- a/libnm-core/nm-utils.c
+++ b/libnm-core/nm-utils.c
@@ -4437,6 +4437,47 @@ _nm_utils_inet6_is_token (const struct in6_addr *in6addr)
 }
 
 /**
+ * _nm_utils_dhcp_duid_valid:
+ * @duid: the candidate DUID
+ *
+ * Checks if @duid string contains either a special duid value ("ll",
+ * "llt", "lease" or the "stable" variants) or a valid hex DUID.
+ *
+ * Return value: %TRUE or %FALSE
+ */
+gboolean
+_nm_utils_dhcp_duid_valid (const char *duid, GBytes **out_duid_bin)
+{
+	guint8 duid_arr[128 + 2];
+	gsize duid_len;
+
+	NM_SET_OUT (out_duid_bin, NULL);
+
+	if (!duid)
+		return FALSE;
+
+	if (NM_IN_STRSET (duid, "lease",
+	                        "llt",
+	                        "ll",
+	                        "stable-llt",
+	                        "stable-ll",
+	                        "stable-uuid")) {
+		return TRUE;
+	}
+
+	if (_str2bin (duid, FALSE, ":", duid_arr, sizeof (duid_arr), &duid_len)) {
+		/* MAX DUID length is 128 octects + the type code (2 octects). */
+		if (   duid_len > 2
+		    && duid_len <= (128 + 2)) {
+			NM_SET_OUT (out_duid_bin, g_bytes_new (duid_arr, duid_len));
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
+
+/**
  * nm_utils_check_virtual_device_compatibility:
  * @virtual_type: a virtual connection type
  * @other_type: a connection type to test against @virtual_type
@@ -6182,6 +6223,40 @@ nm_utils_format_variant_attributes (GHashTable *attributes,
 
 /*****************************************************************************/
 
+/*
+ * nm_utils_get_timestamp_msec():
+ *
+ * Gets current time in milliseconds of CLOCK_BOOTTIME.
+ *
+ * Returns: time in milliseconds
+ *
+ * Since: 1.12
+ */
+gint64
+nm_utils_get_timestamp_msec (void)
+{
+	struct timespec ts;
+
+	if (clock_gettime (CLOCK_BOOTTIME, &ts) != -1)
+		goto success;
+
+	if (errno == EINVAL) {
+		/* The fallback to CLOCK_MONOTONIC is taken only if we're running on a
+		 * criminally old kernel, prior to 2.6.39 (released on 18 May, 2011).
+		 * That happens during buildcheck on old builders, we don't expect to
+		 * be actually runs on kernels that old. */
+		if (clock_gettime (CLOCK_MONOTONIC, &ts) != -1)
+			goto success;
+	}
+
+	g_return_val_if_reached (-1);
+
+success:
+	return (((gint64) ts.tv_sec) * 1000) + (ts.tv_nsec / 1000000);
+}
+
+/*****************************************************************************/
+
 /**
  * nm_utils_version:
  *
diff --git a/libnm-core/nm-utils.h b/libnm-core/nm-utils.h
index 1f645a80..70245869 100644
--- a/libnm-core/nm-utils.h
+++ b/libnm-core/nm-utils.h
@@ -248,6 +248,11 @@ NMTCTfilter *nm_utils_tc_tfilter_from_str  (const char *str, GError **error);
 NM_AVAILABLE_IN_1_12
 char *nm_utils_tc_tfilter_to_str           (NMTCTfilter *tfilter, GError **error);
 
+/*****************************************************************************/
+
+NM_AVAILABLE_IN_1_12
+gint64 nm_utils_get_timestamp_msec         (void);
+
 G_END_DECLS
 
 #endif /* __NM_UTILS_H__ */