about summary refs log tree commit diff
path: root/src/supplicant
diff options
context:
space:
mode:
Diffstat (limited to 'src/supplicant')
-rw-r--r--src/supplicant/nm-supplicant-config.c62
-rw-r--r--src/supplicant/nm-supplicant-config.h4
-rw-r--r--src/supplicant/nm-supplicant-interface.c156
-rw-r--r--src/supplicant/nm-supplicant-interface.h31
-rw-r--r--src/supplicant/nm-supplicant-manager.c44
-rw-r--r--src/supplicant/nm-supplicant-manager.h1
-rw-r--r--src/supplicant/nm-supplicant-settings-verify.c12
-rw-r--r--src/supplicant/nm-supplicant-settings-verify.h1
-rw-r--r--src/supplicant/nm-supplicant-types.h1
-rw-r--r--src/supplicant/tests/test-supplicant-config.c3
10 files changed, 277 insertions, 38 deletions
diff --git a/src/supplicant/nm-supplicant-config.c b/src/supplicant/nm-supplicant-config.c
index 7708224b..806c087c 100644
--- a/src/supplicant/nm-supplicant-config.c
+++ b/src/supplicant/nm-supplicant-config.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -50,6 +49,8 @@ typedef struct {
 	gboolean   dispose_has_run;
 	gboolean   support_pmf;
 	gboolean   support_fils;
+	gboolean   support_ft;
+	gboolean   support_sha384;
 } NMSupplicantConfigPrivate;
 
 struct _NMSupplicantConfig {
@@ -68,7 +69,8 @@ G_DEFINE_TYPE (NMSupplicantConfig, nm_supplicant_config, G_TYPE_OBJECT)
 /*****************************************************************************/
 
 NMSupplicantConfig *
-nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils)
+nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils,
+                          gboolean support_ft, gboolean support_sha384)
 {
 	NMSupplicantConfigPrivate *priv;
 	NMSupplicantConfig *self;
@@ -78,6 +80,8 @@ nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils)
 
 	priv->support_pmf = support_pmf;
 	priv->support_fils = support_fils;
+	priv->support_ft = support_ft;
+	priv->support_sha384 = support_sha384;
 
 	return self;
 }
@@ -454,7 +458,7 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
                                            GError **error)
 {
 	NMSupplicantConfigPrivate *priv;
-	gboolean is_adhoc, is_ap;
+	gboolean is_adhoc, is_ap, is_mesh;
 	const char *mode, *band;
 	guint32 channel;
 	GBytes *ssid;
@@ -469,6 +473,7 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
 	mode = nm_setting_wireless_get_mode (setting);
 	is_adhoc = (mode && !strcmp (mode, "adhoc")) ? TRUE : FALSE;
 	is_ap = (mode && !strcmp (mode, "ap")) ? TRUE : FALSE;
+	is_mesh = (mode && !strcmp (mode, "mesh")) ? TRUE : FALSE;
 	if (is_adhoc || is_ap)
 		priv->ap_scan = 2;
 	else
@@ -498,7 +503,12 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
 			return FALSE;
 	}
 
