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);