summary refs log tree commit diff
path: root/src/devices/wifi
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/wifi')
-rw-r--r--src/devices/wifi/meson.build30
-rw-r--r--src/devices/wifi/nm-device-iwd.c44
-rw-r--r--src/devices/wifi/nm-device-iwd.h18
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.c38
-rw-r--r--src/devices/wifi/nm-device-olpc-mesh.h25
-rw-r--r--src/devices/wifi/nm-device-wifi-p2p.c96
-rw-r--r--src/devices/wifi/nm-device-wifi-p2p.h21
-rw-r--r--src/devices/wifi/nm-device-wifi.c218
-rw-r--r--src/devices/wifi/nm-device-wifi.h18
-rw-r--r--src/devices/wifi/nm-iwd-manager.c20
-rw-r--r--src/devices/wifi/nm-iwd-manager.h18
-rw-r--r--src/devices/wifi/nm-wifi-ap.c123
-rw-r--r--src/devices/wifi/nm-wifi-ap.h19
-rw-r--r--src/devices/wifi/nm-wifi-common.c18
-rw-r--r--src/devices/wifi/nm-wifi-common.h18
-rw-r--r--src/devices/wifi/nm-wifi-factory.c18
-rw-r--r--src/devices/wifi/nm-wifi-p2p-peer.c19
-rw-r--r--src/devices/wifi/nm-wifi-p2p-peer.h19
-rw-r--r--src/devices/wifi/nm-wifi-utils.c254
-rw-r--r--src/devices/wifi/nm-wifi-utils.h18
-rw-r--r--src/devices/wifi/tests/meson.build14
-rw-r--r--src/devices/wifi/tests/test-devices-wifi.c16
22 files changed, 352 insertions, 730 deletions
diff --git a/src/devices/wifi/meson.build b/src/devices/wifi/meson.build
index 4dfbe4c8..6566f201 100644
--- a/src/devices/wifi/meson.build
+++ b/src/devices/wifi/meson.build
@@ -19,14 +19,11 @@ if enable_iwd
   )
 endif
 
-deps = [
-  nm_dep,
-]
-
 libnm_device_plugin_wifi = shared_module(
   'nm-device-plugin-wifi',
   sources: sources,
-  dependencies: deps,
+  dependencies: daemon_nm_default_dep,
+  c_args: daemon_c_flags,
   link_args: ldflags_linker_script_devices,
   link_depends: linker_script_devices,
   install: true,
@@ -41,13 +38,20 @@ test(
   args: [libnm_device_plugin_wifi.full_path(), linker_script_devices],
 )
 
-# FIXME: check_so_symbols replacement
-'''
-check-local-devices-wifi: src/devices/wifi/libnm-device-plugin-wifi.la
-  $(srcdir)/tools/check-exports.sh $(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so "$(srcdir)/linker-script-devices.ver"
-  $(call check_so_symbols,$(builddir)/src/devices/wifi/.libs/libnm-device-plugin-wifi.so)
-'''
-
 if enable_tests
-  subdir('tests')
+  test_unit = 'test-devices-wifi'
+
+  exe = executable(
+    test_unit,
+    ['tests/' + test_unit + '.c'] + common_sources,
+    dependencies: libnetwork_manager_test_dep,
+    c_args: test_c_flags,
+  )
+
+  test(
+    test_unit,
+    test_script,
+    args: test_args + [exe.full_path()],
+    timeout: default_test_timeout,
+  )
 endif
diff --git a/src/devices/wifi/nm-device-iwd.c b/src/devices/wifi/nm-device-iwd.c
index 0e6759e1..6b587e3f 100644
--- a/src/devices/wifi/nm-device-iwd.c
+++ b/src/devices/wifi/nm-device-iwd.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2017 Intel Corporation
  */
 
@@ -1714,18 +1700,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
 	NMDeviceIwd *self = NM_DEVICE_IWD (device);
 	NMDeviceIwdPrivate *priv = NM_DEVICE_IWD_GET_PRIVATE (self);
-	NMActStageReturn ret;
 	NMWifiAP *ap = NULL;
+	gs_unref_object NMWifiAP *ap_fake = NULL;
 	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingWireless *s_wireless;
 	const char *mode;
 	const char *ap_path;
 
-	ret = NM_DEVICE_CLASS (nm_device_iwd_parent_class)->act_stage1_prepare (device, out_failure_reason);
-	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
-		return ret;
-
 	req = nm_device_get_act_request (device);
 	g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
 
@@ -1741,7 +1723,9 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 		goto add_new;
 
 	ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
-	ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL;
+	ap =   ap_path
+	     ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path)
+	     : NULL;
 	if (ap) {
 		set_current_ap (self, ap, TRUE);
 		return NM_ACT_STAGE_RETURN_SUCCESS;
@@ -1767,19 +1751,19 @@ add_new:
 	 * until the real one is found in the scan list (Ad-Hoc or Hidden), or until
 	 * the device is deactivated (Ad-Hoc or Hotspot).
 	 */
-	ap = nm_wifi_ap_new_fake_from_connection (connection);
-	g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+	ap_fake = nm_wifi_ap_new_fake_from_connection (connection);
+	if (!ap_fake)
+		g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE);
 
-	if (nm_wifi_ap_is_hotspot (ap))
-		nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device));
+	if (nm_wifi_ap_is_hotspot (ap_fake))
+		nm_wifi_ap_set_address (ap_fake, nm_device_get_hw_address (device));
 
 	g_object_freeze_notify (G_OBJECT (self));
-	ap_add_remove (self, TRUE, ap, FALSE);
+	ap_add_remove (self, TRUE, ap_fake, FALSE);
 	g_object_thaw_notify (G_OBJECT (self));
-	set_current_ap (self, ap, FALSE);
+	set_current_ap (self, ap_fake, FALSE);
 	nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
-	                                          nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
-	g_object_unref (ap);
+	                                          nm_dbus_object_get_path (NM_DBUS_OBJECT (ap_fake)));
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
diff --git a/src/devices/wifi/nm-device-iwd.h b/src/devices/wifi/nm-device-iwd.h
index aab45b7b..586e02f4 100644
--- a/src/devices/wifi/nm-device-iwd.h
+++ b/src/devices/wifi/nm-device-iwd.h
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2017 Intel Corporation
  */
 
diff --git a/src/devices/wifi/nm-device-olpc-mesh.c b/src/devices/wifi/nm-device-olpc-mesh.c
index aa50c420..c19ec766 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.c
+++ b/src/devices/wifi/nm-device-olpc-mesh.c
@@ -1,26 +1,11 @@
-/* NetworkManager -- Network link manager
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Dan Williams <dcbw@redhat.com>
  * Sjoerd Simons <sjoerd.simons@collabora.co.uk>
  * Daniel Drake <dsd@laptop.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2005 - 2014 Red Hat, Inc.
- * (C) Copyright 2008 Collabora Ltd.
- * (C) Copyright 2009 One Laptop per Child
+ * Copyright (C) 2005 - 2014 Red Hat, Inc.
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2009 One Laptop per Child
  */
 
 #include "nm-default.h"
