about summary refs log tree commit diff
path: root/libnm
diff options
context:
space:
mode:
Diffstat (limited to 'libnm')
-rw-r--r--libnm/NetworkManager.h6
-rw-r--r--libnm/fake-typelib/meson.build2
-rw-r--r--libnm/libnm.ver65
-rw-r--r--libnm/meson.build48
-rw-r--r--libnm/nm-access-point.c2
-rw-r--r--libnm/nm-active-connection.c3
-rw-r--r--libnm/nm-autoptr.h4
-rw-r--r--libnm/nm-checkpoint.c2
-rw-r--r--libnm/nm-client.c21
-rw-r--r--libnm/nm-client.h4
-rw-r--r--libnm/nm-dbus-helpers.c2
-rw-r--r--libnm/nm-device-adsl.c3
-rw-r--r--libnm/nm-device-bond.c4
-rw-r--r--libnm/nm-device-bridge.c4
-rw-r--r--libnm/nm-device-bt.c4
-rw-r--r--libnm/nm-device-dummy.c3
-rw-r--r--libnm/nm-device-ethernet.c4
-rw-r--r--libnm/nm-device-generic.c3
-rw-r--r--libnm/nm-device-infiniband.c4
-rw-r--r--libnm/nm-device-ip-tunnel.c4
-rw-r--r--libnm/nm-device-macsec.c3
-rw-r--r--libnm/nm-device-macvlan.c4
-rw-r--r--libnm/nm-device-modem.c4
-rw-r--r--libnm/nm-device-olpc-mesh.c4
-rw-r--r--libnm/nm-device-ovs-bridge.c3
-rw-r--r--libnm/nm-device-ovs-interface.c3
-rw-r--r--libnm/nm-device-ovs-port.c4
-rw-r--r--libnm/nm-device-team.c4
-rw-r--r--libnm/nm-device-tun.c6
-rw-r--r--libnm/nm-device-vlan.c4
-rw-r--r--libnm/nm-device-vxlan.c4
-rw-r--r--libnm/nm-device-wifi-p2p.c502
-rw-r--r--libnm/nm-device-wifi-p2p.h80
-rw-r--r--libnm/nm-device-wifi.c3
-rw-r--r--libnm/nm-device-wimax.c4
-rw-r--r--libnm/nm-device-wpan.c3
-rw-r--r--libnm/nm-device.c12
-rw-r--r--libnm/nm-dhcp-config.c3
-rw-r--r--libnm/nm-dhcp4-config.c1
-rw-r--r--libnm/nm-dhcp6-config.c1
-rw-r--r--libnm/nm-dns-manager.c3
-rw-r--r--libnm/nm-ip-config.c3
-rw-r--r--libnm/nm-ip4-config.c1
-rw-r--r--libnm/nm-ip6-config.c1
-rw-r--r--libnm/nm-manager.c26
-rw-r--r--libnm/nm-object.c1
-rw-r--r--libnm/nm-property-docs.xml19
-rw-r--r--libnm/nm-remote-connection.c4
-rw-r--r--libnm/nm-remote-settings.c3
-rw-r--r--libnm/nm-secret-agent-old.c524
-rw-r--r--libnm/nm-settings-docs-overrides.xml5
-rw-r--r--libnm/nm-settings-docs.xml20
-rw-r--r--libnm/nm-settings-ifcfg-rh-docs.xml4
-rw-r--r--libnm/nm-settings-keyfile-docs.xml7
-rw-r--r--libnm/nm-types.h4
-rw-r--r--libnm/nm-vpn-connection.c3
-rw-r--r--libnm/nm-vpn-plugin-old.c1
-rw-r--r--libnm/nm-vpn-service-plugin.c8
-rw-r--r--libnm/nm-wifi-p2p-peer.c600
-rw-r--r--libnm/nm-wifi-p2p-peer.h89
-rw-r--r--libnm/nm-wimax-nsp.c4
-rw-r--r--libnm/tests/test-nm-client.c1
-rw-r--r--libnm/tests/test-remote-settings-client.c1
-rw-r--r--libnm/tests/test-secret-agent.c1
64 files changed, 1763 insertions, 414 deletions
diff --git a/libnm/NetworkManager.h b/libnm/NetworkManager.h
index 759a4131..7c70a226 100644
--- a/libnm/NetworkManager.h
+++ b/libnm/NetworkManager.h
@@ -43,14 +43,15 @@
 #include "nm-device-macvlan.h"
 #include "nm-device-modem.h"
 #include "nm-device-olpc-mesh.h"
+#include "nm-device-ovs-bridge.h"
 #include "nm-device-ovs-interface.h"
 #include "nm-device-ovs-port.h"
-#include "nm-device-ovs-bridge.h"
 #include "nm-device-ppp.h"
 #include "nm-device-team.h"
 #include "nm-device-tun.h"
 #include "nm-device-vlan.h"
 #include "nm-device-vxlan.h"
+#include "nm-device-wifi-p2p.h"
 #include "nm-device-wifi.h"
 #include "nm-device-wimax.h"
 #include "nm-device-wireguard.h"
@@ -88,6 +89,7 @@
 #include "nm-setting-ovs-interface.h"
 #include "nm-setting-ovs-patch.h"
 #include "nm-setting-ovs-port.h"
+#include "nm-setting-wifi-p2p.h"
 #include "nm-setting-ppp.h"
 #include "nm-setting-pppoe.h"
 #include "nm-setting-proxy.h"
@@ -103,6 +105,7 @@
 #include "nm-setting-vxlan.h"
 #include "nm-setting-wimax.h"
 #include "nm-setting-wired.h"
+#include "nm-setting-wireguard.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-setting-wpan.h"
@@ -116,6 +119,7 @@
 #include "nm-vpn-editor-plugin.h"
 #include "nm-vpn-plugin-info.h"
 #include "nm-vpn-service-plugin.h"
+#include "nm-wifi-p2p-peer.h"
 #include "nm-wimax-nsp.h"
 
 #include "nm-autoptr.h"
diff --git a/libnm/fake-typelib/meson.build b/libnm/fake-typelib/meson.build
index cafe013a..fdbb2920 100644
--- a/libnm/fake-typelib/meson.build
+++ b/libnm/fake-typelib/meson.build
@@ -20,7 +20,7 @@ endforeach
 
 resource = 'typelibs'
 
-sources += gnome.compile_resources(
+libnm_utils_sources += gnome.compile_resources(
   resource,
   resource + '.gresource.xml',
   source_dir: '.',
diff --git a/libnm/libnm.ver b/libnm/libnm.ver
index 652e01eb..ece9686e 100644
--- a/libnm/libnm.ver
+++ b/libnm/libnm.ver
@@ -1450,6 +1450,71 @@ global:
 	nm_client_add_and_activate_connection2;
 	nm_client_add_and_activate_connection2_finish;
 	nm_device_get_connectivity;
+	nm_device_wifi_p2p_get_hw_address;
+	nm_device_wifi_p2p_get_peers;
+	nm_device_wifi_p2p_get_type;
+	nm_device_wifi_p2p_start_find;
+	nm_device_wifi_p2p_start_find_finish;
+	nm_device_wifi_p2p_stop_find;
+	nm_device_wifi_p2p_stop_find_finish;
+	nm_setting_wifi_p2p_get_peer;
+	nm_setting_wifi_p2p_get_type;
+	nm_setting_wifi_p2p_get_wfd_ies;
+	nm_setting_wifi_p2p_get_wps_method;
+	nm_setting_wifi_p2p_new;
+	nm_setting_wireguard_append_peer;
+	nm_setting_wireguard_clear_peers;
+	nm_setting_wireguard_get_fwmark;
+	nm_setting_wireguard_get_listen_port;
+	nm_setting_wireguard_get_mtu;
+	nm_setting_wireguard_get_peer;
+	nm_setting_wireguard_get_peer_by_public_key;
+	nm_setting_wireguard_get_peer_routes;
+	nm_setting_wireguard_get_peers_len;
+	nm_setting_wireguard_get_private_key;
+	nm_setting_wireguard_get_private_key_flags;
+	nm_setting_wireguard_get_type;
+	nm_setting_wireguard_new;
+	nm_setting_wireguard_remove_peer;
+	nm_setting_wireguard_set_peer;
 	nm_team_link_watcher_get_vlanid;
 	nm_team_link_watcher_new_arp_ping2;
+	nm_utils_base64secret_decode;
+	nm_wifi_p2p_peer_connection_valid;
+	nm_wifi_p2p_peer_filter_connections;
+	nm_wifi_p2p_peer_get_flags;
+	nm_wifi_p2p_peer_get_hw_address;
+	nm_wifi_p2p_peer_get_last_seen;
+	nm_wifi_p2p_peer_get_manufacturer;
+	nm_wifi_p2p_peer_get_model;
+	nm_wifi_p2p_peer_get_model_number;
+	nm_wifi_p2p_peer_get_name;
+	nm_wifi_p2p_peer_get_serial;
+	nm_wifi_p2p_peer_get_strength;
+	nm_wifi_p2p_peer_get_type;
+	nm_wifi_p2p_peer_get_wfd_ies;
+	nm_wireguard_peer_append_allowed_ip;
+	nm_wireguard_peer_clear_allowed_ips;
+	nm_wireguard_peer_cmp;
+	nm_wireguard_peer_get_allowed_ip;
+	nm_wireguard_peer_get_allowed_ips_len;
+	nm_wireguard_peer_get_endpoint;
+	nm_wireguard_peer_get_persistent_keepalive;
+	nm_wireguard_peer_get_preshared_key;
+	nm_wireguard_peer_get_preshared_key_flags;
+	nm_wireguard_peer_get_public_key;
+	nm_wireguard_peer_get_type;
+	nm_wireguard_peer_is_sealed;
+	nm_wireguard_peer_is_valid;
+	nm_wireguard_peer_new;
+	nm_wireguard_peer_new_clone;
+	nm_wireguard_peer_ref;
+	nm_wireguard_peer_remove_allowed_ip;
+	nm_wireguard_peer_seal;
+	nm_wireguard_peer_set_endpoint;
+	nm_wireguard_peer_set_persistent_keepalive;
+	nm_wireguard_peer_set_preshared_key;
+	nm_wireguard_peer_set_preshared_key_flags;
+	nm_wireguard_peer_set_public_key;
+	nm_wireguard_peer_unref;
 } libnm_1_14_0;
diff --git a/libnm/meson.build b/libnm/meson.build
index 2e44a6a4..558a587b 100644
--- a/libnm/meson.build
+++ b/libnm/meson.build
@@ -1,17 +1,18 @@
 libnm_inc = include_directories('.')
 
-sources = files('nm-libnm-utils.c')
-
-deps = [
-  libnmdbus_dep,
-  shared_dep,
-]
-
 cflags = [
   '-DG_LOG_DOMAIN="@0@"'.format(libnm_name),
   '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM',
 ]
 
+libnm_utils_sources = files('nm-libnm-utils.c')
+
+deps = [
+  libnmdbus_dep,
+  shared_nm_utils_base_dep,
+  nm_core_dep,
+]
+
 if have_fake_typelibs
   deps += gir_dep
   subdir('fake-typelib')
@@ -19,7 +20,7 @@ endif
 
 libnm_utils = static_library(
   'nm-utils',
-  sources: sources,
+  sources: libnm_utils_sources,
   include_directories: libnm_core_inc,
   dependencies: deps,
   c_args: cflags,
@@ -40,25 +41,26 @@ libnm_headers = files(
   'nm-device-dummy.h',
   'nm-device-ethernet.h',
   'nm-device-generic.h',
-  'nm-device.h',
   'nm-device-infiniband.h',
   'nm-device-ip-tunnel.h',
   'nm-device-macsec.h',
   'nm-device-macvlan.h',
   'nm-device-modem.h',
   'nm-device-olpc-mesh.h',
+  'nm-device-ovs-bridge.h',
   'nm-device-ovs-interface.h',
   'nm-device-ovs-port.h',
-  'nm-device-ovs-bridge.h',
   'nm-device-ppp.h',
   'nm-device-team.h',
   'nm-device-tun.h',
   'nm-device-vlan.h',
   'nm-device-vxlan.h',
+  'nm-device-wifi-p2p.h',
   'nm-device-wifi.h',
   'nm-device-wimax.h',
   'nm-device-wireguard.h',
   'nm-device-wpan.h',
+  'nm-device.h',
   'nm-dhcp-config.h',
   'nm-ip-config.h',
   'nm-object.h',
@@ -69,6 +71,7 @@ libnm_headers = files(
   'nm-vpn-editor.h',
   'nm-vpn-plugin-old.h',
   'nm-vpn-service-plugin.h',
+  'nm-wifi-p2p-peer.h',
   'nm-wimax-nsp.h',
 )
 
@@ -101,7 +104,6 @@ libnm_sources = files(
   'nm-device-bond.c',
   'nm-device-bridge.c',
   'nm-device-bt.c',
-  'nm-device.c',
   'nm-device-dummy.c',
   'nm-device-ethernet.c',
   'nm-device-generic.c',
@@ -111,18 +113,20 @@ libnm_sources = files(
   'nm-device-macvlan.c',
   'nm-device-modem.c',
   'nm-device-olpc-mesh.c',
+  'nm-device-ovs-bridge.c',
   'nm-device-ovs-interface.c',
   'nm-device-ovs-port.c',
-  'nm-device-ovs-bridge.c',
   'nm-device-ppp.c',
   'nm-device-team.c',
   'nm-device-tun.c',
   'nm-device-vlan.c',
   'nm-device-vxlan.c',
+  'nm-device-wifi-p2p.c',
   'nm-device-wifi.c',
   'nm-device-wimax.c',
   'nm-device-wireguard.c',
   'nm-device-wpan.c',
+  'nm-device.c',
   'nm-dhcp-config.c',
   'nm-dhcp4-config.c',
   'nm-dhcp6-config.c',
@@ -136,20 +140,13 @@ libnm_sources = files(
   'nm-remote-settings.c',
   'nm-secret-agent-old.c',
   'nm-vpn-connection.c',
-  'nm-vpn-plugin-old.c',
   'nm-vpn-editor.c',
+  'nm-vpn-plugin-old.c',
   'nm-vpn-service-plugin.c',
+  'nm-wifi-p2p-peer.c',
   'nm-wimax-nsp.c',
 )
 
-deps = [
-  dl_dep,
-  libudev_dep,
-  shared_dep,
-  uuid_dep,
-  libnm_systemd_shared_no_logging_dep,
-]
-
 linker_script = join_paths(meson.current_source_dir(), 'libnm.ver')
 
 
@@ -158,7 +155,14 @@ libnm = shared_library(
   sources: libnm_sources + libnm_enum,
   version: libnm_version,
   include_directories: libnm_core_inc,
-  dependencies: deps,
+  dependencies: [
+    dl_dep,
+    libudev_dep,
+    shared_nm_utils_base_dep,
+    nm_core_dep,
+    uuid_dep,
+    libnm_systemd_shared_no_logging_dep,
+  ],
   c_args: cflags,
   link_with: libnm_utils,
   link_whole: libnm_core,
diff --git a/libnm/nm-access-point.c b/libnm/nm-access-point.c
index 25281c92..ac00d6e1 100644
--- a/libnm/nm-access-point.c
+++ b/libnm/nm-access-point.c
@@ -23,8 +23,6 @@
 
 #include "nm-access-point.h"
 
-#include <string.h>
-
 #include "nm-connection.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-wireless.h"
diff --git a/libnm/nm-active-connection.c b/libnm/nm-active-connection.c
index 5b238b3b..fdade4bc 100644
--- a/libnm/nm-active-connection.c
+++ b/libnm/nm-active-connection.c
@@ -21,10 +21,9 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-active-connection.h"
 
 #include "nm-dbus-interface.h"
-#include "nm-active-connection.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
 #include "nm-device.h"
diff --git a/libnm/nm-autoptr.h b/libnm/nm-autoptr.h
index e96a03a0..40248dcd 100644
--- a/libnm/nm-autoptr.h
+++ b/libnm/nm-autoptr.h
@@ -51,11 +51,11 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingDummy, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingEthtool, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingGeneric, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingGsm, g_object_unref)
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingInfiniband, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingIP4Config, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingIP6Config, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingIPConfig, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingIPTunnel, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingInfiniband, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingMacsec, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingMacvlan, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingMatch, g_object_unref)
@@ -77,8 +77,10 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingUser, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingVlan, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingVpn, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingVxlan, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWifiP2P, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWimax, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWired, g_object_unref)
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWireGuard, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWireless, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWirelessSecurity, g_object_unref)
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (NMSettingWpan, g_object_unref)
diff --git a/libnm/nm-checkpoint.c b/libnm/nm-checkpoint.c
index ce15d087..0dde238e 100644
--- a/libnm/nm-checkpoint.c
+++ b/libnm/nm-checkpoint.c
@@ -91,7 +91,7 @@ nm_checkpoint_get_created (NMCheckpoint *checkpoint)
  * nm_checkpoint_get_rollback_timeout:
  * @checkpoint: a #NMCheckpoint
  *
- * Gets the the timeout in seconds for automatic rollback.
+ * Gets the timeout in seconds for automatic rollback.
  *
  * Returns: the rollback timeout.
  *
diff --git a/libnm/nm-client.c b/libnm/nm-client.c
index e2522229..0f8cd773 100644
--- a/libnm/nm-client.c
+++ b/libnm/nm-client.c
@@ -21,11 +21,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-client.h"
+
 #include <libudev.h>
 
 #include "nm-utils.h"
-#include "nm-client.h"
 #include "nm-manager.h"
 #include "nm-dns-manager.h"
 #include "nm-remote-settings.h"
@@ -41,6 +41,7 @@
 
 #include "introspection/org.freedesktop.NetworkManager.h"
 #include "introspection/org.freedesktop.NetworkManager.Device.Wireless.h"
+#include "introspection/org.freedesktop.NetworkManager.Device.WifiP2P.h"
 #include "introspection/org.freedesktop.NetworkManager.Device.h"
 #include "introspection/org.freedesktop.NetworkManager.DnsManager.h"
 #include "introspection/org.freedesktop.NetworkManager.Settings.h"
@@ -65,24 +66,26 @@
 #include "nm-device-macvlan.h"
 #include "nm-device-modem.h"
 #include "nm-device-olpc-mesh.h"
+#include "nm-device-ovs-bridge.h"
 #include "nm-device-ovs-interface.h"
 #include "nm-device-ovs-port.h"
-#include "nm-device-ovs-bridge.h"
 #include "nm-device-ppp.h"
 #include "nm-device-team.h"
 #include "nm-device-tun.h"
 #include "nm-device-vlan.h"
 #include "nm-device-vxlan.h"
+#include "nm-device-wifi-p2p.h"
 #include "nm-device-wifi.h"
 #include "nm-device-wimax.h"
 #include "nm-device-wireguard.h"
 #include "nm-device-wpan.h"
+#include "nm-dhcp-config.h"
 #include "nm-dhcp4-config.h"
 #include "nm-dhcp6-config.h"
-#include "nm-dhcp-config.h"
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
 #include "nm-manager.h"
+#include "nm-wifi-p2p-peer.h"
 #include "nm-remote-connection.h"
 #include "nm-remote-settings.h"
 #include "nm-vpn-connection.h"
@@ -1165,7 +1168,7 @@ add_activate_cb (GObject *object,
 {
 	gs_unref_object GSimpleAsyncResult *simple = user_data;
 	gs_unref_variant GVariant *result_data = NULL;
-	NMActiveConnection *ac;
+	gs_unref_object NMActiveConnection *ac = NULL;
 	GError *error = NULL;
 
 	ac = nm_manager_add_and_activate_connection_finish (NM_MANAGER (object), result, &result_data, &error);
@@ -1363,7 +1366,7 @@ nm_client_add_and_activate_connection2 (NMClient *client,
  * @client: an #NMClient
  * @result: the result passed to the #GAsyncReadyCallback
  * @error: location for a #GError, or %NULL
- * @out_result: (allow-none): (transfer full): the output result
+ * @out_result: (allow-none) (transfer full): the output result
  *   of type "a{sv}" returned by D-Bus' AddAndActivate2 call. Currently no
  *   output is implemented yet.
  *
@@ -2611,6 +2614,8 @@ proxy_type (GDBusObjectManagerClient *manager,
 		return NMDBUS_TYPE_MANAGER_PROXY;
 	else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_WIRELESS) == 0)
 		return NMDBUS_TYPE_DEVICE_WIFI_PROXY;
+	else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P) == 0)
+		return NMDBUS_TYPE_DEVICE_WIFI_P2P_PROXY;
 	else if (strcmp (interface_name, NM_DBUS_INTERFACE_DEVICE) == 0)
 		return NMDBUS_TYPE_DEVICE_PROXY;
 	else if (strcmp (interface_name, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0)
@@ -2689,6 +2694,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager
 			type = NM_TYPE_DEVICE_OVS_PORT;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_OVS_BRIDGE) == 0)
 			type = NM_TYPE_DEVICE_OVS_BRIDGE;
+		else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P) == 0)
+			type = NM_TYPE_DEVICE_WIFI_P2P;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_PPP) == 0)
 			type = NM_TYPE_DEVICE_PPP;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_DEVICE_TEAM) == 0)
