diff options
Diffstat (limited to 'libnm-core/nm-connection.c')
-rw-r--r-- | libnm-core/nm-connection.c | 244 |
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 |