about summary refs log tree commit diff
path: root/src/nm-dbus-manager.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nm-dbus-manager.c')
-rw-r--r--src/nm-dbus-manager.c1626
1 files changed, 0 insertions, 1626 deletions
diff --git a/src/nm-dbus-manager.c b/src/nm-dbus-manager.c
deleted file mode 100644
index 3e369129..00000000
--- a/src/nm-dbus-manager.c
+++ /dev/null
@@ -1,1626 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* NetworkManager -- Network link manager
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2006 - 2013 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "nm-default.h"
-
-#include "nm-dbus-manager.h"
-
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <errno.h>
-#include <string.h>
-
-#include "c-list/src/c-list.h"
-#include "nm-dbus-interface.h"
-#include "nm-core-internal.h"
-#include "nm-dbus-compat.h"
-#include "nm-dbus-object.h"
-#include "NetworkManagerUtils.h"
-
-/* The base path for our GDBusObjectManagerServers.  They do not contain
- * "NetworkManager" because GDBusObjectManagerServer requires that all
- * exported objects be *below* the base path, and eg the Manager object
- * is the base path already.
- */
-#define OBJECT_MANAGER_SERVER_BASE_PATH "/org/freedesktop"
-
-/*****************************************************************************/
-
-typedef struct {
-	GVariant *value;
-} PropertyCacheData;
-
-typedef struct {
-	CList registration_lst;
-	NMDBusObject *obj;
-	NMDBusObjectClass *klass;
-	guint info_idx;
-	guint registration_id;
-	PropertyCacheData property_cache[];
-} RegistrationData;
-
-/* we require that @path is the first member of NMDBusManagerData
- * because _objects_by_path_hash() requires that. */
-G_STATIC_ASSERT (G_STRUCT_OFFSET (struct _NMDBusObjectInternal, path) == 0);
-
-enum {
-	PRIVATE_CONNECTION_NEW,
-	PRIVATE_CONNECTION_DISCONNECTED,
-
-	LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL];
-
-typedef struct {
-	GHashTable *objects_by_path;
-	CList objects_lst_head;
-
-	CList private_servers_lst_head;
-
-	NMDBusManagerSetPropertyHandler set_property_handler;
-	gpointer set_property_handler_data;
-
-	GDBusConnection *connection;
-	GDBusProxy *proxy;
-	guint objmgr_registration_id;
-} NMDBusManagerPrivate;
-
-struct _NMDBusManager {
-	GObject parent;
-	NMDBusManagerPrivate _priv;
-};
-
-struct _NMDBusManagerClass {
-	GObjectClass parent;
-};
-
-G_DEFINE_TYPE(NMDBusManager, nm_dbus_manager, G_TYPE_OBJECT)
-
-#define NM_DBUS_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDBusManager, NM_IS_DBUS_MANAGER)
-
-/*****************************************************************************/
-
-#define _NMLOG_DOMAIN      LOGD_CORE
-#define _NMLOG(level, ...) __NMLOG_DEFAULT (level, _NMLOG_DOMAIN, "bus-manager", __VA_ARGS__)
-
-NM_DEFINE_SINGLETON_GETTER (NMDBusManager, nm_dbus_manager_get, NM_TYPE_DBUS_MANAGER);
-
-/*****************************************************************************/
-
-static const GDBusInterfaceInfo interface_info_objmgr;
-static const GDBusSignalInfo signal_info_objmgr_interfaces_added;
-static const GDBusSignalInfo signal_info_objmgr_interfaces_removed;
-static GVariantBuilder *_obj_collect_properties_all (NMDBusObject *obj,
-                                                     GVariantBuilder *builder);
-
-/*****************************************************************************/
-
-static guint
-_objects_by_path_hash (gconstpointer user_data)
-{
-	const char *const*p_data = user_data;
-
-	nm_assert (p_data);
-	nm_assert (*p_data);
-	nm_assert ((*p_data)[0] == '/');
-
-	return nm_hash_str (*p_data);
-}
-
-static gboolean
-_objects_by_path_equal (gconstpointer user_data_a, gconstpointer user_data_b)
-{
-	const char *const*p_data_a = user_data_a;
-	const char *const*p_data_b = user_data_b;
-
-	nm_assert (p_data_a);
-	nm_assert (*p_data_a);
-	nm_assert ((*p_data_a)[0] == '/');
-	nm_assert (p_data_b);
-	nm_assert (*p_data_b);
-	nm_assert ((*p_data_b)[0] == '/');
-
-	return nm_streq (*p_data_a, *p_data_b);
-}
-
-/*****************************************************************************/
-
-typedef struct {
-	CList private_servers_lst;
-
-	const char *tag;
-	GQuark detail;
-	char *address;
-	GDBusServer *server;
-
-	/* With peer bus connections, we'll get a new connection for each
-	 * client.  For each connection we create an ObjectManager for
-	 * that connection to handle exporting our objects.
-	 *
-	 * Note that even for connections that don't export any objects
-	 * we'll still create GDBusObjectManager since that's where we store
-	 * the pointer to the GDBusConnection.
-	 */
-	CList object_mgr_lst_head;
-
-	NMDBusManager *manager;
-} PrivateServer;
-
-typedef struct {
-	CList object_mgr_lst;
-	GDBusObjectManagerServer *manager;
-	char *fake_sender;
-} ObjectMgrData;
-
-typedef struct {
-	GDBusConnection *connection;
-	PrivateServer *server;
-	gboolean remote_peer_vanished;
-} CloseConnectionInfo;
-
-/*****************************************************************************/
-
-static void
-_object_mgr_data_free (ObjectMgrData *obj_mgr_data)
-{
-	GDBusConnection *connection;
-
-	c_list_unlink_stale (&obj_mgr_data->object_mgr_lst);
-
-	connection = g_dbus_object_manager_server_get_connection (obj_mgr_data->manager);
-	if (!g_dbus_connection_is_closed (connection))
-		g_dbus_connection_close (connection, NULL, NULL, NULL);
-	g_dbus_object_manager_server_set_connection (obj_mgr_data->manager, NULL);
-	g_object_unref (obj_mgr_data->manager);
-	g_object_unref (connection);
-
-	g_free (obj_mgr_data->fake_sender);
-
-	g_slice_free (ObjectMgrData, obj_mgr_data);
-}
-
-/*****************************************************************************/
-
-static gboolean
-close_connection_in_idle (gpointer user_data)
-{
-	CloseConnectionInfo *info = user_data;
-	PrivateServer *server = info->server;
-	ObjectMgrData *obj_mgr_data, *obj_mgr_data_safe;
-
-	/* Emit this for the manager */
-	g_signal_emit (server->manager,
-	               signals[PRIVATE_CONNECTION_DISCONNECTED],
-	               server->detail,
-	               info->connection);
-
-	/* FIXME: there's a bug (754730) in GLib for which the connection
-	 * is marked as closed when the remote peer vanishes but its
-	 * resources are not cleaned up.  Work around it by explicitly
-	 * closing the connection in that case. */
-	if (info->remote_peer_vanished)
-		g_dbus_connection_close (info->connection, NULL, NULL, NULL);
-
-	c_list_for_each_entry_safe (obj_mgr_data, obj_mgr_data_safe, &server->object_mgr_lst_head, object_mgr_lst) {
-		gs_unref_object GDBusConnection *connection = NULL;
-
-		connection = g_dbus_object_manager_server_get_connection (obj_mgr_data->manager);
-		if (connection == info->connection) {
-			_object_mgr_data_free (obj_mgr_data);
-			break;
-		}
-	}
-
-	g_object_unref (server->manager);
-	g_slice_free (CloseConnectionInfo, info);
-
-	return G_SOURCE_REMOVE;
-}
-
-static void
-private_server_closed_connection (GDBusConnection *conn,
-                                  gboolean remote_peer_vanished,
-                                  GError *error,
-                                  gpointer user_data)
-{
-	PrivateServer *s = user_data;
-	CloseConnectionInfo *info;
-
-	/* Clean up after the connection */
-	_LOGD ("(%s) closed connection %p on private socket", s->tag, conn);
-
-	info = g_slice_new0 (CloseConnectionInfo);
-	info->connection = conn;
-	info->server = s;
-	info->remote_peer_vanished = remote_peer_vanished;
-
-	g_object_ref (s->manager);
-
-	/* Delay the close of connection to ensure that D-Bus signals
-	 * are handled */
-	g_idle_add (close_connection_in_idle, info);
-}
-
-static gboolean
-private_server_new_connection (GDBusServer *server,
-                               GDBusConnection *conn,
-                               gpointer user_data)
-{
-	PrivateServer *s = user_data;
-	ObjectMgrData *obj_mgr_data;
-	static guint32 counter = 0;
-	GDBusObjectManagerServer *manager;
-	char *sender;
-
-	g_signal_connect (conn, "closed", G_CALLBACK (private_server_closed_connection), s);
-
-	/* Fake a sender since private connections don't have one */
-	sender = g_strdup_printf ("x:y:%d", counter++);
-
-	manager = g_dbus_object_manager_server_new (OBJECT_MANAGER_SERVER_BASE_PATH);
-	g_dbus_object_manager_server_set_connection (manager, conn);
-
-	obj_mgr_data = g_slice_new (ObjectMgrData);
-	obj_mgr_data->manager = manager;
-	obj_mgr_data->fake_sender = sender;
-	c_list_link_tail (&s->object_mgr_lst_head, &obj_mgr_data->object_mgr_lst);
-
-	_LOGD ("(%s) accepted connection %p on private socket", s->tag, conn);
-
-	/* Emit this for the manager.
-	 *
-	 * It is essential to do this from the "new-connection" signal handler, as
-	 * at that point no messages from the connection are yet processed
-	 * (which avoids races with registering objects). */
-	g_signal_emit (s->manager,
-	               signals[PRIVATE_CONNECTION_NEW],
-	               s->detail,
-	               conn,
-	               manager);
-	return TRUE;
-}
-
-static gboolean
-private_server_authorize (GDBusAuthObserver *observer,
-                          GIOStream         *stream,
-                          GCredentials      *credentials,
-                          gpointer           user_data)
-{
-	return g_credentials_get_unix_user (credentials, NULL) == 0;
-}
-
-static gboolean
-private_server_allow_mechanism (GDBusAuthObserver *observer,
-                                const char *mechanism,
-                                gpointer user_data)
-{
-	return NM_IN_STRSET (mechanism, "EXTERNAL");
-}
-
-static void
-private_server_free (gpointer ptr)
-{
-	PrivateServer *s = ptr;
-	ObjectMgrData *obj_mgr_data, *obj_mgr_data_safe;
-
-	c_list_unlink_stale (&s->private_servers_lst);
-
-	unlink (s->address);
-	g_free (s->address);
-
-	c_list_for_each_entry_safe (obj_mgr_data, obj_mgr_data_safe, &s->object_mgr_lst_head, object_mgr_lst)
-		_object_mgr_data_free (obj_mgr_data);
-
-	g_dbus_server_stop (s->server);
-
-	g_signal_handlers_disconnect_by_func (s->server, G_CALLBACK (private_server_new_connection), s);
-
-	g_object_unref (s->server);
-
-	g_slice_free (PrivateServer, s);
-}
-
-void
-nm_dbus_manager_private_server_register (NMDBusManager *self,
-                                         const char *path,
-                                         const char *tag)
-{
-	NMDBusManagerPrivate *priv;
-	PrivateServer *s;
-	gs_unref_object GDBusAuthObserver *auth_observer = NULL;
-	GDBusServer *server;
-	GError *error = NULL;
-	gs_free char *address = NULL;
-	gs_free char *guid = NULL;
-
-	g_return_if_fail (NM_IS_DBUS_MANAGER (self));
-	g_return_if_fail (path);
-	g_return_if_fail (tag);
-
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	/* Only one instance per tag; but don't warn */
-	c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
-		if (nm_streq0 (tag, s->tag))
-			return;
-	}
-
-	unlink (path);
-	address = g_strdup_printf ("unix:path=%s", path);
-
-	_LOGD ("(%s) creating private socket %s", tag, address);
-
-	guid = g_dbus_generate_guid ();
-	auth_observer = g_dbus_auth_observer_new ();
-	g_signal_connect (auth_observer, "authorize-authenticated-peer",
-	                  G_CALLBACK (private_server_authorize), NULL);
-	g_signal_connect (auth_observer, "allow-mechanism",
-	                  G_CALLBACK (private_server_allow_mechanism), NULL);
-	server = g_dbus_server_new_sync (address,
-	                                 G_DBUS_SERVER_FLAGS_NONE,
-	                                 guid,
-	                                 auth_observer,
-	                                 NULL, &error);
-
-	if (!server) {
-		_LOGW ("(%s) failed to set up private socket %s: %s",
-		       tag, address, error->message);
-		g_error_free (error);
-		return;
-	}
-
-	s = g_slice_new0 (PrivateServer);
-	s->address = g_steal_pointer (&address);
-	s->server = server;
-	g_signal_connect (server, "new-connection",
-	                  G_CALLBACK (private_server_new_connection), s);
-
-	c_list_init (&s->object_mgr_lst_head);
-
-	s->manager = self;
-	s->detail = g_quark_from_string (tag);
-	s->tag = g_quark_to_string (s->detail);
-
-	c_list_link_tail (&priv->private_servers_lst_head, &s->private_servers_lst);
-
-	g_dbus_server_start (server);
-}
-
-static const char *
-private_server_get_connection_owner (PrivateServer *s, GDBusConnection *connection)
-{
-	ObjectMgrData *obj_mgr_data;
-
-	nm_assert (s);
-	nm_assert (G_IS_DBUS_CONNECTION (connection));
-
-	c_list_for_each_entry (obj_mgr_data, &s->object_mgr_lst_head, object_mgr_lst) {
-		gs_unref_object GDBusConnection *c = NULL;
-
-		c = g_dbus_object_manager_server_get_connection (obj_mgr_data->manager);
-		if (c == connection)
-			return obj_mgr_data->fake_sender;
-	}
-	return NULL;
-}
-
-static GDBusConnection *
-private_server_get_connection_by_owner (PrivateServer *s, const char *owner)
-{
-	ObjectMgrData *obj_mgr_data;
-
-	nm_assert (s);
-	nm_assert (owner);
-
-	c_list_for_each_entry (obj_mgr_data, &s->object_mgr_lst_head, object_mgr_lst) {
-		if (nm_streq (owner, obj_mgr_data->fake_sender))
-			return g_dbus_object_manager_server_get_connection (obj_mgr_data->manager);
-	}
-	return NULL;
-}
-
-/*****************************************************************************/
-
-static gboolean
-_bus_get_unix_pid (NMDBusManager *self,
-                   const char *sender,
-                   gulong *out_pid,
-                   GError **error)
-{
-	guint32 unix_pid = G_MAXUINT32;
-	gs_unref_variant GVariant *ret = NULL;
-
-	ret = _nm_dbus_proxy_call_sync (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy,
-	                                "GetConnectionUnixProcessID",
-	                                g_variant_new ("(s)", sender),
-	                                G_VARIANT_TYPE ("(u)"),
-	                                G_DBUS_CALL_FLAGS_NONE, 2000,
-	                                NULL, error);
-	if (!ret)
-		return FALSE;
-
-	g_variant_get (ret, "(u)", &unix_pid);
-
-	*out_pid = (gulong) unix_pid;
-	return TRUE;
-}
-
-static gboolean
-_bus_get_unix_user (NMDBusManager *self,
-                    const char *sender,
-                    gulong *out_user,
-                    GError **error)
-{
-	guint32 unix_uid = G_MAXUINT32;
-	gs_unref_variant GVariant *ret = NULL;
-
-	ret = _nm_dbus_proxy_call_sync (NM_DBUS_MANAGER_GET_PRIVATE (self)->proxy,
-	                                "GetConnectionUnixUser",
-	                                g_variant_new ("(s)", sender),
-	                                G_VARIANT_TYPE ("(u)"),
-	                                G_DBUS_CALL_FLAGS_NONE, 2000,
-	                                NULL, error);
-	if (!ret)
-		return FALSE;
-
-	g_variant_get (ret, "(u)", &unix_uid);
-
-	*out_user = (gulong) unix_uid;
-	return TRUE;
-}
-
-/**
- * _get_caller_info():
- *
- * Given a GDBus method invocation, or a GDBusConnection + GDBusMessage,
- * return the sender and the UID of the sender.
- */
-static gboolean
-_get_caller_info (NMDBusManager *self,
-                  GDBusMethodInvocation *context,
-                  GDBusConnection *connection,
-                  GDBusMessage *message,
-                  char **out_sender,
-                  gulong *out_uid,
-                  gulong *out_pid)
-{
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	const char *sender;
-
-	if (context) {
-		connection = g_dbus_method_invocation_get_connection (context);
-
-		/* only bus connections will have a sender */
-		sender = g_dbus_method_invocation_get_sender (context);
-	} else {
-		g_assert (message);
-		sender = g_dbus_message_get_sender (message);
-	}
-	g_assert (connection);
-
-	if (!sender) {
-		PrivateServer *s;
-
-		/* Might be a private connection, for which we fake a sender */
-		c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
-			sender = private_server_get_connection_owner (s, connection);
-			if (sender) {
-				if (out_uid)
-					*out_uid = 0;
-				if (out_sender)
-					*out_sender = g_strdup (sender);
-				if (out_pid) {
-					GCredentials *creds;
-
-					creds = g_dbus_connection_get_peer_credentials (connection);
-					if (creds) {
-						pid_t pid;
-
-						pid = g_credentials_get_unix_pid (creds, NULL);
-						if (pid == -1)
-							*out_pid = G_MAXULONG;
-						else
-							*out_pid = pid;
-					} else
-						*out_pid = G_MAXULONG;
-				}
-				return TRUE;
-			}
-		}
-		return FALSE;
-	}
-
-	/* Bus connections always have a sender */
-	g_assert (sender);
-	if (out_uid) {
-		if (!_bus_get_unix_user (self, sender, out_uid, NULL)) {
-			*out_uid = G_MAXULONG;
-			return FALSE;
-		}
-	}
-
-	if (out_pid) {
-		if (!_bus_get_unix_pid (self, sender, out_pid, NULL)) {
-			*out_pid = G_MAXULONG;
-			return FALSE;
-		}
-	}
-
-	if (out_sender)
-		*out_sender = g_strdup (sender);
-
-	return TRUE;
-}
-
-gboolean
-nm_dbus_manager_get_caller_info (NMDBusManager *self,
-                                 GDBusMethodInvocation *context,
-                                 char **out_sender,
-                                 gulong *out_uid,
-                                 gulong *out_pid)
-{
-	return _get_caller_info (self, context, NULL, NULL, out_sender, out_uid, out_pid);
-}
-
-gboolean
-nm_dbus_manager_get_caller_info_from_message (NMDBusManager *self,
-                                              GDBusConnection *connection,
-                                              GDBusMessage *message,
-                                              char **out_sender,
-                                              gulong *out_uid,
-                                              gulong *out_pid)
-{
-	return _get_caller_info (self, NULL, connection, message, out_sender, out_uid, out_pid);
-}
-
-/**
- * nm_dbus_manager_ensure_uid:
- *
- * @self: bus manager instance
- * @context: D-Bus method invocation
- * @uid: a user-id
- * @error_domain: error domain to return on failure
- * @error_code: error code to return on failure
- *
- * Retrieves the uid of the D-Bus method caller and
- * checks that it matches @uid, unless @uid is G_MAXULONG.
- * In case of failure the function returns FALSE and finishes
- * handling the D-Bus method with an error.
- *
- * Returns: %TRUE if the check succeeded, %FALSE otherwise
- */
-gboolean
-nm_dbus_manager_ensure_uid (NMDBusManager          *self,
-                            GDBusMethodInvocation *context,
-                            gulong uid,
-                            GQuark error_domain,
-                            int error_code)
-{
-	gulong caller_uid;
-	GError *error = NULL;
-
-	g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), FALSE);
-	g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (context), FALSE);
-
-	if (!nm_dbus_manager_get_caller_info (self, context, NULL, &caller_uid, NULL)) {
-		error = g_error_new_literal (error_domain,
-		                             error_code,
-		                             "Unable to determine request UID.");
-		g_dbus_method_invocation_take_error (context, error);
-		return FALSE;
-	}
-
-	if (uid != G_MAXULONG && caller_uid != uid) {
-		error = g_error_new_literal (error_domain,
-		                             error_code,
-		                             "Permission denied");
-		g_dbus_method_invocation_take_error (context, error);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-gboolean
-nm_dbus_manager_get_unix_user (NMDBusManager *self,
-                               const char *sender,
-                               gulong *out_uid)
-{
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	PrivateServer *s;
-	GError *error = NULL;
-
-	g_return_val_if_fail (sender != NULL, FALSE);
-	g_return_val_if_fail (out_uid != NULL, FALSE);
-
-	/* Check if it's a private connection sender, which we fake */
-	c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
-		gs_unref_object GDBusConnection *connection = NULL;
-
-		connection = private_server_get_connection_by_owner (s, sender);
-		if (connection) {
-			*out_uid = 0;
-			return TRUE;
-		}
-	}
-
-	/* Otherwise, a bus connection */
-	if (!_bus_get_unix_user (self, sender, out_uid, &error)) {
-		_LOGW ("failed to get unix user for dbus sender '%s': %s",
-		       sender, error->message);
-		g_error_free (error);
-		return FALSE;
-	}
-
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_dbus_manager_connection_get_private_name (NMDBusManager *self,
-                                             GDBusConnection *connection)
-{
-	NMDBusManagerPrivate *priv;
-	PrivateServer *s;
-	const char *owner;
-
-	g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), FALSE);
-	g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
-
-	if (g_dbus_connection_get_unique_name (connection)) {
-		/* Shortcut. The connection is not a private connection. */
-		return NULL;
-	}
-
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	c_list_for_each_entry (s, &priv->private_servers_lst_head, private_servers_lst) {
-		if ((owner = private_server_get_connection_owner (s, connection)))
-			return owner;
-	}
-	g_return_val_if_reached (NULL);
-}
-
-/**
- * nm_dbus_manager_new_proxy:
- * @self: the #NMDBusManager
- * @connection: the GDBusConnection for which this connection should be created
- * @proxy_type: the type of #GDBusProxy to create
- * @name: any name on the message bus
- * @path: name of the object instance to call methods on
- * @iface: name of the interface to call methods on
- *
- * Creates a new proxy (of type @proxy_type) for a name on a given bus.  Since
- * the process which called the D-Bus method could be coming from a private
- * connection or the system bus connection, different proxies must be created
- * for each case.  This function abstracts that.
- *
- * Returns: a #GDBusProxy capable of calling D-Bus methods of the calling process
- */
-GDBusProxy *
-nm_dbus_manager_new_proxy (NMDBusManager *self,
-                           GDBusConnection *connection,
-                           GType proxy_type,
-                           const char *name,
-                           const char *path,
-                           const char *iface)
-{
-	const char *owner;
-	GDBusProxy *proxy;
-	GError *error = NULL;
-
-	g_return_val_if_fail (g_type_is_a (proxy_type, G_TYPE_DBUS_PROXY), NULL);
-	g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
-
-	/* Might be a private connection, for which @name is fake */
-	owner = nm_dbus_manager_connection_get_private_name (self, connection);
-	if (owner) {
-		g_return_val_if_fail (!g_strcmp0 (owner, name), NULL);
-		name = NULL;
-	}
-
-	proxy = g_initable_new (proxy_type, NULL, &error,
-	                        "g-connection", connection,
-	                        "g-flags", (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-	                                    G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS),
-	                        "g-name", name,
-	                        "g-object-path", path,
-	                        "g-interface-name", iface,
-	                        NULL);
-	if (!proxy) {
-		_LOGW ("could not create proxy for %s on connection %s: %s",
-		       iface, name, error->message);
-		g_error_free (error);
-	}
-	return proxy;
-}
-
-/*****************************************************************************/
-
-GDBusConnection *
-nm_dbus_manager_get_connection (NMDBusManager *self)
-{
-	g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), NULL);
-
-	return NM_DBUS_MANAGER_GET_PRIVATE (self)->connection;
-}
-
-/*****************************************************************************/
-
-static const NMDBusInterfaceInfoExtended *
-_reg_data_get_interface_info (RegistrationData *reg_data)
-{
-	nm_assert (reg_data);
-
-	return reg_data->klass->interface_infos[reg_data->info_idx];
-}
-
-/*****************************************************************************/
-
-static void
-dbus_vtable_method_call (GDBusConnection *connection,
-                         const char *sender,
-                         const char *object_path,
-                         const char *interface_name,
-                         const char *method_name,
-                         GVariant *parameters,
-                         GDBusMethodInvocation *invocation,
-                         gpointer user_data)
-{
-	RegistrationData *reg_data = user_data;
-	NMDBusObject *obj = reg_data->obj;
-	const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-	const NMDBusMethodInfoExtended *method_info = NULL;
-	gboolean on_same_interface;
-
-	on_same_interface = nm_streq (interface_info->parent.name, interface_name);
-
-	/* handle property setter first... */
-	if (   !on_same_interface
-	    && nm_streq (interface_name, DBUS_INTERFACE_PROPERTIES)
-	    && nm_streq (method_name, "Set")) {
-		NMDBusManager *self = nm_dbus_object_get_manager (obj);
-		NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-		const NMDBusPropertyInfoExtended *property_info = NULL;
-		const char *property_interface;
-		const char *property_name;
-		gs_unref_variant GVariant *value = NULL;
-
-		g_variant_get (parameters, "(&s&sv)", &property_interface, &property_name, &value);
-
-		nm_assert (nm_streq (property_interface, interface_info->parent.name));
-
-		property_info = (const NMDBusPropertyInfoExtended *) nm_dbus_utils_interface_info_lookup_property (&interface_info->parent,
-		                                                                                                   property_name,
-		                                                                                                   NULL);
-		if (   !property_info
-		    || !NM_FLAGS_HAS (property_info->parent.flags, G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE))
-			g_return_if_reached ();
-
-		if (!priv->set_property_handler) {
-			g_dbus_method_invocation_return_error (invocation,
-			                                       G_DBUS_ERROR,
-			                                       G_DBUS_ERROR_AUTH_FAILED,
-			                                       "Cannot authenticate setting property %s",
-			                                       property_name);
-			return;
-		}
-
-		priv->set_property_handler (obj,
-		                            interface_info,
-		                            property_info,
-		                            connection,
-		                            sender,
-		                            invocation,
-		                            value,
-		                            priv->set_property_handler_data);
-		return;
-	}
-
-	if (on_same_interface) {
-		method_info = (const NMDBusMethodInfoExtended *) nm_dbus_utils_interface_info_lookup_method (&interface_info->parent,
-		                                                                                             method_name);
-	}
-	if (!method_info) {
-		g_dbus_method_invocation_return_error (invocation,
-		                                       G_DBUS_ERROR,
-		                                       G_DBUS_ERROR_UNKNOWN_METHOD,
-		                                       "Unknown method %s",
-		                                       method_name);
-		return;
-	}
-
-	method_info->handle (reg_data->obj,
-	                     interface_info,
-	                     method_info,
-	                     connection,
-	                     sender,
-	                     invocation,
-	                     parameters);
-}
-
-static GVariant *
-_obj_get_property (RegistrationData *reg_data,
-                   guint property_idx,
-                   gboolean refetch)
-{
-	const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-	const NMDBusPropertyInfoExtended *property_info;
-	GVariant *value;
-
-	property_info = (const NMDBusPropertyInfoExtended *) (interface_info->parent.properties[property_idx]);
-
-	if (refetch)
-		nm_clear_g_variant (&reg_data->property_cache[property_idx].value);
-	else {
-		value = reg_data->property_cache[property_idx].value;
-		if (value)
-			goto out;
-	}
-
-	value = nm_dbus_utils_get_property (G_OBJECT (reg_data->obj),
-	                                    property_info->parent.signature,
-	                                    property_info->property_name);
-	reg_data->property_cache[property_idx].value = value;
-out:
-	return g_variant_ref (value);
-}
-
-static GVariant *
-dbus_vtable_get_property (GDBusConnection *connection,
-                          const char *sender,
-                          const char *object_path,
-                          const char *interface_name,
-                          const char *property_name,
-                          GError **error,
-                          gpointer user_data)
-{
-	RegistrationData *reg_data = user_data;
-	const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-	guint property_idx;
-
-	if (!nm_dbus_utils_interface_info_lookup_property (&interface_info->parent,
-	                                                   property_name,
-	                                                   &property_idx))
-		g_return_val_if_reached (NULL);
-
-	return _obj_get_property (reg_data, property_idx, FALSE);
-}
-
-static const GDBusInterfaceVTable dbus_vtable = {
-	.method_call = dbus_vtable_method_call,
-	.get_property = dbus_vtable_get_property,
-
-	/* set_property is handled via method_call as well. We need to authenticate
-	 * which requires an asynchronous handler. */
-	.set_property = NULL,
-};
-
-static void
-_obj_register (NMDBusManager *self,
-               NMDBusObject *obj)
-{
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	guint i, k;
-	guint n_klasses;
-	GType gtype;
-	NMDBusObjectClass *klasses[10];
-	const NMDBusInterfaceInfoExtended *const*prev_interface_infos = NULL;
-	GVariantBuilder builder;
-
-	nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
-	nm_assert (priv->connection);
-
-	n_klasses = 0;
-	gtype = G_OBJECT_TYPE (obj);
-	while (gtype != NM_TYPE_DBUS_OBJECT) {
-		nm_assert (n_klasses < G_N_ELEMENTS (klasses));
-		klasses[n_klasses++] = g_type_class_ref (gtype);
-		gtype = g_type_parent (gtype);
-	}
-
-	for (k = n_klasses; k > 0; ) {
-		NMDBusObjectClass *klass = NM_DBUS_OBJECT_CLASS (klasses[--k]);
-
-		if (!klass->interface_infos)
-			continue;
-
-		if (prev_interface_infos == klass->interface_infos) {
-			/* derived classes inherrit the interface-infos from the parent class.
-			 * For convenience, we allow the subclass to leave interface-infos untouched,
-			 * but it means we must ignore the parent's interface, because we already
-			 * handled it.
-			 *
-			 * Note that the loop goes from the parent classes to child classes */
-			continue;
-		}
-		prev_interface_infos = klass->interface_infos;
-
-		for (i = 0; klass->interface_infos[i]; i++) {
-			const NMDBusInterfaceInfoExtended *interface_info = klass->interface_infos[i];
-			RegistrationData *reg_data;
-			gs_free_error GError *error = NULL;
-			guint registration_id;
-			guint prop_len = NM_PTRARRAY_LEN (interface_info->parent.properties);
-
-			reg_data = g_malloc0 (sizeof (RegistrationData) + (sizeof (PropertyCacheData) * prop_len));
-
-			registration_id = g_dbus_connection_register_object (priv->connection,
-			                                                     obj->internal.path,
-			                                                     NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info->parent),
-			                                                     &dbus_vtable,
-			                                                     reg_data,
-			                                                     NULL,
-			                                                     &error);
-			if (!registration_id) {
-				_LOGE ("failure to register object %s: %s", obj->internal.path, error->message);
-				g_free (reg_data);
-				continue;
-			}
-
-			reg_data->obj = obj;
-			reg_data->klass = g_type_class_ref (G_TYPE_FROM_CLASS (klass));
-			reg_data->info_idx = i;
-			reg_data->registration_id = registration_id;
-			c_list_link_tail (&obj->internal.registration_lst_head, &reg_data->registration_lst);
-		}
-	}
-
-	for (k = 0; k < n_klasses; k++)
-		g_type_class_unref (klasses[k]);
-
-	nm_assert (!c_list_is_empty (&obj->internal.registration_lst_head));
-
-	/* Currently the interfaces of an object do not changed and strictly depend on the object glib type.
-	 * We don't need more flixibility, and it simplifies the code. Hence, now emit interface-added
-	 * signal for the new object.
-	 *
-	 * Warning: note that if @obj's notify signal is currently blocked via g_object_freeze_notify(),
-	 * we might emit properties with an inconsistent (internal) state. There is no easy solution,
-	 * because we have to emit the signal now, and we don't know what the correct desired state
-	 * of the properties is.
-	 * Another problem is, upon unfreezing the signals, we immediately send PropertiesChanged
-	 * notifications out. Which is a bit odd, as we just export the object.
-	 *
-	 * In general, it's ok to export an object with frozen signals. But you better make sure
-	 * that all properties are in a self-consistent state when exporting the object. */
-	g_dbus_connection_emit_signal (priv->connection,
-	                               NULL,
-	                               OBJECT_MANAGER_SERVER_BASE_PATH,
-	                               interface_info_objmgr.name,
-	                               signal_info_objmgr_interfaces_added.name,
-	                               g_variant_new ("(oa{sa{sv}})",
-	                                              obj->internal.path,
-	                                              _obj_collect_properties_all (obj, &builder)),
-	                               NULL);
-}
-
-static void
-_obj_unregister (NMDBusManager *self,
-                 NMDBusObject *obj)
-{
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	RegistrationData *reg_data;
-	GVariantBuilder builder;
-
-	nm_assert (NM_IS_DBUS_OBJECT (obj));
-
-	if (!priv->connection) {
-		/* nothing to do for the moment. */
-		nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
-		return;
-	}
-
-	nm_assert (!c_list_is_empty (&obj->internal.registration_lst_head));
-	nm_assert (priv->objmgr_registration_id);
-
-	g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
-
-	while ((reg_data = c_list_last_entry (&obj->internal.registration_lst_head, RegistrationData, registration_lst))) {
-		const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-		guint i;
-
-		g_variant_builder_add (&builder,
-		                       "s",
-		                       interface_info->parent.name);
-		c_list_unlink_stale (&reg_data->registration_lst);
-		if (!g_dbus_connection_unregister_object (priv->connection, reg_data->registration_id))
-			nm_assert_not_reached ();
-
-		if (interface_info->parent.properties) {
-			for (i = 0; interface_info->parent.properties[i]; i++)
-				nm_clear_g_variant (&reg_data->property_cache[i].value);
-		}
-
-		g_type_class_unref (reg_data->klass);
-		g_free (reg_data);
-	}
-
-	g_dbus_connection_emit_signal (priv->connection,
-	                               NULL,
-	                               OBJECT_MANAGER_SERVER_BASE_PATH,
-	                               interface_info_objmgr.name,
-	                               signal_info_objmgr_interfaces_removed.name,
-	                               g_variant_new ("(oas)",
-	                                              obj->internal.path,
-	                                              &builder),
-	                               NULL);
-}
-
-NMDBusObject *
-nm_dbus_manager_lookup_object (NMDBusManager *self, const char *path)
-{
-	NMDBusManagerPrivate *priv;
-	gpointer ptr;
-	NMDBusObject *obj;
-
-	g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), NULL);
-	g_return_val_if_fail (path, NULL);
-
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	ptr = g_hash_table_lookup (priv->objects_by_path, &path);
-	if (!ptr)
-		return NULL;
-
-	obj = (NMDBusObject *) (((char *) ptr) - G_STRUCT_OFFSET (NMDBusObject, internal));
-	nm_assert (NM_IS_DBUS_OBJECT (obj));
-	return obj;
-}
-
-void
-_nm_dbus_manager_obj_export (NMDBusObject *obj)
-{
-	NMDBusManager *self;
-	NMDBusManagerPrivate *priv;
-
-	g_return_if_fail (NM_IS_DBUS_OBJECT (obj));
-	g_return_if_fail (obj->internal.path);
-	g_return_if_fail (NM_IS_DBUS_MANAGER (obj->internal.bus_manager));
-	g_return_if_fail (c_list_is_empty (&obj->internal.objects_lst));
-	nm_assert (c_list_is_empty (&obj->internal.registration_lst_head));
-
-	self = obj->internal.bus_manager;
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	if (!g_hash_table_add (priv->objects_by_path, &obj->internal))
-		nm_assert_not_reached ();
-	c_list_link_tail (&priv->objects_lst_head, &obj->internal.objects_lst);
-
-	if (priv->connection)
-		_obj_register (self, obj);
-}
-
-void
-_nm_dbus_manager_obj_unexport (NMDBusObject *obj)
-{
-	NMDBusManager *self;
-	NMDBusManagerPrivate *priv;
-
-	g_return_if_fail (NM_IS_DBUS_OBJECT (obj));
-	g_return_if_fail (obj->internal.path);
-	g_return_if_fail (NM_IS_DBUS_MANAGER (obj->internal.bus_manager));
-	g_return_if_fail (!c_list_is_empty (&obj->internal.objects_lst));
-
-	self = obj->internal.bus_manager;
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	nm_assert (&obj->internal == g_hash_table_lookup (priv->objects_by_path, &obj->internal));
-	nm_assert (c_list_contains (&priv->objects_lst_head, &obj->internal.objects_lst));
-
-	_obj_unregister (self, obj);
-
-	if (!g_hash_table_remove (priv->objects_by_path, &obj->internal))
-		nm_assert_not_reached ();
-	c_list_unlink (&obj->internal.objects_lst);
-}
-
-void
-_nm_dbus_manager_obj_notify (NMDBusObject *obj,
-                             guint n_pspecs,
-                             const GParamSpec *const*pspecs)
-{
-	NMDBusManager *self;
-	NMDBusManagerPrivate *priv;
-	RegistrationData *reg_data;
-	guint i, p;
-	gboolean any_legacy_signals = FALSE;
-	gboolean any_legacy_properties = FALSE;
-	GVariantBuilder legacy_builder;
-	GVariant *device_statistics_args = NULL;
-
-	nm_assert (NM_IS_DBUS_OBJECT (obj));
-	nm_assert (obj->internal.path);
-	nm_assert (NM_IS_DBUS_MANAGER (obj->internal.bus_manager));
-	nm_assert (!c_list_is_empty (&obj->internal.objects_lst));
-
-	c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) {
-		if (_reg_data_get_interface_info (reg_data)->legacy_property_changed) {
-			any_legacy_signals = TRUE;
-			break;
-		}
-	}
-
-	self = obj->internal.bus_manager;
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	/* do a naive search for the matching NMDBusPropertyInfoExtended infos. Since the number of
-	 * (interaces x properties) is static and possibly small, this naive search is effectively
-	 * O(1). We might wanna introduce some index to lookup the properties in question faster.
-	 *
-	 * The nice part of this implementation is however, that the order in which properties
-	 * are added to the GVariant is strictly defined to be the order in which the D-Bus property-info
-	 * is declared. Getting a defined ordering with some smart lookup would be hard. */
-	c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) {
-		const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-		gboolean has_properties = FALSE;
-		GVariantBuilder builder;
-		GVariantBuilder invalidated_builder;
-		GVariant *args;
-
-		if (!interface_info->parent.properties)
-			continue;
-
-		for (i = 0; interface_info->parent.properties[i]; i++) {
-			const NMDBusPropertyInfoExtended *property_info = (const NMDBusPropertyInfoExtended *) interface_info->parent.properties[i];
-
-			for (p = 0; p < n_pspecs; p++) {
-				const GParamSpec *pspec = pspecs[p];
-				gs_unref_variant GVariant *value = NULL;
-
-				if (!nm_streq (property_info->property_name, pspec->name))
-					continue;
-
-				value = _obj_get_property (reg_data, i, TRUE);
-
-				if (   property_info->include_in_legacy_property_changed
-				    && any_legacy_signals) {
-					/* also track the value in the legacy_builder to emit legacy signals below. */
-					if (!any_legacy_properties) {
-						any_legacy_properties = TRUE;
-						g_variant_builder_init (&legacy_builder, G_VARIANT_TYPE ("a{sv}"));
-					}
-					g_variant_builder_add (&legacy_builder, "{sv}", property_info->parent.name, value);
-				}
-
-				if (!has_properties) {
-					has_properties = TRUE;
-					g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
-				}
-				g_variant_builder_add (&builder, "{sv}", property_info->parent.name, value);
-			}
-		}
-
-		if (!has_properties)
-			continue;
-
-		args = g_variant_builder_end (&builder);
-
-		if (G_UNLIKELY (interface_info == &nm_interface_info_device_statistics)) {
-			/* we treat the Device.Statistics signal special, because we need to
-			 * emit a signal also for it (below). */
-			nm_assert (!device_statistics_args);
-			device_statistics_args = g_variant_ref_sink (args);
-		}
-
-		g_variant_builder_init (&invalidated_builder, G_VARIANT_TYPE ("as"));
-		g_dbus_connection_emit_signal (priv->connection,
-		                               NULL,
-		                               obj->internal.path,
-		                               "org.freedesktop.DBus.Properties",
-		                               "PropertiesChanged",
-		                               g_variant_new ("(s@a{sv}as)",
-		                                              interface_info->parent.name,
-		                                              args,
-		                                              &invalidated_builder),
-		                               NULL);
-	}
-
-	if (G_UNLIKELY (device_statistics_args)) {
-		/* this is a special interface: it has a legacy PropertiesChanged signal,
-		 * however, contrary to other interfaces with ~regular~ legacy signals,
-		 * we only notify about properties that actually belong to this interface. */
-		g_dbus_connection_emit_signal (priv->connection,
-		                               NULL,
-		                               obj->internal.path,
-		                               nm_interface_info_device_statistics.parent.name,
-		                               "PropertiesChanged",
-		                               g_variant_new ("(@a{sv})",
-		                                              device_statistics_args),
-		                               NULL);
-		g_variant_unref (device_statistics_args);
-	}
-
-	if (any_legacy_properties) {
-		gs_unref_variant GVariant *args = NULL;
-
-		/* The legacy PropertyChanged signal on the NetworkManager D-Bus interface is
-		 * deprecated for the standard signal on org.freedesktop.DBus.Properties. However,
-		 * for backward compatibility, we still need to emit it.
-		 *
-		 * Due to a bug in dbus-glib in NetworkManager <= 1.0, the signal would
-		 * not only notify about properties that were actually on the corresponding
-		 * D-Bus interface. Instead, it would notify about all relevant properties
-		 * on all interfaces that had such a signal.
-		 *
-		 * For example, "HwAddress" gets emitted both on "fdo.NM.Device.Ethernet"
-		 * and "fdo.NM.Device.Veth" for veth interfaces, although only the former
-		 * actually has such a property.
-		 * Also note that "fdo.NM.Device" interface has no legacy signal. All notifications
-		 * about its properties are instead emitted on the interfaces of the subtypes.
-		 *
-		 * See bgo#770629 and commit bef26a2e69f51259095fa080221db73de09fd38d.
-		 */
-		args = g_variant_ref_sink (g_variant_new ("(a{sv})",
-		                                          &legacy_builder));
-		c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) {
-			const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-
-			if (interface_info->legacy_property_changed) {
-				g_dbus_connection_emit_signal (priv->connection,
-				                               NULL,
-				                               obj->internal.path,
-				                               interface_info->parent.name,
-				                               "PropertiesChanged",
-				                               args,
-				                               NULL);
-			}
-		}
-	}
-}
-
-void
-_nm_dbus_manager_obj_emit_signal (NMDBusObject *obj,
-                                  const NMDBusInterfaceInfoExtended *interface_info,
-                                  const GDBusSignalInfo *signal_info,
-                                  GVariant *args)
-{
-	NMDBusManager *self;
-	NMDBusManagerPrivate *priv;
-
-	g_return_if_fail (NM_IS_DBUS_OBJECT (obj));
-	g_return_if_fail (obj->internal.path);
-	g_return_if_fail (NM_IS_DBUS_MANAGER (obj->internal.bus_manager));
-	g_return_if_fail (!c_list_is_empty (&obj->internal.objects_lst));
-
-	self = obj->internal.bus_manager;
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	if (!priv->connection) {
-		nm_g_variant_unref_floating (args);
-		return;
-	}
-
-	g_dbus_connection_emit_signal (priv->connection,
-	                               NULL,
-	                               obj->internal.path,
-	                               interface_info->parent.name,
-	                               signal_info->name,
-	                               args,
-	                               NULL);
-}
-
-/*****************************************************************************/
-
-static GVariantBuilder *
-_obj_collect_properties_per_interface (NMDBusObject *obj,
-                                       RegistrationData *reg_data,
-                                       GVariantBuilder *builder)
-{
-	const NMDBusInterfaceInfoExtended *interface_info = _reg_data_get_interface_info (reg_data);
-	guint i;
-
-	g_variant_builder_init (builder, G_VARIANT_TYPE ("a{sv}"));
-	if (interface_info->parent.properties) {
-		for (i = 0; interface_info->parent.properties[i]; i++) {
-			const NMDBusPropertyInfoExtended *property_info = (const NMDBusPropertyInfoExtended *) interface_info->parent.properties[i];
-			gs_unref_variant GVariant *variant = NULL;
-
-			variant = _obj_get_property (reg_data, i, FALSE);
-			g_variant_builder_add (builder,
-			                       "{sv}",
-			                       property_info->parent.name,
-			                       variant);
-		}
-	}
-	return builder;
-}
-
-static GVariantBuilder *
-_obj_collect_properties_all (NMDBusObject *obj,
-                             GVariantBuilder *builder)
-{
-	RegistrationData *reg_data;
-
-	g_variant_builder_init (builder, G_VARIANT_TYPE ("a{sa{sv}}"));
-
-	c_list_for_each_entry (reg_data, &obj->internal.registration_lst_head, registration_lst) {
-		GVariantBuilder properties_builder;
-
-		g_variant_builder_add (builder,
-		                       "{sa{sv}}",
-		                       _reg_data_get_interface_info (reg_data)->parent.name,
-		                       _obj_collect_properties_per_interface (obj,
-		                                                              reg_data,
-		                                                              &properties_builder));
-	}
-
-	return builder;
-}
-
-static void
-dbus_vtable_objmgr_method_call (GDBusConnection *connection,
-                                const char *sender,
-                                const char *object_path,
-                                const char *interface_name,
-                                const char *method_name,
-                                GVariant *parameters,
-                                GDBusMethodInvocation *invocation,
-                                gpointer user_data)
-{
-	NMDBusManager *self = user_data;
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	GVariantBuilder array_builder;
-	NMDBusObject *obj;
-
-	nm_assert (nm_streq0 (object_path, OBJECT_MANAGER_SERVER_BASE_PATH));
-
-	if (   !nm_streq (method_name, "GetManagedObjects")
-	    || !nm_streq (interface_name, interface_info_objmgr.name)) {
-		g_dbus_method_invocation_return_error (invocation,
-		                                       G_DBUS_ERROR,
-		                                       G_DBUS_ERROR_UNKNOWN_METHOD,
-		                                       "Unknown method %s - only GetManagedObjects() is supported",
-		                                       method_name);
-		return;
-	}
-
-	g_variant_builder_init (&array_builder, G_VARIANT_TYPE ("a{oa{sa{sv}}}"));
-	c_list_for_each_entry (obj, &priv->objects_lst_head, internal.objects_lst) {
-		GVariantBuilder interfaces_builder;
-
-		/* note that we are called on an idle handler. Hence, all properties are
-		 * supposed to be in a consistent state. That is true, if you always
-		 * g_object_thaw_notify() before returning to the mainloop. Keeping
-		 * signals frozen between while returning from the current call stack
-		 * is anyway a very fragile thing, easy to get wrong. Don't do that. */
-		g_variant_builder_add (&array_builder,
-		                       "{oa{sa{sv}}}",
-		                       obj->internal.path,
-		                       _obj_collect_properties_all (obj,
-		                                                    &interfaces_builder));
-	}
-	g_dbus_method_invocation_return_value (invocation,
-	                                       g_variant_new ("(a{oa{sa{sv}}})",
-	                                                      &array_builder));
-}
-
-static const GDBusInterfaceVTable dbus_vtable_objmgr = {
-	.method_call = dbus_vtable_objmgr_method_call
-};
-
-static const GDBusSignalInfo signal_info_objmgr_interfaces_added = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
-	"InterfacesAdded",
-	.args = NM_DEFINE_GDBUS_ARG_INFOS (
-		NM_DEFINE_GDBUS_ARG_INFO ("object_path",               "o"),
-		NM_DEFINE_GDBUS_ARG_INFO ("interfaces_and_properties", "a{sa{sv}}"),
-	),
-);
-
-static const GDBusSignalInfo signal_info_objmgr_interfaces_removed = NM_DEFINE_GDBUS_SIGNAL_INFO_INIT (
-	"InterfacesRemoved",
-	.args = NM_DEFINE_GDBUS_ARG_INFOS (
-		NM_DEFINE_GDBUS_ARG_INFO ("object_path", "o"),
-		NM_DEFINE_GDBUS_ARG_INFO ("interfaces",  "as"),
-	),
-);
-
-static const GDBusInterfaceInfo interface_info_objmgr = NM_DEFINE_GDBUS_INTERFACE_INFO_INIT (
-	"org.freedesktop.DBus.ObjectManager",
-	.methods = NM_DEFINE_GDBUS_METHOD_INFOS (
-		NM_DEFINE_GDBUS_METHOD_INFO (
-			"GetManagedObjects",
-			.out_args = NM_DEFINE_GDBUS_ARG_INFOS (
-				NM_DEFINE_GDBUS_ARG_INFO ("object_paths_interfaces_and_properties", "a{oa{sa{sv}}}"),
-			),
-		),
-	),
-	.signals = NM_DEFINE_GDBUS_SIGNAL_INFOS (
-		&signal_info_objmgr_interfaces_added,
-		&signal_info_objmgr_interfaces_removed,
-	),
-);
-
-/*****************************************************************************/
-
-gboolean
-nm_dbus_manager_start (NMDBusManager *self,
-                       NMDBusManagerSetPropertyHandler set_property_handler,
-                       gpointer set_property_handler_data)
-{
-	NMDBusManagerPrivate *priv;
-	gs_free_error GError *error = NULL;
-	gs_unref_variant GVariant *ret = NULL;
-	gs_unref_object GDBusConnection *connection = NULL;
-	gs_unref_object GDBusProxy *proxy = NULL;
-	guint32 result;
-	guint registration_id;
-	NMDBusObject *obj;
-
-	g_return_val_if_fail (NM_IS_DBUS_MANAGER (self), FALSE);
-
-	priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	priv->set_property_handler = set_property_handler;
-	priv->set_property_handler_data = set_property_handler_data;
-
-	g_return_val_if_fail (!priv->connection, FALSE);
-
-	/* we will create the D-Bus connection and registering the name synchronously.
-	 * The reason why that is necessary is because:
-	 *  (1) if we are unable to create a D-Bus connection, it means D-Bus is not
-	 *    available and we run in D-Bus less mode. We do not support creating
-	 *    a D-Bus connection later on. This disconnected mode is useful for initrd
-	 *    (well, currently not yet, but will be).
-	 *  (2) if we are able to create the connection and register the name,
-	 *    all is good and we run with D-Bus. Note that D-Bus disconnects
-	 *    from D-Bus are ignored. Essentially, we do not support restarting
-	 *    D-Bus.
-	 *  (3) if we are able to create the connection but registration fails,
-	 *    it means that something is borked. Quite possibly another NetworkManager
-	 *    instance is running. We need to exit right away.
-	 * To appease (1) and (3), we cannot initalize synchronously, because we need
-	 * to know right away whether another NetworkManager instance is running (3).
-	 **/
-
-	connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
-	                             NULL,
-	                             &error);
-	if (!connection) {
-		_LOGI ("cannot connect to D-Bus and proceed without (%s)", error->message);
-		return TRUE;
-	}
-
-	g_dbus_connection_set_exit_on_close (connection, FALSE);
-
-	proxy = g_dbus_proxy_new_sync (connection,
-	                                 G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES
-	                               | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-	                               NULL,
-	                               DBUS_SERVICE_DBUS,
-	                               DBUS_PATH_DBUS,
-	                               DBUS_INTERFACE_DBUS,
-	                               NULL,
-	                               &error);
-	if (!proxy) {
-		_LOGE ("fatal failure to initialize D-Bus: %s", error->message);
-		return FALSE;
-	}
-
-	ret = _nm_dbus_proxy_call_sync (proxy,
-	                                "RequestName",
-	                                g_variant_new ("(su)",
-	                                               NM_DBUS_SERVICE,
-	                                               DBUS_NAME_FLAG_DO_NOT_QUEUE),
-	                                G_VARIANT_TYPE ("(u)"),
-	                                G_DBUS_CALL_FLAGS_NONE, -1,
-	                                NULL,
-	                                &error);
-	if (!ret) {
-		_LOGE ("fatal failure to aquire D-Bus service \"%s"": %s",
-		       NM_DBUS_SERVICE, error->message);
-		return FALSE;
-	}
-
-	g_variant_get (ret, "(u)", &result);
-	if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
-		_LOGE ("fatal failure to acquire D-Bus service \"%s\" (%u). Service already taken",
-		       NM_DBUS_SERVICE, (guint) result);
-		return FALSE;
-	}
-
-	registration_id = g_dbus_connection_register_object (connection,
-	                                                     OBJECT_MANAGER_SERVER_BASE_PATH,
-	                                                     NM_UNCONST_PTR (GDBusInterfaceInfo, &interface_info_objmgr),
-	                                                     &dbus_vtable_objmgr,
-	                                                     self,
-	                                                     NULL,
-	                                                     &error);
-	if (!registration_id) {
-		_LOGE ("failure to register object manager: %s", error->message);
-		return FALSE;
-	}
-
-	priv->objmgr_registration_id = registration_id;
-	priv->connection = g_steal_pointer (&connection);
-	priv->proxy = g_steal_pointer (&proxy);
-
-	_LOGI ("aquired D-Bus service \"%s\"", NM_DBUS_SERVICE);
-
-	c_list_for_each_entry (obj, &priv->objects_lst_head, internal.objects_lst)
-		_obj_register (self, obj);
-
-	return TRUE;
-}
-
-/*****************************************************************************/
-
-static void
-nm_dbus_manager_init (NMDBusManager *self)
-{
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-
-	c_list_init (&priv->private_servers_lst_head);
-	c_list_init (&priv->objects_lst_head);
-	priv->objects_by_path = g_hash_table_new ((GHashFunc) _objects_by_path_hash, (GEqualFunc) _objects_by_path_equal);
-}
-
-static void
-dispose (GObject *object)
-{
-	NMDBusManager *self = NM_DBUS_MANAGER (object);
-	NMDBusManagerPrivate *priv = NM_DBUS_MANAGER_GET_PRIVATE (self);
-	PrivateServer *s, *s_safe;
-
-	/* All exported NMDBusObject instances keep the manager alive, so we don't
-	 * expect any remaining objects. */
-	nm_assert (!priv->objects_by_path || g_hash_table_size (priv->objects_by_path) == 0);
-	nm_assert (c_list_is_empty (&priv->objects_lst_head));
-
-	g_clear_pointer (&priv->objects_by_path, g_hash_table_destroy);
-
-	c_list_for_each_entry_safe (s, s_safe, &priv->private_servers_lst_head, private_servers_lst)
-		private_server_free (s);
-
-	if (priv->objmgr_registration_id) {
-		g_dbus_connection_unregister_object (priv->connection,
-		                                     nm_steal_int (&priv->objmgr_registration_id));
-	}
-
-	g_clear_object (&priv->proxy);
-	g_clear_object (&priv->connection);
-
-	G_OBJECT_CLASS (nm_dbus_manager_parent_class)->dispose (object);
-}
-
-static void
-nm_dbus_manager_class_init (NMDBusManagerClass *klass)
-{
-	GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-	object_class->dispose = dispose;
-
-	signals[PRIVATE_CONNECTION_NEW] =
-	    g_signal_new (NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW,
-	                  G_OBJECT_CLASS_TYPE (object_class),
-	                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-	                  0, NULL, NULL, NULL,
-	                  G_TYPE_NONE, 2, G_TYPE_DBUS_CONNECTION, G_TYPE_DBUS_OBJECT_MANAGER_SERVER);
-
-	signals[PRIVATE_CONNECTION_DISCONNECTED] =
-	    g_signal_new (NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED,
-	                  G_OBJECT_CLASS_TYPE (object_class),
-	                  G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
-	                  0, NULL, NULL, NULL,
-	                  G_TYPE_NONE, 1, G_TYPE_POINTER);
-}