@@ -2715,6 +2722,8 @@ obj_nm_for_gdbus_object (NMClient *self, GDBusObject *object, GDBusObjectManager
 			type = NM_TYPE_IP4_CONFIG;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_IP6_CONFIG) == 0)
 			type = NM_TYPE_IP6_CONFIG;
+		else if (strcmp (ifname, NM_DBUS_INTERFACE_WIFI_P2P_PEER) == 0)
+			type = NM_TYPE_WIFI_P2P_PEER;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS_CONNECTION) == 0)
 			type = NM_TYPE_REMOTE_CONNECTION;
 		else if (strcmp (ifname, NM_DBUS_INTERFACE_SETTINGS) == 0)
diff --git a/libnm/nm-client.h b/libnm/nm-client.h
index 97363ef7..edb3ed78 100644
--- a/libnm/nm-client.h
+++ b/libnm/nm-client.h
@@ -107,6 +107,7 @@ G_BEGIN_DECLS
  *  statistics can be globally enabled or disabled
  * @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether
  *  connectivity check can be enabled or disabled
+ * @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed
  * @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
  *
  * #NMClientPermission values indicate various permissions that NetworkManager
@@ -130,8 +131,9 @@ typedef enum {
 	NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14,
 	NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15,
 	NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16,
+	NM_CLIENT_PERMISSION_WIFI_SCAN = 17,
 
-	NM_CLIENT_PERMISSION_LAST = 16,
+	NM_CLIENT_PERMISSION_LAST = 17,
 } NMClientPermission;
 
 /**
diff --git a/libnm/nm-dbus-helpers.c b/libnm/nm-dbus-helpers.c
index 44eed0c8..a507c658 100644
--- a/libnm/nm-dbus-helpers.c
+++ b/libnm/nm-dbus-helpers.c
@@ -22,8 +22,6 @@
 
 #include "nm-dbus-helpers.h"
 
-#include <string.h>
-
 #include "nm-dbus-interface.h"
 
 static GBusType nm_bus = G_BUS_TYPE_SYSTEM;
diff --git a/libnm/nm-device-adsl.c b/libnm/nm-device-adsl.c
index a82aa8d0..f63468aa 100644
--- a/libnm/nm-device-adsl.c
+++ b/libnm/nm-device-adsl.c
@@ -23,10 +23,7 @@
 
 #include "nm-device-adsl.h"
 
-#include <string.h>
-
 #include "nm-object-private.h"
-
 #include "nm-setting-adsl.h"
 #include "nm-setting-connection.h"
 
diff --git a/libnm/nm-device-bond.c b/libnm/nm-device-bond.c
index 83b7c3b4..4cc47b5c 100644
--- a/libnm/nm-device-bond.c
+++ b/libnm/nm-device-bond.c
@@ -20,12 +20,10 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-setting-bond.h"
 
 #include "nm-setting-connection.h"
-#include "nm-setting-bond.h"
 #include "nm-utils.h"
-
 #include "nm-device-bond.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
diff --git a/libnm/nm-device-bridge.c b/libnm/nm-device-bridge.c
index 39c48d2a..2db3a238 100644
--- a/libnm/nm-device-bridge.c
+++ b/libnm/nm-device-bridge.c
@@ -20,12 +20,10 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-setting-bridge.h"
 
 #include "nm-setting-connection.h"
-#include "nm-setting-bridge.h"
 #include "nm-utils.h"
-
 #include "nm-device-bridge.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
diff --git a/libnm/nm-device-bt.c b/libnm/nm-device-bt.c
index a47e3958..d0af0ff6 100644
--- a/libnm/nm-device-bt.c
+++ b/libnm/nm-device-bt.c
@@ -21,13 +21,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-bt.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-bluetooth.h"
 #include "nm-utils.h"
-
-#include "nm-device-bt.h"
 #include "nm-object-private.h"
 #include "nm-enum-types.h"
 
diff --git a/libnm/nm-device-dummy.c b/libnm/nm-device-dummy.c
index 4c202025..8a372143 100644
--- a/libnm/nm-device-dummy.c
+++ b/libnm/nm-device-dummy.c
@@ -20,9 +20,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-dummy.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-dummy.h"
 #include "nm-setting-connection.h"
diff --git a/libnm/nm-device-ethernet.c b/libnm/nm-device-ethernet.c
index ebb019dc..5d2acdb2 100644
--- a/libnm/nm-device-ethernet.c
+++ b/libnm/nm-device-ethernet.c
@@ -21,14 +21,12 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-ethernet.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-wired.h"
 #include "nm-setting-pppoe.h"
 #include "nm-utils.h"
-
-#include "nm-device-ethernet.h"
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDeviceEthernet, nm_device_ethernet, NM_TYPE_DEVICE)
diff --git a/libnm/nm-device-generic.c b/libnm/nm-device-generic.c
index 62cb89eb..c0bf4d70 100644
--- a/libnm/nm-device-generic.c
+++ b/libnm/nm-device-generic.c
@@ -20,9 +20,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-generic.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-generic.h"
 #include "nm-setting-connection.h"
diff --git a/libnm/nm-device-infiniband.c b/libnm/nm-device-infiniband.c
index 1ed942b5..aaf5ff86 100644
--- a/libnm/nm-device-infiniband.c
+++ b/libnm/nm-device-infiniband.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-infiniband.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-infiniband.h"
 #include "nm-utils.h"
-
-#include "nm-device-infiniband.h"
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDeviceInfiniband, nm_device_infiniband, NM_TYPE_DEVICE)
diff --git a/libnm/nm-device-ip-tunnel.c b/libnm/nm-device-ip-tunnel.c
index 2f7efe9d..150dc989 100644
--- a/libnm/nm-device-ip-tunnel.c
+++ b/libnm/nm-device-ip-tunnel.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-ip-tunnel.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-ip-tunnel.h"
 #include "nm-utils.h"
-
-#include "nm-device-ip-tunnel.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
 
diff --git a/libnm/nm-device-macsec.c b/libnm/nm-device-macsec.c
index 16bbbebb..493bff87 100644
--- a/libnm/nm-device-macsec.c
+++ b/libnm/nm-device-macsec.c
@@ -20,9 +20,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-macsec.h"
+
 #include "nm-device-private.h"
 #include "nm-object-private.h"
 #include "nm-utils.h"
diff --git a/libnm/nm-device-macvlan.c b/libnm/nm-device-macvlan.c
index 23c649cc..37484770 100644
--- a/libnm/nm-device-macvlan.c
+++ b/libnm/nm-device-macvlan.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-setting-macvlan.h"
 
 #include "nm-setting-connection.h"
-#include "nm-setting-macvlan.h"
 #include "nm-setting-wired.h"
 #include "nm-utils.h"
-
 #include "nm-device-macvlan.h"
 #include "nm-object-private.h"
 
diff --git a/libnm/nm-device-modem.c b/libnm/nm-device-modem.c
index 7fc843f6..0373b3c0 100644
--- a/libnm/nm-device-modem.c
+++ b/libnm/nm-device-modem.c
@@ -21,13 +21,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-modem.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-gsm.h"
 #include "nm-setting-cdma.h"
-
-#include "nm-device-modem.h"
 #include "nm-object-private.h"
 #include "nm-enum-types.h"
 
diff --git a/libnm/nm-device-olpc-mesh.c b/libnm/nm-device-olpc-mesh.c
index 875f11a9..62589164 100644
--- a/libnm/nm-device-olpc-mesh.c
+++ b/libnm/nm-device-olpc-mesh.c
@@ -20,12 +20,10 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-olpc-mesh.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-olpc-mesh.h"
-
-#include "nm-device-olpc-mesh.h"
 #include "nm-object-private.h"
 #include "nm-device-wifi.h"
 
diff --git a/libnm/nm-device-ovs-bridge.c b/libnm/nm-device-ovs-bridge.c
index 27ee97cf..4671c8a9 100644
--- a/libnm/nm-device-ovs-bridge.c
+++ b/libnm/nm-device-ovs-bridge.c
@@ -19,9 +19,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-ovs-bridge.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-ovs-bridge.h"
 #include "nm-setting-ovs-port.h"
diff --git a/libnm/nm-device-ovs-interface.c b/libnm/nm-device-ovs-interface.c
index ed3dbd4c..b07373e1 100644
--- a/libnm/nm-device-ovs-interface.c
+++ b/libnm/nm-device-ovs-interface.c
@@ -19,9 +19,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-ovs-interface.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-ovs-interface.h"
 #include "nm-setting-ovs-port.h"
diff --git a/libnm/nm-device-ovs-port.c b/libnm/nm-device-ovs-port.c
index 8be5549a..49cf11cc 100644
--- a/libnm/nm-device-ovs-port.c
+++ b/libnm/nm-device-ovs-port.c
@@ -19,9 +19,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-ovs-port.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-ovs-port.h"
 #include "nm-setting-ovs-port.h"
@@ -76,6 +75,7 @@ get_type_description (NMDevice *device)
 {
 	return "ovs-port";
 }
+
 static gboolean
 connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
 {
diff --git a/libnm/nm-device-team.c b/libnm/nm-device-team.c
index 101e3160..749739ff 100644
--- a/libnm/nm-device-team.c
+++ b/libnm/nm-device-team.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-team.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-team.h"
 #include "nm-utils.h"
-
-#include "nm-device-team.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
 
diff --git a/libnm/nm-device-tun.c b/libnm/nm-device-tun.c
index 2c88bf33..62460244 100644
--- a/libnm/nm-device-tun.c
+++ b/libnm/nm-device-tun.c
@@ -20,14 +20,13 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-tun.h"
+
 #include <arpa/inet.h>
 
 #include "nm-setting-connection.h"
 #include "nm-setting-tun.h"
 #include "nm-utils.h"
-
-#include "nm-device-tun.h"
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDeviceTun, nm_device_tun, NM_TYPE_DEVICE)
@@ -268,6 +267,7 @@ finalize (GObject *object)
 	NMDeviceTunPrivate *priv = NM_DEVICE_TUN_GET_PRIVATE (object);
 
 	g_free (priv->mode);
+	g_free (priv->hw_address);
 
 	G_OBJECT_CLASS (nm_device_tun_parent_class)->finalize (object);
 }
diff --git a/libnm/nm-device-vlan.c b/libnm/nm-device-vlan.c
index 5728d404..e0437245 100644
--- a/libnm/nm-device-vlan.c
+++ b/libnm/nm-device-vlan.c
@@ -20,14 +20,12 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-vlan.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-vlan.h"
 #include "nm-setting-wired.h"
 #include "nm-utils.h"
-
-#include "nm-device-vlan.h"
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDeviceVlan, nm_device_vlan, NM_TYPE_DEVICE)
diff --git a/libnm/nm-device-vxlan.c b/libnm/nm-device-vxlan.c
index 9a87ad13..8dbf1336 100644
--- a/libnm/nm-device-vxlan.c
+++ b/libnm/nm-device-vxlan.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-vxlan.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-vxlan.h"
 #include "nm-utils.h"
-
-#include "nm-device-vxlan.h"
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDeviceVxlan, nm_device_vxlan, NM_TYPE_DEVICE)
diff --git a/libnm/nm-device-wifi-p2p.c b/libnm/nm-device-wifi-p2p.c
new file mode 100644
index 00000000..01397738
--- /dev/null
+++ b/libnm/nm-device-wifi-p2p.c
@@ -0,0 +1,502 @@
+/*
+ * 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.
+ *
+ * Copyright 2018 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-device-wifi-p2p.h"
+
+#include "nm-setting-connection.h"
+#include "nm-setting-wifi-p2p.h"
+#include "nm-utils.h"
+#include "nm-wifi-p2p-peer.h"
+#include "nm-object-private.h"
+#include "nm-core-internal.h"
+#include "nm-dbus-helpers.h"
+
+#include "introspection/org.freedesktop.NetworkManager.Device.WifiP2P.h"
+
+/*****************************************************************************/
+
+typedef struct {
+	NMDeviceWifiP2P *device;
+	GSimpleAsyncResult *simple;
+} RequestScanInfo;
+
+NM_GOBJECT_PROPERTIES_DEFINE_BASE (
+	PROP_HW_ADDRESS,
+	PROP_PEERS,
+);
+
+enum {
+	PEER_ADDED,
+	PEER_REMOVED,
+
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+typedef struct {
+	NMDBusDeviceWifiP2P *proxy;
+
+	char *hw_address;
+
+	GPtrArray   *peers;
+} NMDeviceWifiP2PPrivate;
+
+/**
+ * NMDeviceWifiP2P:
+ *
+ * Since: 1.16
+ */
+struct _NMDeviceWifiP2P {
+	NMDevice parent;
+	NMDeviceWifiP2PPrivate _priv;
+};
+
+struct _NMDeviceWifiP2PClass {
+	NMDeviceClass parent;
+};
+
+G_DEFINE_TYPE (NMDeviceWifiP2P, nm_device_wifi_p2p, NM_TYPE_DEVICE)
+
+#define NM_DEVICE_WIFI_P2P_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDeviceWifiP2P, NM_IS_DEVICE_WIFI_P2P, NMDevice, NMObject)
+
+/*****************************************************************************/
+
+/**
+ * nm_device_wifi_p2p_get_hw_address:
+ * @device: a #NMDeviceWifiP2P
+ *
+ * Gets the actual hardware (MAC) address of the #NMDeviceWifiP2P
+ *
+ * Returns: the actual hardware address. This is the internal string used by the
+ * device, and must not be modified.
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_device_wifi_p2p_get_hw_address (NMDeviceWifiP2P *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI_P2P (device), NULL);
+
+	return nm_str_not_empty (NM_DEVICE_WIFI_P2P_GET_PRIVATE (device)->hw_address);
+}
+
+/**
+ * nm_device_wifi_p2p_get_peers:
+ * @device: a #NMDeviceWifiP2P
+ *
+ * Gets all the found peers of the #NMDeviceWifiP2P.
+ *
+ * Returns: (element-type NMWifiP2PPeer): a #GPtrArray containing all the
+ *          found #NMWifiP2PPeers.
+ * The returned array is owned by the client and should not be modified.
+ *
+ * Since: 1.16
+ **/
+const GPtrArray *
+nm_device_wifi_p2p_get_peers (NMDeviceWifiP2P *device)
+{
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI_P2P (device), NULL);
+
+	return NM_DEVICE_WIFI_P2P_GET_PRIVATE (device)->peers;
+}
+
+/**
+ * nm_device_wifi_p2p_get_peer_by_path:
+ * @device: a #NMDeviceWifiP2P
+ * @path: the object path of the peer
+ *
+ * Gets a #NMWifiP2PPeer by path.
+ *
+ * Returns: (transfer none): the peer or %NULL if none is found.
+ *
+ * Since: 1.16
+ **/
+NMWifiP2PPeer *
+nm_device_wifi_p2p_get_peer_by_path (NMDeviceWifiP2P *device,
+                                     const char *path)
+{
+	const GPtrArray *peers;
+	int i;
+	NMWifiP2PPeer *peer = NULL;
+
+	g_return_val_if_fail (NM_IS_DEVICE_WIFI_P2P (device), NULL);
+	g_return_val_if_fail (path != NULL, NULL);
+
+	peers = nm_device_wifi_p2p_get_peers (device);
+	if (!peers)
+		return NULL;
+
+	for (i = 0; i < peers->len; i++) {
+		NMWifiP2PPeer *candidate = g_ptr_array_index (peers, i);
+		if (!strcmp (nm_object_get_path (NM_OBJECT (candidate)), path)) {
+			peer = candidate;
+			break;
+		}
+	}
+
+	return peer;
+}
+
+static void
+start_find_finished_cb (GObject      *obj,
+                        GAsyncResult *res,
+                        gpointer user_data)
+{
+	NMDBusDeviceWifiP2P *proxy = (NMDBusDeviceWifiP2P*) obj;
+	gs_unref_object GTask *task = G_TASK (user_data);
+	GError *error = NULL;
+	gboolean success;
+
+	success = nmdbus_device_wifi_p2p_call_start_find_finish (proxy, res, &error);
+	if (!success)
+		g_task_return_error (task, error);
+	else
+		g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * nm_device_wifi_p2p_start_find:
+ * @device: a #NMDeviceWifiP2P
+ * @options: (allow-none): optional options passed to StartFind.
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: a #GAsyncReadyCallback, or %NULL
+ * @user_data: user_data for @callback
+ *
+ * Request NM to search for Wi-Fi P2P peers on @device. Note that the call
+ * returns immediately after requesting the find, and it may take some time
+ * after that for peers to be found.
+ *
+ * The find operation will run for 30s by default. You can stop it earlier
+ * using nm_device_p2p_wifi_stop_find().
+ *
+ * Since: 1.16
+ **/
+void
+nm_device_wifi_p2p_start_find (NMDeviceWifiP2P     *device,
+                               GVariant            *options,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (device);
+	GTask *task;
+
+	g_return_if_fail (NM_IS_DEVICE_WIFI_P2P (device));
+
+	task = g_task_new (device, cancellable, callback, user_data);
+
+	if (!options)
+		options = g_variant_new_array (G_VARIANT_TYPE ("{sv}"), NULL, 0);
+	nmdbus_device_wifi_p2p_call_start_find (priv->proxy,
+	                                        options,
+	                                        cancellable,
+	                                        start_find_finished_cb,
+	                                        task);
+}
+
+/**
+ * nm_device_wifi_p2p_start_find_finish:
+ * @device: a #NMDeviceWifiP2P
+ * @result: the #GAsyncResult
+ * @error: #GError return address
+ *
+ * Finish an operation started by nm_device_wifi_p2p_start_find().
+ *
+ * Returns: %TRUE if the call was successful
+ *
+ * Since: 1.16
+ **/
+gboolean
+nm_device_wifi_p2p_start_find_finish (NMDeviceWifiP2P  *device,
+                                      GAsyncResult     *result,
+                                      GError          **error)
+{
+	return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+stop_find_finished_cb (GObject      *obj,
+                       GAsyncResult *res,
+                       gpointer user_data)
+{
+	NMDBusDeviceWifiP2P *proxy = (NMDBusDeviceWifiP2P*) obj;
+	gs_unref_object GTask *task = G_TASK (user_data);
+	GError *error = NULL;
+	gboolean success;
+
+	success = nmdbus_device_wifi_p2p_call_stop_find_finish (proxy, res, &error);
+	if (!success)
+		g_task_return_error (task, error);
+	else
+		g_task_return_boolean (task, TRUE);
+}
+
+/**
+ * nm_device_wifi_p2p_stop_find:
+ * @device: a #NMDeviceWifiP2P
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: a #GAsyncReadyCallback, or %NULL
+ * @user_data: user_data for @callback
+ *
+ * Request NM to stop any ongoing find operation for Wi-Fi P2P peers on @device.
+ *
+ * Since: 1.16
+ **/
+void
+nm_device_wifi_p2p_stop_find (NMDeviceWifiP2P     *device,
+                              GCancellable        *cancellable,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (device);
+	GTask *task;
+
+	g_return_if_fail (NM_IS_DEVICE_WIFI_P2P (device));
+
+	task = g_task_new (device, cancellable, callback, user_data);
+
+	nmdbus_device_wifi_p2p_call_stop_find (priv->proxy,
+	                                       cancellable,
+	                                       stop_find_finished_cb,
+	                                       task);
+}
+
+/**
+ * nm_device_wifi_p2p_stop_find_finish:
+ * @device: a #NMDeviceWifiP2P
+ * @result: the #GAsyncResult
+ * @error: #GError return address
+ *
+ * Finish an operation started by nm_device_wifi_p2p_stop_find().
+ *
+ * Returns: %TRUE if the call was successful
+ *
+ * Since: 1.16
+ **/
+gboolean
+nm_device_wifi_p2p_stop_find_finish (NMDeviceWifiP2P  *device,
+                                      GAsyncResult     *result,
+                                      GError          **error)
+{
+	return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+clean_up_peers (NMDeviceWifiP2P *self)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (self);
+
+	while (priv->peers->len > 0) {
+		NMWifiP2PPeer *peer;
+
+		peer = priv->peers->pdata[priv->peers->len - 1];
+		g_ptr_array_remove_index (priv->peers, priv->peers->len - 1);
+
+		g_signal_emit (self, signals[PEER_REMOVED], 0, peer);
+	}
+}
+
+static gboolean
+connection_compatible (NMDevice *device, NMConnection *connection, GError **error)
+{
+	if (!NM_DEVICE_CLASS (nm_device_wifi_p2p_parent_class)->connection_compatible (device, connection, error))
+		return FALSE;
+
+	if (!nm_connection_is_type (connection, NM_SETTING_WIFI_P2P_SETTING_NAME)) {
+		g_set_error_literal (error, NM_DEVICE_ERROR, NM_DEVICE_ERROR_INCOMPATIBLE_CONNECTION,
+		                     _("The connection was not a Wi-Fi P2P connection."));
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static GType
+get_setting_type (NMDevice *device)
+{
+	return NM_TYPE_SETTING_WIRELESS;
+}
+
+static const char *
+get_hw_address (NMDevice *device)
+{
+	return nm_device_wifi_p2p_get_hw_address (NM_DEVICE_WIFI_P2P (device));
+}
+
+static const char *
+get_type_description (NMDevice *device)
+{
+	return "wifi-p2p";
+}
+
+/*****************************************************************************/
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMDeviceWifiP2P *self = NM_DEVICE_WIFI_P2P (object);
+
+	switch (prop_id) {
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_device_wifi_p2p_get_hw_address (self));
+		break;
+	case PROP_PEERS:
+		g_value_take_boxed (value, _nm_utils_copy_object_array (nm_device_wifi_p2p_get_peers (self)));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+nm_device_wifi_p2p_init (NMDeviceWifiP2P *device)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (device);
+
+	priv->peers = g_ptr_array_new ();
+}
+
+static void
+init_dbus (NMObject *object)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (object);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_DEVICE_WIFI_P2P_HW_ADDRESS,           &priv->hw_address },
+		{ NM_DEVICE_WIFI_P2P_PEERS,                &priv->peers, NULL, NM_TYPE_WIFI_P2P_PEER, "peer" },
+		{ NULL },
+	};
+
+	NM_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->init_dbus (object);
+
+	priv->proxy = NMDBUS_DEVICE_WIFI_P2P (_nm_object_get_proxy (object, NM_DBUS_INTERFACE_DEVICE_WIFI_P2P));
+	_nm_object_register_properties (object,
+	                                NM_DBUS_INTERFACE_DEVICE_WIFI_P2P,
+	                                property_info);
+}
+
+static void
+dispose (GObject *object)
+{
+	clean_up_peers (NM_DEVICE_WIFI_P2P (object));
+
+	G_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->dispose (object);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMDeviceWifiP2PPrivate *priv = NM_DEVICE_WIFI_P2P_GET_PRIVATE (object);
+
+	g_clear_object (&priv->proxy);
+	g_free (priv->hw_address);
+	if (priv->peers)
+		g_ptr_array_unref (priv->peers);
+
+	G_OBJECT_CLASS (nm_device_wifi_p2p_parent_class)->finalize (object);
+}
+
+static void
+nm_device_wifi_p2p_class_init (NMDeviceWifiP2PClass *wifi_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (wifi_class);
+	NMObjectClass *nm_object_class = NM_OBJECT_CLASS (wifi_class);
+	NMDeviceClass *device_class = NM_DEVICE_CLASS (wifi_class);
+
+	object_class->get_property = get_property;
+	object_class->dispose      = dispose;
+	object_class->finalize     = finalize;
+
+	device_class->connection_compatible = connection_compatible;
+	device_class->get_setting_type      = get_setting_type;
+	device_class->get_hw_address        = get_hw_address;
+	device_class->get_type_description  = get_type_description;
+
+	nm_object_class->init_dbus = init_dbus;
+
+	/**
+	 * NMDeviceWifiP2P:hw-address:
+	 *
+	 * The hardware (MAC) address of the device.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_HW_ADDRESS] =
+	    g_param_spec_string (NM_DEVICE_WIFI_P2P_HW_ADDRESS, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMDeviceWifiP2P:peers: (type GPtrArray(NMWifiP2PPeer))
+	 *
+	 * List of all Wi-Fi P2P peers the device can see.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_PEERS] =
+	    g_param_spec_boxed (NM_DEVICE_WIFI_P2P_PEERS, "", "",
+	                        G_TYPE_PTR_ARRAY,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+
+	/**
+	 * NMDeviceWifiP2P::peer-added:
+	 * @device: the Wi-Fi P2P device that received the signal
+	 * @peer: the new access point
+	 *
+	 * Notifies that a #NMWifiP2PPeer is added to the Wi-Fi P2P device.
+	 *
+	 * Since: 1.16
+	 **/
+	signals[PEER_ADDED] =
+	    g_signal_new ("peer-added",
+	                 G_OBJECT_CLASS_TYPE (object_class),
+	                 G_SIGNAL_RUN_FIRST,
+	                 0, NULL, NULL,
+	                 g_cclosure_marshal_VOID__OBJECT,
+	                 G_TYPE_NONE, 1,
+	                 G_TYPE_OBJECT);
+
+	/**
+	 * NMDeviceWifiP2P::peer-removed:
+	 * @device: the Wi-Fi P2P device that received the signal
+	 * @peer: the removed access point
+	 *
+	 * Notifies that a #NMWifiP2PPeer is removed from the Wi-Fi P2P device.
+	 *
+	 * Since: 1.16
+	 **/
+	signals[PEER_REMOVED] =
+	    g_signal_new ("peer-removed",
+	                 G_OBJECT_CLASS_TYPE (object_class),
+	                 G_SIGNAL_RUN_FIRST,
+	                 0, NULL, NULL,
+	                 g_cclosure_marshal_VOID__OBJECT,
+	                 G_TYPE_NONE, 1,
+	                 G_TYPE_OBJECT);
+}
diff --git a/libnm/nm-device-wifi-p2p.h b/libnm/nm-device-wifi-p2p.h
new file mode 100644
index 00000000..ddca122f
--- /dev/null
+++ b/libnm/nm-device-wifi-p2p.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ *
+ * Copyright 2018 - 2019 Red Hat, Inc.
+ */
+
+#ifndef __NM_DEVICE_WIFI_P2P_H__
+#define __NM_DEVICE_WIFI_P2P_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-device.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_DEVICE_WIFI_P2P            (nm_device_wifi_p2p_get_type ())
+#define NM_DEVICE_WIFI_P2P(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DEVICE_WIFI_P2P, NMDeviceWifiP2P))
+#define NM_DEVICE_WIFI_P2P_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DEVICE_WIFI_P2P, NMDeviceWifiP2PClass))
+#define NM_IS_DEVICE_WIFI_P2P(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DEVICE_WIFI_P2P))
+#define NM_IS_DEVICE_WIFI_P2P_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DEVICE_WIFI_P2P))
+#define NM_DEVICE_WIFI_P2P_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DEVICE_WIFI_P2P, NMDeviceWifiP2PClass))
+
+#define NM_DEVICE_WIFI_P2P_HW_ADDRESS          "hw-address"
+#define NM_DEVICE_WIFI_P2P_PEERS               "peers"
+#define NM_DEVICE_WIFI_P2P_WFDIES              "wfdies"
+
+typedef struct _NMDeviceWifiP2PClass NMDeviceWifiP2PClass;
+
+NM_AVAILABLE_IN_1_16
+GType nm_device_wifi_p2p_get_type (void);
+
+NM_AVAILABLE_IN_1_16
+const char *             nm_device_wifi_p2p_get_hw_address   (NMDeviceWifiP2P *device);
+
+NM_AVAILABLE_IN_1_16
+NMWifiP2PPeer *          nm_device_wifi_p2p_get_peer_by_path (NMDeviceWifiP2P *device,
+                                                              const char *path);
+
+NM_AVAILABLE_IN_1_16
+const GPtrArray *        nm_device_wifi_p2p_get_peers        (NMDeviceWifiP2P *device);
+
+NM_AVAILABLE_IN_1_16
+void                     nm_device_wifi_p2p_start_find        (NMDeviceWifiP2P     *device,
+                                                               GVariant            *options,
+                                                               GCancellable        *cancellable,
+                                                               GAsyncReadyCallback  callback,
+                                                               gpointer             user_data);
+NM_AVAILABLE_IN_1_16
+gboolean                 nm_device_wifi_p2p_start_find_finish (NMDeviceWifiP2P     *device,
+                                                               GAsyncResult        *result,
+                                                               GError             **error);
+
+NM_AVAILABLE_IN_1_16
+void                     nm_device_wifi_p2p_stop_find         (NMDeviceWifiP2P     *device,
+                                                               GCancellable        *cancellable,
+                                                               GAsyncReadyCallback  callback,
+                                                               gpointer             user_data);
+NM_AVAILABLE_IN_1_16
+gboolean                 nm_device_wifi_p2p_stop_find_finish  (NMDeviceWifiP2P     *device,
+                                                               GAsyncResult        *result,
+                                                               GError             **error);
+
+G_END_DECLS
+
+#endif /* __NM_DEVICE_WIFI_P2P_H__ */
diff --git a/libnm/nm-device-wifi.c b/libnm/nm-device-wifi.c
index 9fb1eebf..9af3639d 100644
--- a/libnm/nm-device-wifi.c
+++ b/libnm/nm-device-wifi.c
@@ -23,13 +23,10 @@
 
 #include "nm-device-wifi.h"
 
