diff options
| author | Michael Biebl <biebl@debian.org> | 2016-03-30 00:56:30 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2016-03-30 00:56:30 +0200 |
| commit | d9c99a29a0d3384c9c3d2adce430f5cb1134ab6a (patch) | |
| tree | fa41baf72753961e71dd8d5bdbe2b89c9109e4f1 /libnm-core/nm-connection.c | |
| parent | c2de0d98ba39e0a1a970d066fd19be786092f376 (diff) | |
Imported Upstream version 1.1.92 upstream/1.1.92
Diffstat (limited to 'libnm-core/nm-connection.c')
| -rw-r--r-- | libnm-core/nm-connection.c | 90 |
1 files changed, 80 insertions, 10 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 04e601ce..c03e6265 100644 --- a/libnm-core/nm-connection.c +++ b/libnm-core/nm-connection.c @@ -233,9 +233,10 @@ validate_permissions_type (GVariant *variant, GError **error) } /** - * nm_connection_replace_settings: + * _nm_connection_replace_settings: * @connection: a #NMConnection * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings + * @parse_flags: flags. * @error: location to store error, or %NULL * * Replaces @connection's settings with @new_settings (which must be @@ -244,49 +245,82 @@ validate_permissions_type (GVariant *variant, GError **error) * * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not * be deserialized (in which case @connection will be unchanged). + * Only exception is the NM_SETTING_PARSE_FLAGS_NORMALIZE flag: if normalization + * fails, the input @connection is already modified and the original settings + * are lost. **/ gboolean -nm_connection_replace_settings (NMConnection *connection, - GVariant *new_settings, - GError **error) +_nm_connection_replace_settings (NMConnection *connection, + GVariant *new_settings, + NMSettingParseFlags parse_flags, + GError **error) { NMConnectionPrivate *priv; GVariantIter iter; const char *setting_name; GVariant *setting_dict; GSList *settings = NULL, *s; - gboolean changed; + gboolean changed, success; g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + nm_assert (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL)); + nm_assert (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT)); + priv = NM_CONNECTION_GET_PRIVATE (connection); - if (!validate_permissions_type (new_settings, error)) + if ( !NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT) + && !validate_permissions_type (new_settings, error)) return FALSE; g_variant_iter_init (&iter, new_settings); while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) { + gs_unref_variant GVariant *setting_dict_free = NULL; + GError *local = NULL; NMSetting *setting; GType type; + setting_dict_free = setting_dict; + type = nm_setting_lookup_type (setting_name); if (type == G_TYPE_INVALID) { + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; g_set_error_literal (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, _("unknown setting name")); g_prefix_error (error, "%s: ", setting_name); - g_variant_unref (setting_dict); g_slist_free_full (settings, g_object_unref); return FALSE; } - setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, error); - g_variant_unref (setting_dict); + for (s = settings; s; s = s->next) { + if (G_OBJECT_TYPE (s->data) == type) { + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + g_set_error_literal (error, + NM_CONNECTION_ERROR, + NM_CONNECTION_ERROR_INVALID_SETTING, + _("duplicate setting name")); + g_prefix_error (error, "%s: ", setting_name); + g_slist_free_full (settings, g_object_unref); + return FALSE; + } + /* last wins. */ + g_object_unref (s->data); + settings = g_slist_delete_link (settings, s); + break; + } + } + + setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, parse_flags, &local); if (!setting) { + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_propagate_error (error, local); g_slist_free_full (settings, g_object_unref); return FALSE; } @@ -300,14 +334,50 @@ nm_connection_replace_settings (NMConnection *connection, } else changed = (settings != NULL); + /* Note: @settings might be empty in which case the connection + * has no NMSetting instances... which is fine, just something + * to be aware of. */ for (s = settings; s; s = s->next) _nm_connection_add_setting (connection, s->data); g_slist_free (settings); + /* If verification/normalization fails, the original connection + * is already lost. From an API point of view, it would be nicer + * not to touch the input argument if we fail at the end. + * However, that would require creating a temporary connection + * to validate it first. As none of the caller cares about the + * state of the @connection when normalization fails, just do it + * this way. */ + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_NORMALIZE)) + success = nm_connection_normalize (connection, NULL, NULL, error); + else + success = TRUE; + if (changed) g_signal_emit (connection, signals[CHANGED], 0); - return TRUE; + return success; +} + +/** + * nm_connection_replace_settings: + * @connection: a #NMConnection + * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings + * @error: location to store error, or %NULL + * + * Replaces @connection's settings with @new_settings (which must be + * syntactically valid, and describe a known type of connection, but does not + * need to result in a connection that passes nm_connection_verify()). + * + * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not + * be deserialized (in which case @connection will be unchanged). + **/ +gboolean +nm_connection_replace_settings (NMConnection *connection, + GVariant *new_settings, + GError **error) +{ + return _nm_connection_replace_settings (connection, new_settings, NM_SETTING_PARSE_FLAGS_NONE, error); } /** |