-	if ((is_adhoc || is_ap) && fixed_freq) {
+	if (is_mesh) {
+		if (!nm_supplicant_config_add_option (self, "mode", "5", -1, NULL, error))
+			return FALSE;
+	}
+
+	if ((is_adhoc || is_ap || is_mesh) && fixed_freq) {
 		gs_free char *str_freq = NULL;
 
 		str_freq = g_strdup_printf ("%u", fixed_freq);
@@ -506,10 +516,10 @@ nm_supplicant_config_add_setting_wireless (NMSupplicantConfig * self,
 			return FALSE;
 	}
 
-	/* Except for Ad-Hoc and Hotspot, request that the driver probe for the
+	/* Except for Ad-Hoc, Hotspot and Mesh, request that the driver probe for the
 	 * specific SSID we want to associate with.
 	 */
-	if (!(is_adhoc || is_ap)) {
+	if (!(is_adhoc || is_ap || is_mesh)) {
 		if (!nm_supplicant_config_add_option (self, "scan_ssid", "1", -1, NULL, error))
 			return FALSE;
 	}
@@ -755,7 +765,8 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
                                                     GError **error)
 {
 	NMSupplicantConfigPrivate *priv = NM_SUPPLICANT_CONFIG_GET_PRIVATE (self);
-	const char *key_mgmt, *key_mgmt_conf, *auth_alg;
+	nm_auto_free_gstring GString *key_mgmt_conf = NULL;
+	const char *key_mgmt, *auth_alg;
 	const char *psk;
 	gboolean set_pmf;
 
@@ -774,28 +785,43 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
 			fils = NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE;
 	}
 
-	key_mgmt = key_mgmt_conf = nm_setting_wireless_security_get_key_mgmt (setting);
+	key_mgmt = nm_setting_wireless_security_get_key_mgmt (setting);
+	key_mgmt_conf = g_string_new (key_mgmt);
 	if (nm_streq (key_mgmt, "wpa-psk")) {
 		if (priv->support_pmf)
-			key_mgmt_conf = "wpa-psk wpa-psk-sha256";
+			g_string_append (key_mgmt_conf, " wpa-psk-sha256");
+		if (priv->support_ft)
+			g_string_append (key_mgmt_conf, " ft-psk");
 	} else if (nm_streq (key_mgmt, "wpa-eap")) {
+		if (priv->support_pmf)
+			g_string_append (key_mgmt_conf, " wpa-eap-sha256");
+		if (priv->support_ft)
+			g_string_append (key_mgmt_conf, " ft-eap");
+		if (priv->support_ft && priv->support_sha384)
+			g_string_append (key_mgmt_conf, " ft-eap-sha384");
 		switch (fils) {
-		case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL:
-			key_mgmt_conf = priv->support_pmf
-				? "wpa-eap wpa-eap-sha256 fils-sha256 fils-sha384"
-				: "wpa-eap fils-sha256 fils-sha384";
-			break;
 		case NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED:
-			key_mgmt_conf = "fils-sha256 fils-sha384";
+			g_string_truncate (key_mgmt_conf, 0);
+			if (!priv->support_pmf)
+				g_string_assign (key_mgmt_conf, "fils-sha256 fils-sha384");
+			/* fall-through */
+		case NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL:
+			if (priv->support_pmf)
+				g_string_append (key_mgmt_conf, " fils-sha256 fils-sha384");
+			if (priv->support_pmf && priv->support_ft)
+				g_string_append (key_mgmt_conf, " ft-fils-sha256");
+			if (priv->support_pmf && priv->support_ft & priv->support_sha384)
+				g_string_append (key_mgmt_conf, " ft-fils-sha384");
 			break;
 		default:
-			if (priv->support_pmf)
-				key_mgmt_conf = "wpa-eap wpa-eap-sha256";
 			break;
 		}
+	} else if (nm_streq (key_mgmt, "sae")) {
+		if (priv->support_ft)
+			g_string_append (key_mgmt_conf, " ft-sae");
 	}
 
-	if (!add_string_val (self, key_mgmt_conf, "key_mgmt", TRUE, NULL, error))
+	if (!add_string_val (self, key_mgmt_conf->str, "key_mgmt", TRUE, NULL, error))
 		return FALSE;
 
 	auth_alg = nm_setting_wireless_security_get_auth_alg (setting);
diff --git a/src/supplicant/nm-supplicant-config.h b/src/supplicant/nm-supplicant-config.h
index f6c845a3..c4e7310d 100644
--- a/src/supplicant/nm-supplicant-config.h
+++ b/src/supplicant/nm-supplicant-config.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -40,7 +39,8 @@ typedef struct _NMSupplicantConfigClass NMSupplicantConfigClass;
 
 GType nm_supplicant_config_get_type (void);
 
-NMSupplicantConfig *nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils);
+NMSupplicantConfig *nm_supplicant_config_new (gboolean support_pmf, gboolean support_fils,
+                                              gboolean support_ft, gboolean support_sha384);
 
 guint32 nm_supplicant_config_get_ap_scan (NMSupplicantConfig *self);
 
diff --git a/src/supplicant/nm-supplicant-interface.c b/src/supplicant/nm-supplicant-interface.c
index 12d21aba..079afca3 100644
--- a/src/supplicant/nm-supplicant-interface.c
+++ b/src/supplicant/nm-supplicant-interface.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -81,6 +80,12 @@ typedef struct _AddNetworkData {
 	AssocData *assoc_data;
 } AddNetworkData;
 
+typedef struct {
+	NMSupplicantInterface *self;
+	NMSupplicantInterfaceDisconnectCb callback;
+	gpointer user_data;
+} DisconnectData;
+
 enum {
 	STATE,                   /* change in the interface's state */
 	REMOVED,                 /* interface was removed by the supplicant */
@@ -113,7 +118,10 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMSupplicantInterface,
 	PROP_PMF_SUPPORT,
 	PROP_FILS_SUPPORT,
 	PROP_P2P_SUPPORT,
+	PROP_MESH_SUPPORT,
 	PROP_WFD_SUPPORT,
+	PROP_FT_SUPPORT,
+	PROP_SHA384_SUPPORT,
 );
 
 typedef struct {
@@ -125,7 +133,10 @@ typedef struct {
 	NMSupplicantFeature pmf_support;
 	NMSupplicantFeature fils_support;
 	NMSupplicantFeature p2p_support;
+	NMSupplicantFeature mesh_support;
 	NMSupplicantFeature wfd_support;
+	NMSupplicantFeature ft_support;
+	NMSupplicantFeature sha384_support;
 	guint32        max_scan_ssids;
 	guint32        ready_count;
 
@@ -782,11 +793,29 @@ nm_supplicant_interface_get_p2p_support (NMSupplicantInterface *self)
 }
 
 NMSupplicantFeature
+nm_supplicant_interface_get_mesh_support (NMSupplicantInterface *self)
+{
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->mesh_support;
+}
+
+NMSupplicantFeature
 nm_supplicant_interface_get_wfd_support (NMSupplicantInterface *self)
 {
 	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->wfd_support;
 }
 
+NMSupplicantFeature
+nm_supplicant_interface_get_ft_support (NMSupplicantInterface *self)
+{
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->ft_support;
+}
+
+NMSupplicantFeature
+nm_supplicant_interface_get_sha384_support (NMSupplicantInterface *self)
+{
+	return NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self)->sha384_support;
+}
+
 void
 nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
                                         NMSupplicantFeature ap_support)