-#include <string.h>
-
 #include "nm-setting-connection.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wireless-security.h"
 #include "nm-utils.h"
-
 #include "nm-access-point.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
diff --git a/libnm/nm-device-wimax.c b/libnm/nm-device-wimax.c
index 08624594..36cebcf2 100644
--- a/libnm/nm-device-wimax.c
+++ b/libnm/nm-device-wimax.c
@@ -21,13 +21,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-device-wimax.h"
 
 #include "nm-setting-connection.h"
 #include "nm-setting-wimax.h"
 #include "nm-utils.h"
-
-#include "nm-device-wimax.h"
 #include "nm-wimax-nsp.h"
 #include "nm-object-private.h"
 #include "nm-core-internal.h"
diff --git a/libnm/nm-device-wpan.c b/libnm/nm-device-wpan.c
index 61183623..d6acda61 100644
--- a/libnm/nm-device-wpan.c
+++ b/libnm/nm-device-wpan.c
@@ -19,9 +19,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-device-wpan.h"
+
 #include "nm-object-private.h"
 #include "nm-setting-wpan.h"
 #include "nm-setting-connection.h"
diff --git a/libnm/nm-device.c b/libnm/nm-device.c
index 4bcd7c6c..5965cb3b 100644
--- a/libnm/nm-device.c
+++ b/libnm/nm-device.c
@@ -23,7 +23,6 @@
 
 #include "nm-device.h"
 
-#include <string.h>
 #include <libudev.h>
 
 #include "nm-libnm-utils.h"
@@ -295,6 +294,7 @@ coerce_type (NMDeviceType type)
 	case NM_DEVICE_TYPE_WPAN:
 	case NM_DEVICE_TYPE_6LOWPAN:
 	case NM_DEVICE_TYPE_WIREGUARD:
+	case NM_DEVICE_TYPE_WIFI_P2P:
 		return type;
 	}
 	return NM_DEVICE_TYPE_UNKNOWN;