@@ -58,7 +43,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMDeviceOlpcMesh,
 typedef struct {
 	NMDevice *companion;
 	NMManager *manager;
-	gboolean  stage1_waiting;
+	bool stage1_waiting:1;
 } NMDeviceOlpcMeshPrivate;
 
 struct _NMDeviceOlpcMesh {
@@ -145,13 +130,8 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
 	NMDeviceOlpcMesh *self = NM_DEVICE_OLPC_MESH (device);
 	NMDeviceOlpcMeshPrivate *priv = NM_DEVICE_OLPC_MESH_GET_PRIVATE (self);
-	NMActStageReturn ret;
 	gboolean scanning;
 
-	ret = NM_DEVICE_CLASS (nm_device_olpc_mesh_parent_class)->act_stage1_prepare (device, out_failure_reason);
-	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
-		return ret;
-
 	/* disconnect companion device, if it is connected */
 	if (nm_device_get_act_request (NM_DEVICE (priv->companion))) {
 		_LOGI (LOGD_OLPC, "disconnecting companion device %s",
@@ -171,6 +151,7 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 		return NM_ACT_STAGE_RETURN_POSTPONE;
 	}
 
+	priv->stage1_waiting = FALSE;
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
@@ -273,10 +254,9 @@ companion_notify_cb (NMDeviceWifi *companion, GParamSpec *pspec, gpointer user_d
 		return;
 
 	g_object_get (companion, NM_DEVICE_WIFI_SCANNING, &scanning, NULL);
-
 	if (!scanning) {
 		priv->stage1_waiting = FALSE;
-		nm_device_activate_schedule_stage2_device_config (NM_DEVICE (self));
+		nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
 	}
 }
 
@@ -469,7 +449,7 @@ constructed (GObject *object)
 
 	G_OBJECT_CLASS (nm_device_olpc_mesh_parent_class)->constructed (object);
 
-	priv->manager = g_object_ref (nm_manager_get ());
+	priv->manager = g_object_ref (NM_MANAGER_GET);
 
 	g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED, G_CALLBACK (device_added_cb), self);
 	g_signal_connect (priv->manager, NM_MANAGER_DEVICE_REMOVED, G_CALLBACK (device_removed_cb), self);
diff --git a/src/devices/wifi/nm-device-olpc-mesh.h b/src/devices/wifi/nm-device-olpc-mesh.h
index 619fc46a..e6e76d6f 100644
--- a/src/devices/wifi/nm-device-olpc-mesh.h
+++ b/src/devices/wifi/nm-device-olpc-mesh.h
@@ -1,26 +1,11 @@
-/* NetworkManager -- Network link manager
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Dan Williams <dcbw@redhat.com>
  * Sjoerd Simons <sjoerd.simons@collabora.co.uk>
  * Daniel Drake <dsd@laptop.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2005 Red Hat, Inc.
- * (C) Copyright 2008 Collabora Ltd.
- * (C) Copyright 2009 One Laptop per Child
+ * Copyright (C) 2005 Red Hat, Inc.
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2009 One Laptop per Child
  */
 
 #ifndef __NETWORKMANAGER_DEVICE_OLPC_MESH_H__
diff --git a/src/devices/wifi/nm-device-wifi-p2p.c b/src/devices/wifi/nm-device-wifi-p2p.c
index 649f36d0..34ff70fa 100644
--- a/src/devices/wifi/nm-device-wifi-p2p.c
+++ b/src/devices/wifi/nm-device-wifi-p2p.c
@@ -1,21 +1,6 @@
-/* NetworkManager -- Wi-Fi P2P Device
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * Copyright (C) 2018 Red Hat, Inc.
  */
 
 #include "nm-default.h"
@@ -63,6 +48,7 @@ typedef struct {
 
 	CList peers_lst_head;
 
+	guint find_peer_timeout_id;
 	guint sup_timeout_id;
 	guint peer_dump_id;
 	guint peer_missing_id;
@@ -349,7 +335,7 @@ supplicant_find_timeout_cb (gpointer user_data)
 	NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (user_data);
 	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
 
-	priv->sup_timeout_id = 0;
+	priv->find_peer_timeout_id = 0;
 
 	nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface);
 
@@ -368,27 +354,16 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
 	NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (device);
 	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
-	NMActStageReturn ret;
-	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingWifiP2P *s_wifi_p2p;
 	NMWifiP2PPeer *peer;
 
-	nm_clear_g_source (&priv->sup_timeout_id);
-
-	ret = NM_DEVICE_CLASS (nm_device_wifi_p2p_parent_class)->act_stage1_prepare (device, out_failure_reason);
-	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
-		return ret;
-
 	if (!priv->mgmt_iface) {
 		NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
 		return NM_ACT_STAGE_RETURN_FAILURE;
 	}
 
-	req = nm_device_get_act_request (NM_DEVICE (self));
-	g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
-
-	connection = nm_act_request_get_applied_connection (req);
+	connection = nm_device_get_applied_connection (NM_DEVICE (self));
 	g_return_val_if_fail (connection, NM_ACT_STAGE_RETURN_FAILURE);
 
 	s_wifi_p2p = NM_SETTING_WIFI_P2P (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIFI_P2P));
@@ -397,33 +372,19 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 	peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection);
 	if (!peer) {
 		/* Set up a timeout on the find attempt and run a find for the same period of time */
-		priv->sup_timeout_id = g_timeout_add_seconds (10,
-		                                              supplicant_find_timeout_cb,
-		                                              self);
-
-		nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10);
+		if (priv->find_peer_timeout_id == 0) {
+			priv->find_peer_timeout_id = g_timeout_add_seconds (10,
+			                                                    supplicant_find_timeout_cb,
+			                                                    self);
 
+			nm_supplicant_interface_p2p_start_find (priv->mgmt_iface, 10);
+		}
 		return NM_ACT_STAGE_RETURN_POSTPONE;
 	}
 
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
-static void
-cleanup_p2p_connect_attempt (NMDeviceWifiP2P *self, gboolean disconnect)
-{
-	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
-
-	nm_clear_g_source (&priv->sup_timeout_id);
-	nm_clear_g_source (&priv->peer_missing_id);
-
-	if (priv->mgmt_iface)
-		nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface);
-
-	if (disconnect && priv->group_iface)
-		nm_supplicant_interface_p2p_disconnect (priv->group_iface);
-}
-
 /*
  * supplicant_connection_timeout_cb
  *
@@ -461,7 +422,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 	NMWifiP2PPeer *peer;
 	GBytes *wfd_ies;
 
-	nm_clear_g_source (&priv->sup_timeout_id);
+	if (nm_clear_g_source (&priv->find_peer_timeout_id))
+		nm_assert_not_reached ();
 
 	if (!priv->mgmt_iface) {
 		NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_FAILED);
@@ -493,9 +455,11 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 	                                     "pbc", NULL);
 
 	/* Set up a timeout on the connect attempt */
-	priv->sup_timeout_id = g_timeout_add_seconds (45,
-	                                              supplicant_connection_timeout_cb,
-	                                              self);
+	if (priv->sup_timeout_id == 0) {
+		priv->sup_timeout_id = g_timeout_add_seconds (45,
+		                                              supplicant_connection_timeout_cb,
+		                                              self);
+	}
 
 	/* We'll get stage3 started when the P2P group has been started */
 	return NM_ACT_STAGE_RETURN_POSTPONE;
