summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libnm-core/nm-connection.c71
-rw-r--r--libnm-core/nm-core-internal.h14
-rw-r--r--libnm-core/nm-setting-connection.c15
-rw-r--r--libnm-core/nm-setting-ip-config.c11
-rw-r--r--libnm-core/nm-setting-ip4-config.c44
-rw-r--r--libnm-core/nm-setting-ip6-config.c44
-rw-r--r--libnm-core/nm-setting-private.h13
-rw-r--r--libnm-core/nm-setting-vlan.c9
-rw-r--r--libnm-core/nm-setting.c128
-rw-r--r--libnm-core/tests/test-general.c10
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);