@@ -356,7 +356,7 @@ get_property (GObject *object,
 
 	switch (prop_id) {
 	case PROP_DEVICE_TYPE:
-		g_value_set_enum (value, coerce_type (nm_device_get_device_type (device)));
+		g_value_set_enum (value, nm_device_get_device_type (device));
 		break;
 	case PROP_UDI:
 		g_value_set_string (value, nm_device_get_udi (device));
@@ -937,7 +937,7 @@ nm_device_get_device_type (NMDevice *self)
 {
 	g_return_val_if_fail (NM_IS_DEVICE (self), NM_DEVICE_TYPE_UNKNOWN);
 
-	return NM_DEVICE_GET_PRIVATE (self)->device_type;
+	return coerce_type (NM_DEVICE_GET_PRIVATE (self)->device_type);
 }
 
 /**
@@ -1428,6 +1428,8 @@ get_type_name (NMDevice *device)
 		return _("6LoWPAN");
 	case NM_DEVICE_TYPE_WIREGUARD:
 		return _("WireGuard");
+	case NM_DEVICE_TYPE_WIFI_P2P:
+		return _("Wi-Fi P2P");
 	case NM_DEVICE_TYPE_GENERIC:
 	case NM_DEVICE_TYPE_UNUSED1:
 	case NM_DEVICE_TYPE_UNUSED2:
@@ -2133,7 +2135,7 @@ nm_device_reapply_finish (NMDevice *device,
  * nm_device_get_applied_connection:
  * @device: a #NMDevice
  * @flags: the flags argument. Currently this value must always be zero.
- * @version_id: (out): (allow-none): returns the current version id of
+ * @version_id: (out) (allow-none): returns the current version id of
  *   the applied connection
  * @cancellable: a #GCancellable, or %NULL
  * @error: location for a #GError, or %NULL
@@ -2267,7 +2269,7 @@ nm_device_get_applied_connection_async  (NMDevice *device,
  * nm_device_get_applied_connection_finish:
  * @device: a #NMDevice
  * @result: the result passed to the #GAsyncReadyCallback
- * @version_id: (out): (allow-none): the current version id of the applied
+ * @version_id: (out) (allow-none): the current version id of the applied
  *   connection.
  * @error: location for a #GError, or %NULL
  *
diff --git a/libnm/nm-dhcp-config.c b/libnm/nm-dhcp-config.c
index 3f835670..e13bbd34 100644
--- a/libnm/nm-dhcp-config.c
+++ b/libnm/nm-dhcp-config.c
@@ -21,9 +21,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-dhcp-config.h"
+
 #include "nm-dhcp4-config.h"
 #include "nm-dhcp6-config.h"
 #include "nm-dbus-interface.h"
diff --git a/libnm/nm-dhcp4-config.c b/libnm/nm-dhcp4-config.c
index 0e783576..b01e1677 100644
--- a/libnm/nm-dhcp4-config.c
+++ b/libnm/nm-dhcp4-config.c
@@ -21,6 +21,7 @@
 #include "nm-default.h"
 
 #include "nm-dhcp4-config.h"
+
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDhcp4Config, nm_dhcp4_config, NM_TYPE_DHCP_CONFIG)
diff --git a/libnm/nm-dhcp6-config.c b/libnm/nm-dhcp6-config.c
index 9252e734..03dbcc30 100644
--- a/libnm/nm-dhcp6-config.c
+++ b/libnm/nm-dhcp6-config.c
@@ -21,6 +21,7 @@
 #include "nm-default.h"
 
 #include "nm-dhcp6-config.h"
+
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMDhcp6Config, nm_dhcp6_config, NM_TYPE_DHCP_CONFIG)
diff --git a/libnm/nm-dns-manager.c b/libnm/nm-dns-manager.c
index 37117b72..a3c2bba3 100644
--- a/libnm/nm-dns-manager.c
+++ b/libnm/nm-dns-manager.c
@@ -22,11 +22,8 @@
 
 #include "nm-dns-manager.h"
 
-#include <string.h>
-
 #include "nm-dbus-interface.h"
 #include "nm-connection.h"
-
 #include "nm-client.h"
 #include "nm-object-private.h"
 #include "nm-dbus-helpers.h"
diff --git a/libnm/nm-ip-config.c b/libnm/nm-ip-config.c
index c1e888be..618b05f1 100644
--- a/libnm/nm-ip-config.c
+++ b/libnm/nm-ip-config.c
@@ -21,9 +21,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-ip-config.h"
+
 #include "nm-ip4-config.h"
 #include "nm-ip6-config.h"
 #include "nm-setting-ip-config.h"
diff --git a/libnm/nm-ip4-config.c b/libnm/nm-ip4-config.c
index 322ea4e8..ac16ef6a 100644
--- a/libnm/nm-ip4-config.c
+++ b/libnm/nm-ip4-config.c
@@ -21,6 +21,7 @@
 #include "nm-default.h"
 
 #include "nm-ip4-config.h"
+
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMIP4Config, nm_ip4_config, NM_TYPE_IP_CONFIG)
diff --git a/libnm/nm-ip6-config.c b/libnm/nm-ip6-config.c
index 93cdf332..773faf6a 100644
--- a/libnm/nm-ip6-config.c
+++ b/libnm/nm-ip6-config.c
@@ -21,6 +21,7 @@
 #include "nm-default.h"
 
 #include "nm-ip6-config.h"
+
 #include "nm-object-private.h"
 
 G_DEFINE_TYPE (NMIP6Config, nm_ip6_config, NM_TYPE_IP_CONFIG)
diff --git a/libnm/nm-manager.c b/libnm/nm-manager.c
index 3254d4a0..7a169863 100644
--- a/libnm/nm-manager.c
+++ b/libnm/nm-manager.c
@@ -23,8 +23,6 @@
 
 #include "nm-manager.h"
 
-#include <string.h>
-
 #include "nm-utils.h"
 #include "nm-checkpoint.h"
 #include "nm-common-macros.h"
@@ -312,6 +310,8 @@ nm_permission_to_client (const char *nm)
 		return NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS;
 	else if (!strcmp (nm, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK))
 		return NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
+	else if (!strcmp (nm, NM_AUTH_PERMISSION_WIFI_SCAN))
+		return NM_CLIENT_PERMISSION_WIFI_SCAN;
 
 	return NM_CLIENT_PERMISSION_NONE;
 }
@@ -918,6 +918,8 @@ activate_info_complete (ActivateInfo *info,
                         NMActiveConnection *active,
                         GError *error)
 {
+	nm_assert ((!error) != (!active));
+
 	nm_clear_g_signal_handler (info->cancellable, &info->cancelled_id);
 
 	c_list_unlink_stale (&info->lst);
@@ -1118,6 +1120,10 @@ add_activate_cb (GObject *object,
 	gs_free_error GError *error = NULL;
 	gboolean success;
 
+	nm_assert (info);
+	nm_assert (!info->active_path);
+	nm_assert (!info->add_and_activate_output);
+
 	if (info->activate_type == ACTIVATE_TYPE_ADD_AND_ACTIVATE_CONNECTION) {
 		success = nmdbus_manager_call_add_and_activate_connection_finish (NMDBUS_MANAGER (object),
 		                                                                  NULL,
@@ -1209,12 +1215,12 @@ nm_manager_add_and_activate_connection_async (NMManager *manager,
 		                                                  info);
 	} else {
 		nmdbus_manager_call_add_and_activate_connection (priv->proxy,
-		                                                  dict,
-		                                                  nm_object_get_path (NM_OBJECT (device)),
-		                                                  specific_object ?: "/",
-		                                                  cancellable,
-		                                                  add_activate_cb,
-		                                                  info);
+		                                                 dict,
+		                                                 nm_object_get_path (NM_OBJECT (device)),
+		                                                 specific_object ?: "/",
+		                                                 cancellable,
+		                                                 add_activate_cb,
+		                                                 info);
 	}
 }
 
@@ -1624,7 +1630,7 @@ nm_manager_checkpoint_rollback_finish (NMManager *manager,
 	if (g_simple_async_result_propagate_error (simple, error))
 		return NULL;
 	else
-		return g_simple_async_result_get_op_res_gpointer (simple);
+		return g_hash_table_ref (g_simple_async_result_get_op_res_gpointer (simple));
 }
 
 static void
@@ -1818,6 +1824,8 @@ dispose (GObject *object)
 		priv->all_devices = NULL;
 	}
 
+	nm_clear_pointer (&priv->checkpoints, g_ptr_array_unref);
+
 	free_active_connections (manager);
 	g_clear_object (&priv->primary_connection);
 	g_clear_object (&priv->activating_connection);
diff --git a/libnm/nm-object.c b/libnm/nm-object.c
index d2ae25aa..f54dac5d 100644
--- a/libnm/nm-object.c
+++ b/libnm/nm-object.c
@@ -23,7 +23,6 @@
 
 #include "nm-object.h"
 
-#include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 
diff --git a/libnm/nm-property-docs.xml b/libnm/nm-property-docs.xml
index 31bceefb..6344f784 100644
--- a/libnm/nm-property-docs.xml
+++ b/libnm/nm-property-docs.xml
@@ -22,7 +22,7 @@
     <property name="read-only" name_upper="READ_ONLY" type="boolean" default="FALSE" description="FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." />
     <property name="secondaries" name_upper="SECONDARIES" type="array of string" default="[]" description="List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported." />
     <property name="slave-type" name_upper="SLAVE_TYPE" type="string" description="Setting name of the device type of this slave's master connection (eg, &quot;bond&quot;), or NULL if this connection is not a slave." />
-    <property name="stable-id" name_upper="STABLE_ID" type="string" description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that &quot;${DEVICE}&quot; corresponds the the interface name of the device and &quot;${MAC}&quot; is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to &quot;${CONNECTION}&quot; and uses a unique, fixed ID for the connection." />
+    <property name="stable-id" name_upper="STABLE_ID" type="string" description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that &quot;${DEVICE}&quot; corresponds to the interface name of the device and &quot;${MAC}&quot; is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to &quot;${CONNECTION}&quot; and uses a unique, fixed ID for the connection." />
     <property name="timestamp" name_upper="TIMESTAMP" type="uint64" default="0" description="The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved)." />
     <property name="type" name_upper="TYPE" type="string" description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, &quot;802-3-ethernet&quot; or &quot;802-11-wireless&quot; or &quot;bluetooth&quot;, etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, &quot;vpn&quot; or &quot;bridge&quot;, etc)." />
     <property name="uuid" name_upper="UUID" type="string" description="A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the &quot;id&quot; property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or &quot;type&quot; property changes. The UUID must be in the format &quot;2815492f-7e56-435e-b2e9-246bd7cdc664&quot; (ie, contains only hexadecimal characters and &quot;-&quot;)." />
@@ -387,6 +387,11 @@
     <property name="tos" name_upper="TOS" type="uint32" default="0" description="Specifies the TOS value to use in outgoing packets." />
     <property name="ttl" name_upper="TTL" type="uint32" default="0" description="Specifies the time-to-live value to use in outgoing packets." />
   </setting>
+  <setting name="wifi-p2p" description="Wi-Fi P2P Settings" name_upper="WIFI_P2P" >
+    <property name="peer" name_upper="PEER" type="string" description="The P2P device that should be connected to. Currently this is the only way to create or join a group." />
+    <property name="wfd-ies" name_upper="WFD_IES" type="byte array" description="The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display requires a protocol specific information element to be set in certain Wi-Fi frames. These can be specified here for the purpose of establishing a connection. This setting is only useful when implementing a Wi-Fi Display client." />
+    <property name="wps-method" name_upper="WPS_METHOD" type="uint32" default="0" description="Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use." />
+  </setting>
   <setting name="wimax" description="WiMax Settings" name_upper="WIMAX" >
     <property name="mac-address" name_upper="MAC_ADDRESS" type="byte array" description="If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1" />
     <property name="network-name" name_upper="NETWORK_NAME" type="string" description="Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1" />
@@ -407,6 +412,14 @@
     <property name="wake-on-lan" name_upper="WAKE_ON_LAN" type="uint32" default="1" description="The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable management of Wake-on-LAN in NetworkManager)." />
     <property name="wake-on-lan-password" name_upper="WAKE_ON_LAN_PASSWORD" type="string" description="If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address.  If NULL, no password will be required." />
   </setting>
+  <setting name="wireguard" description="WireGuard Ethernet Settings" name_upper="WIREGUARD" >
+    <property name="fwmark" name_upper="FWMARK" type="uint32" default="0" description="The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets." />
+    <property name="listen-port" name_upper="LISTEN_PORT" type="uint32" default="0" description="The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up." />
+    <property name="mtu" name_upper="MTU" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation." />
+    <property name="peer-routes" name_upper="PEER_ROUTES" type="boolean" default="TRUE" description="Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively." />
+    <property name="private-key" name_upper="PRIVATE_KEY" type="string" description="The 256 bit private-key in base64 encoding." />
+    <property name="private-key-flags" name_upper="PRIVATE_KEY_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;private-key&quot; property." />
+  </setting>
   <setting name="802-11-wireless" description="Wi-Fi Settings" name_upper="WIRELESS" >
     <property name="band" name_upper="BAND" type="string" description="802.11 frequency band of the network.  One of &quot;a&quot; for 5GHz 802.11a or &quot;bg&quot; for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network to the specific band, i.e. if &quot;a&quot; is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible.  This setting depends on specific driver capability and may not work with all drivers." />
     <property name="bssid" name_upper="BSSID" type="byte array" description="If specified, directs the device to only associate with the given access point.  This capability is highly driver dependent and not supported by all devices.  Note: this property does not control the BSSID used when creating an Ad-Hoc network and is unlikely to in the future." />
@@ -430,14 +443,14 @@
     <property name="auth-alg" name_upper="AUTH_ALG" type="string" description="When WEP is used (ie, key-mgmt = &quot;none&quot; or &quot;ieee8021x&quot;) indicate the 802.11 authentication algorithm required by the AP here.  One of &quot;open&quot; for Open System, &quot;shared&quot; for Shared Key, or &quot;leap&quot; for Cisco LEAP.  When using Cisco LEAP (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;) the &quot;leap-username&quot; and &quot;leap-password&quot; properties must be specified." />
     <property name="fils" name_upper="FILS" type="int32" default="0" description="Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled." />
     <property name="group" name_upper="GROUP" type="array of string" default="[]" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list.  For maximum compatibility leave this property empty.  Each list element may be one of &quot;wep40&quot;, &quot;wep104&quot;, &quot;tkip&quot;, or &quot;ccmp&quot;." />
-    <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection.  One of &quot;none&quot; (WEP), &quot;ieee8021x&quot; (Dynamic WEP), &quot;wpa-none&quot; (Ad-Hoc WPA-PSK), &quot;wpa-psk&quot; (infrastructure WPA-PSK), or &quot;wpa-eap&quot; (WPA-Enterprise).  This property must be set for any Wi-Fi connection that uses security." />
+    <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection.  One of &quot;none&quot; (WEP), &quot;ieee8021x&quot; (Dynamic WEP), &quot;wpa-none&quot; (Ad-Hoc WPA-PSK), &quot;wpa-psk&quot; (infrastructure WPA-PSK), &quot;sae&quot; (SAE) or &quot;wpa-eap&quot; (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." />
     <property name="leap-password" name_upper="LEAP_PASSWORD" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;)." />
     <property name="leap-password-flags" name_upper="LEAP_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;leap-password&quot; property." />
     <property name="leap-username" name_upper="LEAP_USERNAME" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;)." />
     <property name="pairwise" name_upper="PAIRWISE" type="array of string" default="[]" description="A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty.  Each list element may be one of &quot;tkip&quot; or &quot;ccmp&quot;." />
     <property name="pmf" name_upper="PMF" type="int32" default="0" description="Indicates whether Protected Management Frames (802.11w) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled." />
     <property name="proto" name_upper="PROTO" type="array of string" default="[]" description="List of strings specifying the allowed WPA protocol versions to use. Each element may be one &quot;wpa&quot; (allow WPA) or &quot;rsn&quot; (allow WPA2/RSN).  If not specified, both WPA and RSN connections are allowed." />
-    <property name="psk" name_upper="PSK" type="string" description="Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network." />
+    <property name="psk" name_upper="PSK" type="string" description="Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII passphrase of 8 to 63 characters that is (as specified in the 802.11i standard) hashed to derive the actual key, or the key in form of 64 hexadecimal character. The WPA3-Personal networks use a passphrase of any length for SAE authentication." />
     <property name="psk-flags" name_upper="PSK_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;psk&quot; property." />
     <property name="wep-key-flags" name_upper="WEP_KEY_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;wep-key0&quot;, &quot;wep-key1&quot;, &quot;wep-key2&quot;, and &quot;wep-key3&quot; properties." />
     <property name="wep-key-type" name_upper="WEP_KEY_TYPE" type="NMWepKeyType (uint32)" description="Controls the interpretation of WEP keys.  Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key." />
diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c
index 08faa77e..a011ca87 100644
--- a/libnm/nm-remote-connection.c
+++ b/libnm/nm-remote-connection.c
@@ -21,14 +21,12 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-remote-connection.h"
 
 #include "nm-dbus-interface.h"
 #include "nm-utils.h"
 #include "nm-setting-connection.h"
 #include "nm-core-internal.h"
-
-#include "nm-remote-connection.h"
 #include "nm-remote-connection-private.h"
 #include "nm-object-private.h"
 #include "nm-dbus-helpers.h"
diff --git a/libnm/nm-remote-settings.c b/libnm/nm-remote-settings.c
index f2b26215..6b2d6e92 100644
--- a/libnm/nm-remote-settings.c
+++ b/libnm/nm-remote-settings.c
@@ -23,11 +23,8 @@
 
 #include "nm-remote-settings.h"
 
-#include <string.h>
-
 #include "nm-dbus-interface.h"
 #include "nm-connection.h"
-
 #include "nm-client.h"
 #include "nm-remote-connection.h"
 #include "nm-remote-connection-private.h"
diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c
index 1b9e8915..56a88b00 100644
--- a/libnm/nm-secret-agent-old.c
+++ b/libnm/nm-secret-agent-old.c
@@ -20,55 +20,63 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-secret-agent-old.h"
 
 #include "nm-dbus-interface.h"
-#include "nm-secret-agent-old.h"
 #include "nm-enum-types.h"
 #include "nm-dbus-helpers.h"
 #include "nm-simple-connection.h"
 #include "nm-core-internal.h"
+#include "c-list/src/c-list.h"
 
 #include "introspection/org.freedesktop.NetworkManager.SecretAgent.h"
 #include "introspection/org.freedesktop.NetworkManager.AgentManager.h"
 
-static void nm_secret_agent_old_initable_iface_init (GInitableIface *iface);
-static void nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface);
-G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_OBJECT,
-                                  G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_secret_agent_old_initable_iface_init);
-                                  G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_secret_agent_old_async_initable_iface_init);
-                                  )
-
-#define NM_SECRET_AGENT_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate))
+/*****************************************************************************/
 
 typedef struct {
-	gboolean registered;
-	gboolean registering;
-	NMSecretAgentCapabilities capabilities;
+	char *path;
+	char *setting_name;
+	GDBusMethodInvocation *context;
+	CList gsi_lst;
+} GetSecretsInfo;
 
+NM_GOBJECT_PROPERTIES_DEFINE (NMSecretAgentOld,
+	PROP_IDENTIFIER,
+	PROP_AUTO_REGISTER,
+	PROP_REGISTERED,
+	PROP_CAPABILITIES,
+);
+
+typedef struct {
 	GDBusConnection *bus;
-	gboolean private_bus;
-	gboolean session_bus;
 	NMDBusAgentManager *manager_proxy;
 	NMDBusSecretAgent *dbus_secret_agent;
 
 	/* GetSecretsInfo structs of in-flight GetSecrets requests */
-	GSList *pending_gets;
+	CList gsi_lst_head;
 
 	char *identifier;
-	gboolean auto_register;
-	gboolean suppress_auto;
+
+	NMSecretAgentCapabilities capabilities;
+
+	bool registered:1;
+	bool registering:1;
+	bool private_bus:1;
+	bool session_bus:1;
+	bool auto_register:1;
+	bool suppress_auto:1;
 } NMSecretAgentOldPrivate;
 
-enum {
-	PROP_0,
-	PROP_IDENTIFIER,
-	PROP_AUTO_REGISTER,
-	PROP_REGISTERED,
-	PROP_CAPABILITIES,
+static void nm_secret_agent_old_initable_iface_init (GInitableIface *iface);
+static void nm_secret_agent_old_async_initable_iface_init (GAsyncInitableIface *iface);
 
-	LAST_PROP
-};
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMSecretAgentOld, nm_secret_agent_old, G_TYPE_OBJECT,
+                                  G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, nm_secret_agent_old_initable_iface_init);
+                                  G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, nm_secret_agent_old_async_initable_iface_init);
+                                  )
+
+#define NM_SECRET_AGENT_OLD_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SECRET_AGENT_OLD, NMSecretAgentOldPrivate))
 
 /*****************************************************************************/
 