@@ -837,6 +866,15 @@ nm_supplicant_interface_set_p2p_support (NMSupplicantInterface *self,
 }
 
 void
+nm_supplicant_interface_set_mesh_support (NMSupplicantInterface *self,
+                                          NMSupplicantFeature mesh_support)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	priv->mesh_support = mesh_support;
+}
+
+void
 nm_supplicant_interface_set_wfd_support (NMSupplicantInterface *self,
                                          NMSupplicantFeature wfd_support)
 {
@@ -845,6 +883,24 @@ nm_supplicant_interface_set_wfd_support (NMSupplicantInterface *self,
 	priv->wfd_support = wfd_support;
 }
 
+void
+nm_supplicant_interface_set_ft_support (NMSupplicantInterface *self,
+                                        NMSupplicantFeature ft_support)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	priv->ft_support = ft_support;
+}
+
+void
+nm_supplicant_interface_set_sha384_support (NMSupplicantInterface *self,
+                                            NMSupplicantFeature sha384_support)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+
+	priv->sha384_support = sha384_support;
+}
+
 /*****************************************************************************/
 
 static void
@@ -2118,6 +2174,60 @@ nm_supplicant_interface_disconnect (NMSupplicantInterface * self)
 }
 
 static void
+disconnect_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
+{
+	DisconnectData *disconnect_data = user_data;
+	gs_unref_object NMSupplicantInterface *self = disconnect_data->self;
+	gs_unref_variant GVariant *reply = NULL;
+	gs_free_error GError *error = NULL;
+
+	reply = g_dbus_proxy_call_finish (proxy, result, &error);
+
+	/* an already disconnected interface is not an error*/
+	if (   !reply
+	    && !strstr (error->message, "fi.w1.wpa_supplicant1.NotConnected")) {
+		g_clear_error(&error);
+	}
+
+	disconnect_data->callback(self, error, disconnect_data->user_data);
+	g_slice_free (DisconnectData, disconnect_data);
+}
+
+void
+nm_supplicant_interface_disconnect_async ( NMSupplicantInterface * self,
+                                           GCancellable * cancellable,
+                                           NMSupplicantInterfaceDisconnectCb callback,
+                                           gpointer user_data)
+{
+	NMSupplicantInterfacePrivate *priv = NM_SUPPLICANT_INTERFACE_GET_PRIVATE (self);
+	DisconnectData *disconnect_data;
+
+	/* Don't do anything if there is no connection to the supplicant yet. */
+	if (!priv->iface_proxy)
+		return;
+
+	g_return_if_fail (NM_IS_SUPPLICANT_INTERFACE (self));
+	g_return_if_fail (NULL != callback);
+
+	disconnect_data = g_slice_new0(DisconnectData);
+
+	/* Keep interface alive until disconnect finishes */
+	disconnect_data->self = g_object_ref (self);
+	disconnect_data->callback = callback;
+	disconnect_data->user_data = user_data;
+
+	/* Disconnect the interface */
+	g_dbus_proxy_call (priv->iface_proxy,
+	                   "Disconnect",
+	                   NULL,
+	                   G_DBUS_CALL_FLAGS_NONE,
+	                   -1,
+	                   cancellable,
+	                   (GAsyncReadyCallback) disconnect_cb,
+	                   disconnect_data);
+}
+
+static void
 assoc_select_network_cb (GDBusProxy *proxy, GAsyncResult *result, gpointer user_data)
 {
 	NMSupplicantInterface *self;
@@ -2681,10 +2791,22 @@ set_property (GObject *object,
 		/* construct-only */
 		priv->p2p_support = g_value_get_int (value);
 		break;
+	case PROP_MESH_SUPPORT:
+		/* construct-only */
+		priv->mesh_support = g_value_get_int (value);
+		break;
 	case PROP_WFD_SUPPORT:
 		/* construct-only */
 		priv->wfd_support = g_value_get_int (value);
 		break;
+	case PROP_FT_SUPPORT:
+		/* construct-only */
+		priv->ft_support = g_value_get_int (value);
+		break;
+	case PROP_SHA384_SUPPORT:
+		/* construct-only */
+		priv->sha384_support = g_value_get_int (value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -2710,7 +2832,10 @@ nm_supplicant_interface_new (const char *ifname,
                              NMSupplicantFeature pmf_support,
                              NMSupplicantFeature fils_support,
                              NMSupplicantFeature p2p_support,
-                             NMSupplicantFeature wfd_support)
+                             NMSupplicantFeature mesh_support,
+                             NMSupplicantFeature wfd_support,
+                             NMSupplicantFeature ft_support,
+                             NMSupplicantFeature sha384_support)
 {
 	/* One of ifname or path need to be set */
 	g_return_val_if_fail (ifname != NULL || object_path != NULL, NULL);
@@ -2725,7 +2850,10 @@ nm_supplicant_interface_new (const char *ifname,
 	                     NM_SUPPLICANT_INTERFACE_PMF_SUPPORT, (int) pmf_support,
 	                     NM_SUPPLICANT_INTERFACE_FILS_SUPPORT, (int) fils_support,
 	                     NM_SUPPLICANT_INTERFACE_P2P_SUPPORT, (int) p2p_support,
+	                     NM_SUPPLICANT_INTERFACE_MESH_SUPPORT, (int) mesh_support,
 	                     NM_SUPPLICANT_INTERFACE_WFD_SUPPORT, (int) wfd_support,
+	                     NM_SUPPLICANT_INTERFACE_FT_SUPPORT, (int) ft_support,
+	                     NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT, (int) sha384_support,
 	                     NULL);
 }
 
@@ -2876,6 +3004,14 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 	                      G_PARAM_WRITABLE |
 	                      G_PARAM_CONSTRUCT_ONLY |
 	                      G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_MESH_SUPPORT] =
+	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_MESH_SUPPORT, "", "",
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      NM_SUPPLICANT_FEATURE_YES,
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      G_PARAM_WRITABLE |
+	                      G_PARAM_CONSTRUCT_ONLY |
+	                      G_PARAM_STATIC_STRINGS);
 	obj_properties[PROP_WFD_SUPPORT] =
 	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_WFD_SUPPORT, "", "",
 	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
