diff options
-rw-r--r-- | libnm-core/nm-connection.c | 71 | ||||
-rw-r--r-- | libnm-core/nm-core-internal.h | 14 | ||||
-rw-r--r-- | libnm-core/nm-setting-connection.c | 15 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip-config.c | 11 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip4-config.c | 44 | ||||
-rw-r--r-- | libnm-core/nm-setting-ip6-config.c | 44 | ||||
-rw-r--r-- | libnm-core/nm-setting-private.h | 13 | ||||
-rw-r--r-- | libnm-core/nm-setting-vlan.c | 9 | ||||
-rw-r--r-- | libnm-core/nm-setting.c | 128 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 10 |
10 files changed, 285 insertions, 74 deletions
diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 04e601ce8c..f0b2387bac 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 @@ -246,9 +247,10 @@ validate_permissions_type (GVariant *variant, GError **error) * be deserialized (in which case @connection will be unchanged). **/ 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; @@ -261,32 +263,61 @@ nm_connection_replace_settings (NMConnection *connection, 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,6 +331,9 @@ 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); @@ -311,6 +345,27 @@ nm_connection_replace_settings (NMConnection *connection, } /** + * 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); +} + +/** * nm_connection_replace_settings_from_connection: * @connection: a #NMConnection * @new_connection: a #NMConnection to replace the settings of @connection with diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 92de9d1313..60c3c55294 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -100,6 +100,20 @@ NM_SETTING_SECRET_FLAG_NOT_SAVED | \ NM_SETTING_SECRET_FLAG_NOT_REQUIRED) +typedef enum { /*< skip >*/ + NM_SETTING_PARSE_FLAGS_NONE = 0, + NM_SETTING_PARSE_FLAGS_STRICT = 1LL << 0, + NM_SETTING_PARSE_FLAGS_BEST_EFFORT = 1LL << 1, + + _NM_SETTING_PARSE_FLAGS_LAST, + NM_SETTING_PARSE_FLAGS_ALL = ((_NM_SETTING_PARSE_FLAGS_LAST - 1) << 1) - 1, +} NMSettingParseFlags; + +gboolean _nm_connection_replace_settings (NMConnection *connection, + GVariant *new_settings, + NMSettingParseFlags parse_flags, + GError **error); + guint32 _nm_setting_get_setting_priority (NMSetting *setting); gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 44237d9801..e1cd913aad 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -1055,11 +1055,13 @@ find_virtual_interface_name (GVariant *connection_dict) return interface_name; } -static void +static gboolean nm_setting_connection_set_interface_name (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { const char *interface_name; @@ -1074,12 +1076,16 @@ nm_setting_connection_set_interface_name (NMSetting *setting, g_object_set (G_OBJECT (setting), NM_SETTING_CONNECTION_INTERFACE_NAME, interface_name, NULL); + + return TRUE; } -static void +static gboolean nm_setting_connection_no_interface_name (NMSetting *setting, GVariant *connection_dict, - const char *property) + const char *property, + NMSettingParseFlags parse_flags, + GError **error) { const char *virtual_interface_name; @@ -1087,6 +1093,7 @@ nm_setting_connection_no_interface_name (NMSetting *setting, g_object_set (G_OBJECT (setting), NM_SETTING_CONNECTION_INTERFACE_NAME, virtual_interface_name, NULL); + return TRUE; } static gboolean diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c index d76179c8e3..a69045b36e 100644 --- a/libnm-core/nm-setting-ip-config.c +++ b/libnm-core/nm-setting-ip-config.c @@ -2464,17 +2464,22 @@ get_property (GObject *object, guint prop_id, } } -static void +static gboolean ip_gateway_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { + /* FIXME: properly handle errors */ + /* Don't set from 'gateway' if we're going to use the gateway in 'addresses' */ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "gateway")) - return; + return TRUE; g_object_set (setting, property, g_variant_get_string (value, NULL), NULL); + return TRUE; } static void diff --git a/libnm-core/nm-setting-ip4-config.c b/libnm-core/nm-setting-ip4-config.c index b0308e7162..9b479a083d 100644 --- a/libnm-core/nm-setting-ip4-config.c +++ b/libnm-core/nm-setting-ip4-config.c @@ -313,19 +313,23 @@ ip4_addresses_get (NMSetting *setting, return ret; } -static void +static gboolean ip4_addresses_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *addrs; GVariant *s_ip4; char **labels, *gateway = NULL; int i; + /* FIXME: properly handle errors */ + if (!_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data")) - return; + return TRUE; addrs = nm_utils_ip4_addresses_from_variant (value, &gateway); @@ -344,6 +348,7 @@ ip4_addresses_set (NMSetting *setting, NULL); g_ptr_array_unref (addrs); g_free (gateway); + return TRUE; } static GVariant * @@ -399,21 +404,26 @@ ip4_address_data_get (NMSetting *setting, return ret; } -static void +static gboolean ip4_address_data_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *addrs; + /* FIXME: properly handle errors */ + /* Ignore 'address-data' if we're going to process 'addresses' */ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data")) - return; + return TRUE; addrs = nm_utils_ip_addresses_from_variant (value, AF_INET); g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); g_ptr_array_unref (addrs); + return TRUE; } static GVariant * @@ -430,20 +440,25 @@ ip4_routes_get (NMSetting *setting, return ret; } -static void +static gboolean ip4_routes_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *routes; + /* FIXME: properly handle errors */ + if (!_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data")) - return; + return TRUE; routes = nm_utils_ip4_routes_from_variant (value); g_object_set (setting, property, routes, NULL); g_ptr_array_unref (routes); + return TRUE; } static GVariant * @@ -461,21 +476,26 @@ ip4_route_data_get (NMSetting *setting, return ret; } -static void +static gboolean ip4_route_data_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *routes; + /* FIXME: properly handle errors */ + /* Ignore 'route-data' if we're going to process 'routes' */ if (_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data")) - return; + return TRUE; routes = nm_utils_ip_routes_from_variant (value, AF_INET); g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); g_ptr_array_unref (routes); + return TRUE; } diff --git a/libnm-core/nm-setting-ip6-config.c b/libnm-core/nm-setting-ip6-config.c index f2d85084f3..bab8c535c7 100644 --- a/libnm-core/nm-setting-ip6-config.c +++ b/libnm-core/nm-setting-ip6-config.c @@ -239,17 +239,21 @@ ip6_addresses_get (NMSetting *setting, return ret; } -static void +static gboolean ip6_addresses_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *addrs; char *gateway = NULL; + /* FIXME: properly handle errors */ + if (!_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data")) - return; + return TRUE; addrs = nm_utils_ip6_addresses_from_variant (value, &gateway); @@ -259,6 +263,7 @@ ip6_addresses_set (NMSetting *setting, NULL); g_ptr_array_unref (addrs); g_free (gateway); + return TRUE; } static GVariant * @@ -276,21 +281,26 @@ ip6_address_data_get (NMSetting *setting, return ret; } -static void +static gboolean ip6_address_data_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *addrs; + /* FIXME: properly handle errors */ + /* Ignore 'address-data' if we're going to process 'addresses' */ if (_nm_setting_use_legacy_property (setting, connection_dict, "addresses", "address-data")) - return; + return TRUE; addrs = nm_utils_ip_addresses_from_variant (value, AF_INET6); g_object_set (setting, NM_SETTING_IP_CONFIG_ADDRESSES, addrs, NULL); g_ptr_array_unref (addrs); + return TRUE; } static GVariant * @@ -307,20 +317,25 @@ ip6_routes_get (NMSetting *setting, return ret; } -static void +static gboolean ip6_routes_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *routes; + /* FIXME: properly handle errors */ + if (!_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data")) - return; + return TRUE; routes = nm_utils_ip6_routes_from_variant (value); g_object_set (setting, property, routes, NULL); g_ptr_array_unref (routes); + return TRUE; } static GVariant * @@ -338,21 +353,26 @@ ip6_route_data_get (NMSetting *setting, return ret; } -static void +static gboolean ip6_route_data_set (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value) + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error) { GPtrArray *routes; + /* FIXME: properly handle errors */ + /* Ignore 'route-data' if we're going to process 'routes' */ if (_nm_setting_use_legacy_property (setting, connection_dict, "routes", "route-data")) - return; + return TRUE; routes = nm_utils_ip_routes_from_variant (value, AF_INET6); g_object_set (setting, NM_SETTING_IP_CONFIG_ROUTES, routes, NULL); g_ptr_array_unref (routes); + return TRUE; } static void diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h index cb7ca52e3d..6560c4a296 100644 --- a/libnm-core/nm-setting-private.h +++ b/libnm-core/nm-setting-private.h @@ -126,6 +126,7 @@ GVariant *_nm_setting_to_dbus (NMSetting *setting, NMSetting *_nm_setting_new_from_dbus (GType setting_type, GVariant *setting_dict, GVariant *connection_dict, + NMSettingParseFlags parse_flags, GError **error); typedef GVariant * (*NMSettingPropertyGetFunc) (NMSetting *setting, @@ -133,13 +134,17 @@ typedef GVariant * (*NMSettingPropertyGetFunc) (NMSetting *setting, typedef GVariant * (*NMSettingPropertySynthFunc) (NMSetting *setting, NMConnection *connection, const char *property); -typedef void (*NMSettingPropertySetFunc) (NMSetting *setting, +typedef gboolean (*NMSettingPropertySetFunc) (NMSetting *setting, GVariant *connection_dict, const char *property, - GVariant *value); -typedef void (*NMSettingPropertyNotSetFunc) (NMSetting *setting, + GVariant *value, + NMSettingParseFlags parse_flags, + GError **error); +typedef gboolean (*NMSettingPropertyNotSetFunc) (NMSetting *setting, GVariant *connection_dict, - const char *property); + const char *property, + NMSettingParseFlags parse_flags, + GError **error); void _nm_setting_class_add_dbus_only_property (NMSettingClass *setting_class, const char *property_name, diff --git a/libnm-core/nm-setting-vlan.c b/libnm-core/nm-setting-vlan.c index 39587d59f9..827a47af23 100644 --- a/libnm-core/nm-setting-vlan.c +++ b/libnm-core/nm-setting-vlan.c @@ -692,16 +692,19 @@ _override_flags_get (NMSetting *setting, const char *property) return g_variant_new_uint32 (nm_setting_vlan_get_flags ((NMSettingVlan *) setting)); } -static void +static gboolean _override_flags_not_set (NMSetting *setting, - GVariant *connection_dict, - const char *property) + GVariant *connection_dict, + const char *property, + NMSettingParseFlags parse_flags, + GError **error) { /* we changed the default value for FLAGS. When an older client * doesn't serialize the property, we assume it is the old default. */ g_object_set (G_OBJECT (setting), NM_SETTING_VLAN_FLAGS, (NMVlanFlags) 0, NULL); + return TRUE; } static GSList * diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index fec645b263..0c41bd84c3 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -774,6 +774,7 @@ _nm_setting_to_dbus (NMSetting *setting, NMConnection *connection, NMConnectionS * mapping property names to values * @connection_dict: the #GVariant containing an %NM_VARIANT_TYPE_CONNECTION * dictionary mapping setting names to dictionaries. + * @parse_flags: flags to determine behavior during parsing. * @error: location to store error, or %NULL * * Creates a new #NMSetting object and populates that object with the properties @@ -790,16 +791,20 @@ NMSetting * _nm_setting_new_from_dbus (GType setting_type, GVariant *setting_dict, GVariant *connection_dict, + NMSettingParseFlags parse_flags, GError **error) { - NMSetting *setting; + gs_unref_object NMSetting *setting = NULL; + gs_unref_hashtable GHashTable *keys = NULL; const NMSettingProperty *properties; - guint n_properties; - guint i; + guint i, n_properties; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); g_return_val_if_fail (g_variant_is_of_type (setting_dict, NM_VARIANT_TYPE_SETTING), NULL); + 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)); + /* connection_dict is not technically optional, but some tests in test-general * don't bother with it in cases where they know it's not needed. */ @@ -813,19 +818,49 @@ _nm_setting_new_from_dbus (GType setting_type, */ setting = (NMSetting *) g_object_new (setting_type, NULL); + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) { + GVariantIter iter; + GVariant *entry, *entry_key; + char *key; + + keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + g_variant_iter_init (&iter, setting_dict); + while ((entry = g_variant_iter_next_value (&iter))) { + entry_key = g_variant_get_child_value (entry, 0); + key = g_strdup (g_variant_get_string (entry_key, NULL)); + g_variant_unref (entry_key); + g_variant_unref (entry); + + if (!nm_g_hash_table_add (keys, key)) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_SETTING, + _("duplicate property")); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key); + return NULL; + } + } + } + properties = nm_setting_class_get_properties (NM_SETTING_GET_CLASS (setting), &n_properties); for (i = 0; i < n_properties; i++) { const NMSettingProperty *property = &properties[i]; - GVariant *value; + gs_unref_variant GVariant *value = NULL; + gs_free_error GError *local = NULL; if (property->param_spec && !(property->param_spec->flags & G_PARAM_WRITABLE)) continue; value = g_variant_lookup_value (setting_dict, property->name, NULL); + if (value && keys) + g_hash_table_remove (keys, property->name); + if (value && property->set_func) { + if (!g_variant_type_equal (g_variant_get_type (value), property->dbus_type)) { - property_type_error: + /* for backward behavior, fail unless best-effort is chosen. */ + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, _("can't set property of type '%s' from value of type '%s'"), property->dbus_type ? @@ -834,36 +869,83 @@ _nm_setting_new_from_dbus (GType setting_type, g_type_name (property->param_spec->value_type) : "(unknown)", g_variant_get_type_string (value)); g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); - - g_variant_unref (value); - g_object_unref (setting); return NULL; } - property->set_func (setting, - connection_dict, - property->name, - value); + if (!property->set_func (setting, + connection_dict, + property->name, + value, + parse_flags, + &local)) { + if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("failed to set property: %s"), + local->message); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); + return NULL; + } } else if (!value && property->not_set_func) { - property->not_set_func (setting, - connection_dict, - property->name); + if (!property->not_set_func (setting, + connection_dict, + property->name, + parse_flags, + &local)) { + if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("failed to set property: %s"), + local->message); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); + return NULL; + } } else if (value && property->param_spec) { - GValue object_value = { 0, }; + nm_auto_unset_gvalue GValue object_value = G_VALUE_INIT; g_value_init (&object_value, property->param_spec->value_type); - if (!set_property_from_dbus (property, value, &object_value)) - goto property_type_error; + if (!set_property_from_dbus (property, value, &object_value)) { + /* for backward behavior, fail unless best-effort is chosen. */ + if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)) + continue; + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't set property of type '%s' from value of type '%s'"), + property->dbus_type ? + g_variant_type_peek_string (property->dbus_type) : + property->param_spec ? + g_type_name (property->param_spec->value_type) : "(unknown)", + g_variant_get_type_string (value)); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); + return NULL; + } - g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value); - g_value_unset (&object_value); + if (!nm_g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value, &local)) { + if (!NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) + continue; + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can not set property: %s"), + local->message); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); + return NULL; + } } + } - if (value) - g_variant_unref (value); + if ( NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT) + && g_hash_table_size (keys) > 0) { + GHashTableIter iter; + const char *key; + + g_hash_table_iter_init (&iter, keys); + if (g_hash_table_iter_next (&iter, (gpointer *) &key, NULL)) { + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("unknown property")); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), key); + return NULL; + } } - return setting; + return nm_unauto (&setting); } /** diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 82af4140f1..6541834284 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -1025,7 +1025,7 @@ test_setting_new_from_dbus (void) dict = _nm_setting_to_dbus (NM_SETTING (s_wsec), NULL, NM_CONNECTION_SERIALIZE_ALL); g_object_unref (s_wsec); - s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NULL); + s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, NULL); g_variant_unref (dict); g_assert (s_wsec); @@ -1054,7 +1054,7 @@ test_setting_new_from_dbus_transform (void) dbus_mac_address, ETH_ALEN, 1)); dict = g_variant_builder_end (&builder); - s_wired = _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRED, dict, NULL, &error); + s_wired = _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRED, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error); g_assert_no_error (error); g_assert_cmpstr (nm_setting_wired_get_mac_address (NM_SETTING_WIRED (s_wired)), ==, test_mac_address); @@ -1080,7 +1080,7 @@ test_setting_new_from_dbus_enum (void) g_variant_new_int32 (NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR)); dict = g_variant_builder_end (&builder); - s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_IP6_CONFIG, dict, NULL, &error); + s_ip6 = (NMSettingIP6Config *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_IP6_CONFIG, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error); g_assert_no_error (error); g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (s_ip6), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); @@ -1099,7 +1099,7 @@ test_setting_new_from_dbus_enum (void) NM_SETTING_SECRET_FLAG_NOT_SAVED)); dict = g_variant_builder_end (&builder); - s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, &error); + s_wsec = (NMSettingWirelessSecurity *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_WIRELESS_SECURITY, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error); g_assert_no_error (error); g_assert_cmpint (nm_setting_wireless_security_get_wep_key_type (s_wsec), ==, NM_WEP_KEY_TYPE_KEY); @@ -1116,7 +1116,7 @@ test_setting_new_from_dbus_enum (void) g_variant_new_byte ('E')); dict = g_variant_builder_end (&builder); - s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_SERIAL, dict, NULL, &error); + s_serial = (NMSettingSerial *) _nm_setting_new_from_dbus (NM_TYPE_SETTING_SERIAL, dict, NULL, NM_SETTING_PARSE_FLAGS_NONE, &error); g_assert_no_error (error); g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_EVEN); |