Skip to content

Commit

Permalink
libnm: cleanup _nm_connection_ensure_normalized() and split nm_connec…
Browse files Browse the repository at this point in the history
…tion_normalize()

- in _nm_connection_ensure_normalized() allow also to only check that
  the UUID is as expected, without really resetting it.

- split the normalization part out of nm_connection_normalize() and
  reuse it in _nm_connection_ensure_normalized(). As we already verified
  the connnection, we know that normalization is due and don't need to
  verify again.
  • Loading branch information
thom311 committed Jun 17, 2019
1 parent 1cc4a8b commit 45013bf
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 76 deletions.
198 changes: 123 additions & 75 deletions libnm-core/nm-connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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.
Expand All @@ -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)
{
Expand All @@ -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) {
Expand All @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion libnm-core/nm-core-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 45013bf

Please sign in to comment.