@@ -2884,6 +3020,22 @@ nm_supplicant_interface_class_init (NMSupplicantInterfaceClass *klass)
 	                      G_PARAM_WRITABLE |
 	                      G_PARAM_CONSTRUCT_ONLY |
 	                      G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_FT_SUPPORT] =
+	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_FT_SUPPORT, "", "",
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      NM_SUPPLICANT_FEATURE_YES,
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      G_PARAM_WRITABLE |
+	                      G_PARAM_CONSTRUCT_ONLY |
+	                      G_PARAM_STATIC_STRINGS);
+	obj_properties[PROP_SHA384_SUPPORT] =
+	    g_param_spec_int (NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT, "", "",
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      NM_SUPPLICANT_FEATURE_YES,
+	                      NM_SUPPLICANT_FEATURE_UNKNOWN,
+	                      G_PARAM_WRITABLE |
+	                      G_PARAM_CONSTRUCT_ONLY |
+	                      G_PARAM_STATIC_STRINGS);
 
 	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 
diff --git a/src/supplicant/nm-supplicant-interface.h b/src/supplicant/nm-supplicant-interface.h
index 0aa7732a..653830da 100644
--- a/src/supplicant/nm-supplicant-interface.h
+++ b/src/supplicant/nm-supplicant-interface.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -68,7 +67,10 @@ typedef enum {
 #define NM_SUPPLICANT_INTERFACE_PMF_SUPPORT      "pmf-support"
 #define NM_SUPPLICANT_INTERFACE_FILS_SUPPORT     "fils-support"
 #define NM_SUPPLICANT_INTERFACE_P2P_SUPPORT      "p2p-support"
+#define NM_SUPPLICANT_INTERFACE_MESH_SUPPORT     "mesh-support"
 #define NM_SUPPLICANT_INTERFACE_WFD_SUPPORT      "wfd-support"
+#define NM_SUPPLICANT_INTERFACE_FT_SUPPORT       "ft-support"
+#define NM_SUPPLICANT_INTERFACE_SHA384_SUPPORT   "sha384-support"
 
 /* Signals */
 #define NM_SUPPLICANT_INTERFACE_STATE            "state"
@@ -96,7 +98,10 @@ NMSupplicantInterface * nm_supplicant_interface_new (const char *ifname,
                                                      NMSupplicantFeature pmf_support,
                                                      NMSupplicantFeature fils_support,
                                                      NMSupplicantFeature p2p_support,
-                                                     NMSupplicantFeature wfd_support);
+                                                     NMSupplicantFeature mesh_support,
+                                                     NMSupplicantFeature wfd_support,
+                                                     NMSupplicantFeature ft_support,
+                                                     NMSupplicantFeature sha384_support);
 
 void nm_supplicant_interface_set_supplicant_available (NMSupplicantInterface *self,
                                                        gboolean available);