@@ -81,32 +89,23 @@ _internal_unregister (NMSecretAgentOld *self)
 		g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (priv->dbus_secret_agent));
 		priv->registered = FALSE;
 		priv->registering = FALSE;
-		g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
+		_notify (self, PROP_REGISTERED);
 	}
 }
 
-typedef struct {
-	char *path;
-	char *setting_name;
-	GDBusMethodInvocation *context;
-} GetSecretsInfo;
-
 static void
-get_secrets_info_finalize (NMSecretAgentOld *self, GetSecretsInfo *info)
+get_secrets_info_free (GetSecretsInfo *info)
 {
-	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-
-	g_return_if_fail (info != NULL);
+	nm_assert (info);
 
-	priv->pending_gets = g_slist_remove (priv->pending_gets, info);
+	c_list_unlink_stale (&info->gsi_lst);
 
 	g_free (info->path);
 	g_free (info->setting_name);
-	memset (info, 0, sizeof (*info));
-	g_free (info);
+	g_slice_free (GetSecretsInfo, info);
 }
 
-static inline gboolean
+static gboolean
 should_auto_register (NMSecretAgentOld *self)
 {
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
@@ -124,25 +123,20 @@ name_owner_changed (GObject *proxy,
 {
 	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (user_data);
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-	GSList *iter;
-	char *owner;
+	gs_free char *owner = NULL;
+	GetSecretsInfo *info;
 
 	owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (proxy));
-	if (owner != NULL) {
+	if (owner) {
 		if (should_auto_register (self))
 			nm_secret_agent_old_register_async (self, NULL, NULL, NULL);
-		g_free (owner);
 	} else {
-		/* Cancel any pending secrets requests */
-		for (iter = priv->pending_gets; iter; iter = g_slist_next (iter)) {
-			GetSecretsInfo *info = iter->data;
-
+		while ((info = c_list_first_entry (&priv->gsi_lst_head, GetSecretsInfo, gsi_lst))) {
+			c_list_unlink (&info->gsi_lst);
 			NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self,
-			                                                      info->path,
-			                                                      info->setting_name);
+			                                                          info->path,
+			                                                          info->setting_name);
 		}
-		g_slist_free (priv->pending_gets);
-		priv->pending_gets = NULL;
 
 		_internal_unregister (self);
 	}
@@ -154,11 +148,11 @@ verify_sender (NMSecretAgentOld *self,
                GError **error)
 {
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-	char *nm_owner;
+	gs_free char *owner = NULL;
 	const char *sender;
 	guint32 sender_uid;
-	GVariant *ret;
-	GError *local = NULL;
+	gs_unref_variant GVariant *ret = NULL;
+	gs_free_error GError *local = NULL;
 
 	g_return_val_if_fail (context != NULL, FALSE);
 
@@ -170,8 +164,8 @@ verify_sender (NMSecretAgentOld *self,
 
 	/* Verify that the sender is the same as NetworkManager's bus name owner. */
 
-	nm_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy));
-	if (!nm_owner) {
+	owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy));
+	if (!owner) {
 		g_set_error_literal (error,
 		                     NM_SECRET_AGENT_ERROR,
 		                     NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
@@ -185,20 +179,16 @@ verify_sender (NMSecretAgentOld *self,
 		                     NM_SECRET_AGENT_ERROR,
 		                     NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
 		                     "Failed to get request sender.");
-		g_free (nm_owner);
 		return FALSE;
 	}
 
-	/* Check that the sender matches the current NM bus name owner */
-	if (strcmp (sender, nm_owner) != 0) {
+	if (!nm_streq (sender, owner)) {
 		g_set_error_literal (error,
 		                     NM_SECRET_AGENT_ERROR,
 		                     NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
 		                     "Request sender does not match NetworkManager bus name owner.");
-		g_free (nm_owner);
 		return FALSE;
 	}
-	g_free (nm_owner);
 
 	/* If we're connected to the session bus, then this must be a test program,
 	 * so skip the UID check.
@@ -217,8 +207,9 @@ verify_sender (NMSecretAgentOld *self,
 	                                   G_DBUS_CALL_FLAGS_NONE, -1,
 	                                   NULL, &local);
 	if (!ret) {
-		char *remote_error = g_dbus_error_get_remote_error (local);
+		gs_free char *remote_error = NULL;
 
+		remote_error = g_dbus_error_get_remote_error (local);
 		g_dbus_error_strip_remote_error (local);
 		g_set_error (error,
 		             NM_SECRET_AGENT_ERROR,
@@ -226,15 +217,12 @@ verify_sender (NMSecretAgentOld *self,
 		             "Failed to request unix user: (%s) %s.",
 		             remote_error ?: "",
 		             local->message);
-		g_free (remote_error);
-		g_error_free (local);
 		return FALSE;
 	}
 	g_variant_get (ret, "(u)", &sender_uid);
-	g_variant_unref (ret);
 
 	/* We only accept requests from NM, which always runs as root */
-	if (0 != sender_uid) {
+	if (sender_uid != 0) {
 		g_set_error_literal (error,
 		                     NM_SECRET_AGENT_ERROR,
 		                     NM_SECRET_AGENT_ERROR_PERMISSION_DENIED,
@@ -253,8 +241,8 @@ verify_request (NMSecretAgentOld *self,
                 NMConnection **out_connection,
                 GError **error)
 {
-	NMConnection *connection = NULL;
-	GError *local = NULL;
+	gs_unref_object NMConnection *connection = NULL;
+	gs_free_error GError *local = NULL;
 
 	if (!verify_sender (self, context, error))
 		return FALSE;
@@ -273,20 +261,18 @@ verify_request (NMSecretAgentOld *self,
 	}
 
 	/* Make sure the given connection is valid */
-	g_assert (out_connection);
 	connection = _nm_simple_connection_new_from_dbus (connection_dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &local);
-	if (connection) {
-		nm_connection_set_path (connection, connection_path);
-		*out_connection = connection;
-	} else {
+	if (!connection) {
 		g_set_error (error,
 		             NM_SECRET_AGENT_ERROR,
 		             NM_SECRET_AGENT_ERROR_INVALID_CONNECTION,
 		             "Invalid connection: %s", local->message);
-		g_clear_error (&local);
+		return FALSE;
 	}
 
-	return !!connection;
+	nm_connection_set_path (connection, connection_path);
+	NM_SET_OUT (out_connection, g_steal_pointer (&connection));
+	return TRUE;
 }
 
 static void
@@ -306,8 +292,7 @@ get_secrets_cb (NMSecretAgentOld *self,
 		                                       g_variant_new ("(@a{sa{sv}})", secrets));
 	}
 
-	/* Remove the request from internal tracking */
-	get_secrets_info_finalize (self, info);
+	get_secrets_info_free (info);
 }
 
 static void
@@ -322,7 +307,7 @@ impl_secret_agent_old_get_secrets (NMSecretAgentOld *self,
 {
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
 	GError *error = NULL;
-	NMConnection *connection = NULL;
+	gs_unref_object NMConnection *connection = NULL;
 	GetSecretsInfo *info;
 
 	/* Make sure the request comes from NetworkManager and is valid */
@@ -331,34 +316,35 @@ impl_secret_agent_old_get_secrets (NMSecretAgentOld *self,
 		return;
 	}
 
-	info = g_malloc0 (sizeof (GetSecretsInfo));
-	info->path = g_strdup (connection_path);
-	info->setting_name = g_strdup (setting_name);
-	info->context = context;
-	priv->pending_gets = g_slist_append (priv->pending_gets, info);
+	info = g_slice_new (GetSecretsInfo);
+	*info = (GetSecretsInfo) {
+		.path = g_strdup (connection_path),
+		.setting_name = g_strdup (setting_name),
+		.context = context,
+	};
+	c_list_link_tail (&priv->gsi_lst_head, &info->gsi_lst);
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self,
-	                                               connection,
-	                                               connection_path,
-	                                               setting_name,
-	                                               (const char **) hints,
-	                                               flags,
-	                                               get_secrets_cb,
-	                                               info);
-	g_object_unref (connection);
+	                                                   connection,
+	                                                   connection_path,
+	                                                   setting_name,
+	                                                   (const char **) hints,
+	                                                   flags,
+	                                                   get_secrets_cb,
+	                                                   info);
 }
 
 static GetSecretsInfo *
-find_get_secrets_info (GSList *list, const char *path, const char *setting_name)
+find_get_secrets_info (NMSecretAgentOldPrivate *priv,
+                       const char *path,
+                       const char *setting_name)
 {
-	GSList *iter;
-
-	for (iter = list; iter; iter = g_slist_next (iter)) {
-		GetSecretsInfo *candidate = iter->data;
+	GetSecretsInfo *info;
 
-		if (   g_strcmp0 (path, candidate->path) == 0
-		    && g_strcmp0 (setting_name, candidate->setting_name) == 0)
-			return candidate;
+	c_list_for_each_entry (info, &priv->gsi_lst_head, gsi_lst) {
+		if (   nm_streq0 (path, info->path)
+		    && nm_streq0 (setting_name, info->setting_name))
+			return info;
 	}
 	return NULL;
 }
@@ -380,7 +366,7 @@ impl_secret_agent_old_cancel_get_secrets (NMSecretAgentOld *self,
 		return;
 	}
 
-	info = find_get_secrets_info (priv->pending_gets, connection_path, setting_name);
+	info = find_get_secrets_info (priv, connection_path, setting_name);
 	if (!info) {
 		g_dbus_method_invocation_return_error (context,
 		                                       NM_SECRET_AGENT_ERROR,
@@ -389,10 +375,12 @@ impl_secret_agent_old_cancel_get_secrets (NMSecretAgentOld *self,
 		return;
 	}
 
-	/* Send the cancel request up to the subclass and finalize it */
+	c_list_unlink (&info->gsi_lst);
+
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->cancel_get_secrets (self,
-	                                                      info->path,
-	                                                      info->setting_name);
+	                                                          info->path,
+	                                                          info->setting_name);
+
 	g_dbus_method_invocation_return_value (context, NULL);
 }
 
@@ -417,8 +405,8 @@ impl_secret_agent_old_save_secrets (NMSecretAgentOld *self,
                                     const char *connection_path,
                                     gpointer user_data)
 {
+	gs_unref_object NMConnection *connection = NULL;
 	GError *error = NULL;
-	NMConnection *connection = NULL;
 
 	/* Make sure the request comes from NetworkManager and is valid */
 	if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) {
@@ -427,11 +415,10 @@ impl_secret_agent_old_save_secrets (NMSecretAgentOld *self,
 	}
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self,
-	                                                connection,
-	                                                connection_path,
-	                                                save_secrets_cb,
-	                                                context);
-	g_object_unref (connection);
+	                                                    connection,
+	                                                    connection_path,
+	                                                    save_secrets_cb,
+	                                                    context);
 }
 
 static void
@@ -455,8 +442,8 @@ impl_secret_agent_old_delete_secrets (NMSecretAgentOld *self,
                                       const char *connection_path,
                                       gpointer user_data)
 {
+	gs_unref_object NMConnection *connection = NULL;
 	GError *error = NULL;
-	NMConnection *connection = NULL;
 
 	/* Make sure the request comes from NetworkManager and is valid */
 	if (!verify_request (self, context, connection_dict, connection_path, &connection, &error)) {
@@ -465,11 +452,10 @@ impl_secret_agent_old_delete_secrets (NMSecretAgentOld *self,
 	}
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self,
-	                                                  connection,
-	                                                  connection_path,
-	                                                  delete_secrets_cb,
-	                                                  context);
-	g_object_unref (connection);
+	                                                      connection,
+	                                                      connection_path,
+	                                                      delete_secrets_cb,
+	                                                      context);
 }
 
 /*****************************************************************************/
@@ -478,15 +464,13 @@ static gboolean
 check_nm_running (NMSecretAgentOld *self, GError **error)
 {
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-	char *owner;
+	gs_free char *owner = NULL;
 
 	if (priv->private_bus)
 		return TRUE;
 	owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (priv->manager_proxy));
-	if (owner) {
-		g_free (owner);
+	if (owner)
 		return TRUE;
-	}
 
 	g_set_error (error, NM_SECRET_AGENT_ERROR, NM_SECRET_AGENT_ERROR_FAILED,
 	             "NetworkManager is not running");
@@ -568,7 +552,7 @@ nm_secret_agent_old_register (NMSecretAgentOld *self,
 success:
 	priv->registering = FALSE;
 	priv->registered = TRUE;
-	g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
+	_notify (self, PROP_REGISTERED);
 	return TRUE;
 }
 
@@ -576,6 +560,7 @@ static void
 reg_result (NMSecretAgentOld *self, GSimpleAsyncResult *simple, GError *error)
 {
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
+	_nm_unused gs_unref_object GSimpleAsyncResult *simple_free = simple;
 
 	priv->registering = FALSE;
 
@@ -587,13 +572,11 @@ reg_result (NMSecretAgentOld *self, GSimpleAsyncResult *simple, GError *error)
 		_internal_unregister (self);
 	} else {
 		priv->registered = TRUE;
-		g_object_notify (G_OBJECT (self), NM_SECRET_AGENT_OLD_REGISTERED);
+		_notify (self, PROP_REGISTERED);
 
 		g_simple_async_result_set_op_res_gboolean (simple, TRUE);
 		g_simple_async_result_complete (simple);
 	}
-
-	g_object_unref (simple);
 }
 
 static void
@@ -624,6 +607,7 @@ reg_with_caps_cb (GObject *proxy,
 
 	self = NM_SECRET_AGENT_OLD (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
 	g_object_unref (self); /* drop extra ref added by get_source_object() */
+
 	priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
 
 	if (nmdbus_agent_manager_call_register_with_capabilities_finish (NMDBUS_AGENT_MANAGER (proxy), result, NULL)) {
@@ -661,7 +645,7 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self,
 {
 	NMSecretAgentOldPrivate *priv;
 	NMSecretAgentOldClass *class;
-	GSimpleAsyncResult *simple;
+	gs_unref_object GSimpleAsyncResult *simple = NULL;
 	GError *error = NULL;
 
 	g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
@@ -687,7 +671,6 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self,
 	if (!check_nm_running (self, &error)) {
 		g_simple_async_result_take_error (simple, error);
 		g_simple_async_result_complete_in_idle (simple);
-		g_object_unref (simple);
 		return;
 	}
 
@@ -698,7 +681,6 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self,
 	                                       &error)) {
 		g_simple_async_result_take_error (simple, error);
 		g_simple_async_result_complete_in_idle (simple);
-		g_object_unref (simple);
 		return;
 	}
 
@@ -709,7 +691,8 @@ nm_secret_agent_old_register_async (NMSecretAgentOld *self,
 	                                                      priv->identifier,
 	                                                      priv->capabilities,
 	                                                      NULL,
-	                                                      reg_with_caps_cb, simple);
+	                                                      reg_with_caps_cb,
+	                                                      g_steal_pointer (&simple));
 }
 
 /**
@@ -775,7 +758,7 @@ nm_secret_agent_old_unregister (NMSecretAgentOld *self,
 static void
 unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
 {
-	GSimpleAsyncResult *simple = user_data;
+	gs_unref_object GSimpleAsyncResult *simple = user_data;
 	NMSecretAgentOld *self;
 	GError *error = NULL;
 
@@ -793,7 +776,6 @@ unregister_cb (GObject *proxy, GAsyncResult *result, gpointer user_data)
 	}
 
 	g_simple_async_result_complete (simple);
-	g_object_unref (simple);
 }
 
 /**
@@ -814,7 +796,7 @@ nm_secret_agent_old_unregister_async (NMSecretAgentOld *self,
                                       gpointer user_data)
 {
 	NMSecretAgentOldPrivate *priv;
-	GSimpleAsyncResult *simple;
+	gs_unref_object GSimpleAsyncResult *simple = NULL;
 	GError *error = NULL;
 
 	g_return_if_fail (NM_IS_SECRET_AGENT_OLD (self));
@@ -832,14 +814,15 @@ nm_secret_agent_old_unregister_async (NMSecretAgentOld *self,
 	if (!check_nm_running (self, &error)) {
 		g_simple_async_result_take_error (simple, error);
 		g_simple_async_result_complete_in_idle (simple);
-		g_object_unref (simple);
 		return;
 	}
 
 	priv->suppress_auto = TRUE;
 
-	nmdbus_agent_manager_call_unregister (priv->manager_proxy, cancellable,
-	                                      unregister_cb, simple);
+	nmdbus_agent_manager_call_unregister (priv->manager_proxy,
+	                                      cancellable,
+	                                      unregister_cb,
+	                                      g_steal_pointer (&simple));
 }
 
 /**
@@ -916,13 +899,13 @@ nm_secret_agent_old_get_secrets (NMSecretAgentOld *self,
 	g_return_if_fail (callback != NULL);
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->get_secrets (self,
-	                                               connection,
-	                                               nm_connection_get_path (connection),
-	                                               setting_name,
-	                                               hints,
-	                                               flags,
-	                                               callback,
-	                                               user_data);
+	                                                   connection,
+	                                                   nm_connection_get_path (connection),
+	                                                   setting_name,
+	                                                   hints,
+	                                                   flags,
+	                                                   callback,
+	                                                   user_data);
 }
 
 /**
@@ -946,10 +929,10 @@ nm_secret_agent_old_save_secrets (NMSecretAgentOld *self,
 	g_return_if_fail (nm_connection_get_path (connection));
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->save_secrets (self,
-	                                                connection,
-	                                                nm_connection_get_path (connection),
-	                                                callback,
-	                                                user_data);
+	                                                    connection,
+	                                                    nm_connection_get_path (connection),
+	                                                    callback,
+	                                                    user_data);
 }
 
 /**
@@ -973,10 +956,10 @@ nm_secret_agent_old_delete_secrets (NMSecretAgentOld *self,
 	g_return_if_fail (nm_connection_get_path (connection));
 
 	NM_SECRET_AGENT_OLD_GET_CLASS (self)->delete_secrets (self,
-	                                                  connection,
-	                                                  nm_connection_get_path (connection),
-	                                                  callback,
-	                                                  user_data);
+	                                                      connection,
+	                                                      nm_connection_get_path (connection),
+	                                                      callback,
+	                                                      user_data);
 }
 
 /*****************************************************************************/
@@ -1007,20 +990,7 @@ validate_identifier (const char *identifier)
 	return TRUE;
 }
 