@@ -550,17 +514,19 @@ peer_add_remove (NMDeviceWifiP2P *self,
 	if (is_adding) {
 		/* If we are in prepare state, then we are currently runnign a find
 		 * to search for the requested peer. */
-		if (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE) {
+		if (priv->find_peer_timeout_id != 0) {
 			NMConnection *connection;
 
+			nm_assert (nm_device_get_state (device) == NM_DEVICE_STATE_PREPARE);
+
 			connection = nm_device_get_applied_connection (device);
-			g_assert (connection);
+			nm_assert (NM_IS_CONNECTION (connection));
 
 			peer = nm_wifi_p2p_peers_find_first_compatible (&priv->peers_lst_head, connection);
 			if (peer) {
 				/* A peer for the connection was found, cancel the timeout and go to configure state. */
-				nm_clear_g_source (&priv->sup_timeout_id);
-				nm_device_activate_schedule_stage2_device_config (device);
+				nm_clear_g_source (&priv->find_peer_timeout_id);
+				nm_device_activate_schedule_stage1_device_prepare (device);
 			}
 		}
 
@@ -620,8 +586,17 @@ deactivate (NMDevice *device)
 {
 	NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (device);
 	int ifindex = nm_device_get_ip_ifindex (device);
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
+
+	nm_clear_g_source (&priv->find_peer_timeout_id);
+	nm_clear_g_source (&priv->sup_timeout_id);
+	nm_clear_g_source (&priv->peer_missing_id);
 
-	cleanup_p2p_connect_attempt (self, TRUE);
+	if (priv->mgmt_iface)
+		nm_supplicant_interface_p2p_cancel_connect (priv->mgmt_iface);
+
+	if (priv->group_iface)
+		nm_supplicant_interface_p2p_disconnect (priv->group_iface);
 
 	/* Clear any critical protocol notification in the Wi-Fi stack */
 	if (ifindex > 0)
@@ -922,6 +897,7 @@ supplicant_interfaces_release (NMDeviceWifiP2P *self, gboolean set_is_waiting)
 		nm_supplicant_manager_set_wfd_ies (priv->sup_mgr, NULL);
 		g_signal_handlers_disconnect_by_data (priv->mgmt_iface, self);
 		g_clear_object (&priv->mgmt_iface);
+		nm_clear_g_source (&priv->find_peer_timeout_id);
 		nm_clear_g_source (&priv->sup_timeout_id);
 	}
 
diff --git a/src/devices/wifi/nm-device-wifi-p2p.h b/src/devices/wifi/nm-device-wifi-p2p.h
index a13eef15..df25ec65 100644
--- a/src/devices/wifi/nm-device-wifi-p2p.h
+++ b/src/devices/wifi/nm-device-wifi-p2p.h
@@ -1,21 +1,6 @@
-/* NetworkManager -- Wi-Fi P2P Device
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
+// SPDX-License-Identifier: LGPL-2.1+
+/*
+ * Copyright (C) 2018 Red Hat, Inc.
  */
 
 #ifndef __NM_DEVICE_WIFI_P2P_H__
diff --git a/src/devices/wifi/nm-device-wifi.c b/src/devices/wifi/nm-device-wifi.c
index f690100b..65ba2bcc 100644
--- a/src/devices/wifi/nm-device-wifi.c
+++ b/src/devices/wifi/nm-device-wifi.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2005 - 2017 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
@@ -411,7 +397,9 @@ set_current_ap (NMDeviceWifi *self, NMWifiAP *new_ap, gboolean recheck_available
 		NM80211Mode mode = nm_wifi_ap_get_mode (old_ap);
 
 		/* Remove any AP from the internal list if it was created by NM or isn't known to the supplicant */
-		if (mode == NM_802_11_MODE_ADHOC || mode == NM_802_11_MODE_AP || nm_wifi_ap_get_fake (old_ap))
+		if (   NM_IN_SET (mode, NM_802_11_MODE_ADHOC,
+		                        NM_802_11_MODE_AP)
+		    || nm_wifi_ap_get_fake (old_ap))
 			ap_add_remove (self, FALSE, old_ap, recheck_available_connections);
 		g_object_unref (old_ap);
 	}
@@ -645,36 +633,6 @@ deactivate_reset_hw_addr (NMDevice *device)
 }
 
 static gboolean
-is_adhoc_wpa (NMConnection *connection)
-{
-	NMSettingWireless *s_wifi;
-	NMSettingWirelessSecurity *s_wsec;
-	const char *mode, *key_mgmt;
-
-	/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
-	 * and turns them into open networks.  It's been this way since at least
-	 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
-	 */
-
-	s_wifi = nm_connection_get_setting_wireless (connection);
-	g_return_val_if_fail (s_wifi != NULL, FALSE);
-
-	mode = nm_setting_wireless_get_mode (s_wifi);
-	if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) != 0)
-		return FALSE;
-
-	s_wsec = nm_connection_get_setting_wireless_security (connection);
-	if (!s_wsec)
-		return FALSE;
-
-	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
-	if (g_strcmp0 (key_mgmt, "wpa-none") != 0)
-		return FALSE;
-
-	return TRUE;
-}
-
-static gboolean
 check_connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
@@ -720,12 +678,6 @@ check_connection_compatible (NMDevice *device, NMConnection *connection, GError
 		return FALSE;
 	}
 
