diff options
-rw-r--r-- | src/dhcp-manager/nm-dhcp-listener.c | 1 | ||||
-rw-r--r-- | src/nm-bus-manager.c | 411 | ||||
-rw-r--r-- | src/nm-bus-manager.h | 13 | ||||
-rw-r--r-- | src/nm-exported-object.c | 42 | ||||
-rw-r--r-- | src/nm-exported-object.h | 4 | ||||
-rw-r--r-- | src/nm-iface-helper.c | 4 | ||||
-rw-r--r-- | src/nm-manager.c | 6 | ||||
-rw-r--r-- | src/org.freedesktop.NetworkManager.conf | 2 | ||||
-rw-r--r-- | src/settings/nm-secret-agent.c | 2 |
9 files changed, 234 insertions, 251 deletions
diff --git a/src/dhcp-manager/nm-dhcp-listener.c b/src/dhcp-manager/nm-dhcp-listener.c index 6c936e5bf3..25f09ff6c7 100644 --- a/src/dhcp-manager/nm-dhcp-listener.c +++ b/src/dhcp-manager/nm-dhcp-listener.c @@ -148,6 +148,7 @@ out: static void new_connection_cb (NMBusManager *mgr, GDBusConnection *connection, + GDBusObjectManager *manager, NMDhcpListener *self) { NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); diff --git a/src/nm-bus-manager.c b/src/nm-bus-manager.c index 1c09a7b68a..571573833f 100644 --- a/src/nm-bus-manager.c +++ b/src/nm-bus-manager.c @@ -57,7 +57,7 @@ typedef struct _PrivateServer PrivateServer; typedef struct { GDBusConnection *connection; - GHashTable *exported; + GDBusObjectManagerServer *obj_manager; gboolean started; GSList *private_servers; @@ -73,6 +73,13 @@ static gboolean nm_bus_manager_init_bus (NMBusManager *self); static void nm_bus_manager_cleanup (NMBusManager *self); static void start_reconnection_timeout (NMBusManager *self); +/* 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" + NM_DEFINE_SINGLETON_REGISTER (NMBusManager); NMBusManager * @@ -103,66 +110,23 @@ nm_bus_manager_setup (NMBusManager *instance) /**************************************************************/ -static void -nm_assert_exported (NMBusManager *self, const char *path, NMExportedObject *object) -{ -#if NM_MORE_ASSERTS - NMBusManagerPrivate *priv; - const char *p2, *po; - NMExportedObject *o2; - - /* NMBusManager and NMExportedObject are tied closely together. For example, while - * being registered, NMBusManager uses the path from nm_exported_object_get_path() - * as index. It relies on the path being stable. - * - * The alternative would be that NMBusManager copies the path upon registration - * to support diversion of NMExportedObject's path while being registered. But such - * a inconsistency would already indicate a bug, or at least a strange situation. - * - * So instead require some close cooperation between the two classes and add an - * assert here... */ - - nm_assert (NM_IS_BUS_MANAGER (self)); - nm_assert (!path || *path); - nm_assert (!object || NM_IS_EXPORTED_OBJECT (object)); - nm_assert (!!path || !!object); - - priv = NM_BUS_MANAGER_GET_PRIVATE (self); - nm_assert (priv->exported); - - if (!path) { - nm_assert (NM_IS_EXPORTED_OBJECT (object)); - - po = nm_exported_object_get_path (object); - nm_assert (po && *po); - - if (!g_hash_table_lookup_extended (priv->exported, po, (gpointer *) &p2, (gpointer *) &o2)) - nm_assert (FALSE); - - nm_assert (object == o2); - nm_assert (po == p2); - } else { - nm_assert (path && *path); - - if (!g_hash_table_lookup_extended (priv->exported, path, (gpointer *) &p2, (gpointer *) &o2)) - nm_assert (FALSE); - - nm_assert (NM_IS_EXPORTED_OBJECT (o2)); - nm_assert (!object || object == o2); - nm_assert (!g_strcmp0 (path, p2)); - nm_assert (p2 == nm_exported_object_get_path (o2)); - } -#endif -} - -/**************************************************************/ - struct _PrivateServer { const char *tag; GQuark detail; char *address; GDBusServer *server; - GHashTable *connections; + + /* 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. This table + * maps GDBusObjectManager :: 'fake sender'. + * + * 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. + */ + GHashTable *obj_managers; + NMBusManager *manager; }; @@ -177,6 +141,8 @@ close_connection_in_idle (gpointer user_data) { CloseConnectionInfo *info = user_data; PrivateServer *server = info->server; + GHashTableIter iter; + GDBusObjectManagerServer *manager; /* Emit this for the manager */ g_signal_emit (server->manager, @@ -191,7 +157,14 @@ close_connection_in_idle (gpointer user_data) if (info->remote_peer_vanished) g_dbus_connection_close (info->connection, NULL, NULL, NULL); - g_hash_table_remove (server->connections, info->connection); + g_hash_table_iter_init (&iter, server->obj_managers); + while (g_hash_table_iter_next (&iter, (gpointer) &manager, NULL)) { + if (g_dbus_object_manager_server_get_connection (manager) == info->connection) { + g_hash_table_iter_remove (&iter); + break; + } + } + g_object_unref (server->manager); g_slice_free (CloseConnectionInfo, info); @@ -199,10 +172,10 @@ close_connection_in_idle (gpointer user_data) } static void -private_server_closed (GDBusConnection *conn, - gboolean remote_peer_vanished, - GError *error, - gpointer user_data) +private_server_closed_connection (GDBusConnection *conn, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) { PrivateServer *s = user_data; CloseConnectionInfo *info; @@ -230,13 +203,17 @@ private_server_new_connection (GDBusServer *server, { PrivateServer *s = user_data; static guint32 counter = 0; + GDBusObjectManagerServer *manager; char *sender; - g_signal_connect (conn, "closed", G_CALLBACK (private_server_closed), s); + 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++); - g_hash_table_insert (s->connections, g_object_ref (conn), sender); + + manager = g_dbus_object_manager_server_new (OBJECT_MANAGER_SERVER_BASE_PATH); + g_dbus_object_manager_server_set_connection (manager, conn); + g_hash_table_insert (s->obj_managers, manager, sender); nm_log_dbg (LOGD_CORE, "(%s) accepted connection %p on private socket.", s->tag, conn); @@ -245,16 +222,20 @@ private_server_new_connection (GDBusServer *server, g_signal_emit (s->manager, signals[PRIVATE_CONNECTION_NEW], s->detail, - conn); + conn, + manager); return TRUE; } static void -private_server_dbus_connection_destroy (GDBusConnection *conn) +private_server_manager_destroy (GDBusObjectManagerServer *manager) { - if (!g_dbus_connection_is_closed (conn)) - g_dbus_connection_close (conn, NULL, NULL, NULL); - g_object_unref (conn); + GDBusConnection *connection = g_dbus_object_manager_server_get_connection (manager); + + if (!g_dbus_connection_is_closed (connection)) + g_dbus_connection_close (connection, NULL, NULL, NULL); + g_dbus_object_manager_server_set_connection (manager, NULL); + g_object_unref (manager); } static gboolean @@ -308,9 +289,9 @@ private_server_new (const char *path, g_signal_connect (server, "new-connection", G_CALLBACK (private_server_new_connection), s); - s->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, - (GDestroyNotify) private_server_dbus_connection_destroy, - g_free); + s->obj_managers = g_hash_table_new_full (g_direct_hash, g_direct_equal, + (GDestroyNotify) private_server_manager_destroy, + g_free); s->manager = manager; s->detail = g_quark_from_string (tag); s->tag = g_quark_to_string (s->detail); @@ -327,7 +308,7 @@ private_server_free (gpointer ptr) unlink (s->address); g_free (s->address); - g_hash_table_destroy (s->connections); + g_hash_table_destroy (s->obj_managers); g_dbus_server_stop (s->server); g_object_unref (s->server); @@ -364,10 +345,56 @@ nm_bus_manager_private_server_register (NMBusManager *self, static const char * private_server_get_connection_owner (PrivateServer *s, GDBusConnection *connection) { + GHashTableIter iter; + GDBusObjectManagerServer *manager; + const char *owner; + g_return_val_if_fail (s != NULL, NULL); g_return_val_if_fail (connection != NULL, NULL); - return g_hash_table_lookup (s->connections, connection); + g_hash_table_iter_init (&iter, s->obj_managers); + while (g_hash_table_iter_next (&iter, (gpointer) &manager, (gpointer) &owner)) { + if (g_dbus_object_manager_server_get_connection (manager) == connection) + return owner; + } + return NULL; +} + +static GDBusConnection * +private_server_get_connection_by_owner (PrivateServer *s, const char *owner) +{ + GHashTableIter iter; + GDBusObjectManagerServer *manager; + const char *priv_sender; + + g_hash_table_iter_init (&iter, s->obj_managers); + while (g_hash_table_iter_next (&iter, (gpointer) &manager, (gpointer) &priv_sender)) { + if (g_strcmp0 (owner, priv_sender) == 0) + return g_dbus_object_manager_server_get_connection (manager); + } + return NULL; +} + +static void +private_server_register_object (PrivateServer *s, GDBusObjectSkeleton *object) +{ + GHashTableIter iter; + GDBusObjectManagerServer *manager; + + g_hash_table_iter_init (&iter, s->obj_managers); + while (g_hash_table_iter_next (&iter, (gpointer) &manager, NULL)) + g_dbus_object_manager_server_export (manager, object); +} + +static void +private_server_unregister_object (PrivateServer *s, const char *path) +{ + GHashTableIter iter; + GDBusObjectManagerServer *manager; + + g_hash_table_iter_init (&iter, s->obj_managers); + while (g_hash_table_iter_next (&iter, (gpointer) &manager, NULL)) + g_dbus_object_manager_server_unexport (manager, path); } /**************************************************************/ @@ -455,7 +482,7 @@ _get_caller_info (NMBusManager *self, for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { PrivateServer *s = iter->data; - sender = g_hash_table_lookup (s->connections, connection); + sender = private_server_get_connection_owner (s, connection); if (sender) { if (out_uid) *out_uid = 0; @@ -538,17 +565,10 @@ nm_bus_manager_get_unix_user (NMBusManager *self, g_return_val_if_fail (out_uid != NULL, FALSE); /* Check if it's a private connection sender, which we fake */ - for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { - PrivateServer *s = iter->data; - GHashTableIter hiter; - const char *priv_sender; - - g_hash_table_iter_init (&hiter, s->connections); - while (g_hash_table_iter_next (&hiter, NULL, (gpointer) &priv_sender)) { - if (g_strcmp0 (sender, priv_sender) == 0) { - *out_uid = 0; - return TRUE; - } + for (iter = priv->private_servers; iter; iter = iter->next) { + if (private_server_get_connection_by_owner (iter->data, sender)) { + *out_uid = 0; + return TRUE; } } @@ -566,42 +586,30 @@ nm_bus_manager_get_unix_user (NMBusManager *self, /**************************************************************/ static void -private_connection_new (NMBusManager *self, GDBusConnection *connection) +manager_private_connection_new (NMBusManager *self, + GDBusConnection *connection, + GDBusObjectManagerServer *manager, + gpointer user_data) { NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); - GHashTableIter iter; - NMExportedObject *object; - const char *path; - GError *error = NULL; - - /* Register all exported objects on this private connection */ - g_hash_table_iter_init (&iter, priv->exported); - while (g_hash_table_iter_next (&iter, (gpointer *) &path, (gpointer *) &object)) { - GSList *interfaces = nm_exported_object_get_interfaces (object); - - nm_assert_exported (self, path, object); + GList *objects, *iter; - for (; interfaces; interfaces = interfaces->next) { - GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interfaces->data); - - if (g_dbus_interface_skeleton_export (interface, connection, path, &error)) { - nm_log_trace (LOGD_CORE, "(%s) registered %p (%s) at '%s' on private socket.", - PRIV_SOCK_TAG, object, G_OBJECT_TYPE_NAME (interface), path); - } else { - nm_log_warn (LOGD_CORE, "(%s) could not register %p (%s) at '%s' on private socket: %s.", - PRIV_SOCK_TAG, object, G_OBJECT_TYPE_NAME (interface), path, - error->message); - g_clear_error (&error); - } - } + /* Register all exported objects on the new private connection */ + objects = g_dbus_object_manager_get_objects (G_DBUS_OBJECT_MANAGER (priv->obj_manager)); + for (iter = objects; iter; iter = iter->next) { + g_dbus_object_manager_server_export (manager, iter->data); + g_object_unref (iter->data); } + g_list_free (objects); } static void -private_server_setup (NMBusManager *self) +nm_bus_manager_init (NMBusManager *self) { NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); + priv->obj_manager = g_dbus_object_manager_server_new (OBJECT_MANAGER_SERVER_BASE_PATH); + /* Skip this step if this is just a test program */ if (nm_utils_get_testing ()) return; @@ -616,37 +624,17 @@ private_server_setup (NMBusManager *self) priv->private_servers = g_slist_append (priv->private_servers, priv->priv_server); g_signal_connect (self, NM_BUS_MANAGER_PRIVATE_CONNECTION_NEW "::" PRIV_SOCK_TAG, - (GCallback) private_connection_new, + (GCallback) manager_private_connection_new, NULL); } } static void -nm_bus_manager_init (NMBusManager *self) -{ - NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); - - priv->exported = g_hash_table_new (g_str_hash, g_str_equal); - - private_server_setup (self); -} - -static void nm_bus_manager_dispose (GObject *object) { NMBusManager *self = NM_BUS_MANAGER (object); NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); - - if (priv->exported) { - /* We don't take references to the registered objects. - * We rely on the objects to properly unregister. - * Especially, they must unregister before destroying the - * NMBusManager instance. */ - g_assert (g_hash_table_size (priv->exported) == 0); - - g_hash_table_destroy (priv->exported); - priv->exported = NULL; - } + GList *exported, *iter; g_slist_free_full (priv->private_servers, private_server_free); priv->private_servers = NULL; @@ -654,11 +642,24 @@ nm_bus_manager_dispose (GObject *object) nm_bus_manager_cleanup (self); - if (priv->reconnect_id) { - g_source_remove (priv->reconnect_id); - priv->reconnect_id = 0; + if (priv->obj_manager) { + /* The ObjectManager owns the last reference to many exported + * objects, and when that reference is dropped the objects unregister + * themselves via nm_bus_manager_unregister_object(). By that time + * priv->obj_manager is already NULL and that prints warnings. Unregister + * them before clearing the ObjectManager instead. + */ + exported = g_dbus_object_manager_get_objects ((GDBusObjectManager *) priv->obj_manager); + for (iter = exported; iter; iter = iter->next) { + nm_bus_manager_unregister_object (self, iter->data); + g_object_unref (iter->data); + } + g_list_free (exported); + g_clear_object (&priv->obj_manager); } + nm_clear_g_source (&priv->reconnect_id); + G_OBJECT_CLASS (nm_bus_manager_parent_class)->dispose (object); } @@ -683,9 +684,8 @@ nm_bus_manager_class_init (NMBusManagerClass *klass) g_signal_new (NM_BUS_MANAGER_PRIVATE_CONNECTION_NEW, G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, - G_STRUCT_OFFSET (NMBusManagerClass, private_connection_new), - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_POINTER); + 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_BUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED, @@ -711,6 +711,7 @@ nm_bus_manager_cleanup (NMBusManager *self) g_clear_object (&priv->connection); } + g_dbus_object_manager_server_set_connection (priv->obj_manager, NULL); priv->started = FALSE; } @@ -812,6 +813,7 @@ nm_bus_manager_init_bus (NMBusManager *self) return FALSE; } + g_dbus_object_manager_server_set_connection (priv->obj_manager, priv->connection); return TRUE; } @@ -876,131 +878,87 @@ nm_bus_manager_get_connection (NMBusManager *self) void nm_bus_manager_register_object (NMBusManager *self, - NMExportedObject *object) + GDBusObjectSkeleton *object) { NMBusManagerPrivate *priv; - GDBusConnection *connection; - GHashTableIter iter; - const char *path; - GSList *interfaces, *ifs; g_return_if_fail (NM_IS_BUS_MANAGER (self)); g_return_if_fail (NM_IS_EXPORTED_OBJECT (object)); - path = nm_exported_object_get_path (object); - g_return_if_fail (path && *path); - priv = NM_BUS_MANAGER_GET_PRIVATE (self); - /* We hold a direct reference to the @path of the @object. Note that - * this requires the object not to modify the path as long as the object - * is registered. Especially, it must not free the path. - * - * This is a reasonable requirement, because having the object change - * the path while being registered is an awkward situation in the first - * place. While being registered, the @path and @interfaces must stay - * stable -- because the path is the identifier for the object in this - * situation. */ - - if (!nm_g_hash_table_insert (priv->exported, (gpointer) path, object)) +#if NM_MORE_ASSERTS >= 1 +#if GLIB_CHECK_VERSION(2,34,0) + if (g_dbus_object_manager_server_is_exported (priv->obj_manager, object)) g_return_if_reached (); +#endif +#endif - nm_assert_exported (self, path, object); - - interfaces = nm_exported_object_get_interfaces (object); - - if (priv->connection) { - for (ifs = interfaces; ifs; ifs = ifs->next) { - g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (ifs->data), - priv->connection, path, NULL); - } - } - - if (priv->priv_server) { - g_hash_table_iter_init (&iter, priv->priv_server->connections); - while (g_hash_table_iter_next (&iter, (gpointer) &connection, NULL)) { - for (ifs = interfaces; ifs; ifs = ifs->next) { - g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (ifs->data), - connection, path, NULL); - } - } - } + g_dbus_object_manager_server_export (priv->obj_manager, object); + if (priv->priv_server) + private_server_register_object (priv->priv_server, object); } -NMExportedObject * +GDBusObjectSkeleton * nm_bus_manager_get_registered_object (NMBusManager *self, const char *path) { - NMBusManagerPrivate *priv; - NMExportedObject *object; - - g_return_val_if_fail (NM_IS_BUS_MANAGER (self), NULL); - g_return_val_if_fail (path && *path, NULL); - - priv = NM_BUS_MANAGER_GET_PRIVATE (self); - - object = g_hash_table_lookup (priv->exported, path); - - if (object) - nm_assert_exported (self, path, object); + NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); - return object; + return G_DBUS_OBJECT_SKELETON (g_dbus_object_manager_get_object ((GDBusObjectManager *) priv->obj_manager, path)); } void -nm_bus_manager_unregister_object (NMBusManager *self, NMExportedObject *object) +nm_bus_manager_unregister_object (NMBusManager *self, + GDBusObjectSkeleton *object) { NMBusManagerPrivate *priv; - GSList *interfaces; - const char *path; + gs_free char *path = NULL; g_return_if_fail (NM_IS_BUS_MANAGER (self)); g_return_if_fail (NM_IS_EXPORTED_OBJECT (object)); - path = nm_exported_object_get_path (object); - g_return_if_fail (path && *path); - - nm_assert_exported (self, NULL, object); - priv = NM_BUS_MANAGER_GET_PRIVATE (self); - if (!g_hash_table_remove (priv->exported, path)) +#if NM_MORE_ASSERTS >= 1 +#if GLIB_CHECK_VERSION(2,34,0) + if (!g_dbus_object_manager_server_is_exported (priv->obj_manager, object)) g_return_if_reached (); +#endif +#endif - for (interfaces = nm_exported_object_get_interfaces (object); interfaces; interfaces = interfaces->next) { - GDBusInterfaceSkeleton *interface = G_DBUS_INTERFACE_SKELETON (interfaces->data); + g_object_get (G_OBJECT (object), "g-object-path", &path, NULL); + g_return_if_fail (path != NULL); - if (g_dbus_interface_skeleton_get_object_path (interface)) - g_dbus_interface_skeleton_unexport (interface); - } + g_dbus_object_manager_server_unexport (priv->obj_manager, path); + if (priv->priv_server) + private_server_unregister_object (priv->priv_server, path); } -gboolean -nm_bus_manager_connection_is_private (NMBusManager *self, - GDBusConnection *connection) +const char * +nm_bus_manager_connection_get_private_name (NMBusManager *self, + GDBusConnection *connection) { NMBusManagerPrivate *priv; GSList *iter; + const char *owner; g_return_val_if_fail (NM_IS_BUS_MANAGER (self), FALSE); g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE); - if (g_dbus_connection_get_unique_name (connection)) - return FALSE; + if (g_dbus_connection_get_unique_name (connection)) { + /* Shortcut. The connection is not a private connection. */ + return NULL; + } - /* Assert that we still track the private connection. The caller - * of nm_bus_manager_connection_is_private() want's to subscribe - * to NM_BUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED, thus the signal - * never comes if we don't track the connection. */ priv = NM_BUS_MANAGER_GET_PRIVATE (self); for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { PrivateServer *s = iter->data; - if (g_hash_table_contains (s->connections, - connection)) - return TRUE; + if ((owner = private_server_get_connection_owner (s, connection))) + return owner; } - g_return_val_if_reached (TRUE); + g_return_val_if_reached (NULL); } /** @@ -1027,8 +985,6 @@ nm_bus_manager_new_proxy (NMBusManager *self, const char *path, const char *iface) { - NMBusManagerPrivate *priv = NM_BUS_MANAGER_GET_PRIVATE (self); - GSList *iter; const char *owner; GDBusProxy *proxy; GError *error = NULL; @@ -1037,15 +993,10 @@ nm_bus_manager_new_proxy (NMBusManager *self, g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); /* Might be a private connection, for which @name is fake */ - for (iter = priv->private_servers; iter; iter = g_slist_next (iter)) { - PrivateServer *s = iter->data; - - owner = private_server_get_connection_owner (s, connection); - if (owner) { - g_assert_cmpstr (owner, ==, name); - name = NULL; - break; - } + owner = nm_bus_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, diff --git a/src/nm-bus-manager.h b/src/nm-bus-manager.h index 8dd4be7ba2..8e72a3ce99 100644 --- a/src/nm-bus-manager.h +++ b/src/nm-bus-manager.h @@ -72,8 +72,8 @@ gboolean nm_bus_manager_get_caller_info (NMBusManager *self, gulong *out_uid, gulong *out_pid); -gboolean nm_bus_manager_connection_is_private (NMBusManager *self, - GDBusConnection *connection); +const char *nm_bus_manager_connection_get_private_name (NMBusManager *self, + GDBusConnection *connection); gboolean nm_bus_manager_get_unix_user (NMBusManager *self, const char *sender, @@ -87,12 +87,13 @@ gboolean nm_bus_manager_get_caller_info_from_message (NMBusManager *self, gulong *out_pid); void nm_bus_manager_register_object (NMBusManager *self, - NMExportedObject *object); + GDBusObjectSkeleton *object); -void nm_bus_manager_unregister_object (NMBusManager *self, NMExportedObject *object); +void nm_bus_manager_unregister_object (NMBusManager *self, + GDBusObjectSkeleton *object); -NMExportedObject *nm_bus_manager_get_registered_object (NMBusManager *self, - const char *path); +GDBusObjectSkeleton *nm_bus_manager_get_registered_object (NMBusManager *self, + const char *path); void nm_bus_manager_private_server_register (NMBusManager *self, const char *path, diff --git a/src/nm-exported-object.c b/src/nm-exported-object.c index 0746fec0d4..ca3187e8ae 100644 --- a/src/nm-exported-object.c +++ b/src/nm-exported-object.c @@ -35,7 +35,7 @@ static gboolean quitting = FALSE; #define _ASSERT_NO_EARLY_EXPORT #endif -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_OBJECT, +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (NMExportedObject, nm_exported_object, G_TYPE_DBUS_OBJECT_SKELETON, prefix_counters = g_hash_table_new (g_str_hash, g_str_equal); ) @@ -64,6 +64,19 @@ typedef struct { GQuark nm_exported_object_class_info_quark (void); G_DEFINE_QUARK (NMExportedObjectClassInfo, nm_exported_object_class_info) +/*****************************************************************************/ + +#define _NMLOG_PREFIX_NAME "exported-object" +#define _NMLOG_DOMAIN LOGD_CORE + +#define _NMLOG(level, ...) \ + nm_log (level, _NMLOG_DOMAIN, \ + "%s[%p]: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, (self) \ + _NM_UTILS_MACRO_REST (__VA_ARGS__)) + +/*****************************************************************************/ + /* "AddConnectionUnsaved" -> "handle-add-connection-unsaved" */ char * nm_exported_object_skeletonify_method_name (const char *dbus_method_name) @@ -461,6 +474,8 @@ nm_exported_object_create_skeletons (NMExportedObject *self, methods_len, (GObject *) self); + g_dbus_object_skeleton_add_interface ((GDBusObjectSkeleton *) self, interface); + priv->interfaces = g_slist_prepend (priv->interfaces, interface); } } @@ -498,6 +513,7 @@ nm_exported_object_destroy_skeletons (NMExportedObject *self) GDBusInterfaceSkeleton *interface = priv->interfaces->data; priv->interfaces = g_slist_delete_link (priv->interfaces, priv->interfaces); + g_dbus_object_skeleton_remove_interface ((GDBusObjectSkeleton *) self, interface); nm_exported_object_skeleton_release (interface); } } @@ -533,6 +549,11 @@ nm_exported_object_export (NMExportedObject *self) nm_assert (priv->_constructed); #endif + priv->bus_mgr = nm_bus_manager_get (); + if (!priv->bus_mgr) + g_return_val_if_reached (NULL); + g_object_add_weak_pointer ((GObject *) priv->bus_mgr, (gpointer *) &priv->bus_mgr); + class_export_path = NM_EXPORTED_OBJECT_GET_CLASS (self)->export_path; p = strchr (class_export_path, '%'); if (p) { @@ -551,18 +572,19 @@ nm_exported_object_export (NMExportedObject *self) } else priv->path = g_strdup (class_export_path); + _LOGT ("export: \"%s\"", priv->path); + g_dbus_object_skeleton_set_object_path (G_DBUS_OBJECT_SKELETON (self), priv->path); + type = G_OBJECT_TYPE (self); while (type != NM_TYPE_EXPORTED_OBJECT) { nm_exported_object_create_skeletons (self, type); type = g_type_parent (type); } - priv->bus_mgr = g_object_ref (nm_bus_manager_get ()); - /* Important: priv->path and priv->interfaces must not change while * the object is registered. */ - nm_bus_manager_register_object (priv->bus_mgr, self); + nm_bus_manager_register_object (priv->bus_mgr, (GDBusObjectSkeleton *) self); return priv->path; } @@ -615,17 +637,23 @@ nm_exported_object_unexport (NMExportedObject *self) priv = NM_EXPORTED_OBJECT_GET_PRIVATE (self); g_return_if_fail (priv->path); - g_return_if_fail (priv->bus_mgr); /* Important: priv->path and priv->interfaces must not change while * the object is registered. */ - nm_bus_manager_unregister_object (priv->bus_mgr, self); + _LOGT ("unexport: \"%s\"", priv->path); + + if (priv->bus_mgr) { + nm_bus_manager_unregister_object (priv->bus_mgr, (GDBusObjectSkeleton *) self); + g_object_remove_weak_pointer ((GObject *) priv->bus_mgr, (gpointer *) &priv->bus_mgr); + priv->bus_mgr = NULL; + } nm_exported_object_destroy_skeletons (self); + g_dbus_object_skeleton_set_object_path ((GDBusObjectSkeleton *) self, NULL); + g_clear_pointer (&priv->path, g_free); - g_clear_object (&priv->bus_mgr); if (nm_clear_g_source (&priv->notify_idle_id)) { /* We had a notification queued. Since we removed all interfaces, diff --git a/src/nm-exported-object.h b/src/nm-exported-object.h index 3f69a7bda8..88efb6fe98 100644 --- a/src/nm-exported-object.h +++ b/src/nm-exported-object.h @@ -52,11 +52,11 @@ void nm_exported_object_skeleton_release (GDBusInterfaceSkeleton *interface); #define NM_EXPORTED_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_OBJECT, NMExportedObjectClass)) struct _NMExportedObject { - GObject parent; + GDBusObjectSkeleton parent; }; typedef struct { - GObjectClass parent; + GDBusObjectSkeletonClass parent; const char *export_path; char export_on_construction; diff --git a/src/nm-iface-helper.c b/src/nm-iface-helper.c index fdd714f918..396929ff75 100644 --- a/src/nm-iface-helper.c +++ b/src/nm-iface-helper.c @@ -523,7 +523,7 @@ gconstpointer nm_config_get (void); const char *nm_config_get_dhcp_client (gpointer unused); gboolean nm_config_get_configure_and_quit (gpointer unused); gconstpointer nm_bus_manager_get (void); -void nm_bus_manager_register_object (gpointer unused, const char *path, gpointer object); +void nm_bus_manager_register_object (gpointer unused, gpointer object); void nm_bus_manager_unregister_object (gpointer unused, gpointer object); gconstpointer @@ -551,7 +551,7 @@ nm_bus_manager_get (void) } void -nm_bus_manager_register_object (gpointer unused, const char *path, gpointer object) +nm_bus_manager_register_object (gpointer unused, gpointer object) { } diff --git a/src/nm-manager.c b/src/nm-manager.c index 5cba730fec..bb92a13f38 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -4461,7 +4461,7 @@ prop_set_auth_done_cb (NMAuthChain *chain, NMAuthCallResult result; GDBusMessage *reply = NULL; const char *error_message; - NMExportedObject *object; + gs_unref_object NMExportedObject *object = NULL; const NMGlobalDnsConfig *global_dns; gs_unref_variant GVariant *value = NULL; GVariant *args; @@ -4477,8 +4477,8 @@ prop_set_auth_done_cb (NMAuthChain *chain, goto done; } - object = nm_bus_manager_get_registered_object (priv->dbus_mgr, - g_dbus_message_get_path (pfd->message)); + object = NM_EXPORTED_OBJECT (nm_bus_manager_get_registered_object (priv->dbus_mgr, + g_dbus_message_get_path (pfd->message))); if (!object) { reply = g_dbus_message_new_method_error (pfd->message, "org.freedesktop.DBus.Error.UnknownObject", diff --git a/src/org.freedesktop.NetworkManager.conf b/src/org.freedesktop.NetworkManager.conf index e6f030643d..c4082d2b50 100644 --- a/src/org.freedesktop.NetworkManager.conf +++ b/src/org.freedesktop.NetworkManager.conf @@ -37,6 +37,8 @@ send_interface="org.freedesktop.DBus.Introspectable"/> <allow send_destination="org.freedesktop.NetworkManager" send_interface="org.freedesktop.DBus.Properties"/> + <allow send_destination="org.freedesktop.NetworkManager" + send_interface="org.freedesktop.DBus.ObjectManager"/> <!-- Devices (read-only properties, no methods) --> <allow send_destination="org.freedesktop.NetworkManager" diff --git a/src/settings/nm-secret-agent.c b/src/settings/nm-secret-agent.c index f819a9206b..68fdab029c 100644 --- a/src/settings/nm-secret-agent.c +++ b/src/settings/nm-secret-agent.c @@ -679,7 +679,7 @@ nm_secret_agent_new (GDBusMethodInvocation *context, priv->bus_mgr = g_object_ref (nm_bus_manager_get ()); priv->connection = g_object_ref (connection); - priv->connection_is_private = nm_bus_manager_connection_is_private (priv->bus_mgr, connection); + priv->connection_is_private = !!nm_bus_manager_connection_get_private_name (priv->bus_mgr, connection); _LOGt ("constructed: %s, owner=%s%s%s (%s), private-connection=%d, unique-name=%s%s%s", (description = _create_description (dbus_owner, identifier, uid)), |