@@ -113,6 +118,16 @@ nm_supplicant_interface_assoc (NMSupplicantInterface *self,
 
 void nm_supplicant_interface_disconnect (NMSupplicantInterface * iface);
 
+typedef void (*NMSupplicantInterfaceDisconnectCb) (NMSupplicantInterface *iface,
+                                                   GError *error,
+                                                   gpointer user_data);
+
+void
+nm_supplicant_interface_disconnect_async (NMSupplicantInterface * self,
+                                          GCancellable * cancellable,
+                                          NMSupplicantInterfaceDisconnectCb callback,
+                                          gpointer user_data);
+
 const char *nm_supplicant_interface_get_object_path (NMSupplicantInterface * iface);
 
 void nm_supplicant_interface_request_scan (NMSupplicantInterface *self,
@@ -161,7 +176,10 @@ NMSupplicantFeature nm_supplicant_interface_get_ap_support (NMSupplicantInterfac
 NMSupplicantFeature nm_supplicant_interface_get_pmf_support (NMSupplicantInterface *self);
 NMSupplicantFeature nm_supplicant_interface_get_fils_support (NMSupplicantInterface *self);
 NMSupplicantFeature nm_supplicant_interface_get_p2p_support (NMSupplicantInterface *self);
+NMSupplicantFeature nm_supplicant_interface_get_mesh_support (NMSupplicantInterface *self);
 NMSupplicantFeature nm_supplicant_interface_get_wfd_support (NMSupplicantInterface *self);
+NMSupplicantFeature nm_supplicant_interface_get_ft_support (NMSupplicantInterface *self);
+NMSupplicantFeature nm_supplicant_interface_get_sha384_support (NMSupplicantInterface *self);
 
 void nm_supplicant_interface_set_ap_support (NMSupplicantInterface *self,
                                              NMSupplicantFeature apmode);
@@ -178,9 +196,18 @@ void nm_supplicant_interface_set_fils_support (NMSupplicantInterface *self,
 void nm_supplicant_interface_set_p2p_support (NMSupplicantInterface *self,
                                               NMSupplicantFeature p2p_support);
 
+void nm_supplicant_interface_set_mesh_support (NMSupplicantInterface *self,
+                                               NMSupplicantFeature mesh_support);
+
 void nm_supplicant_interface_set_wfd_support (NMSupplicantInterface *self,
                                               NMSupplicantFeature wfd_support);
 
+void nm_supplicant_interface_set_ft_support (NMSupplicantInterface *self,
+                                             NMSupplicantFeature ft_support);
+
+void nm_supplicant_interface_set_sha384_support (NMSupplicantInterface *self,
+                                                 NMSupplicantFeature sha384_support);
+
 void nm_supplicant_interface_enroll_wps (NMSupplicantInterface *self,
                                          const char *const type,
                                          const char *bssid,
diff --git a/src/supplicant/nm-supplicant-manager.c b/src/supplicant/nm-supplicant-manager.c
index 104aeee7..df641c51 100644
--- a/src/supplicant/nm-supplicant-manager.c
+++ b/src/supplicant/nm-supplicant-manager.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -40,7 +39,10 @@ typedef struct {
 	NMSupplicantFeature pmf_support;
 	NMSupplicantFeature fils_support;
 	NMSupplicantFeature p2p_support;
+	NMSupplicantFeature mesh_support;
 	NMSupplicantFeature wfd_support;
+	NMSupplicantFeature ft_support;
+	NMSupplicantFeature sha384_support;
 	guint             die_count_reset_id;
 	guint             die_count;
 } NMSupplicantManagerPrivate;
@@ -232,7 +234,10 @@ nm_supplicant_manager_create_interface (NMSupplicantManager *self,
 	                                     priv->pmf_support,
 	                                     priv->fils_support,
 	                                     priv->p2p_support,
-	                                     priv->wfd_support);
+	                                     priv->mesh_support,
+	                                     priv->wfd_support,
+	                                     priv->ft_support,
+	                                     priv->sha384_support);
 
 	priv->ifaces = g_slist_prepend (priv->ifaces, iface);
 	g_object_add_toggle_ref ((GObject *) iface, _sup_iface_last_ref, self);
@@ -289,7 +294,10 @@ nm_supplicant_manager_create_interface_from_path (NMSupplicantManager *self,
 	                                     priv->pmf_support,
 	                                     priv->fils_support,
 	                                     priv->p2p_support,
-	                                     priv->wfd_support);
+	                                     priv->mesh_support,
+	                                     priv->wfd_support,
+	                                     priv->ft_support,
+	                                     priv->sha384_support);
 
 	priv->ifaces = g_slist_prepend (priv->ifaces, iface);
 	g_object_add_toggle_ref ((GObject *) iface, _sup_iface_last_ref, self);
@@ -325,8 +333,11 @@ update_capabilities (NMSupplicantManager *self)
 	priv->ap_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 	priv->pmf_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 	priv->fils_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
-	/* P2P support is newer than the capabilities property */
+	/* Support for the following is newer than the capabilities property */
 	priv->p2p_support = NM_SUPPLICANT_FEATURE_NO;
+	priv->ft_support = NM_SUPPLICANT_FEATURE_NO;
+	priv->sha384_support = NM_SUPPLICANT_FEATURE_NO;
+	priv->mesh_support = NM_SUPPLICANT_FEATURE_NO;
 
 	value = g_dbus_proxy_get_cached_property (priv->proxy, "Capabilities");
 	if (value) {
@@ -336,6 +347,9 @@ update_capabilities (NMSupplicantManager *self)
 			priv->pmf_support = NM_SUPPLICANT_FEATURE_NO;
 			priv->fils_support = NM_SUPPLICANT_FEATURE_NO;
 			priv->p2p_support = NM_SUPPLICANT_FEATURE_NO;
+			priv->ft_support = NM_SUPPLICANT_FEATURE_NO;
+			priv->sha384_support = NM_SUPPLICANT_FEATURE_NO;
+			priv->mesh_support = NM_SUPPLICANT_FEATURE_NO;
 			if (array) {
 				if (g_strv_contains (array, "ap"))
 					priv->ap_support = NM_SUPPLICANT_FEATURE_YES;
@@ -345,18 +359,27 @@ update_capabilities (NMSupplicantManager *self)
 					priv->fils_support = NM_SUPPLICANT_FEATURE_YES;
 				if (g_strv_contains (array, "p2p"))
 					priv->p2p_support = NM_SUPPLICANT_FEATURE_YES;
+				if (g_strv_contains (array, "ft"))
+					priv->ft_support = NM_SUPPLICANT_FEATURE_YES;
+				if (g_strv_contains (array, "sha384"))
+					priv->sha384_support = NM_SUPPLICANT_FEATURE_YES;
+				if (g_strv_contains (array, "mesh"))
+					priv->mesh_support = NM_SUPPLICANT_FEATURE_YES;
 				g_free (array);
 			}
 		}
 		g_variant_unref (value);
 	}
 
-	/* Tell all interfaces about results of the AP/PMF/FILS/P2P check */
+	/* Tell all interfaces about results of the AP/PMF/FILS/P2P/FT/SHA384 check */
 	for (ifaces = priv->ifaces; ifaces; ifaces = ifaces->next) {
 		nm_supplicant_interface_set_ap_support (ifaces->data, priv->ap_support);
 		nm_supplicant_interface_set_pmf_support (ifaces->data, priv->pmf_support);
 		nm_supplicant_interface_set_fils_support (ifaces->data, priv->fils_support);
 		nm_supplicant_interface_set_p2p_support (ifaces->data, priv->p2p_support);
+		nm_supplicant_interface_set_ft_support (ifaces->data, priv->ft_support);
+		nm_supplicant_interface_set_sha384_support (ifaces->data, priv->sha384_support);
+		nm_supplicant_interface_set_mesh_support (ifaces->data, priv->mesh_support);
 	}
 
 	_LOGD ("AP mode is %ssupported",
@@ -371,6 +394,15 @@ update_capabilities (NMSupplicantManager *self)
 	_LOGD ("P2P is %ssupported",
 	       (priv->p2p_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
 	           (priv->p2p_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
+	_LOGD ("FT is %ssupported",
+	       (priv->ft_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
+	           (priv->ft_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
+	_LOGD ("SHA384 is %ssupported",
+	       (priv->sha384_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
+	           (priv->sha384_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
+	_LOGD ("Mesh is %ssupported",
+	       (priv->mesh_support == NM_SUPPLICANT_FEATURE_YES) ? "" :
+	           (priv->mesh_support == NM_SUPPLICANT_FEATURE_NO) ? "not " : "possibly ");
 
 	/* EAP-FAST */
 	priv->fast_support = NM_SUPPLICANT_FEATURE_NO;
@@ -509,6 +541,8 @@ name_owner_cb (GDBusProxy *proxy, GParamSpec *pspec, gpointer user_data)
 		priv->fast_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 		priv->pmf_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 		priv->fils_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
+		priv->ft_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
+		priv->sha384_support = NM_SUPPLICANT_FEATURE_UNKNOWN;
 
 		set_running (self, FALSE);
 	}
diff --git a/src/supplicant/nm-supplicant-manager.h b/src/supplicant/nm-supplicant-manager.h
index 058745fb..a1f23f53 100644
--- a/src/supplicant/nm-supplicant-manager.h
+++ b/src/supplicant/nm-supplicant-manager.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/src/supplicant/nm-supplicant-settings-verify.c b/src/supplicant/nm-supplicant-settings-verify.c
index f10bbb04..1bd71320 100644
--- a/src/supplicant/nm-supplicant-settings-verify.c
+++ b/src/supplicant/nm-supplicant-settings-verify.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -67,8 +66,8 @@ static const struct validate_entry validate_table[] = {
 const char * pairwise_allowed[] = { "CCMP", "TKIP", "NONE", NULL };
 const char * group_allowed[] =    { "CCMP", "TKIP", "WEP104", "WEP40", NULL };
 const char * proto_allowed[] =    { "WPA", "RSN", NULL };
-const char * key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256",
-                                    "WPA-EAP", "WPA-EAP-SHA256",
+const char * key_mgmt_allowed[] = { "WPA-PSK", "WPA-PSK-SHA256", "FT-PSK",
+                                    "WPA-EAP", "WPA-EAP-SHA256", "FT-EAP", "FT-EAP-SHA384",
                                     "FILS-SHA256", "FILS-SHA384",
                                     "IEEE8021X", "WPA-NONE", "SAE",
                                     "NONE", NULL };
@@ -94,7 +93,6 @@ static const struct Opt opt_table[] = {
 	{ "ssid",               TYPE_BYTES,   0, 32,FALSE,  NULL },
 	{ "bssid",              TYPE_KEYWORD, 0, 0, FALSE,  NULL },
 	{ "scan_ssid",          TYPE_INT,     0, 1, FALSE,  NULL },
-	{ "mode",               TYPE_INT,     0, 2, FALSE,  NULL },
 	{ "frequency",          TYPE_INT,     2412, 5825, FALSE,  NULL },
 	{ "auth_alg",           TYPE_KEYWORD, 0, 0, FALSE,  auth_alg_allowed },
 	{ "psk",                TYPE_BYTES,   0, 0, FALSE,  NULL },
@@ -255,6 +253,12 @@ nm_supplicant_settings_verify_setting (const char * key,
 	g_return_val_if_fail (key != NULL, FALSE);
 	g_return_val_if_fail (value != NULL, FALSE);
 
+	if (strcmp (key, "mode") == 0) {
+		if (strcmp (value, "1") && strcmp (value, "2") && strcmp (value, "5"))
+			return TYPE_INVALID;
+		return TYPE_INT;
+	}
+
 	for (i = 0; i < opt_count; i++) {
 		if (strcmp (opt_table[i].key, key) != 0)
 			continue;
diff --git a/src/supplicant/nm-supplicant-settings-verify.h b/src/supplicant/nm-supplicant-settings-verify.h
index 1eec136d..ea2482d3 100644
--- a/src/supplicant/nm-supplicant-settings-verify.h
+++ b/src/supplicant/nm-supplicant-settings-verify.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/src/supplicant/nm-supplicant-types.h b/src/supplicant/nm-supplicant-types.h
index 747cf152..b28a1efa 100644
--- a/src/supplicant/nm-supplicant-types.h
+++ b/src/supplicant/nm-supplicant-types.h
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager -- Network link manager
  *
  * This program is free software; you can redistribute it and/or modify
diff --git a/src/supplicant/tests/test-supplicant-config.c b/src/supplicant/tests/test-supplicant-config.c
index 2c7a71a3..819256fb 100644
--- a/src/supplicant/tests/test-supplicant-config.c
+++ b/src/supplicant/tests/test-supplicant-config.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager
  *
  * This program is free software; you can redistribute it and/or modify
@@ -111,7 +110,7 @@ build_supplicant_config (NMConnection *connection,
 	NMSetting8021x *s_8021x;
 	gboolean success;
 
-	config = nm_supplicant_config_new (support_pmf, support_fils);
+	config = nm_supplicant_config_new (support_pmf, support_fils, FALSE, FALSE);
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);