-	if (is_adhoc_wpa (connection)) {
-		nm_utils_error_set_literal (error, NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-		                            "Ad-Hoc WPA networks are not supported");
-		return FALSE;
-	}
-
 	/* Early exit if supplicant or device doesn't support requested mode */
 	mode = nm_setting_wireless_get_mode (s_wireless);
 	if (g_strcmp0 (mode, NM_SETTING_WIRELESS_MODE_ADHOC) == 0) {
@@ -953,19 +905,6 @@ complete_connection (NMDevice *device,
 			return FALSE;
 	}
 
-	/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
-	 * and turns them into open networks.  It's been this way since at least
-	 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
-	 */
-	if (is_adhoc_wpa (connection)) {
-		g_set_error_literal (error,
-		                     NM_CONNECTION_ERROR,
-		                     NM_CONNECTION_ERROR_INVALID_SETTING,
-		                     _("WPA Ad-Hoc disabled due to kernel bugs"));
-		g_prefix_error (error, "%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
-		return FALSE;
-	}
-
 	ssid_utf8 = _nm_utils_ssid_to_utf8 (ssid);
 	nm_utils_complete_generic (nm_device_get_platform (device),
 	                           connection,
@@ -1278,7 +1217,8 @@ scanning_prohibited (NMDeviceWifi *self, gboolean periodic)
 	/* Don't scan when a an AP or Ad-Hoc connection is active as it will
 	 * disrupt connected clients or peers.
 	 */
-	if (priv->mode == NM_802_11_MODE_ADHOC || priv->mode == NM_802_11_MODE_AP)
+	if (NM_IN_SET (priv->mode, NM_802_11_MODE_ADHOC,
+	                           NM_802_11_MODE_AP))
 		return TRUE;
 
 	switch (nm_device_get_state (NM_DEVICE (self))) {
@@ -1781,8 +1721,10 @@ wifi_secrets_cb (NMActRequest *req,
 		nm_device_state_changed (device,
 		                         NM_DEVICE_STATE_FAILED,
 		                         NM_DEVICE_STATE_REASON_NO_SECRETS);
-	} else
-		nm_device_activate_schedule_stage1_device_prepare (device);
+		return;
+	}
+
+	nm_device_activate_schedule_stage1_device_prepare (device);
 }
 
 static void
@@ -1801,10 +1743,11 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface,
                                      NMDeviceWifi *self)
 {
 	NMActRequest *req;
-	GVariant *val, *secrets = NULL;
+	gs_unref_variant GVariant *val_key = NULL;
+	gs_unref_variant GVariant *secrets = NULL;
+	gs_free_error GError *error = NULL;
 	const char *array;
 	gsize psk_len = 0;
-	GError *error = NULL;
 
 	if (nm_device_get_state (NM_DEVICE (self)) != NM_DEVICE_STATE_NEED_AUTH) {
 		_LOGI (LOGD_DEVICE | LOGD_WIFI, "WPS: The connection can't be updated with credentials");
@@ -1816,11 +1759,11 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface,
 	req = nm_device_get_act_request (NM_DEVICE (self));
 	g_return_if_fail (NM_IS_ACT_REQUEST (req));
 
-	val = g_variant_lookup_value (credentials, "Key", G_VARIANT_TYPE_BYTESTRING);
-	if (val) {
+	val_key = g_variant_lookup_value (credentials, "Key", G_VARIANT_TYPE_BYTESTRING);
+	if (val_key) {
 		char psk[64];
 
-		array = g_variant_get_fixed_array (val, &psk_len, 1);
+		array = g_variant_get_fixed_array (val_key, &psk_len, 1);
 		if (psk_len >= 8 && psk_len <= 63) {
 			memcpy (psk, array, psk_len);
 			psk[psk_len] = '\0';
@@ -1833,22 +1776,22 @@ supplicant_iface_wps_credentials_cb (NMSupplicantInterface *iface,
 		}
 		if (!secrets)
 			_LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: ignore invalid PSK");
-		g_variant_unref (val);
-	}
-	if (secrets) {
-		if (nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req),
-		                                        nm_act_request_get_applied_connection (req),
-		                                        NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-		                                        secrets,
-		                                        &error)) {
-			wifi_secrets_cancel (self);
-			nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
-		} else {
-			_LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Could not update the connection with credentials: %s", error->message);
-			g_error_free (error);
-		}
-		g_variant_unref (secrets);
 	}
+
+	if (!secrets)
+		return;
+
+	if (!nm_settings_connection_new_secrets (nm_act_request_get_settings_connection (req),
+	                                         nm_act_request_get_applied_connection (req),
+	                                         NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+	                                         secrets,
+	                                         &error)) {
+		_LOGW (LOGD_DEVICE | LOGD_WIFI, "WPS: Could not update the connection with credentials: %s", error->message);
+		return;
+	}
+
+	wifi_secrets_cancel (self);
+	nm_device_activate_schedule_stage1_device_prepare (NM_DEVICE (self));
 }
 
 static gboolean
@@ -2458,9 +2401,9 @@ supplicant_connection_timeout_cb (gpointer user_data)
 	connection = nm_act_request_get_applied_connection (req);
 	g_assert (connection);
 
-	if (   priv->mode == NM_802_11_MODE_ADHOC
-	    || priv->mode == NM_802_11_MODE_MESH
-	    || priv->mode == NM_802_11_MODE_AP) {
+	if (NM_IN_SET (priv->mode, NM_802_11_MODE_ADHOC,
+	                           NM_802_11_MODE_MESH,
+	                           NM_802_11_MODE_AP)) {
 		/* In Ad-Hoc and AP modes there's nothing to check the encryption key
 		 * (if any), so supplicant timeouts here are almost certainly the wifi
 		 * driver being really stupid.
@@ -2666,18 +2609,14 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
 	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
-	NMActStageReturn ret;
 	NMWifiAP *ap = NULL;
+	gs_unref_object NMWifiAP *ap_fake = NULL;
 	NMActRequest *req;
 	NMConnection *connection;
 	NMSettingWireless *s_wireless;
 	const char *mode;
 	const char *ap_path;
 
-	ret = NM_DEVICE_CLASS (nm_device_wifi_parent_class)->act_stage1_prepare (device, out_failure_reason);
-	if (ret != NM_ACT_STAGE_RETURN_SUCCESS)
-		return ret;
-
 	req = nm_device_get_act_request (NM_DEVICE (self));
 	g_return_val_if_fail (req, NM_ACT_STAGE_RETURN_FAILURE);
 
@@ -2703,62 +2642,49 @@ act_stage1_prepare (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 		priv->mode = NM_802_11_MODE_MESH;
 	_notify (self, PROP_MODE);
 
-	/* The kernel doesn't support Ad-Hoc WPA connections well at this time,
-	 * and turns them into open networks.  It's been this way since at least
-	 * 2.6.30 or so; until that's fixed, disable WPA-protected Ad-Hoc networks.
-	 */
-	if (is_adhoc_wpa (connection)) {
-		_LOGW (LOGD_WIFI, "Ad-Hoc WPA disabled due to kernel bugs");
-		NM_SET_OUT (out_failure_reason, NM_DEVICE_STATE_REASON_SUPPLICANT_CONFIG_FAILED);
-		return NM_ACT_STAGE_RETURN_FAILURE;
-	}
-
 	/* expire the temporary MAC address used during scanning */
 	priv->hw_addr_scan_expire = 0;
 
 	/* Set spoof MAC to the interface */
-	if (!nm_device_hw_addr_set_cloned (device, connection, TRUE))
+	if (!nm_device_hw_addr_set_cloned (device, connection, TRUE)) {
+		*out_failure_reason = NM_DEVICE_STATE_REASON_CONFIG_FAILED;
 		return NM_ACT_STAGE_RETURN_FAILURE;
+	}
 
 	/* AP and Mesh modes never use a specific object or existing scanned AP */
-	if (priv->mode != NM_802_11_MODE_AP && priv->mode != NM_802_11_MODE_MESH) {
+	if (!NM_IN_SET (priv->mode, NM_802_11_MODE_AP,
+	                            NM_802_11_MODE_MESH)) {
 		ap_path = nm_active_connection_get_specific_object (NM_ACTIVE_CONNECTION (req));
-		ap = ap_path ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path) : NULL;
-		if (ap)
-			goto done;
-
-		ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
+		ap =   ap_path
+		     ? nm_wifi_ap_lookup_for_device (NM_DEVICE (self), ap_path)
+		     : NULL;
 	}
+	if (!ap)
+		ap = nm_wifi_aps_find_first_compatible (&priv->aps_lst_head, connection);
 
-	if (ap) {
-		nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
-		                                          nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
-		goto done;
-	}
+	if (!ap) {
+		/* If the user is trying to connect to an AP that NM doesn't yet know about
+		 * (hidden network or something), starting a Hotspot or joining a Mesh,
+		 * create a fake APfrom the security settings in the connection.  This "fake"
+		 * AP gets used until the real one is found in the scan list (Ad-Hoc or Hidden),
+		 * or until the device is deactivated (Hotspot).
+		 */
+		ap_fake = nm_wifi_ap_new_fake_from_connection (connection);
+		if (!ap_fake)
+			g_return_val_if_reached (NM_ACT_STAGE_RETURN_FAILURE);
 
-	/* If the user is trying to connect to an AP that NM doesn't yet know about
-	 * (hidden network or something), starting a Hotspot or joining a Mesh,
-	 * create a fake APfrom the security settings in the connection.  This "fake"
-	 * AP gets used until the real one is found in the scan list (Ad-Hoc or Hidden),
-	 * or until the device is deactivated (Hotspot).
-	 */
-	ap = nm_wifi_ap_new_fake_from_connection (connection);
-	g_return_val_if_fail (ap != NULL, NM_ACT_STAGE_RETURN_FAILURE);
+		if (nm_wifi_ap_is_hotspot (ap_fake))
+			nm_wifi_ap_set_address (ap_fake, nm_device_get_hw_address (device));
 
-	if (nm_wifi_ap_is_hotspot (ap))
-		nm_wifi_ap_set_address (ap, nm_device_get_hw_address (device));
+		g_object_freeze_notify (G_OBJECT (self));
+		ap_add_remove (self, TRUE, ap_fake, TRUE);
+		g_object_thaw_notify (G_OBJECT (self));
+		ap = ap_fake;
+	}
 
-	g_object_freeze_notify (G_OBJECT (self));
-	ap_add_remove (self, TRUE, ap, TRUE);
-	g_object_thaw_notify (G_OBJECT (self));
 	set_current_ap (self, ap, FALSE);
 	nm_active_connection_set_specific_object (NM_ACTIVE_CONNECTION (req),
 	                                          nm_dbus_object_get_path (NM_DBUS_OBJECT (ap)));
-	g_object_unref (ap);
-	return NM_ACT_STAGE_RETURN_SUCCESS;
-
-done:
-	set_current_ap (self, ap, TRUE);
 	return NM_ACT_STAGE_RETURN_SUCCESS;
 }
 
@@ -2893,8 +2819,8 @@ act_stage2_config (NMDevice *device, NMDeviceStateReason *out_failure_reason)
 	 * if the user didn't specify one and we didn't find an AP that matched
 	 * the connection, just pick a frequency the device supports.
 	 */
-	if (   ap_mode == NM_802_11_MODE_ADHOC
-	    || ap_mode == NM_802_11_MODE_MESH
+	if (   NM_IN_SET (ap_mode, NM_802_11_MODE_ADHOC,
+	                           NM_802_11_MODE_MESH)
 	    || nm_wifi_ap_is_hotspot (ap))
 		ensure_hotspot_frequency (self, s_wireless, ap);
 
@@ -3242,6 +3168,15 @@ set_enabled (NMDevice *device, gboolean enabled)
 }
 
 static gboolean
+get_guessed_metered (NMDevice *device)
+{
+	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (self);
+
+	return priv->current_ap && nm_wifi_ap_get_metered (priv->current_ap);
+}
+
+static gboolean
 can_reapply_change (NMDevice *device,
                     const char *setting_name,
                     NMSetting *s_old,
@@ -3274,6 +3209,7 @@ static void
 reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_new)
 {
 	NMDeviceWifi *self = NM_DEVICE_WIFI (device);
+	NMDeviceState state = nm_device_get_state (device);
 
 	NM_DEVICE_CLASS (nm_device_wifi_parent_class)->reapply_connection (device,
 	                                                                   con_old,
@@ -3281,7 +3217,8 @@ reapply_connection (NMDevice *device, NMConnection *con_old, NMConnection *con_n
 
 	_LOGD (LOGD_DEVICE, "reapplying wireless settings");
 
-	if (!wake_on_wlan_enable (self))
+	if (   state >= NM_DEVICE_STATE_CONFIG
+	    && !wake_on_wlan_enable (self))
 		_LOGW (LOGD_DEVICE | LOGD_WIFI, "Cannot configure WoWLAN.");
 }
 
@@ -3451,6 +3388,7 @@ nm_device_wifi_class_init (NMDeviceWifiClass *klass)
 	device_class->check_connection_available = check_connection_available;
 	device_class->complete_connection = complete_connection;
 	device_class->get_enabled = get_enabled;
+	device_class->get_guessed_metered = get_guessed_metered;
 	device_class->set_enabled = set_enabled;
 
 	device_class->act_stage1_prepare = act_stage1_prepare;
diff --git a/src/devices/wifi/nm-device-wifi.h b/src/devices/wifi/nm-device-wifi.h
index 82f62be6..aaf47143 100644
--- a/src/devices/wifi/nm-device-wifi.h
+++ b/src/devices/wifi/nm-device-wifi.h
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2005 - 2016 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index c79f6cc6..470cb1c9 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2017 Intel Corporation
  */
 
@@ -912,7 +898,7 @@ nm_iwd_manager_init (NMIwdManager *self)
 {
 	NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE (self);
 
-	priv->manager = g_object_ref (nm_manager_get ());
+	priv->manager = g_object_ref (NM_MANAGER_GET);
 	g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED,
 	                  G_CALLBACK (device_added), self);
 
diff --git a/src/devices/wifi/nm-iwd-manager.h b/src/devices/wifi/nm-iwd-manager.h
index b410e4ce..c50963fe 100644
--- a/src/devices/wifi/nm-iwd-manager.h
+++ b/src/devices/wifi/nm-iwd-manager.h
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2017 Intel Corporation
  */
 
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index c7ab7f04..ee7dc236 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2004 - 2017 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
@@ -67,10 +53,12 @@ struct _NMWifiAPPrivate {
 	NM80211ApSecurityFlags wpa_flags;  /* WPA-related flags */
 	NM80211ApSecurityFlags rsn_flags;  /* RSN (WPA2) -related flags */
 
+	bool               metered:1;
+
 	/* Non-scanned attributes */
-	bool                fake:1;       /* Whether or not the AP is from a scan */
-	bool                hotspot:1;    /* Whether the AP is a local device's hotspot network */
-	gint32              last_seen;    /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
+	bool               fake:1;       /* Whether or not the AP is from a scan */
+	bool               hotspot:1;    /* Whether the AP is a local device's hotspot network */
+	gint32             last_seen;    /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
 };
 
 typedef struct _NMWifiAPPrivate NMWifiAPPrivate;
@@ -406,6 +394,12 @@ nm_wifi_ap_set_last_seen (NMWifiAP *ap, gint32 last_seen)
 	return FALSE;
 }
 
+gboolean
+nm_wifi_ap_get_metered (const NMWifiAP *self)
+{
+	return NM_WIFI_AP_GET_PRIVATE (self)->metered;
+}
+
 /*****************************************************************************/
 
 static NM80211ApSecurityFlags
@@ -731,44 +725,50 @@ get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate)
 /* Management Frame Information Element IDs, ieee80211_eid */
 #define WLAN_EID_HT_CAPABILITY       45
 #define WLAN_EID_VHT_CAPABILITY     191
+#define WLAN_EID_VENDOR_SPECIFIC    221
 
-static guint32
-get_max_rate (const guint8 *bytes, gsize len)
+static void
+parse_ies (const guint8 *bytes, gsize len, guint32 *out_max_rate, gboolean *out_metered)
 {
 	guint8 id, elem_len;
-	guint32 max_rate = 0;
+	guint32 m;
 
-	while (len) {
-		guint32 m;
+	*out_max_rate = 0;
+	*out_metered = FALSE;
 
+	while (len) {
 		if (len < 2)
-			return 0;
+			break;
 
 		id = *bytes++;
 		elem_len = *bytes++;
 		len -= 2;
 
 		if (elem_len > len)
-			return 0;
+			break;
 
 		switch (id) {
 		case WLAN_EID_HT_CAPABILITY:
-			if (!get_max_rate_ht (bytes, elem_len, &m))
-				return 0;
-			max_rate = NM_MAX (max_rate, m);
+			if (get_max_rate_ht (bytes, elem_len, &m))
+				*out_max_rate = NM_MAX (*out_max_rate, m);
 			break;
 		case WLAN_EID_VHT_CAPABILITY:
-			if (!get_max_rate_vht (bytes, elem_len, &m))
-				return 0;
-			max_rate = NM_MAX (max_rate, m);
+			if (get_max_rate_vht (bytes, elem_len, &m))
+				*out_max_rate = NM_MAX (*out_max_rate, m);
+			break;
+		case WLAN_EID_VENDOR_SPECIFIC:
+			if (   len == 8
+			    && bytes[0] == 0x00            /* OUI: Microsoft */
+			    && bytes[1] == 0x50
+			    && bytes[2] == 0xf2
+			    && bytes[3] == 0x11)           /* OUI type: Network cost */
+				*out_metered = (bytes[7] > 1); /* Cost level > 1 */
 			break;
 		}
 
 		len -= elem_len;
 		bytes += elem_len;
 	}
-
-	return max_rate;
 }
 
 /*****************************************************************************/
@@ -788,7 +788,8 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
 	gint16 i16;
 	guint16 u16;
 	gboolean changed = FALSE;
-	guint32 max_rate;
+	gboolean metered;
+	guint32 max_rate, rate;
 
 	g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
 	g_return_val_if_fail (properties, FALSE);
@@ -869,9 +870,12 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
 	v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING);
 	if (v) {
 		bytes = g_variant_get_fixed_array (v, &len, 1);
-		max_rate = NM_MAX (max_rate, get_max_rate (bytes, len));
+		parse_ies (bytes, len, &rate, &metered);
+		max_rate = NM_MAX (max_rate, rate);
 		g_variant_unref (v);
+		priv->metered = metered;
 	}
+
 	if (max_rate)
 		changed |= nm_wifi_ap_set_max_bitrate (ap, max_rate / 1000);
 
@@ -1002,7 +1006,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
 		export_path = "/";
 
 	g_snprintf (str_buf, buf_len,
-	            "%17s %-35s [ %c %3u %3u%% %c W:%04X R:%04X ] %3us sup:%s [nm:%s]",
+	            "%17s %-35s [ %c %3u %3u%% %c%c W:%04X R:%04X ] %3us sup:%s [nm:%s]",
 	            priv->address ?: "(none)",
 	            (ssid_to_free = _nm_utils_ssid_to_string (priv->ssid)),
 	            (priv->mode == NM_802_11_MODE_ADHOC
@@ -1017,6 +1021,7 @@ nm_wifi_ap_to_string (const NMWifiAP *self,
 	            chan,
 	            priv->strength,
 	            priv->flags & NM_802_11_AP_FLAGS_PRIVACY ? 'P' : '_',
+	            priv->metered ? 'M' : '_',
 	            priv->wpa_flags & 0xFFFF,
 	            priv->rsn_flags & 0xFFFF,
 	            priv->last_seen > 0 ? ((now_s > 0 ? now_s : nm_utils_get_monotonic_timestamp_s ()) - priv->last_seen) : -1,
@@ -1232,7 +1237,7 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection)
 	const char *mode, *band, *key_mgmt;
 	guint32 channel;
 	NM80211ApSecurityFlags flags;
-	gboolean psk = FALSE, eap = FALSE;
+	gboolean psk = FALSE, eap = FALSE, adhoc = FALSE;
 
 	g_return_val_if_fail (connection != NULL, NULL);
 
@@ -1252,9 +1257,10 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection)
 	if (mode) {
 		if (!strcmp (mode, "infrastructure"))
 			nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA);
-		else if (!strcmp (mode, "adhoc"))
+		else if (!strcmp (mode, "adhoc")) {
 			nm_wifi_ap_set_mode (ap, NM_802_11_MODE_ADHOC);
-		else if (!strcmp (mode, "mesh"))
+			adhoc = TRUE;
+		} else if (!strcmp (mode, "mesh"))
 			nm_wifi_ap_set_mode (ap, NM_802_11_MODE_MESH);
 		else if (!strcmp (mode, "ap")) {
 			nm_wifi_ap_set_mode (ap, NM_802_11_MODE_INFRA);
@@ -1293,7 +1299,7 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection)
 
 	psk = !strcmp (key_mgmt, "wpa-psk");
 	eap = !strcmp (key_mgmt, "wpa-eap");
-	if (psk || eap) {
+	if (!adhoc && (psk || eap)) {
 		if (has_proto (s_wireless_sec, PROTO_WPA)) {
 			flags = priv->wpa_flags | (eap ? NM_802_11_AP_SEC_KEY_MGMT_802_1X : NM_802_11_AP_SEC_KEY_MGMT_PSK);
 			nm_wifi_ap_set_wpa_flags (ap, flags);
@@ -1305,42 +1311,27 @@ nm_wifi_ap_new_fake_from_connection (NMConnection *connection)
 
 		add_pair_ciphers (ap, s_wireless_sec);
 		add_group_ciphers (ap, s_wireless_sec);
-	} else if (!strcmp (key_mgmt, "wpa-none")) {
-		guint32 i;
-
-		/* Ad-Hoc has special requirements: proto=WPA, pairwise=(none), and
-		 * group=TKIP/CCMP (but not both).
+	} else if (adhoc && psk) {
+		/* Ad-Hoc has special requirements: proto=RSN, pairwise=CCMP and
+		 * group=CCMP.
 		 */
-
 		flags = priv->wpa_flags | NM_802_11_AP_SEC_KEY_MGMT_PSK;
 
-		/* Clear ciphers; pairwise must be unset anyway, and group gets set below */
+		/* Clear ciphers; only CCMP is supported */
 		flags &= ~(  NM_802_11_AP_SEC_PAIR_WEP40
 		           | NM_802_11_AP_SEC_PAIR_WEP104
 		           | NM_802_11_AP_SEC_PAIR_TKIP
-		           | NM_802_11_AP_SEC_PAIR_CCMP
 		           | NM_802_11_AP_SEC_GROUP_WEP40
 		           | NM_802_11_AP_SEC_GROUP_WEP104
-		           | NM_802_11_AP_SEC_GROUP_TKIP
-		           | NM_802_11_AP_SEC_GROUP_CCMP);
+		           | NM_802_11_AP_SEC_GROUP_TKIP);
 
-		for (i = 0; i < nm_setting_wireless_security_get_num_groups (s_wireless_sec); i++) {
-			if (!strcmp (nm_setting_wireless_security_get_group (s_wireless_sec, i), "ccmp")) {
-				flags |= NM_802_11_AP_SEC_GROUP_CCMP;
-				break;
-			}
-		}
-
-		/* Default to TKIP since not all WPA-capable cards can do CCMP */
-		if (!(flags & NM_802_11_AP_SEC_GROUP_CCMP))
-			flags |= NM_802_11_AP_SEC_GROUP_TKIP;
+		flags |= NM_802_11_AP_SEC_PAIR_CCMP;
+		flags |= NM_802_11_AP_SEC_GROUP_CCMP;
+		nm_wifi_ap_set_rsn_flags (ap, flags);
 
-		nm_wifi_ap_set_wpa_flags (ap, flags);
-
-		/* Don't use Ad-Hoc RSN yet */
-		nm_wifi_ap_set_rsn_flags (ap, NM_802_11_AP_SEC_NONE);
+		/* Don't use Ad-Hoc WPA (WPA-none) anymore */
+		nm_wifi_ap_set_wpa_flags (ap, NM_802_11_AP_SEC_NONE);
 	}
-
 done:
 	return ap;
 
diff --git a/src/devices/wifi/nm-wifi-ap.h b/src/devices/wifi/nm-wifi-ap.h
index 755e722c..472dfdf9 100644
--- a/src/devices/wifi/nm-wifi-ap.h
+++ b/src/devices/wifi/nm-wifi-ap.h
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2004 - 2017 Red Hat, Inc.
  * Copyright (C) 2006 - 2008 Novell, Inc.
  */
@@ -95,6 +81,7 @@ gboolean          nm_wifi_ap_get_fake                 (const NMWifiAP *ap);
 gboolean          nm_wifi_ap_set_fake                 (NMWifiAP *ap,
                                                        gboolean fake);
 NM80211ApFlags    nm_wifi_ap_get_flags                (const NMWifiAP *self);
+gboolean          nm_wifi_ap_get_metered              (const NMWifiAP *self);
 
 const char       *nm_wifi_ap_to_string                (const NMWifiAP *self,
                                                        char *str_buf,
diff --git a/src/devices/wifi/nm-wifi-common.c b/src/devices/wifi/nm-wifi-common.c
index 96828d59..087465b5 100644
--- a/src/devices/wifi/nm-wifi-common.c
+++ b/src/devices/wifi/nm-wifi-common.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: LGPL-2.1+
 /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
+ * Copyright (C) 2018 Red Hat, Inc.
  */
 
 #include "nm-default.h"
diff --git a/src/devices/wifi/nm-wifi-common.h b/src/devices/wifi/nm-wifi-common.h
index 81d657ec..829df826 100644
--- a/src/devices/wifi/nm-wifi-common.h
+++ b/src/devices/wifi/nm-wifi-common.h
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: LGPL-2.1+
 /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2018 Red Hat, Inc.
+ * Copyright (C) 2018 Red Hat, Inc.
  */
 
 #ifndef __NM_WIFI_COMMON_H__
diff --git a/src/devices/wifi/nm-wifi-factory.c b/src/devices/wifi/nm-wifi-factory.c
index 2f069882..821460a5 100644
--- a/src/devices/wifi/nm-wifi-factory.c
+++ b/src/devices/wifi/nm-wifi-factory.c
@@ -1,19 +1,5 @@
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: GPL-2.0+
+/*
  * Copyright (C) 2011 - 2014 Red Hat, Inc.
  */
 
diff --git a/src/devices/wifi/nm-wifi-p2p-peer.c b/src/devices/wifi/nm-wifi-p2p-peer.c
index 4b524623..f8da0046 100644
--- a/src/devices/wifi/nm-wifi-p2p-peer.c
+++ b/src/devices/wifi/nm-wifi-p2p-peer.c
@@ -1,20 +1,5 @@
-/* NetworkManager -- Wi-Fi P2P Peer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: LGPL-2.1+
+/*
  * Copyright (C) 2018 Red Hat, Inc.
  */
 
diff --git a/src/devices/wifi/nm-wifi-p2p-peer.h b/src/devices/wifi/nm-wifi-p2p-peer.h
index d6ff7abc..07f25cc1 100644
--- a/src/devices/wifi/nm-wifi-p2p-peer.h
+++ b/src/devices/wifi/nm-wifi-p2p-peer.h
@@ -1,20 +1,5 @@
-/* NetworkManager -- Wi-Fi P2P Peer
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
+// SPDX-License-Identifier: LGPL-2.1+
+/*
  * Copyright (C) 2018 Red Hat, Inc.
  */
 
diff --git a/src/devices/wifi/nm-wifi-utils.c b/src/devices/wifi/nm-wifi-utils.c
index 426eeea8..b9b7ec42 100644
--- a/src/devices/wifi/nm-wifi-utils.c
+++ b/src/devices/wifi/nm-wifi-utils.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: LGPL-2.1+
 /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Red Hat, Inc.
  */
 
 #include "nm-default.h"
@@ -297,96 +283,79 @@ verify_wpa_psk (NMSettingWirelessSecurity *s_wsec,
                 guint32 rsn_flags,
                 GError **error)
 {
-	const char *key_mgmt, *auth_alg, *tmp;
-	int n;
+	const char *key_mgmt, *auth_alg;
 
 	key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
 	auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
 
-	if (key_mgmt) {
-		if (!strcmp (key_mgmt, "wpa-psk") || !strcmp (key_mgmt, "wpa-none")) {
-			if (s_8021x) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_SETTING,
-				                     _("WPA-PSK authentication is incompatible with 802.1x"));
-				g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME);
-				return FALSE;
-			}
+	if (!nm_streq0 (key_mgmt, "wpa-psk"))
+		return TRUE;
 
-			if (auth_alg && strcmp (auth_alg, "open")) {
-				/* WPA must use "open" authentication */
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("WPA-PSK requires 'open' authentication"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-				                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-				return FALSE;
-			}
-		}
+	if (s_8021x) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_SETTING,
+		                     _("WPA-PSK authentication is incompatible with 802.1x"));
+		g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME);
+		return FALSE;
+	}
 
-		if (!strcmp (key_mgmt, "wpa-none")) {
-			if (!adhoc) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("WPA Ad-Hoc authentication requires an Ad-Hoc mode AP"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SETTING_NAME,
-				                NM_SETTING_WIRELESS_MODE);
-				return FALSE;
-			}
+	if (auth_alg && !nm_streq (auth_alg, "open")) {
+		/* WPA must use "open" authentication */
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("WPA-PSK requires 'open' authentication"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+		return FALSE;
+	}
 
-			/* Ad-Hoc WPA requires 'wpa' proto, 'none' pairwise, and 'tkip' group */
-			n = nm_setting_wireless_security_get_num_protos (s_wsec);
-			tmp = (n > 0) ? nm_setting_wireless_security_get_proto (s_wsec, 0) : NULL;
-			if (n > 1 || !tmp || strcmp (tmp, "wpa")) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("WPA Ad-Hoc authentication requires 'wpa' protocol"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-				                NM_SETTING_WIRELESS_SECURITY_PROTO);
-				return FALSE;
-			}
+	/* Make sure the AP's capabilities support WPA-PSK */
+	if (   !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
+	    && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("Access point does not support PSK but setting requires it"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+		return FALSE;
+	}
 
-			n = nm_setting_wireless_security_get_num_pairwise (s_wsec);
-			tmp = (n > 0) ? nm_setting_wireless_security_get_pairwise (s_wsec, 0) : NULL;
-			if (n > 1 || g_strcmp0 (tmp, "none")) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("WPA Ad-Hoc authentication requires 'none' pairwise cipher"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-				                NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
-				return FALSE;
-			}
+	if (adhoc) {
+		/* Ad-Hoc RSN requires 'rsn' proto, 'ccmp' pairwise, and 'ccmp' group */
+		if (   nm_setting_wireless_security_get_num_protos (s_wsec) != 1
+		    || !nm_streq0 (nm_setting_wireless_security_get_proto (s_wsec, 0), "rsn")) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("WPA Ad-Hoc authentication requires 'rsn' protocol"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+			                NM_SETTING_WIRELESS_SECURITY_PROTO);
+			return FALSE;
+		}
 
-			n = nm_setting_wireless_security_get_num_groups (s_wsec);
-			tmp = (n > 0) ? nm_setting_wireless_security_get_group (s_wsec, 0) : NULL;
-			if (n > 1 || !tmp || strcmp (tmp, "tkip")) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("WPA Ad-Hoc requires 'tkip' group cipher"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-				                NM_SETTING_WIRELESS_SECURITY_GROUP);
-				return FALSE;
-			}
+		if (   nm_setting_wireless_security_get_num_pairwise (s_wsec) != 1
+		    || !nm_streq0 (nm_setting_wireless_security_get_pairwise (s_wsec, 0), "ccmp")) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("WPA Ad-Hoc authentication requires 'ccmp' pairwise cipher"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+			                NM_SETTING_WIRELESS_SECURITY_PAIRWISE);
+			return FALSE;
 		}
 
-		if (!strcmp (key_mgmt, "wpa-psk")) {
-			/* Make sure the AP's capabilities support WPA-PSK */
-			if (   !(wpa_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)
-			    && !(rsn_flags & NM_802_11_AP_SEC_KEY_MGMT_PSK)) {
-				g_set_error_literal (error,
-				                     NM_CONNECTION_ERROR,
-				                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-				                     _("Access point does not support PSK but setting requires it"));
-				g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-				                NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-				return FALSE;
-			}
+		if (   nm_setting_wireless_security_get_num_groups (s_wsec) != 1
+		    || !nm_streq0 (nm_setting_wireless_security_get_group (s_wsec, 0), "ccmp")) {
+			g_set_error_literal (error,
+			                     NM_CONNECTION_ERROR,
+			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+			                     _("WPA Ad-Hoc requires 'ccmp' group cipher"));
+			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+			                NM_SETTING_WIRELESS_SECURITY_GROUP);
+			return FALSE;
 		}
 	}
 
@@ -463,61 +432,52 @@ verify_adhoc (NMSettingWirelessSecurity *s_wsec,
 {
 	const char *key_mgmt = NULL, *leap_username = NULL, *auth_alg = NULL;
 
+	if (!adhoc)
+		return TRUE;
+
 	if (s_wsec) {
 		key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
 		auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
 		leap_username = nm_setting_wireless_security_get_leap_username (s_wsec);
 	}
 
-	if (adhoc) {
-		if (key_mgmt && strcmp (key_mgmt, "wpa-none") && strcmp (key_mgmt, "none")) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("Access point mode is Ad-Hoc but setting requires Infrastructure security"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-			                NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-			return FALSE;
-		}
+	if (key_mgmt && !NM_IN_STRSET (key_mgmt, "none", "wpa-psk")) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("Ad-Hoc mode requires 'none' or 'wpa-psk' key management"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
+		return FALSE;
+	}
 
-		if (s_8021x) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_SETTING,
-			                     _("Ad-Hoc mode is incompatible with 802.1x security"));
-			g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME);
-			return FALSE;
-		}
+	if (s_8021x) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_SETTING,
+		                     _("Ad-Hoc mode is incompatible with 802.1x security"));
+		g_prefix_error (error, "%s: ", NM_SETTING_802_1X_SETTING_NAME);
+		return FALSE;
+	}
 
