diff --git a/introspection/nm-settings-connection.xml b/introspection/nm-settings-connection.xml
index d7e5dbf033..9cfa935db8 100644
--- a/introspection/nm-settings-connection.xml
+++ b/introspection/nm-settings-connection.xml
@@ -9,10 +9,11 @@
- Update the connection with new settings and properties, replacing
- all previous settings and properties. Secrets may be part of the
- update request, and will be either stored in persistent storage or
- given to a Secret Agent for storage, depending on the request.
+ Update the connection with new settings and properties (replacing
+ all previous settings and properties) and save the connection to
+ disk. Secrets may be part of the update request, and will be either
+ stored in persistent storage or sent to a Secret Agent for storage,
+ depending on the flags associated with each secret.
@@ -23,6 +24,23 @@
+
+
+ Update the connection with new settings and properties (replacing
+ all previous settings and properties) but do not immediately save
+ the connection to disk. Secrets may be part of the update request
+ and may sent to a Secret Agent for storage, depending on the the
+ flags associated with each secret.
+
+
+
+
+
+ New connection settings, properties, and (optionally) secrets.
+
+
+
+
Delete the connection.
diff --git a/introspection/nm-settings.xml b/introspection/nm-settings.xml
index c791466843..794e302b23 100644
--- a/introspection/nm-settings.xml
+++ b/introspection/nm-settings.xml
@@ -56,6 +56,27 @@
+
+
+ Add new connection but do not save it to disk immediately. This
+ operation does not start the network connection unless (1) device is
+ idle and able to connect to the network described by the new connection,
+ and (2) the connection is allowed to be started automatically.
+
+
+
+
+
+ Connection settings and properties.
+
+
+
+
+ Object path of the new connection that was just added.
+
+
+
+
Save the hostname to persistent configuration.
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 170abdae64..21a20945c0 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -3089,6 +3089,7 @@ add_and_activate_auth_done (PendingActivation *pending, GError *error)
/* Basic sender auth checks performed; try to add the connection */
nm_settings_add_connection (priv->settings,
pending->connection,
+ TRUE,
pending->context,
activation_add_done,
pending);
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 093bc38fa1..747a66c531 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -52,6 +52,10 @@ static void impl_settings_connection_update (NMSettingsConnection *connection,
GHashTable *new_settings,
DBusGMethodInvocation *context);
+static void impl_settings_connection_update_unsaved (NMSettingsConnection *connection,
+ GHashTable *new_settings,
+ DBusGMethodInvocation *context);
+
static void impl_settings_connection_delete (NMSettingsConnection *connection,
DBusGMethodInvocation *context);
@@ -1159,8 +1163,26 @@ typedef struct {
DBusGMethodInvocation *context;
NMAgentManager *agent_mgr;
gulong sender_uid;
+ NMConnection *new_settings;
+ gboolean save_to_disk;
} UpdateInfo;
+static void
+update_complete (NMSettingsConnection *self,
+ UpdateInfo *info,
+ GError *error)
+{
+ if (error)
+ dbus_g_method_return_error (info->context, error);
+ else
+ dbus_g_method_return (info->context);
+
+ g_clear_object (&info->agent_mgr);
+ g_clear_object (&info->new_settings);
+ memset (info, 0, sizeof (*info));
+ g_free (info);
+}
+
static void
con_update_cb (NMSettingsConnection *self,
GError *error,
@@ -1169,9 +1191,7 @@ con_update_cb (NMSettingsConnection *self,
UpdateInfo *info = user_data;
NMConnection *for_agent;
- if (error)
- dbus_g_method_return_error (info->context, error);
- else {
+ if (!error) {
/* Dupe the connection so we can clear out non-agent-owned secrets,
* as agent-owned secrets are the only ones we send back be saved.
* Only send secrets to agents of the same UID that called update too.
@@ -1186,9 +1206,7 @@ con_update_cb (NMSettingsConnection *self,
dbus_g_method_return (info->context);
}
- g_object_unref (info->agent_mgr);
- memset (info, 0, sizeof (*info));
- g_free (info);
+ update_complete (self, info, error);
}
static void
@@ -1198,32 +1216,36 @@ update_auth_cb (NMSettingsConnection *self,
GError *error,
gpointer data)
{
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- NMConnection *new_settings = data;
- UpdateInfo *info;
+ UpdateInfo *info = data;
+ GError *local = NULL;
- if (error)
- dbus_g_method_return_error (context, error);
- else {
- info = g_malloc0 (sizeof (*info));
- info->context = context;
- info->agent_mgr = g_object_ref (priv->agent_mgr);
- info->sender_uid = sender_uid;
-
- /* Cache the new secrets from the agent, as stuff like inotify-triggered
- * changes to connection's backing config files will blow them away if
- * they're in the main connection.
- */
- update_agent_secrets_cache (self, new_settings);
-
- /* Update and commit our settings. */
- nm_settings_connection_replace_and_commit (self,
- new_settings,
- con_update_cb,
- info);
+ if (error) {
+ update_complete (self, info, error);
+ return;
}
- g_object_unref (new_settings);
+ info->sender_uid = sender_uid;
+
+ /* Cache the new secrets from the agent, as stuff like inotify-triggered
+ * changes to connection's backing config files will blow them away if
+ * they're in the main connection.
+ */
+ update_agent_secrets_cache (self, info->new_settings);
+
+ if (info->save_to_disk) {
+ nm_settings_connection_replace_and_commit (self,
+ info->new_settings,
+ con_update_cb,
+ info);
+ } else {
+ /* Do nothing if there's nothing to update */
+ if (!nm_connection_compare (NM_CONNECTION (self), info->new_settings, NM_SETTING_COMPARE_FLAG_EXACT)) {
+ if (!nm_settings_connection_replace_settings (self, info->new_settings, TRUE, &local))
+ g_assert (local);
+ }
+ con_update_cb (self, local, info);
+ g_clear_error (&local);
+ }
}
static const char *
@@ -1253,13 +1275,15 @@ get_modify_permission_update (NMConnection *old, NMConnection *new)
}
static void
-impl_settings_connection_update (NMSettingsConnection *self,
- GHashTable *new_settings,
- DBusGMethodInvocation *context)
+impl_settings_connection_update_helper (NMSettingsConnection *self,
+ GHashTable *new_settings,
+ DBusGMethodInvocation *context,
+ gboolean save_to_disk)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMConnection *tmp;
GError *error = NULL;
+ UpdateInfo *info;
/* If the connection is read-only, that has to be changed at the source of
* the problem (ex a system settings plugin that can't write connections out)
@@ -1295,11 +1319,34 @@ impl_settings_connection_update (NMSettingsConnection *self,
return;
}
+ info = g_malloc0 (sizeof (*info));
+ info->context = context;
+ info->agent_mgr = g_object_ref (priv->agent_mgr);
+ info->sender_uid = G_MAXULONG;
+ info->save_to_disk = save_to_disk;
+ info->new_settings = tmp;
+
auth_start (self,
context,
- get_modify_permission_update (NM_CONNECTION (self), tmp),
+ get_modify_permission_update (NM_CONNECTION (self), info->new_settings),
update_auth_cb,
- tmp);
+ info);
+}
+
+static void
+impl_settings_connection_update (NMSettingsConnection *self,
+ GHashTable *new_settings,
+ DBusGMethodInvocation *context)
+{
+ impl_settings_connection_update_helper (self, new_settings, context, TRUE);
+}
+
+static void
+impl_settings_connection_update_unsaved (NMSettingsConnection *self,
+ GHashTable *new_settings,
+ DBusGMethodInvocation *context)
+{
+ impl_settings_connection_update_helper (self, new_settings, context, FALSE);
}
static void
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 9eeee9ead0..9e82003f90 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -100,6 +100,10 @@ static void impl_settings_add_connection (NMSettings *self,
GHashTable *settings,
DBusGMethodInvocation *context);
+static void impl_settings_add_connection_unsaved (NMSettings *self,
+ GHashTable *settings,
+ DBusGMethodInvocation *context);
+
static void impl_settings_save_hostname (NMSettings *self,
const char *hostname,
DBusGMethodInvocation *context);
@@ -894,6 +898,7 @@ remove_default_wired_connection (NMSettings *self,
static NMSettingsConnection *
add_new_connection (NMSettings *self,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error)
{
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
@@ -927,14 +932,20 @@ add_new_connection (NMSettings *self,
NMSystemConfigInterface *plugin = NM_SYSTEM_CONFIG_INTERFACE (iter->data);
GError *add_error = NULL;
- g_clear_error (error);
- added = nm_system_config_interface_add_connection (plugin, connection, &add_error);
+ added = nm_system_config_interface_add_connection (plugin, connection, save_to_disk, &add_error);
if (added) {
claim_connection (self, added, TRUE);
return added;
}
- g_propagate_error (error, add_error);
+ nm_log_dbg (LOGD_SETTINGS, "Failed to add %s/'%s': %s",
+ nm_connection_get_uuid (connection),
+ nm_connection_get_id (connection),
+ add_error ? add_error->message : "(unknown)");
+ g_clear_error (&add_error);
}
+
+ g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_ADD_FAILED,
+ "No plugin supported adding this connection");
return NULL;
}
@@ -986,13 +997,14 @@ pk_add_cb (NMAuthChain *chain,
NMSettings *self = NM_SETTINGS (user_data);
NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
NMAuthCallResult result;
- GError *error = NULL, *add_error = NULL;
+ GError *error = NULL;
NMConnection *connection;
NMSettingsConnection *added = NULL;
NMSettingsAddCallback callback;
gpointer callback_data;
gulong caller_uid;
const char *perm;
+ gboolean save_to_disk;
priv->auths = g_slist_remove (priv->auths, chain);
@@ -1013,15 +1025,8 @@ pk_add_cb (NMAuthChain *chain,
/* Authorized */
connection = nm_auth_chain_get_data (chain, "connection");
g_assert (connection);
- added = add_new_connection (self, connection, &add_error);
- if (!added) {
- error = g_error_new (NM_SETTINGS_ERROR,
- NM_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_clear_error (&add_error);
- }
+ save_to_disk = GPOINTER_TO_UINT (nm_auth_chain_get_data (chain, "save-to-disk"));
+ added = add_new_connection (self, connection, save_to_disk, &error);
}
callback = nm_auth_chain_get_data (chain, "callback");
@@ -1038,19 +1043,6 @@ pk_add_cb (NMAuthChain *chain,
nm_auth_chain_unref (chain);
}
-static void
-add_cb (NMSettings *self,
- NMSettingsConnection *connection,
- GError *error,
- DBusGMethodInvocation *context,
- gpointer user_data)
-{
- if (error)
- dbus_g_method_return_error (context, error);
- else
- dbus_g_method_return (context, nm_connection_get_path (NM_CONNECTION (connection)));
-}
-
/* FIXME: remove if/when kernel supports adhoc wpa */
static gboolean
is_adhoc_wpa (NMConnection *connection)
@@ -1086,6 +1078,7 @@ is_adhoc_wpa (NMConnection *connection)
void
nm_settings_add_connection (NMSettings *self,
NMConnection *connection,
+ gboolean save_to_disk,
DBusGMethodInvocation *context,
NMSettingsAddCallback callback,
gpointer user_data)
@@ -1178,6 +1171,7 @@ nm_settings_add_connection (NMSettings *self,
nm_auth_chain_set_data (chain, "callback", callback, NULL);
nm_auth_chain_set_data (chain, "callback-data", user_data, NULL);
nm_auth_chain_set_data_ulong (chain, "caller-uid", caller_uid);
+ nm_auth_chain_set_data (chain, "save-to-disk", GUINT_TO_POINTER (save_to_disk), NULL);
} else {
error = g_error_new_literal (NM_SETTINGS_ERROR,
NM_SETTINGS_ERROR_PERMISSION_DENIED,
@@ -1188,16 +1182,35 @@ nm_settings_add_connection (NMSettings *self,
}
static void
-impl_settings_add_connection (NMSettings *self,
- GHashTable *settings,
- DBusGMethodInvocation *context)
+impl_settings_add_connection_add_cb (NMSettings *self,
+ NMSettingsConnection *connection,
+ GError *error,
+ DBusGMethodInvocation *context,
+ gpointer user_data)
+{
+ if (error)
+ dbus_g_method_return_error (context, error);
+ else
+ dbus_g_method_return (context, nm_connection_get_path (NM_CONNECTION (connection)));
+}
+
+static void
+impl_settings_add_connection_helper (NMSettings *self,
+ GHashTable *settings,
+ gboolean save_to_disk,
+ DBusGMethodInvocation *context)
{
NMConnection *connection;
GError *error = NULL;
connection = nm_connection_new_from_hash (settings, &error);
if (connection) {
- nm_settings_add_connection (self, connection, context, add_cb, NULL);
+ nm_settings_add_connection (self,
+ connection,
+ save_to_disk,
+ context,
+ impl_settings_add_connection_add_cb,
+ NULL);
g_object_unref (connection);
} else {
g_assert (error);
@@ -1206,6 +1219,22 @@ impl_settings_add_connection (NMSettings *self,
}
}
+static void
+impl_settings_add_connection (NMSettings *self,
+ GHashTable *settings,
+ DBusGMethodInvocation *context)
+{
+ impl_settings_add_connection_helper (self, settings, TRUE, context);
+}
+
+static void
+impl_settings_add_connection_unsaved (NMSettings *self,
+ GHashTable *settings,
+ DBusGMethodInvocation *context)
+{
+ impl_settings_add_connection_helper (self, settings, FALSE, context);
+}
+
static void
pk_hostname_cb (NMAuthChain *chain,
GError *chain_error,
@@ -1406,7 +1435,7 @@ default_wired_try_update (NMDefaultWiredConnection *wired,
g_assert (id);
remove_default_wired_connection (self, NM_SETTINGS_CONNECTION (wired), FALSE);
- added = add_new_connection (self, NM_CONNECTION (wired), &error);
+ added = add_new_connection (self, NM_CONNECTION (wired), TRUE, &error);
if (added) {
nm_settings_connection_delete (NM_SETTINGS_CONNECTION (wired), delete_cb, NULL);
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index 66dbcac094..351c2931e1 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -94,6 +94,7 @@ typedef void (*NMSettingsAddCallback) (NMSettings *settings,
void nm_settings_add_connection (NMSettings *self,
NMConnection *connection,
+ gboolean save_to_disk,
DBusGMethodInvocation *context,
NMSettingsAddCallback callback,
gpointer user_data);
diff --git a/src/settings/nm-system-config-interface.c b/src/settings/nm-system-config-interface.c
index 45aa6305da..1a9d5d58ed 100644
--- a/src/settings/nm-system-config-interface.c
+++ b/src/settings/nm-system-config-interface.c
@@ -150,13 +150,14 @@ nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface *config)
NMSettingsConnection *
nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error)
{
g_return_val_if_fail (config != NULL, NULL);
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
if (NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection)
- return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, error);
+ return NM_SYSTEM_CONFIG_INTERFACE_GET_INTERFACE (config)->add_connection (config, connection, save_to_disk, error);
return NULL;
}
diff --git a/src/settings/nm-system-config-interface.h b/src/settings/nm-system-config-interface.h
index 96a640619e..9648fdb5d9 100644
--- a/src/settings/nm-system-config-interface.h
+++ b/src/settings/nm-system-config-interface.h
@@ -110,12 +110,14 @@ struct _NMSystemConfigInterface {
GSList * (*get_unmanaged_specs) (NMSystemConfigInterface *config);
/*
- * Save the given connection to backing storage, and return a new
+ * Initialize the plugin-specific connection and return a new
* NMSettingsConnection subclass that contains the same settings as the
- * original connection.
+ * original connection. The connection should only be saved to backing
+ * storage if @save_to_disk is TRUE.
*/
NMSettingsConnection * (*add_connection) (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error);
/* Signals */
@@ -139,6 +141,7 @@ GSList *nm_system_config_interface_get_unmanaged_specs (NMSystemConfigInterface
NMSettingsConnection *nm_system_config_interface_add_connection (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error);
G_END_DECLS
diff --git a/src/settings/plugins/example/plugin.c b/src/settings/plugins/example/plugin.c
index 3a1ea96baa..8d4b627705 100644
--- a/src/settings/plugins/example/plugin.c
+++ b/src/settings/plugins/example/plugin.c
@@ -503,6 +503,7 @@ get_connections (NMSystemConfigInterface *config)
static NMSettingsConnection *
add_connection (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error)
{
SCPluginExample *self = SC_PLUGIN_EXAMPLE (config);
@@ -513,10 +514,11 @@ add_connection (NMSystemConfigInterface *config,
* way we don't trigger the new NMSettingsConnection subclass' file watch
* functions needlessly.
*/
- if (write_connection (connection, NULL, &path, error)) {
- added = _internal_new_connection (self, path, connection, error);
- g_free (path);
- }
+ if (save_to_disk && !write_connection (connection, NULL, &path, error))
+ return NULL;
+
+ added = _internal_new_connection (self, path, connection, error);
+ g_free (path);
return added;
}
diff --git a/src/settings/plugins/ifcfg-rh/plugin.c b/src/settings/plugins/ifcfg-rh/plugin.c
index d6b3c447c0..13edfb17ea 100644
--- a/src/settings/plugins/ifcfg-rh/plugin.c
+++ b/src/settings/plugins/ifcfg-rh/plugin.c
@@ -452,17 +452,26 @@ get_unmanaged_specs (NMSystemConfigInterface *config)
static NMSettingsConnection *
add_connection (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
NMIfcfgConnection *added = NULL;
char *path = NULL;
- /* Write it out first, then add the connection to our internal list */
- if (writer_new_connection (connection, IFCFG_DIR, &path, error)) {
- added = _internal_new_connection (self, path, connection, error);
- g_free (path);
+ /* Ensure we reject attempts to add the connection long before we're
+ * asked to write it to disk.
+ */
+ if (!writer_can_write_connection (connection, error))
+ return NULL;
+
+ if (save_to_disk) {
+ if (!writer_new_connection (connection, IFCFG_DIR, &path, error))
+ return NULL;
}
+
+ added = _internal_new_connection (self, path, connection, error);
+ g_free (path);
return (NMSettingsConnection *) added;
}
diff --git a/src/settings/plugins/ifcfg-rh/writer.c b/src/settings/plugins/ifcfg-rh/writer.c
index e393a6da9c..022af1a14b 100644
--- a/src/settings/plugins/ifcfg-rh/writer.c
+++ b/src/settings/plugins/ifcfg-rh/writer.c
@@ -2105,12 +2105,11 @@ write_connection (NMConnection *connection,
gboolean no_8021x = FALSE;
gboolean wired = FALSE;
- s_con = nm_connection_get_setting_connection (connection);
- if (!s_con) {
- g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
- "Missing '%s' setting", NM_SETTING_CONNECTION_SETTING_NAME);
+ if (!writer_can_write_connection (connection, error))
return FALSE;
- }
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
if (filename) {
/* For existing connections, 'filename' should be full path to ifcfg file */
@@ -2235,6 +2234,30 @@ out:
return success;
}
+gboolean
+writer_can_write_connection (NMConnection *connection, GError **error)
+{
+ NMSettingConnection *s_con;
+
+ if ( ( nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)
+ && !nm_connection_get_setting_pppoe (connection))
+ || nm_connection_is_type (connection, NM_SETTING_VLAN_SETTING_NAME)
+ || nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)
+ || nm_connection_is_type (connection, NM_SETTING_INFINIBAND_SETTING_NAME)
+ || nm_connection_is_type (connection, NM_SETTING_BOND_SETTING_NAME)
+ || nm_connection_is_type (connection, NM_SETTING_BRIDGE_SETTING_NAME))
+ return TRUE;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+ g_set_error (error, IFCFG_PLUGIN_ERROR, 0,
+ "The ifcfg-rh plugin cannot write the connection '%s' (type '%s' pppoe %d)",
+ nm_connection_get_id (connection),
+ nm_setting_connection_get_connection_type (s_con),
+ !!nm_connection_get_setting_pppoe (connection));
+ return FALSE;
+}
+
gboolean
writer_new_connection (NMConnection *connection,
const char *ifcfg_dir,
diff --git a/src/settings/plugins/ifcfg-rh/writer.h b/src/settings/plugins/ifcfg-rh/writer.h
index edeac0cccc..894313dd06 100644
--- a/src/settings/plugins/ifcfg-rh/writer.h
+++ b/src/settings/plugins/ifcfg-rh/writer.h
@@ -25,6 +25,9 @@
#include
#include
+gboolean writer_can_write_connection (NMConnection *connection,
+ GError **error);
+
gboolean writer_new_connection (NMConnection *connection,
const char *ifcfg_dir,
char **out_filename,
diff --git a/src/settings/plugins/ifnet/Makefile.am b/src/settings/plugins/ifnet/Makefile.am
index 234d4adbbb..ed387e583a 100644
--- a/src/settings/plugins/ifnet/Makefile.am
+++ b/src/settings/plugins/ifnet/Makefile.am
@@ -45,7 +45,9 @@ lib_ifnet_io_la_SOURCES = \
net_utils.h\
net_utils.c\
wpa_parser.h\
- wpa_parser.c
+ wpa_parser.c \
+ errors.h \
+ errors.c
lib_ifnet_io_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
diff --git a/src/settings/plugins/ifnet/connection_parser.c b/src/settings/plugins/ifnet/connection_parser.c
index 5ccf5b3495..8aed34437b 100644
--- a/src/settings/plugins/ifnet/connection_parser.c
+++ b/src/settings/plugins/ifnet/connection_parser.c
@@ -43,6 +43,7 @@
#include "wpa_parser.h"
#include "connection_parser.h"
#include "nm-ifnet-connection.h"
+#include "errors.h"
static char *
connection_id_from_ifnet_name (const char *conn_name)
@@ -2806,16 +2807,11 @@ ifnet_update_parsers_by_connection (NMConnection *connection,
gboolean wired = FALSE, pppoe = TRUE;
const char *new_name = NULL;
- s_con =
- NM_SETTING_CONNECTION (nm_connection_get_setting
- (connection, NM_TYPE_SETTING_CONNECTION));
- if (!s_con) {
- g_set_error (error, ifnet_plugin_error_quark (), 0,
- "Missing '%s' setting",
- NM_SETTING_CONNECTION_SETTING_NAME);
+ if (!ifnet_can_write_connection (connection, error))
return FALSE;
- }
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
type = nm_setting_connection_get_connection_type (s_con);
if (!type) {
@@ -2910,6 +2906,66 @@ ifnet_delete_connection_in_parsers (const char *conn_name,
return result;
}
+static void
+check_unsupported_secrets (NMSetting *setting,
+ const char *key,
+ const GValue *value,
+ GParamFlags flags,
+ gpointer user_data)
+{
+ gboolean *unsupported_secret = user_data;
+
+ if (flags & NM_SETTING_PARAM_SECRET) {
+ NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ nm_setting_get_secret_flags (setting, key, &secret_flags, NULL);
+ if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
+ *unsupported_secret = TRUE;
+ }
+}
+
+gboolean
+ifnet_can_write_connection (NMConnection *connection, GError **error)
+{
+ NMSettingConnection *s_con;
+ gboolean has_unsupported_secrets = FALSE;
+
+ s_con = nm_connection_get_setting_connection (connection);
+ g_assert (s_con);
+
+ /* If the connection is not available for all users, ignore
+ * it as this plugin only deals with System Connections */
+ if (nm_setting_connection_get_num_permissions (s_con)) {
+ g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0,
+ "The ifnet plugin does not support non-system-wide connections.");
+ return FALSE;
+ }
+
+ /* If the connection has flagged secrets, ignore
+ * it as this plugin does not deal with user agent service */
+ nm_connection_for_each_setting_value (connection,
+ check_unsupported_secrets,
+ &has_unsupported_secrets);
+ if (has_unsupported_secrets) {
+ g_set_error_literal (error, IFNET_PLUGIN_ERROR, 0,
+ "The ifnet plugin only supports persistent system secrets.");
+ return FALSE;
+ }
+
+ /* Only support wired, wifi, and PPPoE */
+ if ( !nm_connection_is_type (connection, NM_SETTING_WIRED_SETTING_NAME)
+ && !nm_connection_is_type (connection, NM_SETTING_WIRELESS_SETTING_NAME)
+ && !nm_connection_is_type (connection, NM_SETTING_PPPOE_SETTING_NAME)) {
+ g_set_error (error, IFNET_PLUGIN_ERROR, 0,
+ "The ifnet plugin cannot write the connection '%s' (type '%s')",
+ nm_connection_get_id (connection),
+ nm_setting_connection_get_connection_type (s_con));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
/* get the available wired name(eth*). */
static gchar *
get_wired_name ()
@@ -3003,6 +3059,9 @@ ifnet_add_new_connection (NMConnection *connection,
const char *type;
gchar *new_type, *new_name = NULL;
+ if (!ifnet_can_write_connection (connection, error))
+ return FALSE;
+
s_con = nm_connection_get_setting_connection (connection);
g_assert (s_con);
type = nm_setting_connection_get_connection_type (s_con);
@@ -3053,3 +3112,4 @@ out:
*out_new_name = new_name;
return success;
}
+
diff --git a/src/settings/plugins/ifnet/connection_parser.h b/src/settings/plugins/ifnet/connection_parser.h
index 54046b05a3..74213669de 100644
--- a/src/settings/plugins/ifnet/connection_parser.h
+++ b/src/settings/plugins/ifnet/connection_parser.h
@@ -24,6 +24,8 @@
#include
#include "net_parser.h"
+gboolean ifnet_can_write_connection (NMConnection *connection, GError **error);
+
NMConnection *ifnet_update_connection_from_config_block (const char *conn_name,
const char *basepath,
GError **error);
diff --git a/src/settings/plugins/ifnet/errors.c b/src/settings/plugins/ifnet/errors.c
new file mode 100644
index 0000000000..295db18bae
--- /dev/null
+++ b/src/settings/plugins/ifnet/errors.c
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#include
+#include "errors.h"
+
+GQuark
+ifnet_plugin_error_quark (void)
+{
+ static GQuark error_quark = 0;
+
+ if (G_UNLIKELY (error_quark == 0))
+ error_quark = g_quark_from_static_string ("ifnet-plugin-error-quark");
+
+ return error_quark;
+}
+
+
diff --git a/src/settings/plugins/ifnet/errors.h b/src/settings/plugins/ifnet/errors.h
new file mode 100644
index 0000000000..52517d007e
--- /dev/null
+++ b/src/settings/plugins/ifnet/errors.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
+/* NetworkManager system settings service
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2013 Red Hat, Inc.
+ */
+
+#ifndef __ERRORS_H__
+#define __ERRORS_H__
+
+#include
+
+#define IFNET_PLUGIN_ERROR (ifnet_plugin_error_quark ())
+GQuark ifnet_plugin_error_quark (void);
+
+#endif /* __ERRORS_H__ */
+
diff --git a/src/settings/plugins/ifnet/net_utils.c b/src/settings/plugins/ifnet/net_utils.c
index ae2307f913..672e686bb8 100644
--- a/src/settings/plugins/ifnet/net_utils.c
+++ b/src/settings/plugins/ifnet/net_utils.c
@@ -95,17 +95,6 @@ is_true (const char *str)
return FALSE;
}
-GQuark
-ifnet_plugin_error_quark (void)
-{
- static GQuark error_quark = 0;
-
- if (G_UNLIKELY (error_quark == 0))
- error_quark =
- g_quark_from_static_string ("ifnet-plugin-error-quark");
- return error_quark;
-}
-
static char *
find_default_gateway_str (char *str)
{
diff --git a/src/settings/plugins/ifnet/net_utils.h b/src/settings/plugins/ifnet/net_utils.h
index 71430c838f..cee71d57e5 100644
--- a/src/settings/plugins/ifnet/net_utils.h
+++ b/src/settings/plugins/ifnet/net_utils.h
@@ -67,8 +67,6 @@ void set_ip6_dns_servers (NMSettingIP6Config * s_ip6, const char *conn_name);
gchar *strip_string (gchar *str, gchar t);
gboolean is_managed (const char *conn_name);
-GQuark ifnet_plugin_error_quark (void);
-
gboolean is_hex (const char *value);
gboolean is_ascii (const char *value);
gboolean is_true (const char *str);
diff --git a/src/settings/plugins/ifnet/plugin.c b/src/settings/plugins/ifnet/plugin.c
index 486f893514..8b056a6701 100644
--- a/src/settings/plugins/ifnet/plugin.c
+++ b/src/settings/plugins/ifnet/plugin.c
@@ -335,54 +335,36 @@ reload_connections (gpointer config)
g_list_free (conn_names);
}
-static void
-check_flagged_secrets (NMSetting *setting,
- const char *key,
- const GValue *value,
- GParamFlags flags,
- gpointer user_data)
-{
- gboolean *is_system_secret = user_data;
-
- if (flags & NM_SETTING_PARAM_SECRET) {
- NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
-
- nm_setting_get_secret_flags (setting, key, &secret_flags, NULL);
-
- if (secret_flags != NM_SETTING_SECRET_FLAG_NONE) {
- *is_system_secret = TRUE;
- }
- }
-}
-
static NMSettingsConnection *
add_connection (NMSystemConfigInterface *config,
NMConnection *source,
+ gboolean save_to_disk,
GError **error)
{
SCPluginIfnetPrivate *priv = SC_PLUGIN_IFNET_GET_PRIVATE (config);
- gboolean has_flagged_secrets = FALSE;
- NMSettingConnection *s_con;
+ NMIfnetConnection *new = NULL;
- s_con = nm_connection_get_setting_connection (source);
- g_assert (s_con);
-
- /* If the connection is not available for all users, ignore
- * it as this plugin only deals with System Connections */
- if (nm_setting_connection_get_num_permissions (s_con))
+ /* Ensure we reject attempts to add the connection long before we're
+ * asked to write it to disk.
+ */
+ if (!ifnet_can_write_connection (source, error))
return NULL;
- /* If the connection has flagged secrets, ignore
- * it as this plugin does not deal with user agent service */
- nm_connection_for_each_setting_value (source, check_flagged_secrets, &has_flagged_secrets);
- if (has_flagged_secrets)
- return NULL;
+ if (save_to_disk) {
+ if (!ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, NULL, NULL, error))
+ return NULL;
+ reload_connections (config);
+ new = g_hash_table_lookup (priv->connections, nm_connection_get_uuid (source));
+ } else {
+ new = nm_ifnet_connection_new (source, NULL);
+ if (new) {
+ g_hash_table_insert (priv->connections,
+ (gpointer) nm_connection_get_uuid (NM_CONNECTION (new)),
+ new);
+ }
+ }
- if (!ifnet_add_new_connection (source, CONF_NET_FILE, WPA_SUPPLICANT_CONF, NULL, NULL, error))
- return NULL;
-
- reload_connections (config);
- return g_hash_table_lookup (priv->connections, nm_connection_get_uuid (source));
+ return (NMSettingsConnection *) new;
}
static void
diff --git a/src/settings/plugins/ifnet/tests/Makefile.am b/src/settings/plugins/ifnet/tests/Makefile.am
index 2c39ed6337..f3dc6cbe27 100644
--- a/src/settings/plugins/ifnet/tests/Makefile.am
+++ b/src/settings/plugins/ifnet/tests/Makefile.am
@@ -18,7 +18,8 @@ check_ifnet_SOURCES = \
../connection_parser.c \
../net_parser.c \
../net_utils.c \
- ../wpa_parser.c
+ ../wpa_parser.c \
+ ../errors.c
check_ifnet_CPPFLAGS = \
$(CHECK_CFLAGS) \
diff --git a/src/settings/plugins/keyfile/plugin.c b/src/settings/plugins/keyfile/plugin.c
index 5980809d3a..b216eda246 100644
--- a/src/settings/plugins/keyfile/plugin.c
+++ b/src/settings/plugins/keyfile/plugin.c
@@ -78,8 +78,6 @@ _internal_new_connection (SCPluginKeyfile *self,
SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (self);
NMKeyfileConnection *connection;
- g_return_val_if_fail (full_path != NULL, NULL);
-
connection = nm_keyfile_connection_new (source, full_path, error);
if (connection) {
g_hash_table_insert (priv->connections,
@@ -347,17 +345,20 @@ get_connections (NMSystemConfigInterface *config)
static NMSettingsConnection *
add_connection (NMSystemConfigInterface *config,
NMConnection *connection,
+ gboolean save_to_disk,
GError **error)
{
SCPluginKeyfile *self = SC_PLUGIN_KEYFILE (config);
NMSettingsConnection *added = NULL;
char *path = NULL;
- /* Write it out first, then add the connection to our internal list */
- if (nm_keyfile_plugin_write_connection (connection, NULL, &path, error)) {
- added = _internal_new_connection (self, path, connection, error);
- g_free (path);
+ if (save_to_disk) {
+ if (!nm_keyfile_plugin_write_connection (connection, NULL, &path, error))
+ return NULL;
}
+
+ added = _internal_new_connection (self, path, connection, error);
+ g_free (path);
return added;
}