-static void
-nm_secret_agent_old_init (NMSecretAgentOld *self)
-{
-	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-
-	priv->dbus_secret_agent = nmdbus_secret_agent_skeleton_new ();
-	_nm_dbus_bind_properties (self, priv->dbus_secret_agent);
-	_nm_dbus_bind_methods (self, priv->dbus_secret_agent,
-	                       "GetSecrets", impl_secret_agent_old_get_secrets,
-	                       "CancelGetSecrets", impl_secret_agent_old_cancel_get_secrets,
-	                       "DeleteSecrets", impl_secret_agent_old_delete_secrets,
-	                       "SaveSecrets", impl_secret_agent_old_save_secrets,
-	                       NULL);
-}
+/*****************************************************************************/
 
 static void
 init_common (NMSecretAgentOld *self)
@@ -1037,42 +1007,14 @@ init_common (NMSecretAgentOld *self)
 	}
 }
 
-static gboolean
-init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
-{
-	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
-	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
-
-	priv->bus = _nm_dbus_new_connection (cancellable, error);
-	if (!priv->bus)
-		return FALSE;
-
-	priv->manager_proxy = nmdbus_agent_manager_proxy_new_sync (priv->bus,
-	                                                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-	                                                           | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
-	                                                           NM_DBUS_SERVICE,
-	                                                           NM_DBUS_PATH_AGENT_MANAGER,
-	                                                           cancellable,
-	                                                           error);
-	if (!priv->manager_proxy)
-		return FALSE;
-
-	init_common (self);
-
-	if (priv->auto_register)
-		return nm_secret_agent_old_register (self, cancellable, error);
-	else
-		return TRUE;
-}
-
 typedef struct {
 	NMSecretAgentOld *self;
 	GCancellable *cancellable;
 	GSimpleAsyncResult *simple;
-} NMSecretAgentOldInitData;
+} InitData;
 
 static void
-init_async_complete (NMSecretAgentOldInitData *init_data, GError *error)
+init_async_complete (InitData *init_data, GError *error)
 {
 	if (!error)
 		g_simple_async_result_set_op_res_gboolean (init_data->simple, TRUE);
@@ -1083,14 +1025,14 @@ init_async_complete (NMSecretAgentOldInitData *init_data, GError *error)
 
 	g_object_unref (init_data->simple);
 	g_clear_object (&init_data->cancellable);
-	g_slice_free (NMSecretAgentOldInitData, init_data);
+	g_slice_free (InitData, init_data);
 }
 
 static void
 init_async_registered (GObject *object, GAsyncResult *result, gpointer user_data)
 {
 	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object);
-	NMSecretAgentOldInitData *init_data = user_data;
+	InitData *init_data = user_data;
 	GError *error = NULL;
 
 	nm_secret_agent_old_register_finish (self, result, &error);
@@ -1100,7 +1042,7 @@ init_async_registered (GObject *object, GAsyncResult *result, gpointer user_data
 static void
 init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data)
 {
-	NMSecretAgentOldInitData *init_data = user_data;
+	InitData *init_data = user_data;
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self);
 	GError *error = NULL;
 
@@ -1122,7 +1064,7 @@ init_async_got_proxy (GObject *object, GAsyncResult *result, gpointer user_data)
 static void
 init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data)
 {
-	NMSecretAgentOldInitData *init_data = user_data;
+	InitData *init_data = user_data;
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (init_data->self);
 	GError *error = NULL;
 
@@ -1141,36 +1083,7 @@ init_async_got_bus (GObject *initable, GAsyncResult *result, gpointer user_data)
 	                                init_async_got_proxy, init_data);
 }
 
-static void
-init_async (GAsyncInitable *initable, int io_priority,
-            GCancellable *cancellable, GAsyncReadyCallback callback,
-            gpointer user_data)
-{
-	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
-	NMSecretAgentOldInitData *init_data;
-
-	init_data = g_slice_new (NMSecretAgentOldInitData);
-	init_data->self = self;
-	init_data->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-
-	init_data->simple = g_simple_async_result_new (G_OBJECT (initable), callback,
-	                                               user_data, init_async);
-	if (cancellable)
-		g_simple_async_result_set_check_cancellable (init_data->simple, cancellable);
-
-	_nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data);
-}
-
-static gboolean
-init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
-{
-	GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
-	if (g_simple_async_result_propagate_error (simple, error))
-		return FALSE;
-	else
-		return TRUE;
-}
+/*****************************************************************************/
 
 static void
 get_property (GObject *object,
@@ -1229,23 +1142,109 @@ set_property (GObject *object,
 	}
 }
 
+/*****************************************************************************/
+
+static void
+nm_secret_agent_old_init (NMSecretAgentOld *self)
+{
+	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
+
+	c_list_init (&priv->gsi_lst_head);
+	priv->dbus_secret_agent = nmdbus_secret_agent_skeleton_new ();
+	_nm_dbus_bind_properties (self, priv->dbus_secret_agent);
+	_nm_dbus_bind_methods (self, priv->dbus_secret_agent,
+	                       "GetSecrets", impl_secret_agent_old_get_secrets,
+	                       "CancelGetSecrets", impl_secret_agent_old_cancel_get_secrets,
+	                       "DeleteSecrets", impl_secret_agent_old_delete_secrets,
+	                       "SaveSecrets", impl_secret_agent_old_save_secrets,
+	                       NULL);
+}
+
+static gboolean
+init_sync (GInitable *initable, GCancellable *cancellable, GError **error)
+{
+	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
+	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
+
+	priv->bus = _nm_dbus_new_connection (cancellable, error);
+	if (!priv->bus)
+		return FALSE;
+
+	priv->manager_proxy = nmdbus_agent_manager_proxy_new_sync (priv->bus,
+	                                                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
+	                                                           | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
+	                                                           NM_DBUS_SERVICE,
+	                                                           NM_DBUS_PATH_AGENT_MANAGER,
+	                                                           cancellable,
+	                                                           error);
+	if (!priv->manager_proxy)
+		return FALSE;
+
+	init_common (self);
+
+	if (priv->auto_register)
+		return nm_secret_agent_old_register (self, cancellable, error);
+	else
+		return TRUE;
+}
+
+static void
+init_async (GAsyncInitable *initable, int io_priority,
+            GCancellable *cancellable, GAsyncReadyCallback callback,
+            gpointer user_data)
+{
+	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (initable);
+	InitData *init_data;
+
+	init_data = g_slice_new (InitData);
+	*init_data = (InitData) {
+		.self = self,
+		.cancellable = nm_g_object_ref (cancellable),
+		.simple = g_simple_async_result_new (G_OBJECT (initable),
+		                                     callback,
+		                                     user_data,
+		                                     init_async),
+	};
+
+	if (cancellable)
+		g_simple_async_result_set_check_cancellable (init_data->simple, cancellable);
+
+	_nm_dbus_new_connection_async (cancellable, init_async_got_bus, init_data);
+}
+
+static gboolean
+init_finish (GAsyncInitable *initable, GAsyncResult *result, GError **error)
+{
+	GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
+
+	if (g_simple_async_result_propagate_error (simple, error))
+		return FALSE;
+	else
+		return TRUE;
+}
+
 static void
 dispose (GObject *object)
 {
 	NMSecretAgentOld *self = NM_SECRET_AGENT_OLD (object);
 	NMSecretAgentOldPrivate *priv = NM_SECRET_AGENT_OLD_GET_PRIVATE (self);
+	GetSecretsInfo *info;
 
-	if (priv->registered)
+	if (priv->registered) {
+		priv->registered = FALSE;
 		nm_secret_agent_old_unregister_async (self, NULL, NULL, NULL);
+	}
 
-	g_clear_pointer (&priv->identifier, g_free);
+	nm_clear_g_free (&priv->identifier);
 
-	while (priv->pending_gets)
-		get_secrets_info_finalize (self, priv->pending_gets->data);
+	while ((info = c_list_first_entry (&priv->gsi_lst_head, GetSecretsInfo, gsi_lst)))
+		get_secrets_info_free (info);
 
-	g_signal_handlers_disconnect_matched (priv->dbus_secret_agent, G_SIGNAL_MATCH_DATA,
-	                                      0, 0, NULL, NULL, self);
-	g_object_unref (priv->dbus_secret_agent);
+	if (priv->dbus_secret_agent) {
+		g_signal_handlers_disconnect_matched (priv->dbus_secret_agent, G_SIGNAL_MATCH_DATA,
+		                                      0, 0, NULL, NULL, self);
+		g_clear_object (&priv->dbus_secret_agent);
+	}
 
 	g_clear_object (&priv->manager_proxy);
 	g_clear_object (&priv->bus);
@@ -1260,7 +1259,6 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class)
 
 	g_type_class_add_private (class, sizeof (NMSecretAgentOldPrivate));
 
-	/* Virtual methods */
 	object_class->dispose = dispose;
 	object_class->get_property = get_property;
 	object_class->set_property = set_property;
@@ -1276,13 +1274,12 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class)
 	 * of 3 characters.  An example valid identifier is 'org.gnome.nm-applet'
 	 * (without quotes).
 	 **/
