diff options
Diffstat (limited to 'libnm-util/nm-setting.c')
-rw-r--r-- | libnm-util/nm-setting.c | 306 |
1 files changed, 231 insertions, 75 deletions
diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index 0e8a06c4d..105981bc3 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -1,9 +1,6 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* - * Dan Williams <dcbw@redhat.com> - * Tambet Ingo <tambet@gmail.com> - * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -19,11 +16,14 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA. * - * (C) Copyright 2007 - 2011 Red Hat, Inc. - * (C) Copyright 2007 - 2008 Novell, Inc. + * Copyright 2007 - 2011 Red Hat, Inc. + * Copyright 2007 - 2008 Novell, Inc. */ +#include "config.h" + #include <string.h> +#include <glib/gi18n-lib.h> #include "nm-setting.h" #include "nm-setting-private.h" @@ -211,6 +211,17 @@ _get_setting_type_priority (GType type) return info->priority; } +guint32 +_nm_setting_get_setting_priority (NMSetting *setting) +{ + NMSettingPrivate *priv; + + g_return_val_if_fail (NM_IS_SETTING (setting), G_MAXUINT32); + priv = NM_SETTING_GET_PRIVATE (setting); + _ensure_setting_info (setting, priv); + return priv->info->priority; +} + gboolean _nm_setting_type_is_base_type (GType type) { @@ -262,8 +273,8 @@ _nm_setting_compare_priority (gconstpointer a, gconstpointer b) { guint32 prio_a, prio_b; - prio_a = _get_setting_type_priority (G_OBJECT_TYPE (a)); - prio_b = _get_setting_type_priority (G_OBJECT_TYPE (b)); + prio_a = _nm_setting_get_setting_priority ((NMSetting *) a); + prio_b = _nm_setting_get_setting_priority ((NMSetting *) b); if (prio_a < prio_b) return -1; @@ -291,7 +302,7 @@ destroy_gvalue (gpointer data) * Converts the #NMSetting into a #GHashTable mapping each setting property * name to a GValue describing that property, suitable for marshalling over * D-Bus or serializing. The mapping is string to GValue. - * + * * Returns: (transfer full) (element-type utf8 GObject.Value): a new #GHashTable * describing the setting's properties **/ @@ -306,11 +317,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) g_return_val_if_fail (NM_IS_SETTING (setting), NULL); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); - if (!property_specs) { - g_warning ("%s: couldn't find property specs for object of type '%s'", - __func__, g_type_name (G_OBJECT_TYPE (setting))); - return NULL; - } hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, destroy_gvalue); @@ -343,12 +349,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) } g_free (property_specs); - /* Don't return empty hashes, except for base types */ - if (g_hash_table_size (hash) < 1 && !_nm_setting_is_base_type (setting)) { - g_hash_table_destroy (hash); - hash = NULL; - } - return hash; } @@ -364,7 +364,7 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) * are strongly typed, thus the GValue type of the hash value must be correct. * See the documentation on each #NMSetting object subclass for the correct * property names and value types. - * + * * Returns: a new #NMSetting object populated with the properties from the * hash table, or %NULL on failure **/ @@ -396,19 +396,16 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) param_spec = g_object_class_find_property (class, prop_name); if (!param_spec) { - /* Oh, we're so nice and only warn, maybe it should be a fatal error? */ - g_warning ("Ignoring invalid property '%s'", prop_name); + /* Assume that any unrecognized property either can be ignored, or + * else has a backward-compatibility equivalent. + */ + g_debug ("Ignoring unrecognized property '%s'", prop_name); continue; } g_value_init (dst_value, G_VALUE_TYPE (src_value)); - if (g_value_transform (src_value, dst_value)) - params[n_params++].name = prop_name; - else { - g_warning ("Ignoring property '%s' with invalid type (%s)", - prop_name, G_VALUE_TYPE_NAME (src_value)); - g_value_unset (dst_value); - } + g_value_copy (src_value, dst_value); + params[n_params++].name = prop_name; } setting = (NMSetting *) g_object_newv (setting_type, n_params, params); @@ -422,6 +419,27 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) return setting; } +gboolean +_nm_setting_get_property (NMSetting *setting, const char *property_name, GValue *value) +{ + GParamSpec *prop_spec; + + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (property_name, FALSE); + g_return_val_if_fail (value, FALSE); + + prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), property_name); + + if (!prop_spec) { + g_value_unset (value); + return FALSE; + } + + g_value_init (value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), property_name, value); + return TRUE; +} + static void duplicate_setting (NMSetting *setting, const char *name, @@ -517,20 +535,31 @@ nm_setting_get_name (NMSetting *setting) gboolean nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error) { - g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); - g_return_val_if_fail (!error || *error == NULL, FALSE); + NMSettingVerifyResult result = _nm_setting_verify (setting, all_settings, error); + + if (result == NM_SETTING_VERIFY_NORMALIZABLE) + g_clear_error (error); + + return result == NM_SETTING_VERIFY_SUCCESS || result == NM_SETTING_VERIFY_NORMALIZABLE; +} + +NMSettingVerifyResult +_nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error) +{ + g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_VERIFY_ERROR); + g_return_val_if_fail (!error || *error == NULL, NM_SETTING_VERIFY_ERROR); if (NM_SETTING_GET_CLASS (setting)->verify) return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error); - return TRUE; + return NM_SETTING_VERIFY_SUCCESS; } static gboolean compare_property (NMSetting *setting, - NMSetting *other, - const GParamSpec *prop_spec, - NMSettingCompareFlags flags) + NMSetting *other, + const GParamSpec *prop_spec, + NMSettingCompareFlags flags) { GValue value1 = G_VALUE_INIT; GValue value2 = G_VALUE_INIT; @@ -541,8 +570,12 @@ compare_property (NMSetting *setting, NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE; NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE; - nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL); - nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL); + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + + if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL)) + g_return_val_if_reached (FALSE); + if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL)) + g_return_val_if_reached (FALSE); /* If the secret flags aren't the same the settings aren't the same */ if (a_secret_flags != b_secret_flags) @@ -610,7 +643,7 @@ nm_setting_compare (NMSetting *a, /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */ if ( (flags & NM_SETTING_COMPARE_FLAG_FUZZY) - && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))) + && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))) continue; if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE)) @@ -647,7 +680,16 @@ should_compare_prop (NMSetting *setting, if (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) return FALSE; - nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL); + if ( NM_IS_SETTING_VPN (setting) + && g_strcmp0 (prop_name, NM_SETTING_VPN_SECRETS) == 0) { + /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET. + * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the + * setting accidently uses a key "secrets". */ + return FALSE; + } + + if (!nm_setting_get_secret_flags (setting, prop_name, &secret_flags, NULL)) + g_return_val_if_reached (FALSE); if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) && (secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED)) @@ -699,6 +741,8 @@ nm_setting_diff (NMSetting *a, guint i; NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A; NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B; + NMSettingDiffResult a_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; + NMSettingDiffResult b_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; gboolean results_created = FALSE; g_return_val_if_fail (results != NULL, FALSE); @@ -708,6 +752,12 @@ nm_setting_diff (NMSetting *a, g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE); } + if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == + (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) { + /* conflicting flags: default to WITH_DEFAULT (clearing NO_DEFAULT). */ + flags &= ~NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT; + } + /* If the caller is calling this function in a pattern like this to get * complete diffs: * @@ -720,6 +770,8 @@ nm_setting_diff (NMSetting *a, if (invert_results) { a_result = NM_SETTING_DIFF_RESULT_IN_B; b_result = NM_SETTING_DIFF_RESULT_IN_A; + a_result_default = NM_SETTING_DIFF_RESULT_IN_B_DEFAULT; + b_result_default = NM_SETTING_DIFF_RESULT_IN_A_DEFAULT; } if (*results == NULL) { @@ -732,8 +784,7 @@ nm_setting_diff (NMSetting *a, for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp; - gboolean different = TRUE; + NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN; /* Handle compare flags */ if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags)) @@ -742,28 +793,58 @@ nm_setting_diff (NMSetting *a, continue; if (b) { + gboolean different; + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); if (different) { + gboolean a_is_default, b_is_default; GValue value = G_VALUE_INIT; g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (a), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= a_result; + a_is_default = g_param_value_defaults (prop_spec, &value); g_value_reset (&value); g_object_get_property (G_OBJECT (b), prop_spec->name, &value); - if (!g_param_value_defaults (prop_spec, &value)) - r |= b_result; + b_is_default = g_param_value_defaults (prop_spec, &value); g_value_unset (&value); + if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) { + if (!a_is_default) + r |= a_result; + if (!b_is_default) + r |= b_result; + } else { + r |= a_result | b_result; + if (a_is_default) + r |= a_result_default; + if (b_is_default) + r |= b_result_default; + } } - } else + } else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0) r = a_result; /* only in A */ + else { + GValue value = G_VALUE_INIT; - if (different) { - tmp = GPOINTER_TO_UINT (g_hash_table_lookup (*results, prop_spec->name)); - g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (tmp | r)); + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) + r |= a_result; + else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) + r |= a_result | a_result_default; + + g_value_unset (&value); + } + + if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) { + void *p; + + if (g_hash_table_lookup_extended (*results, prop_spec->name, NULL, &p)) { + if ((r & GPOINTER_TO_UINT (p)) != r) + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r | GPOINTER_TO_UINT (p))); + } else + g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (r)); } } g_free (property_specs); @@ -788,8 +869,8 @@ nm_setting_diff (NMSetting *a, **/ void nm_setting_enumerate_values (NMSetting *setting, - NMSettingValueIterFn func, - gpointer user_data) + NMSettingValueIterFn func, + gpointer user_data) { GParamSpec **property_specs; guint n_property_specs; @@ -862,15 +943,19 @@ _nm_setting_clear_secrets (NMSetting *setting) static gboolean clear_secrets_with_flags (NMSetting *setting, - GParamSpec *pspec, - NMSettingClearSecretsWithFlagsFn func, - gpointer user_data) + GParamSpec *pspec, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) { NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; gboolean changed = FALSE; + g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE); + /* Clear the secret if the user function says to do so */ - nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL); + if (!nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL)) + g_return_val_if_reached (FALSE); + if (func (setting, pspec->name, flags, user_data) == TRUE) { GValue value = G_VALUE_INIT; @@ -963,7 +1048,6 @@ static int update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) { GParamSpec *prop_spec; - GValue transformed_value = G_VALUE_INIT; prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); if (!prop_spec) { @@ -995,11 +1079,6 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** g_object_set_property (G_OBJECT (setting), prop_spec->name, value); return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } - if (g_value_transform (value, &transformed_value)) { - g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value); - g_value_unset (&transformed_value); - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; - } g_set_error (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, @@ -1016,7 +1095,7 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** * * Update the setting's secrets, given a hash table of secrets intended for that * setting (deserialized from D-Bus for example). - * + * * Returns: %TRUE if the secrets were successfully updated, %FALSE on failure to * update one or more of the secrets. **/ @@ -1095,8 +1174,11 @@ get_secret_flags (NMSetting *setting, char *flags_prop; NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; - if (verify_secret) - g_return_val_if_fail (is_secret_prop (setting, secret_name, error), FALSE); + if (verify_secret && !is_secret_prop (setting, secret_name, error)) { + if (out_flags) + *out_flags = NM_SETTING_SECRET_FLAG_NONE; + return FALSE; + } flags_prop = g_strdup_printf ("%s-flags", secret_name); g_object_get (G_OBJECT (setting), flags_prop, &flags, NULL); @@ -1199,8 +1281,6 @@ nm_setting_to_string (NMSetting *setting) g_return_val_if_fail (NM_IS_SETTING (setting), NULL); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); - if (!property_specs) - return NULL; string = g_string_new (nm_setting_get_name (setting)); g_string_append_c (string, '\n'); @@ -1259,6 +1339,87 @@ nm_setting_get_virtual_iface_name (NMSetting *setting) return NULL; } + +NMSettingVerifyResult +_nm_setting_verify_deprecated_virtual_iface_name (const char *interface_name, + gboolean allow_missing, + const char *setting_name, + const char *setting_property, + GQuark error_quark, + gint e_invalid_property, + gint e_missing_property, + GSList *all_settings, + GError **error) +{ + NMSettingConnection *s_con; + const char *con_name; + + s_con = NM_SETTING_CONNECTION (nm_setting_find_in_list (all_settings, NM_SETTING_CONNECTION_SETTING_NAME)); + con_name = s_con ? nm_setting_connection_get_interface_name (s_con) : NULL; + if (!interface_name && !con_name) { + if (allow_missing) + return NM_SETTING_VERIFY_SUCCESS; + + g_set_error_literal (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); + return NM_SETTING_VERIFY_ERROR; + } + if (!con_name && !nm_utils_iface_valid_name (interface_name)) { + /* the interface_name is invalid, we cannot normalize it. Only do this if !con_name, + * because if con_name is set, it can overwrite interface_name. */ + g_set_error_literal (error, + error_quark, + e_invalid_property, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", setting_name, setting_property); + return NM_SETTING_VERIFY_ERROR; + } + if (!con_name) { + /* NMSettingConnection has interface not set, it should be normalized to interface_name */ + g_set_error_literal (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_MISSING_PROPERTY, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + if (!nm_utils_iface_valid_name (con_name)) { + /* NMSettingConnection:interface_name is invalid, we cannot normalize it. */ + g_set_error_literal (error, + NM_SETTING_CONNECTION_ERROR, + NM_SETTING_CONNECTION_ERROR_INVALID_PROPERTY, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME); + return NM_SETTING_VERIFY_ERROR; + } + if (!interface_name) { + /* Normalize by setting NMSettingConnection:interface_name. */ + g_set_error_literal (error, + error_quark, + e_missing_property, + _("property is missing")); + g_prefix_error (error, "%s.%s: ", setting_name, setting_property); + return NM_SETTING_VERIFY_NORMALIZABLE; + } + if (strcmp (con_name, interface_name) != 0) { + /* con_name and interface_name are different. It can be normalized by setting interface_name + * to con_name. */ + g_set_error_literal (error, + error_quark, + e_invalid_property, + _("property is invalid")); + g_prefix_error (error, "%s.%s: ", setting_name, setting_property); + /* we would like to make this a NORMALIZEABLE_ERROR, but that might + * break older connections. */ + return NM_SETTING_VERIFY_NORMALIZABLE; + } + + return NM_SETTING_VERIFY_SUCCESS; +} + /*****************************************************************************/ static void @@ -1348,13 +1509,8 @@ nm_setting_class_init (NMSettingClass *setting_class) **/ g_object_class_install_property (object_class, PROP_NAME, - g_param_spec_string (NM_SETTING_NAME, - "Name", - "The setting's name; these names are defined by the " - "specification and cannot be changed after the object " - "has been created. Each setting class has a name, and " - "all objects of that class share the same name.", - NULL, - G_PARAM_READWRITE)); + g_param_spec_string (NM_SETTING_NAME, "", "", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); } - |