diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml index 0043ec7564..7e02db7216 100644 --- a/introspection/nm-settings.xml +++ b/introspection/nm-settings.xml @@ -82,6 +82,40 @@ + + + Loads or reloads the indicated connections from disk. You + should call this after making changes directly to an on-disk + connection file to make sure that NetworkManager sees the + changes. (If "monitor-connection-files" in NetworkManager.conf + is "true", then this will have no real effect, but is + harmless.) As with AddConnection(), this operation does not + necessarily start the network connection. + + + + + + Array of paths to on-disk connection profiles in directories + monitored by NetworkManager. + + + + + Success or failure of the operation as a whole. True if + NetworkManager at least tried to load the indicated + connections, even if it did not succeed. False if an error + occurred before trying to load the connections (eg, + permission denied). + + + + + Paths of connection files that could not be loaded. + + + + Tells NetworkManager to reload all connection files from disk, diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index 8c29a9111b..be413f8759 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -104,6 +104,10 @@ static void impl_settings_add_connection_unsaved (NMSettings *self, GHashTable *settings, DBusGMethodInvocation *context); +static void impl_settings_load_connections (NMSettings *self, + char **filenames, + DBusGMethodInvocation *context); + static void impl_settings_reload_connections (NMSettings *self, DBusGMethodInvocation *context); @@ -1223,22 +1227,20 @@ impl_settings_add_connection_unsaved (NMSettings *self, impl_settings_add_connection_helper (self, settings, FALSE, context); } -static void -impl_settings_reload_connections (NMSettings *self, - DBusGMethodInvocation *context) +static gboolean +ensure_root (NMDBusManager *dbus_mgr, + DBusGMethodInvocation *context) { - NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); - GSList *iter; gulong caller_uid; GError *error = NULL; - if (!nm_dbus_manager_get_caller_info (priv->dbus_mgr, context, NULL, &caller_uid, NULL)) { + if (!nm_dbus_manager_get_caller_info (dbus_mgr, context, NULL, &caller_uid, NULL)) { error = g_error_new_literal (NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_PERMISSION_DENIED, "Unable to determine request UID."); dbus_g_method_return_error (context, error); g_error_free (error); - return; + return FALSE; } if (caller_uid != 0) { error = g_error_new_literal (NM_SETTINGS_ERROR, @@ -1246,9 +1248,57 @@ impl_settings_reload_connections (NMSettings *self, "Permission denied"); dbus_g_method_return_error (context, error); g_error_free (error); - return; + return FALSE; } + return TRUE; +} + +static void +impl_settings_load_connections (NMSettings *self, + char **filenames, + DBusGMethodInvocation *context) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + GPtrArray *failures; + GSList *iter; + int i; + + if (!ensure_root (priv->dbus_mgr, context)) + return; + + failures = g_ptr_array_new (); + + for (i = 0; filenames[i]; i++) { + for (iter = priv->plugins; iter; iter = g_slist_next (iter)) { + NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data); + + if (nm_system_config_interface_load_connection (plugin, filenames[i])) + break; + } + + if (!iter) { + if (!g_path_is_absolute (filenames[i])) + nm_log_warn (LOGD_SETTINGS, "Connection filename '%s' is not an absolute path", filenames[i]); + g_ptr_array_add (failures, (char *) filenames[i]); + } + } + + g_ptr_array_add (failures, NULL); + dbus_g_method_return (context, failures->len == 1, failures->pdata); + g_ptr_array_unref (failures); +} + +static void +impl_settings_reload_connections (NMSettings *self, + DBusGMethodInvocation *context) +{ + NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self); + GSList *iter; + + if (!ensure_root (priv->dbus_mgr, context)) + return; + if (!priv->connections_loaded) { load_connections (self); } else { diff --git a/src/settings/nm-system-config-interface.c b/src/settings/nm-system-config-interface.c index 20e52c7d05..b77ffa7929 100644 --- a/src/settings/nm-system-config-interface.c +++ b/src/settings/nm-system-config-interface.c @@ -145,6 +145,17 @@ nm_system_config_interface_get_connections (NMSystemConfigInterface *config) return NULL; } +gboolean +nm_system_config_interface_load_connection (NMSystemConfigInterface *config, + const char *filename) +{ + g_return_val_if_fail (config != NULL, NULL); + + if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->load_connection) + return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->load_connection (config, filename); + return FALSE; +} + void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config) { diff --git a/src/settings/nm-system-config-interface.h b/src/settings/nm-system-config-interface.h index 55643ef9f1..76ee168faa 100644 --- a/src/settings/nm-system-config-interface.h +++ b/src/settings/nm-system-config-interface.h @@ -90,6 +90,12 @@ struct _NMSystemConfigInterface { */ GSList * (*get_connections) (NMSystemConfigInterface *config); + /* Requests that the plugin load/reload a single connection, if it + * recognizes the filename. Returns success or failure. + */ + gboolean (*load_connection) (NMSystemConfigInterface *config, + const char *filename); + /* Requests that the plugin reload all connection files from disk, * and emit signals reflecting new, changed, and removed connections. */ @@ -150,6 +156,8 @@ void nm_system_config_interface_init (NMSystemConfigInterface *config, GSList *nm_system_config_interface_get_connections (NMSystemConfigInterface *config); +gboolean nm_system_config_interface_load_connection (NMSystemConfigInterface *config, + const char *filename); void nm_system_config_interface_reload_connections (NMSystemConfigInterface *config); GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config); diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c index ea0ddf34e2..6024202f92 100644 --- a/src/settings/plugins/ifcfg-rh/plugin.c +++ b/src/settings/plugins/ifcfg-rh/plugin.c @@ -512,6 +512,30 @@ get_connections (NMSystemConfigInterface *config) return list; } +static gboolean +load_connection (NMSystemConfigInterface *config, + const char *filename) +{ + SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (config); + NMIfcfgConnection *connection; + int dir_len = strlen (IFCFG_DIR); + + if ( strncmp (filename, IFCFG_DIR, dir_len) != 0 + || filename[dir_len] != '/' + || strchr (filename + dir_len + 1, '/') != NULL) + return FALSE; + + if (utils_should_ignore_file (filename + dir_len + 1, TRUE)) + return FALSE; + + connection = find_by_path (plugin, filename); + connection_new_or_changed (plugin, filename, connection, NULL); + if (!connection) + connection = find_by_path (plugin, filename); + + return (connection != NULL); +} + static void reload_connections (NMSystemConfigInterface *config) { @@ -968,6 +992,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c /* 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; diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c index 950f566b03..3439f55d5e 100644 --- a/src/settings/plugins/keyfile/plugin.c +++ b/src/settings/plugins/keyfile/plugin.c @@ -406,6 +406,33 @@ get_connections (NMSystemConfigInterface *config) return list; } +static gboolean +load_connection (NMSystemConfigInterface *config, + const char *filename) +{ + SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config); + NMKeyfileConnection *connection; + int dir_len = strlen (KEYFILE_DIR); + + if ( strncmp (filename, KEYFILE_DIR, dir_len) != 0 + || filename[dir_len] != '/' + || strchr (filename + dir_len + 1, '/') != NULL) + return FALSE; + + if (nm_keyfile_plugin_utils_should_ignore_file (filename + dir_len + 1)) + return FALSE; + + connection = find_by_path (self, filename); + if (connection) + update_connection (self, connection, filename); + else { + new_connection (self, filename, NULL); + connection = find_by_path (self, filename); + } + + return (connection != NULL); +} + static void reload_connections (NMSystemConfigInterface *config) { @@ -705,6 +732,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c { /* interface implementation */ system_config_interface_class->get_connections = get_connections; + system_config_interface_class->load_connection = load_connection; system_config_interface_class->reload_connections = reload_connections; system_config_interface_class->add_connection = add_connection; system_config_interface_class->get_unmanaged_specs = get_unmanaged_specs;