From 0d69dfe39ef61b42b2024c7fbd8bbad9e9c6d164 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 23 Jul 2009 09:20:52 -0400 Subject: [PATCH 01/30] libnm-glib: implement new settings interfaces The old NMExportedConnection was used for both client and server-side classes, which was a mistake and made the code very complicated to follow. Additionally, all PolicyKit operations were synchronous, and PK operations can block for a long time (ie for user input) before returning, so they need to be async. But NMExportedConnection and NMSysconfigConnection didn't allow for async PK ops at all. Use this opportunity to clean up the mess and create GInterfaces that both server and client objects implement, so that the connection editor and applet can operate on generic objects like they did before (using the interfaces) but can perform specific operations (like async PK verification of callers) depending on whether they are local or remote or whatever. --- configure.ac | 34 +- introspection/nm-settings-system.xml | 2 +- introspection/nm-settings.xml | 15 +- libnm-glib/Makefile.am | 28 +- libnm-glib/libnm_glib.ver | 31 +- libnm-glib/nm-dbus-connection.c | 323 ------- libnm-glib/nm-dbus-connection.h | 59 -- libnm-glib/nm-dbus-settings-system.c | 391 --------- libnm-glib/nm-dbus-settings-system.h | 70 -- libnm-glib/nm-dbus-settings.c | 373 -------- libnm-glib/nm-dbus-settings.h | 60 -- libnm-glib/nm-exported-connection.c | 306 +++++++ libnm-glib/nm-exported-connection.h | 71 ++ libnm-glib/nm-remote-connection.c | 419 +++++++++ libnm-glib/nm-remote-connection.h | 57 ++ libnm-glib/nm-remote-settings-system.c | 259 ++++++ libnm-glib/nm-remote-settings-system.h | 55 ++ libnm-glib/nm-remote-settings.c | 425 +++++++++ libnm-glib/nm-remote-settings.h | 58 ++ libnm-glib/nm-settings-connection-interface.c | 210 +++++ libnm-glib/nm-settings-connection-interface.h | 116 +++ libnm-glib/nm-settings-interface.c | 195 +++++ libnm-glib/nm-settings-interface.h | 93 ++ libnm-glib/nm-settings-service.c | 287 ++++++ libnm-glib/nm-settings-service.h | 71 ++ libnm-glib/nm-settings-system-interface.c | 114 +++ libnm-glib/nm-settings-system-interface.h | 69 ++ libnm-glib/nm-settings.c | 607 ------------- libnm-glib/nm-settings.h | 145 --- marshallers/nm-marshal.list | 1 - src/nm-manager.c | 98 ++- src/system-settings/Makefile.am | 1 - .../nm-default-wired-connection.c | 119 ++- .../nm-default-wired-connection.h | 1 - src/system-settings/nm-polkit-helpers.c | 184 ---- src/system-settings/nm-polkit-helpers.h | 10 +- src/system-settings/nm-sysconfig-connection.c | 517 +++++++---- src/system-settings/nm-sysconfig-connection.h | 10 +- src/system-settings/nm-sysconfig-settings.c | 822 ++++++++++-------- src/system-settings/nm-sysconfig-settings.h | 46 +- .../nm-system-config-interface.c | 8 +- .../nm-system-config-interface.h | 21 +- .../plugins/ifcfg-rh/nm-ifcfg-connection.c | 92 +- system-settings/plugins/ifcfg-rh/plugin.c | 56 +- system-settings/plugins/ifcfg-suse/plugin.c | 6 +- system-settings/plugins/ifupdown/plugin.c | 4 +- system-settings/plugins/keyfile/io/writer.c | 10 +- .../plugins/keyfile/nm-keyfile-connection.c | 114 +-- system-settings/plugins/keyfile/plugin.c | 38 +- 49 files changed, 3999 insertions(+), 3102 deletions(-) delete mode 100644 libnm-glib/nm-dbus-connection.c delete mode 100644 libnm-glib/nm-dbus-connection.h delete mode 100644 libnm-glib/nm-dbus-settings-system.c delete mode 100644 libnm-glib/nm-dbus-settings-system.h delete mode 100644 libnm-glib/nm-dbus-settings.c delete mode 100644 libnm-glib/nm-dbus-settings.h create mode 100644 libnm-glib/nm-exported-connection.c create mode 100644 libnm-glib/nm-exported-connection.h create mode 100644 libnm-glib/nm-remote-connection.c create mode 100644 libnm-glib/nm-remote-connection.h create mode 100644 libnm-glib/nm-remote-settings-system.c create mode 100644 libnm-glib/nm-remote-settings-system.h create mode 100644 libnm-glib/nm-remote-settings.c create mode 100644 libnm-glib/nm-remote-settings.h create mode 100644 libnm-glib/nm-settings-connection-interface.c create mode 100644 libnm-glib/nm-settings-connection-interface.h create mode 100644 libnm-glib/nm-settings-interface.c create mode 100644 libnm-glib/nm-settings-interface.h create mode 100644 libnm-glib/nm-settings-service.c create mode 100644 libnm-glib/nm-settings-service.h create mode 100644 libnm-glib/nm-settings-system-interface.c create mode 100644 libnm-glib/nm-settings-system-interface.h delete mode 100644 libnm-glib/nm-settings.c delete mode 100644 libnm-glib/nm-settings.h delete mode 100644 src/system-settings/nm-polkit-helpers.c diff --git a/configure.ac b/configure.ac index adaf2e040f..7a8e7651e0 100644 --- a/configure.ac +++ b/configure.ac @@ -212,42 +212,10 @@ PKG_CHECK_MODULES(UUID, uuid) AC_SUBST(UUID_CFLAGS) AC_SUBST(UUID_LIBS) -PKG_CHECK_MODULES(POLKIT, polkit-dbus) +PKG_CHECK_MODULES(POLKIT, polkit-gobject-1) -##### Find out the version of PolicyKit we're using -polkit_version=`pkg-config --modversion polkit` -POLKIT_VERSION_MAJOR=`echo $polkit_version | awk -F. '{print $1}'` -POLKIT_VERSION_MINOR=`echo $polkit_version | awk -F. '{print $2}'` -POLKIT_VERSION_MICRO=`echo $polkit_version | awk -F. '{print $3}'` -if test "z$POLKIT_VERSION_MAJOR" = "z"; then - POLKIT_VERSION_MAJOR="0" -fi -if test "z$POLKIT_VERSION_MINOR" = "z"; then - POLKIT_VERSION_MINOR="0" -fi -if test "z$POLKIT_VERSION_MICRO" = "z"; then - POLKIT_VERSION_MICRO="0" -fi - -if test "z$POLKIT_VERSION_MAJOR" = "z0" -a "z$POLKIT_VERSION_MINOR" = "z0" -a "z$POLKIT_VERSION_MICRO" = "z0"; then - echo "Error: Couldn't determine the version of your PolicyKit package." - echo " This is probably an error in this script, please report it" - echo " along with the following information:" - echo " Base PolicyKit version ='$polkit_version'" - echo " POLKIT_VERSION_MAJOR='$POLKIT_VERSION_MAJOR'" - echo " POLKIT_VERSION_MINOR='$POLKIT_VERSION_MINOR'" - echo " POLKIT_VERSION_MICRO='$POLKIT_VERSION_MICRO'" - exit 1 -else - echo "Your PolicyKit version is $POLKIT_VERSION_MAJOR,$POLKIT_VERSION_MINOR,$POLKIT_VERSION_MICRO." - POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MAJOR=$POLKIT_VERSION_MAJOR" - POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MINOR=$POLKIT_VERSION_MINOR" - POLKIT_CFLAGS="$POLKIT_CFLAGS -DPOLKIT_VERSION_MICRO=$POLKIT_VERSION_MICRO" -fi AC_SUBST(POLKIT_CFLAGS) -AC_PATH_PROG([POLKIT_POLICY_FILE_VALIDATE], [polkit-policy-file-validate], [false]) - AC_ARG_WITH(crypto, AS_HELP_STRING([--with-crypto=nss | gnutls], [Cryptography library to use for certificate and key operations]),ac_crypto=$withval, ac_crypto=nss) with_nss=no diff --git a/introspection/nm-settings-system.xml b/introspection/nm-settings-system.xml index 0e13b7a8d6..d03b8dddb8 100644 --- a/introspection/nm-settings-system.xml +++ b/introspection/nm-settings-system.xml @@ -8,7 +8,7 @@ - Add new connection. + DEPRECATED. Adds new connection. diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml index 5e072f2641..0e77a0377a 100644 --- a/introspection/nm-settings.xml +++ b/introspection/nm-settings.xml @@ -18,9 +18,22 @@ + + + Add new connection. + + + + + + Connection settings and properties. + + + + - Emitted when a new connection has been configured. + Emitted when a new connection has been added. diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 16de0dd0c5..3e14bd750d 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -41,7 +41,6 @@ libnminclude_HEADERS = \ nm-device-bt.h \ nm-access-point.h \ nm-ip4-config.h \ - nm-settings.h \ nm-gsm-device.h \ nm-cdma-device.h \ nm-serial-device.h \ @@ -50,10 +49,15 @@ libnminclude_HEADERS = \ nm-vpn-plugin-ui-interface.h \ nm-types.h \ nm-active-connection.h \ - nm-dbus-connection.h \ - nm-dbus-settings.h \ - nm-dbus-settings-system.h \ - nm-dhcp4-config.h + nm-dhcp4-config.h \ + nm-remote-connection.h \ + nm-settings-interface.h \ + nm-settings-system-interface.h \ + nm-remote-settings.h \ + nm-remote-settings-system.h \ + nm-settings-connection-interface.h \ + nm-exported-connection.h \ + nm-settings-service.h libnm_glib_la_SOURCES = \ libnm_glib.c \ @@ -69,7 +73,6 @@ libnm_glib_la_SOURCES = \ nm-device-bt.c \ nm-access-point.c \ nm-ip4-config.c \ - nm-settings.c \ nm-gsm-device.c \ nm-cdma-device.c \ nm-serial-device.c \ @@ -79,10 +82,15 @@ libnm_glib_la_SOURCES = \ nm-object-cache.c \ nm-object-cache.h \ nm-active-connection.c \ - nm-dbus-connection.c \ - nm-dbus-settings.c \ - nm-dbus-settings-system.c \ - nm-dhcp4-config.c + nm-dhcp4-config.c \ + nm-remote-connection.c \ + nm-settings-interface.c \ + nm-settings-system-interface.c \ + nm-remote-settings.c \ + nm-remote-settings-system.c \ + nm-settings-connection-interface.c \ + nm-exported-connection.c \ + nm-settings-service.c libnm_glib_la_LIBADD = \ $(top_builddir)/libnm-util/libnm-util.la \ diff --git a/libnm-glib/libnm_glib.ver b/libnm-glib/libnm_glib.ver index e45f347440..ef79722748 100644 --- a/libnm-glib/libnm_glib.ver +++ b/libnm-glib/libnm_glib.ver @@ -40,8 +40,6 @@ global: nm_client_wireless_get_enabled; nm_client_wireless_hardware_get_enabled; nm_client_wireless_set_enabled; - nm_dbus_connection_get_type; - nm_dbus_connection_new; nm_dbus_settings_get_connection_by_path; nm_dbus_settings_get_type; nm_dbus_settings_new; @@ -85,14 +83,9 @@ global: nm_dhcp4_config_get_options; nm_dhcp4_config_get_type; nm_dhcp4_config_new; - nm_exported_connection_delete; - nm_exported_connection_get_connection; + nm_exported_connection_export; nm_exported_connection_get_type; nm_exported_connection_new; - nm_exported_connection_register_object; - nm_exported_connection_signal_removed; - nm_exported_connection_signal_updated; - nm_exported_connection_update; nm_gsm_device_get_type; nm_gsm_device_new; nm_ip4_config_get_addresses; @@ -107,9 +100,31 @@ global: nm_object_get_connection; nm_object_get_path; nm_object_get_type; + nm_remote_connection_get_type; + nm_remote_connection_new; + nm_remote_settings_get_type; + nm_remote_settings_new; + nm_remote_settings_system_get_type; + nm_remote_settings_system_new; nm_serial_device_get_bytes_received; nm_serial_device_get_bytes_sent; nm_serial_device_get_type; + nm_settings_connection_interface_delete; + nm_settings_connection_interface_emit_updated; + nm_settings_connection_interface_get_secrets; + nm_settings_connection_interface_get_type; + nm_settings_connection_interface_update; + nm_settings_interface_add_connection; + nm_settings_interface_error_quark; + nm_settings_interface_get_connection_by_path; + nm_settings_interface_get_type; + nm_settings_interface_list_connections; + nm_settings_service_export; + nm_settings_service_get_connection_by_path; + nm_settings_service_get_type; + nm_settings_system_interface_get_type; + nm_settings_system_interface_add_connection; + nm_settings_system_interface_save_hostname; nm_settings_error_quark; nm_settings_get_type; nm_settings_list_connections; diff --git a/libnm-glib/nm-dbus-connection.c b/libnm-glib/nm-dbus-connection.c deleted file mode 100644 index 25085b7d1b..0000000000 --- a/libnm-glib/nm-dbus-connection.c +++ /dev/null @@ -1,323 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - * Copyright (C) 2008 Red Hat, Inc. - */ - -#include -#include -#include -#include "nm-dbus-connection.h" -#include "nm-exported-connection-bindings.h" -#include "nm-utils.h" - -G_DEFINE_TYPE (NMDBusConnection, nm_dbus_connection, NM_TYPE_EXPORTED_CONNECTION) - -#define NM_DBUS_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionPrivate)) - -typedef struct { - DBusGConnection *dbus_connection; - NMConnectionScope scope; - char *path; - - DBusGProxy *proxy; - - gboolean disposed; -} NMDBusConnectionPrivate; - -enum { - PROP_0, - PROP_BUS, - PROP_SCOPE, - PROP_PATH, - - LAST_PROP -}; - -NMDBusConnection * -nm_dbus_connection_new (DBusGConnection *dbus_connection, - NMConnectionScope scope, - const char *path) -{ - g_return_val_if_fail (dbus_connection != NULL, NULL); - g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL); - g_return_val_if_fail (path != NULL, NULL); - - return (NMDBusConnection *) g_object_new (NM_TYPE_DBUS_CONNECTION, - NM_DBUS_CONNECTION_BUS, dbus_connection, - NM_DBUS_CONNECTION_SCOPE, scope, - NM_DBUS_CONNECTION_PATH, path, - NULL); -} - -static GHashTable * -get_settings (NMExportedConnection *exported) -{ - return nm_connection_to_hash (nm_exported_connection_get_connection (exported)); -} - -static gboolean -update (NMExportedConnection *exported, GHashTable *new_settings, GError **err) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported); - - return org_freedesktop_NetworkManagerSettings_Connection_update (priv->proxy, new_settings, err); -} - -static gboolean -do_delete (NMExportedConnection *exported, GError **err) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (exported); - - return org_freedesktop_NetworkManagerSettings_Connection_delete (priv->proxy, err); -} - -static void -connection_updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data) -{ - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (user_data); - NMConnection *wrapped; - GError *error = NULL; - - wrapped = nm_exported_connection_get_connection (exported); - if (nm_connection_replace_settings (wrapped, settings, &error)) - nm_exported_connection_signal_updated (exported, settings); - else { - g_warning ("%s: '%s' / '%s' invalid: %d", - __func__, - error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", - (error && error->message) ? error->message : "(none)", - error ? error->code : -1); - g_clear_error (&error); - nm_exported_connection_signal_removed (exported); - } -} - -static void -connection_removed_cb (DBusGProxy *proxy, gpointer user_data) -{ - nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (user_data)); -} - -/* GObject */ - -static void -nm_dbus_connection_init (NMDBusConnection *connection) -{ -} - -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDBusConnectionPrivate *priv; - NMConnection *wrapped; - const char *service; - GHashTable *settings = NULL; - GError *error = NULL; - - object = G_OBJECT_CLASS (nm_dbus_connection_parent_class)->constructor (type, n_construct_params, construct_params); - - if (!object) - return NULL; - - priv = NM_DBUS_CONNECTION_GET_PRIVATE (object); - - if (!priv->dbus_connection) { - nm_warning ("DBusGConnection not provided."); - goto err; - } - - if (!priv->path) - nm_warning ("DBus path not provided."); - - service = (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) ? - NM_DBUS_SERVICE_SYSTEM_SETTINGS : NM_DBUS_SERVICE_USER_SETTINGS; - - priv->proxy = dbus_g_proxy_new_for_name (priv->dbus_connection, - service, - priv->path, - NM_DBUS_IFACE_SETTINGS_CONNECTION); - - if (!org_freedesktop_NetworkManagerSettings_Connection_get_settings (priv->proxy, &settings, &error)) { - nm_warning ("Can not retrieve settings: %s", error->message); - g_error_free (error); - goto err; - } - - wrapped = nm_connection_new_from_hash (settings, &error); - g_hash_table_destroy (settings); - - if (!wrapped) { - nm_warning ("Invalid connection: '%s' / '%s' invalid: %d", - g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)), - error->message, - error->code); - g_error_free (error); - goto err; - } - - nm_connection_set_scope (wrapped, priv->scope); - nm_connection_set_path (wrapped, priv->path); - - g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); - g_object_unref (wrapped); - - dbus_g_proxy_add_signal (priv->proxy, "Updated", - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "Updated", - G_CALLBACK (connection_updated_cb), - object, NULL); - - dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->proxy, "Removed", - G_CALLBACK (connection_removed_cb), - object, NULL); - - return object; - - err: - g_object_unref (object); - - return NULL; -} - -static void -dispose (GObject *object) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object); - - if (priv->disposed) - return; - - priv->disposed = TRUE; - - g_object_unref (priv->proxy); - dbus_g_connection_unref (priv->dbus_connection); - - G_OBJECT_CLASS (nm_dbus_connection_parent_class)->dispose (object); -} - -static void -finalize (GObject *object) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object); - - g_free (priv->path); - - G_OBJECT_CLASS (nm_dbus_connection_parent_class)->finalize (object); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_BUS: - /* Construct only */ - priv->dbus_connection = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); - break; - case PROP_SCOPE: - /* Construct only */ - priv->scope = (NMConnectionScope) g_value_get_uint (value); - break; - case PROP_PATH: - /* Construct only */ - priv->path = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDBusConnectionPrivate *priv = NM_DBUS_CONNECTION_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_BUS: - g_value_set_boxed (value, priv->dbus_connection); - break; - case PROP_SCOPE: - g_value_set_uint (value, priv->scope); - break; - case PROP_PATH: - g_value_set_string (value, priv->path); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_dbus_connection_class_init (NMDBusConnectionClass *dbus_connection_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (dbus_connection_class); - NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (dbus_connection_class); - - g_type_class_add_private (dbus_connection_class, sizeof (NMDBusConnectionPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - - connection_class->get_settings = get_settings; - connection_class->update = update; - connection_class->do_delete = do_delete; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_BUS, - g_param_spec_boxed (NM_DBUS_CONNECTION_BUS, - "DBusGConnection", - "DBusGConnection", - DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_SCOPE, - g_param_spec_uint (NM_DBUS_CONNECTION_SCOPE, - "Scope", - "NMConnection scope", - NM_CONNECTION_SCOPE_UNKNOWN, - NM_CONNECTION_SCOPE_USER, - NM_CONNECTION_SCOPE_UNKNOWN, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_PATH, - g_param_spec_string (NM_DBUS_CONNECTION_PATH, - "DBus path", - "DBus path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} diff --git a/libnm-glib/nm-dbus-connection.h b/libnm-glib/nm-dbus-connection.h deleted file mode 100644 index e6b0bc675b..0000000000 --- a/libnm-glib/nm-dbus-connection.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifndef NM_DBUS_CONNECTION_H -#define NM_DBUS_CONNECTION_H - -#include -#include - -G_BEGIN_DECLS - -#define NM_TYPE_DBUS_CONNECTION (nm_dbus_connection_get_type ()) -#define NM_DBUS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_CONNECTION, NMDBusConnection)) -#define NM_DBUS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionClass)) -#define NM_IS_DBUS_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_CONNECTION)) -#define NM_IS_DBUS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_CONNECTION)) -#define NM_DBUS_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_CONNECTION, NMDBusConnectionClass)) - -#define NM_DBUS_CONNECTION_BUS "bus" -#define NM_DBUS_CONNECTION_SCOPE "scope" -#define NM_DBUS_CONNECTION_PATH "path" - -typedef struct { - NMExportedConnection parent; -} NMDBusConnection; - -typedef struct { - NMExportedConnectionClass parent; -} NMDBusConnectionClass; - -GType nm_dbus_connection_get_type (void); - -NMDBusConnection *nm_dbus_connection_new (DBusGConnection *dbus_connection, - NMConnectionScope scope, - const char *path); - -G_END_DECLS - -#endif /* NM_DBUS_CONNECTION_H */ diff --git a/libnm-glib/nm-dbus-settings-system.c b/libnm-glib/nm-dbus-settings-system.c deleted file mode 100644 index 16ff4ec0a5..0000000000 --- a/libnm-glib/nm-dbus-settings-system.c +++ /dev/null @@ -1,391 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - * Copyright (C) 2008 Red Hat, Inc. - */ - -#include -#include -#include "nm-dbus-settings-system.h" -#include "nm-settings-system-bindings.h" - -G_DEFINE_TYPE (NMDBusSettingsSystem, nm_dbus_settings_system, NM_TYPE_DBUS_SETTINGS) - -#define NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemPrivate)) - -typedef struct { - DBusGProxy *settings_proxy; - DBusGProxy *props_proxy; - - gboolean got_unmanaged_devices; - GSList *unmanaged_devices; - - gboolean got_hostname; - char *hostname; - - gboolean got_can_modify; - gboolean can_modify; - - gboolean disposed; -} NMDBusSettingsSystemPrivate; - -enum { - PROP_0, - PROP_UNMANAGED_DEVICES, - PROP_HOSTNAME, - PROP_CAN_MODIFY, - - LAST_PROP -}; - -NMDBusSettingsSystem * -nm_dbus_settings_system_new (DBusGConnection *dbus_connection) -{ - g_return_val_if_fail (dbus_connection != NULL, NULL); - - return (NMDBusSettingsSystem *) g_object_new (NM_TYPE_DBUS_SETTINGS_SYSTEM, - NM_DBUS_SETTINGS_DBUS_CONNECTION, dbus_connection, - NM_DBUS_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM, - NULL); -} - -gboolean -nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self, - NMConnection *connection, - GError **err) -{ - NMDBusSettingsSystemPrivate *priv; - GHashTable *settings; - gboolean ret; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE); - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - settings = nm_connection_to_hash (connection); - - ret = org_freedesktop_NetworkManagerSettings_System_add_connection (priv->settings_proxy, settings, err); - g_hash_table_destroy (settings); - - return ret; -} - -static void -update_unmanaged_devices (NMDBusSettingsSystem *self, GValue *value) -{ - NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - if (priv->unmanaged_devices) { - g_slist_foreach (priv->unmanaged_devices, (GFunc) g_free, NULL); - g_slist_free (priv->unmanaged_devices); - priv->unmanaged_devices = NULL; - } - - if (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_ARRAY) { - GPtrArray *array; - int i; - - array = (GPtrArray *) g_value_get_boxed (value); - for (i = 0; i < array->len; i++) - priv->unmanaged_devices = g_slist_prepend (priv->unmanaged_devices, - g_strdup ((const char *) g_ptr_array_index (array, i))); - - priv->got_unmanaged_devices = TRUE; - } else - g_warning ("Invalid return value type: %s", G_VALUE_TYPE_NAME (value)); -} - -GSList * -nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self) -{ - NMDBusSettingsSystemPrivate *priv; - GValue value = { 0, }; - GError *err = NULL; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), NULL); - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - if (priv->got_unmanaged_devices) - return priv->unmanaged_devices; - - if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err, - G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS, - G_TYPE_STRING, "UnmanagedDevices", - G_TYPE_INVALID, - G_TYPE_VALUE, &value, - G_TYPE_INVALID)) { - g_warning ("Could not retrieve unmanaged devices: %s", err->message); - g_error_free (err); - return NULL; - } - - update_unmanaged_devices (self, &value); - g_value_unset (&value); - - return priv->unmanaged_devices; -} - -gboolean -nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self, - const char *hostname, - GError **err) -{ - NMDBusSettingsSystemPrivate *priv; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE); - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - return org_freedesktop_NetworkManagerSettings_System_save_hostname (priv->settings_proxy, hostname ? hostname : "", err); -} - -static void -update_hostname (NMDBusSettingsSystem *self, GValue *value) -{ - NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - if (priv->hostname) { - g_free (priv->hostname); - priv->hostname = NULL; - } - - if (G_VALUE_TYPE (value) == G_TYPE_STRING) { - priv->hostname = g_value_dup_string (value); - priv->got_hostname = TRUE; - } else - g_warning ("%s: Invalid return value type: %s", __func__, G_VALUE_TYPE_NAME (value)); -} - -const char * -nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self) -{ - NMDBusSettingsSystemPrivate *priv; - GValue value = { 0, }; - GError *err = NULL; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), NULL); - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - if (priv->got_hostname) - return priv->hostname; - - if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err, - G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS, - G_TYPE_STRING, "Hostname", - G_TYPE_INVALID, - G_TYPE_VALUE, &value, - G_TYPE_INVALID)) { - g_warning ("Could not retrieve hostname: %s", err->message); - g_error_free (err); - return NULL; - } - - update_hostname (self, &value); - g_value_unset (&value); - - return priv->hostname; -} - -gboolean -nm_dbus_settings_system_get_can_modify (NMDBusSettingsSystem *self) -{ - NMDBusSettingsSystemPrivate *priv; - GValue value = { 0, }; - GError *err = NULL; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS_SYSTEM (self), FALSE); - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - - if (priv->got_can_modify) - return priv->can_modify; - - if (!dbus_g_proxy_call (priv->props_proxy, "Get", &err, - G_TYPE_STRING, NM_DBUS_SERVICE_SYSTEM_SETTINGS, - G_TYPE_STRING, "CanModify", - G_TYPE_INVALID, - G_TYPE_VALUE, &value, - G_TYPE_INVALID)) { - g_warning ("Could not retrieve can-modify: %s", err->message); - g_error_free (err); - return FALSE; - } - - priv->can_modify = g_value_get_boolean (&value); - g_value_unset (&value); - - return priv->can_modify; -} - -static void -proxy_properties_changed (DBusGProxy *proxy, - GHashTable *properties, - gpointer user_data) -{ - NMDBusSettingsSystem *self = NM_DBUS_SETTINGS_SYSTEM (user_data); - NMDBusSettingsSystemPrivate * priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (self); - GValue *value; - - value = (GValue *) g_hash_table_lookup (properties, "UnmanagedDevices"); - if (value) { - update_unmanaged_devices (self, value); - g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES); - } - - value = (GValue *) g_hash_table_lookup (properties, "Hostname"); - if (value) { - update_hostname (self, value); - g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_HOSTNAME); - } - - value = (GValue *) g_hash_table_lookup (properties, "CanModify"); - if (value) { - priv->can_modify = g_value_get_boolean (value); - g_object_notify (G_OBJECT (self), NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY); - } -} - -static void -nm_dbus_settings_system_init (NMDBusSettingsSystem *self) -{ -} - -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDBusSettingsSystemPrivate *priv; - DBusGConnection *dbus_connection = NULL; - - object = G_OBJECT_CLASS (nm_dbus_settings_system_parent_class)->constructor (type, n_construct_params, construct_params); - - if (!object) - return NULL; - - priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (object); - - g_object_get (object, - NM_DBUS_SETTINGS_DBUS_CONNECTION, &dbus_connection, - NULL); - - priv->settings_proxy = dbus_g_proxy_new_for_name (dbus_connection, - NM_DBUS_SERVICE_SYSTEM_SETTINGS, - NM_DBUS_PATH_SETTINGS, - NM_DBUS_IFACE_SETTINGS_SYSTEM); - dbus_g_proxy_add_signal (priv->settings_proxy, "PropertiesChanged", - DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->settings_proxy, "PropertiesChanged", - G_CALLBACK (proxy_properties_changed), - object, NULL); - - priv->props_proxy = dbus_g_proxy_new_for_name (dbus_connection, - NM_DBUS_SERVICE_SYSTEM_SETTINGS, - NM_DBUS_PATH_SETTINGS, - "org.freedesktop.DBus.Properties"); - - return object; -} - -static void -dispose (GObject *object) -{ - NMDBusSettingsSystemPrivate *priv = NM_DBUS_SETTINGS_SYSTEM_GET_PRIVATE (object); - - if (priv->disposed) - return; - - priv->disposed = TRUE; - - g_free (priv->hostname); - - if (priv->unmanaged_devices) { - g_slist_foreach (priv->unmanaged_devices, (GFunc) g_free, NULL); - g_slist_free (priv->unmanaged_devices); - } - - g_object_unref (priv->settings_proxy); - g_object_unref (priv->props_proxy); - - G_OBJECT_CLASS (nm_dbus_settings_system_parent_class)->dispose (object); -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDBusSettingsSystem *self = NM_DBUS_SETTINGS_SYSTEM (object); - - switch (prop_id) { - case PROP_UNMANAGED_DEVICES: - g_value_set_pointer (value, nm_dbus_settings_system_get_unmanaged_devices (self)); - break; - case PROP_HOSTNAME: - g_value_set_string (value, nm_dbus_settings_system_get_hostname (self)); - break; - case PROP_CAN_MODIFY: - g_value_set_boolean (value, nm_dbus_settings_system_get_can_modify (self)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_dbus_settings_system_class_init (NMDBusSettingsSystemClass *dbus_settings_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (dbus_settings_class); - - g_type_class_add_private (dbus_settings_class, sizeof (NMDBusSettingsSystemPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->dispose = dispose; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_UNMANAGED_DEVICES, - g_param_spec_pointer (NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES, - "Unmanaged devices", - "Unmanaged devices", - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_HOSTNAME, - g_param_spec_string (NM_DBUS_SETTINGS_SYSTEM_HOSTNAME, - "Hostname", - "Configured hostname", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_HOSTNAME, - g_param_spec_boolean (NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY, - "Can modify", - "Can modify", - FALSE, - G_PARAM_READABLE)); -} - diff --git a/libnm-glib/nm-dbus-settings-system.h b/libnm-glib/nm-dbus-settings-system.h deleted file mode 100644 index 5c6175b6a8..0000000000 --- a/libnm-glib/nm-dbus-settings-system.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - * Copyright (C) 2008 Red Hat, Inc. - */ - -#ifndef NM_DBUS_SETTINGS_SYSTEM_H -#define NM_DBUS_SETTINGS_SYSTEM_H - -#include - -G_BEGIN_DECLS - -#define NM_TYPE_DBUS_SETTINGS_SYSTEM (nm_dbus_settings_system_get_type ()) -#define NM_DBUS_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystem)) -#define NM_DBUS_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemClass)) -#define NM_IS_DBUS_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM)) -#define NM_IS_DBUS_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM)) -#define NM_DBUS_SETTINGS_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_SETTINGS_SYSTEM, NMDBusSettingsSystemClass)) - -#define NM_DBUS_SETTINGS_SYSTEM_UNMANAGED_DEVICES "unmanaged-devices" -#define NM_DBUS_SETTINGS_SYSTEM_HOSTNAME "hostname" -#define NM_DBUS_SETTINGS_SYSTEM_CAN_MODIFY "can-modify" - -typedef struct { - NMDBusSettings parent; -} NMDBusSettingsSystem; - -typedef struct { - NMDBusSettingsClass parent; -} NMDBusSettingsSystemClass; - -GType nm_dbus_settings_system_get_type (void); - -NMDBusSettingsSystem *nm_dbus_settings_system_new (DBusGConnection *dbus_connection); - -gboolean nm_dbus_settings_system_add_connection (NMDBusSettingsSystem *self, - NMConnection *connection, - GError **err); - -GSList *nm_dbus_settings_system_get_unmanaged_devices (NMDBusSettingsSystem *self); - -const char *nm_dbus_settings_system_get_hostname (NMDBusSettingsSystem *self); - -gboolean nm_dbus_settings_system_save_hostname (NMDBusSettingsSystem *self, - const char *hostname, - GError **err); - -gboolean nm_dbus_settings_system_get_can_modify (NMDBusSettingsSystem *self); - -G_END_DECLS - -#endif /* NM_DBUS_SETTINGS_SYSTEM_H */ diff --git a/libnm-glib/nm-dbus-settings.c b/libnm-glib/nm-dbus-settings.c deleted file mode 100644 index 9f47d903a4..0000000000 --- a/libnm-glib/nm-dbus-settings.c +++ /dev/null @@ -1,373 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - */ - -#include -#include -#include - -#include "nm-dbus-settings.h" -#include "nm-settings-bindings.h" - -G_DEFINE_TYPE (NMDBusSettings, nm_dbus_settings, NM_TYPE_SETTINGS) - -#define NM_DBUS_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsPrivate)) - -typedef struct { - DBusGConnection *dbus_connection; - NMConnectionScope scope; - DBusGProxy *settings_proxy; - DBusGProxy *dbus_proxy; - - GHashTable *connections; - - gboolean disposed; -} NMDBusSettingsPrivate; - -enum { - PROP_0, - PROP_DBUS_CONNECTION, - PROP_SCOPE, - - LAST_PROP -}; - -NMDBusSettings * -nm_dbus_settings_new (DBusGConnection *dbus_connection) -{ - g_return_val_if_fail (dbus_connection != NULL, NULL); - - return (NMDBusSettings *) g_object_new (NM_TYPE_DBUS_SETTINGS, - NM_DBUS_SETTINGS_DBUS_CONNECTION, dbus_connection, - NM_DBUS_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_USER, - NULL); -} - -NMDBusConnection * -nm_dbus_settings_get_connection_by_path (NMDBusSettings *self, const char *path) -{ - g_return_val_if_fail (NM_IS_DBUS_SETTINGS (self), NULL); - g_return_val_if_fail (path != NULL, NULL); - - return g_hash_table_lookup (NM_DBUS_SETTINGS_GET_PRIVATE (self)->connections, path); -} - -static void -connection_removed_cb (NMExportedConnection *exported, gpointer user_data) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (user_data); - NMConnection *connection; - - connection = nm_exported_connection_get_connection (exported); - g_hash_table_remove (priv->connections, nm_connection_get_path (connection)); -} - -static void -new_connection_cb (DBusGProxy *proxy, - const char *path, - gpointer user_data) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (user_data); - NMDBusConnection *connection; - - connection = nm_dbus_connection_new (priv->dbus_connection, priv->scope, path); - if (connection) { - g_signal_connect (connection, "removed", - G_CALLBACK (connection_removed_cb), - user_data); - - g_hash_table_insert (priv->connections, g_strdup (path), connection); - nm_settings_signal_new_connection (NM_SETTINGS (user_data), - NM_EXPORTED_CONNECTION (connection)); - } -} - -static void -fetch_connections_done (DBusGProxy *proxy, - GPtrArray *connections, - GError *err, - gpointer user_data) -{ - if (!err) { - int i; - - for (i = 0; i < connections->len; i++) { - char *path = g_ptr_array_index (connections, i); - - new_connection_cb (proxy, path, user_data); - g_free (path); - } - - g_ptr_array_free (connections, TRUE); - } else { - g_warning ("Could not retrieve dbus connections: %s.", err->message); - g_error_free (err); - } -} - -static void -settings_proxy_destroyed (gpointer data, GObject *destroyed_object) -{ - NM_DBUS_SETTINGS_GET_PRIVATE (data)->settings_proxy = NULL; -} - -static gboolean -fetch_connections (gpointer data) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (data); - DBusGProxyCall *call; - - if (!priv->settings_proxy) { - const char *service = (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) ? - NM_DBUS_SERVICE_SYSTEM_SETTINGS : NM_DBUS_SERVICE_USER_SETTINGS; - - priv->settings_proxy = dbus_g_proxy_new_for_name (priv->dbus_connection, - service, - NM_DBUS_PATH_SETTINGS, - NM_DBUS_IFACE_SETTINGS); - - g_object_weak_ref (G_OBJECT (priv->settings_proxy), settings_proxy_destroyed, data); - - dbus_g_proxy_add_signal (priv->settings_proxy, "NewConnection", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->settings_proxy, "NewConnection", - G_CALLBACK (new_connection_cb), - data, - NULL); - } - - call = org_freedesktop_NetworkManagerSettings_list_connections_async (priv->settings_proxy, - fetch_connections_done, - data); - - return FALSE; -} - -static void -hash_values_to_slist (gpointer key, gpointer data, gpointer user_data) -{ - GSList **list = (GSList **) user_data; - - *list = g_slist_prepend (*list, data); -} - -static GSList * -list_connections (NMSettings *settings) -{ - GSList *list = NULL; - - g_return_val_if_fail (NM_IS_DBUS_SETTINGS (settings), NULL); - - g_hash_table_foreach (NM_DBUS_SETTINGS_GET_PRIVATE (settings)->connections, hash_values_to_slist, &list); - - return list; -} - -static void -remove_one_connection (gpointer key, gpointer value, gpointer user_data) -{ - nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (value)); -} - -static gboolean -remove_connections (gpointer data) -{ - NMDBusSettings *self = NM_DBUS_SETTINGS (data); - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (self); - - g_hash_table_foreach (priv->connections, remove_one_connection, NULL); - - return FALSE; -} - -static void -name_owner_changed (DBusGProxy *proxy, - const char *name, - const char *old_owner, - const char *new_owner, - gpointer user_data) -{ - if (!strcmp (name, NM_DBUS_SERVICE_SYSTEM_SETTINGS)) { - if (new_owner && strlen (new_owner) > 0) - g_idle_add (fetch_connections, user_data); - else - g_idle_add (remove_connections, user_data); - } -} - -/* GObject stuff */ - -static void -nm_dbus_settings_init (NMDBusSettings *settings) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (settings); - - priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); -} - -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMDBusSettingsPrivate *priv; - - object = G_OBJECT_CLASS (nm_dbus_settings_parent_class)->constructor (type, n_construct_params, construct_params); - - if (!object) - return NULL; - - priv = NM_DBUS_SETTINGS_GET_PRIVATE (object); - - if (!priv->dbus_connection) { - g_warning ("DBus connection not provided."); - goto err; - } - - if (priv->scope == NM_CONNECTION_SCOPE_UNKNOWN) { - g_warning ("Connection scope not provided."); - goto err; - } - - priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->dbus_connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); - - dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", - G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_INVALID); - dbus_g_proxy_connect_signal (priv->dbus_proxy, - "NameOwnerChanged", - G_CALLBACK (name_owner_changed), - object, NULL); - - g_idle_add (fetch_connections, object); - - return object; - - err: - g_object_unref (object); - - return NULL; -} - -static void -dispose (GObject *object) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object); - - if (priv->disposed) - return; - - priv->disposed = TRUE; - - if (priv->connections) - g_hash_table_destroy (priv->connections); - - if (priv->dbus_proxy) - g_object_unref (priv->dbus_proxy); - - if (priv->settings_proxy) - g_object_unref (priv->settings_proxy); - - dbus_g_connection_unref (priv->dbus_connection); - - G_OBJECT_CLASS (nm_dbus_settings_parent_class)->dispose (object); -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_DBUS_CONNECTION: - /* Construct only */ - priv->dbus_connection = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); - break; - case PROP_SCOPE: - priv->scope = (NMConnectionScope) g_value_get_uint (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMDBusSettingsPrivate *priv = NM_DBUS_SETTINGS_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_DBUS_CONNECTION: - g_value_set_boxed (value, priv->dbus_connection); - break; - case PROP_SCOPE: - g_value_set_uint (value, priv->scope); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_dbus_settings_class_init (NMDBusSettingsClass *dbus_settings_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (dbus_settings_class); - NMSettingsClass *settings_class = NM_SETTINGS_CLASS (dbus_settings_class); - - g_type_class_add_private (dbus_settings_class, sizeof (NMDBusSettingsPrivate)); - - /* Virtual methods */ - object_class->constructor = constructor; - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = dispose; - - settings_class->list_connections = list_connections; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_DBUS_CONNECTION, - g_param_spec_boxed (NM_DBUS_SETTINGS_DBUS_CONNECTION, - "DBusGConnection", - "DBusGConnection", - DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_class_install_property - (object_class, PROP_SCOPE, - g_param_spec_uint (NM_DBUS_SETTINGS_SCOPE, - "Scope", - "NMConnection scope", - NM_CONNECTION_SCOPE_UNKNOWN, - NM_CONNECTION_SCOPE_USER, - NM_CONNECTION_SCOPE_USER, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} diff --git a/libnm-glib/nm-dbus-settings.h b/libnm-glib/nm-dbus-settings.h deleted file mode 100644 index bdf33ec094..0000000000 --- a/libnm-glib/nm-dbus-settings.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2008 Novell, Inc. - */ - -#ifndef NM_DBUS_SETTINGS_H -#define NM_DBUS_SETTINGS_H - -#include -#include -#include -#include - -G_BEGIN_DECLS - -#define NM_TYPE_DBUS_SETTINGS (nm_dbus_settings_get_type ()) -#define NM_DBUS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DBUS_SETTINGS, NMDBusSettings)) -#define NM_DBUS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsClass)) -#define NM_IS_DBUS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DBUS_SETTINGS)) -#define NM_IS_DBUS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_DBUS_SETTINGS)) -#define NM_DBUS_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DBUS_SETTINGS, NMDBusSettingsClass)) - -#define NM_DBUS_SETTINGS_DBUS_CONNECTION "dbus-connection" -#define NM_DBUS_SETTINGS_SCOPE "scope" - -typedef struct { - NMSettings parent; -} NMDBusSettings; - -typedef struct { - NMSettingsClass parent; -} NMDBusSettingsClass; - -GType nm_dbus_settings_get_type (void); - -NMDBusSettings *nm_dbus_settings_new (DBusGConnection *dbus_connection); - -NMDBusConnection *nm_dbus_settings_get_connection_by_path (NMDBusSettings *self, - const char *path); - -G_END_DECLS - -#endif /* NM_DBUS_SETTINGS_H */ diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c new file mode 100644 index 0000000000..57dde41442 --- /dev/null +++ b/libnm-glib/nm-exported-connection.c @@ -0,0 +1,306 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2008 Novell, Inc. + * (C) Copyright 2008 - 2009 Red Hat, Inc. + */ + +#include +#include + +#include "nm-exported-connection.h" +#include "nm-settings-connection-interface.h" + +static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection, + GHashTable **settings, + GError **error); + +static void impl_exported_connection_update (NMExportedConnection *connection, + GHashTable *new_settings, + DBusGMethodInvocation *context); + +static void impl_exported_connection_delete (NMExportedConnection *connection, + DBusGMethodInvocation *context); + +static void impl_exported_connection_get_secrets (NMExportedConnection *connection, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context); + +#include "nm-exported-connection-glue.h" + +G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION) + +#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_EXPORTED_CONNECTION, \ + NMExportedConnectionPrivate)) + +typedef struct { + DBusGConnection *bus; + gboolean disposed; +} NMExportedConnectionPrivate; + +enum { + PROP_0, + PROP_BUS, + + LAST_PROP +}; + + +/**************************************************************/ + +void +nm_exported_connection_export (NMExportedConnection *self) +{ + NMExportedConnectionPrivate *priv; + static guint32 ec_counter = 0; + char *path; + + g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_EXPORTED_CONNECTION (self)); + + priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (self); + + /* Don't allow exporting twice */ + g_return_if_fail (nm_connection_get_path (NM_CONNECTION (self)) == NULL); + + path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); + nm_connection_set_path (NM_CONNECTION (self), path); + dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (self)); + g_free (path); +} + +static GHashTable * +real_get_settings (NMExportedConnection *self, GError **error) +{ + NMConnection *no_secrets; + GHashTable *settings; + + /* Secrets should *never* be returned by the GetSettings method, they + * get returned by the GetSecrets method which can be better + * protected against leakage of secrets to unprivileged callers. + */ + no_secrets = nm_connection_duplicate (NM_CONNECTION (self)); + g_assert (no_secrets); + nm_connection_clear_secrets (no_secrets); + settings = nm_connection_to_hash (no_secrets); + g_assert (settings); + g_object_unref (no_secrets); + + return settings; +} + +/**************************************************************/ + +static gboolean +impl_exported_connection_get_settings (NMExportedConnection *self, + GHashTable **settings, + GError **error) +{ + /* Must always be implemented */ + g_assert (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings); + *settings = NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_settings (self, error); + return *settings ? TRUE : FALSE; +} + +static void +impl_exported_connection_update (NMExportedConnection *self, + GHashTable *new_settings, + DBusGMethodInvocation *context) +{ + NMConnection *tmp; + GError *error = NULL; + + /* Check if the settings are valid first */ + tmp = nm_connection_new_from_hash (new_settings, &error); + if (!tmp) { + g_assert (error); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + g_object_unref (tmp); + + if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->update) + NM_EXPORTED_CONNECTION_GET_CLASS (self)->update (self, new_settings, context); + else { + error = g_error_new (0, 0, "%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +static void +impl_exported_connection_delete (NMExportedConnection *self, + DBusGMethodInvocation *context) +{ + GError *error = NULL; + + if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete) + NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete (self, context); + else { + error = g_error_new (0, 0, "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +static void +impl_exported_connection_get_secrets (NMExportedConnection *self, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context) +{ + GError *error = NULL; + + if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets) + NM_EXPORTED_CONNECTION_GET_CLASS (self)->get_secrets (self, setting_name, hints, request_new, context); + else { + error = g_error_new (0, 0, "%s: %s:%d get_secrets() unimplemented", __func__, __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/**************************************************************/ + +/** + * nm_exported_connection_new: + * @bus: a valid and connected D-Bus connection + * @scope: the Connection scope (either user or system) + * @path: the D-Bus path of the connection as exported by the settings service + * indicated by @scope + * + * Creates a new object representing the remote connection. + * + * Returns: the new exported connection object on success, or %NULL on failure + **/ +NMExportedConnection * +nm_exported_connection_new (DBusGConnection *bus, + NMConnectionScope scope) +{ + g_return_val_if_fail (bus != NULL, NULL); + g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL); + + return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION, + NM_EXPORTED_CONNECTION_BUS, bus, + NM_CONNECTION_SCOPE, scope, + NULL); +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMExportedConnectionPrivate *priv; + + object = G_OBJECT_CLASS (nm_exported_connection_parent_class)->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); + g_assert (priv->bus); + + return object; +} + +static void +nm_exported_connection_init (NMExportedConnection *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + /* Construct only */ + priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + g_value_set_boxed (value, priv->bus); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); + + if (!priv->disposed) { + priv->disposed = TRUE; + dbus_g_connection_unref (priv->bus); + } + + G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object); +} + +static void +nm_exported_connection_class_init (NMExportedConnectionClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMExportedConnectionPrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + + class->get_settings = real_get_settings; + + /** + * NMExportedConnection:bus: + * + * The %DBusGConnection which this object is exported on + **/ + g_object_class_install_property (object_class, PROP_BUS, + g_param_spec_boxed (NM_EXPORTED_CONNECTION_BUS, + "Bus", + "Bus", + DBUS_TYPE_G_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), + &dbus_glib_nm_exported_connection_object_info); +} diff --git a/libnm-glib/nm-exported-connection.h b/libnm-glib/nm-exported-connection.h new file mode 100644 index 0000000000..79c7f80c39 --- /dev/null +++ b/libnm-glib/nm-exported-connection.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Red Hat, Inc. + */ + +#ifndef NM_EXPORTED_CONNECTION_H +#define NM_EXPORTED_CONNECTION_H + +#include +#include + +G_BEGIN_DECLS + +#define NM_TYPE_EXPORTED_CONNECTION (nm_exported_connection_get_type ()) +#define NM_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnection)) +#define NM_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass)) +#define NM_IS_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION)) +#define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION)) +#define NM_EXPORTED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass)) + +#define NM_EXPORTED_CONNECTION_BUS "bus" + +typedef struct { + NMConnection parent; +} NMExportedConnection; + +typedef struct { + NMConnectionClass parent; + + GHashTable * (*get_settings) (NMExportedConnection *self, + GError **error); + + void (*update) (NMExportedConnection *self, + GHashTable *new_settings, + DBusGMethodInvocation *context); + + void (*delete) (NMExportedConnection *self, + DBusGMethodInvocation *context); + + void (*get_secrets) (NMExportedConnection *self, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context); +} NMExportedConnectionClass; + +GType nm_exported_connection_get_type (void); + +NMExportedConnection *nm_exported_connection_new (DBusGConnection *bus, + NMConnectionScope scope); + +void nm_exported_connection_export (NMExportedConnection *self); + +G_END_DECLS + +#endif /* NM_EXPORTED_CONNECTION_H */ diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c new file mode 100644 index 0000000000..76fdcf0244 --- /dev/null +++ b/libnm-glib/nm-remote-connection.c @@ -0,0 +1,419 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#include + +#include +#include +#include +#include "nm-remote-connection.h" +#include "nm-dbus-glib-types.h" +#include "nm-exported-connection-bindings.h" +#include "nm-settings-connection-interface.h" + +#define NM_REMOTE_CONNECTION_BUS "bus" + +static void settings_connection_interface_init (NMSettingsConnectionInterface *klass); + +G_DEFINE_TYPE_EXTENDED (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, settings_connection_interface_init)) + +enum { + PROP_0, + PROP_BUS, + + LAST_PROP +}; + + +typedef struct { + NMRemoteConnection *self; + DBusGProxy *proxy; + DBusGProxyCall *call; + GFunc callback; + gpointer user_data; +} RemoteCall; + +typedef struct { + DBusGConnection *bus; + DBusGProxy *proxy; + DBusGProxy *secrets_proxy; + GSList *calls; + + gboolean disposed; +} NMRemoteConnectionPrivate; + +#define NM_REMOTE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionPrivate)) + +/****************************************************************/ + +static void +remote_call_complete (NMRemoteConnection *self, RemoteCall *call) +{ + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + + priv->calls = g_slist_remove (priv->calls, call); + /* Don't need to cancel it since this function should only be called from + * the dispose handler (where the proxy will be destroyed immediately after) + * or from the call's completion callback. + */ + memset (call, 0, sizeof (RemoteCall)); + g_free (call); +} + +static void +update_cb (DBusGProxy *proxy, GError *error, gpointer user_data) +{ + RemoteCall *call = user_data; + NMSettingsConnectionInterfaceUpdateFunc func = (NMSettingsConnectionInterfaceUpdateFunc) call->callback; + + (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data); + remote_call_complete (call->self, call); +} + +static gboolean +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + GHashTable *settings = NULL; + RemoteCall *call; + + call = g_malloc0 (sizeof (RemoteCall)); + call->self = self; + call->callback = (GFunc) callback; + call->user_data = user_data; + call->proxy = priv->proxy; + + settings = nm_connection_to_hash (NM_CONNECTION (self)); + + call->call = org_freedesktop_NetworkManagerSettings_Connection_update_async (priv->proxy, + settings, + update_cb, + call); + g_assert (call->call); + priv->calls = g_slist_append (priv->calls, call); + + g_hash_table_destroy (settings); + + return TRUE; +} + +static void +delete_cb (DBusGProxy *proxy, GError *error, gpointer user_data) +{ + RemoteCall *call = user_data; + NMSettingsConnectionInterfaceDeleteFunc func = (NMSettingsConnectionInterfaceDeleteFunc) call->callback; + + (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), error, call->user_data); + remote_call_complete (call->self, call); +} + +static gboolean +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + RemoteCall *call; + + call = g_malloc0 (sizeof (RemoteCall)); + call->self = self; + call->callback = (GFunc) callback; + call->user_data = user_data; + call->proxy = priv->proxy; + + call->call = org_freedesktop_NetworkManagerSettings_Connection_delete_async (priv->proxy, + delete_cb, + call); + g_assert (call->call); + priv->calls = g_slist_append (priv->calls, call); + + return TRUE; +} + +static void +get_secrets_cb (DBusGProxy *proxy, GHashTable *secrets, GError *error, gpointer user_data) +{ + RemoteCall *call = user_data; + NMSettingsConnectionInterfaceGetSecretsFunc func = (NMSettingsConnectionInterfaceGetSecretsFunc) call->callback; + + (*func)(NM_SETTINGS_CONNECTION_INTERFACE (call->self), secrets, error, call->user_data); + remote_call_complete (call->self, call); +} + +static gboolean +get_secrets (NMSettingsConnectionInterface *connection, + const char *setting_name, + const char **hints, + gboolean request_new, + NMSettingsConnectionInterfaceGetSecretsFunc callback, + gpointer user_data) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (connection); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + RemoteCall *call; + + call = g_malloc0 (sizeof (RemoteCall)); + call->self = self; + call->callback = (GFunc) callback; + call->user_data = user_data; + call->proxy = priv->secrets_proxy; + + call->call = org_freedesktop_NetworkManagerSettings_Connection_Secrets_get_secrets_async (priv->proxy, + setting_name, + hints, + request_new, + get_secrets_cb, + call); + g_assert (call->call); + priv->calls = g_slist_append (priv->calls, call); + + return TRUE; +} + +/****************************************************************/ + +static gboolean +replace_settings (NMRemoteConnection *self, GHashTable *new_settings) +{ + GError *error = NULL; + + if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) { + g_warning ("%s: error updating %s connection %s settings: (%d) %s", + __func__, + (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system", + nm_connection_get_path (NM_CONNECTION (self)), + error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + return FALSE; + } + + /* Emit update irregardless to let listeners figure out what to do with + * the connection; whether to delete / ignore it or not. + */ + nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (self)); + return TRUE; +} + +static void +get_settings_cb (DBusGProxy *proxy, + GHashTable *new_settings, + GError *error, + gpointer user_data) +{ + NMRemoteConnection *self = user_data; + + if (error) { + g_warning ("%s: error getting %s connection %s settings: (%d) %s", + __func__, + (nm_connection_get_scope (NM_CONNECTION (self)) == NM_CONNECTION_SCOPE_USER) ? "user" : "system", + nm_connection_get_path (NM_CONNECTION (self)), + error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_error_free (error); + } else { + replace_settings (self, new_settings); + g_hash_table_destroy (new_settings); + } +} + +static void +updated_cb (DBusGProxy *proxy, GHashTable *settings, gpointer user_data) +{ + replace_settings (NM_REMOTE_CONNECTION (user_data), settings); +} + +static void +removed_cb (DBusGProxy *proxy, gpointer user_data) +{ + g_signal_emit_by_name (G_OBJECT (user_data), "removed"); +} + +/****************************************************************/ + +static void +settings_connection_interface_init (NMSettingsConnectionInterface *klass) +{ + /* interface implementation */ + klass->update = update; + klass->delete = do_delete; + klass->get_secrets = get_secrets; +} + +/** + * nm_remote_connection_new: + * @bus: a valid and connected D-Bus connection + * @scope: the Connection scope (either user or system) + * @path: the D-Bus path of the connection as exported by the settings service + * indicated by @scope + * + * Creates a new object representing the remote connection. + * + * Returns: the new remote connection object on success, or %NULL on failure + **/ +NMRemoteConnection * +nm_remote_connection_new (DBusGConnection *bus, + NMConnectionScope scope, + const char *path) +{ + g_return_val_if_fail (bus != NULL, NULL); + g_return_val_if_fail (path != NULL, NULL); + + return (NMRemoteConnection *) g_object_new (NM_TYPE_REMOTE_CONNECTION, + NM_REMOTE_CONNECTION_BUS, bus, + NM_CONNECTION_SCOPE, scope, + NM_CONNECTION_PATH, path, + NULL); +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMRemoteConnectionPrivate *priv; + const char *service = NM_DBUS_SERVICE_USER_SETTINGS; + + object = G_OBJECT_CLASS (nm_remote_connection_parent_class)->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); + g_assert (priv->bus); + g_assert (nm_connection_get_path (NM_CONNECTION (object))); + + if (nm_connection_get_scope (NM_CONNECTION (object)) == NM_CONNECTION_SCOPE_SYSTEM) + service = NM_DBUS_SERVICE_SYSTEM_SETTINGS; + + priv->proxy = dbus_g_proxy_new_for_name (priv->bus, + service, + nm_connection_get_path (NM_CONNECTION (object)), + NM_DBUS_IFACE_SETTINGS_CONNECTION); + g_assert (priv->proxy); + + priv->secrets_proxy = dbus_g_proxy_new_for_name (priv->bus, + service, + nm_connection_get_path (NM_CONNECTION (object)), + NM_DBUS_IFACE_SETTINGS_CONNECTION_SECRETS); + g_assert (priv->secrets_proxy); + + dbus_g_proxy_add_signal (priv->proxy, "Updated", DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "Updated", G_CALLBACK (updated_cb), object, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "Removed", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "Removed", G_CALLBACK (removed_cb), object, NULL); + + org_freedesktop_NetworkManagerSettings_Connection_get_settings_async (priv->proxy, + get_settings_cb, + object); + return object; +} + +static void +nm_remote_connection_init (NMRemoteConnection *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + /* Construct only */ + priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (object); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_BUS: + g_value_set_boxed (value, priv->bus); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMRemoteConnection *self = NM_REMOTE_CONNECTION (object); + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (object); + + if (!priv->disposed) { + priv->disposed = TRUE; + + while (g_slist_length (priv->calls)) + remote_call_complete (self, priv->calls->data); + + g_object_unref (priv->proxy); + g_object_unref (priv->secrets_proxy); + dbus_g_connection_unref (priv->bus); + } + + G_OBJECT_CLASS (nm_remote_connection_parent_class)->dispose (object); +} + +static void +nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (remote_class); + + g_type_class_add_private (object_class, sizeof (NMRemoteConnectionPrivate)); + + /* virtual methods */ + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + object_class->constructor = constructor; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_BUS, + g_param_spec_boxed (NM_REMOTE_CONNECTION_BUS, + "DBusGConnection", + "DBusGConnection", + DBUS_TYPE_G_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + diff --git a/libnm-glib/nm-remote-connection.h b/libnm-glib/nm-remote-connection.h new file mode 100644 index 0000000000..1210684d05 --- /dev/null +++ b/libnm-glib/nm-remote-connection.h @@ -0,0 +1,57 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#ifndef __NM_REMOTE_CONNECTION_H__ +#define __NM_REMOTE_CONNECTION_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_REMOTE_CONNECTION (nm_remote_connection_get_type ()) +#define NM_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnection)) +#define NM_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass)) +#define NM_IS_REMOTE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION)) +#define NM_IS_REMOTE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_CONNECTION)) +#define NM_REMOTE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_CONNECTION, NMRemoteConnectionClass)) + +typedef struct { + NMConnection parent; +} NMRemoteConnection; + +typedef struct { + NMConnectionClass parent_class; +} NMRemoteConnectionClass; + +GType nm_remote_connection_get_type (void); + +NMRemoteConnection *nm_remote_connection_new (DBusGConnection *dbus_connection, + NMConnectionScope scope, + const char *path); +G_END_DECLS + +#endif /* __NM_REMOTE_CONNECTION__ */ + diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c new file mode 100644 index 0000000000..9dcca659e0 --- /dev/null +++ b/libnm-glib/nm-remote-settings-system.c @@ -0,0 +1,259 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2008 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ + +#include +#include +#include + +#include "nm-marshal.h" +#include "nm-dbus-glib-types.h" +#include "nm-remote-settings-system.h" +#include "nm-settings-system-bindings.h" +#include "nm-settings-system-interface.h" + +static void settings_system_interface_init (NMSettingsSystemInterface *klass); + +G_DEFINE_TYPE_EXTENDED (NMRemoteSettingsSystem, nm_remote_settings_system, NM_TYPE_REMOTE_SETTINGS, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, settings_system_interface_init)) + +#define NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemPrivate)) + +typedef struct { + DBusGProxy *proxy; + DBusGProxy *props_proxy; + + char *hostname; + gboolean can_modify; + + gboolean disposed; +} NMRemoteSettingsSystemPrivate; + +static void +properties_changed_cb (DBusGProxy *proxy, + GHashTable *properties, + gpointer user_data) +{ + NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data); + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self); + GHashTableIter iter; + gpointer key, tmp; + + g_hash_table_iter_init (&iter, properties); + while (g_hash_table_iter_next (&iter, &key, &tmp)) { + GValue *value = tmp; + + if (!strcmp ((const char *) key, "Hostname")) { + g_free (priv->hostname); + priv->hostname = g_value_dup_string (value); + g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME); + } + + if (!strcmp ((const char *) key, "CanModify")) { + priv->can_modify = g_value_get_boolean (value); + g_object_notify (G_OBJECT (self), NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY); + } + } +} + +static void +get_all_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data); + GHashTable *props = NULL; + GError *error = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_warning ("%s: couldn't retrieve system settings properties: (%d) %s.", + __func__, + error ? error->code : -1, + (error && error->message) ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + properties_changed_cb (NULL, props, self); + g_hash_table_destroy (props); +} + +static gboolean +save_hostname (NMSettingsSystemInterface *settings, + const char *hostname, + NMSettingsSystemSaveHostnameFunc callback, + gpointer user_data) +{ + return FALSE; +} + +/****************************************************************/ + +static void +settings_system_interface_init (NMSettingsSystemInterface *klass) +{ + /* interface implementation */ + klass->save_hostname = save_hostname; +} + +/** + * nm_remote_settings_system_new: + * @bus: a valid and connected D-Bus connection + * + * Creates a new object representing the remote system settings service. + * + * Returns: the new remote system settings object on success, or %NULL on failure + **/ +NMRemoteSettingsSystem * +nm_remote_settings_system_new (DBusGConnection *bus) +{ + g_return_val_if_fail (bus != NULL, NULL); + + return (NMRemoteSettingsSystem *) g_object_new (NM_TYPE_REMOTE_SETTINGS_SYSTEM, + NM_REMOTE_SETTINGS_BUS, bus, + NM_REMOTE_SETTINGS_SCOPE, NM_CONNECTION_SCOPE_SYSTEM, + NULL); +} + +static void +nm_remote_settings_system_init (NMRemoteSettingsSystem *self) +{ +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMRemoteSettingsSystemPrivate *priv; + DBusGConnection *bus = NULL; + + object = G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object); + + g_object_get (G_OBJECT (object), NM_REMOTE_SETTINGS_BUS, &bus, NULL); + g_assert (bus); + + /* D-Bus properties proxy */ + priv->props_proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE_SYSTEM_SETTINGS, + NM_DBUS_PATH_SETTINGS, + "org.freedesktop.DBus.Properties"); + g_assert (priv->props_proxy); + + /* System settings proxy */ + priv->proxy = dbus_g_proxy_new_for_name (bus, + NM_DBUS_SERVICE_SYSTEM_SETTINGS, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS_SYSTEM); + g_assert (priv->proxy); + + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->proxy, "PropertiesChanged", + DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "PropertiesChanged", + G_CALLBACK (properties_changed_cb), + object, + NULL); + + /* Get properties */ + dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", + get_all_cb, + object, + NULL, + G_TYPE_STRING, NM_DBUS_IFACE_SETTINGS_SYSTEM, + G_TYPE_INVALID); + + dbus_g_connection_unref (bus); + + return object; +} + +static void +dispose (GObject *object) +{ + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object); + + if (priv->disposed) + return; + + priv->disposed = TRUE; + + g_free (priv->hostname); + + g_object_unref (priv->props_proxy); + g_object_unref (priv->proxy); + + G_OBJECT_CLASS (nm_remote_settings_system_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (object); + + switch (prop_id) { + case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME: + g_value_set_string (value, priv->hostname); + break; + case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY: + g_value_set_boolean (value, priv->can_modify); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_remote_settings_system_class_init (NMRemoteSettingsSystemClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (NMRemoteSettingsSystemPrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* Properties */ + g_object_class_override_property (object_class, + NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME, + NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME); + + g_object_class_override_property (object_class, + NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY, + NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY); +} + diff --git a/libnm-glib/nm-remote-settings-system.h b/libnm-glib/nm-remote-settings-system.h new file mode 100644 index 0000000000..09d76dfee7 --- /dev/null +++ b/libnm-glib/nm-remote-settings-system.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2008 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_REMOTE_SETTINGS_SYSTEM_H +#define NM_REMOTE_SETTINGS_SYSTEM_H + +#include +#include + +#include "nm-remote-settings.h" + +G_BEGIN_DECLS + +#define NM_TYPE_REMOTE_SETTINGS_SYSTEM (nm_remote_settings_system_get_type ()) +#define NM_REMOTE_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystem)) +#define NM_REMOTE_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass)) +#define NM_IS_REMOTE_SETTINGS_SYSTEM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM)) +#define NM_IS_REMOTE_SETTINGS_SYSTEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM)) +#define NM_REMOTE_SETTINGS_SYSTEM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS_SYSTEM, NMRemoteSettingsSystemClass)) + +typedef struct { + NMRemoteSettings parent; +} NMRemoteSettingsSystem; + +typedef struct { + NMRemoteSettingsClass parent; +} NMRemoteSettingsSystemClass; + +GType nm_remote_settings_system_get_type (void); + +NMRemoteSettingsSystem *nm_remote_settings_system_new (DBusGConnection *bus); + +G_END_DECLS + +#endif /* NM_REMOTE_SETTINGS_SYSTEM_H */ diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c new file mode 100644 index 0000000000..6a261ace99 --- /dev/null +++ b/libnm-glib/nm-remote-settings.c @@ -0,0 +1,425 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2008 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ + +#include +#include +#include + +#include "nm-marshal.h" +#include "nm-remote-settings.h" +#include "nm-settings-bindings.h" +#include "nm-settings-interface.h" + +static void settings_interface_init (NMSettingsInterface *class); + +G_DEFINE_TYPE_EXTENDED (NMRemoteSettings, nm_remote_settings, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init)) + +#define NM_REMOTE_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsPrivate)) + +typedef struct { + DBusGConnection *bus; + NMConnectionScope scope; + + DBusGProxy *proxy; + GHashTable *connections; + + DBusGProxy *dbus_proxy; + + guint fetch_id; + + gboolean disposed; +} NMRemoteSettingsPrivate; + +enum { + PROP_0, + PROP_BUS, + PROP_SCOPE, + + LAST_PROP +}; + +static NMSettingsConnectionInterface * +get_connection_by_path (NMSettingsInterface *settings, const char *path) +{ + return g_hash_table_lookup (NM_REMOTE_SETTINGS_GET_PRIVATE (settings)->connections, path); +} + +static void +connection_removed_cb (NMRemoteConnection *remote, gpointer user_data) +{ + g_hash_table_remove (NM_REMOTE_SETTINGS_GET_PRIVATE (user_data)->connections, + nm_connection_get_path (NM_CONNECTION (remote))); +} + +static void +new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + NMRemoteConnection *connection; + + connection = nm_remote_connection_new (priv->bus, priv->scope, path); + if (connection) { + g_signal_connect (connection, "removed", + G_CALLBACK (connection_removed_cb), + self); + + g_hash_table_insert (priv->connections, g_strdup (path), connection); + g_signal_emit_by_name (self, "new-connection", connection); + } +} + +static void +fetch_connections_done (DBusGProxy *proxy, + GPtrArray *connections, + GError *error, + gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + int i; + + if (error) { + g_warning ("%s: error fetching %s connections: (%d) %s.", + __func__, + priv->scope == NM_CONNECTION_SCOPE_USER ? "user" : "system", + error->code, + error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + for (i = 0; connections && (i < connections->len); i++) { + char *path = g_ptr_array_index (connections, i); + + new_connection_cb (proxy, path, user_data); + g_free (path); + } + g_ptr_array_free (connections, TRUE); +} + +static gboolean +fetch_connections (gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + + priv->fetch_id = 0; + + org_freedesktop_NetworkManagerSettings_list_connections_async (priv->proxy, + fetch_connections_done, + self); + return FALSE; +} + +static GSList * +list_connections (NMSettingsInterface *settings) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (settings); + GSList *list = NULL; + GHashTableIter iter; + gpointer value; + + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) + list = g_slist_prepend (list, NM_REMOTE_CONNECTION (value)); + + return list; +} + +typedef struct { + NMSettingsInterface *self; + NMSettingsAddConnectionFunc callback; + gpointer callback_data; +} AddConnectionInfo; + +static void +add_connection_done (DBusGProxy *proxy, + GError *error, + gpointer user_data) +{ + AddConnectionInfo *info = user_data; + + info->callback (info->self, error, info->callback_data); + g_free (info); +} + +static gboolean +add_connection (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection, + NMSettingsAddConnectionFunc callback, + gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (settings); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + AddConnectionInfo *info; + GHashTable *new_settings; + + info = g_malloc0 (sizeof (AddConnectionInfo)); + info->self = settings; + info->callback = callback; + info->callback_data = user_data; + + new_settings = nm_connection_to_hash (NM_CONNECTION (connection)); + org_freedesktop_NetworkManagerSettings_add_connection_async (priv->proxy, + new_settings, + add_connection_done, + info); + g_hash_table_destroy (new_settings); + return TRUE; +} + +static gboolean +remove_connections (gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + GHashTableIter iter; + gpointer value; + + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) + g_signal_emit_by_name (NM_REMOTE_CONNECTION (value), "removed"); + + g_hash_table_remove_all (priv->connections); + return FALSE; +} + +static void +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + const char *sname = NM_DBUS_SERVICE_USER_SETTINGS; + + if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) + sname = NM_DBUS_SERVICE_SYSTEM_SETTINGS; + + if (!strcmp (name, sname)) { + if (priv->fetch_id) + g_source_remove (priv->fetch_id); + + if (new_owner && strlen (new_owner) > 0) + priv->fetch_id = g_idle_add (fetch_connections, self); + else + priv->fetch_id = g_idle_add (remove_connections, self); + } +} + +/****************************************************************/ + +static void +settings_interface_init (NMSettingsInterface *iface) +{ + /* interface implementation */ + iface->list_connections = list_connections; + iface->get_connection_by_path = get_connection_by_path; + iface->add_connection = add_connection; +} + +/** + * nm_remote_settings_new: + * @bus: a valid and connected D-Bus connection + * @scope: the settings service scope (either user or system) + * + * Creates a new object representing the remote settings service. + * + * Returns: the new remote settings object on success, or %NULL on failure + **/ +NMRemoteSettings * +nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope) +{ + g_return_val_if_fail (bus != NULL, NULL); + g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL); + + return (NMRemoteSettings *) g_object_new (NM_TYPE_REMOTE_SETTINGS, + NM_REMOTE_SETTINGS_BUS, bus, + NM_REMOTE_SETTINGS_SCOPE, scope, + NULL); +} + +static void +nm_remote_settings_init (NMRemoteSettings *self) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + + priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + NMRemoteSettingsPrivate *priv; + const char *service = NM_DBUS_SERVICE_USER_SETTINGS; + + object = G_OBJECT_CLASS (nm_remote_settings_parent_class)->constructor (type, n_construct_params, construct_params); + if (!object) + return NULL; + + priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + + /* D-Bus proxy for clearing connections on NameOwnerChanged */ + priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus"); + g_assert (priv->dbus_proxy); + + dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_STRING_STRING, + G_TYPE_NONE, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->dbus_proxy, + "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + object, NULL); + + /* Settings service proxy */ + if (priv->scope == NM_CONNECTION_SCOPE_SYSTEM) + service = NM_DBUS_SERVICE_SYSTEM_SETTINGS; + + priv->proxy = dbus_g_proxy_new_for_name (priv->bus, + service, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS); + g_assert (priv->proxy); + + dbus_g_proxy_add_signal (priv->proxy, "NewConnection", + DBUS_TYPE_G_OBJECT_PATH, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "NewConnection", + G_CALLBACK (new_connection_cb), + object, + NULL); + + priv->fetch_id = g_idle_add (fetch_connections, object); + + return object; +} + +static void +dispose (GObject *object) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + + if (priv->disposed) + return; + + priv->disposed = TRUE; + + if (priv->fetch_id) + g_source_remove (priv->fetch_id); + + if (priv->connections) + g_hash_table_destroy (priv->connections); + + g_object_unref (priv->dbus_proxy); + g_object_unref (priv->proxy); + dbus_g_connection_unref (priv->bus); + + G_OBJECT_CLASS (nm_remote_settings_parent_class)->dispose (object); +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + /* Construct only */ + priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); + break; + case PROP_SCOPE: + priv->scope = (NMConnectionScope) g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + g_value_set_boxed (value, priv->bus); + break; + case PROP_SCOPE: + g_value_set_uint (value, priv->scope); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_remote_settings_class_init (NMRemoteSettingsClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMRemoteSettingsPrivate)); + + /* Virtual methods */ + object_class->constructor = constructor; + object_class->set_property = set_property; + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* Properties */ + g_object_class_install_property + (object_class, PROP_BUS, + g_param_spec_boxed (NM_REMOTE_SETTINGS_BUS, + "DBusGConnection", + "DBusGConnection", + DBUS_TYPE_G_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_SCOPE, + g_param_spec_uint (NM_REMOTE_SETTINGS_SCOPE, + "Scope", + "NMConnection scope", + NM_CONNECTION_SCOPE_UNKNOWN, + NM_CONNECTION_SCOPE_USER, + NM_CONNECTION_SCOPE_USER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); +} + diff --git a/libnm-glib/nm-remote-settings.h b/libnm-glib/nm-remote-settings.h new file mode 100644 index 0000000000..f94aee4f2e --- /dev/null +++ b/libnm-glib/nm-remote-settings.h @@ -0,0 +1,58 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2008 Novell, Inc. + * Copyright (C) 2009 Red Hat, Inc. + */ + +#ifndef NM_REMOTE_SETTINGS_H +#define NM_REMOTE_SETTINGS_H + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define NM_TYPE_REMOTE_SETTINGS (nm_remote_settings_get_type ()) +#define NM_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettings)) +#define NM_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) +#define NM_IS_REMOTE_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS)) +#define NM_IS_REMOTE_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_REMOTE_SETTINGS)) +#define NM_REMOTE_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_REMOTE_SETTINGS, NMRemoteSettingsClass)) + +#define NM_REMOTE_SETTINGS_BUS "bus" +#define NM_REMOTE_SETTINGS_SCOPE "scope" + +typedef struct { + GObject parent; +} NMRemoteSettings; + +typedef struct { + GObjectClass parent; +} NMRemoteSettingsClass; + +GType nm_remote_settings_get_type (void); + +NMRemoteSettings *nm_remote_settings_new (DBusGConnection *bus, NMConnectionScope scope); + +G_END_DECLS + +#endif /* NM_REMOTE_SETTINGS_H */ diff --git a/libnm-glib/nm-settings-connection-interface.c b/libnm-glib/nm-settings-connection-interface.c new file mode 100644 index 0000000000..72859c17f7 --- /dev/null +++ b/libnm-glib/nm-settings-connection-interface.c @@ -0,0 +1,210 @@ +/* -*- 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) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#include "nm-settings-connection-interface.h" +#include "nm-dbus-glib-types.h" + +/** + * nm_settings_connection_interface_update: + * @self: an object implementing #NMSettingsConnectionInterface + * @callback: a function to be called when the update completes + * @user_data: caller-specific data to be passed to @callback + * + * Update the connection with current settings and properties. + * + * Returns: TRUE on success, FALSE on failure + **/ +gboolean +nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update) { + return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->update (connection, + callback, + user_data); + } + return FALSE; +} + +/** + * nm_settings_connection_interface_delete: + * @self: a objecting implementing #NMSettingsConnectionInterface + * @callback: a function to be called when the delete completes + * @user_data: caller-specific data to be passed to @callback + * + * Delete the connection. + * + * Returns: TRUE on success, FALSE on failure + **/ +gboolean +nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete) { + return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->delete (connection, + callback, + user_data); + } + return FALSE; +} + +/** + * nm_settings_connection_interface_get_secrets: + * @self: a object implementing #NMSettingsConnectionInterface + * @setting_name: the #NMSetting object name to get secrets for + * @hints: #NMSetting key names to get secrets for (optional) + * @request_new: hint that new secrets (instead of cached or stored secrets) + * should be returned + * @callback: a function to be called when the update completes + * @user_data: caller-specific data to be passed to @callback + * + * Request the connection's secrets. + * + * Returns: TRUE on success, FALSE on failure + **/ +gboolean +nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection, + const char *setting_name, + const char **hints, + gboolean request_new, + NMSettingsConnectionInterfaceGetSecretsFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets) { + return NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->get_secrets (connection, + setting_name, + hints, + request_new, + callback, + user_data); + } + return FALSE; +} + +void +nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection) +{ + if (NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated) + NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE (connection)->emit_updated (connection); + else { + NMConnection *tmp; + GHashTable *settings; + + tmp = nm_connection_duplicate (NM_CONNECTION (connection)); + nm_connection_clear_secrets (tmp); + settings = nm_connection_to_hash (tmp); + g_object_unref (tmp); + + g_signal_emit_by_name (connection, "updated", settings); + g_hash_table_destroy (settings); + } +} + +static void +nm_settings_connection_interface_init (gpointer g_iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Properties */ + g_object_interface_install_property + (g_iface, + g_param_spec_string (NM_SETTINGS_CONNECTION_INTERFACE_PATH, + "Path", + "D-Bus path", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_interface_install_property + (g_iface, + g_param_spec_uint (NM_SETTINGS_CONNECTION_INTERFACE_SCOPE, + "Scope", + "Connection scope (user, system)", + NM_CONNECTION_SCOPE_UNKNOWN, + NM_CONNECTION_SCOPE_USER, + NM_CONNECTION_SCOPE_USER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + /* Signals */ + g_signal_new ("updated", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSettingsConnectionInterface, updated), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT); + + g_signal_new ("removed", + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSettingsConnectionInterface, removed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + initialized = TRUE; +} + +GType +nm_settings_connection_interface_get_type (void) +{ + static GType itype = 0; + + if (!itype) { + const GTypeInfo iinfo = { + sizeof (NMSettingsConnectionInterface), /* class_size */ + nm_settings_connection_interface_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + itype = g_type_register_static (G_TYPE_INTERFACE, + "NMSettingsConnectionInterface", + &iinfo, 0); + + g_type_interface_add_prerequisite (itype, NM_TYPE_CONNECTION); + } + + return itype; +} + diff --git a/libnm-glib/nm-settings-connection-interface.h b/libnm-glib/nm-settings-connection-interface.h new file mode 100644 index 0000000000..6270797af0 --- /dev/null +++ b/libnm-glib/nm-settings-connection-interface.h @@ -0,0 +1,116 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#ifndef __NM_SETTINGS_CONNECTION_INTERFACE_H__ +#define __NM_SETTINGS_CONNECTION_INTERFACE_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define NM_TYPE_SETTINGS_CONNECTION_INTERFACE (nm_settings_connection_interface_get_type ()) +#define NM_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface)) +#define NM_IS_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE)) +#define NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface)) + +#define NM_SETTINGS_CONNECTION_INTERFACE_PATH "path" +#define NM_SETTINGS_CONNECTION_INTERFACE_SCOPE "scope" + +typedef enum { + NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST = 0x1000, + + NM_SETTINGS_CONNECTION_INTERFACE_PROP_PATH = NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST, + NM_SETTINGS_CONNECTION_INTERFACE_PROP_SCOPE +} NMSettingsConnectionInterfaceProp; + + +typedef struct _NMSettingsConnectionInterface NMSettingsConnectionInterface; + +typedef void (*NMSettingsConnectionInterfaceUpdateFunc) (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data); + +typedef void (*NMSettingsConnectionInterfaceDeleteFunc) (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data); + +typedef void (*NMSettingsConnectionInterfaceGetSecretsFunc) (NMSettingsConnectionInterface *connection, + GHashTable *secrets, + GError *error, + gpointer user_data); + +struct _NMSettingsConnectionInterface { + GTypeInterface g_iface; + + /* Methods */ + gboolean (*update) (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data); + + gboolean (*delete) (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data); + + gboolean (*get_secrets) (NMSettingsConnectionInterface *connection, + const char *setting_name, + const char **hints, + gboolean request_new, + NMSettingsConnectionInterfaceGetSecretsFunc callback, + gpointer user_data); + + void (*emit_updated) (NMSettingsConnectionInterface *connection); + + /* Signals */ + /* 'new_settings' hash should *not* contain secrets */ + void (*updated) (NMSettingsConnectionInterface *connection, + GHashTable *new_settings); + + void (*removed) (NMSettingsConnectionInterface *connection); +}; + +GType nm_settings_connection_interface_get_type (void); + +gboolean nm_settings_connection_interface_update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data); + +gboolean nm_settings_connection_interface_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data); + +gboolean nm_settings_connection_interface_get_secrets (NMSettingsConnectionInterface *connection, + const char *setting_name, + const char **hints, + gboolean request_new, + NMSettingsConnectionInterfaceGetSecretsFunc callback, + gpointer user_data); + +void nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *connection); + +G_END_DECLS + +#endif /* __NM_SETTINGS_CONNECTION_INTERFACE_H__ */ + diff --git a/libnm-glib/nm-settings-interface.c b/libnm-glib/nm-settings-interface.c new file mode 100644 index 0000000000..66c63d7728 --- /dev/null +++ b/libnm-glib/nm-settings-interface.c @@ -0,0 +1,195 @@ +/* -*- 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) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2008 Red Hat, Inc. + */ + +#include "nm-settings-interface.h" + + +/** + * nm_settings_interface_error_quark: + * + * Setting error quark. + * + * Returns: the setting error quark + **/ +GQuark +nm_settings_interface_error_quark (void) +{ + static GQuark quark; + + if (G_UNLIKELY (!quark)) + quark = g_quark_from_static_string ("nm-settings-interface-error-quark"); + return quark; +} + +/* This should really be standard. */ +#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } + +GType +nm_settings_interface_error_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + /* The connection was invalid. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, "InvalidConnection"), + /* The connection is read-only; modifications are not allowed. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, "ReadOnlyConnection"), + /* A bug in the settings service caused the error. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "InternalError"), + /* Retrieval or request of secrets failed. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE, "SecretsUnavailable"), + /* The request for secrets was canceled. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED, "SecretsRequestCanceled"), + /* The request could not be completed because permission was denied. */ + ENUM_ENTRY (NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED, "PermissionDenied"), + { 0, 0, 0 }, + }; + etype = g_enum_register_static ("NMSettingsInterfaceError", values); + } + return etype; +} + + +/** + * nm_settings_list_connections: + * @settings: a object implementing %NMSettingsInterface + * + * Returns: all connections known to the object. + **/ +GSList * +nm_settings_interface_list_connections (NMSettingsInterface *settings) +{ + g_return_val_if_fail (settings != NULL, NULL); + g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL); + + if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections) + return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->list_connections (settings); + return NULL; +} + +/** + * nm_settings_get_connection_by_path: + * @settings: a object implementing %NMSettingsInterface + * @path: the D-Bus object path of the remote connection + * + * Returns the object implementing %NMSettingsConnectionInterface at @path. + * + * Returns: the remote connection object on success, or NULL if the object was + * not known + **/ +NMSettingsConnectionInterface * +nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings, + const char *path) +{ + g_return_val_if_fail (settings != NULL, NULL); + g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), NULL); + g_return_val_if_fail (path != NULL, NULL); + + if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path) + return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->get_connection_by_path (settings, path); + return NULL; +} + +/** + * nm_settings_interface_add_connection: + * @settings: a object implementing %NMSettingsInterface + * @connection: the settings to add; note that this objects settings will be + * added, not the object itself + * @callback: callback to be called when the add operation completes + * @user_data: caller-specific data passed to @callback + * + * Requests that the settings service add the given settings to a new connection. + * + * Returns: TRUE if the request was successful, FALSE if it failed + **/ +gboolean +nm_settings_interface_add_connection (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection, + NMSettingsAddConnectionFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (settings != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), FALSE); + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection) { + return NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection (settings, + connection, + callback, + user_data); + } + return FALSE; +} + +/*****************************************************************/ + +static void +nm_settings_interface_init (gpointer g_iface) +{ + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Signals */ + g_signal_new (NM_SETTINGS_INTERFACE_NEW_CONNECTION, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSettingsInterface, new_connection), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + initialized = TRUE; +} + +GType +nm_settings_interface_get_type (void) +{ + static GType settings_interface_type = 0; + + if (!settings_interface_type) { + const GTypeInfo settings_interface_info = { + sizeof (NMSettingsInterface), /* class_size */ + nm_settings_interface_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + settings_interface_type = g_type_register_static (G_TYPE_INTERFACE, + "NMSettingsInterface", + &settings_interface_info, 0); + + g_type_interface_add_prerequisite (settings_interface_type, G_TYPE_OBJECT); + } + + return settings_interface_type; +} + diff --git a/libnm-glib/nm-settings-interface.h b/libnm-glib/nm-settings-interface.h new file mode 100644 index 0000000000..a058042f62 --- /dev/null +++ b/libnm-glib/nm-settings-interface.h @@ -0,0 +1,93 @@ +/* -*- 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) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#ifndef NM_SETTINGS_INTERFACE_H +#define NM_SETTINGS_INTERFACE_H + +#include + +#include "NetworkManager.h" +#include "nm-settings-connection-interface.h" + +typedef enum { + NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION = 0, + NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, + NM_SETTINGS_INTERFACE_ERROR_SECRETS_UNAVAILABLE, + NM_SETTINGS_INTERFACE_ERROR_SECRETS_REQUEST_CANCELED, + NM_SETTINGS_INTERFACE_ERROR_PERMISSION_DENIED +} NMSettingsInterfaceError; + +#define NM_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_quark ()) +GQuark nm_settings_interface_error_quark (void); + +#define NM_TYPE_SETTINGS_INTERFACE_ERROR (nm_settings_interface_error_get_type ()) +GType nm_settings_interface_error_get_type (void); + + +#define NM_TYPE_SETTINGS_INTERFACE (nm_settings_interface_get_type ()) +#define NM_SETTINGS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface)) +#define NM_IS_SETTINGS_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_INTERFACE)) +#define NM_SETTINGS_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_INTERFACE, NMSettingsInterface)) + +#define NM_SETTINGS_INTERFACE_NEW_CONNECTION "new-connection" + +typedef struct _NMSettingsInterface NMSettingsInterface; + +typedef void (*NMSettingsAddConnectionFunc) (NMSettingsInterface *settings, + GError *error, + gpointer user_data); + +struct _NMSettingsInterface { + GTypeInterface g_iface; + + /* Methods */ + /* Returns a list of objects implementing NMSettingsConnectionInterface */ + GSList * (*list_connections) (NMSettingsInterface *settings); + + NMSettingsConnectionInterface * (*get_connection_by_path) (NMSettingsInterface *settings, + const char *path); + + gboolean (*add_connection) (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection, + NMSettingsAddConnectionFunc callback, + gpointer user_data); + + /* Signals */ + void (*new_connection) (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection); +}; + +GType nm_settings_interface_get_type (void); + +/* Returns a list of objects implementing NMSettingsConnectionInterface */ +GSList *nm_settings_interface_list_connections (NMSettingsInterface *settings); + +NMSettingsConnectionInterface *nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings, + const char *path); + +gboolean nm_settings_interface_add_connection (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection, + NMSettingsAddConnectionFunc callback, + gpointer user_data); + + +#endif /* NM_SETTINGS_INTERFACE_H */ diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c new file mode 100644 index 0000000000..c8e1d4ce50 --- /dev/null +++ b/libnm-glib/nm-settings-service.c @@ -0,0 +1,287 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2008 Novell, Inc. + * (C) Copyright 2008 - 2009 Red Hat, Inc. + */ + +#include +#include + +#include "nm-settings-service.h" +#include "nm-settings-interface.h" +#include "nm-exported-connection.h" + +static gboolean impl_settings_list_connections (NMSettingsService *self, + GPtrArray **connections, + GError **error); + +static void impl_settings_add_connection (NMSettingsService *self, + GHashTable *settings, + DBusGMethodInvocation *context); + +#include "nm-settings-glue.h" + +static void settings_interface_init (NMSettingsInterface *class); + +G_DEFINE_TYPE_EXTENDED (NMSettingsService, nm_settings_service, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, settings_interface_init)) + +#define NM_SETTINGS_SERVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ + NM_TYPE_SETTINGS_SERVICE, \ + NMSettingsServicePrivate)) + +typedef struct { + DBusGConnection *bus; + NMConnectionScope scope; + gboolean exported; + + gboolean disposed; +} NMSettingsServicePrivate; + +enum { + PROP_0, + PROP_BUS, + PROP_SCOPE, + + LAST_PROP +}; + + +/**************************************************************/ + +void +nm_settings_service_export (NMSettingsService *self) +{ + NMSettingsServicePrivate *priv; + + g_return_if_fail (self != NULL); + g_return_if_fail (NM_IS_SETTINGS_SERVICE (self)); + + priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self); + + g_return_if_fail (priv->bus != NULL); + + /* Don't allow exporting twice */ + g_return_if_fail (priv->exported == FALSE); + + dbus_g_connection_register_g_object (priv->bus, + NM_DBUS_PATH_SETTINGS, + G_OBJECT (self)); + priv->exported = TRUE; +} + +/**************************************************************/ + +static GSList * +list_connections (NMSettingsInterface *settings) +{ + /* Must always be implemented */ + g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections); + return NM_SETTINGS_SERVICE_GET_CLASS (settings)->list_connections (NM_SETTINGS_SERVICE (settings)); +} + +static gboolean +impl_settings_list_connections (NMSettingsService *self, + GPtrArray **connections, + GError **error) +{ + GSList *list = NULL, *iter; + + list = list_connections (NM_SETTINGS_INTERFACE (self)); + *connections = g_ptr_array_sized_new (g_slist_length (list) + 1); + for (iter = list; iter; iter = g_slist_next (iter)) { + g_ptr_array_add (*connections, + g_strdup (nm_connection_get_path (NM_CONNECTION (iter->data)))); + } + g_slist_free (list); + return TRUE; +} + +static NMSettingsConnectionInterface * +get_connection_by_path (NMSettingsInterface *settings, const char *path) +{ + NMExportedConnection *connection; + + /* Must always be implemented */ + g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path); + connection = NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path (NM_SETTINGS_SERVICE (settings), path); + return (NMSettingsConnectionInterface *) connection; +} + +NMExportedConnection * +nm_settings_service_get_connection_by_path (NMSettingsService *self, + const char *path) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (NM_IS_SETTINGS_SERVICE (self), NULL); + + return (NMExportedConnection *) get_connection_by_path (NM_SETTINGS_INTERFACE (self), path); +} + +static void +impl_settings_add_connection (NMSettingsService *self, + GHashTable *settings, + DBusGMethodInvocation *context) +{ + NMConnection *tmp; + GError *error = NULL; + + /* Check if the settings are valid first */ + tmp = nm_connection_new_from_hash (settings, &error); + if (!tmp) { + g_assert (error); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + g_object_unref (tmp); + + if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) + NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (self, settings, context); + else { + error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, + "%s: %s:%d add_connection() not implemented", + __func__, __FILE__, __LINE__); + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + +/**************************************************************/ + +static void +settings_interface_init (NMSettingsInterface *iface) +{ + /* interface implementation */ + iface->list_connections = list_connections; + iface->get_connection_by_path = get_connection_by_path; +} + +static GObject * +constructor (GType type, + guint n_construct_params, + GObjectConstructParam *construct_params) +{ + GObject *object; + + object = G_OBJECT_CLASS (nm_settings_service_parent_class)->constructor (type, n_construct_params, construct_params); + if (object) + g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->scope != NM_CONNECTION_SCOPE_UNKNOWN); + return object; +} + +static void +nm_settings_service_init (NMSettingsService *self) +{ +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + /* Construct only */ + priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); + break; + case PROP_SCOPE: + /* Construct only */ + priv->scope = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object); + + switch (prop_id) { + case PROP_BUS: + g_value_set_boxed (value, priv->bus); + break; + case PROP_SCOPE: + g_value_set_uint (value, priv->scope); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +dispose (GObject *object) +{ + NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object); + + if (!priv->disposed) { + priv->disposed = TRUE; + dbus_g_connection_unref (priv->bus); + } + + G_OBJECT_CLASS (nm_settings_service_parent_class)->dispose (object); +} + +static void +nm_settings_service_class_init (NMSettingsServiceClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMSettingsServicePrivate)); + + /* Virtual methods */ + object_class->dispose = dispose; + object_class->constructor = constructor; + object_class->get_property = get_property; + object_class->set_property = set_property; + + /** + * NMSettingsService:bus: + * + * The %DBusGConnection which this object is exported on + **/ + g_object_class_install_property (object_class, PROP_BUS, + g_param_spec_boxed (NM_SETTINGS_SERVICE_BUS, + "Bus", + "Bus", + DBUS_TYPE_G_CONNECTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** + * NMSettingsService:scope: + * + * The capabilities of the device. + **/ + g_object_class_install_property (object_class, PROP_SCOPE, + g_param_spec_uint (NM_SETTINGS_SERVICE_SCOPE, + "Scope", + "Scope", + NM_CONNECTION_SCOPE_USER, + NM_CONNECTION_SCOPE_SYSTEM, + NM_CONNECTION_SCOPE_USER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), + &dbus_glib_nm_settings_object_info); +} diff --git a/libnm-glib/nm-settings-service.h b/libnm-glib/nm-settings-service.h new file mode 100644 index 0000000000..2a6bb86aa2 --- /dev/null +++ b/libnm-glib/nm-settings-service.h @@ -0,0 +1,71 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager system settings service + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * (C) Copyright 2009 Red Hat, Inc. + */ + +#ifndef NM_SETTINGS_SERVICE_H +#define NM_SETTINGS_SERVICE_H + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define NM_TYPE_SETTINGS_SERVICE (nm_settings_service_get_type ()) +#define NM_SETTINGS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsService)) +#define NM_SETTINGS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass)) +#define NM_IS_SETTINGS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE)) +#define NM_IS_SETTINGS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTINGS_SERVICE)) +#define NM_SETTINGS_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS_SERVICE, NMSettingsServiceClass)) + +#define NM_SETTINGS_SERVICE_BUS "bus" +#define NM_SETTINGS_SERVICE_SCOPE "scope" + +typedef struct { + GObject parent; +} NMSettingsService; + +typedef struct { + GObjectClass parent; + + /* Returned list must contain all NMExportedConnection objects exported + * by the settings service. The list (but not the NMExportedConnection + * objects) will be freed by caller. + */ + GSList * (*list_connections) (NMSettingsService *self); + + NMExportedConnection * (*get_connection_by_path) (NMSettingsService *self, + const char *path); + + void (*add_connection) (NMSettingsService *self, + GHashTable *settings, + DBusGMethodInvocation *context); +} NMSettingsServiceClass; + +GType nm_settings_service_get_type (void); + +NMExportedConnection *nm_settings_service_get_connection_by_path (NMSettingsService *self, + const char *path); + +void nm_settings_service_export (NMSettingsService *self); + +G_END_DECLS + +#endif /* NM_SETTINGS_SERVICE_H */ diff --git a/libnm-glib/nm-settings-system-interface.c b/libnm-glib/nm-settings-system-interface.c new file mode 100644 index 0000000000..c563eb17a7 --- /dev/null +++ b/libnm-glib/nm-settings-system-interface.c @@ -0,0 +1,114 @@ +/* -*- 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) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2008 Red Hat, Inc. + */ + +#include "nm-settings-interface.h" +#include "nm-settings-system-interface.h" + + +/** + * nm_settings_system_interface_save_hostname: + * @settings: a object implementing %NMSettingsSystemInterface + * @hostname: the new persistent hostname to set, or NULL to clear any existing + * persistent hostname + * @callback: callback to be called when the hostname operation completes + * @user_data: caller-specific data passed to @callback + * + * Requests that the machine's persistent hostname be set to the specified value + * or cleared. + * + * Returns: TRUE if the request was successful, FALSE if it failed + **/ +gboolean +nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings, + const char *hostname, + NMSettingsSystemSaveHostnameFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (settings != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE); + g_return_val_if_fail (hostname != NULL, FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname) { + return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->save_hostname (settings, + hostname, + callback, + user_data); + } + return FALSE; +} + +static void +nm_settings_system_interface_init (gpointer g_iface) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Properties */ + g_object_interface_install_property + (g_iface, + g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME, + "Hostname", + "Persistent hostname", + NULL, + G_PARAM_READABLE)); + + g_object_interface_install_property + (g_iface, + g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY, + "CanModify", + "Can modify anything (hostname, connections, etc)", + NULL, + G_PARAM_READABLE)); + + initialized = TRUE; +} + +GType +nm_settings_system_interface_get_type (void) +{ + static GType itype = 0; + + if (!itype) { + const GTypeInfo iinfo = { + sizeof (NMSettingsSystemInterface), /* class_size */ + nm_settings_system_interface_init, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL + }; + + itype = g_type_register_static (G_TYPE_INTERFACE, + "NMSettingsSystemInterface", + &iinfo, 0); + + g_type_interface_add_prerequisite (itype, NM_TYPE_SETTINGS_INTERFACE); + } + + return itype; +} + diff --git a/libnm-glib/nm-settings-system-interface.h b/libnm-glib/nm-settings-system-interface.h new file mode 100644 index 0000000000..6f535aaa6a --- /dev/null +++ b/libnm-glib/nm-settings-system-interface.h @@ -0,0 +1,69 @@ +/* -*- 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) 2007 - 2008 Novell, Inc. + * Copyright (C) 2007 - 2009 Red Hat, Inc. + */ + +#ifndef NM_SETTINGS_SYSTEM_INTERFACE_H +#define NM_SETTINGS_SYSTEM_INTERFACE_H + +#include + +#include "NetworkManager.h" + +#define NM_TYPE_SETTINGS_SYSTEM_INTERFACE (nm_settings_system_interface_get_type ()) +#define NM_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface)) +#define NM_IS_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE)) +#define NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface)) + +#define NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME "hostname" +#define NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY "can-modify" + +typedef enum { + NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST = 0x1000, + + NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME = NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST, + NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY +} NMSettingsSystemInterfaceProp; + + +typedef struct _NMSettingsSystemInterface NMSettingsSystemInterface; + + +typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *settings, + GError *error, + gpointer user_data); + +struct _NMSettingsSystemInterface { + GTypeInterface g_iface; + + /* Methods */ + gboolean (*save_hostname) (NMSettingsSystemInterface *settings, + const char *hostname, + NMSettingsSystemSaveHostnameFunc callback, + gpointer user_data); +}; + +GType nm_settings_system_interface_get_type (void); + +gboolean nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings, + const char *hostname, + NMSettingsSystemSaveHostnameFunc callback, + gpointer user_data); + +#endif /* NM_SETTINGS_SYSTEM_INTERFACE_H */ diff --git a/libnm-glib/nm-settings.c b/libnm-glib/nm-settings.c deleted file mode 100644 index cbe0f8875e..0000000000 --- a/libnm-glib/nm-settings.c +++ /dev/null @@ -1,607 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#include -#include -#include -#include "nm-settings.h" -#include "nm-dbus-glib-types.h" - - -#define NM_TYPE_SETTINGS_ERROR (nm_settings_error_get_type ()) - -/** - * nm_settings_error_quark: - * - * Setting error quark. - * - * Returns: the setting error quark - **/ -GQuark -nm_settings_error_quark (void) -{ - static GQuark quark; - - if (G_UNLIKELY (!quark)) - quark = g_quark_from_static_string ("nm-settings-error-quark"); - return quark; -} - -/* This should really be standard. */ -#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC } - -static GType -nm_settings_error_get_type (void) -{ - static GType etype = 0; - - if (etype == 0) { - static const GEnumValue values[] = { - /* The connection was invalid. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_INVALID_CONNECTION, "InvalidConnection"), - /* The connection is read-only; modifications are not allowed. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, "ReadOnlyConnection"), - /* A bug in the settings service caused the error. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_INTERNAL_ERROR, "InternalError"), - /* Retrieval or request of secrets failed. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, "SecretsUnavailable"), - /* The request for secrets was canceled. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED, "SecretsRequestCanceled"), - /* The request could not be completed because permission was denied. */ - ENUM_ENTRY (NM_SETTINGS_ERROR_PERMISSION_DENIED, "PermissionDenied"), - { 0, 0, 0 }, - }; - etype = g_enum_register_static ("NMSettingsError", values); - } - return etype; -} - - -/* - * NMSettings implementation - */ - -static gboolean impl_settings_list_connections (NMSettings *settings, GPtrArray **connections, GError **error); - -#include "nm-settings-glue.h" - -#define SETTINGS_CLASS(o) (NM_SETTINGS_CLASS (G_OBJECT_GET_CLASS (o))) - -G_DEFINE_TYPE (NMSettings, nm_settings, G_TYPE_OBJECT) - -enum { - S_NEW_CONNECTION, - - S_LAST_SIGNAL -}; - -static guint settings_signals[S_LAST_SIGNAL] = { 0 }; - -static gboolean -impl_settings_list_connections (NMSettings *settings, GPtrArray **connections, GError **error) -{ - GSList *list, *iter; - - g_return_val_if_fail (NM_IS_SETTINGS (settings), FALSE); - - list = nm_settings_list_connections (settings); - - *connections = g_ptr_array_new (); - for (iter = list; iter; iter = iter->next) { - NMConnection *connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (iter->data)); - - g_ptr_array_add (*connections, g_strdup (nm_connection_get_path (connection))); - } - - g_slist_free (list); - - return TRUE; -} - -static void -nm_settings_init (NMSettings *settings) -{ -} - -static void -nm_settings_finalize (GObject *object) -{ - G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object); -} - -static void -nm_settings_class_init (NMSettingsClass *settings_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (settings_class); - - /* virtual methods */ - object_class->finalize = nm_settings_finalize; - - settings_class->list_connections = NULL; - - /* signals */ - - /** - * NMSettings::new-connection: - * @setting: the setting that received the signal - * @connection: the new #NMExportedConnection - * - * Notifies that a new exported connection is added. - **/ - settings_signals[S_NEW_CONNECTION] = - g_signal_new ("new-connection", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSettingsClass, new_connection), - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_OBJECT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (settings_class), - &dbus_glib_nm_settings_object_info); - - dbus_g_error_domain_register (NM_SETTINGS_ERROR, NULL, NM_TYPE_SETTINGS_ERROR); -} - -/** - * nm_settings_list_connections: - * @settings: - * - * Lists all the available connections. - * - * Returns: the #GSList containing #NMExportedConnections - **/ -GSList * -nm_settings_list_connections (NMSettings *settings) -{ - GSList *list = NULL; - - g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); - - if (SETTINGS_CLASS (settings)->list_connections) - list = SETTINGS_CLASS (settings)->list_connections (settings); - else - g_warning ("Missing implementation for Settings::list_connections."); - - return list; -} - -void -nm_settings_signal_new_connection (NMSettings *settings, NMExportedConnection *connection) -{ - g_return_if_fail (NM_IS_SETTINGS (settings)); - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); - - g_signal_emit (settings, settings_signals[S_NEW_CONNECTION], 0, connection); -} - -/* - * NMExportedConnection implementation - */ - -static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection, - GHashTable **settings, - GError **error); - -static gboolean impl_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings, - DBusGMethodInvocation *context); - -static gboolean impl_exported_connection_delete (NMExportedConnection *connection, - DBusGMethodInvocation *context); - -static void impl_exported_connection_get_secrets (NMExportedConnection *connection, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - DBusGMethodInvocation *context); - -#include "nm-exported-connection-glue.h" - -#define EXPORTED_CONNECTION_CLASS(o) (NM_EXPORTED_CONNECTION_CLASS (G_OBJECT_GET_CLASS (o))) - -G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, G_TYPE_OBJECT) - -enum { - EC_UPDATED, - EC_REMOVED, - - EC_LAST_SIGNAL -}; - -static guint connection_signals[EC_LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_CONNECTION, - - LAST_PROP -}; - -typedef struct { - NMConnection *wrapped; -} NMExportedConnectionPrivate; - -#define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ - NM_TYPE_EXPORTED_CONNECTION, \ - NMExportedConnectionPrivate)) - -NMExportedConnection * -nm_exported_connection_new (NMConnection *wrapped) -{ - g_return_val_if_fail (NM_IS_CONNECTION (wrapped), NULL); - - return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION, - NM_EXPORTED_CONNECTION_CONNECTION, wrapped, - NULL); -} - -static GHashTable * -real_get_settings (NMExportedConnection *exported) -{ - NMExportedConnectionPrivate *priv; - NMConnection *no_secrets; - GHashTable *hash; - - g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (exported), NULL); - - priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (exported); - - /* Secrets should *never* be returned by the GetSettings method, they - * get returned by the GetSecrets method which can be better - * protected against leakage of secrets to unprivileged callers. - */ - no_secrets = nm_connection_duplicate (priv->wrapped); - nm_connection_clear_secrets (no_secrets); - hash = nm_connection_to_hash (no_secrets); - g_object_unref (G_OBJECT (no_secrets)); - return hash; -} - -static gboolean -impl_exported_connection_get_settings (NMExportedConnection *connection, - GHashTable **settings, - GError **error) -{ - NMExportedConnectionPrivate *priv; - - g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE); - - priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (connection); - - if (!EXPORTED_CONNECTION_CLASS (connection)->get_settings) - *settings = real_get_settings (connection); - else - *settings = EXPORTED_CONNECTION_CLASS (connection)->get_settings (connection); - - return TRUE; -} - -static gboolean -impl_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings, - DBusGMethodInvocation *context) -{ - GError *err = NULL; - NMConnection *wrapped; - gboolean success = FALSE; - - /* Read-only connections obviously cannot be changed */ - wrapped = nm_exported_connection_get_connection (connection); - if (wrapped) { - NMSettingConnection *s_con; - - s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION); - if (s_con && nm_setting_connection_get_read_only (s_con)) { - g_set_error (&err, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, - "%s.%d - Read-only connections may not be modified.", - __FILE__, __LINE__); - } - } - - if (!err) { - /* A hack to share the DBusGMethodInvocation with the possible overriders of connection::update */ - g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context); - success = nm_exported_connection_update (connection, new_settings, &err); - g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL); - } - - if (success) { - dbus_g_method_return (context); - } else { - dbus_g_method_return_error (context, err); - g_error_free (err); - } - - return success; -} - -static gboolean -impl_exported_connection_delete (NMExportedConnection *connection, - DBusGMethodInvocation *context) -{ - GError *err = NULL; - NMConnection *wrapped; - gboolean success = FALSE; - - /* Read-only connections obviously cannot be changed */ - wrapped = nm_exported_connection_get_connection (connection); - if (wrapped) { - NMSettingConnection *s_con; - - s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION); - if (s_con && nm_setting_connection_get_read_only (s_con)) { - g_set_error (&err, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, - "%s.%d - Read-only connections may not be deleted.", - __FILE__, __LINE__); - } - } - - if (!err) { - /* A hack to share the DBusGMethodInvocation with the possible overriders of connection::delete */ - g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, context); - success = nm_exported_connection_delete (connection, &err); - g_object_set_data (G_OBJECT (connection), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION, NULL); - } - - if (success) { - dbus_g_method_return (context); - } else { - dbus_g_method_return_error (context, err); - g_error_free (err); - } - - return success; -} - -static void -impl_exported_connection_get_secrets (NMExportedConnection *connection, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - DBusGMethodInvocation *context) -{ - GError *error = NULL; - - if (!NM_IS_EXPORTED_CONNECTION (connection)) { - g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "%s.%d - Invalid connection in ConnectionSettings::GetSecrets.", - __FILE__, __LINE__); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - if (!EXPORTED_CONNECTION_CLASS (connection)->service_get_secrets) { - g_set_error (&error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, - "%s.%d - Missing implementation for ConnectionSettings::GetSecrets.", - __FILE__, __LINE__); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - EXPORTED_CONNECTION_CLASS (connection)->service_get_secrets (connection, setting_name, hints, request_new, context); -} - -static void -nm_exported_connection_init (NMExportedConnection *connection) -{ -} - -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - GObject *connection; - NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_CONNECTION: - if (priv->wrapped) { - g_object_unref (priv->wrapped); - priv->wrapped = NULL; - } - - connection = g_value_dup_object (value); - if (connection) - priv->wrapped = NM_CONNECTION (connection); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (object); - - switch (prop_id) { - case PROP_CONNECTION: - g_value_set_object (value, nm_exported_connection_get_connection (exported)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_exported_connection_dispose (GObject *object) -{ - NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - - if (priv->wrapped) { - g_object_unref (priv->wrapped); - priv->wrapped = NULL; - } - - G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object); -} - -static void -nm_exported_connection_class_init (NMExportedConnectionClass *exported_connection_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (exported_connection_class); - - g_type_class_add_private (object_class, sizeof (NMExportedConnectionPrivate)); - - /* virtual methods */ - object_class->set_property = set_property; - object_class->get_property = get_property; - object_class->dispose = nm_exported_connection_dispose; - - exported_connection_class->get_settings = real_get_settings; - - /* Properties */ - g_object_class_install_property - (object_class, PROP_CONNECTION, - g_param_spec_object (NM_EXPORTED_CONNECTION_CONNECTION, - "Connection", - "Wrapped connection", - NM_TYPE_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - /* signals */ - connection_signals[EC_UPDATED] = - g_signal_new ("updated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMExportedConnectionClass, updated), - NULL, NULL, - g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, 1, - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT); - - connection_signals[EC_REMOVED] = - g_signal_new ("removed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMExportedConnectionClass, removed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (exported_connection_class), - &dbus_glib_nm_exported_connection_object_info); -} - -NMConnection * -nm_exported_connection_get_connection (NMExportedConnection *connection) -{ - g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), NULL); - - return NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped; -} - -void -nm_exported_connection_register_object (NMExportedConnection *connection, - NMConnectionScope scope, - DBusGConnection *dbus_connection) -{ - NMExportedConnectionPrivate *priv; - static guint32 ec_counter = 0; - char *path; - - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); - g_return_if_fail (dbus_connection != NULL); - - priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (connection); - /* Don't allow the connection to be exported twice */ - g_return_if_fail (nm_connection_get_path (priv->wrapped) == NULL); - - path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); - nm_connection_set_path (priv->wrapped, path); - nm_connection_set_scope (priv->wrapped, scope); - - dbus_g_connection_register_g_object (dbus_connection, - path, - G_OBJECT (connection)); - g_free (path); -} - -gboolean -nm_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings, - GError **err) -{ - gboolean success = TRUE; - GError *error = NULL; - - g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE); - g_return_val_if_fail (new_settings != NULL, FALSE); - - if (EXPORTED_CONNECTION_CLASS (connection)->update) - success = EXPORTED_CONNECTION_CLASS (connection)->update (connection, new_settings, err); - - if (success) { - if (!nm_connection_replace_settings (NM_EXPORTED_CONNECTION_GET_PRIVATE (connection)->wrapped, new_settings, &error)) { - g_warning ("%s: '%s' / '%s' invalid: %d", - __func__, - error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", - (error && error->message) ? error->message : "(none)", - error ? error->code : -1); - g_clear_error (&error); - success = FALSE; - } else - nm_exported_connection_signal_updated (connection, new_settings); - } - - return success; -} - -gboolean -nm_exported_connection_delete (NMExportedConnection *connection, GError **err) -{ - gboolean success = TRUE; - - g_return_val_if_fail (NM_IS_EXPORTED_CONNECTION (connection), FALSE); - - if (EXPORTED_CONNECTION_CLASS (connection)->do_delete) - success = EXPORTED_CONNECTION_CLASS (connection)->do_delete (connection, err); - - if (success) - nm_exported_connection_signal_removed (connection); - - return success; -} - -void -nm_exported_connection_signal_updated (NMExportedConnection *connection, GHashTable *settings) -{ - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); - - g_signal_emit (connection, connection_signals[EC_UPDATED], 0, settings); -} - -void -nm_exported_connection_signal_removed (NMExportedConnection *connection) -{ - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); - - g_signal_emit (connection, connection_signals[EC_REMOVED], 0); -} diff --git a/libnm-glib/nm-settings.h b/libnm-glib/nm-settings.h deleted file mode 100644 index a4c2dec8cb..0000000000 --- a/libnm-glib/nm-settings.h +++ /dev/null @@ -1,145 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * libnm_glib -- Access network status & information from glib applications - * - * 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 (C) 2007 - 2008 Novell, Inc. - * Copyright (C) 2007 - 2008 Red Hat, Inc. - */ - -#ifndef __NM_SETTINGS_H__ -#define __NM_SETTINGS_H__ - -#include -#include - -#include - -G_BEGIN_DECLS - -typedef enum -{ - NM_SETTINGS_ERROR_INVALID_CONNECTION = 0, - NM_SETTINGS_ERROR_READ_ONLY_CONNECTION, - NM_SETTINGS_ERROR_INTERNAL_ERROR, - NM_SETTINGS_ERROR_SECRETS_UNAVAILABLE, - NM_SETTINGS_ERROR_SECRETS_REQUEST_CANCELED, - NM_SETTINGS_ERROR_PERMISSION_DENIED -} NMSettingsError; - -#define NM_SETTINGS_ERROR (nm_settings_error_quark ()) -GQuark nm_settings_error_quark (void); - - -#define NM_TYPE_EXPORTED_CONNECTION (nm_exported_connection_get_type ()) -#define NM_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnection)) -#define NM_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass)) -#define NM_IS_EXPORTED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION)) -#define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION)) -#define NM_EXPORTED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass)) - -#define NM_EXPORTED_CONNECTION_CONNECTION "connection" - -#define NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION "nm-exported-connection-dbus-method-invocation" - -typedef struct { - GObject parent; -} NMExportedConnection; - -typedef struct { - GObjectClass parent_class; - - /* virtual methods */ - GHashTable * (*get_settings) (NMExportedConnection *connection); - - /* service_get_secrets is used in a D-Bus service (like the system settings - * service) to respond to GetSecrets requests from clients. - */ - void (*service_get_secrets) (NMExportedConnection *connection, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - DBusGMethodInvocation *context); - - gboolean (*update) (NMExportedConnection *connection, - GHashTable *new_settings, - GError **err); - - gboolean (*do_delete) (NMExportedConnection *connection, - GError **err); - - /* signals */ - void (*updated) (NMExportedConnection *connection, GHashTable *settings); - void (*removed) (NMExportedConnection *connection); -} NMExportedConnectionClass; - -GType nm_exported_connection_get_type (void); - -NMExportedConnection *nm_exported_connection_new (NMConnection *wrapped); - -void nm_exported_connection_register_object (NMExportedConnection *connection, - NMConnectionScope scope, - DBusGConnection *dbus_connection); - -NMConnection *nm_exported_connection_get_connection (NMExportedConnection *connection); - -gboolean nm_exported_connection_update (NMExportedConnection *connection, - GHashTable *new_settings, - GError **err); - -gboolean nm_exported_connection_delete (NMExportedConnection *connection, - GError **err); - -void nm_exported_connection_signal_updated (NMExportedConnection *connection, - GHashTable *new_settings); - -void nm_exported_connection_signal_removed (NMExportedConnection *connection); - - - -#define NM_TYPE_SETTINGS (nm_settings_get_type ()) -#define NM_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS, NMSettings)) -#define NM_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SETTINGS, NMSettingsClass)) -#define NM_IS_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS)) -#define NM_IS_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SETTINGS)) -#define NM_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SETTINGS, NMSettingsClass)) - -typedef struct { - GObject parent; -} NMSettings; - -typedef struct { - GObjectClass parent_class; - - /* virtual methods */ - /* Returns a list of NMExportedConnections. Caller should free the list. */ - GSList * (*list_connections) (NMSettings *settings); - - /* signals */ - void (* new_connection) (NMSettings *settings, NMExportedConnection *connection); -} NMSettingsClass; - -GType nm_settings_get_type (void); - -GSList *nm_settings_list_connections (NMSettings *settings); - -void nm_settings_signal_new_connection (NMSettings *settings, NMExportedConnection *connection); - - -G_END_DECLS - -#endif diff --git a/marshallers/nm-marshal.list b/marshallers/nm-marshal.list index 6b855f9a07..cb166f5d2c 100644 --- a/marshallers/nm-marshal.list +++ b/marshallers/nm-marshal.list @@ -18,7 +18,6 @@ VOID:STRING,INT VOID:STRING,UINT VOID:OBJECT,OBJECT,ENUM VOID:POINTER,STRING -POINTER:POINTER VOID:STRING,BOXED BOOLEAN:POINTER,STRING,BOOLEAN,UINT,STRING,STRING BOOLEAN:VOID diff --git a/src/nm-manager.c b/src/nm-manager.c index 731589c40a..7e90d85547 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -49,6 +49,8 @@ #include "nm-bluez-common.h" #include "nm-sysconfig-settings.h" #include "nm-secrets-provider-interface.h" +#include "nm-settings-interface.h" +#include "nm-settings-system-interface.h" #define NM_AUTOIP_DBUS_SERVICE "org.freedesktop.nm_avahi_autoipd" #define NM_AUTOIP_DBUS_IFACE "org.freedesktop.nm_avahi_autoipd" @@ -862,18 +864,16 @@ user_query_connections (NMManager *manager) /*******************************************************************/ static void -system_connection_updated_cb (NMExportedConnection *exported, +system_connection_updated_cb (NMSettingsConnectionInterface *connection, gpointer unused, NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); const char *path; - NMConnection *existing; - NMConnection *connection; + NMSettingsConnectionInterface *existing; GError *error = NULL; - connection = nm_exported_connection_get_connection (exported); - path = nm_connection_get_path (connection); + path = nm_connection_get_path (NM_CONNECTION (connection)); existing = g_hash_table_lookup (priv->system_connections, path); if (!existing) @@ -883,14 +883,14 @@ system_connection_updated_cb (NMExportedConnection *exported, return; } - if (!nm_connection_verify (existing, &error)) { + if (!nm_connection_verify (NM_CONNECTION (existing), &error)) { /* Updated connection invalid, remove existing connection */ nm_warning ("%s: Invalid connection: '%s' / '%s' invalid: %d", __func__, g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)), error->message, error->code); g_error_free (error); - remove_connection (manager, existing, priv->system_connections); + remove_connection (manager, NM_CONNECTION (existing), priv->system_connections); return; } @@ -901,37 +901,33 @@ system_connection_updated_cb (NMExportedConnection *exported, } static void -system_connection_removed_cb (NMExportedConnection *exported, +system_connection_removed_cb (NMSettingsConnectionInterface *connection, NMManager *manager) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); const char *path; - NMConnection *connection; - connection = nm_exported_connection_get_connection (exported); - path = nm_connection_get_path (connection); + path = nm_connection_get_path (NM_CONNECTION (connection)); connection = g_hash_table_lookup (priv->system_connections, path); if (connection) - remove_connection (manager, connection, priv->system_connections); + remove_connection (manager, NM_CONNECTION (connection), priv->system_connections); } static void system_internal_new_connection (NMManager *manager, - NMExportedConnection *exported) + NMSettingsConnectionInterface *connection) { NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); - NMConnection *connection; const char *path; - g_return_if_fail (exported != NULL); + g_return_if_fail (connection != NULL); - g_signal_connect (exported, "updated", + g_signal_connect (connection, "updated", G_CALLBACK (system_connection_updated_cb), manager); - g_signal_connect (exported, "removed", + g_signal_connect (connection, "removed", G_CALLBACK (system_connection_removed_cb), manager); - connection = nm_exported_connection_get_connection (exported); path = nm_connection_get_path (NM_CONNECTION (connection)); g_hash_table_insert (priv->system_connections, g_strdup (path), g_object_ref (connection)); @@ -939,10 +935,10 @@ system_internal_new_connection (NMManager *manager, static void system_new_connection_cb (NMSysconfigSettings *settings, - NMExportedConnection *exported, + NMSettingsConnectionInterface *connection, NMManager *manager) { - system_internal_new_connection (manager, exported); + system_internal_new_connection (manager, connection); } static void @@ -951,9 +947,9 @@ system_query_connections (NMManager *manager) NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (manager); GSList *system_connections, *iter; - system_connections = nm_sysconfig_settings_list_connections (priv->sys_settings); + system_connections = nm_settings_interface_list_connections (NM_SETTINGS_INTERFACE (priv->sys_settings)); for (iter = system_connections; iter; iter = g_slist_next (iter)) - system_internal_new_connection (manager, NM_EXPORTED_CONNECTION (iter->data)); + system_internal_new_connection (manager, NM_SETTINGS_CONNECTION_INTERFACE (iter->data)); g_slist_free (system_connections); } @@ -1679,43 +1675,55 @@ user_get_secrets (NMManager *self, return info; } +static void +system_get_secrets_reply_cb (NMSettingsConnectionInterface *connection, + GHashTable *secrets, + GError *error, + gpointer user_data) +{ + GetSecretsInfo *info = user_data; + + nm_secrets_provider_interface_get_secrets_result (info->provider, + info->setting_name, + info->caller, + error ? NULL : secrets, + error); + free_get_secrets_info (info); +} + static gboolean -system_get_secrets_cb (gpointer user_data) +system_get_secrets_idle_cb (gpointer user_data) { GetSecretsInfo *info = user_data; NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (info->manager); - GHashTable *settings; - NMSysconfigConnection *exported; + NMSettingsConnectionInterface *connection; GError *error = NULL; const char *hints[3] = { NULL, NULL, NULL }; - exported = nm_sysconfig_settings_get_connection_by_path (priv->sys_settings, - info->connection_path); - if (!exported) { - g_set_error (&error, 0, 0, "%s", "unknown connection (not exported by " - "system settings)"); + info->idle_id = 0; + + connection = nm_settings_interface_get_connection_by_path (NM_SETTINGS_INTERFACE (priv->sys_settings), + info->connection_path); + if (!connection) { + error = g_error_new_literal (0, 0, "unknown connection (not exported by system settings)"); nm_secrets_provider_interface_get_secrets_result (info->provider, info->setting_name, info->caller, NULL, error); - g_clear_error (&error); + g_error_free (error); + free_get_secrets_info (info); return FALSE; } hints[0] = info->hint1; hints[1] = info->hint2; - settings = nm_sysconfig_connection_get_secrets (exported, - info->setting_name, - hints, - info->request_new, - &error); - nm_secrets_provider_interface_get_secrets_result (info->provider, - info->setting_name, - info->caller, - settings, - NULL); - g_hash_table_destroy (settings); + nm_settings_connection_interface_get_secrets (connection, + info->setting_name, + hints, + info->request_new, + system_get_secrets_reply_cb, + info); return FALSE; } @@ -1744,9 +1752,9 @@ system_get_secrets (NMManager *self, g_object_weak_ref (G_OBJECT (provider), (GWeakNotify) free_get_secrets_info, info); info->idle_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - system_get_secrets_cb, + system_get_secrets_idle_cb, info, - free_get_secrets_info); + NULL); return info; } @@ -2455,7 +2463,7 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error) g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, G_CALLBACK (system_unmanaged_devices_changed_cb), singleton); - g_signal_connect (priv->sys_settings, "notify::" NM_SYSCONFIG_SETTINGS_HOSTNAME, + g_signal_connect (priv->sys_settings, "notify::" NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME, G_CALLBACK (system_hostname_changed_cb), singleton); g_signal_connect (priv->sys_settings, "new-connection", G_CALLBACK (system_new_connection_cb), singleton); diff --git a/src/system-settings/Makefile.am b/src/system-settings/Makefile.am index e5c9313f6e..7be27ddc17 100644 --- a/src/system-settings/Makefile.am +++ b/src/system-settings/Makefile.am @@ -15,7 +15,6 @@ libsystem_settings_la_SOURCES = \ nm-sysconfig-settings.h \ nm-inotify-helper.c \ nm-inotify-helper.h \ - nm-polkit-helpers.c \ nm-polkit-helpers.h \ nm-system-config-error.c \ nm-system-config-error.h \ diff --git a/src/system-settings/nm-default-wired-connection.c b/src/system-settings/nm-default-wired-connection.c index d95c1bac86..0fbd40bd4b 100644 --- a/src/system-settings/nm-default-wired-connection.c +++ b/src/system-settings/nm-default-wired-connection.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -32,8 +31,15 @@ #include "nm-dbus-glib-types.h" #include "nm-marshal.h" #include "nm-default-wired-connection.h" +#include "nm-settings-connection-interface.h" -G_DEFINE_TYPE (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SYSCONFIG_CONNECTION) +static NMSettingsConnectionInterface *parent_settings_connection_iface; + +static void settings_connection_interface_init (NMSettingsConnectionInterface *iface); + +G_DEFINE_TYPE_EXTENDED (NMDefaultWiredConnection, nm_default_wired_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, + settings_connection_interface_init)) #define NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEFAULT_WIRED_CONNECTION, NMDefaultWiredConnectionPrivate)) @@ -86,18 +92,13 @@ nm_default_wired_connection_get_device (NMDefaultWiredConnection *wired) } static GByteArray * -dup_wired_mac (NMExportedConnection *exported) +dup_wired_mac (NMConnection *connection) { - NMConnection *wrapped; NMSettingWired *s_wired; const GByteArray *mac; GByteArray *dup; - wrapped = nm_exported_connection_get_connection (exported); - if (!wrapped) - return NULL; - - s_wired = (NMSettingWired *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_WIRED); + s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); if (!s_wired) return NULL; @@ -111,53 +112,59 @@ dup_wired_mac (NMExportedConnection *exported) } static gboolean -update (NMExportedConnection *exported, - GHashTable *new_settings, - GError **error) +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) { - NMDefaultWiredConnection *connection = NM_DEFAULT_WIRED_CONNECTION (exported); - gboolean success; + NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection); GByteArray *mac; + gboolean failed = FALSE; /* Ensure object stays alive across signal emission */ - g_object_ref (exported); + g_object_ref (self); /* Save a copy of the current MAC address just in case the user * changed it when updating the connection. */ - mac = dup_wired_mac (exported); + mac = dup_wired_mac (NM_CONNECTION (self)); - /* Let NMSysconfigConnection check permissions */ - success = NM_EXPORTED_CONNECTION_CLASS (nm_default_wired_connection_parent_class)->update (exported, new_settings, error); - if (success) { - g_signal_emit_by_name (connection, "try-update", new_settings, error); - success = *error ? FALSE : TRUE; - - if (success) - g_signal_emit (connection, signals[DELETED], 0, mac); - } + g_signal_emit (self, signals[TRY_UPDATE], 0, &failed); + if (!failed) + g_signal_emit (connection, signals[DELETED], 0, mac); g_byte_array_free (mac, TRUE); - g_object_unref (exported); - return success; + g_object_unref (self); + + return parent_settings_connection_iface->update (connection, callback, user_data); } -static gboolean -do_delete (NMExportedConnection *exported, GError **error) +static gboolean +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) { - gboolean success; + NMDefaultWiredConnection *self = NM_DEFAULT_WIRED_CONNECTION (connection); GByteArray *mac; - g_object_ref (exported); - mac = dup_wired_mac (exported); + g_object_ref (self); + mac = dup_wired_mac (NM_CONNECTION (self)); - success = NM_EXPORTED_CONNECTION_CLASS (nm_default_wired_connection_parent_class)->do_delete (exported, error); - if (success) - g_signal_emit (exported, signals[DELETED], 0, mac); + g_signal_emit (self, signals[DELETED], 0, mac); g_byte_array_free (mac, TRUE); - g_object_unref (exported); - return success; + g_object_unref (self); + + return parent_settings_connection_iface->delete (connection, callback, user_data); +} + +/****************************************************************/ + +static void +settings_connection_interface_init (NMSettingsConnectionInterface *iface) +{ + parent_settings_connection_iface = g_type_interface_peek_parent (iface); + iface->update = update; + iface->delete = do_delete; } static void @@ -172,7 +179,6 @@ constructor (GType type, { GObject *object; NMDefaultWiredConnectionPrivate *priv; - NMConnection *wrapped; NMSettingConnection *s_con; NMSettingWired *s_wired; char *id, *uuid; @@ -183,8 +189,6 @@ constructor (GType type, priv = NM_DEFAULT_WIRED_CONNECTION_GET_PRIVATE (object); - wrapped = nm_connection_new (); - s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ()); id = g_strdup_printf (_("Auto %s"), nm_device_get_iface (priv->device)); @@ -201,15 +205,12 @@ constructor (GType type, g_free (id); g_free (uuid); - nm_connection_add_setting (wrapped, NM_SETTING (s_con)); + nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_con)); /* Lock the connection to the specific device */ s_wired = NM_SETTING_WIRED (nm_setting_wired_new ()); g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, priv->mac, NULL); - nm_connection_add_setting (wrapped, NM_SETTING (s_wired)); - - g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); - g_object_unref (wrapped); + nm_connection_add_setting (NM_CONNECTION (object), NM_SETTING (s_wired)); return object; } @@ -288,19 +289,20 @@ try_update_signal_accumulator (GSignalInvocationHint *ihint, const GValue *handler_return, gpointer data) { - gpointer new_ptr = g_value_get_pointer (handler_return); + if (g_value_get_boolean (handler_return)) { + g_value_set_boolean (return_accu, TRUE); + /* Stop */ + return FALSE; + } - g_value_set_pointer (return_accu, new_ptr); - - /* Continue if no error was returned from the handler */ - return new_ptr ? FALSE : TRUE; + /* Continue if handler didn't fail */ + return TRUE; } static void nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - NMExportedConnectionClass *exported_class = NM_EXPORTED_CONNECTION_CLASS (klass); g_type_class_add_private (klass, sizeof (NMDefaultWiredConnectionPrivate)); @@ -310,9 +312,6 @@ nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass) object_class->get_property = get_property; object_class->finalize = finalize; - exported_class->update = update; - exported_class->do_delete = do_delete; - /* Properties */ g_object_class_install_property (object_class, PROP_MAC, @@ -343,16 +342,14 @@ nm_default_wired_connection_class_init (NMDefaultWiredConnectionClass *klass) G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_LAST, 0, try_update_signal_accumulator, NULL, - _nm_marshal_POINTER__POINTER, - G_TYPE_POINTER, 1, - DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT); + _nm_marshal_BOOLEAN__VOID, + G_TYPE_BOOLEAN, 0); /* The 'deleted' signal is used to signal intentional deletions (like * updating or user-requested deletion) rather than using the - * NMExportedConnection superclass' 'removed' signal, since that signal - * doesn't have the semantics we want; it gets emitted as a side-effect - * of various operations and is meant more for D-Bus clients instead - * of in-service uses. + * superclass' 'removed' signal, since that signal doesn't have the + * semantics we want; it gets emitted as a side-effect of various operations + * and is meant more for D-Bus clients instead of in-service uses. */ signals[DELETED] = g_signal_new ("deleted", diff --git a/src/system-settings/nm-default-wired-connection.h b/src/system-settings/nm-default-wired-connection.h index 22a2276d96..de89b67567 100644 --- a/src/system-settings/nm-default-wired-connection.h +++ b/src/system-settings/nm-default-wired-connection.h @@ -22,7 +22,6 @@ #ifndef NM_DEFAULT_WIRED_CONNECTION_H #define NM_DEFAULT_WIRED_CONNECTION_H -#include #include "nm-sysconfig-connection.h" #include "nm-device.h" diff --git a/src/system-settings/nm-polkit-helpers.c b/src/system-settings/nm-polkit-helpers.c deleted file mode 100644 index 638f2a8c14..0000000000 --- a/src/system-settings/nm-polkit-helpers.c +++ /dev/null @@ -1,184 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager system settings service - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * (C) Copyright 2008 Novell, Inc. - * (C) Copyright 2008 Red Hat, Inc. - */ - -#include -#include "nm-polkit-helpers.h" -#include "nm-system-config-error.h" - -static gboolean -pk_io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data) -{ - int fd; - PolKitContext *pk_context = (PolKitContext *) user_data; - - fd = g_io_channel_unix_get_fd (channel); - polkit_context_io_func (pk_context, fd); - - return TRUE; -} - -static int -pk_io_add_watch (PolKitContext *pk_context, int fd) -{ - guint id = 0; - GIOChannel *channel; - - channel = g_io_channel_unix_new (fd); - if (channel == NULL) - goto out; - id = g_io_add_watch (channel, G_IO_IN, pk_io_watch_have_data, pk_context); - if (id == 0) { - g_io_channel_unref (channel); - goto out; - } - g_io_channel_unref (channel); - - out: - return id; -} - -static void -pk_io_remove_watch (PolKitContext *pk_context, int watch_id) -{ - g_source_remove (watch_id); -} - -PolKitContext * -create_polkit_context (GError **error) -{ - static PolKitContext *global_context = NULL; - PolKitError *pk_err = NULL; - - if (G_LIKELY (global_context)) - return polkit_context_ref (global_context); - - global_context = polkit_context_new (); - polkit_context_set_io_watch_functions (global_context, pk_io_add_watch, pk_io_remove_watch); - if (!polkit_context_init (global_context, &pk_err)) { - g_set_error (error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "%s (%d): %s", - pk_err ? polkit_error_get_error_name (pk_err) : "(unknown)", - pk_err ? polkit_error_get_error_code (pk_err) : -1, - pk_err ? polkit_error_get_error_message (pk_err) : "(unknown)"); - if (pk_err) - polkit_error_free (pk_err); - - /* PK 0.6's polkit_context_init() unrefs the global_context on failure */ -#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR >= 7) - polkit_context_unref (global_context); -#endif - global_context = NULL; - } - - return global_context; -} - -gboolean -check_polkit_privileges (DBusGConnection *dbus_connection, - PolKitContext *pol_ctx, - DBusGMethodInvocation *context, - GError **err) -{ - DBusConnection *tmp; - DBusError dbus_error; - char *sender; - gulong sender_uid = G_MAXULONG; - PolKitCaller *pk_caller; - PolKitAction *pk_action; - PolKitResult pk_result; - - /* Always allow uid 0 */ - tmp = dbus_g_connection_get_connection (dbus_connection); - if (!tmp) { - g_set_error (err, - NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "Could not get D-Bus connection."); - return FALSE; - } - - sender = dbus_g_method_get_sender (context); - - dbus_error_init (&dbus_error); - /* FIXME: do this async */ - sender_uid = dbus_bus_get_unix_user (tmp, sender, &dbus_error); - if (dbus_error_is_set (&dbus_error)) { - g_set_error (err, - NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "Could not determine the Unix user ID of the requestor: %s: %s", - dbus_error.name, dbus_error.message); - dbus_error_free (&dbus_error); - return FALSE; - } - - /* PolicyKit < 1.0 is not compatible with root processes spawned outside - * the session manager, and when asking ConsoleKit for the session of the - * process, ConsoleKit won't be able to get XDG_SESSION_COOKIE because it - * doesn't exist in the caller's environment for non-session-managed - * processes. So, for PK < 1.0, ignore PolicyKit for uid 0. - */ - if (0 == sender_uid) - return TRUE; - - /* Non-root users need to auth via PolicyKit */ - dbus_error_init (&dbus_error); - pk_caller = polkit_caller_new_from_dbus_name (dbus_g_connection_get_connection (dbus_connection), - sender, - &dbus_error); - g_free (sender); - - if (dbus_error_is_set (&dbus_error)) { - *err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, - "Error getting information about caller: %s: %s", - dbus_error.name, dbus_error.message); - dbus_error_free (&dbus_error); - - if (pk_caller) - polkit_caller_unref (pk_caller); - - return FALSE; - } - - pk_action = polkit_action_new (); - polkit_action_set_action_id (pk_action, NM_SYSCONFIG_POLICY_ACTION); - -#if (POLKIT_VERSION_MAJOR == 0) && (POLKIT_VERSION_MINOR < 7) - pk_result = polkit_context_can_caller_do_action (pol_ctx, pk_action, pk_caller); -#else - pk_result = polkit_context_is_caller_authorized (pol_ctx, pk_action, pk_caller, TRUE, NULL); -#endif - polkit_caller_unref (pk_caller); - polkit_action_unref (pk_action); - - if (pk_result != POLKIT_RESULT_YES) { - *err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, - "%s %s", - NM_SYSCONFIG_POLICY_ACTION, - polkit_result_to_string_representation (pk_result)); - return FALSE; - } - - return TRUE; -} diff --git a/src/system-settings/nm-polkit-helpers.h b/src/system-settings/nm-polkit-helpers.h index 1382648c13..af7cd7a95c 100644 --- a/src/system-settings/nm-polkit-helpers.h +++ b/src/system-settings/nm-polkit-helpers.h @@ -22,16 +22,8 @@ #ifndef NM_POLKIT_HELPERS_H #define NM_POLKIT_HELPERS_H -#include -#include -#include +#include #define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify" -PolKitContext *create_polkit_context (GError **error); -gboolean check_polkit_privileges (DBusGConnection *dbus_connection, - PolKitContext *pol_ctx, - DBusGMethodInvocation *context, - GError **err); - #endif /* NM_POLKIT_HELPERS_H */ diff --git a/src/system-settings/nm-sysconfig-connection.c b/src/system-settings/nm-sysconfig-connection.c index 3ed0eda8f1..4dbef0daf5 100644 --- a/src/system-settings/nm-sysconfig-connection.c +++ b/src/system-settings/nm-sysconfig-connection.c @@ -16,51 +16,55 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * (C) Copyright 2008 Novell, Inc. + * (C) Copyright 2008 - 2009 Red Hat, Inc. */ #include +#include + #include "nm-sysconfig-connection.h" #include "nm-system-config-error.h" -#include "nm-polkit-helpers.h" #include "nm-dbus-glib-types.h" +#include "nm-settings-connection-interface.h" +#include "nm-settings-interface.h" +#include "nm-polkit-helpers.h" -G_DEFINE_ABSTRACT_TYPE (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION) + +static void settings_connection_interface_init (NMSettingsConnectionInterface *klass); + +G_DEFINE_TYPE_EXTENDED (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_EXPORTED_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, + settings_connection_interface_init)) #define NM_SYSCONFIG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_SYSCONFIG_CONNECTION, \ NMSysconfigConnectionPrivate)) typedef struct { - DBusGConnection *dbus_connection; - PolKitContext *pol_ctx; - - DBusGProxy *proxy; + DBusGConnection *bus; + PolkitAuthority *authority; } NMSysconfigConnectionPrivate; +/**************************************************************/ + static gboolean -update (NMExportedConnection *exported, - GHashTable *new_settings, - GError **err) +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) { - NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported); - DBusGMethodInvocation *context; - - context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION); - g_return_val_if_fail (context != NULL, FALSE); - - return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err); + /* Default handler for subclasses */ + callback (connection, NULL, user_data); + return TRUE; } static gboolean -do_delete (NMExportedConnection *exported, GError **err) +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) { - NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (exported); - DBusGMethodInvocation *context; - - context = g_object_get_data (G_OBJECT (exported), NM_EXPORTED_CONNECTION_DBUS_METHOD_INVOCATION); - g_return_val_if_fail (context != NULL, FALSE); - - return check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, context, err); + /* Default handler for subclasses */ + callback (connection, NULL, user_data); + return TRUE; } static GValue * @@ -118,25 +122,28 @@ destroy_gvalue (gpointer data) g_slice_free (GValue, value); } -GHashTable * -nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - GError **error) +static gboolean +get_secrets (NMSettingsConnectionInterface *connection, + const char *setting_name, + const char **hints, + gboolean request_new, + NMSettingsConnectionInterfaceGetSecretsFunc callback, + gpointer user_data) { - NMConnection *connection; GHashTable *settings = NULL; GHashTable *secrets = NULL; NMSetting *setting; + GError *error = NULL; - connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (self)); - setting = nm_connection_get_setting_by_name (connection, setting_name); + setting = nm_connection_get_setting_by_name (NM_CONNECTION (connection), setting_name); if (!setting) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "%s.%d - Connection didn't have requested setting '%s'.", - __FILE__, __LINE__, setting_name); - return NULL; + error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, + "%s.%d - Connection didn't have requested setting '%s'.", + __FILE__, __LINE__, setting_name); + (*callback) (connection, NULL, error, user_data); + g_error_free (error); + return TRUE; } /* Returned secrets are a{sa{sv}}; this is the outer a{s...} hash that @@ -150,166 +157,349 @@ nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self, nm_setting_enumerate_values (setting, add_secrets, secrets); g_hash_table_insert (settings, g_strdup (setting_name), secrets); - return settings; + callback (connection, settings, NULL, user_data); + g_hash_table_destroy (settings); + return TRUE; } +/**************************************************************/ + typedef struct { NMSysconfigConnection *self; - char *setting_name; DBusGMethodInvocation *context; -} GetUnixUserInfo; + PolkitSubject *subject; + GCancellable *cancellable; -static GetUnixUserInfo * -get_unix_user_info_new (NMSysconfigConnection *self, - const char *setting_name, - DBusGMethodInvocation *context) + /* Update */ + NMConnection *connection; + + /* Secrets */ + char *setting_name; + char **hints; + gboolean request_new; +} PolkitCall; + +static PolkitCall * +polkit_call_new (NMSysconfigConnection *self, + DBusGMethodInvocation *context, + NMConnection *connection, + const char *setting_name, + const char **hints, + gboolean request_new) { - GetUnixUserInfo *info; + PolkitCall *call; + char *sender; g_return_val_if_fail (self != NULL, NULL); - g_return_val_if_fail (setting_name != NULL, NULL); g_return_val_if_fail (context != NULL, NULL); - info = g_malloc0 (sizeof (GetUnixUserInfo)); - info->self = self; - info->setting_name = g_strdup (setting_name); - info->context = context; - return info; + call = g_malloc0 (sizeof (PolkitCall)); + call->self = self; + call->context = context; + call->cancellable = g_cancellable_new (); + call->connection = connection; + call->setting_name = g_strdup (setting_name); + if (hints) + call->hints = g_strdupv ((char **) hints); + call->request_new = request_new; + + sender = dbus_g_method_get_sender (context); + call->subject = polkit_system_bus_name_new (sender); + g_free (sender); + + return call; } static void -get_unix_user_info_free (gpointer user_data) +polkit_call_free (PolkitCall *call) { - GetUnixUserInfo *info = user_data; + if (call->connection) + g_object_unref (call->connection); + g_free (call->setting_name); + if (call->hints) + g_strfreev (call->hints); - g_free (info->setting_name); - g_free (info); + g_object_unref (call->subject); + g_object_unref (call->cancellable); + g_free (call); } static void -get_unix_user_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +con_update_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) { - GetUnixUserInfo *info = user_data; - NMSysconfigConnection *self; - NMSysconfigConnectionPrivate *priv; + PolkitCall *call = user_data; + + if (error) + dbus_g_method_return_error (call->context, error); + else + dbus_g_method_return (call->context); + + polkit_call_free (call); +} + +static void +pk_update_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + PolkitCall *call = user_data; + NMSysconfigConnection *self = call->self; + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + PolkitAuthorizationResult *pk_result; GError *error = NULL; - guint32 requestor_uid = G_MAXUINT32; - GHashTable *secrets; + GHashTable *settings; - g_return_if_fail (info != NULL); - - self = info->self; - priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); - - if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_UINT, &requestor_uid, G_TYPE_INVALID)) - goto error; - - /* Non-root users need PolicyKit authorization */ - if (requestor_uid != 0) { - if (!check_polkit_privileges (priv->dbus_connection, priv->pol_ctx, info->context, &error)) - goto error; - } - - secrets = nm_sysconfig_connection_get_secrets (self, info->setting_name, NULL, FALSE, &error); - if (secrets) { - /* success; return secrets to caller */ - dbus_g_method_return (info->context, secrets); - g_hash_table_destroy (secrets); + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); return; } - if (!error) { - /* Shouldn't happen, but... */ - g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "%s", "Could not get secrets from connection (unknown error ocurred)"); + /* Caller didn't successfully authenticate */ + if (!polkit_authorization_result_get_is_authorized (pk_result)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Insufficient privileges."); + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + goto out; } -error: - dbus_g_method_return_error (info->context, error); - g_clear_error (&error); + /* Update our settings internally so the update() call will save the new + * ones. + */ + settings = nm_connection_to_hash (call->connection); + if (!nm_connection_replace_settings (NM_CONNECTION (self), settings, &error)) { + /* Shouldn't really happen since we've already validated the settings */ + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + goto out; + } + g_hash_table_destroy (settings); + + /* Caller is authenticated, now we can finally try to update */ + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self), + con_update_cb, + call); + +out: + g_object_unref (pk_result); } static void -service_get_secrets (NMExportedConnection *exported, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - DBusGMethodInvocation *context) +dbus_update (NMExportedConnection *exported, + GHashTable *new_settings, + DBusGMethodInvocation *context) { NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported); NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); - GetUnixUserInfo *info; + PolkitCall *call; + NMConnection *tmp; GError *error = NULL; - char *sender = NULL; - sender = dbus_g_method_get_sender (context); - if (!sender) { - g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "%s", "Could not determine D-Bus requestor to authorize GetSecrets request"); - goto out; - } - - if (priv->proxy) - g_object_unref (priv->proxy); - - priv->proxy = dbus_g_proxy_new_for_name (priv->dbus_connection, - DBUS_SERVICE_DBUS, - DBUS_PATH_DBUS, - DBUS_INTERFACE_DBUS); - if (!priv->proxy) { - g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "%s", "Could not connect to D-Bus to authorize GetSecrets request"); - goto out; - } - - info = get_unix_user_info_new (self, setting_name, context); - if (!info) { - g_set_error (&error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "%s", "Not enough memory to authorize GetSecrets request"); - goto out; - } - - dbus_g_proxy_begin_call_with_timeout (priv->proxy, "GetConnectionUnixUser", - get_unix_user_cb, - info, - get_unix_user_info_free, - 5000, - G_TYPE_STRING, sender, - G_TYPE_INVALID); - -out: - if (error) { + /* Check if the settings are valid first */ + tmp = nm_connection_new_from_hash (new_settings, &error); + if (!tmp) { + g_assert (error); dbus_g_method_return_error (context, error); g_error_free (error); + return; } + + call = polkit_call_new (self, context, tmp, NULL, NULL, FALSE); + g_assert (call); + polkit_authority_check_authorization (priv->authority, + call->subject, + NM_SYSCONFIG_POLICY_ACTION, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + call->cancellable, + pk_update_cb, + call); } -/* GObject */ +static void +con_delete_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) +{ + PolkitCall *call = user_data; + + if (error) + dbus_g_method_return_error (call->context, error); + else + dbus_g_method_return (call->context); + + polkit_call_free (call); +} + +static void +pk_delete_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + PolkitCall *call = user_data; + NMSysconfigConnection *self = call->self; + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + PolkitAuthorizationResult *pk_result; + GError *error = NULL; + + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + return; + } + + /* Caller didn't successfully authenticate */ + if (!polkit_authorization_result_get_is_authorized (pk_result)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Insufficient privileges."); + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + goto out; + } + + /* Caller is authenticated, now we can finally try to delete */ + nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (self), + con_delete_cb, + call); + +out: + g_object_unref (pk_result); +} + +static void +dbus_delete (NMExportedConnection *exported, + DBusGMethodInvocation *context) +{ + NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported); + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + PolkitCall *call; + + call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE); + g_assert (call); + polkit_authority_check_authorization (priv->authority, + call->subject, + NM_SYSCONFIG_POLICY_ACTION, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + call->cancellable, + pk_delete_cb, + call); +} + +static void +con_secrets_cb (NMSettingsConnectionInterface *connection, + GHashTable *secrets, + GError *error, + gpointer user_data) +{ + PolkitCall *call = user_data; + + if (error) + dbus_g_method_return_error (call->context, error); + else + dbus_g_method_return (call->context, secrets); + + polkit_call_free (call); +} + +static void +pk_secrets_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + PolkitCall *call = user_data; + NMSysconfigConnection *self = call->self; + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + PolkitAuthorizationResult *pk_result; + GError *error = NULL; + + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + return; + } + + /* Caller didn't successfully authenticate */ + if (!polkit_authorization_result_get_is_authorized (pk_result)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Insufficient privileges."); + dbus_g_method_return_error (call->context, error); + g_error_free (error); + polkit_call_free (call); + goto out; + } + + /* Caller is authenticated, now we can finally try to update */ + nm_settings_connection_interface_get_secrets (NM_SETTINGS_CONNECTION_INTERFACE (self), + call->setting_name, + (const char **) call->hints, + call->request_new, + con_secrets_cb, + call); + +out: + g_object_unref (pk_result); +} + +static void +dbus_get_secrets (NMExportedConnection *exported, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context) +{ + NMSysconfigConnection *self = NM_SYSCONFIG_CONNECTION (exported); + NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); + PolkitCall *call; + + call = polkit_call_new (self, context, NULL, setting_name, hints, request_new); + g_assert (call); + polkit_authority_check_authorization (priv->authority, + call->subject, + NM_SYSCONFIG_POLICY_ACTION, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + call->cancellable, + pk_secrets_cb, + call); +} + +/**************************************************************/ + +static void +settings_connection_interface_init (NMSettingsConnectionInterface *iface) +{ + iface->update = update; + iface->delete = do_delete; + iface->get_secrets = get_secrets; +} static void nm_sysconfig_connection_init (NMSysconfigConnection *self) { NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (self); - GError *err = NULL; - priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err); - if (err) { - g_warning ("%s: error getting D-Bus connection: %s", - __func__, - (err && err->message) ? err->message : "(unknown)"); - g_error_free (err); - } - - priv->pol_ctx = create_polkit_context (&err); - if (!priv->pol_ctx) { - g_warning ("%s: error creating PolicyKit context: %s", - __func__, - (err && err->message) ? err->message : "(unknown)"); - } + priv->authority = polkit_authority_get (); + if (!priv->authority) + g_warning ("%s: error creating PolicyKit authority", __func__); } static void @@ -317,30 +507,23 @@ dispose (GObject *object) { NMSysconfigConnectionPrivate *priv = NM_SYSCONFIG_CONNECTION_GET_PRIVATE (object); - if (priv->proxy) - g_object_unref (priv->proxy); - - if (priv->pol_ctx) - polkit_context_unref (priv->pol_ctx); - - if (priv->dbus_connection) - dbus_g_connection_unref (priv->dbus_connection); + if (priv->authority) + g_object_unref (priv->authority); G_OBJECT_CLASS (nm_sysconfig_connection_parent_class)->dispose (object); } static void -nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *sysconfig_connection_class) +nm_sysconfig_connection_class_init (NMSysconfigConnectionClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (sysconfig_connection_class); - NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (sysconfig_connection_class); + GObjectClass *object_class = G_OBJECT_CLASS (class); + NMExportedConnectionClass *ec_class = NM_EXPORTED_CONNECTION_CLASS (class); - g_type_class_add_private (sysconfig_connection_class, sizeof (NMSysconfigConnectionPrivate)); + g_type_class_add_private (class, sizeof (NMSysconfigConnectionPrivate)); /* Virtual methods */ object_class->dispose = dispose; - - connection_class->update = update; - connection_class->do_delete = do_delete; - connection_class->service_get_secrets = service_get_secrets; + ec_class->update = dbus_update; + ec_class->delete = dbus_delete; + ec_class->get_secrets = dbus_get_secrets; } diff --git a/src/system-settings/nm-sysconfig-connection.h b/src/system-settings/nm-sysconfig-connection.h index 694cc58e14..3e67f52473 100644 --- a/src/system-settings/nm-sysconfig-connection.h +++ b/src/system-settings/nm-sysconfig-connection.h @@ -21,7 +21,8 @@ #ifndef NM_SYSCONFIG_CONNECTION_H #define NM_SYSCONFIG_CONNECTION_H -#include +#include +#include G_BEGIN_DECLS @@ -42,13 +43,6 @@ typedef struct { GType nm_sysconfig_connection_get_type (void); -/* Only for internal NM usage */ -GHashTable *nm_sysconfig_connection_get_secrets (NMSysconfigConnection *self, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - GError **error); - G_END_DECLS #endif /* NM_SYSCONFIG_CONNECTION_H */ diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 99f71c166b..64259d83c1 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -19,7 +19,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2007 - 2008 Red Hat, Inc. + * (C) Copyright 2007 - 2009 Red Hat, Inc. * (C) Copyright 2008 Novell, Inc. */ @@ -32,9 +32,12 @@ #include #include #include +#include #include #include #include +#include +#include #include "../nm-device-ethernet.h" #include "nm-dbus-glib-types.h" @@ -60,20 +63,30 @@ EXPORT(nm_inotify_helper_remove_watch) EXPORT(nm_sysconfig_connection_get_type) /* END LINKER CRACKROCK */ +static void claim_connection (NMSysconfigSettings *self, + NMSettingsConnectionInterface *connection, + gboolean do_export); -static gboolean -impl_settings_add_connection (NMSysconfigSettings *self, GHashTable *hash, DBusGMethodInvocation *context); +static gboolean impl_settings_list_connections (NMSysconfigSettings *self, + GPtrArray **connections, + GError **error); -static gboolean -impl_settings_save_hostname (NMSysconfigSettings *self, const char *hostname, DBusGMethodInvocation *context); +static void impl_settings_add_connection (NMSysconfigSettings *self, + GHashTable *settings, + DBusGMethodInvocation *context); +static void impl_settings_save_hostname (NMSysconfigSettings *self, + const char *hostname, + DBusGMethodInvocation *context); + +#include "nm-settings-glue.h" #include "nm-settings-system-glue.h" -static void unmanaged_devices_changed (NMSystemConfigInterface *config, gpointer user_data); +static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); typedef struct { NMDBusManager *dbus_mgr; - PolKitContext *pol_ctx; + PolkitAuthority *authority; char *config_file; GSList *plugins; @@ -83,7 +96,15 @@ typedef struct { char *orig_hostname; } NMSysconfigSettingsPrivate; -G_DEFINE_TYPE (NMSysconfigSettings, nm_sysconfig_settings, NM_TYPE_SETTINGS); +static void settings_interface_init (NMSettingsInterface *klass); + +static void settings_system_interface_init (NMSettingsSystemInterface *klass); + +G_DEFINE_TYPE_WITH_CODE (NMSysconfigSettings, nm_sysconfig_settings, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, + settings_interface_init) + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, + settings_system_interface_init)) #define NM_SYSCONFIG_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsPrivate)) @@ -125,7 +146,7 @@ load_connections (NMSysconfigSettings *self) // priority plugin. for (elt = plugin_connections; elt; elt = g_slist_next (elt)) - nm_sysconfig_settings_add_connection (self, NM_EXPORTED_CONNECTION (elt->data), TRUE); + claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (elt->data), TRUE); g_slist_free (plugin_connections); } @@ -133,71 +154,53 @@ load_connections (NMSysconfigSettings *self) priv->connections_loaded = TRUE; /* FIXME: Bad hack */ - unmanaged_devices_changed (NULL, self); + unmanaged_specs_changed (NULL, self); } -static void -hash_keys_to_slist (gpointer key, gpointer val, gpointer user_data) -{ - GSList **list = (GSList **) user_data; - - *list = g_slist_prepend (*list, key); -} - -GSList * -nm_sysconfig_settings_list_connections (NMSysconfigSettings *self) +static gboolean +impl_settings_list_connections (NMSysconfigSettings *self, + GPtrArray **connections, + GError **error) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *list = NULL; + GHashTableIter iter; + gpointer key; load_connections (self); - g_hash_table_foreach (priv->connections, hash_keys_to_slist, &list); + *connections = g_ptr_array_sized_new (g_hash_table_size (priv->connections)); - return list; -} + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + NMSettingsConnectionInterface *connection = key; + char *path = NULL; -static GSList * -list_connections (NMSettings *settings) -{ - return nm_sysconfig_settings_list_connections (NM_SYSCONFIG_SETTINGS (settings)); -} - -typedef struct { - const char *path; - NMSysconfigConnection *found; -} FindConnectionInfo; - -static void -find_by_path (gpointer key, gpointer data, gpointer user_data) -{ - FindConnectionInfo *info = user_data; - NMSysconfigConnection *exported = NM_SYSCONFIG_CONNECTION (data); - const char *path; - - if (!info->found) { - NMConnection *connection; - - connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (exported)); - g_assert (connection); - path = nm_connection_get_path (connection); + g_object_get (G_OBJECT (connection), NM_SETTINGS_CONNECTION_INTERFACE_PATH, &path, NULL); g_assert (path); - if (!strcmp (path, info->path)) - info->found = exported; + g_ptr_array_add (*connections, path); } + return TRUE; } -NMSysconfigConnection * -nm_sysconfig_settings_get_connection_by_path (NMSysconfigSettings *self, - const char *path) +static NMSettingsConnectionInterface * +get_connection_by_path (NMSettingsInterface *self, + const char *path) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - FindConnectionInfo info; + GHashTableIter iter; + gpointer key; - info.path = path; - info.found = NULL; - g_hash_table_foreach (priv->connections, find_by_path, &info); - return info.found; + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + NMConnection *candidate = NM_CONNECTION (key); + const char *candidate_path; + + candidate_path = nm_connection_get_path (candidate); + g_assert (candidate_path); + if (!strcmp (path, candidate_path)) + return NM_SETTINGS_CONNECTION_INTERFACE (candidate); + } + return NULL; } static void @@ -210,30 +213,6 @@ clear_unmanaged_specs (NMSysconfigSettings *self) priv->unmanaged_specs = NULL; } -static void -finalize (GObject *object) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object); - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - g_hash_table_destroy (priv->connections); - - clear_unmanaged_specs (self); - - g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); - g_slist_free (priv->plugins); - - if (priv->pol_ctx) - polkit_context_unref (priv->pol_ctx); - - g_object_unref (priv->dbus_mgr); - - g_free (priv->orig_hostname); - g_free (priv->config_file); - - G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object); -} - static char* uscore_to_wincaps (const char *uscore) { @@ -288,9 +267,8 @@ nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self) return priv->unmanaged_specs; } -NMSystemConfigInterface * -nm_sysconfig_settings_get_plugin (NMSysconfigSettings *self, - guint32 capability) +static NMSystemConfigInterface * +get_plugin (NMSysconfigSettings *self, guint32 capability) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); GSList *iter; @@ -338,125 +316,12 @@ nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) return hostname; } -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object); - const GSList *specs, *iter; - GSList *copy = NULL; - - switch (prop_id) { - case PROP_UNMANAGED_SPECS: - specs = nm_sysconfig_settings_get_unmanaged_specs (self); - for (iter = specs; iter; iter = g_slist_next (iter)) - copy = g_slist_append (copy, g_strdup (iter->data)); - g_value_take_boxed (value, copy); - break; - case PROP_HOSTNAME: - g_value_take_string (value, nm_sysconfig_settings_get_hostname (self)); - - /* Don't ever pass NULL through D-Bus */ - if (!g_value_get_string (value)) - g_value_set_static_string (value, ""); - break; - case PROP_CAN_MODIFY: - g_value_set_boolean (value, !!nm_sysconfig_settings_get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - NMSettingsClass *settings_class = NM_SETTINGS_CLASS (class); - - g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate)); - - /* virtual methods */ - object_class->notify = notify; - object_class->get_property = get_property; - object_class->finalize = finalize; - settings_class->list_connections = list_connections; - - /* properties */ - g_object_class_install_property - (object_class, PROP_UNMANAGED_SPECS, - g_param_spec_boxed (NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, - "Unamanged device specs", - "Unmanaged device specs", - DBUS_TYPE_G_LIST_OF_STRING, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_HOSTNAME, - g_param_spec_string (NM_SYSCONFIG_SETTINGS_HOSTNAME, - "Hostname", - "Hostname", - NULL, - G_PARAM_READABLE)); - - g_object_class_install_property - (object_class, PROP_CAN_MODIFY, - g_param_spec_boolean (NM_SYSCONFIG_SETTINGS_CAN_MODIFY, - "CanModify", - "Can modify", - FALSE, - G_PARAM_READABLE)); - - /* signals */ - signals[PROPERTIES_CHANGED] = - g_signal_new ("properties-changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSysconfigSettingsClass, properties_changed), - NULL, NULL, - g_cclosure_marshal_VOID__BOXED, - G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (settings_class), - &dbus_glib_nm_settings_system_object_info); - - dbus_g_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR, - NM_DBUS_IFACE_SETTINGS_SYSTEM, - NM_TYPE_SYSCONFIG_SETTINGS_ERROR); -} - -static void -nm_sysconfig_settings_init (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - char hostname[HOST_NAME_MAX + 2]; - GError *error = NULL; - - priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); - - priv->pol_ctx = create_polkit_context (&error); - if (!priv->pol_ctx) { - g_warning ("%s: failed to create PolicyKit context: %s", - __func__, - (error && error->message) ? error->message : "(unknown)"); - } - - /* Grab hostname on startup and use that if no plugins provide one */ - memset (hostname, 0, sizeof (hostname)); - if (gethostname (&hostname[0], HOST_NAME_MAX) == 0) { - /* only cache it if it's a valid hostname */ - if (strlen (hostname) && strcmp (hostname, "localhost") && strcmp (hostname, "localhost.localdomain")) - priv->orig_hostname = g_strdup (hostname); - } -} - static void plugin_connection_added (NMSystemConfigInterface *config, - NMExportedConnection *connection, + NMSettingsConnectionInterface *connection, gpointer user_data) { - nm_sysconfig_settings_add_connection (NM_SYSCONFIG_SETTINGS (user_data), connection, TRUE); + claim_connection (NM_SYSCONFIG_SETTINGS (user_data), connection, TRUE); } static gboolean @@ -473,8 +338,8 @@ find_unmanaged_device (NMSysconfigSettings *self, const char *needle) } static void -unmanaged_devices_changed (NMSystemConfigInterface *config, - gpointer user_data) +unmanaged_specs_changed (NMSystemConfigInterface *config, + gpointer user_data) { NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (user_data); NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); @@ -482,7 +347,7 @@ unmanaged_devices_changed (NMSystemConfigInterface *config, clear_unmanaged_specs (self); - /* Ask all the plugins for their unmanaged devices */ + /* Ask all the plugins for their unmanaged specs */ for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { GSList *specs, *specs_iter; @@ -505,7 +370,7 @@ hostname_changed (NMSystemConfigInterface *config, GParamSpec *pspec, gpointer user_data) { - g_object_notify (G_OBJECT (user_data), NM_SYSCONFIG_SETTINGS_HOSTNAME); + g_object_notify (G_OBJECT (user_data), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME); } static void @@ -522,8 +387,10 @@ add_plugin (NMSysconfigSettings *self, NMSystemConfigInterface *plugin) priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin)); - g_signal_connect (plugin, "connection-added", G_CALLBACK (plugin_connection_added), self); - g_signal_connect (plugin, "unmanaged-devices-changed", G_CALLBACK (unmanaged_devices_changed), self); + g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, + G_CALLBACK (plugin_connection_added), self); + g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED, + G_CALLBACK (unmanaged_specs_changed), self); g_signal_connect (plugin, "notify::hostname", G_CALLBACK (hostname_changed), self); nm_system_config_interface_init (plugin, NULL); @@ -639,23 +506,45 @@ load_plugins (NMSysconfigSettings *self, const char *plugins, GError **error) } static void -connection_removed (NMExportedConnection *connection, - gpointer user_data) +connection_removed (NMSettingsConnectionInterface *connection, + gpointer user_data) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data); g_hash_table_remove (priv->connections, connection); } -void -nm_sysconfig_settings_add_connection (NMSysconfigSettings *self, - NMExportedConnection *connection, - gboolean do_export) +static void +export_connection (NMSysconfigSettings *self, + NMSettingsConnectionInterface *connection) +{ + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + static guint32 ec_counter = 0; + char *path; + DBusGConnection *bus; + + g_return_if_fail (connection != NULL); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); + + path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); + nm_connection_set_path (NM_CONNECTION (connection), path); + nm_connection_set_scope (NM_CONNECTION (connection), NM_CONNECTION_SCOPE_SYSTEM); + + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + dbus_g_connection_register_g_object (bus, path, G_OBJECT (connection)); + + g_free (path); +} + +static void +claim_connection (NMSysconfigSettings *self, + NMSettingsConnectionInterface *connection, + gboolean do_export) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self)); - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); if (g_hash_table_lookup (priv->connections, connection)) /* A plugin is lying to us. */ @@ -665,52 +554,85 @@ nm_sysconfig_settings_add_connection (NMSysconfigSettings *self, g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self); if (do_export) { - DBusGConnection *g_connection; - - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - nm_exported_connection_register_object (connection, NM_CONNECTION_SCOPE_SYSTEM, g_connection); - nm_settings_signal_new_connection (NM_SETTINGS (self), connection); + export_connection (self, connection); + g_signal_emit_by_name (self, "new-connection", connection); } } -void -nm_sysconfig_settings_remove_connection (NMSysconfigSettings *self, - NMExportedConnection *connection, - gboolean do_signal) +static void +remove_connection (NMSysconfigSettings *self, + NMSettingsConnectionInterface *connection, + gboolean do_signal) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self)); - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection)); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); if (g_hash_table_lookup (priv->connections, connection)) { - nm_exported_connection_signal_removed (connection); + g_signal_emit_by_name (G_OBJECT (connection), "removed"); g_hash_table_remove (priv->connections, connection); } } -gboolean -nm_sysconfig_settings_add_new_connection (NMSysconfigSettings *self, - GHashTable *hash, - GError **error) +typedef struct { + NMSysconfigSettings *self; + DBusGMethodInvocation *context; + PolkitSubject *subject; + GCancellable *cancellable; + + NMConnection *connection; + char *hostname; +} PolkitCall; + +static PolkitCall * +polkit_call_new (NMSysconfigSettings *self, + DBusGMethodInvocation *context, + NMConnection *connection, + const char *hostname) +{ + PolkitCall *call; + char *sender; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (context != NULL, NULL); + + call = g_malloc0 (sizeof (PolkitCall)); + call->self = self; + call->context = context; + call->connection = connection; + if (hostname) + call->hostname = g_strdup (hostname); + call->cancellable = g_cancellable_new (); + + sender = dbus_g_method_get_sender (context); + call->subject = polkit_system_bus_name_new (sender); + g_free (sender); + + return call; +} + +static void +polkit_call_free (PolkitCall *call) +{ + if (call->connection) + g_object_unref (call->connection); + g_free (call->hostname); + g_object_unref (call->subject); + g_object_unref (call->cancellable); + g_free (call); +} + +static gboolean +add_new_connection (NMSysconfigSettings *self, + NMConnection *connection, + GError **error) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - NMConnection *connection; GError *tmp_error = NULL, *last_error = NULL; GSList *iter; gboolean success = FALSE; - connection = nm_connection_new_from_hash (hash, &tmp_error); - if (!connection) { - /* Invalid connection hash */ - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION, - "Invalid connection: '%s' / '%s' invalid: %d", - tmp_error ? g_type_name (nm_connection_lookup_setting_type_by_quark (tmp_error->domain)) : "(unknown)", - tmp_error ? tmp_error->message : "(unknown)", tmp_error ? tmp_error->code : -1); - g_clear_error (&tmp_error); - return FALSE; - } - /* Here's how it works: 1) plugin writes a connection. 2) plugin notices that a new connection is available for reading. @@ -720,82 +642,133 @@ nm_sysconfig_settings_add_new_connection (NMSysconfigSettings *self, for (iter = priv->plugins; iter && !success; iter = iter->next) { success = nm_system_config_interface_add_connection (NM_SYSTEM_CONFIG_INTERFACE (iter->data), - connection, &tmp_error); + connection, + &tmp_error); g_clear_error (&last_error); if (!success) last_error = tmp_error; } - g_object_unref (connection); - - if (!success) { - g_set_error (error, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, - "Saving connection failed: (%d) %s", - last_error ? last_error->code : -1, - last_error && last_error->message ? last_error->message : "(unknown)"); - g_clear_error (&last_error); - } - + if (!success) + *error = last_error; return success; } -static gboolean +static void +pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data) +{ + PolkitCall *call = user_data; + NMSysconfigSettings *self = call->self; + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + PolkitAuthorizationResult *pk_result; + GError *error = NULL, *add_error = NULL; + + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + dbus_g_method_return_error (call->context, error); + goto out; + } + + /* Caller didn't successfully authenticate */ + if (!polkit_authorization_result_get_is_authorized (pk_result)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Insufficient privileges."); + dbus_g_method_return_error (call->context, error); + goto out; + } + + if (add_new_connection (self, call->connection, &add_error)) { + dbus_g_method_return (call->context); + } else { + error = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, + "Saving connection failed: (%d) %s", + add_error ? add_error->code : -1, + (add_error && add_error->message) ? add_error->message : "(unknown)"); + g_error_free (add_error); + dbus_g_method_return_error (call->context, error); + } + +out: + g_clear_error (&error); + polkit_call_free (call); + if (pk_result) + g_object_unref (pk_result); +} + +static void impl_settings_add_connection (NMSysconfigSettings *self, - GHashTable *hash, + GHashTable *settings, DBusGMethodInvocation *context) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - DBusGConnection *g_connection; - GError *err = NULL; + PolkitCall *call; + NMConnection *tmp; + GError *error = NULL; /* Do any of the plugins support adding? */ - if (!nm_sysconfig_settings_get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) { - err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED, - "%s", "None of the registered plugins support add."); - goto out; + if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED, + "None of the registered plugins support add."); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; } - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!check_polkit_privileges (g_connection, priv->pol_ctx, context, &err)) - goto out; - - nm_sysconfig_settings_add_new_connection (self, hash, &err); - - out: - if (err) { - dbus_g_method_return_error (context, err); - g_error_free (err); - return FALSE; - } else { - dbus_g_method_return (context); - return TRUE; + /* Check if the settings are valid first */ + tmp = nm_connection_new_from_hash (settings, &error); + if (!tmp) { + g_assert (error); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; } + + call = polkit_call_new (self, context, tmp, NULL); + g_assert (call); + polkit_authority_check_authorization (priv->authority, + call->subject, + NM_SYSCONFIG_POLICY_ACTION, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + call->cancellable, + pk_add_cb, + call); } -static gboolean -impl_settings_save_hostname (NMSysconfigSettings *self, - const char *hostname, - DBusGMethodInvocation *context) +static void +pk_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data) { + PolkitCall *call = user_data; + NMSysconfigSettings *self = call->self; NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GError *err = NULL; + PolkitAuthorizationResult *pk_result; + GError *error = NULL; GSList *iter; gboolean success = FALSE; - DBusGConnection *g_connection; - /* Do any of the plugins support setting the hostname? */ - if (!nm_sysconfig_settings_get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) { - err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, - "%s", "None of the registered plugins support setting the hostname."); + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + dbus_g_method_return_error (call->context, error); goto out; } - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - if (!check_polkit_privileges (g_connection, priv->pol_ctx, context, &err)) + /* Caller didn't successfully authenticate */ + if (!polkit_authorization_result_get_is_authorized (pk_result)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, + "Insufficient privileges."); + dbus_g_method_return_error (call->context, error); goto out; + } /* Set the hostname in all plugins */ for (iter = priv->plugins; iter; iter = iter->next) { @@ -803,32 +776,64 @@ impl_settings_save_hostname (NMSysconfigSettings *self, g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); if (caps & NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME) { - g_object_set (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, hostname, NULL); + g_object_set (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, call->hostname, NULL); success = TRUE; } } - if (!success) { - err = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, - "%s", "Saving the hostname failed."); + if (success) { + dbus_g_method_return (call->context); + } else { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_FAILED, + "Saving the hostname failed."); + dbus_g_method_return_error (call->context, error); } - out: - if (err) { - dbus_g_method_return_error (context, err); - g_error_free (err); - return FALSE; - } else { - dbus_g_method_return (context); - return TRUE; +out: + g_clear_error (&error); + polkit_call_free (call); + if (pk_result) + g_object_unref (pk_result); +} + +static void +impl_settings_save_hostname (NMSysconfigSettings *self, + const char *hostname, + DBusGMethodInvocation *context) +{ + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + PolkitCall *call; + GError *error = NULL; + + /* Do any of the plugins support setting the hostname? */ + if (!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) { + error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, + NM_SYSCONFIG_SETTINGS_ERROR_SAVE_HOSTNAME_NOT_SUPPORTED, + "None of the registered plugins support setting the hostname."); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; } + + call = polkit_call_new (self, context, NULL, hostname); + g_assert (call); + polkit_authority_check_authorization (priv->authority, + call->subject, + NM_SYSCONFIG_POLICY_ACTION, + NULL, + POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, + call->cancellable, + pk_hostname_cb, + call); } static gboolean have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac) { - GSList *list, *iter; + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + GHashTableIter iter; + gpointer key; NMSettingConnection *s_con; NMSettingWired *s_wired; const GByteArray *setting_mac; @@ -838,16 +843,11 @@ have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac) g_return_val_if_fail (mac != NULL, FALSE); /* Find a wired connection locked to the given MAC address, if any */ - list = nm_settings_list_connections (NM_SETTINGS (self)); - for (iter = list; iter; iter = g_slist_next (iter)) { - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (iter->data); - NMConnection *connection; + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + NMConnection *connection = NM_CONNECTION (key); const char *connection_type; - connection = nm_exported_connection_get_connection (exported); - if (!connection) - continue; - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); connection_type = nm_setting_connection_get_connection_type (s_con); @@ -877,7 +877,6 @@ have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac) } } - g_slist_free (list); return ret; } @@ -932,7 +931,6 @@ default_wired_deleted (NMDefaultWiredConnection *wired, NMSysconfigSettings *self) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - NMConnection *wrapped; NMSettingConnection *s_con; char *tmp; GKeyFile *config; @@ -951,9 +949,8 @@ default_wired_deleted (NMDefaultWiredConnection *wired, * connection for that device again. */ - wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (wired)); - g_assert (wrapped); - s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired), + NM_TYPE_SETTING_CONNECTION); g_assert (s_con); /* Ignore removals of read-only connections, since they couldn't have @@ -1015,13 +1012,11 @@ cleanup: NULL); } -static void +static gboolean default_wired_try_update (NMDefaultWiredConnection *wired, - GHashTable *new_settings, NMSysconfigSettings *self) { GError *error = NULL; - NMConnection *wrapped; NMSettingConnection *s_con; const char *id; @@ -1029,32 +1024,32 @@ default_wired_try_update (NMDefaultWiredConnection *wired, * persistent storage. */ - wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (wired)); - g_assert (wrapped); - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION)); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired), + NM_TYPE_SETTING_CONNECTION); g_assert (s_con); id = nm_setting_connection_get_id (s_con); g_assert (id); - nm_sysconfig_settings_remove_connection (self, NM_EXPORTED_CONNECTION (wired), FALSE); - if (nm_sysconfig_settings_add_new_connection (self, new_settings, &error)) { + remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE); + if (add_new_connection (self, NM_CONNECTION (wired), &error)) { g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)), DEFAULT_WIRED_TAG, NULL); g_message ("Saved default wired connection '%s' to persistent storage", id); - return; + return FALSE; } g_warning ("%s: couldn't save default wired connection '%s': %d / %s", - __func__, id, error ? error->code : -1, + __func__, id, + error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); - g_clear_error (&error); /* If there was an error, don't destroy the default wired connection, * but add it back to the system settings service. Connection is already * exported on the bus, don't export it again, thus do_export == FALSE. */ - nm_sysconfig_settings_add_connection (self, NM_EXPORTED_CONNECTION (wired), FALSE); + claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE); + return TRUE; } void @@ -1062,9 +1057,8 @@ nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device) { GByteArray *mac = NULL; struct ether_addr tmp; - NMDefaultWiredConnection *connection; + NMDefaultWiredConnection *wired; NMSettingConnection *s_con; - NMConnection *wrapped; gboolean read_only = TRUE; const char *id; @@ -1087,28 +1081,27 @@ nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device) || is_mac_auto_wired_blacklisted (self, mac)) goto ignore; - if (nm_sysconfig_settings_get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) + if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) read_only = FALSE; - connection = nm_default_wired_connection_new (mac, device, read_only); - if (!connection) + wired = nm_default_wired_connection_new (mac, device, read_only); + if (!wired) goto ignore; - wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection)); - g_assert (wrapped); - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION)); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (wired), + NM_TYPE_SETTING_CONNECTION); g_assert (s_con); id = nm_setting_connection_get_id (s_con); g_assert (id); g_message ("Added default wired connection '%s' for %s", id, nm_device_get_udi (device)); - g_signal_connect (connection, "try-update", (GCallback) default_wired_try_update, self); - g_signal_connect (connection, "deleted", (GCallback) default_wired_deleted, self); - nm_sysconfig_settings_add_connection (self, NM_EXPORTED_CONNECTION (connection), TRUE); - g_object_unref (connection); + g_signal_connect (wired, "try-update", (GCallback) default_wired_try_update, self); + g_signal_connect (wired, "deleted", (GCallback) default_wired_deleted, self); + claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), TRUE); + g_object_unref (wired); - g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_TAG, connection); + g_object_set_data (G_OBJECT (device), DEFAULT_WIRED_TAG, wired); ignore: g_byte_array_free (mac, TRUE); @@ -1117,14 +1110,14 @@ ignore: void nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device) { - NMExportedConnection *exported; + NMDefaultWiredConnection *connection; if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET) return; - exported = (NMExportedConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG); - if (exported) - nm_sysconfig_settings_remove_connection (self, exported, TRUE); + connection = (NMDefaultWiredConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG); + if (connection) + remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (connection), TRUE); } NMSysconfigSettings * @@ -1161,3 +1154,144 @@ nm_sysconfig_settings_new (const char *config_file, return self; } +/***************************************************************/ + +static void +finalize (GObject *object) +{ + NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object); + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + + g_hash_table_destroy (priv->connections); + + clear_unmanaged_specs (self); + + g_slist_foreach (priv->plugins, (GFunc) g_object_unref, NULL); + g_slist_free (priv->plugins); + + if (priv->authority) + g_object_unref (priv->authority); + + g_object_unref (priv->dbus_mgr); + + g_free (priv->orig_hostname); + g_free (priv->config_file); + + G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object); +} + +static void +settings_interface_init (NMSettingsInterface *iface) +{ + iface->get_connection_by_path = get_connection_by_path; + + dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), + &dbus_glib_nm_settings_object_info); +} + +static void +settings_system_interface_init (NMSettingsSystemInterface *iface) +{ + dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), + &dbus_glib_nm_settings_system_object_info); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object); + const GSList *specs, *iter; + GSList *copy = NULL; + + switch (prop_id) { + case PROP_UNMANAGED_SPECS: + specs = nm_sysconfig_settings_get_unmanaged_specs (self); + for (iter = specs; iter; iter = g_slist_next (iter)) + copy = g_slist_append (copy, g_strdup (iter->data)); + g_value_take_boxed (value, copy); + break; + case PROP_HOSTNAME: + g_value_take_string (value, nm_sysconfig_settings_get_hostname (self)); + + /* Don't ever pass NULL through D-Bus */ + if (!g_value_get_string (value)) + g_value_set_static_string (value, ""); + break; + case PROP_CAN_MODIFY: + g_value_set_boolean (value, !!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate)); + + /* virtual methods */ + object_class->notify = notify; + object_class->get_property = get_property; + object_class->finalize = finalize; + + /* properties */ + g_object_class_install_property + (object_class, PROP_UNMANAGED_SPECS, + g_param_spec_boxed (NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS, + "Unamanged device specs", + "Unmanaged device specs", + DBUS_TYPE_G_LIST_OF_STRING, + G_PARAM_READABLE)); + + g_object_class_override_property (object_class, + NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME, + NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME); + + g_object_class_override_property (object_class, + NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY, + NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY); + + /* signals */ + signals[PROPERTIES_CHANGED] = + g_signal_new ("properties-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSysconfigSettingsClass, properties_changed), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT); + + dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), + &dbus_glib_nm_settings_object_info); + + dbus_g_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR, + NM_DBUS_IFACE_SETTINGS_SYSTEM, + NM_TYPE_SYSCONFIG_SETTINGS_ERROR); +} + +static void +nm_sysconfig_settings_init (NMSysconfigSettings *self) +{ + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + char hostname[HOST_NAME_MAX + 2]; + + priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); + + priv->authority = polkit_authority_get (); + if (!priv->authority) + g_warning ("%s: failed to create PolicyKit authority.", __func__); + + /* Grab hostname on startup and use that if no plugins provide one */ + memset (hostname, 0, sizeof (hostname)); + if (gethostname (&hostname[0], HOST_NAME_MAX) == 0) { + /* only cache it if it's a valid hostname */ + if (strlen (hostname) && strcmp (hostname, "localhost") && strcmp (hostname, "localhost.localdomain")) + priv->orig_hostname = g_strdup (hostname); + } +} + diff --git a/src/system-settings/nm-sysconfig-settings.h b/src/system-settings/nm-sysconfig-settings.h index 632c75daf8..badb6442e9 100644 --- a/src/system-settings/nm-sysconfig-settings.h +++ b/src/system-settings/nm-sysconfig-settings.h @@ -27,15 +27,11 @@ #define __NM_SYSCONFIG_SETTINGS_H__ #include -#include #include "nm-sysconfig-connection.h" #include "nm-system-config-interface.h" #include "nm-device.h" -typedef struct _NMSysconfigSettings NMSysconfigSettings; -typedef struct _NMSysconfigSettingsClass NMSysconfigSettingsClass; - #define NM_TYPE_SYSCONFIG_SETTINGS (nm_sysconfig_settings_get_type ()) #define NM_SYSCONFIG_SETTINGS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettings)) #define NM_SYSCONFIG_SETTINGS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass)) @@ -44,21 +40,17 @@ typedef struct _NMSysconfigSettingsClass NMSysconfigSettingsClass; #define NM_SYSCONFIG_SETTINGS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsClass)) #define NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS "unmanaged-specs" -#define NM_SYSCONFIG_SETTINGS_HOSTNAME "hostname" -#define NM_SYSCONFIG_SETTINGS_CAN_MODIFY "can-modify" -struct _NMSysconfigSettings -{ - NMSettings parent_instance; -}; +typedef struct { + GObject parent_instance; +} NMSysconfigSettings; -struct _NMSysconfigSettingsClass -{ - NMSettingsClass parent_class; +typedef struct { + GObjectClass parent_class; /* Signals */ - void (*properties_changed) (NMSysconfigSettings *settings, GHashTable *properties); -}; + void (*properties_changed) (NMSysconfigSettings *self, GHashTable *properties); +} NMSysconfigSettingsClass; GType nm_sysconfig_settings_get_type (void); @@ -66,34 +58,10 @@ NMSysconfigSettings *nm_sysconfig_settings_new (const char *config_file, const char *plugins, GError **error); -/* Registers an exising connection with the settings service */ -void nm_sysconfig_settings_add_connection (NMSysconfigSettings *settings, - NMExportedConnection *connection, - gboolean do_export); - -void nm_sysconfig_settings_remove_connection (NMSysconfigSettings *settings, - NMExportedConnection *connection, - gboolean do_signal); - -NMSystemConfigInterface *nm_sysconfig_settings_get_plugin (NMSysconfigSettings *self, - guint32 capability); - -/* Adds a new connection from a hash of that connection's settings, - * potentially saving the new connection to persistent storage. - */ -gboolean nm_sysconfig_settings_add_new_connection (NMSysconfigSettings *self, - GHashTable *hash, - GError **error); - const GSList *nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self); char *nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self); -GSList *nm_sysconfig_settings_list_connections (NMSysconfigSettings *self); - -NMSysconfigConnection *nm_sysconfig_settings_get_connection_by_path (NMSysconfigSettings *self, - const char *path); - void nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device); void nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device); diff --git a/src/system-settings/nm-system-config-interface.c b/src/system-settings/nm-system-config-interface.c index 2f33e59069..90fd93ba3d 100644 --- a/src/system-settings/nm-system-config-interface.c +++ b/src/system-settings/nm-system-config-interface.c @@ -66,19 +66,19 @@ interface_init (gpointer g_iface) G_PARAM_READWRITE)); /* Signals */ - g_signal_new ("connection-added", + g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, iface_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMSystemConfigInterface, connection_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, - NM_TYPE_EXPORTED_CONNECTION); + NM_TYPE_SETTINGS_CONNECTION_INTERFACE); - g_signal_new ("unmanaged-devices-changed", + g_signal_new (NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED, iface_type, G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_devices_changed), + G_STRUCT_OFFSET (NMSystemConfigInterface, unmanaged_specs_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); diff --git a/src/system-settings/nm-system-config-interface.h b/src/system-settings/nm-system-config-interface.h index 1be49a7ee0..c5bbaaa917 100644 --- a/src/system-settings/nm-system-config-interface.h +++ b/src/system-settings/nm-system-config-interface.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include G_BEGIN_DECLS @@ -61,6 +61,9 @@ GObject * nm_system_config_factory (void); #define NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES "capabilities" #define NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME "hostname" +#define NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED "unmanaged-specs-changed" +#define NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED "connection-added" + typedef enum { NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE = 0x00000000, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS = 0x00000001, @@ -87,8 +90,9 @@ struct _NMSystemConfigInterface { /* Called when the plugin is loaded to initialize it */ void (*init) (NMSystemConfigInterface *config); - /* Returns the plugins currently known list of connections. The returned - * list is freed by the system settings service. + /* Returns a GSList of objects that implement NMSettingsConnectionInterface + * that represent connections the plugin knows about. The returned list + * is freed by the system settings service. */ GSList * (*get_connections) (NMSystemConfigInterface *config); @@ -109,15 +113,18 @@ struct _NMSystemConfigInterface { /* * Add a new connection. */ - gboolean (*add_connection) (NMSystemConfigInterface *config, NMConnection *connection, GError **error); + gboolean (*add_connection) (NMSystemConfigInterface *config, + NMConnection *connection, + GError **error); /* Signals */ /* Emitted when a new connection has been found by the plugin */ - void (*connection_added) (NMSystemConfigInterface *config, NMExportedConnection *connection); + void (*connection_added) (NMSystemConfigInterface *config, + NMSettingsConnectionInterface *connection); - /* Emitted when the list of unmanaged devices changes */ - void (*unmanaged_devices_changed) (NMSystemConfigInterface *config); + /* Emitted when the list of unmanaged device specifications changes */ + void (*unmanaged_specs_changed) (NMSystemConfigInterface *config); }; GType nm_system_config_interface_get_type (void); diff --git a/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index 4767b5183c..aafc41e9f4 100644 --- a/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "common.h" #include "nm-ifcfg-connection.h" @@ -40,7 +41,13 @@ #include "writer.h" #include "nm-inotify-helper.h" -G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SYSCONFIG_CONNECTION) +static NMSettingsConnectionInterface *parent_settings_connection_iface; + +static void settings_connection_interface_init (NMSettingsConnectionInterface *klass); + +G_DEFINE_TYPE_EXTENDED (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, + settings_connection_interface_init)) #define NM_IFCFG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionPrivate)) @@ -97,24 +104,32 @@ nm_ifcfg_connection_new (const char *filename, { GObject *object; NMIfcfgConnectionPrivate *priv; - NMConnection *wrapped; + NMConnection *tmp; char *unmanaged = NULL; char *keyfile = NULL; NMInotifyHelper *ih; + GHashTable *settings; g_return_val_if_fail (filename != NULL, NULL); - wrapped = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error); - if (!wrapped) + tmp = connection_from_file (filename, NULL, NULL, &unmanaged, &keyfile, error, ignore_error); + if (!tmp) return NULL; object = (GObject *) g_object_new (NM_TYPE_IFCFG_CONNECTION, NM_IFCFG_CONNECTION_FILENAME, filename, NM_IFCFG_CONNECTION_UNMANAGED, unmanaged, - NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); - if (!object) - goto out; + if (!object) { + g_object_unref (tmp); + return NULL; + } + + /* Update our settings with what was read from the file */ + settings = nm_connection_to_hash (tmp); + nm_connection_replace_settings (NM_CONNECTION (object), settings, NULL); + g_hash_table_destroy (settings); + g_object_unref (tmp); priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); @@ -126,9 +141,7 @@ nm_ifcfg_connection_new (const char *filename, priv->keyfile = keyfile; priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile); -out: - g_object_unref (wrapped); - return (NMIfcfgConnection *) object; + return NM_IFCFG_CONNECTION (object); } const char * @@ -147,43 +160,51 @@ nm_ifcfg_connection_get_unmanaged_spec (NMIfcfgConnection *self) return NM_IFCFG_CONNECTION_GET_PRIVATE (self)->unmanaged; } -gboolean -nm_ifcfg_connection_update (NMIfcfgConnection *self, GHashTable *new_settings, GError **error) +static gboolean +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) { - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (self); - NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported); - NMConnection *connection; + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); + GError *error = NULL; - connection = nm_exported_connection_get_connection (exported); - if (!nm_connection_replace_settings (connection, new_settings, error)) + if (!writer_update_connection (NM_CONNECTION (connection), + IFCFG_DIR, + priv->filename, + priv->keyfile, + &error)) { + callback (connection, error, user_data); + g_error_free (error); return FALSE; + } - return writer_update_connection (connection, IFCFG_DIR, priv->filename, priv->keyfile, error); + return parent_settings_connection_iface->update (connection, callback, user_data); } -static gboolean -update (NMExportedConnection *exported, GHashTable *new_settings, GError **error) +static gboolean +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) { - if (!NM_EXPORTED_CONNECTION_CLASS (nm_ifcfg_connection_parent_class)->update (exported, new_settings, error)) - return FALSE; - - return nm_ifcfg_connection_update (NM_IFCFG_CONNECTION (exported), new_settings, error); -} - -static gboolean -do_delete (NMExportedConnection *exported, GError **error) -{ - NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (exported); + NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (connection); g_unlink (priv->filename); if (priv->keyfile) g_unlink (priv->keyfile); - return TRUE; + return parent_settings_connection_iface->delete (connection, callback, user_data); } /* GObject */ +static void +settings_connection_interface_init (NMSettingsConnectionInterface *iface) +{ + parent_settings_connection_iface = g_type_interface_peek_parent (iface); + iface->update = update; + iface->delete = do_delete; +} + static void nm_ifcfg_connection_init (NMIfcfgConnection *connection) { @@ -193,14 +214,11 @@ static void finalize (GObject *object) { NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object); - NMConnection *wrapped; NMInotifyHelper *ih; g_free (priv->udi); - wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (object)); - if (wrapped) - nm_connection_clear_secrets (wrapped); + nm_connection_clear_secrets (NM_CONNECTION (object)); ih = nm_inotify_helper_get (); @@ -267,7 +285,6 @@ static void nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (ifcfg_connection_class); - NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (ifcfg_connection_class); g_type_class_add_private (ifcfg_connection_class, sizeof (NMIfcfgConnectionPrivate)); @@ -276,9 +293,6 @@ nm_ifcfg_connection_class_init (NMIfcfgConnectionClass *ifcfg_connection_class) object_class->get_property = get_property; object_class->finalize = finalize; - connection_class->update = update; - connection_class->do_delete = do_delete; - /* Properties */ g_object_class_install_property (object_class, PROP_FILENAME, diff --git a/system-settings/plugins/ifcfg-rh/plugin.c b/system-settings/plugins/ifcfg-rh/plugin.c index 361a858005..f861aebebd 100644 --- a/system-settings/plugins/ifcfg-rh/plugin.c +++ b/system-settings/plugins/ifcfg-rh/plugin.c @@ -88,7 +88,7 @@ connection_unmanaged_changed (NMIfcfgConnection *connection, GParamSpec *pspec, gpointer user_data) { - g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), "unmanaged-devices-changed"); + g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } static void @@ -117,13 +117,10 @@ read_one_connection (SCPluginIfcfg *plugin, const char *filename) connection = nm_ifcfg_connection_new (filename, &error, &ignore_error); if (connection) { - NMConnection *wrapped; NMSettingConnection *s_con; const char *cid; - wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection)); - g_assert (wrapped); - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION)); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION); g_assert (s_con); cid = nm_setting_connection_get_id (s_con); @@ -137,7 +134,7 @@ read_one_connection (SCPluginIfcfg *plugin, const char *filename) if (nm_ifcfg_connection_get_unmanaged_spec (connection)) { PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Ignoring connection '%s' and its " "device because NM_CONTROLLED was false.", cid); - g_signal_emit_by_name (plugin, "unmanaged-devices-changed"); + g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } else { /* Wait for the connection to become unmanaged once it knows the * UDI of it's device, if/when the device gets plugged in. @@ -227,6 +224,13 @@ read_connections (SCPluginIfcfg *plugin) /* Monitoring */ +static void +ignore_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) +{ +} + static void connection_changed_handler (SCPluginIfcfg *plugin, const char *path, @@ -234,7 +238,7 @@ connection_changed_handler (SCPluginIfcfg *plugin, gboolean *do_remove, gboolean *do_new) { - NMIfcfgConnection *tmp; + NMIfcfgConnection *new; GError *error = NULL; GHashTable *settings; gboolean ignore_error = FALSE; @@ -248,8 +252,8 @@ connection_changed_handler (SCPluginIfcfg *plugin, PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path); - tmp = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, &error, &ignore_error); - if (!tmp) { + new = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, &error, &ignore_error); + if (!new) { /* errors reading connection; remove it */ if (!ignore_error) { PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error: %s", @@ -265,7 +269,7 @@ connection_changed_handler (SCPluginIfcfg *plugin, /* Successfully read connection changes */ old_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (connection)); - new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (tmp)); + new_unmanaged = nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (new)); if (new_unmanaged) { if (!old_unmanaged) { @@ -273,16 +277,11 @@ connection_changed_handler (SCPluginIfcfg *plugin, *do_remove = *do_new = TRUE; } } else { - NMConnection *old_wrapped, *new_wrapped; - - new_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (tmp)); - old_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection)); - if (old_unmanaged) { /* now managed */ NMSettingConnection *s_con; const char *cid; - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (new_wrapped, NM_TYPE_SETTING_CONNECTION)); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (new), NM_TYPE_SETTING_CONNECTION); g_assert (s_con); cid = nm_setting_connection_get_id (s_con); @@ -290,25 +289,30 @@ connection_changed_handler (SCPluginIfcfg *plugin, PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "Managing connection '%s' and its " "device because NM_CONTROLLED was true.", cid); - g_signal_emit_by_name (plugin, "connection-added", connection); + g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); } /* Only update if different */ - if (!nm_connection_compare (new_wrapped, old_wrapped, NM_SETTING_COMPARE_FLAG_EXACT)) { - settings = nm_connection_to_hash (new_wrapped); - if (!nm_ifcfg_connection_update (connection, settings, &error)) { + if (!nm_connection_compare (NM_CONNECTION (new), + NM_CONNECTION (connection), + NM_SETTING_COMPARE_FLAG_EXACT)) { + settings = nm_connection_to_hash (NM_CONNECTION (new)); + if (!nm_connection_replace_settings (NM_CONNECTION (connection), settings, &error)) { PLUGIN_WARN (IFCFG_PLUGIN_NAME, " error updating: %s", (error && error->message) ? error->message : "(unknown)"); g_clear_error (&error); } g_hash_table_destroy (settings); + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (connection), + ignore_cb, + NULL); } /* Update unmanaged status */ g_object_set (connection, "unmanaged", new_unmanaged, NULL); - g_signal_emit_by_name (plugin, "unmanaged-devices-changed"); + g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } - g_object_unref (tmp); + g_object_unref (new); } static void @@ -330,18 +334,18 @@ handle_connection_remove_or_new (SCPluginIfcfg *plugin, unmanaged = nm_ifcfg_connection_get_unmanaged_spec (connection); g_hash_table_remove (priv->connections, path); - nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection)); + g_signal_emit_by_name (connection, "removed"); /* Emit unmanaged changes _after_ removing the connection */ if (unmanaged) - g_signal_emit_by_name (plugin, "unmanaged-devices-changed"); + g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } if (do_new) { connection = read_one_connection (plugin, path); if (connection) { - if (!nm_ifcfg_connection_get_unmanaged_spec (NM_IFCFG_CONNECTION (connection))) - g_signal_emit_by_name (plugin, "connection-added", connection); + if (!nm_ifcfg_connection_get_unmanaged_spec (connection)) + g_signal_emit_by_name (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); } } } diff --git a/system-settings/plugins/ifcfg-suse/plugin.c b/system-settings/plugins/ifcfg-suse/plugin.c index c07ff2df60..86d3abea88 100644 --- a/system-settings/plugins/ifcfg-suse/plugin.c +++ b/system-settings/plugins/ifcfg-suse/plugin.c @@ -190,7 +190,7 @@ read_connection (SCPluginIfcfg *self, GUdevDevice *device, NMDeviceType dev_type if (address && (strlen (address) == 17)) { spec = g_strdup_printf ("mac:%s", address); g_hash_table_insert (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex), spec); - g_signal_emit_by_name (self, "unmanaged-devices-changed"); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } else PLUGIN_WARN (IFCFG_PLUGIN_NAME, " (%s) error getting hardware address", iface); } else { @@ -201,7 +201,7 @@ read_connection (SCPluginIfcfg *self, GUdevDevice *device, NMDeviceType dev_type g_hash_table_insert (priv->connections, GUINT_TO_POINTER (ifindex), connection); - g_signal_emit_by_name (self, "connection-added", connection); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); } } } @@ -281,7 +281,7 @@ handle_uevent (GUdevClient *client, ifindex = (guint32) g_udev_device_get_property_as_uint64 (device, "IFINDEX"); if (g_hash_table_remove (priv->unmanaged_specs, GUINT_TO_POINTER (ifindex))) - g_signal_emit_by_name (self, "unmanaged-devices-changed"); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); exported = (NMExportedConnection *) g_hash_table_lookup (priv->connections, GUINT_TO_POINTER (ifindex)); diff --git a/system-settings/plugins/ifupdown/plugin.c b/system-settings/plugins/ifupdown/plugin.c index 00c3ffc30d..a38f40cfca 100644 --- a/system-settings/plugins/ifupdown/plugin.c +++ b/system-settings/plugins/ifupdown/plugin.c @@ -255,7 +255,7 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device) g_hash_table_insert (priv->well_known_ifaces, g_strdup (iface), g_object_ref (device)); if (ALWAYS_UNMANAGE || priv->unmanage_well_known) - g_signal_emit_by_name (G_OBJECT (self), "unmanaged-devices-changed"); + g_signal_emit_by_name (G_OBJECT (self), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); else bind_device_to_connection (self, device, exported); } @@ -278,7 +278,7 @@ udev_device_removed (SCPluginIfupdown *self, GUdevDevice *device) return; if (ALWAYS_UNMANAGE || priv->unmanage_well_known) - g_signal_emit_by_name (G_OBJECT (self), "unmanaged-devices-changed"); + g_signal_emit_by_name (G_OBJECT (self), NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); } static void diff --git a/system-settings/plugins/keyfile/io/writer.c b/system-settings/plugins/keyfile/io/writer.c index bbf40c7937..efa5d1d4e5 100644 --- a/system-settings/plugins/keyfile/io/writer.c +++ b/system-settings/plugins/keyfile/io/writer.c @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include "nm-dbus-glib-types.h" #include "writer.h" @@ -437,14 +437,18 @@ write_connection (NMConnection *connection, g_file_set_contents (path, data, len, error); if (chown (path, owner_uid, owner_grp) < 0) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INTERNAL_ERROR, + g_set_error (error, + NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "%s.%d: error chowning '%s': %d", __FILE__, __LINE__, path, errno); unlink (path); } else { err = chmod (path, S_IRUSR | S_IWUSR); if (err) { - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INTERNAL_ERROR, + g_set_error (error, + NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "%s.%d: error setting permissions on '%s': %d", __FILE__, __LINE__, path, errno); unlink (path); diff --git a/system-settings/plugins/keyfile/nm-keyfile-connection.c b/system-settings/plugins/keyfile/nm-keyfile-connection.c index 9d9427b340..2b12da7591 100644 --- a/system-settings/plugins/keyfile/nm-keyfile-connection.c +++ b/system-settings/plugins/keyfile/nm-keyfile-connection.c @@ -22,16 +22,22 @@ #include #include #include -#include #include #include +#include #include "nm-dbus-glib-types.h" #include "nm-keyfile-connection.h" #include "reader.h" #include "writer.h" -G_DEFINE_TYPE (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SYSCONFIG_CONNECTION) +static NMSettingsConnectionInterface *parent_settings_connection_iface; + +static void settings_connection_interface_init (NMSettingsConnectionInterface *klass); + +G_DEFINE_TYPE_EXTENDED (NMKeyfileConnection, nm_keyfile_connection, NM_TYPE_SYSCONFIG_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, + settings_connection_interface_init)) #define NM_KEYFILE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_KEYFILE_CONNECTION, NMKeyfileConnectionPrivate)) @@ -65,50 +71,52 @@ nm_keyfile_connection_get_filename (NMKeyfileConnection *self) } static gboolean -update (NMExportedConnection *exported, - GHashTable *new_settings, - GError **error) +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) { - NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported); + NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (connection); + char *filename = NULL; + GError *error = NULL; gboolean success; - success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error); - if (success) { - NMConnection *connection; - char *filename = NULL; - - connection = nm_exported_connection_get_connection (exported); - success = nm_connection_replace_settings (connection, new_settings, error); - if (success) { - success = write_connection (connection, KEYFILE_DIR, 0, 0, &filename, error); - if (success && filename && strcmp (priv->filename, filename)) { - /* Update the filename if it changed */ - g_free (priv->filename); - priv->filename = filename; - } else - g_free (filename); - } + success = write_connection (NM_CONNECTION (connection), KEYFILE_DIR, 0, 0, &filename, &error); + if (success && filename && strcmp (priv->filename, filename)) { + /* Update the filename if it changed */ + g_free (priv->filename); + priv->filename = filename; + success = parent_settings_connection_iface->update (connection, callback, user_data); + } else { + callback (connection, error, user_data); + g_error_free (error); + g_free (filename); } return success; } -static gboolean -do_delete (NMExportedConnection *exported, GError **err) +static gboolean +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) { - NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported); - gboolean success; + NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (connection); - success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->do_delete (exported, err); + g_unlink (priv->filename); - if (success) - g_unlink (priv->filename); - - return success; + return parent_settings_connection_iface->delete (connection, callback, user_data); } /* GObject */ +static void +settings_connection_interface_init (NMSettingsConnectionInterface *iface) +{ + parent_settings_connection_iface = g_type_interface_peek_parent (iface); + iface->update = update; + iface->delete = do_delete; +} + static void nm_keyfile_connection_init (NMKeyfileConnection *connection) { @@ -121,8 +129,9 @@ constructor (GType type, { GObject *object; NMKeyfileConnectionPrivate *priv; - NMConnection *wrapped; NMSettingConnection *s_con; + NMConnection *tmp; + GHashTable *settings; object = G_OBJECT_CLASS (nm_keyfile_connection_parent_class)->constructor (type, n_construct_params, construct_params); @@ -131,17 +140,21 @@ constructor (GType type, priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (object); - if (!priv->filename) { - g_warning ("Keyfile file name not provided."); - goto err; - } + g_assert (priv->filename); - wrapped = connection_from_file (priv->filename); - if (!wrapped) - goto err; + tmp = connection_from_file (priv->filename); + if (!tmp) { + g_object_unref (object); + return NULL; + } + + settings = nm_connection_to_hash (tmp); + nm_connection_replace_settings (NM_CONNECTION (object), settings, NULL); + g_hash_table_destroy (settings); + g_object_unref (tmp); /* if for some reason the connection didn't have a UUID, add one */ - s_con = (NMSettingConnection *) nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (object), NM_TYPE_SETTING_CONNECTION); if (s_con && !nm_setting_connection_get_uuid (s_con)) { GError *error = NULL; char *uuid; @@ -150,23 +163,16 @@ constructor (GType type, g_object_set (s_con, NM_SETTING_CONNECTION_UUID, uuid, NULL); g_free (uuid); - if (!write_connection (wrapped, KEYFILE_DIR, 0, 0, NULL, &error)) { + if (!write_connection (NM_CONNECTION (object), KEYFILE_DIR, 0, 0, NULL, &error)) { g_warning ("Couldn't update connection %s with a UUID: (%d) %s", - nm_setting_connection_get_id (s_con), error ? error->code : 0, - error ? error->message : "unknown"); + nm_setting_connection_get_id (s_con), + error ? error->code : 0, + (error && error->message) ? error->message : "unknown"); g_error_free (error); } } - g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); - g_object_unref (wrapped); - return object; - - err: - g_object_unref (object); - - return NULL; } static void @@ -174,6 +180,8 @@ finalize (GObject *object) { NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (object); + nm_connection_clear_secrets (NM_CONNECTION (object)); + g_free (priv->filename); G_OBJECT_CLASS (nm_keyfile_connection_parent_class)->finalize (object); @@ -216,7 +224,6 @@ static void nm_keyfile_connection_class_init (NMKeyfileConnectionClass *keyfile_connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (keyfile_connection_class); - NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (keyfile_connection_class); g_type_class_add_private (keyfile_connection_class, sizeof (NMKeyfileConnectionPrivate)); @@ -226,9 +233,6 @@ nm_keyfile_connection_class_init (NMKeyfileConnectionClass *keyfile_connection_c object_class->get_property = get_property; object_class->finalize = finalize; - connection_class->update = update; - connection_class->do_delete = do_delete; - /* Properties */ g_object_class_install_property (object_class, PROP_FILENAME, diff --git a/system-settings/plugins/keyfile/plugin.c b/system-settings/plugins/keyfile/plugin.c index f981f34e37..37908c5a78 100644 --- a/system-settings/plugins/keyfile/plugin.c +++ b/system-settings/plugins/keyfile/plugin.c @@ -112,15 +112,13 @@ find_by_uuid (gpointer key, gpointer data, gpointer user_data) { NMKeyfileConnection *keyfile = NM_KEYFILE_CONNECTION (data); FindByUUIDInfo *info = user_data; - NMConnection *connection; NMSettingConnection *s_con; const char *uuid; if (info->found) return; - connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (keyfile)); - s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (keyfile), NM_TYPE_SETTING_CONNECTION); uuid = s_con ? nm_setting_connection_get_uuid (s_con) : NULL; if (uuid && !strcmp (info->uuid, uuid)) @@ -128,17 +126,15 @@ find_by_uuid (gpointer key, gpointer data, gpointer user_data) } static void -update_connection_settings (NMExportedConnection *orig, - NMExportedConnection *new) +update_connection_settings (NMConnection *orig, + NMConnection *new) { - NMConnection *wrapped; GHashTable *new_settings; GError *error = NULL; - new_settings = nm_connection_to_hash (nm_exported_connection_get_connection (new)); - wrapped = nm_exported_connection_get_connection (orig); - if (nm_connection_replace_settings (wrapped, new_settings, &error)) - nm_exported_connection_signal_updated (orig, new_settings); + new_settings = nm_connection_to_hash (new); + if (nm_connection_replace_settings (orig, new_settings, &error)) + nm_settings_connection_interface_emit_updated (NM_SETTINGS_CONNECTION_INTERFACE (orig)); else { g_warning ("%s: '%s' / '%s' invalid: %d", __func__, @@ -146,7 +142,7 @@ update_connection_settings (NMExportedConnection *orig, (error && error->message) ? error->message : "(none)", error ? error->code : -1); g_clear_error (&error); - nm_exported_connection_signal_removed (orig); + g_signal_emit_by_name (orig, "removed"); } g_hash_table_destroy (new_settings); @@ -175,7 +171,7 @@ dir_changed (GFileMonitor *monitor, /* Removing from the hash table should drop the last reference */ g_object_ref (connection); g_hash_table_remove (priv->hash, name); - nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection)); + g_signal_emit_by_name (connection, "removed"); g_object_unref (connection); } break; @@ -183,18 +179,17 @@ dir_changed (GFileMonitor *monitor, case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: if (connection) { /* Update */ - NMExportedConnection *tmp; + NMKeyfileConnection *tmp; - tmp = (NMExportedConnection *) nm_keyfile_connection_new (name); + tmp = (NMKeyfileConnection *) nm_keyfile_connection_new (name); if (tmp) { - update_connection_settings (NM_EXPORTED_CONNECTION (connection), tmp); + update_connection_settings (NM_CONNECTION (connection), NM_CONNECTION (tmp)); g_object_unref (tmp); } } else { /* New */ connection = nm_keyfile_connection_new (name); if (connection) { - NMConnection *tmp; NMSettingConnection *s_con; const char *connection_uuid; NMKeyfileConnection *found = NULL; @@ -202,8 +197,7 @@ dir_changed (GFileMonitor *monitor, /* Connection renames will show up as different files but with * the same UUID. Try to find the original connection. */ - tmp = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection)); - s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION); + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION); connection_uuid = s_con ? nm_setting_connection_get_uuid (s_con) : NULL; if (connection_uuid) { @@ -228,8 +222,8 @@ dir_changed (GFileMonitor *monitor, /* Updating settings should update the NMKeyfileConnection's * filename property too. */ - update_connection_settings (NM_EXPORTED_CONNECTION (found), - NM_EXPORTED_CONNECTION (connection)); + update_connection_settings (NM_CONNECTION (found), + NM_CONNECTION (connection)); /* Re-insert the connection back into the hash with the new filename */ g_hash_table_insert (priv->hash, @@ -242,7 +236,7 @@ dir_changed (GFileMonitor *monitor, g_hash_table_insert (priv->hash, (gpointer) nm_keyfile_connection_get_filename (connection), connection); - g_signal_emit_by_name (config, "connection-added", connection); + g_signal_emit_by_name (config, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection); } } } @@ -269,7 +263,7 @@ conf_file_changed (GFileMonitor *monitor, case G_FILE_MONITOR_EVENT_DELETED: case G_FILE_MONITOR_EVENT_CREATED: case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - g_signal_emit_by_name (self, "unmanaged-devices-changed"); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); /* hostname */ tmp = plugin_get_hostname (self); From 890866bef956bdca9317abdb2e033a8e3c5872e2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 10 Aug 2009 23:25:11 -0500 Subject: [PATCH 02/30] system-settings: clean up settings service classes Make NMSettingsService implement most of the NMSettingsInterface API to make subclasses simpler, and consolidate exporting of NMExportedConnection subclasses in NMSettingsService instead of in 3 places. Make NMSysconfigSettings a subclass of NMSettingsService and save a ton of code. --- introspection/nm-settings-system.xml | 13 -- libnm-glib/libnm_glib.ver | 1 + libnm-glib/nm-exported-connection.c | 122 +------------ libnm-glib/nm-exported-connection.h | 7 +- libnm-glib/nm-settings-service.c | 108 ++++++++++-- libnm-glib/nm-settings-service.h | 12 +- src/nm-manager.c | 7 +- src/system-settings/nm-sysconfig-connection.c | 1 - src/system-settings/nm-sysconfig-settings.c | 166 +++++------------- src/system-settings/nm-sysconfig-settings.h | 6 +- system-settings/plugins/ifcfg-rh/plugin.c | 2 - 11 files changed, 162 insertions(+), 283 deletions(-) diff --git a/introspection/nm-settings-system.xml b/introspection/nm-settings-system.xml index d03b8dddb8..ff98719f8f 100644 --- a/introspection/nm-settings-system.xml +++ b/introspection/nm-settings-system.xml @@ -6,19 +6,6 @@ Implemented by the system settings service to provide additional settings to NetworkManager. - - - DEPRECATED. Adds new connection. - - - - - - Connection properties. - - - - Save the hostname to persistent configuration. diff --git a/libnm-glib/libnm_glib.ver b/libnm-glib/libnm_glib.ver index ef79722748..7946e60121 100644 --- a/libnm-glib/libnm_glib.ver +++ b/libnm-glib/libnm_glib.ver @@ -120,6 +120,7 @@ global: nm_settings_interface_get_type; nm_settings_interface_list_connections; nm_settings_service_export; + nm_settings_service_export_connection; nm_settings_service_get_connection_by_path; nm_settings_service_get_type; nm_settings_system_interface_get_type; diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c index 57dde41442..8753224d49 100644 --- a/libnm-glib/nm-exported-connection.c +++ b/libnm-glib/nm-exported-connection.c @@ -51,41 +51,12 @@ G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION) NMExportedConnectionPrivate)) typedef struct { - DBusGConnection *bus; - gboolean disposed; + gboolean foo; } NMExportedConnectionPrivate; -enum { - PROP_0, - PROP_BUS, - - LAST_PROP -}; - /**************************************************************/ -void -nm_exported_connection_export (NMExportedConnection *self) -{ - NMExportedConnectionPrivate *priv; - static guint32 ec_counter = 0; - char *path; - - g_return_if_fail (self != NULL); - g_return_if_fail (NM_IS_EXPORTED_CONNECTION (self)); - - priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (self); - - /* Don't allow exporting twice */ - g_return_if_fail (nm_connection_get_path (NM_CONNECTION (self)) == NULL); - - path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); - nm_connection_set_path (NM_CONNECTION (self), path); - dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (self)); - g_free (path); -} - static GHashTable * real_get_settings (NMExportedConnection *self, GError **error) { @@ -183,124 +154,35 @@ impl_exported_connection_get_secrets (NMExportedConnection *self, /** * nm_exported_connection_new: - * @bus: a valid and connected D-Bus connection * @scope: the Connection scope (either user or system) - * @path: the D-Bus path of the connection as exported by the settings service - * indicated by @scope * * Creates a new object representing the remote connection. * * Returns: the new exported connection object on success, or %NULL on failure **/ NMExportedConnection * -nm_exported_connection_new (DBusGConnection *bus, - NMConnectionScope scope) +nm_exported_connection_new (NMConnectionScope scope) { - g_return_val_if_fail (bus != NULL, NULL); g_return_val_if_fail (scope != NM_CONNECTION_SCOPE_UNKNOWN, NULL); return (NMExportedConnection *) g_object_new (NM_TYPE_EXPORTED_CONNECTION, - NM_EXPORTED_CONNECTION_BUS, bus, NM_CONNECTION_SCOPE, scope, NULL); } -static GObject * -constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) -{ - GObject *object; - NMExportedConnectionPrivate *priv; - - object = G_OBJECT_CLASS (nm_exported_connection_parent_class)->constructor (type, n_construct_params, construct_params); - if (!object) - return NULL; - - priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - g_assert (priv->bus); - - return object; -} - static void nm_exported_connection_init (NMExportedConnection *self) { } -static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) -{ - NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_BUS: - /* Construct only */ - priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) -{ - NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_BUS: - g_value_set_boxed (value, priv->bus); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -dispose (GObject *object) -{ - NMExportedConnectionPrivate *priv = NM_EXPORTED_CONNECTION_GET_PRIVATE (object); - - if (!priv->disposed) { - priv->disposed = TRUE; - dbus_g_connection_unref (priv->bus); - } - - G_OBJECT_CLASS (nm_exported_connection_parent_class)->dispose (object); -} - static void nm_exported_connection_class_init (NMExportedConnectionClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (class); - g_type_class_add_private (class, sizeof (NMExportedConnectionPrivate)); /* Virtual methods */ - object_class->dispose = dispose; - object_class->constructor = constructor; - object_class->get_property = get_property; - object_class->set_property = set_property; - class->get_settings = real_get_settings; - /** - * NMExportedConnection:bus: - * - * The %DBusGConnection which this object is exported on - **/ - g_object_class_install_property (object_class, PROP_BUS, - g_param_spec_boxed (NM_EXPORTED_CONNECTION_BUS, - "Bus", - "Bus", - DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), &dbus_glib_nm_exported_connection_object_info); } diff --git a/libnm-glib/nm-exported-connection.h b/libnm-glib/nm-exported-connection.h index 79c7f80c39..7455d4c8a7 100644 --- a/libnm-glib/nm-exported-connection.h +++ b/libnm-glib/nm-exported-connection.h @@ -33,8 +33,6 @@ G_BEGIN_DECLS #define NM_IS_EXPORTED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_EXPORTED_CONNECTION)) #define NM_EXPORTED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_EXPORTED_CONNECTION, NMExportedConnectionClass)) -#define NM_EXPORTED_CONNECTION_BUS "bus" - typedef struct { NMConnection parent; } NMExportedConnection; @@ -61,10 +59,7 @@ typedef struct { GType nm_exported_connection_get_type (void); -NMExportedConnection *nm_exported_connection_new (DBusGConnection *bus, - NMConnectionScope scope); - -void nm_exported_connection_export (NMExportedConnection *self); +NMExportedConnection *nm_exported_connection_new (NMConnectionScope scope); G_END_DECLS diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c index c8e1d4ce50..e05c3bc48c 100644 --- a/libnm-glib/nm-settings-service.c +++ b/libnm-glib/nm-settings-service.c @@ -19,6 +19,7 @@ * (C) Copyright 2008 - 2009 Red Hat, Inc. */ +#include #include #include @@ -115,11 +116,18 @@ impl_settings_list_connections (NMSettingsService *self, static NMSettingsConnectionInterface * get_connection_by_path (NMSettingsInterface *settings, const char *path) { - NMExportedConnection *connection; + NMExportedConnection *connection = NULL; + GSList *list = NULL, *iter; + + list = list_connections (settings); + for (iter = list; iter; iter = g_slist_next (iter)) { + if (!strcmp (nm_connection_get_path (NM_CONNECTION (iter->data)), path)) { + connection = NM_EXPORTED_CONNECTION (iter->data); + break; + } + } + g_slist_free (list); - /* Must always be implemented */ - g_assert (NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path); - connection = NM_SETTINGS_SERVICE_GET_CLASS (settings)->get_connection_by_path (NM_SETTINGS_SERVICE (settings), path); return (NMSettingsConnectionInterface *) connection; } @@ -133,6 +141,48 @@ nm_settings_service_get_connection_by_path (NMSettingsService *self, return (NMExportedConnection *) get_connection_by_path (NM_SETTINGS_INTERFACE (self), path); } +static gboolean +add_connection (NMSettingsInterface *settings, + NMSettingsConnectionInterface *connection, + NMSettingsAddConnectionFunc callback, + gpointer user_data) +{ + NMSettingsService *self = NM_SETTINGS_SERVICE (settings); + GError *error = NULL; + gboolean success = FALSE; + + if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) { + NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self), + connection, + NULL, + callback, + user_data); + success = TRUE; + } else { + error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, + "%s: %s:%d add_connection() not implemented", + __func__, __FILE__, __LINE__); + callback (settings, error, user_data); + g_error_free (error); + } + + return success; +} + +static void +dbus_add_connection_cb (NMSettingsInterface *settings, + GError *error, + gpointer user_data) +{ + DBusGMethodInvocation *context = user_data; + + if (error) + dbus_g_method_return_error (context, error); + else + dbus_g_method_return (context); +} + static void impl_settings_add_connection (NMSettingsService *self, GHashTable *settings, @@ -149,11 +199,14 @@ impl_settings_add_connection (NMSettingsService *self, g_error_free (error); return; } - g_object_unref (tmp); - if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) - NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (self, settings, context); - else { + if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) { + NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self), + NM_SETTINGS_CONNECTION_INTERFACE (tmp), + context, + dbus_add_connection_cb, + context); + } else { error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, "%s: %s:%d add_connection() not implemented", @@ -161,6 +214,30 @@ impl_settings_add_connection (NMSettingsService *self, dbus_g_method_return_error (context, error); g_error_free (error); } + + g_object_unref (tmp); +} + +void +nm_settings_service_export_connection (NMSettingsService *self, + NMSettingsConnectionInterface *connection) +{ + NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (self); + static guint32 ec_counter = 0; + char *path; + + g_return_if_fail (connection != NULL); + g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); + + /* Don't allow exporting twice */ + g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL); + + path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); + nm_connection_set_path (NM_CONNECTION (connection), path); + nm_connection_set_scope (NM_CONNECTION (connection), priv->scope); + + dbus_g_connection_register_g_object (priv->bus, path, G_OBJECT (connection)); + g_free (path); } /**************************************************************/ @@ -171,6 +248,10 @@ settings_interface_init (NMSettingsInterface *iface) /* interface implementation */ iface->list_connections = list_connections; iface->get_connection_by_path = get_connection_by_path; + iface->add_connection = add_connection; + + dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), + &dbus_glib_nm_settings_object_info); } static GObject * @@ -181,8 +262,10 @@ constructor (GType type, GObject *object; object = G_OBJECT_CLASS (nm_settings_service_parent_class)->constructor (type, n_construct_params, construct_params); - if (object) + if (object) { g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->scope != NM_CONNECTION_SCOPE_UNKNOWN); + g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->bus != NULL); + } return object; } @@ -196,11 +279,14 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { NMSettingsServicePrivate *priv = NM_SETTINGS_SERVICE_GET_PRIVATE (object); + DBusGConnection *bus; switch (prop_id) { case PROP_BUS: /* Construct only */ - priv->bus = dbus_g_connection_ref ((DBusGConnection *) g_value_get_boxed (value)); + bus = g_value_get_boxed (value); + if (bus) + priv->bus = dbus_g_connection_ref (bus); break; case PROP_SCOPE: /* Construct only */ @@ -277,9 +363,9 @@ nm_settings_service_class_init (NMSettingsServiceClass *class) g_param_spec_uint (NM_SETTINGS_SERVICE_SCOPE, "Scope", "Scope", - NM_CONNECTION_SCOPE_USER, NM_CONNECTION_SCOPE_SYSTEM, NM_CONNECTION_SCOPE_USER, + NM_CONNECTION_SCOPE_USER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), diff --git a/libnm-glib/nm-settings-service.h b/libnm-glib/nm-settings-service.h index 2a6bb86aa2..b8d93a7162 100644 --- a/libnm-glib/nm-settings-service.h +++ b/libnm-glib/nm-settings-service.h @@ -51,12 +51,11 @@ typedef struct { */ GSList * (*list_connections) (NMSettingsService *self); - NMExportedConnection * (*get_connection_by_path) (NMSettingsService *self, - const char *path); - void (*add_connection) (NMSettingsService *self, - GHashTable *settings, - DBusGMethodInvocation *context); + NMSettingsConnectionInterface *connection, + DBusGMethodInvocation *context, /* Only present for D-Bus calls */ + NMSettingsAddConnectionFunc callback, + gpointer user_data); } NMSettingsServiceClass; GType nm_settings_service_get_type (void); @@ -66,6 +65,9 @@ NMExportedConnection *nm_settings_service_get_connection_by_path (NMSettingsServ void nm_settings_service_export (NMSettingsService *self); +void nm_settings_service_export_connection (NMSettingsService *self, + NMSettingsConnectionInterface *exported); + G_END_DECLS #endif /* NM_SETTINGS_SERVICE_H */ diff --git a/src/nm-manager.c b/src/nm-manager.c index 9442db71a6..28a5f86843 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -2508,6 +2508,7 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error) { static NMManager *singleton = NULL; NMManagerPrivate *priv; + DBusGConnection *bus; if (singleton) return g_object_ref (singleton); @@ -2517,11 +2518,15 @@ nm_manager_get (const char *config_file, const char *plugins, GError **error) priv = NM_MANAGER_GET_PRIVATE (singleton); - priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, error); + bus = nm_dbus_manager_get_connection (priv->dbus_mgr); + g_assert (bus); + + priv->sys_settings = nm_sysconfig_settings_new (config_file, plugins, bus, error); if (!priv->sys_settings) { g_object_unref (singleton); return NULL; } + nm_settings_service_export (NM_SETTINGS_SERVICE (priv->sys_settings)); priv->config_file = g_strdup (config_file); diff --git a/src/system-settings/nm-sysconfig-connection.c b/src/system-settings/nm-sysconfig-connection.c index 4dbef0daf5..db197a3f28 100644 --- a/src/system-settings/nm-sysconfig-connection.c +++ b/src/system-settings/nm-sysconfig-connection.c @@ -41,7 +41,6 @@ G_DEFINE_TYPE_EXTENDED (NMSysconfigConnection, nm_sysconfig_connection, NM_TYPE_ NMSysconfigConnectionPrivate)) typedef struct { - DBusGConnection *bus; PolkitAuthority *authority; } NMSysconfigConnectionPrivate; diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 64259d83c1..e586669df4 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -43,7 +43,6 @@ #include "nm-dbus-glib-types.h" #include "nm-sysconfig-settings.h" #include "nm-sysconfig-connection.h" -#include "nm-dbus-manager.h" #include "nm-polkit-helpers.h" #include "nm-system-config-error.h" #include "nm-utils.h" @@ -67,25 +66,15 @@ static void claim_connection (NMSysconfigSettings *self, NMSettingsConnectionInterface *connection, gboolean do_export); -static gboolean impl_settings_list_connections (NMSysconfigSettings *self, - GPtrArray **connections, - GError **error); - -static void impl_settings_add_connection (NMSysconfigSettings *self, - GHashTable *settings, - DBusGMethodInvocation *context); - static void impl_settings_save_hostname (NMSysconfigSettings *self, const char *hostname, DBusGMethodInvocation *context); -#include "nm-settings-glue.h" #include "nm-settings-system-glue.h" static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); typedef struct { - NMDBusManager *dbus_mgr; PolkitAuthority *authority; char *config_file; @@ -96,13 +85,9 @@ typedef struct { char *orig_hostname; } NMSysconfigSettingsPrivate; -static void settings_interface_init (NMSettingsInterface *klass); - static void settings_system_interface_init (NMSettingsSystemInterface *klass); -G_DEFINE_TYPE_WITH_CODE (NMSysconfigSettings, nm_sysconfig_settings, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_INTERFACE, - settings_interface_init) +G_DEFINE_TYPE_WITH_CODE (NMSysconfigSettings, nm_sysconfig_settings, NM_TYPE_SETTINGS_SERVICE, G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, settings_system_interface_init)) @@ -157,50 +142,20 @@ load_connections (NMSysconfigSettings *self) unmanaged_specs_changed (NULL, self); } -static gboolean -impl_settings_list_connections (NMSysconfigSettings *self, - GPtrArray **connections, - GError **error) +static GSList * +list_connections (NMSettingsService *settings) { - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (settings); GHashTableIter iter; gpointer key; + GSList *list = NULL; - load_connections (self); - - *connections = g_ptr_array_sized_new (g_hash_table_size (priv->connections)); + load_connections (NM_SYSCONFIG_SETTINGS (settings)); g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, &key, NULL)) { - NMSettingsConnectionInterface *connection = key; - char *path = NULL; - - g_object_get (G_OBJECT (connection), NM_SETTINGS_CONNECTION_INTERFACE_PATH, &path, NULL); - g_assert (path); - g_ptr_array_add (*connections, path); - } - return TRUE; -} - -static NMSettingsConnectionInterface * -get_connection_by_path (NMSettingsInterface *self, - const char *path) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GHashTableIter iter; - gpointer key; - - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, &key, NULL)) { - NMConnection *candidate = NM_CONNECTION (key); - const char *candidate_path; - - candidate_path = nm_connection_get_path (candidate); - g_assert (candidate_path); - if (!strcmp (path, candidate_path)) - return NM_SETTINGS_CONNECTION_INTERFACE (candidate); - } - return NULL; + while (g_hash_table_iter_next (&iter, &key, NULL)) + list = g_slist_prepend (list, NM_EXPORTED_CONNECTION (key)); + return g_slist_reverse (list); } static void @@ -514,28 +469,6 @@ connection_removed (NMSettingsConnectionInterface *connection, g_hash_table_remove (priv->connections, connection); } -static void -export_connection (NMSysconfigSettings *self, - NMSettingsConnectionInterface *connection) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - static guint32 ec_counter = 0; - char *path; - DBusGConnection *bus; - - g_return_if_fail (connection != NULL); - g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); - - path = g_strdup_printf ("%s/%u", NM_DBUS_PATH_SETTINGS, ec_counter++); - nm_connection_set_path (NM_CONNECTION (connection), path); - nm_connection_set_scope (NM_CONNECTION (connection), NM_CONNECTION_SCOPE_SYSTEM); - - bus = nm_dbus_manager_get_connection (priv->dbus_mgr); - dbus_g_connection_register_g_object (bus, path, G_OBJECT (connection)); - - g_free (path); -} - static void claim_connection (NMSysconfigSettings *self, NMSettingsConnectionInterface *connection, @@ -554,7 +487,7 @@ claim_connection (NMSysconfigSettings *self, g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self); if (do_export) { - export_connection (self, connection); + nm_settings_service_export_connection (NM_SETTINGS_SERVICE (self), connection); g_signal_emit_by_name (self, "new-connection", connection); } } @@ -582,6 +515,9 @@ typedef struct { GCancellable *cancellable; NMConnection *connection; + NMSettingsAddConnectionFunc callback; + gpointer callback_data; + char *hostname; } PolkitCall; @@ -589,6 +525,8 @@ static PolkitCall * polkit_call_new (NMSysconfigSettings *self, DBusGMethodInvocation *context, NMConnection *connection, + NMSettingsAddConnectionFunc callback, + gpointer callback_data, const char *hostname) { PolkitCall *call; @@ -600,7 +538,12 @@ polkit_call_new (NMSysconfigSettings *self, call = g_malloc0 (sizeof (PolkitCall)); call->self = self; call->context = context; - call->connection = connection; + if (connection) + call->connection = g_object_ref (connection); + if (callback) { + call->callback = callback; + call->callback_data = callback_data; + } if (hostname) call->hostname = g_strdup (hostname); call->cancellable = g_cancellable_new (); @@ -668,7 +611,7 @@ pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data) &error); /* Some random error happened */ if (error) { - dbus_g_method_return_error (call->context, error); + call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); goto out; } @@ -677,20 +620,20 @@ pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data) error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, NM_SYSCONFIG_SETTINGS_ERROR_NOT_PRIVILEGED, "Insufficient privileges."); - dbus_g_method_return_error (call->context, error); + call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); goto out; } - if (add_new_connection (self, call->connection, &add_error)) { - dbus_g_method_return (call->context); - } else { + if (add_new_connection (self, call->connection, &add_error)) + call->callback (NM_SETTINGS_INTERFACE (self), NULL, call->callback_data); + else { error = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, "Saving connection failed: (%d) %s", add_error ? add_error->code : -1, (add_error && add_error->message) ? add_error->message : "(unknown)"); g_error_free (add_error); - dbus_g_method_return_error (call->context, error); + call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); } out: @@ -701,13 +644,15 @@ out: } static void -impl_settings_add_connection (NMSysconfigSettings *self, - GHashTable *settings, - DBusGMethodInvocation *context) +add_connection (NMSettingsService *service, + NMSettingsConnectionInterface *connection, + DBusGMethodInvocation *context, /* Only present for D-Bus calls */ + NMSettingsAddConnectionFunc callback, + gpointer user_data) { + NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (service); NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); PolkitCall *call; - NMConnection *tmp; GError *error = NULL; /* Do any of the plugins support adding? */ @@ -715,21 +660,12 @@ impl_settings_add_connection (NMSysconfigSettings *self, error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, NM_SYSCONFIG_SETTINGS_ERROR_ADD_NOT_SUPPORTED, "None of the registered plugins support add."); - dbus_g_method_return_error (context, error); + callback (NM_SETTINGS_INTERFACE (service), error, user_data); g_error_free (error); return; } - /* Check if the settings are valid first */ - tmp = nm_connection_new_from_hash (settings, &error); - if (!tmp) { - g_assert (error); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - call = polkit_call_new (self, context, tmp, NULL); + call = polkit_call_new (self, context, NM_CONNECTION (connection), callback, user_data, NULL); g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, @@ -816,7 +752,7 @@ impl_settings_save_hostname (NMSysconfigSettings *self, return; } - call = polkit_call_new (self, context, NULL, hostname); + call = polkit_call_new (self, context, NULL, NULL, NULL, hostname); g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, @@ -1123,13 +1059,16 @@ nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *devic NMSysconfigSettings * nm_sysconfig_settings_new (const char *config_file, const char *plugins, + DBusGConnection *bus, GError **error) { NMSysconfigSettings *self; NMSysconfigSettingsPrivate *priv; - DBusGConnection *g_connection; - self = g_object_new (NM_TYPE_SYSCONFIG_SETTINGS, NULL); + self = g_object_new (NM_TYPE_SYSCONFIG_SETTINGS, + NM_SETTINGS_SERVICE_BUS, bus, + NM_SETTINGS_SERVICE_SCOPE, NM_CONNECTION_SCOPE_SYSTEM, + NULL); if (!self) return NULL; @@ -1137,12 +1076,6 @@ nm_sysconfig_settings_new (const char *config_file, priv->config_file = g_strdup (config_file); - priv->dbus_mgr = nm_dbus_manager_get (); - g_assert (priv->dbus_mgr); - - g_connection = nm_dbus_manager_get_connection (priv->dbus_mgr); - dbus_g_connection_register_g_object (g_connection, NM_DBUS_PATH_SETTINGS, G_OBJECT (self)); - if (plugins) { /* Load the plugins; fail if a plugin is not found. */ if (!load_plugins (self, plugins, error)) { @@ -1172,23 +1105,12 @@ finalize (GObject *object) if (priv->authority) g_object_unref (priv->authority); - g_object_unref (priv->dbus_mgr); - g_free (priv->orig_hostname); g_free (priv->config_file); G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object); } -static void -settings_interface_init (NMSettingsInterface *iface) -{ - iface->get_connection_by_path = get_connection_by_path; - - dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), - &dbus_glib_nm_settings_object_info); -} - static void settings_system_interface_init (NMSettingsSystemInterface *iface) { @@ -1231,6 +1153,7 @@ static void nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); + NMSettingsServiceClass *ss_class = NM_SETTINGS_SERVICE_CLASS (class); g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate)); @@ -1238,6 +1161,8 @@ nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) object_class->notify = notify; object_class->get_property = get_property; object_class->finalize = finalize; + ss_class->list_connections = list_connections; + ss_class->add_connection = add_connection; /* properties */ g_object_class_install_property @@ -1266,9 +1191,6 @@ nm_sysconfig_settings_class_init (NMSysconfigSettingsClass *class) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_VARIANT); - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), - &dbus_glib_nm_settings_object_info); - dbus_g_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR, NM_DBUS_IFACE_SETTINGS_SYSTEM, NM_TYPE_SYSCONFIG_SETTINGS_ERROR); diff --git a/src/system-settings/nm-sysconfig-settings.h b/src/system-settings/nm-sysconfig-settings.h index badb6442e9..ae2ba68329 100644 --- a/src/system-settings/nm-sysconfig-settings.h +++ b/src/system-settings/nm-sysconfig-settings.h @@ -27,6 +27,7 @@ #define __NM_SYSCONFIG_SETTINGS_H__ #include +#include #include "nm-sysconfig-connection.h" #include "nm-system-config-interface.h" @@ -42,11 +43,11 @@ #define NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS "unmanaged-specs" typedef struct { - GObject parent_instance; + NMSettingsService parent_instance; } NMSysconfigSettings; typedef struct { - GObjectClass parent_class; + NMSettingsServiceClass parent_class; /* Signals */ void (*properties_changed) (NMSysconfigSettings *self, GHashTable *properties); @@ -56,6 +57,7 @@ GType nm_sysconfig_settings_get_type (void); NMSysconfigSettings *nm_sysconfig_settings_new (const char *config_file, const char *plugins, + DBusGConnection *bus, GError **error); const GSList *nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self); diff --git a/system-settings/plugins/ifcfg-rh/plugin.c b/system-settings/plugins/ifcfg-rh/plugin.c index f861aebebd..c8d37322cc 100644 --- a/system-settings/plugins/ifcfg-rh/plugin.c +++ b/system-settings/plugins/ifcfg-rh/plugin.c @@ -31,8 +31,6 @@ #include #include -#include - #include #ifndef NO_GIO From 155f19cb2a7ec066502b8da4c8091b39ef5ab239 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 10 Aug 2009 23:39:08 -0500 Subject: [PATCH 03/30] libnm-glib: don't require a bus connection at construction time --- libnm-glib/nm-settings-service.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c index e05c3bc48c..0245cb1ae1 100644 --- a/libnm-glib/nm-settings-service.c +++ b/libnm-glib/nm-settings-service.c @@ -228,6 +228,7 @@ nm_settings_service_export_connection (NMSettingsService *self, g_return_if_fail (connection != NULL); g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); + g_return_if_fail (priv->bus != NULL); /* Don't allow exporting twice */ g_return_if_fail (nm_connection_get_path (NM_CONNECTION (connection)) == NULL); @@ -264,7 +265,6 @@ constructor (GType type, object = G_OBJECT_CLASS (nm_settings_service_parent_class)->constructor (type, n_construct_params, construct_params); if (object) { g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->scope != NM_CONNECTION_SCOPE_UNKNOWN); - g_assert (NM_SETTINGS_SERVICE_GET_PRIVATE (object)->bus != NULL); } return object; } @@ -324,7 +324,8 @@ dispose (GObject *object) if (!priv->disposed) { priv->disposed = TRUE; - dbus_g_connection_unref (priv->bus); + if (priv->bus) + dbus_g_connection_unref (priv->bus); } G_OBJECT_CLASS (nm_settings_service_parent_class)->dispose (object); From 71507c9fa3be2be587816061f5f08bd97c228268 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 10 Aug 2009 23:52:03 -0500 Subject: [PATCH 04/30] system-settings: fix issues with system settings service property types --- libnm-glib/nm-settings-system-interface.c | 10 +++++----- src/system-settings/nm-sysconfig-settings.c | 6 ++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/libnm-glib/nm-settings-system-interface.c b/libnm-glib/nm-settings-system-interface.c index c563eb17a7..07114c0fc0 100644 --- a/libnm-glib/nm-settings-system-interface.c +++ b/libnm-glib/nm-settings-system-interface.c @@ -75,11 +75,11 @@ nm_settings_system_interface_init (gpointer g_iface) g_object_interface_install_property (g_iface, - g_param_spec_string (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY, - "CanModify", - "Can modify anything (hostname, connections, etc)", - NULL, - G_PARAM_READABLE)); + g_param_spec_boolean (NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY, + "CanModify", + "Can modify anything (hostname, connections, etc)", + FALSE, + G_PARAM_READABLE)); initialized = TRUE; } diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index e586669df4..ceef21b36d 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -104,8 +104,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, PROP_UNMANAGED_SPECS, - PROP_HOSTNAME, - PROP_CAN_MODIFY, LAST_PROP }; @@ -1133,14 +1131,14 @@ get_property (GObject *object, guint prop_id, copy = g_slist_append (copy, g_strdup (iter->data)); g_value_take_boxed (value, copy); break; - case PROP_HOSTNAME: + case NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME: g_value_take_string (value, nm_sysconfig_settings_get_hostname (self)); /* Don't ever pass NULL through D-Bus */ if (!g_value_get_string (value)) g_value_set_static_string (value, ""); break; - case PROP_CAN_MODIFY: + case NM_SETTINGS_SYSTEM_INTERFACE_PROP_CAN_MODIFY: g_value_set_boolean (value, !!get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)); break; default: From 27d425d853748ea3e09cffc0e53c381d50ecca6f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 00:01:53 -0500 Subject: [PATCH 05/30] libnm-glib: fix signal marshaller type --- libnm-glib/nm-remote-settings-system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index 9dcca659e0..fb9b0e2abc 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -173,7 +173,7 @@ constructor (GType type, NM_DBUS_IFACE_SETTINGS_SYSTEM); g_assert (priv->proxy); - dbus_g_object_register_marshaller (_nm_marshal_VOID__STRING_BOXED, + dbus_g_object_register_marshaller (g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, DBUS_TYPE_G_MAP_OF_VARIANT, G_TYPE_INVALID); From ce7ebaa7f91f5e771802b0731afc153d975ac453 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 00:02:05 -0500 Subject: [PATCH 06/30] libnm-util: ensure NMConnection scope & path can be set on construction --- libnm-util/nm-connection.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index 7dcb310e96..5a56758fd8 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -1172,7 +1172,7 @@ nm_connection_class_init (NMConnectionClass *klass) NM_CONNECTION_SCOPE_UNKNOWN, NM_CONNECTION_SCOPE_USER, NM_CONNECTION_SCOPE_UNKNOWN, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * NMConnection:path: @@ -1186,7 +1186,7 @@ nm_connection_class_init (NMConnectionClass *klass) "Path", "Path", NULL, - G_PARAM_READWRITE)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /* Signals */ From 4fb162e7548d073b4c98c1d0e7bffd4b1089634d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 00:11:36 -0500 Subject: [PATCH 07/30] libnm-glib: implement stub update & delete functions --- libnm-glib/nm-exported-connection.c | 31 ++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c index 8753224d49..80391de63a 100644 --- a/libnm-glib/nm-exported-connection.c +++ b/libnm-glib/nm-exported-connection.c @@ -44,7 +44,11 @@ static void impl_exported_connection_get_secrets (NMExportedConnection *connecti #include "nm-exported-connection-glue.h" -G_DEFINE_TYPE (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION) +static void settings_connection_interface_init (NMSettingsConnectionInterface *class); + +G_DEFINE_TYPE_EXTENDED (NMExportedConnection, nm_exported_connection, NM_TYPE_CONNECTION, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_CONNECTION_INTERFACE, + settings_connection_interface_init)) #define NM_EXPORTED_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \ NM_TYPE_EXPORTED_CONNECTION, \ @@ -90,6 +94,15 @@ impl_exported_connection_get_settings (NMExportedConnection *self, return *settings ? TRUE : FALSE; } +static gboolean +update (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceUpdateFunc callback, + gpointer user_data) +{ + callback (connection, NULL, user_data); + return TRUE; +} + static void impl_exported_connection_update (NMExportedConnection *self, GHashTable *new_settings, @@ -117,6 +130,15 @@ impl_exported_connection_update (NMExportedConnection *self, } } +static gboolean +do_delete (NMSettingsConnectionInterface *connection, + NMSettingsConnectionInterfaceDeleteFunc callback, + gpointer user_data) +{ + callback (connection, NULL, user_data); + return TRUE; +} + static void impl_exported_connection_delete (NMExportedConnection *self, DBusGMethodInvocation *context) @@ -152,6 +174,13 @@ impl_exported_connection_get_secrets (NMExportedConnection *self, /**************************************************************/ +static void +settings_connection_interface_init (NMSettingsConnectionInterface *iface) +{ + iface->update = update; + iface->delete = do_delete; +} + /** * nm_exported_connection_new: * @scope: the Connection scope (either user or system) From cff9205ebd143deb5781436e88591f44d134adc1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 09:53:34 -0500 Subject: [PATCH 08/30] libnm-glib: remove redundant Scope and Path properties on NMSettingsConnectionInterface Since NMSettingsConnectionInterface already has NM_TYPE_CONNECTION as a prerequisite, which already implements these properties, it's pointless to have them on NMSettingsConnectionInterface too. --- libnm-glib/nm-settings-connection-interface.c | 19 ------------------- libnm-glib/nm-settings-connection-interface.h | 10 ---------- 2 files changed, 29 deletions(-) diff --git a/libnm-glib/nm-settings-connection-interface.c b/libnm-glib/nm-settings-connection-interface.c index 72859c17f7..cc3c4b977e 100644 --- a/libnm-glib/nm-settings-connection-interface.c +++ b/libnm-glib/nm-settings-connection-interface.c @@ -141,25 +141,6 @@ nm_settings_connection_interface_init (gpointer g_iface) if (initialized) return; - /* Properties */ - g_object_interface_install_property - (g_iface, - g_param_spec_string (NM_SETTINGS_CONNECTION_INTERFACE_PATH, - "Path", - "D-Bus path", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_object_interface_install_property - (g_iface, - g_param_spec_uint (NM_SETTINGS_CONNECTION_INTERFACE_SCOPE, - "Scope", - "Connection scope (user, system)", - NM_CONNECTION_SCOPE_UNKNOWN, - NM_CONNECTION_SCOPE_USER, - NM_CONNECTION_SCOPE_USER, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - /* Signals */ g_signal_new ("updated", iface_type, diff --git a/libnm-glib/nm-settings-connection-interface.h b/libnm-glib/nm-settings-connection-interface.h index 6270797af0..e8118bb72e 100644 --- a/libnm-glib/nm-settings-connection-interface.h +++ b/libnm-glib/nm-settings-connection-interface.h @@ -36,16 +36,6 @@ G_BEGIN_DECLS #define NM_IS_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE)) #define NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface)) -#define NM_SETTINGS_CONNECTION_INTERFACE_PATH "path" -#define NM_SETTINGS_CONNECTION_INTERFACE_SCOPE "scope" - -typedef enum { - NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST = 0x1000, - - NM_SETTINGS_CONNECTION_INTERFACE_PROP_PATH = NM_SETTINGS_CONNECTION_INTERFACE_PROP_FIRST, - NM_SETTINGS_CONNECTION_INTERFACE_PROP_SCOPE -} NMSettingsConnectionInterfaceProp; - typedef struct _NMSettingsConnectionInterface NMSettingsConnectionInterface; From cb0303180dfafa9f0cd41e0d7f1f5e4639bd30ed Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 10:33:13 -0500 Subject: [PATCH 09/30] libnm-glib: don't expose NMRemoteConnetions until they are valid Give them time to get their settings from the remote settings service first, then let subclasses/users/whatever know about them. --- libnm-glib/Makefile.am | 1 + libnm-glib/nm-remote-connection.c | 24 +++++++++-- libnm-glib/nm-remote-settings.c | 71 +++++++++++++++++++++++++++++-- 3 files changed, 89 insertions(+), 7 deletions(-) diff --git a/libnm-glib/Makefile.am b/libnm-glib/Makefile.am index 3e14bd750d..2b7dd016fc 100644 --- a/libnm-glib/Makefile.am +++ b/libnm-glib/Makefile.am @@ -84,6 +84,7 @@ libnm_glib_la_SOURCES = \ nm-active-connection.c \ nm-dhcp4-config.c \ nm-remote-connection.c \ + nm-remote-connection-private.h \ nm-settings-interface.c \ nm-settings-system-interface.c \ nm-remote-settings.c \ diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c index 76fdcf0244..65edda1a01 100644 --- a/libnm-glib/nm-remote-connection.c +++ b/libnm-glib/nm-remote-connection.c @@ -27,6 +27,7 @@ #include #include #include "nm-remote-connection.h" +#include "nm-remote-connection-private.h" #include "nm-dbus-glib-types.h" #include "nm-exported-connection-bindings.h" #include "nm-settings-connection-interface.h" @@ -41,6 +42,7 @@ G_DEFINE_TYPE_EXTENDED (NMRemoteConnection, nm_remote_connection, NM_TYPE_CONNEC enum { PROP_0, PROP_BUS, + PROP_INIT_RESULT, LAST_PROP }; @@ -60,6 +62,7 @@ typedef struct { DBusGProxy *secrets_proxy; GSList *calls; + NMRemoteConnectionInitResult init_result; gboolean disposed; } NMRemoteConnectionPrivate; @@ -227,6 +230,7 @@ get_settings_cb (DBusGProxy *proxy, gpointer user_data) { NMRemoteConnection *self = user_data; + NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); if (error) { g_warning ("%s: error getting %s connection %s settings: (%d) %s", @@ -236,9 +240,13 @@ get_settings_cb (DBusGProxy *proxy, error ? error->code : -1, (error && error->message) ? error->message : "(unknown)"); g_error_free (error); + priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_ERROR; + g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT); } else { replace_settings (self, new_settings); g_hash_table_destroy (new_settings); + priv->init_result = NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS; + g_object_notify (G_OBJECT (self), NM_REMOTE_CONNECTION_INIT_RESULT); } } @@ -365,8 +373,8 @@ get_property (GObject *object, guint prop_id, NMRemoteConnectionPrivate *priv = NM_REMOTE_CONNECTION_GET_PRIVATE (self); switch (prop_id) { - case PROP_BUS: - g_value_set_boxed (value, priv->bus); + case PROP_INIT_RESULT: + g_value_set_uint (value, priv->init_result); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -414,6 +422,16 @@ nm_remote_connection_class_init (NMRemoteConnectionClass *remote_class) "DBusGConnection", "DBusGConnection", DBUS_TYPE_G_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property + (object_class, PROP_INIT_RESULT, + g_param_spec_uint (NM_REMOTE_CONNECTION_INIT_RESULT, + "Initialization result (PRIVATE)", + "Initialization result (PRIVATE)", + NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN, + NM_REMOTE_CONNECTION_INIT_RESULT_ERROR, + NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN, + G_PARAM_READABLE)); } diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c index 6a261ace99..ea8fd2664a 100644 --- a/libnm-glib/nm-remote-settings.c +++ b/libnm-glib/nm-remote-settings.c @@ -29,6 +29,7 @@ #include "nm-remote-settings.h" #include "nm-settings-bindings.h" #include "nm-settings-interface.h" +#include "nm-remote-connection-private.h" static void settings_interface_init (NMSettingsInterface *class); @@ -43,6 +44,7 @@ typedef struct { DBusGProxy *proxy; GHashTable *connections; + GHashTable *pending; /* Connections we don't have settings for yet */ DBusGProxy *dbus_proxy; @@ -68,8 +70,58 @@ get_connection_by_path (NMSettingsInterface *settings, const char *path) static void connection_removed_cb (NMRemoteConnection *remote, gpointer user_data) { - g_hash_table_remove (NM_REMOTE_SETTINGS_GET_PRIVATE (user_data)->connections, - nm_connection_get_path (NM_CONNECTION (remote))); + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + const char *path; + + path = nm_connection_get_path (NM_CONNECTION (remote)); + g_hash_table_remove (priv->connections, path); + g_hash_table_remove (priv->pending, path); +} + +static void +connection_init_result_cb (NMRemoteConnection *remote, + GParamSpec *pspec, + gpointer user_data) +{ + NMRemoteSettings *self = NM_REMOTE_SETTINGS (user_data); + NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); + guint32 init_result = NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN; + const char *path; + + /* Disconnect from the init-result signal just to be safe */ + g_signal_handlers_disconnect_matched (remote, + G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA, + 0, + 0, + NULL, + G_CALLBACK (connection_init_result_cb), + self); + + path = nm_connection_get_path (NM_CONNECTION (remote)); + + g_object_get (G_OBJECT (remote), + NM_REMOTE_CONNECTION_INIT_RESULT, &init_result, + NULL); + + switch (init_result) { + case NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS: + /* ref it when adding to ->connections, since removing it from ->pending + * will unref it. + */ + g_hash_table_insert (priv->connections, g_strdup (path), g_object_ref (remote)); + + /* Finally, let users know of the new connection now that it has all + * its settings and is valid. + */ + g_signal_emit_by_name (self, "new-connection", remote); + break; + case NM_REMOTE_CONNECTION_INIT_RESULT_ERROR: + default: + break; + } + + g_hash_table_remove (priv->pending, path); } static void @@ -85,8 +137,15 @@ new_connection_cb (DBusGProxy *proxy, const char *path, gpointer user_data) G_CALLBACK (connection_removed_cb), self); - g_hash_table_insert (priv->connections, g_strdup (path), connection); - g_signal_emit_by_name (self, "new-connection", connection); + g_signal_connect (connection, "notify::" NM_REMOTE_CONNECTION_INIT_RESULT, + G_CALLBACK (connection_init_result_cb), + self); + + /* Add the connection to the pending table to wait for it to retrieve + * it's settings asynchronously over D-Bus. The connection isn't + * really valid until it has all its settings, so hide it until it does. + */ + g_hash_table_insert (priv->pending, g_strdup (path), connection); } } @@ -269,6 +328,7 @@ nm_remote_settings_init (NMRemoteSettings *self) NMRemoteSettingsPrivate *priv = NM_REMOTE_SETTINGS_GET_PRIVATE (self); priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + priv->pending = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); } static GObject * @@ -344,6 +404,9 @@ dispose (GObject *object) if (priv->connections) g_hash_table_destroy (priv->connections); + if (priv->pending) + g_hash_table_destroy (priv->pending); + g_object_unref (priv->dbus_proxy); g_object_unref (priv->proxy); dbus_g_connection_unref (priv->bus); From d26b436d9e6be3fa19ad7241dc79192076e65d14 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 14:12:48 -0500 Subject: [PATCH 10/30] libnm-glib: NMSettingsInterface::add_connection() should take an NMConnection instead of an NMSettingsConnectionInterface, because we won't always have an object that implements NMSettingsConnectionInterface. Plus, since NMConnection is a prerequisite of NMSettingsConnectionInterface, the NMConnection will always be there anyway. --- libnm-glib/nm-remote-settings.c | 4 ++-- libnm-glib/nm-settings-interface.c | 6 +++--- libnm-glib/nm-settings-interface.h | 4 ++-- libnm-glib/nm-settings-service.c | 4 ++-- libnm-glib/nm-settings-service.h | 2 +- src/system-settings/nm-sysconfig-settings.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libnm-glib/nm-remote-settings.c b/libnm-glib/nm-remote-settings.c index ea8fd2664a..3d335fe715 100644 --- a/libnm-glib/nm-remote-settings.c +++ b/libnm-glib/nm-remote-settings.c @@ -226,7 +226,7 @@ add_connection_done (DBusGProxy *proxy, static gboolean add_connection (NMSettingsInterface *settings, - NMSettingsConnectionInterface *connection, + NMConnection *connection, NMSettingsAddConnectionFunc callback, gpointer user_data) { @@ -240,7 +240,7 @@ add_connection (NMSettingsInterface *settings, info->callback = callback; info->callback_data = user_data; - new_settings = nm_connection_to_hash (NM_CONNECTION (connection)); + new_settings = nm_connection_to_hash (connection); org_freedesktop_NetworkManagerSettings_add_connection_async (priv->proxy, new_settings, add_connection_done, diff --git a/libnm-glib/nm-settings-interface.c b/libnm-glib/nm-settings-interface.c index 66c63d7728..51a9ad00d6 100644 --- a/libnm-glib/nm-settings-interface.c +++ b/libnm-glib/nm-settings-interface.c @@ -112,7 +112,7 @@ nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings, /** * nm_settings_interface_add_connection: * @settings: a object implementing %NMSettingsInterface - * @connection: the settings to add; note that this objects settings will be + * @connection: the settings to add; note that this object's settings will be * added, not the object itself * @callback: callback to be called when the add operation completes * @user_data: caller-specific data passed to @callback @@ -123,14 +123,14 @@ nm_settings_interface_get_connection_by_path (NMSettingsInterface *settings, **/ gboolean nm_settings_interface_add_connection (NMSettingsInterface *settings, - NMSettingsConnectionInterface *connection, + NMConnection *connection, NMSettingsAddConnectionFunc callback, gpointer user_data) { g_return_val_if_fail (settings != NULL, FALSE); g_return_val_if_fail (NM_IS_SETTINGS_INTERFACE (settings), FALSE); g_return_val_if_fail (connection != NULL, FALSE); - g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection), FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (callback != NULL, FALSE); if (NM_SETTINGS_INTERFACE_GET_INTERFACE (settings)->add_connection) { diff --git a/libnm-glib/nm-settings-interface.h b/libnm-glib/nm-settings-interface.h index a058042f62..44c4d9dc2e 100644 --- a/libnm-glib/nm-settings-interface.h +++ b/libnm-glib/nm-settings-interface.h @@ -67,7 +67,7 @@ struct _NMSettingsInterface { const char *path); gboolean (*add_connection) (NMSettingsInterface *settings, - NMSettingsConnectionInterface *connection, + NMConnection *connection, NMSettingsAddConnectionFunc callback, gpointer user_data); @@ -85,7 +85,7 @@ NMSettingsConnectionInterface *nm_settings_interface_get_connection_by_path (NMS const char *path); gboolean nm_settings_interface_add_connection (NMSettingsInterface *settings, - NMSettingsConnectionInterface *connection, + NMConnection *connection, NMSettingsAddConnectionFunc callback, gpointer user_data); diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c index 0245cb1ae1..aa063a8274 100644 --- a/libnm-glib/nm-settings-service.c +++ b/libnm-glib/nm-settings-service.c @@ -143,7 +143,7 @@ nm_settings_service_get_connection_by_path (NMSettingsService *self, static gboolean add_connection (NMSettingsInterface *settings, - NMSettingsConnectionInterface *connection, + NMConnection *connection, NMSettingsAddConnectionFunc callback, gpointer user_data) { @@ -202,7 +202,7 @@ impl_settings_add_connection (NMSettingsService *self, if (NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection) { NM_SETTINGS_SERVICE_GET_CLASS (self)->add_connection (NM_SETTINGS_SERVICE (self), - NM_SETTINGS_CONNECTION_INTERFACE (tmp), + tmp, context, dbus_add_connection_cb, context); diff --git a/libnm-glib/nm-settings-service.h b/libnm-glib/nm-settings-service.h index b8d93a7162..f2ee7363cd 100644 --- a/libnm-glib/nm-settings-service.h +++ b/libnm-glib/nm-settings-service.h @@ -52,7 +52,7 @@ typedef struct { GSList * (*list_connections) (NMSettingsService *self); void (*add_connection) (NMSettingsService *self, - NMSettingsConnectionInterface *connection, + NMConnection *connection, DBusGMethodInvocation *context, /* Only present for D-Bus calls */ NMSettingsAddConnectionFunc callback, gpointer user_data); diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index ceef21b36d..7b9d923776 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -643,7 +643,7 @@ out: static void add_connection (NMSettingsService *service, - NMSettingsConnectionInterface *connection, + NMConnection *connection, DBusGMethodInvocation *context, /* Only present for D-Bus calls */ NMSettingsAddConnectionFunc callback, gpointer user_data) @@ -663,7 +663,7 @@ add_connection (NMSettingsService *service, return; } - call = polkit_call_new (self, context, NM_CONNECTION (connection), callback, user_data, NULL); + call = polkit_call_new (self, context, connection, callback, user_data, NULL); g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, From 549b303e9b1d603394fd084a630ee911610eacdb Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 15:32:39 -0500 Subject: [PATCH 11/30] libnm-glib: (NMSettingsConnectionInterface) emit 'removed' signal on successful deletion --- libnm-glib/nm-exported-connection.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c index 80391de63a..5d5462eb37 100644 --- a/libnm-glib/nm-exported-connection.c +++ b/libnm-glib/nm-exported-connection.c @@ -135,6 +135,7 @@ do_delete (NMSettingsConnectionInterface *connection, NMSettingsConnectionInterfaceDeleteFunc callback, gpointer user_data) { + g_signal_emit_by_name (connection, "removed"); callback (connection, NULL, user_data); return TRUE; } From 7dc07202e348f16a3de4097ef82ffe89ac6bd406 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 11 Aug 2009 16:06:07 -0500 Subject: [PATCH 12/30] polkit: fix policy for polkit >= 0.92 --- policy/Makefile.am | 2 +- .../org.freedesktop.network-manager-settings.system.policy.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/policy/Makefile.am b/policy/Makefile.am index c5d24764ee..17fc56dc50 100644 --- a/policy/Makefile.am +++ b/policy/Makefile.am @@ -1,4 +1,4 @@ -polkit_policydir = $(datadir)/PolicyKit/policy +polkit_policydir = $(datadir)/polkit-1/actions dist_polkit_policy_in_files = org.freedesktop.network-manager-settings.system.policy.in dist_polkit_policy_DATA = $(dist_polkit_policy_in_files:.policy.in=.policy) diff --git a/policy/org.freedesktop.network-manager-settings.system.policy.in b/policy/org.freedesktop.network-manager-settings.system.policy.in index ca8c14bf35..8b24a23b13 100644 --- a/policy/org.freedesktop.network-manager-settings.system.policy.in +++ b/policy/org.freedesktop.network-manager-settings.system.policy.in @@ -14,7 +14,7 @@ <_message>System policy prevents modification of system settings no - auth_admin_keep_always + auth_admin_keep From 00e1be621e18e81f77c3d4232852f78c7c2bc5c1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Aug 2009 17:04:21 -0500 Subject: [PATCH 13/30] libnm-glib: exported connection fixes Ensure that updating the connection really sends out the updated signal, and that trying to update/delete a read-only connection over D-Bus returns an error. --- libnm-glib/nm-exported-connection.c | 57 ++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c index 5d5462eb37..fa6abb415b 100644 --- a/libnm-glib/nm-exported-connection.c +++ b/libnm-glib/nm-exported-connection.c @@ -21,8 +21,10 @@ #include #include +#include #include "nm-exported-connection.h" +#include "nm-settings-interface.h" #include "nm-settings-connection-interface.h" static gboolean impl_exported_connection_get_settings (NMExportedConnection *connection, @@ -99,6 +101,7 @@ update (NMSettingsConnectionInterface *connection, NMSettingsConnectionInterfaceUpdateFunc callback, gpointer user_data) { + nm_settings_connection_interface_emit_updated (connection); callback (connection, NULL, user_data); return TRUE; } @@ -110,6 +113,31 @@ impl_exported_connection_update (NMExportedConnection *self, { NMConnection *tmp; GError *error = NULL; + NMSettingConnection *s_con; + + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), + NM_TYPE_SETTING_CONNECTION); + if (!s_con) { + error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, + "Connection did not have required 'connection' setting"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + /* If the connection is read-only, that has to be changed at the source of + * the problem (ex a system settings plugin that can't write connections out) + * instead of over D-Bus. + */ + if (nm_setting_connection_get_read_only (s_con)) { + error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, + "Connection is read-only"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } /* Check if the settings are valid first */ tmp = nm_connection_new_from_hash (new_settings, &error); @@ -124,7 +152,9 @@ impl_exported_connection_update (NMExportedConnection *self, if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->update) NM_EXPORTED_CONNECTION_GET_CLASS (self)->update (self, new_settings, context); else { - error = g_error_new (0, 0, "%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__); + error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, + "%s: %s:%d update() unimplemented", __func__, __FILE__, __LINE__); dbus_g_method_return_error (context, error); g_error_free (error); } @@ -145,11 +175,34 @@ impl_exported_connection_delete (NMExportedConnection *self, DBusGMethodInvocation *context) { GError *error = NULL; + NMSettingConnection *s_con; + + s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), + NM_TYPE_SETTING_CONNECTION); + if (!s_con) { + error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, + "Connection did not have required 'connection' setting"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + if (nm_setting_connection_get_read_only (s_con)) { + error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, + "Connection is read-only"); + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } if (NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete) NM_EXPORTED_CONNECTION_GET_CLASS (self)->delete (self, context); else { - error = g_error_new (0, 0, "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__); + error = g_error_new (NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INTERNAL_ERROR, + "%s: %s:%d delete() unimplemented", __func__, __FILE__, __LINE__); dbus_g_method_return_error (context, error); g_error_free (error); } From fb34976ab9414e9f87c295bb9e1e1382cba398d1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Aug 2009 17:10:20 -0500 Subject: [PATCH 14/30] system-settings: remove redundant default methods for update/delete NMExportedConnection implements these already, and we want the functionality that it provides, so we don't need to override them here. --- src/system-settings/nm-sysconfig-connection.c | 22 ------------------- 1 file changed, 22 deletions(-) diff --git a/src/system-settings/nm-sysconfig-connection.c b/src/system-settings/nm-sysconfig-connection.c index db197a3f28..b711c232b0 100644 --- a/src/system-settings/nm-sysconfig-connection.c +++ b/src/system-settings/nm-sysconfig-connection.c @@ -46,26 +46,6 @@ typedef struct { /**************************************************************/ -static gboolean -update (NMSettingsConnectionInterface *connection, - NMSettingsConnectionInterfaceUpdateFunc callback, - gpointer user_data) -{ - /* Default handler for subclasses */ - callback (connection, NULL, user_data); - return TRUE; -} - -static gboolean -do_delete (NMSettingsConnectionInterface *connection, - NMSettingsConnectionInterfaceDeleteFunc callback, - gpointer user_data) -{ - /* Default handler for subclasses */ - callback (connection, NULL, user_data); - return TRUE; -} - static GValue * string_to_gvalue (const char *str) { @@ -486,8 +466,6 @@ dbus_get_secrets (NMExportedConnection *exported, static void settings_connection_interface_init (NMSettingsConnectionInterface *iface) { - iface->update = update; - iface->delete = do_delete; iface->get_secrets = get_secrets; } From 2164c14559591bdf03377cf172694a1a7b62e272 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Aug 2009 17:11:07 -0500 Subject: [PATCH 15/30] ifcfg-rh: use GHashTableIter a bit more --- system-settings/plugins/ifcfg-rh/plugin.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/system-settings/plugins/ifcfg-rh/plugin.c b/system-settings/plugins/ifcfg-rh/plugin.c index c8d37322cc..0e8eb48f88 100644 --- a/system-settings/plugins/ifcfg-rh/plugin.c +++ b/system-settings/plugins/ifcfg-rh/plugin.c @@ -410,29 +410,27 @@ setup_ifcfg_monitoring (SCPluginIfcfg *plugin) } } -static void -hash_to_slist (gpointer key, gpointer value, gpointer user_data) -{ - NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value); - GSList **list = (GSList **) user_data; - - if (!nm_ifcfg_connection_get_unmanaged_spec (exported)) - *list = g_slist_prepend (*list, value); -} - static GSList * get_connections (NMSystemConfigInterface *config) { SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); GSList *list = NULL; + GHashTableIter iter; + gpointer value; if (!priv->connections) { setup_ifcfg_monitoring (plugin); read_connections (plugin); } - g_hash_table_foreach (priv->connections, hash_to_slist, &list); + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + NMIfcfgConnection *exported = NM_IFCFG_CONNECTION (value); + + if (!nm_ifcfg_connection_get_unmanaged_spec (exported)) + list = g_slist_prepend (list, value); + } return list; } From 5be1f8e133c310ddc9bf081cfa9410a1b72ab4e6 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Aug 2009 17:13:08 -0500 Subject: [PATCH 16/30] ifcfg-suse: port to new settings API --- .../plugins/ifcfg-suse/nm-suse-connection.c | 125 +++++++++--------- system-settings/plugins/ifcfg-suse/plugin.c | 69 +++++----- 2 files changed, 99 insertions(+), 95 deletions(-) diff --git a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c b/system-settings/plugins/ifcfg-suse/nm-suse-connection.c index d2949df12f..b114b74ed5 100644 --- a/system-settings/plugins/ifcfg-suse/nm-suse-connection.c +++ b/system-settings/plugins/ifcfg-suse/nm-suse-connection.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include "nm-suse-connection.h" #include "parser.h" #include "nm-system-config-error.h" @@ -40,43 +42,53 @@ typedef struct { } NMSuseConnectionPrivate; static void -file_changed (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) +ignore_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) { - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (user_data); - NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported); - NMConnection *new_connection; - GHashTable *new_settings; +} + +static void +file_changed (GFileMonitor *monitor, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + gpointer user_data) +{ + NMSuseConnection *self = NM_SUSE_CONNECTION (user_data); + NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (self); + NMConnection *new; switch (event_type) { case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: - new_connection = parse_ifcfg (priv->iface, priv->dev_type); - if (new_connection) { + new = parse_ifcfg (priv->iface, priv->dev_type); + if (new) { GError *error = NULL; + GHashTable *settings; - new_settings = nm_connection_to_hash (new_connection); - if (nm_connection_replace_settings (nm_exported_connection_get_connection (exported), new_settings, &error)) - nm_exported_connection_signal_updated (exported, new_settings); - else { - g_warning ("%s: '%s' / '%s' invalid: %d", - __func__, - error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", - (error && error->message) ? error->message : "(none)", - error ? error->code : -1); - g_clear_error (&error); - nm_exported_connection_signal_removed (exported); + if (!nm_connection_compare (new, + NM_CONNECTION (self), + NM_SETTING_COMPARE_FLAG_EXACT)) { + settings = nm_connection_to_hash (new); + if (!nm_connection_replace_settings (NM_CONNECTION (self), settings, &error)) { + g_warning ("%s: '%s' / '%s' invalid: %d", + __func__, + error ? g_type_name (nm_connection_lookup_setting_type_by_quark (error->domain)) : "(none)", + (error && error->message) ? error->message : "(none)", + error ? error->code : -1); + g_clear_error (&error); + } + g_hash_table_destroy (settings); + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (self), + ignore_cb, + NULL); } - - g_hash_table_destroy (new_settings); - g_object_unref (new_connection); + g_object_unref (new); } else - nm_exported_connection_signal_removed (exported); + g_signal_emit_by_name (self, "removed"); break; case G_FILE_MONITOR_EVENT_DELETED: - nm_exported_connection_signal_removed (exported); + g_signal_emit_by_name (self, "removed"); break; default: break; @@ -86,24 +98,40 @@ file_changed (GFileMonitor *monitor, NMSuseConnection * nm_suse_connection_new (const char *iface, NMDeviceType dev_type) { - NMConnection *connection; + NMConnection *tmp; GFile *file; GFileMonitor *monitor; NMSuseConnection *exported; NMSuseConnectionPrivate *priv; + GHashTable *settings; + NMSettingConnection *s_con; g_return_val_if_fail (iface != NULL, NULL); - connection = parse_ifcfg (iface, dev_type); - if (!connection) + tmp = parse_ifcfg (iface, dev_type); + if (!tmp) return NULL; - exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION, - NM_EXPORTED_CONNECTION_CONNECTION, connection, - NULL); - g_object_unref (connection); - if (!exported) + /* Ensure the read connection is read-only since we don't have write capability yet */ + s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION); + g_assert (s_con); + if (!nm_setting_connection_get_read_only (s_con)) { + g_warning ("%s: expected read-only connection!", __func__); + g_object_unref (tmp); return NULL; + } + + exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION, NULL); + if (!exported) { + g_object_unref (tmp); + return NULL; + } + + /* Update our settings with what was read from the file */ + settings = nm_connection_to_hash (tmp); + nm_connection_replace_settings (NM_CONNECTION (exported), settings, NULL); + g_hash_table_destroy (settings); + g_object_unref (tmp); priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported); @@ -123,28 +151,6 @@ nm_suse_connection_new (const char *iface, NMDeviceType dev_type) return exported; } -static gboolean -update (NMExportedConnection *exported, - GHashTable *new_settings, - GError **err) -{ - g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, - "%s", "Please use YaST to change this connection."); - - return FALSE; -} - -static gboolean -do_delete (NMExportedConnection *exported, GError **err) -{ - g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, - "%s", "Please use YaST to remove this connection."); - - return FALSE; -} - /* GObject */ static void @@ -165,6 +171,7 @@ finalize (GObject *object) g_object_unref (priv->monitor); } + nm_connection_clear_secrets (NM_CONNECTION (object)); g_free (priv->filename); G_OBJECT_CLASS (nm_suse_connection_parent_class)->finalize (object); @@ -174,13 +181,9 @@ static void nm_suse_connection_class_init (NMSuseConnectionClass *suse_connection_class) { GObjectClass *object_class = G_OBJECT_CLASS (suse_connection_class); - NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (suse_connection_class); g_type_class_add_private (suse_connection_class, sizeof (NMSuseConnectionPrivate)); /* Virtual methods */ object_class->finalize = finalize; - - connection_class->update = update; - connection_class->do_delete = do_delete; } diff --git a/system-settings/plugins/ifcfg-suse/plugin.c b/system-settings/plugins/ifcfg-suse/plugin.c index 86d3abea88..86138d4a4f 100644 --- a/system-settings/plugins/ifcfg-suse/plugin.c +++ b/system-settings/plugins/ifcfg-suse/plugin.c @@ -90,38 +90,41 @@ ifcfg_plugin_error_quark (void) } static void -update_one_connection (gpointer key, gpointer val, gpointer user_data) +ignore_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) { - NMExportedConnection *exported = NM_EXPORTED_CONNECTION (val); - NMConnection *connection; - NMSettingIP4Config *ip4_config; - - connection = nm_exported_connection_get_connection (exported); - ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG); - if (!ip4_config) - return; - - if (nm_setting_ip4_config_get_num_addresses (ip4_config)) { - /* suse only has one address per device */ - NMIP4Address *ip4_address = nm_setting_ip4_config_get_address (ip4_config, 0); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (user_data); - GHashTable *settings; - - if (nm_ip4_address_get_gateway (ip4_address) != priv->default_gw) { - nm_ip4_address_set_gateway (ip4_address, priv->default_gw); - settings = nm_connection_to_hash (connection); - nm_exported_connection_signal_updated (exported, settings); - g_hash_table_destroy (settings); - } - } } static void update_connections (SCPluginIfcfg *self) { SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); + GHashTableIter iter; + gpointer value; - g_hash_table_foreach (priv->connections, update_one_connection, self); + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + NMSuseConnection *exported = NM_SUSE_CONNECTION (value); + NMSettingIP4Config *ip4_config; + + ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_IP4_CONFIG); + if (!ip4_config) + continue; + + if (nm_setting_ip4_config_get_num_addresses (ip4_config)) { + /* suse only has one address per device */ + NMIP4Address *ip4_address; + + ip4_address = nm_setting_ip4_config_get_address (ip4_config, 0); + if (nm_ip4_address_get_gateway (ip4_address) != priv->default_gw) { + nm_ip4_address_set_gateway (ip4_address, priv->default_gw); + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported), + ignore_cb, + NULL); + } + } + } } static void @@ -286,7 +289,9 @@ handle_uevent (GUdevClient *client, exported = (NMExportedConnection *) g_hash_table_lookup (priv->connections, GUINT_TO_POINTER (ifindex)); if (exported) { - nm_exported_connection_signal_removed (exported); + nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported), + ignore_cb, + NULL); g_hash_table_remove (priv->connections, GUINT_TO_POINTER (ifindex)); } } @@ -306,20 +311,14 @@ init (NMSystemConfigInterface *config) g_signal_connect (priv->client, "uevent", G_CALLBACK (handle_uevent), self); } -static void -get_connections_cb (gpointer key, gpointer val, gpointer user_data) -{ - GSList **list = (GSList **) user_data; - - *list = g_slist_prepend (*list, val); -} - static GSList * get_connections (NMSystemConfigInterface *config) { SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); GSList *list = NULL; + GHashTableIter iter; + gpointer value; if (!priv->initialized) { const char *filename; @@ -336,7 +335,9 @@ get_connections (NMSystemConfigInterface *config) priv->initialized = TRUE; } - g_hash_table_foreach (priv->connections, get_connections_cb, &list); + g_hash_table_iter_init (&iter, priv->connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) + list = g_slist_prepend (list, value); return list; } From 650cbcc10849af93a5a308fb8d4073e7455a8140 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 12 Aug 2009 17:13:24 -0500 Subject: [PATCH 17/30] ifupdown: port to new settings API --- .../plugins/ifupdown/nm-ifupdown-connection.c | 67 ++++------- system-settings/plugins/ifupdown/parser.c | 51 ++++---- system-settings/plugins/ifupdown/parser.h | 7 +- system-settings/plugins/ifupdown/plugin.c | 111 +++++++++--------- 4 files changed, 103 insertions(+), 133 deletions(-) diff --git a/system-settings/plugins/ifupdown/nm-ifupdown-connection.c b/system-settings/plugins/ifupdown/nm-ifupdown-connection.c index 275771f34b..ad9a479a6a 100644 --- a/system-settings/plugins/ifupdown/nm-ifupdown-connection.c +++ b/system-settings/plugins/ifupdown/nm-ifupdown-connection.c @@ -29,13 +29,10 @@ #include #include #include -#include #include "nm-ifupdown-connection.h" #include "parser.h" -G_DEFINE_TYPE (NMIfupdownConnection, - nm_ifupdown_connection, - NM_TYPE_SYSCONFIG_CONNECTION) +G_DEFINE_TYPE (NMIfupdownConnection, nm_ifupdown_connection, NM_TYPE_SYSCONFIG_CONNECTION) #define NM_IFUPDOWN_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFUPDOWN_CONNECTION, NMIfupdownConnectionPrivate)) @@ -60,36 +57,16 @@ nm_ifupdown_connection_new (if_block *block) NULL); } -static gboolean -update (NMExportedConnection *exported, - GHashTable *new_settings, - GError **err) -{ - g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_UPDATE_NOT_SUPPORTED, - "%s.%d - %s", __FILE__, __LINE__, "connection update not supported (read-only)."); - return FALSE; -} - -static gboolean -do_delete (NMExportedConnection *exported, GError **err) -{ - g_set_error (err, NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_DELETE_NOT_SUPPORTED, - "%s", "ifupdown - connection delete not supported (read-only)."); - return FALSE; -} - static void -service_get_secrets (NMExportedConnection *exported, - const gchar *setting_name, - const gchar **hints, - gboolean request_new, - DBusGMethodInvocation *context) +get_secrets (NMExportedConnection *exported, + const gchar *setting_name, + const gchar **hints, + gboolean request_new, + DBusGMethodInvocation *context) { GError *error = NULL; - PLUGIN_PRINT ("SCPlugin-Ifupdown", "get_secrets for setting_name:'%s')", setting_name); + PLUGIN_PRINT ("SCPlugin-Ifupdown", "get_secrets() for setting_name:'%s'", setting_name); /* FIXME: Only wifi secrets are supported for now */ if (strcmp (setting_name, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME)) { @@ -104,10 +81,9 @@ service_get_secrets (NMExportedConnection *exported, return; } - NM_EXPORTED_CONNECTION_CLASS (nm_ifupdown_connection_parent_class)->service_get_secrets (exported, setting_name, hints, request_new, context); + NM_EXPORTED_CONNECTION_CLASS (nm_ifupdown_connection_parent_class)->get_secrets (exported, setting_name, hints, request_new, context); } -/* GObject */ static void nm_ifupdown_connection_init (NMIfupdownConnection *connection) { @@ -120,23 +96,29 @@ constructor (GType type, { GObject *object; NMIfupdownConnectionPrivate *priv; - NMConnection *wrapped = nm_connection_new(); + GError *error = NULL; object = G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->constructor (type, n_construct_params, construct_params); g_return_val_if_fail (object, NULL); priv = NM_IFUPDOWN_CONNECTION_GET_PRIVATE (object); if (!priv) { - nm_warning ("%s.%d - no private instance.", __FILE__, __LINE__); + g_warning ("%s.%d - no private instance.", __FILE__, __LINE__); goto err; } if (!priv->ifblock) { - nm_warning ("(ifupdown) ifblock not provided to constructor."); + g_warning ("(ifupdown) ifblock not provided to constructor."); goto err; } - g_object_set (object, NM_EXPORTED_CONNECTION_CONNECTION, wrapped, NULL); - g_object_unref (wrapped); + if (!ifupdown_update_connection_from_if_block (NM_CONNECTION (object), priv->ifblock, &error)) { + g_warning ("%s.%d - invalid connection read from /etc/network/interfaces: (%d) %s", + __FILE__, + __LINE__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + goto err; + } return object; @@ -145,12 +127,6 @@ constructor (GType type, return NULL; } -static void -finalize (GObject *object) -{ - G_OBJECT_CLASS (nm_ifupdown_connection_parent_class)->finalize (object); -} - static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) @@ -197,11 +173,8 @@ nm_ifupdown_connection_class_init (NMIfupdownConnectionClass *ifupdown_connectio object_class->constructor = constructor; object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; - connection_class->update = update; - connection_class->do_delete = do_delete; - connection_class->service_get_secrets = service_get_secrets; + connection_class->get_secrets = get_secrets; /* Properties */ g_object_class_install_property diff --git a/system-settings/plugins/ifupdown/parser.c b/system-settings/plugins/ifupdown/parser.c index 81da0aea9d..dc2f8abf68 100644 --- a/system-settings/plugins/ifupdown/parser.c +++ b/system-settings/plugins/ifupdown/parser.c @@ -525,58 +525,53 @@ update_ip4_setting_from_if_block(NMConnection *connection, nm_connection_add_setting(connection, NM_SETTING(ip4_setting)); } -void -ifupdown_update_connection_from_if_block(NMConnection *connection, - if_block *block) +gboolean +ifupdown_update_connection_from_if_block (NMConnection *connection, + if_block *block, + GError **error) { const char *type = NULL; char *idstr = NULL; char *uuid_base = NULL; - GError *verify_error = NULL; char *uuid = NULL; + NMSettingConnection *s_con; + gboolean success = FALSE; - NMSettingConnection *connection_setting = - NM_SETTING_CONNECTION(nm_connection_get_setting - (connection, NM_TYPE_SETTING_CONNECTION)); - - if(!connection_setting) { - connection_setting = NM_SETTING_CONNECTION(nm_setting_connection_new()); - nm_connection_add_setting(connection, NM_SETTING(connection_setting)); + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION); + if(!s_con) { + s_con = NM_SETTING_CONNECTION (nm_setting_connection_new()); + g_assert (s_con); + nm_connection_add_setting (connection, NM_SETTING (s_con)); } type = _ifupdownplugin_guess_connection_type (block); - idstr = g_strconcat("Ifupdown (", block->name,")", NULL); + idstr = g_strconcat ("Ifupdown (", block->name, ")", NULL); uuid_base = idstr; - uuid = nm_utils_uuid_generate_from_string(uuid_base); - g_object_set (connection_setting, + uuid = nm_utils_uuid_generate_from_string (uuid_base); + g_object_set (s_con, NM_SETTING_CONNECTION_TYPE, type, NM_SETTING_CONNECTION_ID, idstr, NM_SETTING_CONNECTION_UUID, uuid, NM_SETTING_CONNECTION_READ_ONLY, TRUE, + NM_SETTING_CONNECTION_AUTOCONNECT, FALSE, NULL); g_free (uuid); - PLUGIN_PRINT("SCPlugin-Ifupdown", "update_connection_setting_from_if_block: name:%s, type:%s, autoconnect:%d, id:%s, uuid: %s", - block->name, type, - ((gboolean) strcmp("dhcp", type) == 0), - idstr, - nm_setting_connection_get_uuid (connection_setting)); + PLUGIN_PRINT("SCPlugin-Ifupdown", "update_connection_setting_from_if_block: name:%s, type:%s, id:%s, uuid: %s", + block->name, type, idstr, nm_setting_connection_get_uuid (s_con)); - if(!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) { + if (!strcmp (NM_SETTING_WIRED_SETTING_NAME, type)) update_wired_setting_from_if_block (connection, block); - } - else if(!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { + else if (!strcmp (NM_SETTING_WIRELESS_SETTING_NAME, type)) { update_wireless_setting_from_if_block (connection, block); update_wireless_security_setting_from_if_block (connection, block); } - update_ip4_setting_from_if_block(connection, block); + update_ip4_setting_from_if_block (connection, block); - if(!nm_connection_verify(connection, &verify_error)) { - nm_warning("connection broken: %s (%d)", - verify_error->message, verify_error->code); - } + success = nm_connection_verify (connection, error); - g_free(idstr); + g_free (idstr); + return success; } diff --git a/system-settings/plugins/ifupdown/parser.h b/system-settings/plugins/ifupdown/parser.h index 5e7ddd6056..6aebb8c71c 100644 --- a/system-settings/plugins/ifupdown/parser.h +++ b/system-settings/plugins/ifupdown/parser.h @@ -26,8 +26,9 @@ G_BEGIN_DECLS -void -ifupdown_update_connection_from_if_block(NMConnection *connection, - if_block *block); +gboolean +ifupdown_update_connection_from_if_block (NMConnection *connection, + if_block *block, + GError **error); G_END_DECLS diff --git a/system-settings/plugins/ifupdown/plugin.c b/system-settings/plugins/ifupdown/plugin.c index a38f40cfca..e8e4e25e99 100644 --- a/system-settings/plugins/ifupdown/plugin.c +++ b/system-settings/plugins/ifupdown/plugin.c @@ -86,8 +86,8 @@ static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); G_DEFINE_TYPE_EXTENDED (SCPluginIfupdown, sc_plugin_ifupdown, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, - system_config_interface_init)) + G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, + system_config_interface_init)) #define SC_PLUGIN_IFUPDOWN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFUPDOWN, SCPluginIfupdownPrivate)) @@ -124,9 +124,6 @@ GObject__set_property (GObject *object, guint prop_id, static void GObject__dispose (GObject *object); -static void -GObject__finalize (GObject *object); - /* other helpers */ static const char * get_hostname (NMSystemConfigInterface *config); @@ -155,7 +152,6 @@ sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class) g_type_class_add_private (req_class, sizeof (SCPluginIfupdownPrivate)); object_class->dispose = GObject__dispose; - object_class->finalize = GObject__finalize; object_class->get_property = GObject__get_property; object_class->set_property = GObject__set_property; @@ -176,13 +172,19 @@ sc_plugin_ifupdown_class_init (SCPluginIfupdownClass *req_class) NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); } +static void +ignore_cb (NMSettingsConnectionInterface *connection, + GError *error, + gpointer user_data) +{ +} + static void bind_device_to_connection (SCPluginIfupdown *self, GUdevDevice *device, - NMExportedConnection *exported) + NMIfupdownConnection *exported) { GByteArray *mac_address; - NMConnection *connection; NMSetting *s_wired = NULL; NMSetting *s_wifi = NULL; const char *iface, *address; @@ -194,13 +196,6 @@ bind_device_to_connection (SCPluginIfupdown *self, return; } - connection = nm_exported_connection_get_connection (exported); - if (!connection) { - PLUGIN_WARN ("SCPluginIfupdown", "no device locking possible. " - "NMExportedConnection doesnt have a real connection."); - return; - } - address = g_udev_device_get_sysfs_attr (device, "address"); if (!address || !strlen (address)) { PLUGIN_WARN ("SCPluginIfupdown", "failed to get MAC address for %s", iface); @@ -217,8 +212,8 @@ bind_device_to_connection (SCPluginIfupdown *self, mac_address = g_byte_array_sized_new (ETH_ALEN); g_byte_array_append (mac_address, &(tmp_mac->ether_addr_octet[0]), ETH_ALEN); - s_wired = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); - s_wifi = nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS); + s_wired = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRED); + s_wifi = nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_WIRELESS); if (s_wifi) { PLUGIN_PRINT ("SCPluginIfupdown", "locking wired connection setting"); g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac_address, NULL); @@ -226,8 +221,11 @@ bind_device_to_connection (SCPluginIfupdown *self, PLUGIN_PRINT ("SCPluginIfupdown", "locking wireless connection setting"); g_object_set (s_wifi, NM_SETTING_WIRELESS_MAC_ADDRESS, mac_address, NULL); } - g_byte_array_free (mac_address, TRUE); + + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported), + ignore_cb, + NULL); } static void @@ -235,7 +233,7 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device) { SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (self); const char *iface, *path; - NMExportedConnection *exported; + NMIfupdownConnection *exported; iface = g_udev_device_get_name (device); path = g_udev_device_get_sysfs_path (device); @@ -248,7 +246,7 @@ udev_device_added (SCPluginIfupdown *self, GUdevDevice *device) /* if we have a configured connection for this particular iface * we want to either unmanage the device or lock it */ - exported = (NMExportedConnection *) g_hash_table_lookup (priv->iface_connections, iface); + exported = (NMIfupdownConnection *) g_hash_table_lookup (priv->iface_connections, iface); if (!exported) return; @@ -352,14 +350,23 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) if(!strcmp ("auto", block->type)) g_hash_table_insert (auto_ifaces, block->name, GUINT_TO_POINTER (1)); else if (!strcmp ("iface", block->type) && strcmp ("lo", block->name)) { - NMExportedConnection *exported; + NMIfupdownConnection *exported; - g_hash_table_remove (priv->iface_connections, block->name); + /* Remove any connection for this block that was previously found */ + exported = g_hash_table_lookup (priv->iface_connections, block->name); + if (exported) { + nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (exported), + ignore_cb, + NULL); + g_hash_table_remove (priv->iface_connections, block->name); + } - exported = NM_EXPORTED_CONNECTION (nm_ifupdown_connection_new (block)); - ifupdown_update_connection_from_if_block (nm_exported_connection_get_connection (exported), - block); - g_hash_table_insert (priv->iface_connections, block->name, exported); + /* add the new connection */ + exported = nm_ifupdown_connection_new (block); + if (exported) { + g_hash_table_insert (priv->iface_connections, block->name, exported); + g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, exported); + } } block = block->next; } @@ -367,17 +374,20 @@ SCPluginIfupdown_init (NMSystemConfigInterface *config) /* Make 'auto' interfaces autoconnect=TRUE */ keys = g_hash_table_get_keys (priv->iface_connections); for (iter = keys; iter; iter = g_list_next (iter)) { - NMExportedConnection *exported; - NMConnection *wrapped; + NMIfupdownConnection *exported; NMSetting *setting; if (!g_hash_table_lookup (auto_ifaces, iter->data)) continue; exported = g_hash_table_lookup (priv->iface_connections, iter->data); - wrapped = nm_exported_connection_get_connection (exported); - setting = NM_SETTING (nm_connection_get_setting (wrapped, NM_TYPE_SETTING_CONNECTION)); + setting = NM_SETTING (nm_connection_get_setting (NM_CONNECTION (exported), NM_TYPE_SETTING_CONNECTION)); g_object_set (setting, NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, NULL); + + nm_settings_connection_interface_update (NM_SETTINGS_CONNECTION_INTERFACE (exported), + ignore_cb, + NULL); + PLUGIN_PRINT("SCPlugin-Ifupdown", "autoconnect"); } g_list_free (keys); @@ -433,15 +443,15 @@ SCPluginIfupdown_get_connections (NMSystemConfigInterface *config) { SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config); GSList *connections = NULL; - GList *priv_list = g_hash_table_get_values(priv->iface_connections); - GList *it = priv_list; + GHashTableIter iter; + gpointer value; + PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) ... get_connections.", GPOINTER_TO_UINT(config)); - while(it) { - NMExportedConnection *conn = it->data; - connections = g_slist_append(connections, conn); - it = it->next; - } + g_hash_table_iter_init (&iter, priv->iface_connections); + while (g_hash_table_iter_next (&iter, NULL, &value)) + connections = g_slist_prepend (connections, value); + PLUGIN_PRINT("SCPlugin-Ifupdown", "(%d) connections count: %d", GPOINTER_TO_UINT(config), g_slist_length(connections)); return connections; } @@ -455,28 +465,25 @@ static GSList* SCPluginIfupdown_get_unmanaged_specs (NMSystemConfigInterface *config) { SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config); - GList *devs, *iter; GSList *specs = NULL; + GHashTableIter iter; + gpointer value; if (!ALWAYS_UNMANAGE && !priv->unmanage_well_known) return NULL; - devs = g_hash_table_get_values (priv->well_known_ifaces); - PLUGIN_PRINT("Ifupdown", "get unmanaged devices count: %d", g_list_length (devs)); + PLUGIN_PRINT("Ifupdown", "get unmanaged devices count: %d", + g_hash_table_size (priv->well_known_ifaces)); - for (iter = devs; iter; iter = g_list_next (iter)) { - GUdevDevice *device = G_UDEV_DEVICE (iter->data); + g_hash_table_iter_init (&iter, priv->well_known_ifaces); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + GUdevDevice *device = G_UDEV_DEVICE (value); const char *address; - char *spec; address = g_udev_device_get_sysfs_attr (device, "address"); - if (!address) - continue; - - spec = g_strdup_printf ("mac:%s", address); - specs = g_slist_append (specs, spec); + if (address) + specs = g_slist_append (specs, g_strdup_printf ("mac:%s", address)); } - g_list_free (devs); return specs; } @@ -619,12 +626,6 @@ GObject__dispose (GObject *object) G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->dispose (object); } -static void -GObject__finalize (GObject *object) -{ - G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->finalize (object); -} - G_MODULE_EXPORT GObject * nm_system_config_factory (void) { From 0b4dae681c7eb33e5549698ac5e367b51c4e5a9f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Sat, 22 Aug 2009 16:19:50 -0500 Subject: [PATCH 18/30] libnm-glib: remove duplicate object D-Bus info registration Was causing duplicate signal emissions on the bus. --- libnm-glib/nm-settings-service.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libnm-glib/nm-settings-service.c b/libnm-glib/nm-settings-service.c index aa063a8274..de93d9932f 100644 --- a/libnm-glib/nm-settings-service.c +++ b/libnm-glib/nm-settings-service.c @@ -368,7 +368,4 @@ nm_settings_service_class_init (NMSettingsServiceClass *class) NM_CONNECTION_SCOPE_USER, NM_CONNECTION_SCOPE_USER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (class), - &dbus_glib_nm_settings_object_info); } From def14729b9778f718c818c812ca86bfc551ffb08 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 09:38:14 -0500 Subject: [PATCH 19/30] introspection: fix Removed signal detail --- introspection/nm-exported-connection.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/introspection/nm-exported-connection.xml b/introspection/nm-exported-connection.xml index f742e7d92c..5cb157ebc6 100644 --- a/introspection/nm-exported-connection.xml +++ b/introspection/nm-exported-connection.xml @@ -53,7 +53,7 @@ - Emitted when this settings object was removed. FIXME: Is this emitted after it was removed or when it is about to be removed? If after removed, then different semantics to Device removed. if prior to removal, should be called AboutToBeRemoved. + Emitted when this connection has been deleted/removed. After receipt of this signal, the object no longer exists. From 624708ac5dee1cf8a3f68aaf5ef6ce861c64100e Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 09:38:38 -0500 Subject: [PATCH 20/30] introspection: whitespace fixup --- introspection/nm-settings.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml index 0e77a0377a..b252c00d59 100644 --- a/introspection/nm-settings.xml +++ b/introspection/nm-settings.xml @@ -41,5 +41,7 @@ + + From 74c3ed23a3c0ccade03e4fd1c6b236722fa1ac91 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 10:15:32 -0500 Subject: [PATCH 21/30] libnm-glib: use defined signal names --- libnm-glib/nm-settings-connection-interface.c | 6 +++--- libnm-glib/nm-settings-connection-interface.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libnm-glib/nm-settings-connection-interface.c b/libnm-glib/nm-settings-connection-interface.c index cc3c4b977e..7405fd4678 100644 --- a/libnm-glib/nm-settings-connection-interface.c +++ b/libnm-glib/nm-settings-connection-interface.c @@ -127,7 +127,7 @@ nm_settings_connection_interface_emit_updated (NMSettingsConnectionInterface *co settings = nm_connection_to_hash (tmp); g_object_unref (tmp); - g_signal_emit_by_name (connection, "updated", settings); + g_signal_emit_by_name (connection, NM_SETTINGS_CONNECTION_INTERFACE_UPDATED, settings); g_hash_table_destroy (settings); } } @@ -142,7 +142,7 @@ nm_settings_connection_interface_init (gpointer g_iface) return; /* Signals */ - g_signal_new ("updated", + g_signal_new (NM_SETTINGS_CONNECTION_INTERFACE_UPDATED, iface_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMSettingsConnectionInterface, updated), @@ -150,7 +150,7 @@ nm_settings_connection_interface_init (gpointer g_iface) g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, DBUS_TYPE_G_MAP_OF_MAP_OF_VARIANT); - g_signal_new ("removed", + g_signal_new (NM_SETTINGS_CONNECTION_INTERFACE_REMOVED, iface_type, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (NMSettingsConnectionInterface, removed), diff --git a/libnm-glib/nm-settings-connection-interface.h b/libnm-glib/nm-settings-connection-interface.h index e8118bb72e..477ff9863d 100644 --- a/libnm-glib/nm-settings-connection-interface.h +++ b/libnm-glib/nm-settings-connection-interface.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS #define NM_IS_SETTINGS_CONNECTION_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE)) #define NM_SETTINGS_CONNECTION_INTERFACE_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), NM_TYPE_SETTINGS_CONNECTION_INTERFACE, NMSettingsConnectionInterface)) +#define NM_SETTINGS_CONNECTION_INTERFACE_UPDATED "updated" +#define NM_SETTINGS_CONNECTION_INTERFACE_REMOVED "removed" typedef struct _NMSettingsConnectionInterface NMSettingsConnectionInterface; From 56a597be320b23ed0ea2269a4a77ac8f5567433a Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 10:17:05 -0500 Subject: [PATCH 22/30] core: use defined signal names --- src/nm-manager.c | 4 ++-- src/system-settings/nm-sysconfig-settings.c | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/nm-manager.c b/src/nm-manager.c index 28a5f86843..7a1ab2f38b 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -944,9 +944,9 @@ system_internal_new_connection (NMManager *manager, g_return_if_fail (connection != NULL); - g_signal_connect (connection, "updated", + g_signal_connect (connection, NM_SETTINGS_CONNECTION_INTERFACE_UPDATED, G_CALLBACK (system_connection_updated_cb), manager); - g_signal_connect (connection, "removed", + g_signal_connect (connection, NM_SETTINGS_CONNECTION_INTERFACE_REMOVED, G_CALLBACK (system_connection_removed_cb), manager); path = nm_connection_get_path (NM_CONNECTION (connection)); diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 7b9d923776..f07ab8da85 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -482,11 +482,14 @@ claim_connection (NMSysconfigSettings *self, return; g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1)); - g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self); + g_signal_connect (connection, + NM_SETTINGS_CONNECTION_INTERFACE_REMOVED, + G_CALLBACK (connection_removed), + self); if (do_export) { nm_settings_service_export_connection (NM_SETTINGS_SERVICE (self), connection); - g_signal_emit_by_name (self, "new-connection", connection); + g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_NEW_CONNECTION, connection); } } @@ -501,7 +504,7 @@ remove_connection (NMSysconfigSettings *self, g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); if (g_hash_table_lookup (priv->connections, connection)) { - g_signal_emit_by_name (G_OBJECT (connection), "removed"); + g_signal_emit_by_name (G_OBJECT (connection), NM_SETTINGS_CONNECTION_INTERFACE_REMOVED); g_hash_table_remove (priv->connections, connection); } } From a4349dac9f719ae27b78f59c694502dbd8469d97 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 11:36:08 -0500 Subject: [PATCH 23/30] libnm-glib: consolidate writable connection checks --- libnm-glib/nm-exported-connection.c | 67 +++++++++++++++-------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/libnm-glib/nm-exported-connection.c b/libnm-glib/nm-exported-connection.c index fa6abb415b..43df56bb59 100644 --- a/libnm-glib/nm-exported-connection.c +++ b/libnm-glib/nm-exported-connection.c @@ -85,6 +85,39 @@ real_get_settings (NMExportedConnection *self, GError **error) /**************************************************************/ +static gboolean +check_writable (NMConnection *connection, GError **error) +{ + NMSettingConnection *s_con; + + g_return_val_if_fail (connection != NULL, FALSE); + g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); + + s_con = (NMSettingConnection *) nm_connection_get_setting (connection, + NM_TYPE_SETTING_CONNECTION); + if (!s_con) { + g_set_error_literal (error, + NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, + "Connection did not have required 'connection' setting"); + return FALSE; + } + + /* If the connection is read-only, that has to be changed at the source of + * the problem (ex a system settings plugin that can't write connections out) + * instead of over D-Bus. + */ + if (nm_setting_connection_get_read_only (s_con)) { + g_set_error_literal (error, + NM_SETTINGS_INTERFACE_ERROR, + NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, + "Connection is read-only"); + return FALSE; + } + + return TRUE; +} + static gboolean impl_exported_connection_get_settings (NMExportedConnection *self, GHashTable **settings, @@ -113,27 +146,12 @@ impl_exported_connection_update (NMExportedConnection *self, { NMConnection *tmp; GError *error = NULL; - NMSettingConnection *s_con; - - s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), - NM_TYPE_SETTING_CONNECTION); - if (!s_con) { - error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, - NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, - "Connection did not have required 'connection' setting"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } /* If the connection is read-only, that has to be changed at the source of * the problem (ex a system settings plugin that can't write connections out) * instead of over D-Bus. */ - if (nm_setting_connection_get_read_only (s_con)) { - error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, - NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, - "Connection is read-only"); + if (!check_writable (NM_CONNECTION (self), &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; @@ -175,23 +193,8 @@ impl_exported_connection_delete (NMExportedConnection *self, DBusGMethodInvocation *context) { GError *error = NULL; - NMSettingConnection *s_con; - s_con = (NMSettingConnection *) nm_connection_get_setting (NM_CONNECTION (self), - NM_TYPE_SETTING_CONNECTION); - if (!s_con) { - error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, - NM_SETTINGS_INTERFACE_ERROR_INVALID_CONNECTION, - "Connection did not have required 'connection' setting"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return; - } - - if (nm_setting_connection_get_read_only (s_con)) { - error = g_error_new_literal (NM_SETTINGS_INTERFACE_ERROR, - NM_SETTINGS_INTERFACE_ERROR_READ_ONLY_CONNECTION, - "Connection is read-only"); + if (!check_writable (NM_CONNECTION (self), &error)) { dbus_g_method_return_error (context, error); g_error_free (error); return; From 909375920bde62b4eac27c771562dba68b043aac Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 12:59:24 -0500 Subject: [PATCH 24/30] libnm-glib: add missing private header --- libnm-glib/nm-remote-connection-private.h | 35 +++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 libnm-glib/nm-remote-connection-private.h diff --git a/libnm-glib/nm-remote-connection-private.h b/libnm-glib/nm-remote-connection-private.h new file mode 100644 index 0000000000..22d84ae743 --- /dev/null +++ b/libnm-glib/nm-remote-connection-private.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* + * libnm_glib -- Access network status & information from glib applications + * + * 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 (C) 2009 Red Hat, Inc. + */ + +#ifndef __NM_REMOTE_CONNECTION_PRIVATE_H__ +#define __NM_REMOTE_CONNECTION_PRIVATE_H__ + +#define NM_REMOTE_CONNECTION_INIT_RESULT "init-result" + +typedef enum { + NM_REMOTE_CONNECTION_INIT_RESULT_UNKNOWN = 0, + NM_REMOTE_CONNECTION_INIT_RESULT_SUCCESS, + NM_REMOTE_CONNECTION_INIT_RESULT_ERROR +} NMRemoteConnectionInitResult; + +#endif /* __NM_REMOTE_CONNECTION_PRIVATE__ */ + From 2dbaab2221c092e1cb1855b14419964b4b8a04fc Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 13:03:09 -0500 Subject: [PATCH 25/30] system-settings: add permissions Since the new PolicyKit does away with easy checking of authorizations, we get to implement it by ourselves, but that's OK since we can actually use it for a lot more stuff. So add the GetPermissions call which returns the permissions the caller actually has, and a signal informing callers that their permissions might have changed. Hook this all up to PolicyKit so it's useful. --- introspection/nm-settings-system.xml | 37 ++++ libnm-glib/libnm_glib.ver | 1 + libnm-glib/nm-remote-settings-system.c | 45 +++++ libnm-glib/nm-settings-system-interface.c | 33 ++++ libnm-glib/nm-settings-system-interface.h | 26 +++ ....network-manager-settings.system.policy.in | 27 +++ src/system-settings/nm-polkit-helpers.h | 5 +- src/system-settings/nm-sysconfig-connection.c | 6 +- src/system-settings/nm-sysconfig-settings.c | 180 +++++++++++++++++- 9 files changed, 348 insertions(+), 12 deletions(-) diff --git a/introspection/nm-settings-system.xml b/introspection/nm-settings-system.xml index ff98719f8f..598274c0d1 100644 --- a/introspection/nm-settings-system.xml +++ b/introspection/nm-settings-system.xml @@ -39,6 +39,43 @@ + + + Emitted when system authorization details change, indicating that clients may wish to recheck permissions with GetPermissions. + + + + + + Returns a bitfield indicating certain operations the caller is permitted to perform. Some of these operations may require authorization by the user. + + + + + + A bitfield of permitted operations. Some of these operations may require the user to authorize via password entry or other means. + + + + + + + No permissions. + + + Can modify/add/delete connections. + + + Can share connections via a encrypted user-created WiFi network. + + + Can share connections via a open/unencrypted user-created WiFi network. + + + Can modify the persistent system hostname. + + + diff --git a/libnm-glib/libnm_glib.ver b/libnm-glib/libnm_glib.ver index f1ea6f0395..342f713dcc 100644 --- a/libnm-glib/libnm_glib.ver +++ b/libnm-glib/libnm_glib.ver @@ -135,6 +135,7 @@ global: nm_settings_service_get_type; nm_settings_system_interface_get_type; nm_settings_system_interface_add_connection; + nm_settings_system_interface_get_permissions; nm_settings_system_interface_save_hostname; nm_settings_error_quark; nm_settings_get_type; diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index fb9b0e2abc..34a810d2e2 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -105,9 +105,53 @@ save_hostname (NMSettingsSystemInterface *settings, NMSettingsSystemSaveHostnameFunc callback, gpointer user_data) { + // FIXME: implement using get_permissions as a template return FALSE; } +typedef struct { + NMSettingsSystemInterface *settings; + NMSettingsSystemGetPermissionsFunc callback; + gpointer callback_data; +} GetPermissionsInfo; + +static void +get_permissions_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GetPermissionsInfo *info = user_data; + NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; + GError *error = NULL; + + dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_UINT, &permissions, + G_TYPE_INVALID); + info->callback (info->settings, permissions, error, info->callback_data); + g_clear_error (&error); +} + +static gboolean +get_permissions (NMSettingsSystemInterface *settings, + NMSettingsSystemGetPermissionsFunc callback, + gpointer user_data) +{ + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings); + GetPermissionsInfo *info; + + info = g_malloc0 (sizeof (GetPermissionsInfo)); + info->settings = settings; + info->callback = callback; + info->callback_data = user_data; + + dbus_g_proxy_begin_call (priv->proxy, "GetPermissions", + get_permissions_cb, + info, + g_free, + G_TYPE_INVALID); + return TRUE; +} + /****************************************************************/ static void @@ -115,6 +159,7 @@ settings_system_interface_init (NMSettingsSystemInterface *klass) { /* interface implementation */ klass->save_hostname = save_hostname; + klass->get_permissions = get_permissions; } /** diff --git a/libnm-glib/nm-settings-system-interface.c b/libnm-glib/nm-settings-system-interface.c index 07114c0fc0..8403793b69 100644 --- a/libnm-glib/nm-settings-system-interface.c +++ b/libnm-glib/nm-settings-system-interface.c @@ -56,9 +56,33 @@ nm_settings_system_interface_save_hostname (NMSettingsSystemInterface *settings, return FALSE; } +/** + * nm_settings_system_interface_get_permissions: + * @settings: a object implementing %NMSettingsSystemInterface + * @callback: callback to be called when the permissions operation completes + * @user_data: caller-specific data passed to @callback + * + * Requests an indication of the operations the caller is permitted to perform + * including those that may require authorization. + **/ +gboolean +nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings, + NMSettingsSystemGetPermissionsFunc callback, + gpointer user_data) +{ + g_return_val_if_fail (settings != NULL, FALSE); + g_return_val_if_fail (NM_IS_SETTINGS_SYSTEM_INTERFACE (settings), FALSE); + g_return_val_if_fail (callback != NULL, FALSE); + + if (NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions) + return NM_SETTINGS_SYSTEM_INTERFACE_GET_INTERFACE (settings)->get_permissions (settings, callback, user_data); + return FALSE; +} + static void nm_settings_system_interface_init (gpointer g_iface) { + GType iface_type = G_TYPE_FROM_INTERFACE (g_iface); static gboolean initialized = FALSE; if (initialized) @@ -81,6 +105,15 @@ nm_settings_system_interface_init (gpointer g_iface) FALSE, G_PARAM_READABLE)); + /* Signals */ + g_signal_new (NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS, + iface_type, + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (NMSettingsSystemInterface, check_permissions), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + initialized = TRUE; } diff --git a/libnm-glib/nm-settings-system-interface.h b/libnm-glib/nm-settings-system-interface.h index 6f535aaa6a..b4ea39e30b 100644 --- a/libnm-glib/nm-settings-system-interface.h +++ b/libnm-glib/nm-settings-system-interface.h @@ -26,6 +26,14 @@ #include "NetworkManager.h" +typedef enum { + NM_SETTINGS_SYSTEM_PERMISSION_NONE = 0x0, + NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY = 0x1, + NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED = 0x2, + NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN = 0x4, + NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY = 0x8 +} NMSettingsSystemPermission; + #define NM_TYPE_SETTINGS_SYSTEM_INTERFACE (nm_settings_system_interface_get_type ()) #define NM_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface)) #define NM_IS_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE)) @@ -34,6 +42,8 @@ #define NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME "hostname" #define NM_SETTINGS_SYSTEM_INTERFACE_CAN_MODIFY "can-modify" +#define NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS "check-permissions" + typedef enum { NM_SETTINGS_SYSTEM_INTERFACE_PROP_FIRST = 0x1000, @@ -49,6 +59,11 @@ typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *set GError *error, gpointer user_data); +typedef void (*NMSettingsSystemGetPermissionsFunc) (NMSettingsSystemInterface *settings, + NMSettingsSystemPermission permissions, + GError *error, + gpointer user_data); + struct _NMSettingsSystemInterface { GTypeInterface g_iface; @@ -57,6 +72,13 @@ struct _NMSettingsSystemInterface { const char *hostname, NMSettingsSystemSaveHostnameFunc callback, gpointer user_data); + + gboolean (*get_permissions) (NMSettingsSystemInterface *settings, + NMSettingsSystemGetPermissionsFunc callback, + gpointer user_data); + + /* Signals */ + void (*check_permissions) (NMSettingsSystemInterface *settings); }; GType nm_settings_system_interface_get_type (void); @@ -66,4 +88,8 @@ gboolean nm_settings_system_interface_save_hostname (NMSettingsSystemInterface * NMSettingsSystemSaveHostnameFunc callback, gpointer user_data); +gboolean nm_settings_system_interface_get_permissions (NMSettingsSystemInterface *settings, + NMSettingsSystemGetPermissionsFunc callback, + gpointer user_data); + #endif /* NM_SETTINGS_SYSTEM_INTERFACE_H */ diff --git a/policy/org.freedesktop.network-manager-settings.system.policy.in b/policy/org.freedesktop.network-manager-settings.system.policy.in index 8b24a23b13..620e3a6a58 100644 --- a/policy/org.freedesktop.network-manager-settings.system.policy.in +++ b/policy/org.freedesktop.network-manager-settings.system.policy.in @@ -18,4 +18,31 @@ + + <_description>Modify persistent system hostname + <_message>System policy prevents modification of the persistent system hostname + + no + auth_admin_keep + + + + + <_description>Connection sharing via a protected WiFi network + <_message>System policy prevents sharing connections via a protected WiFi network + + no + yes + + + + + <_description>Connection sharing via an open WiFi network + <_message>System policy prevents sharing connections via an open WiFi network + + no + yes + + + diff --git a/src/system-settings/nm-polkit-helpers.h b/src/system-settings/nm-polkit-helpers.h index af7cd7a95c..c26fcc2c9b 100644 --- a/src/system-settings/nm-polkit-helpers.h +++ b/src/system-settings/nm-polkit-helpers.h @@ -24,6 +24,9 @@ #include -#define NM_SYSCONFIG_POLICY_ACTION "org.freedesktop.network-manager-settings.system.modify" +#define NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY "org.freedesktop.network-manager-settings.system.modify" +#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED "org.freedesktop.network-manager-settings.system.wifi.share.protected" +#define NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN "org.freedesktop.network-manager-settings.system.wifi.share.open" +#define NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY "org.freedesktop.network-manager-settings.system.hostname.modify" #endif /* NM_POLKIT_HELPERS_H */ diff --git a/src/system-settings/nm-sysconfig-connection.c b/src/system-settings/nm-sysconfig-connection.c index b711c232b0..8be95f5a90 100644 --- a/src/system-settings/nm-sysconfig-connection.c +++ b/src/system-settings/nm-sysconfig-connection.c @@ -296,7 +296,7 @@ dbus_update (NMExportedConnection *exported, g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, - NM_SYSCONFIG_POLICY_ACTION, + NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, call->cancellable, @@ -371,7 +371,7 @@ dbus_delete (NMExportedConnection *exported, g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, - NM_SYSCONFIG_POLICY_ACTION, + NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, call->cancellable, @@ -453,7 +453,7 @@ dbus_get_secrets (NMExportedConnection *exported, g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, - NM_SYSCONFIG_POLICY_ACTION, + NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, call->cancellable, diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index f07ab8da85..6f925de135 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -70,6 +70,9 @@ static void impl_settings_save_hostname (NMSysconfigSettings *self, const char *hostname, DBusGMethodInvocation *context); +static void impl_settings_get_permissions (NMSysconfigSettings *self, + DBusGMethodInvocation *context); + #include "nm-settings-system-glue.h" static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); @@ -513,15 +516,19 @@ typedef struct { NMSysconfigSettings *self; DBusGMethodInvocation *context; PolkitSubject *subject; - GCancellable *cancellable; NMConnection *connection; NMSettingsAddConnectionFunc callback; gpointer callback_data; char *hostname; + + NMSettingsSystemPermission permissions; + guint32 permissions_calls; } PolkitCall; +#include "nm-dbus-manager.h" + static PolkitCall * polkit_call_new (NMSysconfigSettings *self, DBusGMethodInvocation *context, @@ -547,7 +554,6 @@ polkit_call_new (NMSysconfigSettings *self, } if (hostname) call->hostname = g_strdup (hostname); - call->cancellable = g_cancellable_new (); sender = dbus_g_method_get_sender (context); call->subject = polkit_system_bus_name_new (sender); @@ -563,7 +569,6 @@ polkit_call_free (PolkitCall *call) g_object_unref (call->connection); g_free (call->hostname); g_object_unref (call->subject); - g_object_unref (call->cancellable); g_free (call); } @@ -670,10 +675,10 @@ add_connection (NMSettingsService *service, g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, - NM_SYSCONFIG_POLICY_ACTION, + NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - call->cancellable, + NULL, pk_add_cb, call); } @@ -757,14 +762,169 @@ impl_settings_save_hostname (NMSysconfigSettings *self, g_assert (call); polkit_authority_check_authorization (priv->authority, call->subject, - NM_SYSCONFIG_POLICY_ACTION, + NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY, NULL, POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - call->cancellable, + NULL, pk_hostname_cb, call); } +static void +pk_authority_changed_cb (GObject *object, gpointer user_data) +{ + /* Let clients know they should re-check their authorization */ + g_signal_emit_by_name (NM_SYSCONFIG_SETTINGS (user_data), + NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS); +} + +typedef struct { + PolkitCall *pk_call; + const char *pk_action; + NMSettingsSystemPermission permission; +} PermissionsCall; + +static void +permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data) +{ + PermissionsCall *call = user_data; + PolkitCall *pk_call = call->pk_call; + NMSysconfigSettings *self = pk_call->self; + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + PolkitAuthorizationResult *pk_result; + GError *error = NULL; + + pk_result = polkit_authority_check_authorization_finish (priv->authority, + result, + &error); + /* Some random error happened */ + if (error) { + g_warning ("%s.%d (%s): error checking '%s' permission: (%d) %s", + __FILE__, __LINE__, __func__, + call->pk_action, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + if (error) + g_error_free (error); + } else { + /* If the caller is authorized, or the caller could authorize via a + * challenge, then authorization is possible. Otherwise, caller is out of + * luck. + */ + if ( polkit_authorization_result_get_is_authorized (pk_result) + || polkit_authorization_result_get_is_challenge (pk_result)) + pk_call->permissions |= call->permission; + } + + g_object_unref (pk_result); + + pk_call->permissions_calls--; + if (pk_call->permissions_calls == 0) { + /* All the permissions calls are done, return the full permissions + * bitfield back to the user. + */ + dbus_g_method_return (pk_call->context, pk_call->permissions); + + polkit_call_free (pk_call); + } + memset (call, 0, sizeof (PermissionsCall)); + g_free (call); +} + +static void +start_permission_check (NMSysconfigSettings *self, + PolkitCall *pk_call, + const char *pk_action, + NMSettingsSystemPermission permission) +{ + NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); + PermissionsCall *call; + + g_return_if_fail (pk_call != NULL); + g_return_if_fail (pk_action != NULL); + g_return_if_fail (permission != NM_SETTINGS_SYSTEM_PERMISSION_NONE); + + call = g_malloc0 (sizeof (PermissionsCall)); + call->pk_call = pk_call; + call->pk_action = pk_action; + call->permission = permission; + + pk_call->permissions_calls++; + + polkit_authority_check_authorization (priv->authority, + pk_call->subject, + pk_action, + NULL, + 0, + NULL, + permission_call_done, + call); +} + +static void +impl_settings_get_permissions (NMSysconfigSettings *self, + DBusGMethodInvocation *context) +{ + PolkitCall *call; + + call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE); + g_assert (call); + + /* Start checks for the various permissions */ + + /* Only check for connection-modify if one of our plugins supports it. */ + if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) { + start_permission_check (self, call, + NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, + NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY); + } + + /* Only check for hostname-modify if one of our plugins supports it. */ + if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) { + start_permission_check (self, call, + NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY, + NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY); + } + + // FIXME: hook these into plugin permissions like the modify permissions */ + start_permission_check (self, call, + NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN, + NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN); + start_permission_check (self, call, + NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED, + NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED); +} + +static gboolean +get_permissions (NMSettingsSystemInterface *settings, + NMSettingsSystemGetPermissionsFunc callback, + gpointer user_data) +{ + NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings); + NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; + + /* Local caller (ie, NM) gets full permissions by default because it doesn't + * need authorization. However, permissions are still subject to plugin's + * restrictions. i.e. if no plugins support connection-modify, then even + * the local caller won't get that permission. + */ + + /* Only check for connection-modify if one of our plugins supports it. */ + if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) + permissions |= NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY; + + /* Only check for hostname-modify if one of our plugins supports it. */ + if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) + permissions |= NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY; + + // FIXME: hook these into plugin permissions like the modify permissions */ + permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN; + permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED; + + callback (settings, permissions, NULL, user_data); + return TRUE; +} + static gboolean have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac) { @@ -1115,6 +1275,8 @@ finalize (GObject *object) static void settings_system_interface_init (NMSettingsSystemInterface *iface) { + iface->get_permissions = get_permissions; + dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), &dbus_glib_nm_settings_system_object_info); } @@ -1206,7 +1368,9 @@ nm_sysconfig_settings_init (NMSysconfigSettings *self) priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); priv->authority = polkit_authority_get (); - if (!priv->authority) + if (priv->authority) + g_signal_connect (priv->authority, "changed", G_CALLBACK (pk_authority_changed_cb), self); + else g_warning ("%s: failed to create PolicyKit authority.", __func__); /* Grab hostname on startup and use that if no plugins provide one */ From d56674b147c9244907019c3a09f83a49aa87bbf2 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 15:57:11 -0500 Subject: [PATCH 26/30] libnm-glib: NMSettingsSystemPermission -> NMSettingsSystemPermissions --- libnm-glib/nm-remote-settings-system.c | 3 ++- libnm-glib/nm-settings-system-interface.h | 4 ++-- src/system-settings/nm-sysconfig-settings.c | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index 34a810d2e2..270e43cb2c 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -44,6 +44,7 @@ typedef struct { char *hostname; gboolean can_modify; + NMSettingsSystemPermissions permissions; gboolean disposed; } NMRemoteSettingsSystemPrivate; @@ -121,7 +122,7 @@ get_permissions_cb (DBusGProxy *proxy, gpointer user_data) { GetPermissionsInfo *info = user_data; - NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; + NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; GError *error = NULL; dbus_g_proxy_end_call (proxy, call, &error, diff --git a/libnm-glib/nm-settings-system-interface.h b/libnm-glib/nm-settings-system-interface.h index b4ea39e30b..0905402e9f 100644 --- a/libnm-glib/nm-settings-system-interface.h +++ b/libnm-glib/nm-settings-system-interface.h @@ -32,7 +32,7 @@ typedef enum { NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED = 0x2, NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN = 0x4, NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY = 0x8 -} NMSettingsSystemPermission; +} NMSettingsSystemPermissions; #define NM_TYPE_SETTINGS_SYSTEM_INTERFACE (nm_settings_system_interface_get_type ()) #define NM_SETTINGS_SYSTEM_INTERFACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SETTINGS_SYSTEM_INTERFACE, NMSettingsSystemInterface)) @@ -60,7 +60,7 @@ typedef void (*NMSettingsSystemSaveHostnameFunc) (NMSettingsSystemInterface *set gpointer user_data); typedef void (*NMSettingsSystemGetPermissionsFunc) (NMSettingsSystemInterface *settings, - NMSettingsSystemPermission permissions, + NMSettingsSystemPermissions permissions, GError *error, gpointer user_data); diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c index 6f925de135..0f50364091 100644 --- a/src/system-settings/nm-sysconfig-settings.c +++ b/src/system-settings/nm-sysconfig-settings.c @@ -523,7 +523,7 @@ typedef struct { char *hostname; - NMSettingsSystemPermission permissions; + NMSettingsSystemPermissions permissions; guint32 permissions_calls; } PolkitCall; @@ -781,7 +781,7 @@ pk_authority_changed_cb (GObject *object, gpointer user_data) typedef struct { PolkitCall *pk_call; const char *pk_action; - NMSettingsSystemPermission permission; + NMSettingsSystemPermissions permission; } PermissionsCall; static void @@ -835,7 +835,7 @@ static void start_permission_check (NMSysconfigSettings *self, PolkitCall *pk_call, const char *pk_action, - NMSettingsSystemPermission permission) + NMSettingsSystemPermissions permission) { NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); PermissionsCall *call; @@ -901,7 +901,7 @@ get_permissions (NMSettingsSystemInterface *settings, gpointer user_data) { NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings); - NMSettingsSystemPermission permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; + NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; /* Local caller (ie, NM) gets full permissions by default because it doesn't * need authorization. However, permissions are still subject to plugin's From 844ff941865c92384178ac7d1401bfa1424b5bbe Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 16:12:51 -0500 Subject: [PATCH 27/30] libnm-glib: handle system settings permissions changes --- libnm-glib/nm-remote-settings-system.c | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index 270e43cb2c..d5db0ccc69 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -44,7 +44,9 @@ typedef struct { char *hostname; gboolean can_modify; + NMSettingsSystemPermissions permissions; + gboolean have_permissions; gboolean disposed; } NMRemoteSettingsSystemPrivate; @@ -122,12 +124,16 @@ get_permissions_cb (DBusGProxy *proxy, gpointer user_data) { GetPermissionsInfo *info = user_data; + NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (info->settings); + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self); NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; GError *error = NULL; dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_UINT, &permissions, G_TYPE_INVALID); + priv->permissions = permissions; + priv->have_permissions = !error; info->callback (info->settings, permissions, error, info->callback_data); g_clear_error (&error); } @@ -140,6 +146,13 @@ get_permissions (NMSettingsSystemInterface *settings, NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (settings); GetPermissionsInfo *info; + /* Skip D-Bus if we already have permissions */ + if (priv->have_permissions) { + callback (settings, priv->permissions, NULL, user_data); + return TRUE; + } + + /* Otherwise fetch them from NM */ info = g_malloc0 (sizeof (GetPermissionsInfo)); info->settings = settings; info->callback = callback; @@ -153,6 +166,16 @@ get_permissions (NMSettingsSystemInterface *settings, return TRUE; } +static void +check_permissions_cb (NMRemoteSettingsSystem *self) +{ + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self); + + /* Permissions need to be re-fetched */ + priv->have_permissions = FALSE; + g_signal_emit_by_name (self, NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS); +} + /****************************************************************/ static void @@ -231,6 +254,13 @@ constructor (GType type, object, NULL); + /* Monitor for permissions changes */ + dbus_g_proxy_add_signal (priv->proxy, "CheckPermissions", G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "CheckPermissions", + G_CALLBACK (check_permissions_cb), + object, + NULL); + /* Get properties */ dbus_g_proxy_begin_call (priv->props_proxy, "GetAll", get_all_cb, From 243cba8398262f661dd33cdc2ba31ca4586237b1 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 16:17:41 -0500 Subject: [PATCH 28/30] libnm-glib: implement SaveHostname --- libnm-glib/nm-remote-settings-system.c | 37 ++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index d5db0ccc69..34b414c57d 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -102,14 +102,47 @@ get_all_cb (DBusGProxy *proxy, g_hash_table_destroy (props); } +typedef struct { + NMSettingsSystemInterface *settings; + NMSettingsSystemSaveHostnameFunc callback; + gpointer callback_data; +} SaveHostnameInfo; + +static void +save_hostname_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + SaveHostnameInfo *info = user_data; + GError *error = NULL; + + dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID); + info->callback (info->settings, error, info->callback_data); + g_clear_error (&error); +} + static gboolean save_hostname (NMSettingsSystemInterface *settings, const char *hostname, NMSettingsSystemSaveHostnameFunc callback, gpointer user_data) { - // FIXME: implement using get_permissions as a template - return FALSE; + NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (settings); + NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self); + SaveHostnameInfo *info; + + info = g_malloc0 (sizeof (SaveHostnameInfo)); + info->settings = settings; + info->callback = callback; + info->callback_data = user_data; + + dbus_g_proxy_begin_call (priv->proxy, "SaveHostname", + save_hostname_cb, + info, + g_free, + G_TYPE_STRING, hostname ? hostname : "", + G_TYPE_INVALID); + return TRUE; } typedef struct { From 7ededcf7b8ead556df15bb9f44f1639a3f963854 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 19:35:34 -0500 Subject: [PATCH 29/30] libnm-glib: include header for easer use of NMRemoteSettingsSystem --- libnm-glib/nm-remote-settings-system.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libnm-glib/nm-remote-settings-system.h b/libnm-glib/nm-remote-settings-system.h index 09d76dfee7..aeb1188a81 100644 --- a/libnm-glib/nm-remote-settings-system.h +++ b/libnm-glib/nm-remote-settings-system.h @@ -28,6 +28,7 @@ #include #include "nm-remote-settings.h" +#include "nm-settings-system-interface.h" G_BEGIN_DECLS From a5eb29ad9f8f98ac8d3e6f971e2974fd62dd993b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 24 Aug 2009 19:42:00 -0500 Subject: [PATCH 30/30] libnm-glib: fix crash when system permissions change --- libnm-glib/nm-remote-settings-system.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libnm-glib/nm-remote-settings-system.c b/libnm-glib/nm-remote-settings-system.c index 34b414c57d..02aaff4cde 100644 --- a/libnm-glib/nm-remote-settings-system.c +++ b/libnm-glib/nm-remote-settings-system.c @@ -200,8 +200,9 @@ get_permissions (NMSettingsSystemInterface *settings, } static void -check_permissions_cb (NMRemoteSettingsSystem *self) +check_permissions_cb (DBusGProxy *proxy, gpointer user_data) { + NMRemoteSettingsSystem *self = NM_REMOTE_SETTINGS_SYSTEM (user_data); NMRemoteSettingsSystemPrivate *priv = NM_REMOTE_SETTINGS_SYSTEM_GET_PRIVATE (self); /* Permissions need to be re-fetched */