diff options
Diffstat (limited to 'src/settings/plugins/ifcfg-rh/plugin.c')
| -rw-r--r-- | src/settings/plugins/ifcfg-rh/plugin.c | 711 |
1 files changed, 333 insertions, 378 deletions
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index 526cdafe..5afc46d6 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -30,39 +30,28 @@ #include <sys/stat.h> #include <gmodule.h> -#include <glib-object.h> -#include <glib/gi18n.h> -#include <gio/gio.h> - -#include <dbus/dbus.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> - -#if HAVE_SELINUX -#include <selinux/selinux.h> -#endif #include "nm-setting-connection.h" +#include "nm-default.h" #include "common.h" -#include "nm-dbus-glib-types.h" #include "plugin.h" -#include "nm-system-config-interface.h" +#include "nm-settings-plugin.h" #include "nm-config.h" -#include "nm-logging.h" #include "NetworkManagerUtils.h" #include "nm-ifcfg-connection.h" -#include "nm-inotify-helper.h" #include "shvar.h" #include "reader.h" #include "writer.h" #include "utils.h" -#include "gsystem-local-alloc.h" +#include "nm-dbus-compat.h" +#include "nm-exported-object.h" -#define DBUS_SERVICE_NAME "com.redhat.ifcfgrh1" -#define DBUS_OBJECT_PATH "/com/redhat/ifcfgrh1" +#include "nmdbus-ifcfg-rh.h" +#define IFCFGRH1_DBUS_SERVICE_NAME "com.redhat.ifcfgrh1" +#define IFCFGRH1_DBUS_OBJECT_PATH "/com/redhat/ifcfgrh1" #define _NMLOG_DOMAIN LOGD_SETTINGS #define _NMLOG(level, ...) \ @@ -76,15 +65,7 @@ #define ERR_GET_MSG(err) (((err) && (err)->message) ? (err)->message : "(unknown)") -static gboolean impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin, - const char *in_ifcfg, - const char **out_uuid, - const char **out_path, - GError **error); - -#include "nm-ifcfg-rh-glue.h" - -static NMIfcfgConnection *update_connection (SCPluginIfcfg *plugin, +static NMIfcfgConnection *update_connection (SettingsPluginIfcfg *plugin, NMConnection *source, const char *full_path, NMIfcfgConnection *connection, @@ -92,37 +73,40 @@ static NMIfcfgConnection *update_connection (SCPluginIfcfg *plugin, GHashTable *protected_connections, GError **error); -static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class); +static void settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface); -G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE, - system_config_interface_init)) +G_DEFINE_TYPE_EXTENDED (SettingsPluginIfcfg, settings_plugin_ifcfg, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (NM_TYPE_SETTINGS_PLUGIN, + settings_plugin_interface_init)) -#define SC_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SC_TYPE_PLUGIN_IFCFG, SCPluginIfcfgPrivate)) +#define SETTINGS_PLUGIN_IFCFG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SETTINGS_TYPE_PLUGIN_IFCFG, SettingsPluginIfcfgPrivate)) typedef struct { - GHashTable *connections; /* uuid::connection */ + NMConfig *config; + + struct { + GDBusConnection *connection; + GDBusInterfaceSkeleton *interface; + GCancellable *cancellable; + gulong signal_id; + } dbus; + GHashTable *connections; /* uuid::connection */ gboolean initialized; - gulong ih_event_id; - int sc_network_wd; - GFileMonitor *hostname_monitor; - guint hostname_monitor_id; - char *hostname; GFileMonitor *ifcfg_monitor; - guint ifcfg_monitor_id; - - DBusGConnection *bus; -} SCPluginIfcfgPrivate; + gulong ifcfg_monitor_id; +} SettingsPluginIfcfgPrivate; +static SettingsPluginIfcfg *settings_plugin_ifcfg_get (void); +NM_DEFINE_SINGLETON_GETTER (SettingsPluginIfcfg, settings_plugin_ifcfg_get, SETTINGS_TYPE_PLUGIN_IFCFG); static void connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data) { - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); + SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (user_data); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); const char *path; path = nm_settings_connection_get_filename (NM_SETTINGS_CONNECTION (connection)); @@ -142,14 +126,14 @@ connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data) static void connection_removed_cb (NMSettingsConnection *obj, gpointer user_data) { - g_hash_table_remove (SC_PLUGIN_IFCFG_GET_PRIVATE (user_data)->connections, + g_hash_table_remove (SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (user_data)->connections, nm_connection_get_uuid (NM_CONNECTION (obj))); } static void -remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection) +remove_connection (SettingsPluginIfcfg *self, NMIfcfgConnection *connection) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); gboolean unmanaged, unrecognized; g_return_if_fail (self != NULL); @@ -168,15 +152,15 @@ remove_connection (SCPluginIfcfg *self, NMIfcfgConnection *connection) /* Emit changes _after_ removing the connection */ if (unmanaged) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); if (unrecognized) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); } static NMIfcfgConnection * -find_by_path (SCPluginIfcfg *self, const char *path) +find_by_path (SettingsPluginIfcfg *self, const char *path) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); GHashTableIter iter; NMSettingsConnection *candidate = NULL; @@ -191,7 +175,7 @@ find_by_path (SCPluginIfcfg *self, const char *path) } static NMIfcfgConnection * -update_connection (SCPluginIfcfg *self, +update_connection (SettingsPluginIfcfg *self, NMConnection *source, const char *full_path, NMIfcfgConnection *connection, @@ -199,7 +183,7 @@ update_connection (SCPluginIfcfg *self, GHashTable *protected_connections, GError **error) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); NMIfcfgConnection *connection_new; NMIfcfgConnection *connection_by_uuid; GError *local = NULL; @@ -346,18 +330,18 @@ update_connection (SCPluginIfcfg *self, if (old_unmanaged /* && !new_unmanaged */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" and its device because NM_CONTROLLED was true.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid); } else if (old_unrecognized /* && !new_unrecognized */) { _LOGI ("Managing connection "NM_IFCFG_CONNECTION_LOG_FMT" because it is now a recognized type.", NM_IFCFG_CONNECTION_LOG_ARG (connection_new)); - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_by_uuid); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_by_uuid); } } if (unmanaged_changed) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); if (unrecognized_changed) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); } nm_settings_connection_set_filename (NM_SETTINGS_CONNECTION (connection_by_uuid), full_path); g_object_unref (connection_new); @@ -401,11 +385,11 @@ update_connection (SCPluginIfcfg *self, /* Only raise the signal if we were called without source, i.e. if we read the connection from file. * Otherwise, we were called by add_connection() which does not expect the signal. */ if (nm_ifcfg_connection_get_unmanaged_spec (connection_new)) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNMANAGED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED); else if (nm_ifcfg_connection_get_unrecognized_spec (connection_new)) - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_UNRECOGNIZED_SPECS_CHANGED); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_UNRECOGNIZED_SPECS_CHANGED); else - g_signal_emit_by_name (self, NM_SYSTEM_CONFIG_INTERFACE_CONNECTION_ADDED, connection_new); + g_signal_emit_by_name (self, NM_SETTINGS_PLUGIN_CONNECTION_ADDED, connection_new); } return connection_new; } @@ -418,7 +402,7 @@ ifcfg_dir_changed (GFileMonitor *monitor, GFileMonitorEvent event_type, gpointer user_data) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data); + SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (user_data); char *path, *ifcfg_path; NMIfcfgConnection *connection; @@ -447,9 +431,9 @@ ifcfg_dir_changed (GFileMonitor *monitor, } static void -setup_ifcfg_monitoring (SCPluginIfcfg *plugin) +setup_ifcfg_monitoring (SettingsPluginIfcfg *plugin) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin); GFile *file; GFileMonitor *monitor; @@ -502,9 +486,9 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths) } static void -read_connections (SCPluginIfcfg *plugin) +read_connections (SettingsPluginIfcfg *plugin) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin); GDir *dir; GError *err = NULL; const char *item; @@ -574,10 +558,10 @@ read_connections (SCPluginIfcfg *plugin) } static GSList * -get_connections (NMSystemConfigInterface *config) +get_connections (NMSettingsPlugin *config) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin); GSList *list = NULL; GHashTableIter iter; NMIfcfgConnection *connection; @@ -600,10 +584,10 @@ get_connections (NMSystemConfigInterface *config) } static gboolean -load_connection (NMSystemConfigInterface *config, +load_connection (NMSettingsPlugin *config, const char *filename) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); + SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config); NMIfcfgConnection *connection; int dir_len = strlen (IFCFG_DIR); char *ifcfg_path; @@ -629,18 +613,18 @@ load_connection (NMSystemConfigInterface *config, } static void -reload_connections (NMSystemConfigInterface *config) +reload_connections (NMSettingsPlugin *config) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); + SettingsPluginIfcfg *plugin = SETTINGS_PLUGIN_IFCFG (config); read_connections (plugin); } static GSList * -get_unhandled_specs (NMSystemConfigInterface *config, +get_unhandled_specs (NMSettingsPlugin *config, const char *property) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (config); GSList *list = NULL, *list_iter; GHashTableIter iter; gpointer connection; @@ -668,24 +652,24 @@ get_unhandled_specs (NMSystemConfigInterface *config, } static GSList * -get_unmanaged_specs (NMSystemConfigInterface *config) +get_unmanaged_specs (NMSettingsPlugin *config) { return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNMANAGED_SPEC); } static GSList * -get_unrecognized_specs (NMSystemConfigInterface *config) +get_unrecognized_specs (NMSettingsPlugin *config) { return get_unhandled_specs (config, NM_IFCFG_CONNECTION_UNRECOGNIZED_SPEC); } static NMSettingsConnection * -add_connection (NMSystemConfigInterface *config, +add_connection (NMSettingsPlugin *config, NMConnection *connection, gboolean save_to_disk, GError **error) { - SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config); + SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (config); gs_free char *path = NULL; /* Ensure we reject attempts to add the connection long before we're @@ -701,312 +685,316 @@ add_connection (NMSystemConfigInterface *config, return NM_SETTINGS_CONNECTION (update_connection (self, connection, path, NULL, FALSE, NULL, error)); } -#define SC_NETWORK_FILE "/etc/sysconfig/network" -#define HOSTNAME_FILE "/etc/hostname" - -static char * -plugin_get_hostname (SCPluginIfcfg *plugin) +static void +impl_ifcfgrh_get_ifcfg_details (SettingsPluginIfcfg *plugin, + GDBusMethodInvocation *context, + const char *in_ifcfg) { - shvarFile *network; - char *hostname; - gboolean ignore_localhost; + NMIfcfgConnection *connection; + NMSettingConnection *s_con; + const char *uuid; + const char *path; + gs_free char *ifcfg_path = NULL; - if (g_file_get_contents (HOSTNAME_FILE, &hostname, NULL, NULL)) { - g_strchomp (hostname); - return hostname; + if (!g_path_is_absolute (in_ifcfg)) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "ifcfg path '%s' is not absolute", in_ifcfg); + return; } - network = svOpenFile (SC_NETWORK_FILE, NULL); - if (!network) { - _LOGW ("Could not get hostname: failed to read " SC_NETWORK_FILE); - return NULL; + ifcfg_path = utils_detect_ifcfg_path (in_ifcfg, TRUE); + if (!ifcfg_path) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "ifcfg path '%s' is not an ifcfg base file", in_ifcfg); + return; } - hostname = svGetValue (network, "HOSTNAME", FALSE); - ignore_localhost = svTrueValue (network, "NM_IGNORE_HOSTNAME_LOCALHOST", FALSE); - if (ignore_localhost) { - /* Ignore a default hostname ('localhost[6]' or 'localhost[6].localdomain[6]') - * to preserve 'network' service behavior. - */ - if (hostname && !nm_utils_is_specific_hostname (hostname)) { - g_free (hostname); - hostname = NULL; - } + connection = find_by_path (plugin, ifcfg_path); + if ( !connection + || nm_ifcfg_connection_get_unmanaged_spec (connection) + || nm_ifcfg_connection_get_unrecognized_spec (connection)) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_INVALID_CONNECTION, + "ifcfg file '%s' unknown", in_ifcfg); + return; } - svCloseFile (network); - return hostname; -} - -static gboolean -plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname) -{ - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - shvarFile *network; - char *hostname_eol; - gboolean ret; -#if HAVE_SELINUX - security_context_t se_ctx_prev = NULL, se_ctx = NULL; - struct stat file_stat = { .st_mode = 0 }; - mode_t st_mode = 0; - - /* Get default context for HOSTNAME_FILE and set it for fscreate */ - if (stat (HOSTNAME_FILE, &file_stat) == 0) - st_mode = file_stat.st_mode; - matchpathcon (HOSTNAME_FILE, st_mode, &se_ctx); - matchpathcon_fini (); - getfscreatecon (&se_ctx_prev); - setfscreatecon (se_ctx); -#endif - - hostname_eol = g_strdup_printf ("%s\n", hostname); - ret = g_file_set_contents (HOSTNAME_FILE, hostname_eol, -1, NULL); - -#if HAVE_SELINUX - /* Restore previous context and cleanup */ - setfscreatecon (se_ctx_prev); - freecon (se_ctx); - freecon (se_ctx_prev); -#endif - - if (!ret) { - _LOGW ("Could not save hostname: failed to create/open " HOSTNAME_FILE); - g_free (hostname_eol); - return FALSE; + s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); + if (!s_con) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "unable to retrieve the connection setting"); + return; } - g_free (priv->hostname); - priv->hostname = g_strdup (hostname); - g_free (hostname_eol); + uuid = nm_setting_connection_get_uuid (s_con); + if (!uuid) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "unable to get the UUID"); + return; + } - /* Remove "HOSTNAME" from SC_NETWORK_FILE, if present */ - network = svOpenFile (SC_NETWORK_FILE, NULL); - if (network) { - svSetValue (network, "HOSTNAME", NULL, FALSE); - svWriteFile (network, 0644, NULL); - svCloseFile (network); + path = nm_connection_get_path (NM_CONNECTION (connection)); + if (!path) { + g_dbus_method_invocation_return_error (context, + NM_SETTINGS_ERROR, + NM_SETTINGS_ERROR_FAILED, + "unable to get the connection D-Bus path"); + return; } - return TRUE; + g_dbus_method_invocation_return_value (context, + g_variant_new ("(so)", uuid, path)); } -static void -hostname_maybe_changed (SCPluginIfcfg *plugin) -{ - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - char *new_hostname; - - new_hostname = plugin_get_hostname (plugin); - if ( (new_hostname && !priv->hostname) - || (!new_hostname && priv->hostname) - || (priv->hostname && new_hostname && strcmp (priv->hostname, new_hostname))) { - g_free (priv->hostname); - priv->hostname = new_hostname; - g_object_notify (G_OBJECT (plugin), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); - } else - g_free (new_hostname); -} +/*****************************************************************************/ static void -sc_network_changed_cb (NMInotifyHelper *ih, - struct inotify_event *evt, - const char *path, - gpointer user_data) +_dbus_clear (SettingsPluginIfcfg *self) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); - if (evt->wd != priv->sc_network_wd) - return; + nm_clear_g_signal_handler (priv->dbus.connection, &priv->dbus.signal_id); + + nm_clear_g_cancellable (&priv->dbus.cancellable); + + if (priv->dbus.interface) { + g_dbus_interface_skeleton_unexport (priv->dbus.interface); + nm_exported_object_skeleton_release (priv->dbus.interface); + priv->dbus.interface = NULL; + } - hostname_maybe_changed (plugin); + g_clear_object (&priv->dbus.connection); } static void -hostname_changed_cb (GFileMonitor *monitor, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - gpointer user_data) +_dbus_connection_closed (GDBusConnection *connection, + gboolean remote_peer_vanished, + GError *error, + gpointer user_data) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data); + _LOGW ("dbus: %s bus closed", IFCFGRH1_DBUS_SERVICE_NAME); + _dbus_clear (SETTINGS_PLUGIN_IFCFG (user_data)); - hostname_maybe_changed (plugin); + /* Retry or recover? */ } -static gboolean -impl_ifcfgrh_get_ifcfg_details (SCPluginIfcfg *plugin, - const char *in_ifcfg, - const char **out_uuid, - const char **out_path, - GError **error) +static void +_dbus_request_name_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { - NMIfcfgConnection *connection; - NMSettingConnection *s_con; - const char *uuid; - const char *path; + GDBusConnection *connection = G_DBUS_CONNECTION (source_object); + SettingsPluginIfcfg *self; + SettingsPluginIfcfgPrivate *priv; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *ret = NULL; + guint32 result; + + ret = g_dbus_connection_call_finish (connection, res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; - if (!g_path_is_absolute (in_ifcfg)) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "ifcfg path '%s' is not absolute", in_ifcfg); - return FALSE; - } + self = SETTINGS_PLUGIN_IFCFG (user_data); + priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); - connection = find_by_path (plugin, in_ifcfg); - if ( !connection - || nm_ifcfg_connection_get_unmanaged_spec (connection) - || nm_ifcfg_connection_get_unrecognized_spec (connection)) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_INVALID_CONNECTION, - "ifcfg file '%s' unknown", in_ifcfg); - return FALSE; - } + g_clear_object (&priv->dbus.cancellable); - s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); - if (!s_con) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "unable to retrieve the connection setting"); - return FALSE; + if (!ret) { + _LOGW ("dbus: couldn't acquire D-Bus service: %s", error->message); + _dbus_clear (self); + return; } - uuid = nm_setting_connection_get_uuid (s_con); - if (!uuid) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "unable to get the UUID"); - return FALSE; - } - - path = nm_connection_get_path (NM_CONNECTION (connection)); - if (!path) { - g_set_error (error, - NM_SETTINGS_ERROR, - NM_SETTINGS_ERROR_FAILED, - "unable to get the connection D-Bus path"); - return FALSE; + g_variant_get (ret, "(u)", &result); + + if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + _LOGW ("dbus: couldn't acquire ifcfgrh1 D-Bus service (already taken)"); + _dbus_clear (self); + return; } - *out_uuid = g_strdup (uuid); - *out_path = g_strdup (path); + { + GType skeleton_type = NMDBUS_TYPE_IFCFGRH1_SKELETON; + gs_free char *method_name_get_ifcfg_details = NULL; + NMExportedObjectDBusMethodImpl methods[] = { + { + .method_name = (method_name_get_ifcfg_details = nm_exported_object_skeletonify_method_name ("GetIfcfgDetails")), + .impl = G_CALLBACK (impl_ifcfgrh_get_ifcfg_details), + }, + }; + + priv->dbus.interface = nm_exported_object_skeleton_create (skeleton_type, + g_type_class_peek (SETTINGS_TYPE_PLUGIN_IFCFG), + methods, + G_N_ELEMENTS (methods), + (GObject *) self); + + if (!g_dbus_interface_skeleton_export (priv->dbus.interface, + priv->dbus.connection, + IFCFGRH1_DBUS_OBJECT_PATH, + &error)) { + nm_exported_object_skeleton_release (priv->dbus.interface); + priv->dbus.interface = NULL; + _LOGW ("dbus: failed exporting interface: %s", error->message); + _dbus_clear (self); + return; + } + } - return TRUE; + _LOGD ("dbus: aquired D-Bus service %s and exported %s object", + IFCFGRH1_DBUS_SERVICE_NAME, + IFCFGRH1_DBUS_OBJECT_PATH); } static void -init (NMSystemConfigInterface *config) +_dbus_create_done (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + SettingsPluginIfcfg *self; + SettingsPluginIfcfgPrivate *priv; + gs_free_error GError *error = NULL; + GDBusConnection *connection; + + connection = g_dbus_connection_new_for_address_finish (res, &error); + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return; + + self = SETTINGS_PLUGIN_IFCFG (user_data); + priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); + + g_clear_object (&priv->dbus.cancellable); + + if (!connection) { + _LOGW ("dbus: couldn't initialize system bus: %s", error->message); + return; + } + + priv->dbus.connection = connection; + priv->dbus.cancellable = g_cancellable_new (); + + priv->dbus.signal_id = g_signal_connect (priv->dbus.connection, + "closed", + G_CALLBACK (_dbus_connection_closed), + self); + + g_dbus_connection_call (priv->dbus.connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName", + g_variant_new ("(su)", + IFCFGRH1_DBUS_SERVICE_NAME, + DBUS_NAME_FLAG_DO_NOT_QUEUE), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->dbus.cancellable, + _dbus_request_name_done, + self); } static void -sc_plugin_ifcfg_init (SCPluginIfcfg *plugin) +_dbus_setup (SettingsPluginIfcfg *self) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - NMInotifyHelper *ih; - GError *error = NULL; - gboolean success = FALSE; - GFile *file; - GFileMonitor *monitor; - - priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); + gs_free char *address = NULL; + gs_free_error GError *error = NULL; - /* We watch SC_NETWORK_FILE via NMInotifyHelper (which doesn't track file creation but - * *does* track modifications made via other hard links), since we expect it to always - * exist. But we watch HOSTNAME_FILE via GFileMonitor (which has the opposite - * semantics), since /etc/hostname might not exist, but is unlikely to have hard - * links. bgo 532815 is the bug for being able to just use GFileMonitor for both. - */ - - ih = nm_inotify_helper_get (); - priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (sc_network_changed_cb), plugin); - priv->sc_network_wd = nm_inotify_helper_add_watch (ih, SC_NETWORK_FILE); + g_return_if_fail (!priv->dbus.connection); - file = g_file_new_for_path (HOSTNAME_FILE); - monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL); - g_object_unref (file); - if (monitor) { - priv->hostname_monitor_id = - g_signal_connect (monitor, "changed", G_CALLBACK (hostname_changed_cb), plugin); - priv->hostname_monitor = monitor; + address = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, NULL, &error); + if (address == NULL) { + _LOGW ("dbus: failed getting address for system bus: %s", error->message); + return; } - priv->hostname = plugin_get_hostname (plugin); + priv->dbus.cancellable = g_cancellable_new (); - priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); - if (!priv->bus) { - _LOGW ("Couldn't connect to D-Bus: %s", error->message); - g_clear_error (&error); - } else { - DBusConnection *tmp; - DBusGProxy *proxy; - int result; - - tmp = dbus_g_connection_get_connection (priv->bus); - dbus_connection_set_exit_on_disconnect (tmp, FALSE); - - proxy = dbus_g_proxy_new_for_name (priv->bus, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus"); - - if (!dbus_g_proxy_call (proxy, "RequestName", &error, - G_TYPE_STRING, DBUS_SERVICE_NAME, - G_TYPE_UINT, DBUS_NAME_FLAG_DO_NOT_QUEUE, - G_TYPE_INVALID, - G_TYPE_UINT, &result, - G_TYPE_INVALID)) { - _LOGW ("Couldn't acquire D-Bus service: %s", error->message); - g_clear_error (&error); - } else if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { - _LOGW ("Couldn't acquire ifcfgrh1 D-Bus service (already taken)"); - } else - success = TRUE; - } + g_dbus_connection_new_for_address (address, + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT + | G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION, + NULL, + priv->dbus.cancellable, + _dbus_create_done, + self); +} - if (!success) { - if (priv->bus) { - dbus_g_connection_unref (priv->bus); - priv->bus = NULL; - } +static void +config_changed_cb (NMConfig *config, + NMConfigData *config_data, + NMConfigChangeFlags changes, + NMConfigData *old_data, + SettingsPluginIfcfg *self) +{ + /* If the dbus connection for some reason is borked the D-Bus service + * won't be offered. + * + * On SIGHUP and SIGUSR1 try to re-connect to D-Bus. So in the unlikely + * event that the D-Bus conneciton is broken, that allows for recovery + * without need for restarting NetworkManager. */ + if ( NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGHUP) + || NM_FLAGS_HAS (changes, NM_CONFIG_CHANGE_SIGUSR1)) { + if (!SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self)->dbus.connection) + _dbus_setup (self); } } +/*****************************************************************************/ + static void -dispose (GObject *object) +init (NMSettingsPlugin *config) { - SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (object); - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin); - NMInotifyHelper *ih; +} - if (priv->bus) { - dbus_g_connection_unref (priv->bus); - priv->bus = NULL; - } +static void +settings_plugin_ifcfg_init (SettingsPluginIfcfg *plugin) +{ + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (plugin); + + priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +} - if (priv->ih_event_id) { - ih = nm_inotify_helper_get (); +static void +constructed (GObject *object) +{ + SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); - g_signal_handler_disconnect (ih, priv->ih_event_id); - priv->ih_event_id = 0; + G_OBJECT_CLASS (settings_plugin_ifcfg_parent_class)->constructed (object); - if (priv->sc_network_wd >= 0) - nm_inotify_helper_remove_watch (ih, priv->sc_network_wd); - } + priv->config = nm_config_get (); + g_object_add_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config); + g_signal_connect (priv->config, + NM_CONFIG_SIGNAL_CONFIG_CHANGED, + G_CALLBACK (config_changed_cb), + self); - if (priv->hostname_monitor) { - if (priv->hostname_monitor_id) - g_signal_handler_disconnect (priv->hostname_monitor, priv->hostname_monitor_id); + _dbus_setup (self); +} + +static void +dispose (GObject *object) +{ + SettingsPluginIfcfg *self = SETTINGS_PLUGIN_IFCFG (object); + SettingsPluginIfcfgPrivate *priv = SETTINGS_PLUGIN_IFCFG_GET_PRIVATE (self); - g_file_monitor_cancel (priv->hostname_monitor); - g_object_unref (priv->hostname_monitor); + if (priv->config) { + g_object_remove_weak_pointer ((GObject *) priv->config, (gpointer *) &priv->config); + g_signal_handlers_disconnect_by_func (priv->config, config_changed_cb, self); + priv->config = NULL; } - g_free (priv->hostname); + _dbus_clear (self); if (priv->connections) { g_hash_table_destroy (priv->connections); @@ -1021,27 +1009,22 @@ dispose (GObject *object) g_object_unref (priv->ifcfg_monitor); } - G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object); + G_OBJECT_CLASS (settings_plugin_ifcfg_parent_class)->dispose (object); } static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (object); - switch (prop_id) { - case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME: + case NM_SETTINGS_PLUGIN_PROP_NAME: g_value_set_string (value, IFCFG_PLUGIN_NAME); break; - case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO: + case NM_SETTINGS_PLUGIN_PROP_INFO: g_value_set_string (value, IFCFG_PLUGIN_INFO); break; - case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: - g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); - break; - case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: - g_value_set_string (value, priv->hostname); + case NM_SETTINGS_PLUGIN_PROP_CAPABILITIES: + g_value_set_uint (value, NM_SETTINGS_PLUGIN_CAP_MODIFY_CONNECTIONS); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1053,15 +1036,7 @@ static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - const char *hostname; - switch (prop_id) { - case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: - hostname = g_value_get_string (value); - if (hostname && strlen (hostname) < 1) - hostname = NULL; - plugin_set_hostname (SC_PLUGIN_IFCFG (object), hostname); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1069,65 +1044,45 @@ set_property (GObject *object, guint prop_id, } static void -sc_plugin_ifcfg_class_init (SCPluginIfcfgClass *req_class) +settings_plugin_ifcfg_class_init (SettingsPluginIfcfgClass *req_class) { GObjectClass *object_class = G_OBJECT_CLASS (req_class); - g_type_class_add_private (req_class, sizeof (SCPluginIfcfgPrivate)); + g_type_class_add_private (req_class, sizeof (SettingsPluginIfcfgPrivate)); + object_class->constructed = constructed; object_class->dispose = dispose; object_class->get_property = get_property; object_class->set_property = set_property; g_object_class_override_property (object_class, - NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME, - NM_SYSTEM_CONFIG_INTERFACE_NAME); - - g_object_class_override_property (object_class, - NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO, - NM_SYSTEM_CONFIG_INTERFACE_INFO); + NM_SETTINGS_PLUGIN_PROP_NAME, + NM_SETTINGS_PLUGIN_NAME); g_object_class_override_property (object_class, - NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES, - NM_SYSTEM_CONFIG_INTERFACE_CAPABILITIES); + NM_SETTINGS_PLUGIN_PROP_INFO, + NM_SETTINGS_PLUGIN_INFO); g_object_class_override_property (object_class, - NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME, - NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME); - - dbus_g_object_type_install_info (G_TYPE_FROM_CLASS (req_class), - &dbus_glib_nm_ifcfg_rh_object_info); + NM_SETTINGS_PLUGIN_PROP_CAPABILITIES, + NM_SETTINGS_PLUGIN_CAPABILITIES); } static void -system_config_interface_init (NMSystemConfigInterface *system_config_interface_class) +settings_plugin_interface_init (NMSettingsPluginInterface *plugin_iface) { /* interface implementation */ - system_config_interface_class->get_connections = get_connections; - system_config_interface_class->add_connection = add_connection; - system_config_interface_class->load_connection = load_connection; - system_config_interface_class->reload_connections = reload_connections; - system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs; - system_config_interface_class->get_unrecognized_specs = get_unrecognized_specs; - system_config_interface_class->init = init; + plugin_iface->get_connections = get_connections; + plugin_iface->add_connection = add_connection; + plugin_iface->load_connection = load_connection; + plugin_iface->reload_connections = reload_connections; + plugin_iface->get_unmanaged_specs = get_unmanaged_specs; + plugin_iface->get_unrecognized_specs = get_unrecognized_specs; + plugin_iface->init = init; } G_MODULE_EXPORT GObject * -nm_system_config_factory (void) +nm_settings_plugin_factory (void) { - static SCPluginIfcfg *singleton = NULL; - SCPluginIfcfgPrivate *priv; - - if (!singleton) { - singleton = SC_PLUGIN_IFCFG (g_object_new (SC_TYPE_PLUGIN_IFCFG, NULL)); - priv = SC_PLUGIN_IFCFG_GET_PRIVATE (singleton); - if (priv->bus) - dbus_g_connection_register_g_object (priv->bus, - DBUS_OBJECT_PATH, - G_OBJECT (singleton)); - _LOGD ("Acquired D-Bus service %s", DBUS_SERVICE_NAME); - } else - g_object_ref (singleton); - - return G_OBJECT (singleton); + return g_object_ref (settings_plugin_ifcfg_get ()); } |