-	g_object_class_install_property
-		(object_class, PROP_IDENTIFIER,
-		 g_param_spec_string (NM_SECRET_AGENT_OLD_IDENTIFIER, "", "",
-		                      NULL,
-		                      G_PARAM_READWRITE |
-		                      G_PARAM_CONSTRUCT_ONLY |
-		                      G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_IDENTIFIER] =
+	    g_param_spec_string (NM_SECRET_AGENT_OLD_IDENTIFIER, "", "",
+	                         NULL,
+	                         G_PARAM_READWRITE |
+	                         G_PARAM_CONSTRUCT_ONLY |
+	                         G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * NMSecretAgentOld:auto-register:
@@ -1305,39 +1302,38 @@ nm_secret_agent_old_class_init (NMSecretAgentOldClass *class)
 	 * auto-registration. This ensures that the agent remains un-registered when
 	 * you expect it to be unregistered.
 	 **/
-	g_object_class_install_property
-		(object_class, PROP_AUTO_REGISTER,
-		 g_param_spec_boolean (NM_SECRET_AGENT_OLD_AUTO_REGISTER, "", "",
-		                       TRUE,
-		                       G_PARAM_READWRITE |
-		                       G_PARAM_CONSTRUCT |
-		                       G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_AUTO_REGISTER] =
+	    g_param_spec_boolean (NM_SECRET_AGENT_OLD_AUTO_REGISTER, "", "",
+	                          TRUE,
+	                          G_PARAM_READWRITE |
+	                          G_PARAM_CONSTRUCT |
+	                          G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * NMSecretAgentOld:registered:
 	 *
 	 * %TRUE if the agent is registered with NetworkManager, %FALSE if not.
 	 **/
-	g_object_class_install_property
-		(object_class, PROP_REGISTERED,
-		 g_param_spec_boolean (NM_SECRET_AGENT_OLD_REGISTERED, "", "",
-		                       FALSE,
-		                       G_PARAM_READABLE |
-		                       G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_REGISTERED] =
+	    g_param_spec_boolean (NM_SECRET_AGENT_OLD_REGISTERED, "", "",
+	                          FALSE,
+	                          G_PARAM_READABLE |
+	                          G_PARAM_STATIC_STRINGS);
 
 	/**
 	 * NMSecretAgentOld:capabilities:
 	 *
 	 * A bitfield of %NMSecretAgentCapabilities.
 	 **/
-	g_object_class_install_property
-		(object_class, PROP_CAPABILITIES,
-		 g_param_spec_flags (NM_SECRET_AGENT_OLD_CAPABILITIES, "", "",
-		                     NM_TYPE_SECRET_AGENT_CAPABILITIES,
-		                     NM_SECRET_AGENT_CAPABILITY_NONE,
-		                     G_PARAM_READWRITE |
-		                     G_PARAM_CONSTRUCT |
-		                     G_PARAM_STATIC_STRINGS));
+	obj_properties[PROP_CAPABILITIES] =
+	    g_param_spec_flags (NM_SECRET_AGENT_OLD_CAPABILITIES, "", "",
+	                        NM_TYPE_SECRET_AGENT_CAPABILITIES,
+	                        NM_SECRET_AGENT_CAPABILITY_NONE,
+	                        G_PARAM_READWRITE |
+	                        G_PARAM_CONSTRUCT |
+	                        G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
 }
 
 static void
diff --git a/libnm/nm-settings-docs-overrides.xml b/libnm/nm-settings-docs-overrides.xml
index 54d85107..8f14996d 100644
--- a/libnm/nm-settings-docs-overrides.xml
+++ b/libnm/nm-settings-docs-overrides.xml
@@ -162,6 +162,8 @@ vlan&apos;s interface name."/>
 </setting>
 <setting name="vxlan">
 </setting>
+<setting name="wifi-p2p">
+</setting>
 <setting name="wimax">
 </setting>
 <setting name="802-3-ethernet">
@@ -176,6 +178,9 @@ can only contain explicit hardware addresses. Note that this property
 only exists in D-Bus API. libnm and nmcli continue to call this property
 &quot;cloned-mac-address&quot;."/>
 </setting>
+<setting name="wireguard">
+<property name="peers" variable="peers" format="array of &apos;a{sv}&apos;" values="" default="" example="" description="Array of dictionaries for the WireGuard peers."/>
+</setting>
 <setting name="802-11-wireless-security">
 </setting>
 <setting name="802-11-wireless">
diff --git a/libnm/nm-settings-docs.xml b/libnm/nm-settings-docs.xml
index 5c33c2a4..ee5f3641 100644
--- a/libnm/nm-settings-docs.xml
+++ b/libnm/nm-settings-docs.xml
@@ -22,7 +22,7 @@
     <property name="read-only" name_upper="READ_ONLY" type="boolean" default="FALSE" description="FALSE if the connection can be modified using the provided settings service's D-Bus interface with the right privileges, or TRUE if the connection is read-only and cannot be modified." />
     <property name="secondaries" name_upper="SECONDARIES" type="array of string" default="[]" description="List of connection UUIDs that should be activated when the base connection itself is activated. Currently only VPN connections are supported." />
     <property name="slave-type" name_upper="SLAVE_TYPE" type="string" description="Setting name of the device type of this slave's master connection (eg, &quot;bond&quot;), or NULL if this connection is not a slave." />
-    <property name="stable-id" name_upper="STABLE_ID" type="string" description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that &quot;${DEVICE}&quot; corresponds the the interface name of the device and &quot;${MAC}&quot; is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to &quot;${CONNECTION}&quot; and uses a unique, fixed ID for the connection." />
+    <property name="stable-id" name_upper="STABLE_ID" type="string" description="This represents the identity of the connection used for various purposes. It allows to configure multiple profiles to share the identity. Also, the stable-id can contain placeholders that are substituted dynamically and deterministically depending on the context. The stable-id is used for generating IPv6 stable private addresses with ipv6.addr-gen-mode=stable-privacy. It is also used to seed the generated cloned MAC address for ethernet.cloned-mac-address=stable and wifi.cloned-mac-address=stable. It is also used as DHCP client identifier with ipv4.dhcp-client-id=stable and to derive the DHCP DUID with ipv6.dhcp-duid=stable-[llt,ll,uuid]. Note that depending on the context where it is used, other parameters are also seeded into the generation algorithm. For example, a per-host key is commonly also included, so that different systems end up generating different IDs. Or with ipv6.addr-gen-mode=stable-privacy, also the device's name is included, so that different interfaces yield different addresses. The '$' character is treated special to perform dynamic substitutions at runtime. Currently supported are &quot;${CONNECTION}&quot;, &quot;${DEVICE}&quot;, &quot;${MAC}&quot;, &quot;${BOOT}&quot;, &quot;${RANDOM}&quot;. These effectively create unique IDs per-connection, per-device, per-boot, or every time. Note that &quot;${DEVICE}&quot; corresponds to the interface name of the device and &quot;${MAC}&quot; is the permanent MAC address of the device. Any unrecognized patterns following '$' are treated verbatim, however are reserved for future use. You are thus advised to avoid '$' or escape it as &quot;$$&quot;. For example, set it to &quot;${CONNECTION}-${BOOT}-${DEVICE}&quot; to create a unique id for this connection that changes with every reboot and differs depending on the interface where the profile activates. If the value is unset, a global connection default is consulted. If the value is still unset, the default is similar to &quot;${CONNECTION}&quot; and uses a unique, fixed ID for the connection." />
     <property name="timestamp" name_upper="TIMESTAMP" type="uint64" default="0" description="The time, in seconds since the Unix Epoch, that the connection was last _successfully_ fully activated. NetworkManager updates the connection timestamp periodically when the connection is active to ensure that an active connection has the latest timestamp. The property is only meant for reading (changes to this property will not be preserved)." />
     <property name="type" name_upper="TYPE" type="string" description="Base type of the connection. For hardware-dependent connections, should contain the setting name of the hardware-type specific setting (ie, &quot;802-3-ethernet&quot; or &quot;802-11-wireless&quot; or &quot;bluetooth&quot;, etc), and for non-hardware dependent connections like VPN or otherwise, should contain the setting name of that setting type (ie, &quot;vpn&quot; or &quot;bridge&quot;, etc)." />
     <property name="uuid" name_upper="UUID" type="string" description="A universally unique identifier for the connection, for example generated with libuuid.  It should be assigned when the connection is created, and never changed as long as the connection still applies to the same network.  For example, it should not be changed when the &quot;id&quot; property or NMSettingIP4Config changes, but might need to be re-created when the Wi-Fi SSID, mobile broadband network provider, or &quot;type&quot; property changes. The UUID must be in the format &quot;2815492f-7e56-435e-b2e9-246bd7cdc664&quot; (ie, contains only hexadecimal characters and &quot;-&quot;)." />
@@ -395,6 +395,11 @@
     <property name="tos" name_upper="TOS" type="uint32" default="0" description="Specifies the TOS value to use in outgoing packets." />
     <property name="ttl" name_upper="TTL" type="uint32" default="0" description="Specifies the time-to-live value to use in outgoing packets." />
   </setting>
+  <setting name="wifi-p2p" description="Wi-Fi P2P Settings" name_upper="WIFI_P2P" >
+    <property name="peer" name_upper="PEER" type="string" description="The P2P device that should be connected to. Currently this is the only way to create or join a group." />
+    <property name="wfd-ies" name_upper="WFD_IES" type="byte array" description="The Wi-Fi Display (WFD) Information Elements (IEs) to set. Wi-Fi Display requires a protocol specific information element to be set in certain Wi-Fi frames. These can be specified here for the purpose of establishing a connection. This setting is only useful when implementing a Wi-Fi Display client." />
+    <property name="wps-method" name_upper="WPS_METHOD" type="uint32" default="0" description="Flags indicating which mode of WPS is to be used. There's little point in changing the default setting as NetworkManager will automatically determine the best method to use." />
+  </setting>
   <setting name="wimax" description="WiMax Settings" name_upper="WIMAX" >
     <property name="mac-address" name_upper="MAC_ADDRESS" type="byte array" description="If specified, this connection will only apply to the WiMAX device whose MAC address matches. This property does not change the MAC address of the device (known as MAC spoofing). Deprecated: 1" />
     <property name="network-name" name_upper="NETWORK_NAME" type="string" description="Network Service Provider (NSP) name of the WiMAX network this connection should use. Deprecated: 1" />
@@ -416,6 +421,15 @@
     <property name="wake-on-lan" name_upper="WAKE_ON_LAN" type="uint32" default="1" description="The NMSettingWiredWakeOnLan options to enable. Not all devices support all options. May be any combination of NM_SETTING_WIRED_WAKE_ON_LAN_PHY (0x2), NM_SETTING_WIRED_WAKE_ON_LAN_UNICAST (0x4), NM_SETTING_WIRED_WAKE_ON_LAN_MULTICAST (0x8), NM_SETTING_WIRED_WAKE_ON_LAN_BROADCAST (0x10), NM_SETTING_WIRED_WAKE_ON_LAN_ARP (0x20), NM_SETTING_WIRED_WAKE_ON_LAN_MAGIC (0x40) or the special values NM_SETTING_WIRED_WAKE_ON_LAN_DEFAULT (0x1) (to use global settings) and NM_SETTING_WIRED_WAKE_ON_LAN_IGNORE (0x8000) (to disable management of Wake-on-LAN in NetworkManager)." />
     <property name="wake-on-lan-password" name_upper="WAKE_ON_LAN_PASSWORD" type="string" description="If specified, the password used with magic-packet-based Wake-on-LAN, represented as an Ethernet MAC address.  If NULL, no password will be required." />
   </setting>
+  <setting name="wireguard" description="WireGuard Ethernet Settings" name_upper="WIREGUARD" >
+    <property name="fwmark" name_upper="FWMARK" type="uint32" default="0" description="The use of fwmark is optional and is by default off. Setting it to 0 disables it. Otherwise it is a 32-bit fwmark for outgoing packets." />
+    <property name="listen-port" name_upper="LISTEN_PORT" type="uint32" default="0" description="The listen-port. If listen-port is not specified, the port will be chosen randomly when the interface comes up." />
+    <property name="mtu" name_upper="MTU" type="uint32" default="0" description="If non-zero, only transmit packets of the specified size or smaller, breaking larger packets up into multiple fragments. If zero a default MTU is used. Note that contrary to wg-quick's MTU setting, this does not take into account the current routes at the time of activation." />
+    <property name="peer-routes" name_upper="PEER_ROUTES" type="boolean" default="TRUE" description="Whether to automatically add routes for the AllowedIPs ranges of the peers. If TRUE (the default), NetworkManager will automatically add routes in the routing tables according to ipv4.route-table and ipv6.route-table. If FALSE, no such routes are added automatically. In this case, the user may want to configure static routes in ipv4.routes and ipv6.routes, respectively." />
+    <property name="peers" name_upper="PEERS" type="array of 'a{sv}'" description="Array of dictionaries for the WireGuard peers." />
+    <property name="private-key" name_upper="PRIVATE_KEY" type="string" description="The 256 bit private-key in base64 encoding." />
+    <property name="private-key-flags" name_upper="PRIVATE_KEY_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;private-key&quot; property." />
+  </setting>
   <setting name="802-11-wireless" description="Wi-Fi Settings" name_upper="WIRELESS" >
     <property name="assigned-mac-address" name_upper="ASSIGNED_MAC_ADDRESS" type="string" description="The new field for the cloned MAC address. It can be either a hardware address in ASCII representation, or one of the special values &quot;preserve&quot;, &quot;permanent&quot;, &quot;random&quot; or &quot;stable&quot;. This field replaces the deprecated &quot;cloned-mac-address&quot; on D-Bus, which can only contain explicit hardware addresses. Note that this property only exists in D-Bus API. libnm and nmcli continue to call this property &quot;cloned-mac-address&quot;." />
     <property name="band" name_upper="BAND" type="string" description="802.11 frequency band of the network.  One of &quot;a&quot; for 5GHz 802.11a or &quot;bg&quot; for 2.4GHz 802.11.  This will lock associations to the Wi-Fi network to the specific band, i.e. if &quot;a&quot; is specified, the device will not associate with the same network in the 2.4GHz band even if the network's settings are compatible.  This setting depends on specific driver capability and may not work with all drivers." />
@@ -441,14 +455,14 @@
     <property name="auth-alg" name_upper="AUTH_ALG" type="string" description="When WEP is used (ie, key-mgmt = &quot;none&quot; or &quot;ieee8021x&quot;) indicate the 802.11 authentication algorithm required by the AP here.  One of &quot;open&quot; for Open System, &quot;shared&quot; for Shared Key, or &quot;leap&quot; for Cisco LEAP.  When using Cisco LEAP (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;) the &quot;leap-username&quot; and &quot;leap-password&quot; properties must be specified." />
     <property name="fils" name_upper="FILS" type="int32" default="0" description="Indicates whether Fast Initial Link Setup (802.11ai) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_FILS_DISABLE (1) (disable FILS), NM_SETTING_WIRELESS_SECURITY_FILS_OPTIONAL (2) (enable FILS if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_FILS_REQUIRED (3) (enable FILS and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_FILS_DEFAULT (0) and no global default is set, FILS will be optionally enabled." />
     <property name="group" name_upper="GROUP" type="array of string" default="[]" description="A list of group/broadcast encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list.  For maximum compatibility leave this property empty.  Each list element may be one of &quot;wep40&quot;, &quot;wep104&quot;, &quot;tkip&quot;, or &quot;ccmp&quot;." />
-    <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection.  One of &quot;none&quot; (WEP), &quot;ieee8021x&quot; (Dynamic WEP), &quot;wpa-none&quot; (Ad-Hoc WPA-PSK), &quot;wpa-psk&quot; (infrastructure WPA-PSK), or &quot;wpa-eap&quot; (WPA-Enterprise).  This property must be set for any Wi-Fi connection that uses security." />
+    <property name="key-mgmt" name_upper="KEY_MGMT" type="string" description="Key management used for the connection.  One of &quot;none&quot; (WEP), &quot;ieee8021x&quot; (Dynamic WEP), &quot;wpa-none&quot; (Ad-Hoc WPA-PSK), &quot;wpa-psk&quot; (infrastructure WPA-PSK), &quot;sae&quot; (SAE) or &quot;wpa-eap&quot; (WPA-Enterprise). This property must be set for any Wi-Fi connection that uses security." />
     <property name="leap-password" name_upper="LEAP_PASSWORD" type="string" description="The login password for legacy LEAP connections (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;)." />
     <property name="leap-password-flags" name_upper="LEAP_PASSWORD_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;leap-password&quot; property." />
     <property name="leap-username" name_upper="LEAP_USERNAME" type="string" description="The login username for legacy LEAP connections (ie, key-mgmt = &quot;ieee8021x&quot; and auth-alg = &quot;leap&quot;)." />
     <property name="pairwise" name_upper="PAIRWISE" type="array of string" default="[]" description="A list of pairwise encryption algorithms which prevents connections to Wi-Fi networks that do not utilize one of the algorithms in the list. For maximum compatibility leave this property empty.  Each list element may be one of &quot;tkip&quot; or &quot;ccmp&quot;." />
     <property name="pmf" name_upper="PMF" type="int32" default="0" description="Indicates whether Protected Management Frames (802.11w) must be enabled for the connection.  One of NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) (use global default value), NM_SETTING_WIRELESS_SECURITY_PMF_DISABLE (1) (disable PMF), NM_SETTING_WIRELESS_SECURITY_PMF_OPTIONAL (2) (enable PMF if the supplicant and the access point support it) or NM_SETTING_WIRELESS_SECURITY_PMF_REQUIRED (3) (enable PMF and fail if not supported).  When set to NM_SETTING_WIRELESS_SECURITY_PMF_DEFAULT (0) and no global default is set, PMF will be optionally enabled." />
     <property name="proto" name_upper="PROTO" type="array of string" default="[]" description="List of strings specifying the allowed WPA protocol versions to use. Each element may be one &quot;wpa&quot; (allow WPA) or &quot;rsn&quot; (allow WPA2/RSN).  If not specified, both WPA and RSN connections are allowed." />
-    <property name="psk" name_upper="PSK" type="string" description="Pre-Shared-Key for WPA networks.  If the key is 64-characters long, it must contain only hexadecimal characters and is interpreted as a hexadecimal WPA key.  Otherwise, the key must be between 8 and 63 ASCII characters (as specified in the 802.11i standard) and is interpreted as a WPA passphrase, and is hashed to derive the actual WPA-PSK used when connecting to the Wi-Fi network." />
+    <property name="psk" name_upper="PSK" type="string" description="Pre-Shared-Key for WPA networks. For WPA-PSK, it's either an ASCII passphrase of 8 to 63 characters that is (as specified in the 802.11i standard) hashed to derive the actual key, or the key in form of 64 hexadecimal character. The WPA3-Personal networks use a passphrase of any length for SAE authentication." />
     <property name="psk-flags" name_upper="PSK_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;psk&quot; property." />
     <property name="wep-key-flags" name_upper="WEP_KEY_FLAGS" type="NMSettingSecretFlags (uint32)" description="Flags indicating how to handle the &quot;wep-key0&quot;, &quot;wep-key1&quot;, &quot;wep-key2&quot;, and &quot;wep-key3&quot; properties." />
     <property name="wep-key-type" name_upper="WEP_KEY_TYPE" type="NMWepKeyType (uint32)" description="Controls the interpretation of WEP keys.  Allowed values are NM_WEP_KEY_TYPE_KEY (1), in which case the key is either a 10- or 26-character hexadecimal string, or a 5- or 13-character ASCII password; or NM_WEP_KEY_TYPE_PASSPHRASE (2), in which case the passphrase is provided as a string and will be hashed using the de-facto MD5 method to derive the actual WEP key." />
diff --git a/libnm/nm-settings-ifcfg-rh-docs.xml b/libnm/nm-settings-ifcfg-rh-docs.xml
index d1913062..cec2d527 100644
--- a/libnm/nm-settings-ifcfg-rh-docs.xml
+++ b/libnm/nm-settings-ifcfg-rh-docs.xml
@@ -297,6 +297,8 @@ but VLAN id from DEVICE takes precedence over VLAN_ID."/>
 </setting>
 <setting name="vxlan">
 </setting>
+<setting name="wifi-p2p">
+</setting>
 <setting name="wimax">
 </setting>
 <setting name="802-3-ethernet">
@@ -325,6 +327,8 @@ is listed."/>
 <property name="s390-options" variable="OPTIONS and PORTNAME, CTCPROTO," format="" values="" default="" example="" description="S390 device options. All options go to OPTIONS, except for
 &quot;portname&quot; and &quot;ctcprot&quot; that have their own variables."/>
 </setting>
+<setting name="wireguard">
+</setting>
 <setting name="802-11-wireless-security">
 <property name="key-mgmt" variable="KEY_MGMT(+)" format="" values="IEEE8021X, WPA-PSK, WPA-EAP" default="" example="" description="Key management menthod."/>
 <property name="wep-tx-keyidx" variable="DEFAULTKEY" format="" values="1, 2, 3, 4" default="1" example="" description="Index of active WEP key."/>
diff --git a/libnm/nm-settings-keyfile-docs.xml b/libnm/nm-settings-keyfile-docs.xml
index 09b119a2..002d5609 100644
--- a/libnm/nm-settings-keyfile-docs.xml
+++ b/libnm/nm-settings-keyfile-docs.xml
@@ -102,6 +102,11 @@ under [vpn-secrets] section."/>
 </setting>
 <setting name="vxlan">
 </setting>
+<setting name="wifi-p2p">
+<property name="peer" variable="peer" format="usual hex-digits-and-colons notation" values="" default="" example="" description="MAC address in traditional hex-digits-and-colons notation
+(e.g. 00:22:68:12:79:A2), or semicolon separated list of 6 bytes (obsolete)
+(e.g. 0;34;104;18;121;162)."/>
+</setting>
 <setting name="wimax">
 </setting>
 <setting name="802-3-ethernet">
@@ -113,6 +118,8 @@ under [vpn-secrets] section."/>
 (e.g. 0;34;104;18;121;178)."/>
 <property name="mac-address-blacklist" variable="mac-address-blacklist" format="list of MACs (separated with semicolons)" values="" default="" example="mac-address-blacklist= 00:22:68:12:79:A6;00:22:68:12:79:78" description="MAC address blacklist."/>
 </setting>
+<setting name="wireguard">
+</setting>
 <setting name="802-11-wireless-security">
 </setting>
 <setting name="802-11-wireless">
diff --git a/libnm/nm-types.h b/libnm/nm-types.h
index bb77e642..16a2ba18 100644
--- a/libnm/nm-types.h
+++ b/libnm/nm-types.h
@@ -39,8 +39,8 @@ typedef struct _NMDeviceBt           NMDeviceBt;
 typedef struct _NMDeviceDummy        NMDeviceDummy;
 typedef struct _NMDeviceEthernet     NMDeviceEthernet;
 typedef struct _NMDeviceGeneric      NMDeviceGeneric;
-typedef struct _NMDeviceInfiniband   NMDeviceInfiniband;
 typedef struct _NMDeviceIPTunnel     NMDeviceIPTunnel;
+typedef struct _NMDeviceInfiniband   NMDeviceInfiniband;
 typedef struct _NMDeviceMacsec       NMDeviceMacsec;
 typedef struct _NMDeviceMacvlan      NMDeviceMacvlan;
 typedef struct _NMDeviceModem        NMDeviceModem;
@@ -54,6 +54,7 @@ typedef struct _NMDeviceTun          NMDeviceTun;
 typedef struct _NMDeviceVlan         NMDeviceVlan;
 typedef struct _NMDeviceVxlan        NMDeviceVxlan;
 typedef struct _NMDeviceWifi         NMDeviceWifi;
+typedef struct _NMDeviceWifiP2P      NMDeviceWifiP2P;
 typedef struct _NMDeviceWimax        NMDeviceWimax;
 typedef struct _NMDeviceWireGuard    NMDeviceWireGuard;
 typedef struct _NMDeviceWpan         NMDeviceWpan;
@@ -62,6 +63,7 @@ typedef struct _NMIPConfig           NMIPConfig;
 typedef struct _NMObject             NMObject;
 typedef struct _NMRemoteConnection   NMRemoteConnection;
 typedef struct _NMVpnConnection      NMVpnConnection;
+typedef struct _NMWifiP2PPeer        NMWifiP2PPeer;
 typedef struct _NMWimaxNsp           NMWimaxNsp;
 
 #endif  /* NM_TYPES_H */
diff --git a/libnm/nm-vpn-connection.c b/libnm/nm-vpn-connection.c
index bc26d0b9..9fc32ed6 100644
--- a/libnm/nm-vpn-connection.c
+++ b/libnm/nm-vpn-connection.c
@@ -21,9 +21,8 @@
 
 #include "nm-default.h"
 
-#include <string.h>
-
 #include "nm-vpn-connection.h"
+
 #include "nm-dbus-interface.h"
 #include "nm-utils.h"
 #include "nm-object-private.h"
diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c
index bfafc7b7..80900cec 100644
--- a/libnm/nm-vpn-plugin-old.c
+++ b/libnm/nm-vpn-plugin-old.c
@@ -23,7 +23,6 @@
 
 #include "nm-vpn-plugin-old.h"
 
-#include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 
diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c
index ed9da7f7..a2728342 100644
--- a/libnm/nm-vpn-service-plugin.c
+++ b/libnm/nm-vpn-service-plugin.c
@@ -23,7 +23,6 @@
 
 #include "nm-vpn-service-plugin.h"
 
-#include <errno.h>
 #include <signal.h>
 #include <stdlib.h>
 
@@ -808,7 +807,6 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
 	while (1) {
 		ssize_t nr;
 
-		errno = 0;
 		nr = read (fd, &c, 1);
 		if (nr < 0) {
 			if (errno == EAGAIN) {
@@ -830,8 +828,8 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
 			/* done a line */
 			g_return_val_if_fail (hash, FALSE);
 			g_hash_table_insert (hash,
-					     g_string_free (key, FALSE),
-					     g_string_free (val, FALSE));
+			                     g_string_free (key, FALSE),
+			                     g_string_free (val, FALSE));
 			key = NULL;
 			val = NULL;
 			hash = NULL;
@@ -839,7 +837,7 @@ nm_vpn_service_plugin_read_vpn_details (int fd,
 		}
 
 		if (strcmp (line->str, "DONE") == 0) {
-			 /* finish marker */
+			/* finish marker */
 			break;
 		} else if (strncmp (line->str, DATA_KEY_TAG, strlen (DATA_KEY_TAG)) == 0) {
 			if (key != NULL) {
diff --git a/libnm/nm-wifi-p2p-peer.c b/libnm/nm-wifi-p2p-peer.c
new file mode 100644
index 00000000..4dd8545d
--- /dev/null
+++ b/libnm/nm-wifi-p2p-peer.c
@@ -0,0 +1,600 @@
+/*
+ * 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.
+ *
+ * Copyright 2018 - 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-wifi-p2p-peer.h"
+
+#include "nm-connection.h"
+#include "nm-setting-connection.h"
+#include "nm-setting-wifi-p2p.h"
+#include "nm-utils.h"
+#include "nm-dbus-interface.h"
+#include "nm-object-private.h"
+
+/*****************************************************************************/
+
+NM_GOBJECT_PROPERTIES_DEFINE_BASE (
+	PROP_FLAGS,
+	PROP_NAME,
+	PROP_MANUFACTURER,
+	PROP_MODEL,
+	PROP_MODEL_NUMBER,
+	PROP_SERIAL,
+	PROP_WFD_IES,
+	PROP_HW_ADDRESS,
+	PROP_STRENGTH,
+	PROP_LAST_SEEN,
+);
+
+typedef struct {
+	char *name;
+	char *manufacturer;
+	char *model;
+	char *model_number;
+	char *serial;
+
+	GBytes *wfd_ies;
+
+	char *hw_address;
+
+	int last_seen;
+
+	NM80211ApFlags flags;
+
+	guint8 strength;
+} NMWifiP2PPeerPrivate;
+
+/**
+ * NMWifiP2PPeer:
+ */
+struct _NMWifiP2PPeer {
+	NMObject parent;
+	NMWifiP2PPeerPrivate _priv;
+};
+
+struct _NMWifiP2PPeerClass {
+	NMObjectClass parent;
+};
+
+G_DEFINE_TYPE (NMWifiP2PPeer, nm_wifi_p2p_peer, NM_TYPE_OBJECT)
+
+#define NM_WIFI_P2P_PEER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMWifiP2PPeer, NM_IS_WIFI_P2P_PEER, NMObject)
+
+/*****************************************************************************/
+
+/**
+ * nm_wifi_p2p_peer_get_flags:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the flags of the P2P peer.
+ *
+ * Returns: the flags
+ *
+ * Since: 1.16
+ **/
+NM80211ApFlags
+nm_wifi_p2p_peer_get_flags (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NM_802_11_AP_FLAGS_NONE);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->flags;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_name:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the name of the P2P peer.
+ *
+ * Returns: the name
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_name (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->name;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_manufacturer:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the manufacturer of the P2P peer.
+ *
+ * Returns: the manufacturer
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_manufacturer (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->manufacturer;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_model:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the model of the P2P peer.
+ *
+ * Returns: the model
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_model (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_model_number:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the model number of the P2P peer.
+ *
+ * Returns: the model number
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_model_number (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->model_number;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_serial:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the serial number of the P2P peer.
+ *
+ * Returns: the serial number
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_serial (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->serial;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_wfd_ies:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the WFD information elements of the P2P peer.
+ *
+ * Returns: (transfer none): the #GBytes containing the WFD IEs, or %NULL.
+ *
+ * Since: 1.16
+ **/
+GBytes *
+nm_wifi_p2p_peer_get_wfd_ies (NMWifiP2PPeer *peer)
+{
+	NMWifiP2PPeerPrivate *priv;
+
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	priv = NM_WIFI_P2P_PEER_GET_PRIVATE (peer);
+	if (!priv->wfd_ies || g_bytes_get_size (priv->wfd_ies) == 0)
+		return NULL;
+
+	return priv->wfd_ies;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_hw_address:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the hardware address of the P2P peer.
+ *
+ * Returns: the hardware address
+ *
+ * Since: 1.16
+ **/
+const char *
+nm_wifi_p2p_peer_get_hw_address (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), NULL);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->hw_address;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_strength:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Gets the current signal strength of the P2P peer as a percentage.
+ *
+ * Returns: the signal strength (0 to 100)
+ *
+ * Since: 1.16
+ **/
+guint8
+nm_wifi_p2p_peer_get_strength (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), 0);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->strength;
+}
+
+/**
+ * nm_wifi_p2p_peer_get_last_seen:
+ * @peer: a #NMWifiP2PPeer
+ *
+ * Returns the timestamp (in CLOCK_BOOTTIME seconds) for the last time the
+ * P2P peer was seen.  A value of -1 means the P2P peer has never been seen.
+ *
+ * Returns: the last seen time in seconds
+ *
+ * Since: 1.16
+ **/
+int
+nm_wifi_p2p_peer_get_last_seen (NMWifiP2PPeer *peer)
+{
+	g_return_val_if_fail (NM_IS_WIFI_P2P_PEER (peer), -1);
+
+	return NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->last_seen;
+}
+
+/**
+ * nm_wifi_p2p_peer_connection_valid:
+ * @peer: an #NMWifiP2PPeer to validate @connection against
+ * @connection: an #NMConnection to validate against @peer
+ *
+ * Validates a given connection against a given Wi-Fi P2P peer to ensure that
+ * the connection may be activated with that peer. The connection must match the
+ * @peer's address and in the future possibly other attributes.
+ *
+ * Returns: %TRUE if the connection may be activated with this Wi-Fi P2P Peer,
+ * %FALSE if it cannot be.
+ *
+ * Since: 1.16
+ **/
+gboolean
+nm_wifi_p2p_peer_connection_valid (NMWifiP2PPeer *peer, NMConnection *connection)
+{
+	NMSettingConnection *s_con;
+	NMSettingWifiP2P *s_wifi_p2p;
+	const char *ctype;
+	const char *hw_address;
+	const char *setting_peer;
+
+	s_wifi_p2p = (NMSettingWifiP2P *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIFI_P2P);
+	if (!s_wifi_p2p)
+		return FALSE;
+
+	s_con = nm_connection_get_setting_connection (connection);
+	if (!s_con)
+		return FALSE;
+
+	ctype = nm_setting_connection_get_connection_type (s_con);
+	if (   !ctype
+	    || !nm_streq (ctype, NM_SETTING_WIFI_P2P_SETTING_NAME))
+		return FALSE;
+
+	/* HW Address check */
+	hw_address = nm_wifi_p2p_peer_get_hw_address (peer);
+	if (!hw_address)
+		return FALSE;
+
+	setting_peer = nm_setting_wifi_p2p_get_peer (s_wifi_p2p);
+	if (   !setting_peer
+	    || !nm_streq (hw_address, setting_peer))
+		return FALSE;
+
+	return TRUE;
+}
+
+/**
+ * nm_wifi_p2p_peer_filter_connections:
+ * @peer: an #NMWifiP2PPeer to filter connections for
+ * @connections: (element-type NMConnection): an array of #NMConnections to
+ * filter
+ *
+ * Filters a given array of connections for a given #NMWifiP2PPeer object and
+ * returns connections which may be activated with the P2P peer.  Any
+ * returned connections will match the @peers's HW address and in the future
+ * possibly other attributes.
+ *
+ * To obtain the list of connections that are compatible with this P2P peer,
+ * use nm_client_get_connections() and then filter the returned list for a given
+ * #NMDevice using nm_device_filter_connections() and finally filter that list
+ * with this function.
+ *
+ * Returns: (transfer container) (element-type NMConnection): an array of
+ * #NMConnections that could be activated with the given @peer. The array should
+ * be freed with g_ptr_array_unref() when it is no longer required.
+ *
+ * Since: 1.16
+ **/
+GPtrArray *
+nm_wifi_p2p_peer_filter_connections (NMWifiP2PPeer *peer, const GPtrArray *connections)
+{
+	GPtrArray *filtered;
+	guint i;
+
+	filtered = g_ptr_array_new_with_free_func (g_object_unref);
+	for (i = 0; i < connections->len; i++) {
+		NMConnection *candidate = connections->pdata[i];
+
+		if (nm_wifi_p2p_peer_connection_valid (peer, candidate))
+			g_ptr_array_add (filtered, g_object_ref (candidate));
+	}
+
+	return filtered;
+}
+
+/*****************************************************************************/
+
+static void
+init_dbus (NMObject *object)
+{
+	NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (object);
+	const NMPropertiesInfo property_info[] = {
+		{ NM_WIFI_P2P_PEER_FLAGS,        &priv->flags },
+		{ NM_WIFI_P2P_PEER_NAME,         &priv->name },
+		{ NM_WIFI_P2P_PEER_MANUFACTURER, &priv->manufacturer },
+		{ NM_WIFI_P2P_PEER_MODEL,        &priv->model },
+		{ NM_WIFI_P2P_PEER_MODEL_NUMBER, &priv->model_number },
+		{ NM_WIFI_P2P_PEER_SERIAL,       &priv->serial },
+		{ NM_WIFI_P2P_PEER_WFD_IES,      &priv->wfd_ies },
+		{ NM_WIFI_P2P_PEER_HW_ADDRESS,   &priv->hw_address },
+		{ NM_WIFI_P2P_PEER_STRENGTH,     &priv->strength },
+		{ NM_WIFI_P2P_PEER_LAST_SEEN,    &priv->last_seen },
+		{ NULL },
+	};
+
+	NM_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->init_dbus (object);
+
+	_nm_object_register_properties (object,
+	                                NM_DBUS_INTERFACE_WIFI_P2P_PEER,
+	                                property_info);
+}
+
+/*****************************************************************************/
+
+static void
+get_property (GObject *object,
+              guint prop_id,
+              GValue *value,
+              GParamSpec *pspec)
+{
+	NMWifiP2PPeer *peer = NM_WIFI_P2P_PEER (object);
+
+	switch (prop_id) {
+	case PROP_FLAGS:
+		g_value_set_flags (value, nm_wifi_p2p_peer_get_flags (peer));
+		break;
+	case PROP_NAME:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_name (peer));
+		break;
+	case PROP_MANUFACTURER:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_manufacturer (peer));
+		break;
+	case PROP_MODEL:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_model (peer));
+		break;
+	case PROP_MODEL_NUMBER:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_model_number (peer));
+		break;
+	case PROP_SERIAL:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_serial (peer));
+		break;
+	case PROP_WFD_IES:
+		g_value_set_boxed (value, nm_wifi_p2p_peer_get_wfd_ies (peer));
+		break;
+	case PROP_HW_ADDRESS:
+		g_value_set_string (value, nm_wifi_p2p_peer_get_hw_address (peer));
+		break;
+	case PROP_STRENGTH:
+		g_value_set_uchar (value, nm_wifi_p2p_peer_get_strength (peer));
+		break;
+	case PROP_LAST_SEEN:
+		g_value_set_int (value, nm_wifi_p2p_peer_get_last_seen (peer));
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/*****************************************************************************/
+
+static void
+nm_wifi_p2p_peer_init (NMWifiP2PPeer *peer)
+{
+	NM_WIFI_P2P_PEER_GET_PRIVATE (peer)->last_seen = -1;
+}
+
+static void
+finalize (GObject *object)
+{
+	NMWifiP2PPeerPrivate *priv = NM_WIFI_P2P_PEER_GET_PRIVATE (object);
+
+	g_free (priv->name);
+	g_free (priv->manufacturer);
+	g_free (priv->model);
+	g_free (priv->model_number);
+	g_free (priv->serial);
+
+	g_free (priv->hw_address);
+
+	g_bytes_unref (priv->wfd_ies);
+
+	G_OBJECT_CLASS (nm_wifi_p2p_peer_parent_class)->finalize (object);
+}
+
+static void
+nm_wifi_p2p_peer_class_init (NMWifiP2PPeerClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+	NMObjectClass *nm_object_class = NM_OBJECT_CLASS (klass);
+
+	object_class->get_property = get_property;
+	object_class->finalize     = finalize;
+
+	nm_object_class->init_dbus = init_dbus;
+
+	/**
+	 * NMWifiP2PPeer:flags:
+	 *
+	 * The flags of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_FLAGS] =
+	    g_param_spec_flags (NM_WIFI_P2P_PEER_FLAGS, "", "",
+	                        NM_TYPE_802_11_AP_FLAGS,
+	                        NM_802_11_AP_FLAGS_NONE,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:name:
+	 *
+	 * The name of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_NAME] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_NAME, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:manufacturer:
+	 *
+	 * The manufacturer of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_MANUFACTURER] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_MANUFACTURER, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:model:
+	 *
+	 * The model of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_MODEL] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_MODEL, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:model-number:
+	 *
+	 * The hardware address of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_MODEL_NUMBER] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_MODEL_NUMBER, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:serial:
+	 *
+	 * The serial number of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_SERIAL] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_SERIAL, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:wfd-ies:
+	 *
+	 * The WFD information elements of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_WFD_IES] =
+	    g_param_spec_boxed (NM_WIFI_P2P_PEER_WFD_IES, "", "",
+	                        G_TYPE_BYTES,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+	/**
+	 * NMWifiP2PPeer:hw-address:
+	 *
+	 * The hardware address of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_HW_ADDRESS] =
+	    g_param_spec_string (NM_WIFI_P2P_PEER_HW_ADDRESS, "", "",
+	                         NULL,
+	                         G_PARAM_READABLE |
+	                         G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:strength:
+	 *
+	 * The current signal strength of the P2P peer.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_STRENGTH] =
+	    g_param_spec_uchar (NM_WIFI_P2P_PEER_STRENGTH, "", "",
+	                        0, G_MAXUINT8, 0,
+	                        G_PARAM_READABLE |
+	                        G_PARAM_STATIC_STRINGS);
+
+	/**
+	 * NMWifiP2PPeer:last-seen:
+	 *
+	 * The timestamp (in CLOCK_BOOTTIME seconds) for the last time the
+	 * P2P peer was found.  A value of -1 means the peer has never been seen.
+	 *
+	 * Since: 1.16
+	 **/
+	obj_properties[PROP_LAST_SEEN] =
+	    g_param_spec_int (NM_WIFI_P2P_PEER_LAST_SEEN, "", "",
+	                      -1, G_MAXINT, -1,
+	                      G_PARAM_READABLE |
+	                      G_PARAM_STATIC_STRINGS);
+
+	g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties);
+}
diff --git a/libnm/nm-wifi-p2p-peer.h b/libnm/nm-wifi-p2p-peer.h
new file mode 100644
index 00000000..7d48883b
--- /dev/null
+++ b/libnm/nm-wifi-p2p-peer.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ *
+ * Copyright 2018 - 2019 Red Hat, Inc.
+ */
+
+#ifndef __NM_WIFI_P2P_PEER_H__
+#define __NM_WIFI_P2P_PEER_H__
+
+#if !defined (__NETWORKMANAGER_H_INSIDE__) && !defined (NETWORKMANAGER_COMPILATION)
+#error "Only <NetworkManager.h> can be included directly."
+#endif
+
+#include "nm-object.h"
+
+G_BEGIN_DECLS
+
+#define NM_TYPE_WIFI_P2P_PEER            (nm_wifi_p2p_peer_get_type ())
+#define NM_WIFI_P2P_PEER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeer))
+#define NM_WIFI_P2P_PEER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass))
+#define NM_IS_WIFI_P2P_PEER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_WIFI_P2P_PEER))
+#define NM_IS_WIFI_P2P_PEER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_WIFI_P2P_PEER))
+#define NM_WIFI_P2P_PEER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_WIFI_P2P_PEER, NMWifiP2PPeerClass))
+
+#define NM_WIFI_P2P_PEER_FLAGS                "flags"
+#define NM_WIFI_P2P_PEER_NAME                 "name"
+#define NM_WIFI_P2P_PEER_MANUFACTURER         "manufacturer"
+#define NM_WIFI_P2P_PEER_MODEL                "model"
+#define NM_WIFI_P2P_PEER_MODEL_NUMBER         "model-number"
+#define NM_WIFI_P2P_PEER_SERIAL               "serial"
+#define NM_WIFI_P2P_PEER_WFD_IES              "wfd-ies"
+#define NM_WIFI_P2P_PEER_HW_ADDRESS           "hw-address"
+#define NM_WIFI_P2P_PEER_STRENGTH             "strength"
+#define NM_WIFI_P2P_PEER_LAST_SEEN            "last-seen"
+
+typedef struct _NMWifiP2PPeerClass NMWifiP2PPeerClass;
+
+NM_AVAILABLE_IN_1_16
+GType nm_wifi_p2p_peer_get_type (void);
+
+NM_AVAILABLE_IN_1_16
+NM80211ApFlags         nm_wifi_p2p_peer_get_flags        (NMWifiP2PPeer *peer);
+
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_name         (NMWifiP2PPeer *peer);
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_manufacturer (NMWifiP2PPeer *peer);
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_model        (NMWifiP2PPeer *peer);
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_model_number (NMWifiP2PPeer *peer);
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_serial       (NMWifiP2PPeer *peer);
+
+NM_AVAILABLE_IN_1_16
+GBytes *               nm_wifi_p2p_peer_get_wfd_ies      (NMWifiP2PPeer *peer);
+
+NM_AVAILABLE_IN_1_16
+const char *           nm_wifi_p2p_peer_get_hw_address   (NMWifiP2PPeer *peer);
+
+NM_AVAILABLE_IN_1_16
+guint8                 nm_wifi_p2p_peer_get_strength     (NMWifiP2PPeer *peer);
+NM_AVAILABLE_IN_1_16
+int                    nm_wifi_p2p_peer_get_last_seen    (NMWifiP2PPeer *peer);
+
+NM_AVAILABLE_IN_1_16
+GPtrArray *            nm_wifi_p2p_peer_filter_connections (NMWifiP2PPeer *peer,
+                                                            const GPtrArray *connections);
+
+NM_AVAILABLE_IN_1_16
+gboolean               nm_wifi_p2p_peer_connection_valid   (NMWifiP2PPeer *peer,
+                                                            NMConnection *connection);
+
+G_END_DECLS
+
+#endif /* __NM_WIFI_P2P_PEER_H__ */
diff --git a/libnm/nm-wimax-nsp.c b/libnm/nm-wimax-nsp.c
index 90c2c2bb..7baf7f02 100644
--- a/libnm/nm-wimax-nsp.c
+++ b/libnm/nm-wimax-nsp.c
@@ -20,13 +20,11 @@
 
 #include "nm-default.h"
 
-#include <string.h>
+#include "nm-wimax-nsp.h"
 
 #include "nm-connection.h"
 #include "nm-setting-connection.h"
 #include "nm-setting-wimax.h"
-
-#include "nm-wimax-nsp.h"
 #include "nm-dbus-interface.h"
 #include "nm-object-private.h"
 #include "nm-enum-types.h"
diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c
index 21272e4d..35ae33be 100644
--- a/libnm/tests/test-nm-client.c
+++ b/libnm/tests/test-nm-client.c
@@ -20,7 +20,6 @@
 
 #include "nm-default.h"
 
-#include <string.h>
 #include <sys/types.h>
 #include <signal.h>
 
diff --git a/libnm/tests/test-remote-settings-client.c b/libnm/tests/test-remote-settings-client.c
index 45d60c06..1b211494 100644
--- a/libnm/tests/test-remote-settings-client.c
+++ b/libnm/tests/test-remote-settings-client.c
@@ -20,7 +20,6 @@
 
 #include "nm-default.h"
 
-#include <string.h>
 #include <sys/types.h>
 #include <signal.h>
 
diff --git a/libnm/tests/test-secret-agent.c b/libnm/tests/test-secret-agent.c
index 53110be6..35a215ca 100644
--- a/libnm/tests/test-secret-agent.c
+++ b/libnm/tests/test-secret-agent.c
@@ -20,7 +20,6 @@
 
 #include "nm-default.h"
 
-#include <string.h>
 #include <sys/types.h>
 #include <signal.h>