diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index f986f824e35..f2e0acbcc4f 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; } diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 685b2cc0d9a..c44c7abf2d0 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -204,7 +204,8 @@ NMSettingVerifyResult _nm_connection_verify (NMConnection *connection, GError ** 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);