-		if (leap_username) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("Ad-Hoc mode is incompatible with LEAP security"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-			                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-			return FALSE;
-		}
+	if (leap_username) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("Ad-Hoc mode is incompatible with LEAP security"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+		return FALSE;
+	}
 
-		if (auth_alg && strcmp (auth_alg, "open")) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("Ad-Hoc mode requires 'open' authentication"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-			                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
-			return FALSE;
-		}
-	} else {
-		if (key_mgmt && !strcmp (key_mgmt, "wpa-none")) {
-			g_set_error_literal (error,
-			                     NM_CONNECTION_ERROR,
-			                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
-			                     _("Access point mode is Infrastructure but setting requires Ad-Hoc security"));
-			g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
-			                NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
-			return FALSE;
-		}
+	if (auth_alg && !nm_streq (auth_alg, "open")) {
+		g_set_error_literal (error,
+		                     NM_CONNECTION_ERROR,
+		                     NM_CONNECTION_ERROR_INVALID_PROPERTY,
+		                     _("Ad-Hoc mode requires 'open' authentication"));
+		g_prefix_error (error, "%s.%s: ", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
+		                NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
+		return FALSE;
 	}
 
 	return TRUE;
@@ -773,11 +733,13 @@ nm_wifi_utils_complete_connection (GBytes *ap_ssid,
 		return FALSE;
 
 	if (adhoc) {
-		g_object_set (s_wsec, NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-none", NULL);
-		/* Ad-Hoc does not support RSN/WPA2 */
-		nm_setting_wireless_security_add_proto (s_wsec, "wpa");
-		nm_setting_wireless_security_add_pairwise (s_wsec, "none");
-		nm_setting_wireless_security_add_group (s_wsec, "tkip");
+		g_object_set (s_wsec,
+		              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk",
+		              NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "open",
+		              NULL);
+		nm_setting_wireless_security_add_proto (s_wsec, "rsn");
+		nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp");
+		nm_setting_wireless_security_add_group (s_wsec, "ccmp");
 	} else if (s_8021x) {
 		g_object_set (s_wsec,
 		              NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
diff --git a/src/devices/wifi/nm-wifi-utils.h b/src/devices/wifi/nm-wifi-utils.h
index 251d122f..982080b9 100644
--- a/src/devices/wifi/nm-wifi-utils.h
+++ b/src/devices/wifi/nm-wifi-utils.h
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: LGPL-2.1+
 /*
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA.
- *
- * (C) Copyright 2011 Red Hat, Inc.
+ * Copyright (C) 2011 Red Hat, Inc.
  */
 
 #ifndef __NM_WIFI_UTILS_H__
diff --git a/src/devices/wifi/tests/meson.build b/src/devices/wifi/tests/meson.build
deleted file mode 100644
index ba756d53..00000000
--- a/src/devices/wifi/tests/meson.build
+++ /dev/null
@@ -1,14 +0,0 @@
-test_unit = 'test-devices-wifi'
-
-exe = executable(
-  test_unit,
-  [test_unit + '.c'] + common_sources,
-  dependencies: test_nm_dep,
-)
-
-test(
-  test_unit,
-  test_script,
-  args: test_args + [exe.full_path()],
-  timeout: default_test_timeout,
-)
diff --git a/src/devices/wifi/tests/test-devices-wifi.c b/src/devices/wifi/tests/test-devices-wifi.c
index a0b3e17f..a960e7a2 100644
--- a/src/devices/wifi/tests/test-devices-wifi.c
+++ b/src/devices/wifi/tests/test-devices-wifi.c
@@ -1,20 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
  * Copyright (C) 2011 Red Hat, Inc.
- *
  */
 
 #include "nm-default.h"