summaryrefslogtreecommitdiff
path: root/libnm-core/nm-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnm-core/nm-connection.c')
-rw-r--r--libnm-core/nm-connection.c244
1 files changed, 169 insertions, 75 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c
index f986f824e3..a2bd72b0d9 100644
--- a/libnm-core/nm-connection.c
+++ b/libnm-core/nm-connection.c
@@ -1585,63 +1585,29 @@ nm_connection_verify_secrets (NMConnection *connection, GError **error)
return TRUE;
}
-/**
- * nm_connection_normalize:
- * @connection: the #NMConnection to normalize
- * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with
- * normalization parameters to allow customization of the normalization by providing
- * specific arguments. Unknown arguments will be ignored and the default will be
- * used. The keys must be strings compared with g_str_equal() function.
- * The values are opaque and depend on the parameter name.
- * @modified: (out) (allow-none): outputs whether any settings were modified.
- * @error: location to store error, or %NULL. Contains the reason,
- * why the connection is invalid, if the function returns an error.
- *
- * Does some basic normalization and fixup of well known inconsistencies
- * and deprecated fields. If the connection was modified in any way,
- * the output parameter @modified is set %TRUE.
- *
- * Finally the connection will be verified and %TRUE returns if the connection
- * is valid. As this function only performs some specific normalization steps
- * it cannot repair all connections. If the connection has errors that
- * cannot be normalized, the connection will not be modified.
- *
- * Returns: %TRUE if the connection is valid, %FALSE if it is not
- **/
-gboolean
-nm_connection_normalize (NMConnection *connection,
- GHashTable *parameters,
- gboolean *modified,
- GError **error)
+static gboolean
+_connection_normalize (NMConnection *connection,
+ GHashTable *parameters,
+ gboolean *modified,
+ GError **error)
{
NMSettingVerifyResult success;
- gboolean was_modified = FALSE;
- GError *normalizable_error = NULL;
-
- success = _nm_connection_verify (connection, &normalizable_error);
-
- if (success == NM_SETTING_VERIFY_ERROR ||
- success == NM_SETTING_VERIFY_SUCCESS) {
- if (normalizable_error)
- g_propagate_error (error, normalizable_error);
- if (modified)
- *modified = FALSE;
- if (success == NM_SETTING_VERIFY_ERROR && error && !*error) {
- g_set_error_literal (error,
- NM_CONNECTION_ERROR,
- NM_CONNECTION_ERROR_FAILED,
- _("Unexpected failure to verify the connection"));
- g_return_val_if_reached (FALSE);
- }
- return success == NM_SETTING_VERIFY_SUCCESS;
- }
- g_assert (success == NM_SETTING_VERIFY_NORMALIZABLE || success == NM_SETTING_VERIFY_NORMALIZABLE_ERROR);
- g_clear_error (&normalizable_error);
+ gboolean was_modified;
+
+#if NM_MORE_ASSERTS > 10
+ /* only call this _nm_connection_verify() confirms that the connection
+ * requires normalization and is normalizable. */
+ nm_assert (NM_IN_SET (_nm_connection_verify (connection, NULL),
+ NM_SETTING_VERIFY_NORMALIZABLE,
+ NM_SETTING_VERIFY_NORMALIZABLE_ERROR));
+#endif
/* Try to perform all kind of normalizations on the settings to fix it.
* We only do this, after verifying that the connection contains no un-normalizable
* errors, because in that case we rather fail without touching the settings. */
+ was_modified = FALSE;
+
was_modified |= _normalize_connection_uuid (connection);
was_modified |= _normalize_connection_type (connection);
was_modified |= _normalize_connection_slave_type (connection);
@@ -1663,11 +1629,12 @@ nm_connection_normalize (NMConnection *connection,
was_modified |= _normalize_bridge_vlan_order (connection, parameters);
was_modified |= _normalize_bridge_port_vlan_order (connection, parameters);
- /* Verify anew. */
+ was_modified = !!was_modified;
+
+ /* Verify anew */
success = _nm_connection_verify (connection, error);
- if (modified)
- *modified = was_modified;
+ NM_SET_OUT (modified, was_modified);
if (success != NM_SETTING_VERIFY_SUCCESS) {
/* we would expect, that after normalization, the connection can be verified.
@@ -1689,10 +1656,76 @@ nm_connection_normalize (NMConnection *connection,
return TRUE;
}
+/**
+ * nm_connection_normalize:
+ * @connection: the #NMConnection to normalize
+ * @parameters: (allow-none) (element-type utf8 gpointer): a #GHashTable with
+ * normalization parameters to allow customization of the normalization by providing
+ * specific arguments. Unknown arguments will be ignored and the default will be
+ * used. The keys must be strings compared with g_str_equal() function.
+ * The values are opaque and depend on the parameter name.
+ * @modified: (out) (allow-none): outputs whether any settings were modified.
+ * @error: location to store error, or %NULL. Contains the reason,
+ * why the connection is invalid, if the function returns an error.
+ *
+ * Does some basic normalization and fixup of well known inconsistencies
+ * and deprecated fields. If the connection was modified in any way,
+ * the output parameter @modified is set %TRUE.
+ *
+ * Finally the connection will be verified and %TRUE returns if the connection
+ * is valid. As this function only performs some specific normalization steps
+ * it cannot repair all connections. If the connection has errors that
+ * cannot be normalized, the connection will not be modified.
+ *
+ * Returns: %TRUE if the connection is valid, %FALSE if it is not
+ **/
+gboolean
+nm_connection_normalize (NMConnection *connection,
+ GHashTable *parameters,
+ gboolean *modified,
+ GError **error)
+{
+ NMSettingVerifyResult success;
+ gs_free_error GError *normalizable_error = NULL;
+
+ success = _nm_connection_verify (connection, &normalizable_error);
+
+ if (!NM_IN_SET (success,
+ NM_SETTING_VERIFY_NORMALIZABLE,
+ NM_SETTING_VERIFY_NORMALIZABLE_ERROR)) {
+ if (normalizable_error) {
+ nm_assert (success == NM_SETTING_VERIFY_ERROR);
+ g_propagate_error (error, g_steal_pointer (&normalizable_error));
+ } else
+ nm_assert (success == NM_SETTING_VERIFY_SUCCESS);
+
+ NM_SET_OUT (modified, FALSE);
+
+ if (success != NM_SETTING_VERIFY_SUCCESS) {
+ if ( error
+ && !*error) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_FAILED,
+ _("Unexpected failure to verify the connection"));
+ return FALSE;
+ }
+ return FALSE;
+ }
+
+ if (error && *error)
+ return FALSE;
+ return TRUE;
+ }
+
+ return _connection_normalize (connection, parameters, modified, error);
+}
+
gboolean
_nm_connection_ensure_normalized (NMConnection *connection,
gboolean allow_modify,
- const char *enforce_uuid,
+ const char *expected_uuid,
+ gboolean coerce_uuid,
NMConnection **out_connection_clone,
GError **error)
{
@@ -1701,8 +1734,21 @@ _nm_connection_ensure_normalized (NMConnection *connection,
NMSettingVerifyResult vresult;
nm_assert (NM_IS_CONNECTION (connection));
- nm_assert (out_connection_clone && !*out_connection_clone);
- nm_assert (!enforce_uuid || nm_utils_is_uuid (enforce_uuid));
+ nm_assert (!out_connection_clone || !*out_connection_clone);
+ nm_assert (!expected_uuid || nm_utils_is_uuid (expected_uuid));
+
+ if (expected_uuid) {
+ if (nm_streq0 (expected_uuid, nm_connection_get_uuid (connection)))
+ expected_uuid = NULL;
+ else if ( !coerce_uuid
+ || (!allow_modify && !out_connection_clone)) {
+ g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY,
+ _("unexpected uuid %s instead of %s"),
+ nm_connection_get_uuid (connection),
+ expected_uuid);
+ return FALSE;
+ }
+ }
vresult = _nm_connection_verify (connection, &local);
if (vresult != NM_SETTING_VERIFY_SUCCESS) {
@@ -1712,34 +1758,36 @@ _nm_connection_ensure_normalized (NMConnection *connection,
return FALSE;
}
if (!allow_modify) {
+ if (!out_connection_clone) {
+ /* even NM_SETTING_VERIFY_NORMALIZABLE is treated as an error. We could normalize,
+ * but are not allowed to (and no out argument is provided for cloning). */
+ g_propagate_error (error, g_steal_pointer (&local));
+ return FALSE;
+ }
connection_clone = nm_simple_connection_new_clone (connection);
connection = connection_clone;
}
- if (!nm_connection_normalize (connection, NULL, NULL, error)) {
- nm_assert_not_reached ();
- return FALSE;
- }
+ if (!_connection_normalize (connection, NULL, NULL, error))
+ g_return_val_if_reached (FALSE);
}
- if (enforce_uuid) {
- if (!nm_streq (enforce_uuid, nm_connection_get_uuid (connection))) {
- NMSettingConnection *s_con;
+ if (expected_uuid) {
+ NMSettingConnection *s_con;
- if ( !allow_modify
- && !connection_clone) {
- connection_clone = nm_simple_connection_new_clone (connection);
- connection = connection_clone;
- }
- s_con = nm_connection_get_setting_connection (connection);
- g_object_set (s_con,
- NM_SETTING_CONNECTION_UUID,
- enforce_uuid,
- NULL);
+ if ( !allow_modify
+ && !connection_clone) {
+ nm_assert (out_connection_clone);
+ connection_clone = nm_simple_connection_new_clone (connection);
+ connection = connection_clone;
}
+ s_con = nm_connection_get_setting_connection (connection);
+ g_object_set (s_con,
+ NM_SETTING_CONNECTION_UUID,
+ expected_uuid,
+ NULL);
}
- if (connection_clone)
- *out_connection_clone = g_steal_pointer (&connection_clone);
+ NM_SET_OUT (out_connection_clone, g_steal_pointer (&connection_clone));
return TRUE;
}
@@ -2002,6 +2050,52 @@ nm_connection_clear_secrets_with_flags (NMConnection *connection,
g_signal_emit (connection, signals[SECRETS_CLEARED], 0);
}
+static gboolean
+_clear_secrets_by_secret_flags_cb (NMSetting *setting,
+ const char *secret,
+ NMSettingSecretFlags flags,
+ gpointer user_data)
+{
+ NMSettingSecretFlags filter_flags = GPOINTER_TO_UINT (user_data);
+ gboolean remove_secret;
+
+ if (filter_flags == NM_SETTING_SECRET_FLAG_NONE) {
+ /* Can't use bitops with SECRET_FLAG_NONE so handle that specifically */
+ remove_secret = (flags != NM_SETTING_SECRET_FLAG_NONE);
+ } else {
+ /* Otherwise if the secret has at least one of the desired flags keep it */
+ remove_secret = !NM_FLAGS_ANY (flags, filter_flags);
+ }
+
+ return remove_secret;
+}
+
+/**
+ * _nm_connection_clear_secrets_by_secret_flags:
+ * @self: the #NMConnection to filter (will be modified)
+ * @filter_flags: the secret flags to control whether to drop/remove
+ * a secret or to keep it. The meaning of the filter flags is to
+ * preseve the secrets. The secrets that have matching (see below)
+ * flags are kept, the others are dropped.
+ *
+ * Removes/drops secrets from @self according to @filter_flags.
+ * If @filter_flags is %NM_SETTING_SECRET_NONE, then only secrets that
+ * have %NM_SETTING_SECRET_NONE flags are kept.
+ * Otherwise, only secrets with secret flags are kept that have at least
+ * one of the filter flags.
+ */
+void
+_nm_connection_clear_secrets_by_secret_flags (NMConnection *self,
+ NMSettingSecretFlags filter_flags)
+{
+ nm_connection_clear_secrets_with_flags (self,
+ _clear_secrets_by_secret_flags_cb,
+ GUINT_TO_POINTER (filter_flags));
+}
+
+/*****************************************************************************/
+
+
/*****************************************************************************/
/* Returns always a non-NULL, floating variant that must