diff options
| author | Michael Biebl <biebl@debian.org> | 2011-05-04 21:35:41 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2011-05-04 21:35:41 +0200 |
| commit | 9f806e97a24bba61417ae312fcc0da40914266fb (patch) | |
| tree | 4a25723414ceac11b4cba0558aa16f6f4b459f4b /src/system-settings/nm-sysconfig-settings.c | |
| parent | 8baa1aca8dfd35e3190d7d5655eb83b5b901e263 (diff) | |
Imported Upstream version 0.8.999 upstream/0.8.999
Diffstat (limited to 'src/system-settings/nm-sysconfig-settings.c')
| -rw-r--r-- | src/system-settings/nm-sysconfig-settings.c | 1596 |
1 files changed, 0 insertions, 1596 deletions
diff --git a/src/system-settings/nm-sysconfig-settings.c b/src/system-settings/nm-sysconfig-settings.c deleted file mode 100644 index 1a1fc6fd..00000000 --- a/src/system-settings/nm-sysconfig-settings.c +++ /dev/null @@ -1,1596 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager system settings service - * - * Søren Sandmann <sandmann@daimi.au.dk> - * Dan Williams <dcbw@redhat.com> - * Tambet Ingo <tambet@gmail.com> - * - * 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 2007 - 2011 Red Hat, Inc. - * (C) Copyright 2008 Novell, Inc. - */ - -#include <unistd.h> -#include <string.h> -#include <gmodule.h> -#include <net/ethernet.h> -#include <netinet/ether.h> - -#include <NetworkManager.h> -#include <nm-connection.h> -#include <dbus/dbus.h> -#include <dbus/dbus-glib-lowlevel.h> -#include <nm-settings-system-interface.h> - -#include <nm-setting-8021x.h> -#include <nm-setting-bluetooth.h> -#include <nm-setting-cdma.h> -#include <nm-setting-connection.h> -#include <nm-setting-gsm.h> -#include <nm-setting-ip4-config.h> -#include <nm-setting-ip6-config.h> -#include <nm-setting-olpc-mesh.h> -#include <nm-setting-ppp.h> -#include <nm-setting-pppoe.h> -#include <nm-setting-serial.h> -#include <nm-setting-vpn.h> -#include <nm-setting-wired.h> -#include <nm-setting-wireless.h> -#include <nm-setting-wireless-security.h> - -#include "../nm-device-ethernet.h" -#include "nm-dbus-glib-types.h" -#include "nm-sysconfig-settings.h" -#include "nm-sysconfig-connection.h" -#include "nm-polkit-helpers.h" -#include "nm-system-config-error.h" -#include "nm-default-wired-connection.h" -#include "nm-logging.h" - -#define CONFIG_KEY_NO_AUTO_DEFAULT "no-auto-default" - -/* LINKER CRACKROCK */ -#define EXPORT(sym) void * __export_##sym = &sym; - -#include "nm-inotify-helper.h" -EXPORT(nm_inotify_helper_get_type) -EXPORT(nm_inotify_helper_get) -EXPORT(nm_inotify_helper_add_watch) -EXPORT(nm_inotify_helper_remove_watch) - -EXPORT(nm_sysconfig_connection_get_type) -EXPORT(nm_sysconfig_connection_update) -/* END LINKER CRACKROCK */ - -static void claim_connection (NMSysconfigSettings *self, - NMSettingsConnectionInterface *connection, - gboolean do_export); - -static void impl_settings_save_hostname (NMSysconfigSettings *self, - const char *hostname, - DBusGMethodInvocation *context); - -static void impl_settings_get_permissions (NMSysconfigSettings *self, - DBusGMethodInvocation *context); - -#include "nm-settings-system-glue.h" - -static void unmanaged_specs_changed (NMSystemConfigInterface *config, gpointer user_data); - -typedef struct { - PolkitAuthority *authority; - guint auth_changed_id; - char *config_file; - - GSList *pk_calls; - GSList *permissions_calls; - - GSList *plugins; - gboolean connections_loaded; - GHashTable *connections; - GSList *unmanaged_specs; -} NMSysconfigSettingsPrivate; - -static void settings_system_interface_init (NMSettingsSystemInterface *klass); - -G_DEFINE_TYPE_WITH_CODE (NMSysconfigSettings, nm_sysconfig_settings, NM_TYPE_SETTINGS_SERVICE, - G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_SYSTEM_INTERFACE, - settings_system_interface_init)) - -#define NM_SYSCONFIG_SETTINGS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SYSCONFIG_SETTINGS, NMSysconfigSettingsPrivate)) - -enum { - PROPERTIES_CHANGED, - - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -enum { - PROP_0, - PROP_UNMANAGED_SPECS, - - LAST_PROP -}; - -static void -load_connections (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - if (priv->connections_loaded) - return; - - for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { - NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data); - GSList *plugin_connections; - GSList *elt; - - plugin_connections = nm_system_config_interface_get_connections (plugin); - - // FIXME: ensure connections from plugins loaded with a lower priority - // get rejected when they conflict with connections from a higher - // priority plugin. - - for (elt = plugin_connections; elt; elt = g_slist_next (elt)) - claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (elt->data), TRUE); - - g_slist_free (plugin_connections); - } - - priv->connections_loaded = TRUE; - - /* FIXME: Bad hack */ - unmanaged_specs_changed (NULL, self); -} - -static GSList * -list_connections (NMSettingsService *settings) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (settings); - GHashTableIter iter; - gpointer key; - GSList *list = NULL; - - load_connections (NM_SYSCONFIG_SETTINGS (settings)); - - g_hash_table_iter_init (&iter, priv->connections); - while (g_hash_table_iter_next (&iter, &key, NULL)) - list = g_slist_prepend (list, NM_EXPORTED_CONNECTION (key)); - return g_slist_reverse (list); -} - -static void -clear_unmanaged_specs (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - g_slist_foreach (priv->unmanaged_specs, (GFunc) g_free, NULL); - g_slist_free (priv->unmanaged_specs); - priv->unmanaged_specs = NULL; -} - -static char* -uscore_to_wincaps (const char *uscore) -{ - const char *p; - GString *str; - gboolean last_was_uscore; - - last_was_uscore = TRUE; - - str = g_string_new (NULL); - p = uscore; - while (p && *p) { - if (*p == '-' || *p == '_') - last_was_uscore = TRUE; - else { - if (last_was_uscore) { - g_string_append_c (str, g_ascii_toupper (*p)); - last_was_uscore = FALSE; - } else - g_string_append_c (str, *p); - } - ++p; - } - - return g_string_free (str, FALSE); -} - -static void -notify (GObject *object, GParamSpec *pspec) -{ - GValue *value; - GHashTable *hash; - - value = g_slice_new0 (GValue); - hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL); - - g_value_init (value, pspec->value_type); - g_object_get_property (object, pspec->name, value); - g_hash_table_insert (hash, uscore_to_wincaps (pspec->name), value); - g_signal_emit (object, signals[PROPERTIES_CHANGED], 0, hash); - g_hash_table_destroy (hash); - g_value_unset (value); - g_slice_free (GValue, value); -} - -const GSList * -nm_sysconfig_settings_get_unmanaged_specs (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - load_connections (self); - return priv->unmanaged_specs; -} - -static NMSystemConfigInterface * -get_plugin (NMSysconfigSettings *self, guint32 capability) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - g_return_val_if_fail (self != NULL, NULL); - - /* Do any of the plugins support setting the hostname? */ - for (iter = priv->plugins; iter; iter = iter->next) { - NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE; - - g_object_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES, &caps, NULL); - if (caps & capability) - return NM_SYSTEM_CONFIG_INTERFACE (iter->data); - } - - return NULL; -} - -/* Returns an allocated string which the caller owns and must eventually free */ -char * -nm_sysconfig_settings_get_hostname (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - char *hostname = NULL; - - /* Hostname returned is the hostname returned from the first plugin - * that provides one. - */ - for (iter = priv->plugins; iter; iter = iter->next) { - NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE; - - 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_get (G_OBJECT (iter->data), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME, &hostname, NULL); - if (hostname && strlen (hostname)) - return hostname; - g_free (hostname); - } - } - - return NULL; -} - -static void -plugin_connection_added (NMSystemConfigInterface *config, - NMSettingsConnectionInterface *connection, - gpointer user_data) -{ - claim_connection (NM_SYSCONFIG_SETTINGS (user_data), connection, TRUE); -} - -static gboolean -find_unmanaged_device (NMSysconfigSettings *self, const char *needle) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - for (iter = priv->unmanaged_specs; iter; iter = g_slist_next (iter)) { - if (!strcmp ((const char *) iter->data, needle)) - return TRUE; - } - return FALSE; -} - -static void -unmanaged_specs_changed (NMSystemConfigInterface *config, - gpointer user_data) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (user_data); - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - clear_unmanaged_specs (self); - - /* Ask all the plugins for their unmanaged specs */ - for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { - GSList *specs, *specs_iter; - - specs = nm_system_config_interface_get_unmanaged_specs (NM_SYSTEM_CONFIG_INTERFACE (iter->data)); - for (specs_iter = specs; specs_iter; specs_iter = specs_iter->next) { - if (!find_unmanaged_device (self, (const char *) specs_iter->data)) { - priv->unmanaged_specs = g_slist_prepend (priv->unmanaged_specs, specs_iter->data); - } else - g_free (specs_iter->data); - } - - g_slist_free (specs); - } - - g_object_notify (G_OBJECT (self), NM_SYSCONFIG_SETTINGS_UNMANAGED_SPECS); -} - -static void -hostname_changed (NMSystemConfigInterface *config, - GParamSpec *pspec, - gpointer user_data) -{ - g_object_notify (G_OBJECT (user_data), NM_SETTINGS_SYSTEM_INTERFACE_HOSTNAME); -} - -static void -add_plugin (NMSysconfigSettings *self, NMSystemConfigInterface *plugin) -{ - NMSysconfigSettingsPrivate *priv; - char *pname = NULL; - char *pinfo = NULL; - - g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self)); - g_return_if_fail (NM_IS_SYSTEM_CONFIG_INTERFACE (plugin)); - - priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - priv->plugins = g_slist_append (priv->plugins, g_object_ref (plugin)); - - g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, - G_CALLBACK (plugin_connection_added), self); - g_signal_connect (plugin, "notify::hostname", G_CALLBACK (hostname_changed), self); - - nm_system_config_interface_init (plugin, NULL); - - g_object_get (G_OBJECT (plugin), - NM_SYSTEM_CONFIG_INTERFACE_NAME, &pname, - NM_SYSTEM_CONFIG_INTERFACE_INFO, &pinfo, - NULL); - - g_signal_connect (plugin, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED, - G_CALLBACK (unmanaged_specs_changed), self); - - nm_log_info (LOGD_SYS_SET, "Loaded plugin %s: %s", pname, pinfo); - g_free (pname); - g_free (pinfo); -} - -static GObject * -find_plugin (GSList *list, const char *pname) -{ - GSList *iter; - GObject *obj = NULL; - - g_return_val_if_fail (pname != NULL, FALSE); - - for (iter = list; iter && !obj; iter = g_slist_next (iter)) { - NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data); - char *list_pname = NULL; - - g_object_get (G_OBJECT (plugin), - NM_SYSTEM_CONFIG_INTERFACE_NAME, - &list_pname, - NULL); - if (list_pname && !strcmp (pname, list_pname)) - obj = G_OBJECT (plugin); - - g_free (list_pname); - } - - return obj; -} - -static gboolean -load_plugins (NMSysconfigSettings *self, const char *plugins, GError **error) -{ - GSList *list = NULL; - char **plist; - char **iter; - gboolean success = TRUE; - - plist = g_strsplit (plugins, ",", 0); - if (!plist) - return FALSE; - - for (iter = plist; *iter; iter++) { - GModule *plugin; - char *full_name, *path; - const char *pname = g_strstrip (*iter); - GObject *obj; - GObject * (*factory_func) (void); - - /* ifcfg-fedora was renamed ifcfg-rh; handle old configs here */ - if (!strcmp (pname, "ifcfg-fedora")) - pname = "ifcfg-rh"; - - obj = find_plugin (list, pname); - if (obj) - continue; - - full_name = g_strdup_printf ("nm-settings-plugin-%s", pname); - path = g_module_build_path (PLUGINDIR, full_name); - - plugin = g_module_open (path, G_MODULE_BIND_LOCAL); - if (!plugin) { - g_set_error (error, 0, 0, - "Could not load plugin '%s': %s", - pname, g_module_error ()); - g_free (full_name); - g_free (path); - success = FALSE; - break; - } - - g_free (full_name); - g_free (path); - - if (!g_module_symbol (plugin, "nm_system_config_factory", (gpointer) (&factory_func))) { - g_set_error (error, 0, 0, - "Could not find plugin '%s' factory function.", - pname); - success = FALSE; - break; - } - - obj = (*factory_func) (); - if (!obj || !NM_IS_SYSTEM_CONFIG_INTERFACE (obj)) { - g_set_error (error, 0, 0, - "Plugin '%s' returned invalid system config object.", - pname); - success = FALSE; - break; - } - - g_module_make_resident (plugin); - g_object_weak_ref (obj, (GWeakNotify) g_module_close, plugin); - add_plugin (self, NM_SYSTEM_CONFIG_INTERFACE (obj)); - list = g_slist_append (list, obj); - } - - g_strfreev (plist); - - g_slist_foreach (list, (GFunc) g_object_unref, NULL); - g_slist_free (list); - - return success; -} - -static void -connection_removed (NMSettingsConnectionInterface *connection, - gpointer user_data) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (user_data); - NMSettingConnection *s_con; - GKeyFile *timestamps_file; - const char *connection_uuid; - char *data; - gsize len; - GError *error = NULL; - - /* Remove connection from the table */ - g_hash_table_remove (priv->connections, connection); - - /* Remove timestamp from timestamps database file */ - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); - connection_uuid = nm_setting_connection_get_uuid (s_con); - - timestamps_file = g_key_file_new (); - if (g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) { - g_key_file_remove_key (timestamps_file, "timestamps", connection_uuid, NULL); - data = g_key_file_to_data (timestamps_file, &len, &error); - if (data) { - g_file_set_contents (NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, data, len, &error); - g_free (data); - } - if (error) { - nm_log_warn (LOGD_SYS_SET, "error writing timestamps file '%s': %s", NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, error->message); - g_error_free (error); - } - } - g_key_file_free (timestamps_file); -} - -static void -claim_connection (NMSysconfigSettings *self, - NMSettingsConnectionInterface *connection, - gboolean do_export) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - NMSettingConnection *s_con; - const char *connection_uuid; - guint64 timestamp = 0; - GKeyFile *timestamps_file; - GError *err = NULL; - char *tmp_str; - - g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self)); - g_return_if_fail (NM_IS_SETTINGS_CONNECTION_INTERFACE (connection)); - - if (g_hash_table_lookup (priv->connections, connection)) - /* A plugin is lying to us. */ - return; - - /* Read timestamp from database file and store it into connection's object data */ - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (NM_CONNECTION (connection), NM_TYPE_SETTING_CONNECTION)); - g_assert (s_con); - connection_uuid = nm_setting_connection_get_uuid (s_con); - - timestamps_file = g_key_file_new (); - g_key_file_load_from_file (timestamps_file, NM_SYSCONFIG_SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL); - tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &err); - if (tmp_str) { - timestamp = g_ascii_strtoull (tmp_str, NULL, 10); - g_free (tmp_str); - } - - /* Update connection's timestamp */ - if (!err) { - guint64 *ts_ptr = g_new (guint64, 1); - - *ts_ptr = timestamp; - g_object_set_data_full (G_OBJECT (connection), NM_SYSCONFIG_SETTINGS_TIMESTAMP_TAG, ts_ptr, g_free); - } else { - nm_log_dbg (LOGD_SYS_SET, "failed to read connection timestamp for '%s': (%d) %s", - connection_uuid, err->code, err->message); - g_clear_error (&err); - } - g_key_file_free (timestamps_file); - - g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1)); - g_signal_connect (connection, - NM_SETTINGS_CONNECTION_INTERFACE_REMOVED, - G_CALLBACK (connection_removed), - self); - - if (do_export) { - nm_settings_service_export_connection (NM_SETTINGS_SERVICE (self), connection); - g_signal_emit_by_name (self, NM_SETTINGS_INTERFACE_NEW_CONNECTION, connection); - } -} - -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_SETTINGS_CONNECTION_INTERFACE (connection)); - - if (g_hash_table_lookup (priv->connections, connection)) { - g_signal_emit_by_name (G_OBJECT (connection), NM_SETTINGS_CONNECTION_INTERFACE_REMOVED); - g_hash_table_remove (priv->connections, connection); - } -} - -typedef struct { - NMSysconfigSettings *self; - DBusGMethodInvocation *context; - PolkitSubject *subject; - GCancellable *cancellable; - gboolean disposed; - - NMConnection *connection; - NMSettingsAddConnectionFunc callback; - gpointer callback_data; - - char *hostname; - - NMSettingsSystemPermissions permissions; - guint32 permissions_calls; -} PolkitCall; - -#include "nm-dbus-manager.h" - -static PolkitCall * -polkit_call_new (NMSysconfigSettings *self, - DBusGMethodInvocation *context, - NMConnection *connection, - NMSettingsAddConnectionFunc callback, - gpointer callback_data, - 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->cancellable = g_cancellable_new (); - call->context = context; - if (connection) - call->connection = g_object_ref (connection); - if (callback) { - call->callback = callback; - call->callback_data = callback_data; - } - if (hostname) - call->hostname = g_strdup (hostname); - - 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_object_unref (call->cancellable); - g_free (call->hostname); - g_object_unref (call->subject); - g_free (call); -} - -static gboolean -add_new_connection (NMSysconfigSettings *self, - NMConnection *connection, - GError **error) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GError *tmp_error = NULL, *last_error = NULL; - GSList *iter; - gboolean success = FALSE; - - /* Here's how it works: - 1) plugin writes a connection. - 2) plugin notices that a new connection is available for reading. - 3) plugin reads the new connection (the one it wrote in 1) and emits 'connection-added' signal. - 4) NMSysconfigSettings receives the signal and adds it to it's connection list. - */ - - 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); - g_clear_error (&last_error); - if (!success) { - last_error = tmp_error; - tmp_error = NULL; - } - } - - if (!success) - *error = last_error; - return success; -} - -static void -pk_add_cb (GObject *object, GAsyncResult *result, gpointer user_data) -{ - PolkitCall *call = user_data; - NMSysconfigSettings *self = call->self; - NMSysconfigSettingsPrivate *priv; - PolkitAuthorizationResult *pk_result; - GError *error = NULL, *add_error = NULL; - - /* If NMSysconfigSettings is already gone, do nothing */ - if (call->disposed) { - error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "Request was canceled."); - dbus_g_method_return_error (call->context, error); - g_error_free (error); - polkit_call_free (call); - return; - } - - priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - priv->pk_calls = g_slist_remove (priv->pk_calls, call); - - pk_result = polkit_authority_check_authorization_finish (priv->authority, - result, - &error); - /* Some random error happened */ - if (error) { - call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); - 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."); - call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); - goto out; - } - - if (add_new_connection (self, call->connection, &add_error)) - call->callback (NM_SETTINGS_INTERFACE (self), NULL, call->callback_data); - else { - error = g_error_new (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_ADD_FAILED, - "Saving connection failed: (%d) %s", - add_error ? add_error->code : -1, - (add_error && add_error->message) ? add_error->message : "(unknown)"); - g_error_free (add_error); - call->callback (NM_SETTINGS_INTERFACE (self), error, call->callback_data); - } - -out: - g_clear_error (&error); - polkit_call_free (call); - if (pk_result) - g_object_unref (pk_result); -} - -static void -add_connection (NMSettingsService *service, - NMConnection *connection, - DBusGMethodInvocation *context, /* Only present for D-Bus calls */ - NMSettingsAddConnectionFunc callback, - gpointer user_data) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (service); - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - PolkitCall *call; - GError *error = NULL; - - /* Do any of the plugins support adding? */ - 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."); - callback (NM_SETTINGS_INTERFACE (service), error, user_data); - g_error_free (error); - return; - } - - call = polkit_call_new (self, context, connection, callback, user_data, NULL); - g_assert (call); - polkit_authority_check_authorization (priv->authority, - call->subject, - NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, - NULL, - POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - call->cancellable, - pk_add_cb, - call); - priv->pk_calls = g_slist_append (priv->pk_calls, call); -} - -static void -pk_hostname_cb (GObject *object, GAsyncResult *result, gpointer user_data) -{ - PolkitCall *call = user_data; - NMSysconfigSettings *self = call->self; - NMSysconfigSettingsPrivate *priv; - PolkitAuthorizationResult *pk_result; - GError *error = NULL; - GSList *iter; - gboolean success = FALSE; - - /* If our NMSysconfigConnection is already gone, do nothing */ - if (call->disposed) { - error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "Request was canceled."); - dbus_g_method_return_error (call->context, error); - g_error_free (error); - polkit_call_free (call); - return; - } - - priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - priv->pk_calls = g_slist_remove (priv->pk_calls, call); - - 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; - } - - /* Set the hostname in all plugins */ - for (iter = priv->plugins; iter; iter = iter->next) { - NMSystemConfigInterfaceCapabilities caps = NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE; - - 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, call->hostname, NULL); - success = TRUE; - } - } - - 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: - 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, NULL, NULL, hostname); - g_assert (call); - polkit_authority_check_authorization (priv->authority, - call->subject, - NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY, - NULL, - POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, - call->cancellable, - pk_hostname_cb, - call); - priv->pk_calls = g_slist_append (priv->pk_calls, call); -} - -static void -pk_authority_changed_cb (GObject *object, gpointer user_data) -{ - /* Let clients know they should re-check their authorization */ - g_signal_emit_by_name (NM_SYSCONFIG_SETTINGS (user_data), - NM_SETTINGS_SYSTEM_INTERFACE_CHECK_PERMISSIONS); -} - -typedef struct { - PolkitCall *pk_call; - const char *pk_action; - GCancellable *cancellable; - NMSettingsSystemPermissions permission; - gboolean disposed; -} PermissionsCall; - -static void -permission_call_done (GObject *object, GAsyncResult *result, gpointer user_data) -{ - PermissionsCall *call = user_data; - PolkitCall *pk_call = call->pk_call; - NMSysconfigSettings *self = pk_call->self; - NMSysconfigSettingsPrivate *priv; - PolkitAuthorizationResult *pk_result; - GError *error = NULL; - - /* If NMSysconfigSettings is gone, just skip to the end */ - if (call->disposed) - goto done; - - priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - priv->permissions_calls = g_slist_remove (priv->permissions_calls, call); - - pk_result = polkit_authority_check_authorization_finish (priv->authority, - result, - &error); - /* Some random error happened */ - if (error) { - nm_log_err (LOGD_SYS_SET, "error checking '%s' permission: (%d) %s", - call->pk_action, - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - if (error) - g_error_free (error); - } else { - /* If the caller is authorized, or the caller could authorize via a - * challenge, then authorization is possible. Otherwise, caller is out of - * luck. - */ - if ( polkit_authorization_result_get_is_authorized (pk_result) - || polkit_authorization_result_get_is_challenge (pk_result)) - pk_call->permissions |= call->permission; - } - - g_object_unref (pk_result); - -done: - pk_call->permissions_calls--; - if (pk_call->permissions_calls == 0) { - if (call->disposed) { - error = g_error_new_literal (NM_SYSCONFIG_SETTINGS_ERROR, - NM_SYSCONFIG_SETTINGS_ERROR_GENERAL, - "Request was canceled."); - dbus_g_method_return_error (pk_call->context, error); - g_error_free (error); - } else { - /* All the permissions calls are done, return the full permissions - * bitfield back to the user. - */ - dbus_g_method_return (pk_call->context, pk_call->permissions); - } - - polkit_call_free (pk_call); - } - memset (call, 0, sizeof (PermissionsCall)); - g_free (call); -} - -static void -start_permission_check (NMSysconfigSettings *self, - PolkitCall *pk_call, - const char *pk_action, - NMSettingsSystemPermissions permission) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - PermissionsCall *call; - - g_return_if_fail (pk_call != NULL); - g_return_if_fail (pk_action != NULL); - g_return_if_fail (permission != NM_SETTINGS_SYSTEM_PERMISSION_NONE); - - call = g_malloc0 (sizeof (PermissionsCall)); - call->pk_call = pk_call; - call->pk_action = pk_action; - call->permission = permission; - call->cancellable = g_cancellable_new (); - - pk_call->permissions_calls++; - - polkit_authority_check_authorization (priv->authority, - pk_call->subject, - pk_action, - NULL, - 0, - call->cancellable, - permission_call_done, - call); - priv->permissions_calls = g_slist_append (priv->permissions_calls, call); -} - -static void -impl_settings_get_permissions (NMSysconfigSettings *self, - DBusGMethodInvocation *context) -{ - PolkitCall *call; - - call = polkit_call_new (self, context, NULL, NULL, NULL, FALSE); - g_assert (call); - - /* Start checks for the various permissions */ - - /* Only check for connection-modify if one of our plugins supports it. */ - if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) { - start_permission_check (self, call, - NM_SYSCONFIG_POLICY_ACTION_CONNECTION_MODIFY, - NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY); - } - - /* Only check for hostname-modify if one of our plugins supports it. */ - if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) { - start_permission_check (self, call, - NM_SYSCONFIG_POLICY_ACTION_HOSTNAME_MODIFY, - NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY); - } - - // FIXME: hook these into plugin permissions like the modify permissions */ - start_permission_check (self, call, - NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_OPEN, - NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN); - start_permission_check (self, call, - NM_SYSCONFIG_POLICY_ACTION_WIFI_SHARE_PROTECTED, - NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED); -} - -static gboolean -get_permissions (NMSettingsSystemInterface *settings, - NMSettingsSystemGetPermissionsFunc callback, - gpointer user_data) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (settings); - NMSettingsSystemPermissions permissions = NM_SETTINGS_SYSTEM_PERMISSION_NONE; - - /* Local caller (ie, NM) gets full permissions by default because it doesn't - * need authorization. However, permissions are still subject to plugin's - * restrictions. i.e. if no plugins support connection-modify, then even - * the local caller won't get that permission. - */ - - /* Only check for connection-modify if one of our plugins supports it. */ - if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) - permissions |= NM_SETTINGS_SYSTEM_PERMISSION_CONNECTION_MODIFY; - - /* Only check for hostname-modify if one of our plugins supports it. */ - if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME)) - permissions |= NM_SETTINGS_SYSTEM_PERMISSION_HOSTNAME_MODIFY; - - // FIXME: hook these into plugin permissions like the modify permissions */ - permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_OPEN; - permissions |= NM_SETTINGS_SYSTEM_PERMISSION_WIFI_SHARE_PROTECTED; - - callback (settings, permissions, NULL, user_data); - return TRUE; -} - -static gboolean -have_connection_for_device (NMSysconfigSettings *self, GByteArray *mac) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GHashTableIter iter; - gpointer key; - NMSettingConnection *s_con; - NMSettingWired *s_wired; - const GByteArray *setting_mac; - gboolean ret = FALSE; - - g_return_val_if_fail (NM_IS_SYSCONFIG_SETTINGS (self), FALSE); - g_return_val_if_fail (mac != NULL, FALSE); - - /* Find a wired connection locked to the given MAC address, if any */ - 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; - - s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); - connection_type = nm_setting_connection_get_connection_type (s_con); - - if ( strcmp (connection_type, NM_SETTING_WIRED_SETTING_NAME) - && strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) - continue; - - s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED); - - /* No wired setting; therefore the PPPoE connection applies to any device */ - if (!s_wired && !strcmp (connection_type, NM_SETTING_PPPOE_SETTING_NAME)) { - ret = TRUE; - break; - } - - setting_mac = nm_setting_wired_get_mac_address (s_wired); - if (setting_mac) { - /* A connection mac-locked to this device */ - if (!memcmp (setting_mac->data, mac->data, ETH_ALEN)) { - ret = TRUE; - break; - } - } else { - /* A connection that applies to any wired device */ - ret = TRUE; - break; - } - } - - return ret; -} - -/* Search through the list of blacklisted MAC addresses in the config file. */ -static gboolean -is_mac_auto_wired_blacklisted (NMSysconfigSettings *self, const GByteArray *mac) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GKeyFile *config; - char **list, **iter; - gboolean found = FALSE; - - g_return_val_if_fail (mac != NULL, FALSE); - - if (!priv->config_file) - return FALSE; - - config = g_key_file_new (); - if (!config) { - nm_log_warn (LOGD_SYS_SET, "not enough memory to load config file."); - return FALSE; - } - - g_key_file_set_list_separator (config, ','); - if (!g_key_file_load_from_file (config, priv->config_file, G_KEY_FILE_NONE, NULL)) - goto out; - - list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, NULL, NULL); - for (iter = list; iter && *iter; iter++) { - struct ether_addr *candidate; - - if (strcmp(g_strstrip(*iter), "*") == 0) { - found = TRUE; - break; - } - - candidate = ether_aton (*iter); - if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) { - found = TRUE; - break; - } - } - - if (list) - g_strfreev (list); - -out: - g_key_file_free (config); - return found; -} - -#define DEFAULT_WIRED_TAG "default-wired" - -static void -default_wired_deleted (NMDefaultWiredConnection *wired, - const GByteArray *mac, - NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - NMSettingConnection *s_con; - char *tmp; - GKeyFile *config; - char **list, **iter, **updated; - gboolean found = FALSE; - gsize len = 0, i; - char *data; - - /* If there was no config file specified, there's nothing to do */ - if (!priv->config_file) - goto cleanup; - - /* When the default wired connection is removed (either deleted or saved - * to a new persistent connection by a plugin), write the MAC address of - * the wired device to the config file and don't create a new default wired - * connection for that device again. - */ - - 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 - * been removed by the user. - */ - if (nm_setting_connection_get_read_only (s_con)) - goto cleanup; - - config = g_key_file_new (); - if (!config) - goto cleanup; - - g_key_file_set_list_separator (config, ','); - g_key_file_load_from_file (config, priv->config_file, G_KEY_FILE_KEEP_COMMENTS, NULL); - - list = g_key_file_get_string_list (config, "main", CONFIG_KEY_NO_AUTO_DEFAULT, &len, NULL); - for (iter = list; iter && *iter; iter++) { - struct ether_addr *candidate; - - if (strcmp(g_strstrip(*iter), "*") == 0) { - found = TRUE; - break; - } - - candidate = ether_aton (*iter); - if (candidate && !memcmp (mac->data, candidate->ether_addr_octet, ETH_ALEN)) { - found = TRUE; - break; - } - } - - /* Add this device's MAC to the list */ - if (!found) { - tmp = g_strdup_printf ("%02x:%02x:%02x:%02x:%02x:%02x", - mac->data[0], mac->data[1], mac->data[2], - mac->data[3], mac->data[4], mac->data[5]); - - /* New list; size + 1 for the new element, + 1 again for ending NULL */ - updated = g_malloc0 (sizeof (char*) * (len + 2)); - - /* Copy original list and add new MAC */ - for (i = 0; list && list[i]; i++) - updated[i] = list[i]; - updated[i++] = tmp; - updated[i] = NULL; - - g_key_file_set_string_list (config, - "main", CONFIG_KEY_NO_AUTO_DEFAULT, - (const char **) updated, - len + 2); - /* g_free() not g_strfreev() since 'updated' isn't a deep-copy */ - g_free (updated); - g_free (tmp); - - data = g_key_file_to_data (config, &len, NULL); - if (data) { - g_file_set_contents (priv->config_file, data, len, NULL); - g_free (data); - } - } - - if (list) - g_strfreev (list); - g_key_file_free (config); - -cleanup: - g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)), - DEFAULT_WIRED_TAG, - NULL); -} - -static void -delete_cb (NMSettingsConnectionInterface *connection, GError *error, gpointer user_data) -{ -} - -static gboolean -default_wired_try_update (NMDefaultWiredConnection *wired, - NMSysconfigSettings *self) -{ - GError *error = NULL; - NMSettingConnection *s_con; - const char *id; - - /* Try to move this default wired conneciton to a plugin so that it has - * persistent storage. - */ - - 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); - - remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE); - if (add_new_connection (self, NM_CONNECTION (wired), &error)) { - nm_settings_connection_interface_delete (NM_SETTINGS_CONNECTION_INTERFACE (wired), - delete_cb, - NULL); - - g_object_set_data (G_OBJECT (nm_default_wired_connection_get_device (wired)), - DEFAULT_WIRED_TAG, - NULL); - nm_log_info (LOGD_SYS_SET, "Saved default wired connection '%s' to persistent storage", id); - return FALSE; - } - - nm_log_warn (LOGD_SYS_SET, "couldn't save default wired connection '%s': %d / %s", - id, - error ? error->code : -1, - (error && error->message) ? error->message : "(unknown)"); - - /* 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. - */ - claim_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (wired), FALSE); - return TRUE; -} - -void -nm_sysconfig_settings_device_added (NMSysconfigSettings *self, NMDevice *device) -{ - GByteArray *mac = NULL; - struct ether_addr tmp; - NMDefaultWiredConnection *wired; - NMSettingConnection *s_con; - gboolean read_only = TRUE; - const char *id; - - if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET) - return; - - /* If the device isn't managed or it already has a default wired connection, - * ignore it. - */ - if ( !nm_device_get_managed (device) - || g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG)) - return; - - nm_device_ethernet_get_address (NM_DEVICE_ETHERNET (device), &tmp); - - mac = g_byte_array_sized_new (ETH_ALEN); - g_byte_array_append (mac, tmp.ether_addr_octet, ETH_ALEN); - - if ( have_connection_for_device (self, mac) - || is_mac_auto_wired_blacklisted (self, mac)) - goto ignore; - - if (get_plugin (self, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS)) - read_only = FALSE; - - wired = nm_default_wired_connection_new (mac, device, read_only); - if (!wired) - goto ignore; - - 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_log_info (LOGD_SYS_SET, "Added default wired connection '%s' for %s", - id, nm_device_get_udi (device)); - - 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, wired); - -ignore: - g_byte_array_free (mac, TRUE); -} - -void -nm_sysconfig_settings_device_removed (NMSysconfigSettings *self, NMDevice *device) -{ - NMDefaultWiredConnection *connection; - - if (nm_device_get_device_type (device) != NM_DEVICE_TYPE_ETHERNET) - return; - - connection = (NMDefaultWiredConnection *) g_object_get_data (G_OBJECT (device), DEFAULT_WIRED_TAG); - if (connection) - remove_connection (self, NM_SETTINGS_CONNECTION_INTERFACE (connection), TRUE); -} - -NMSysconfigSettings * -nm_sysconfig_settings_new (const char *config_file, - const char *plugins, - DBusGConnection *bus, - GError **error) -{ - NMSysconfigSettings *self; - NMSysconfigSettingsPrivate *priv; - - self = g_object_new (NM_TYPE_SYSCONFIG_SETTINGS, - NM_SETTINGS_SERVICE_BUS, bus, - NM_SETTINGS_SERVICE_SCOPE, NM_CONNECTION_SCOPE_SYSTEM, - NULL); - if (!self) - return NULL; - - priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - - priv->config_file = g_strdup (config_file); - - if (plugins) { - /* Load the plugins; fail if a plugin is not found. */ - if (!load_plugins (self, plugins, error)) { - g_object_unref (self); - return NULL; - } - unmanaged_specs_changed (NULL, self); - } - - return self; -} - -/***************************************************************/ - -static void -dispose (GObject *object) -{ - NMSysconfigSettings *self = NM_SYSCONFIG_SETTINGS (object); - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GSList *iter; - - if (priv->auth_changed_id) { - g_signal_handler_disconnect (priv->authority, priv->auth_changed_id); - priv->auth_changed_id = 0; - } - - /* Cancel PolicyKit requests */ - for (iter = priv->pk_calls; iter; iter = g_slist_next (iter)) { - PolkitCall *call = iter->data; - - call->disposed = TRUE; - g_cancellable_cancel (call->cancellable); - } - g_slist_free (priv->pk_calls); - priv->pk_calls = NULL; - - /* Cancel PolicyKit permissions requests */ - for (iter = priv->permissions_calls; iter; iter = g_slist_next (iter)) { - PermissionsCall *call = iter->data; - - call->disposed = TRUE; - g_cancellable_cancel (call->cancellable); - } - g_slist_free (priv->permissions_calls); - priv->permissions_calls = NULL; - - G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->dispose (object); -} - -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); - - g_free (priv->config_file); - - G_OBJECT_CLASS (nm_sysconfig_settings_parent_class)->finalize (object); -} - -static void -settings_system_interface_init (NMSettingsSystemInterface *iface) -{ - iface->get_permissions = get_permissions; - - dbus_g_object_type_install_info (G_TYPE_FROM_INTERFACE (iface), - &dbus_glib_nm_settings_system_object_info); -} - -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 NM_SETTINGS_SYSTEM_INTERFACE_PROP_HOSTNAME: - g_value_take_string (value, nm_sysconfig_settings_get_hostname (self)); - - /* Don't ever pass NULL through D-Bus */ - if (!g_value_get_string (value)) - g_value_set_static_string (value, ""); - break; - case NM_SETTINGS_SYSTEM_INTERFACE_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); - NMSettingsServiceClass *ss_class = NM_SETTINGS_SERVICE_CLASS (class); - - g_type_class_add_private (class, sizeof (NMSysconfigSettingsPrivate)); - - /* virtual methods */ - object_class->notify = notify; - object_class->get_property = get_property; - object_class->dispose = dispose; - object_class->finalize = finalize; - ss_class->list_connections = list_connections; - ss_class->add_connection = add_connection; - - /* 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_error_domain_register (NM_SYSCONFIG_SETTINGS_ERROR, - NM_DBUS_IFACE_SETTINGS_SYSTEM, - NM_TYPE_SYSCONFIG_SETTINGS_ERROR); - - dbus_g_error_domain_register (NM_SETTINGS_INTERFACE_ERROR, - NM_DBUS_IFACE_SETTINGS, - NM_TYPE_SETTINGS_INTERFACE_ERROR); - - /* And register all the settings errors with D-Bus */ - dbus_g_error_domain_register (NM_CONNECTION_ERROR, NULL, NM_TYPE_CONNECTION_ERROR); - dbus_g_error_domain_register (NM_SETTING_802_1X_ERROR, NULL, NM_TYPE_SETTING_802_1X_ERROR); - dbus_g_error_domain_register (NM_SETTING_BLUETOOTH_ERROR, NULL, NM_TYPE_SETTING_BLUETOOTH_ERROR); - dbus_g_error_domain_register (NM_SETTING_CDMA_ERROR, NULL, NM_TYPE_SETTING_CDMA_ERROR); - dbus_g_error_domain_register (NM_SETTING_CONNECTION_ERROR, NULL, NM_TYPE_SETTING_CONNECTION_ERROR); - dbus_g_error_domain_register (NM_SETTING_GSM_ERROR, NULL, NM_TYPE_SETTING_GSM_ERROR); - dbus_g_error_domain_register (NM_SETTING_IP4_CONFIG_ERROR, NULL, NM_TYPE_SETTING_IP4_CONFIG_ERROR); - dbus_g_error_domain_register (NM_SETTING_IP6_CONFIG_ERROR, NULL, NM_TYPE_SETTING_IP6_CONFIG_ERROR); - dbus_g_error_domain_register (NM_SETTING_OLPC_MESH_ERROR, NULL, NM_TYPE_SETTING_OLPC_MESH_ERROR); - dbus_g_error_domain_register (NM_SETTING_PPP_ERROR, NULL, NM_TYPE_SETTING_PPP_ERROR); - dbus_g_error_domain_register (NM_SETTING_PPPOE_ERROR, NULL, NM_TYPE_SETTING_PPPOE_ERROR); - dbus_g_error_domain_register (NM_SETTING_SERIAL_ERROR, NULL, NM_TYPE_SETTING_SERIAL_ERROR); - dbus_g_error_domain_register (NM_SETTING_VPN_ERROR, NULL, NM_TYPE_SETTING_VPN_ERROR); - dbus_g_error_domain_register (NM_SETTING_WIRED_ERROR, NULL, NM_TYPE_SETTING_WIRED_ERROR); - dbus_g_error_domain_register (NM_SETTING_WIRELESS_SECURITY_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_SECURITY_ERROR); - dbus_g_error_domain_register (NM_SETTING_WIRELESS_ERROR, NULL, NM_TYPE_SETTING_WIRELESS_ERROR); - dbus_g_error_domain_register (NM_SETTING_ERROR, NULL, NM_TYPE_SETTING_ERROR); -} - -static void -nm_sysconfig_settings_init (NMSysconfigSettings *self) -{ - NMSysconfigSettingsPrivate *priv = NM_SYSCONFIG_SETTINGS_GET_PRIVATE (self); - GError *error = NULL; - - priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); - - priv->authority = polkit_authority_get_sync (NULL, &error); - if (priv->authority) { - priv->auth_changed_id = g_signal_connect (priv->authority, - "changed", - G_CALLBACK (pk_authority_changed_cb), - self); - } else { - nm_log_warn (LOGD_SYS_SET, "failed to create PolicyKit authority: (%d) %s", - error ? error->code : -1, - error && error->message ? error->message : "(unknown)"); - g_clear_error (&error); - } -} - |