diff options
author | Thomas Haller <thaller@redhat.com> | 2016-03-29 13:01:18 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2016-03-29 13:01:18 +0200 |
commit | 53011592af2d282947a513b2b7da1b3b08be2aea (patch) | |
tree | af9f3943aac5ff2ea1a685567301e287b400d961 | |
parent | c473cb42d0d7a2157ddba119aac17fdb9c448e2d (diff) | |
parent | b645a3b39d574fdf4e02bae3ee18bea8a3d3f95c (diff) | |
download | NetworkManager-53011592af2d282947a513b2b7da1b3b08be2aea.tar.gz |
Merge branch master of git://anongit.freedesktop.org/NetworkManager/NetworkManagerth/mif
44 files changed, 1321 insertions, 712 deletions
diff --git a/libnm-core/Makefile.libnm-core b/libnm-core/Makefile.libnm-core index fe8cc8a603..0038ce23d6 100644 --- a/libnm-core/Makefile.libnm-core +++ b/libnm-core/Makefile.libnm-core @@ -52,6 +52,7 @@ libnm_core_headers = \ $(core)/nm-vpn-plugin-info.h libnm_core_private_headers = \ + $(top_builddir)/shared/nm-shared-utils.h \ $(core)/crypto.h \ $(core)/nm-connection-private.h \ $(core)/nm-core-internal.h \ @@ -63,6 +64,7 @@ libnm_core_private_headers = \ $(core)/nm-utils-private.h libnm_core_sources = \ + $(top_builddir)/shared/nm-shared-utils.c \ $(core_build)/nm-core-enum-types.c \ $(core)/crypto.c \ $(core)/nm-connection.c \ diff --git a/libnm-core/nm-connection.c b/libnm-core/nm-connection.c index 04e601ce8c..c03e62656f 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); } /** diff --git a/libnm-core/nm-core-internal.h b/libnm-core/nm-core-internal.h index 3e1236b975..9512ee5619 100644 --- a/libnm-core/nm-core-internal.h +++ b/libnm-core/nm-core-internal.h @@ -100,6 +100,25 @@ 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_NORMALIZE = 1LL << 2, + + _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); + +NMConnection *_nm_simple_connection_new_from_dbus (GVariant *dict, + 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); @@ -179,8 +198,6 @@ GByteArray *nm_utils_rsa_key_encrypt (const guint8 *data, char **out_password, GError **error); -gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); - gulong _nm_dbus_signal_connect_data (GDBusProxy *proxy, const char *signal_name, const GVariantType *signature, diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c index 365bc38c3c..8f584b19d2 100644 --- a/libnm-core/nm-setting-connection.c +++ b/libnm-core/nm-setting-connection.c @@ -1127,11 +1127,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; @@ -1146,12 +1148,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; @@ -1159,6 +1165,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/nm-simple-connection.c b/libnm-core/nm-simple-connection.c index 1036c8ecce..11700666f5 100644 --- a/libnm-core/nm-simple-connection.c +++ b/libnm-core/nm-simple-connection.c @@ -51,7 +51,7 @@ nm_simple_connection_new (void) } /** - * nm_simple_connection_new_from_dbus: + * _nm_simple_connection_new_from_dbus: * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection * @error: on unsuccessful return, an error * @@ -60,25 +60,47 @@ nm_simple_connection_new (void) * hash table. * * Returns: (transfer full): the new #NMSimpleConnection object, populated with - * settings created from the values in the hash table, or %NULL if the - * connection failed to validate + * settings created from the values in the hash table, or %NULL if there was + * an error. **/ NMConnection * -nm_simple_connection_new_from_dbus (GVariant *dict, GError **error) +_nm_simple_connection_new_from_dbus (GVariant *dict, NMSettingParseFlags parse_flags, GError **error) { NMConnection *connection; g_return_val_if_fail (dict != NULL, NULL); g_return_val_if_fail (g_variant_is_of_type (dict, NM_VARIANT_TYPE_CONNECTION), NULL); + g_return_val_if_fail (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL), NULL); + g_return_val_if_fail (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT), NULL); connection = nm_simple_connection_new (); - if ( !nm_connection_replace_settings (connection, dict, error) - || !nm_connection_normalize (connection, NULL, NULL, error)) + if (!_nm_connection_replace_settings (connection, dict, parse_flags, error)) g_clear_object (&connection); return connection; } /** + * nm_simple_connection_new_from_dbus: + * @dict: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION describing the connection + * @error: on unsuccessful return, an error + * + * Creates a new #NMSimpleConnection from a hash table describing the + * connection and normalize the connection. See nm_connection_to_dbus() for a + * description of the expected hash table. + * + * Returns: (transfer full): the new #NMSimpleConnection object, populated with + * settings created from the values in the hash table, or %NULL if the + * connection failed to normalize. + **/ +NMConnection * +nm_simple_connection_new_from_dbus (GVariant *dict, GError **error) +{ + return _nm_simple_connection_new_from_dbus (dict, + NM_SETTING_PARSE_FLAGS_NORMALIZE, + error); +} + +/** * nm_simple_connection_new_clone: * @connection: the #NMConnection to clone * diff --git a/libnm-core/nm-utils.c b/libnm-core/nm-utils.c index 10d54fa86b..a846708101 100644 --- a/libnm-core/nm-utils.c +++ b/libnm-core/nm-utils.c @@ -3789,81 +3789,6 @@ _nm_utils_strstrdictkey_create (const char *v1, const char *v2) return k; } -/**********************************************************************************************/ - -/* _nm_utils_ascii_str_to_int64: - * - * A wrapper for g_ascii_strtoll, that checks whether the whole string - * can be successfully converted to a number and is within a given - * range. On any error, @fallback will be returned and %errno will be set - * to a non-zero value. On success, %errno will be set to zero, check %errno - * for errors. Any trailing or leading (ascii) white space is ignored and the - * functions is locale independent. - * - * The function is guaranteed to return a value between @min and @max - * (inclusive) or @fallback. Also, the parsing is rather strict, it does - * not allow for any unrecognized characters, except leading and trailing - * white space. - **/ -gint64 -_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback) -{ - gint64 v; - size_t len; - char buf[64], *s, *str_free = NULL; - - if (str) { - while (g_ascii_isspace (str[0])) - str++; - } - if (!str || !str[0]) { - errno = EINVAL; - return fallback; - } - - len = strlen (str); - if (g_ascii_isspace (str[--len])) { - /* backward search the first non-ws character. - * We already know that str[0] is non-ws. */ - while (g_ascii_isspace (str[--len])) - ; - - /* str[len] is now the last non-ws character... */ - len++; - - if (len >= sizeof (buf)) - s = str_free = g_malloc (len + 1); - else - s = buf; - - memcpy (s, str, len); - s[len] = 0; - - nm_assert (len > 0 && len < strlen (str) && len == strlen (s)); - nm_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len])); - nm_assert (strncmp (str, s, len) == 0); - - str = s; - } - - errno = 0; - v = g_ascii_strtoll (str, &s, base); - - if (errno != 0) - v = fallback; - else if (s[0] != 0) { - errno = EINVAL; - v = fallback; - } else if (v > max || v < min) { - errno = ERANGE; - v = fallback; - } - - if (G_UNLIKELY (str_free)) - g_free (str_free); - return v; -} - static gboolean validate_dns_option (const char *name, gboolean numeric, gboolean ipv6, const NMUtilsDNSOptionDesc *option_descs) diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 82af4140f1..dcbcb88021 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -74,6 +74,12 @@ G_STATIC_ASSERT (sizeof (bool) <= sizeof (int)); /*****************************************************************************/ +static NMConnection * +_connection_new_from_dbus (GVariant *dict, GError **error) +{ + return _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, error); +} + static void vpn_check_func (const char *key, const char *value, gpointer user_data) { @@ -450,7 +456,7 @@ test_setting_ip4_config_labels (void) NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-data"); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_no_error (error); g_variant_unref (dict); @@ -473,7 +479,7 @@ test_setting_ip4_config_labels (void) NMTST_VARIANT_DROP_PROPERTY (NM_SETTING_IP4_CONFIG_SETTING_NAME, "address-labels"); ); - conn = nm_simple_connection_new_from_dbus (dict2, &error); + conn = _connection_new_from_dbus (dict2, &error); g_assert_no_error (error); g_variant_unref (dict2); @@ -603,7 +609,7 @@ test_setting_ip4_config_address_data (void) g_object_unref (conn); /* When we reserialize that dictionary as a client, 'address-data' will be preferred. */ - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_no_error (error); s_ip4 = nm_connection_get_setting_ip4_config (conn); @@ -619,7 +625,7 @@ test_setting_ip4_config_address_data (void) /* But on the server side, 'addresses' will have precedence. */ _nm_utils_is_manager_process = TRUE; - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); _nm_utils_is_manager_process = FALSE; g_assert_no_error (error); g_variant_unref (dict); @@ -1025,7 +1031,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 +1060,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 +1086,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 +1105,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 +1122,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); @@ -1188,7 +1194,7 @@ test_setting_new_from_dbus_bad (void) g_object_unref (conn); /* sanity-check */ - conn = nm_simple_connection_new_from_dbus (orig_dict, &error); + conn = _connection_new_from_dbus (orig_dict, &error); g_assert_no_error (error); g_assert (conn); g_object_unref (conn); @@ -1201,7 +1207,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_WIRELESS_RATE, "i", 10); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert (conn); g_assert_no_error (error); setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_WIRELESS); @@ -1216,7 +1222,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_IP6_CONFIG_IP6_PRIVACY, "i", NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert (conn); g_assert_no_error (error); setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_IP6_CONFIG); @@ -1233,7 +1239,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_WIRELESS_RATE, "s", "ten"); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "802-11-wireless.rate:")); g_clear_error (&error); @@ -1245,7 +1251,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_WIRELESS_MODE, "b", FALSE); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "802-11-wireless.mode:")); g_clear_error (&error); @@ -1257,7 +1263,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_WIRELESS_SSID, "s", "fred"); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "802-11-wireless.ssid:")); g_clear_error (&error); @@ -1269,7 +1275,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_WIRELESS_BSSID, "i", 42); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "802-11-wireless.bssid:")); g_clear_error (&error); @@ -1281,7 +1287,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_IP6_CONFIG_IP6_PRIVACY, "s", "private"); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "ipv6.ip6-privacy:")); g_clear_error (&error); @@ -1293,7 +1299,7 @@ test_setting_new_from_dbus_bad (void) NM_SETTING_IP_CONFIG_ADDRESSES, "s", "1234::5678"); ); - conn = nm_simple_connection_new_from_dbus (dict, &error); + conn = _connection_new_from_dbus (dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_assert (g_str_has_prefix (error->message, "ipv6.addresses:")); g_clear_error (&error); @@ -1561,7 +1567,7 @@ test_connection_new_from_dbus (void) g_assert (new_settings); /* Replace settings and test */ - connection = nm_simple_connection_new_from_dbus (new_settings, &error); + connection = _connection_new_from_dbus (new_settings, &error); g_assert_no_error (error); g_assert (connection); @@ -3241,7 +3247,7 @@ test_connection_normalize_virtual_iface_name (void) ":::this-is-not-a-valid-interface-name:::"); ); - con = nm_simple_connection_new_from_dbus (connection_dict, &error); + con = _connection_new_from_dbus (connection_dict, &error); g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); g_clear_error (&error); @@ -3253,7 +3259,7 @@ test_connection_normalize_virtual_iface_name (void) IFACE_VIRT); ); - con = nm_simple_connection_new_from_dbus (connection_dict, &error); + con = _connection_new_from_dbus (connection_dict, &error); g_assert_no_error (error); g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_NAME); @@ -3269,7 +3275,7 @@ test_connection_normalize_virtual_iface_name (void) NM_SETTING_CONNECTION_INTERFACE_NAME); ); - con = nm_simple_connection_new_from_dbus (connection_dict, &error); + con = _connection_new_from_dbus (connection_dict, &error); g_assert_no_error (error); g_assert_cmpstr (nm_connection_get_interface_name (con), ==, IFACE_VIRT); @@ -3783,7 +3789,7 @@ test_setting_ip4_gateway (void) "address-data"); ); - conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + conn = _connection_new_from_dbus (conn_dict, &error); g_assert_no_error (error); s_ip4 = (NMSettingIPConfig *) nm_connection_get_setting_ip4_config (conn); @@ -3805,7 +3811,7 @@ test_setting_ip4_gateway (void) "addresses", "aau", &addrs_builder); ); - conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + conn = _connection_new_from_dbus (conn_dict, &error); g_assert_no_error (error); g_variant_unref (conn_dict); @@ -3890,7 +3896,7 @@ test_setting_ip6_gateway (void) "address-data"); ); - conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + conn = _connection_new_from_dbus (conn_dict, &error); g_assert_no_error (error); s_ip6 = (NMSettingIPConfig *) nm_connection_get_setting_ip6_config (conn); @@ -3918,7 +3924,7 @@ test_setting_ip6_gateway (void) "addresses", "a(ayuay)", &addrs_builder); ); - conn = nm_simple_connection_new_from_dbus (conn_dict, &error); + conn = _connection_new_from_dbus (conn_dict, &error); g_assert_no_error (error); g_variant_unref (conn_dict); diff --git a/libnm-glib/nm-remote-connection.c b/libnm-glib/nm-remote-connection.c index 132032f488..a4dc638adc 100644 --- a/libnm-glib/nm-remote-connection.c +++ b/libnm-glib/nm-remote-connection.c @@ -31,6 +31,7 @@ #include "nm-object-private.h" #include "nm-dbus-glib-types.h" #include "nm-dbus-helpers-private.h" +#include "nm-setting-private.h" #define NM_REMOTE_CONNECTION_BUS "bus" #define NM_REMOTE_CONNECTION_DBUS_CONNECTION "dbus-connection" @@ -447,24 +448,6 @@ nm_remote_connection_get_unsaved (NMRemoteConnection *connection) /****************************************************************/ static void -replace_settings (NMRemoteConnection *self, GHashTable *new_settings) -{ - GError *error = NULL; - - if (nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) - g_signal_emit (self, signals[UPDATED], 0, new_settings); - else { - g_warning ("%s: error updating connection %s settings: %s", - __func__, - nm_connection_get_path (NM_CONNECTION (self)), - error->message); - g_clear_error (&error); - - g_signal_emit (self, signals[REMOVED], 0); - } -} - -static void updated_get_settings_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) @@ -488,7 +471,7 @@ updated_get_settings_cb (DBusGProxy *proxy, * object. */ hash = g_hash_table_new (g_str_hash, g_str_equal); - nm_connection_replace_settings (NM_CONNECTION (self), hash, NULL); + _nm_connection_replace_settings (NM_CONNECTION (self), hash); g_hash_table_destroy (hash); priv->visible = FALSE; @@ -497,7 +480,8 @@ updated_get_settings_cb (DBusGProxy *proxy, gs_unref_object NMConnection *self_alive = NULL; self_alive = g_object_ref (self); - replace_settings (self, new_settings); + _nm_connection_replace_settings (NM_CONNECTION (self), new_settings); + g_signal_emit (self, signals[UPDATED], 0, new_settings); g_hash_table_destroy (new_settings); /* Settings service will handle announcing the connection to clients */ @@ -628,7 +612,8 @@ init_sync (GInitable *initable, GCancellable *cancellable, GError **error) return FALSE; priv->visible = TRUE; self_alive = g_object_ref (initable); - replace_settings (NM_REMOTE_CONNECTION (initable), hash); + _nm_connection_replace_settings (NM_CONNECTION (initable), hash); + g_signal_emit (initable, signals[UPDATED], 0, hash); g_hash_table_destroy (hash); /* Get properties */ @@ -703,7 +688,8 @@ init_get_settings_cb (DBusGProxy *proxy, priv->visible = TRUE; self_alive = g_object_ref (init_data->connection); - replace_settings (init_data->connection, settings); + _nm_connection_replace_settings (NM_CONNECTION (init_data->connection), settings); + g_signal_emit (init_data->connection, signals[UPDATED], 0, settings); g_hash_table_destroy (settings); /* Grab properties */ diff --git a/libnm-glib/nm-secret-agent.c b/libnm-glib/nm-secret-agent.c index 0a86245568..03290469ad 100644 --- a/libnm-glib/nm-secret-agent.c +++ b/libnm-glib/nm-secret-agent.c @@ -27,6 +27,7 @@ #include "nm-secret-agent.h" #include "nm-glib-enum-types.h" #include "nm-dbus-helpers-private.h" +#include "nm-setting-private.h" static void impl_secret_agent_get_secrets (NMSecretAgent *self, GHashTable *connection_hash, @@ -302,7 +303,8 @@ verify_request (NMSecretAgent *self, GError **error) { NMConnection *connection = NULL; - GError *local = NULL; + + g_return_val_if_fail (out_connection, FALSE); if (!verify_sender (self, context, error)) return FALSE; @@ -321,21 +323,11 @@ verify_request (NMSecretAgent *self, } /* Make sure the given connection is valid */ - g_assert (out_connection); - connection = nm_connection_new_from_hash (connection_hash, &local); - if (connection) { - nm_connection_set_path (connection, connection_path); - *out_connection = connection; - } else { - g_set_error (error, - NM_SECRET_AGENT_ERROR, - NM_SECRET_AGENT_ERROR_INVALID_CONNECTION, - "Invalid connection: %s", - local->message); - g_clear_error (&local); - } + connection = _nm_connection_new_from_hash (connection_hash); + nm_connection_set_path (connection, connection_path); + *out_connection = connection; - return !!connection; + return TRUE; } static void diff --git a/libnm-glib/nm-vpn-plugin.c b/libnm-glib/nm-vpn-plugin.c index d117e53092..2af9deb4bd 100644 --- a/libnm-glib/nm-vpn-plugin.c +++ b/libnm-glib/nm-vpn-plugin.c @@ -29,6 +29,7 @@ #include "nm-utils.h" #include "nm-connection.h" #include "nm-dbus-glib-types.h" +#include "nm-setting-private.h" static gboolean impl_vpn_plugin_connect (NMVPNPlugin *plugin, GHashTable *connection, @@ -452,13 +453,7 @@ _connect_generic (NMVPNPlugin *plugin, return FALSE; } - connection = nm_connection_new_from_hash (properties, &local); - if (!connection) { - g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - "Invalid connection: %s", local->message); - g_clear_error (&local); - return FALSE; - } + connection = _nm_connection_new_from_hash (properties); priv->interactive = FALSE; if (details && !vpn_class->connect_interactive) { @@ -526,22 +521,11 @@ impl_vpn_plugin_need_secrets (NMVPNPlugin *plugin, char *sn = NULL; GError *ns_err = NULL; gboolean needed = FALSE; - GError *cnfh_err = NULL; g_return_val_if_fail (NM_IS_VPN_PLUGIN (plugin), FALSE); g_return_val_if_fail (properties != NULL, FALSE); - connection = nm_connection_new_from_hash (properties, &cnfh_err); - if (!connection) { - g_set_error (err, - NM_VPN_PLUGIN_ERROR, - NM_VPN_PLUGIN_ERROR_CONNECTION_INVALID, - "The connection was invalid: '%s' / '%s' invalid.", - g_type_name (nm_connection_lookup_setting_type_by_quark (cnfh_err->domain)), - cnfh_err->message); - g_error_free (cnfh_err); - return FALSE; - } + connection = _nm_connection_new_from_hash (properties); if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->need_secrets) { *setting_name = ""; @@ -581,7 +565,6 @@ impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin, { NMVPNPluginPrivate *priv = NM_VPN_PLUGIN_GET_PRIVATE (plugin); NMConnection *connection; - GError *local = NULL; gboolean success; if (priv->state != NM_VPN_SERVICE_STATE_STARTING) { @@ -591,14 +574,7 @@ impl_vpn_plugin_new_secrets (NMVPNPlugin *plugin, return FALSE; } - connection = nm_connection_new_from_hash (properties, &local); - if (!connection) { - g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS, - "Invalid connection: %s", - local->message); - g_clear_error (&local); - return FALSE; - } + connection = _nm_connection_new_from_hash (properties); if (!NM_VPN_PLUGIN_GET_CLASS (plugin)->new_secrets) { g_set_error_literal (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_INTERACTIVE_NOT_SUPPORTED, diff --git a/libnm-glib/tests/test-nm-client.c b/libnm-glib/tests/test-nm-client.c index da2e39e04f..0da93c3fd3 100644 --- a/libnm-glib/tests/test-nm-client.c +++ b/libnm-glib/tests/test-nm-client.c @@ -955,12 +955,8 @@ test_connection_invalid (void) settings = nmtstc_nm_remote_settings_new (); - g_test_expect_message ("libnm-glib", G_LOG_LEVEL_WARNING, "*replace_settings: error updating connection*"); - nmtst_main_loop_run (loop, 100); - g_test_assert_expected_messages (); - _slist_to_array (&connections, nm_remote_settings_list_connections (settings)); g_assert_cmpint (connections->len, ==, 2); @@ -991,12 +987,8 @@ test_connection_invalid (void) FALSE, &path2); - g_test_expect_message ("libnm-glib", G_LOG_LEVEL_WARNING, "*replace_settings: error updating connection*"); - nmtst_main_loop_run (loop, 100); - g_test_assert_expected_messages (); - _slist_to_array (&connections, nm_remote_settings_list_connections (settings)); g_assert_cmpint (connections->len, ==, 3); @@ -1027,15 +1019,11 @@ test_connection_invalid (void) connection, FALSE); - g_test_expect_message ("libnm-glib", G_LOG_LEVEL_WARNING, "*replace_settings: error updating connection*"); - nmtst_main_loop_run (loop, 100); - g_test_assert_expected_messages (); - _slist_to_array (&connections, nm_remote_settings_list_connections (settings)); - g_assert_cmpint (connections->len, ==, 2); + g_assert_cmpint (connections->len, ==, 3); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, (gpointer *) ((const char *[]) { path0, path1, path2 }), @@ -1043,12 +1031,13 @@ test_connection_invalid (void) _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 2); + g_assert_cmpint (n_found, ==, 3); ASSERT_IDX (0); ASSERT_IDX (1); - g_assert_cmpint (idx[2], ==, -1); + ASSERT_IDX (2); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0); /************************************************************************** * Modify the invalid connection again. Note that the connection stays @@ -1073,7 +1062,7 @@ test_connection_invalid (void) _slist_to_array (&connections, nm_remote_settings_list_connections (settings)); - g_assert_cmpint (connections->len, ==, 2); + g_assert_cmpint (connections->len, ==, 3); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, (gpointer *) ((const char *[]) { path0, path1, path2 }), @@ -1081,12 +1070,13 @@ test_connection_invalid (void) _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 2); + g_assert_cmpint (n_found, ==, 3); ASSERT_IDX (0); ASSERT_IDX (1); - g_assert_cmpint (idx[2], ==, -1); + ASSERT_IDX (2); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]); /************************************************************************** @@ -1111,7 +1101,7 @@ test_connection_invalid (void) _slist_to_array (&connections, nm_remote_settings_list_connections (settings)); - g_assert_cmpint (connections->len, ==, 2); + g_assert_cmpint (connections->len, ==, 3); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, (gpointer *) ((const char *[]) { path0, path1, path2 }), @@ -1119,12 +1109,13 @@ test_connection_invalid (void) _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 2); + g_assert_cmpint (n_found, ==, 3); ASSERT_IDX (0); ASSERT_IDX (1); - g_assert_cmpint (idx[2], ==, -1); + ASSERT_IDX (2); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[1]]); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]); g_assert_cmpstr ("test-connection-invalid-1x", ==, nm_connection_get_id (connections->pdata[idx[1]])); #undef ASSERT_IDX diff --git a/libnm-util/Makefile.am b/libnm-util/Makefile.am index 6e63790817..e9ccdae7f3 100644 --- a/libnm-util/Makefile.am +++ b/libnm-util/Makefile.am @@ -63,6 +63,7 @@ nodist_libnm_util_include_HEADERS = \ nm-utils-enum-types.h libnm_util_la_private_headers = \ + $(top_builddir)/shared/nm-shared-utils.h \ crypto.h \ nm-dbus-glib-types.h \ nm-gvaluearray-compat.h \ @@ -71,6 +72,7 @@ libnm_util_la_private_headers = \ nm-utils-private.h libnm_util_la_csources = \ + $(top_builddir)/shared/nm-shared-utils.c \ crypto.c \ nm-connection.c \ nm-param-spec-specialized.c \ diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver index 1ad853f5fb..385cdb8e3b 100644 --- a/libnm-util/libnm-util.ver +++ b/libnm-util/libnm-util.ver @@ -1,5 +1,7 @@ { global: + _nm_connection_new_from_hash; + _nm_connection_replace_settings; nm_connection_add_setting; nm_connection_clear_secrets; nm_connection_clear_secrets_with_flags; diff --git a/libnm-util/nm-connection.c b/libnm-util/nm-connection.c index c440fb1b28..51c480284f 100644 --- a/libnm-util/nm-connection.c +++ b/libnm-util/nm-connection.c @@ -327,19 +327,30 @@ validate_permissions_type (GHashTable *hash, GError **error) return TRUE; } -static gboolean -hash_to_connection (NMConnection *connection, GHashTable *new, GError **error) +/** + * _nm_connection_replace_settings: + * @connection: a #NMConnection + * @new_settings: (element-type utf8 GLib.HashTable): a #GHashTable of settings + **/ +void +_nm_connection_replace_settings (NMConnection *connection, + GHashTable *new_settings) { + NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); GHashTableIter iter; const char *setting_name; GHashTable *setting_hash; - gboolean changed, valid; - NMConnectionPrivate *priv = NM_CONNECTION_GET_PRIVATE (connection); + gboolean changed; + + g_return_if_fail (NM_IS_CONNECTION (connection)); + g_return_if_fail (new_settings != NULL); + + priv = NM_CONNECTION_GET_PRIVATE (connection); if ((changed = g_hash_table_size (priv->settings) > 0)) g_hash_table_foreach_remove (priv->settings, _setting_release, connection); - g_hash_table_iter_init (&iter, new); + g_hash_table_iter_init (&iter, new_settings); while (g_hash_table_iter_next (&iter, (gpointer) &setting_name, (gpointer) &setting_hash)) { GType type = nm_connection_lookup_setting_type (setting_name); @@ -353,10 +364,8 @@ hash_to_connection (NMConnection *connection, GHashTable *new, GError **error) } } - valid = nm_connection_verify (connection, error); if (changed) g_signal_emit (connection, signals[CHANGED], 0); - return valid; } /** @@ -373,16 +382,15 @@ nm_connection_replace_settings (NMConnection *connection, GHashTable *new_settings, GError **error) { - gboolean valid = FALSE; - g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (new_settings != NULL, FALSE); - if (error) - g_return_val_if_fail (*error == NULL, FALSE); + g_return_val_if_fail (!error || !*error, FALSE); - if (validate_permissions_type (new_settings, error)) - valid = hash_to_connection (connection, new_settings, error); - return valid; + if (!validate_permissions_type (new_settings, error)) + return FALSE; + + _nm_connection_replace_settings (connection, new_settings); + return nm_connection_verify (connection, error); } /** @@ -409,7 +417,8 @@ nm_connection_replace_settings_from_connection (NMConnection *connection, NMConnectionPrivate *priv; GHashTableIter iter; NMSetting *setting; - gboolean changed, valid; + gboolean changed = FALSE; + gboolean valid; g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (new_connection), FALSE); @@ -418,7 +427,7 @@ nm_connection_replace_settings_from_connection (NMConnection *connection, /* When 'connection' and 'new_connection' are the same object simply return * in order not to destroy 'connection' */ if (connection == new_connection) - return TRUE; + goto out; /* No need to validate permissions like nm_connection_replace_settings() * since we're dealing with an NMConnection which has already done that. @@ -435,6 +444,7 @@ nm_connection_replace_settings_from_connection (NMConnection *connection, changed = TRUE; } +out: valid = nm_connection_verify (connection, error); if (changed) g_signal_emit (connection, signals[CHANGED], 0); @@ -1441,6 +1451,29 @@ nm_connection_new (void) } /** + * _nm_connection_new_from_hash: + * @hash: (element-type utf8 GLib.HashTable): the #GHashTable describing + * the connection + * + * Creates a new #NMConnection from a hash table describing the connection. See + * nm_connection_to_hash() for a description of the expected hash table. + * + * Returns: the new #NMConnection object, populated with settings created + * from the values in the hash table. + **/ +NMConnection * +_nm_connection_new_from_hash (GHashTable *hash) +{ + NMConnection *connection; + + g_return_val_if_fail (hash != NULL, NULL); + + connection = nm_connection_new (); + _nm_connection_replace_settings (connection, hash); + return connection; +} + +/** * nm_connection_new_from_hash: * @hash: (element-type utf8 GLib.HashTable): the #GHashTable describing * the connection @@ -1463,11 +1496,9 @@ nm_connection_new_from_hash (GHashTable *hash, GError **error) if (!validate_permissions_type (hash, error)) return NULL; - connection = nm_connection_new (); - if (!hash_to_connection (connection, hash, error)) { - g_object_unref (connection); - return NULL; - } + connection = _nm_connection_new_from_hash (hash); + if (!nm_connection_verify (connection, error)) + g_clear_object (&connection); return connection; } diff --git a/libnm-util/nm-setting-private.h b/libnm-util/nm-setting-private.h index 6956463c3f..beb87484f0 100644 --- a/libnm-util/nm-setting-private.h +++ b/libnm-util/nm-setting-private.h @@ -23,6 +23,8 @@ #include "nm-default.h" +#include "nm-connection.h" + #define NM_SETTING_SECRET_FLAGS_ALL \ (NM_SETTING_SECRET_FLAG_NONE | \ NM_SETTING_SECRET_FLAG_AGENT_OWNED | \ @@ -62,6 +64,10 @@ gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); gboolean _nm_setting_get_property (NMSetting *setting, const char *name, GValue *value); +NMConnection *_nm_connection_new_from_hash (GHashTable *hash); +void _nm_connection_replace_settings (NMConnection *connection, + GHashTable *new_settings); + typedef enum NMSettingUpdateSecretResult { NM_SETTING_UPDATE_SECRET_ERROR = FALSE, NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE, diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index add3ad9795..990d6fe73b 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -379,9 +379,6 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) const char *prop_name; GValue *src_value; GObjectClass *class; - guint n_params = 0; - GParameter *params; - int i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); g_return_val_if_fail (hash != NULL, NULL); @@ -390,11 +387,11 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) * already been used. */ class = g_type_class_ref (setting_type); - params = g_new0 (GParameter, g_hash_table_size (hash)); + + setting = (NMSetting *) g_object_new (setting_type, NULL); g_hash_table_iter_init (&iter, hash); while (g_hash_table_iter_next (&iter, (gpointer) &prop_name, (gpointer) &src_value)) { - GValue *dst_value = ¶ms[n_params].value; GParamSpec *param_spec; param_spec = g_object_class_find_property (class, prop_name); @@ -402,21 +399,12 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) /* 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)); - g_value_copy (src_value, dst_value); - params[n_params++].name = prop_name; + nm_g_object_set_property ((GObject *) setting, prop_name, src_value, NULL); } - setting = (NMSetting *) g_object_newv (setting_type, n_params, params); - - for (i = 0; i < n_params; i++) - g_value_unset (¶ms[i].value); - - g_free (params); g_type_class_unref (class); return setting; diff --git a/libnm/nm-client.c b/libnm/nm-client.c index 57a43ca8dc..a7ecdb5572 100644 --- a/libnm/nm-client.c +++ b/libnm/nm-client.c @@ -1189,6 +1189,9 @@ nm_client_deactivate_connection_finish (NMClient *client, * Returns: (transfer none) (element-type NMRemoteConnection): an array * containing all connections provided by the remote settings service. The * returned array is owned by the #NMClient object and should not be modified. + * + * The connections are as received from D-Bus and might not validate according + * to nm_connection_verify(). **/ const GPtrArray * nm_client_get_connections (NMClient *client) @@ -1207,6 +1210,9 @@ nm_client_get_connections (NMClient *client) * * Returns: (transfer none): the remote connection object on success, or %NULL if no * matching object was found. + * + * The connection is as received from D-Bus and might not validate according + * to nm_connection_verify(). **/ NMRemoteConnection * nm_client_get_connection_by_id (NMClient *client, const char *id) @@ -1226,6 +1232,9 @@ nm_client_get_connection_by_id (NMClient *client, const char *id) * * Returns: (transfer none): the remote connection object on success, or %NULL if the object was * not known + * + * The connection is as received from D-Bus and might not validate according + * to nm_connection_verify(). **/ NMRemoteConnection * nm_client_get_connection_by_path (NMClient *client, const char *path) @@ -1245,6 +1254,9 @@ nm_client_get_connection_by_path (NMClient *client, const char *path) * * Returns: (transfer none): the remote connection object on success, or %NULL if the object was * not known + * + * The connection is as received from D-Bus and might not validate according + * to nm_connection_verify(). **/ NMRemoteConnection * nm_client_get_connection_by_uuid (NMClient *client, const char *uuid) diff --git a/libnm/nm-device.c b/libnm/nm-device.c index 28747e1c12..ab3c5d4e8d 100644 --- a/libnm/nm-device.c +++ b/libnm/nm-device.c @@ -2331,6 +2331,9 @@ nm_device_reapply_finish (NMDevice *device, * Returns: (transfer full): a %NMConnection with the currently applied settings * or %NULL on error. * + * The connection is as received from D-Bus and might not validate according + * to nm_connection_verify(). + * * Since: 1.2 **/ NMConnection * @@ -2357,7 +2360,7 @@ nm_device_get_applied_connection (NMDevice *device, return NULL; } - connection = nm_simple_connection_new_from_dbus (dict, error); + connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, error); if (!connection) return NULL; @@ -2399,7 +2402,7 @@ device_get_applied_connection_cb (GObject *proxy, goto out; } - connection = nm_simple_connection_new_from_dbus (dict, &error); + connection = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_simple_async_result_take_error (simple, error); goto out; @@ -2459,6 +2462,9 @@ nm_device_get_applied_connection_async (NMDevice *device, * Returns: (transfer full): a currently applied %NMConnection or %NULL in case * of error. * + * The connection is as received from D-Bus and might not validate according + * to nm_connection_verify(). + * * Since: 1.2 **/ NMConnection * diff --git a/libnm/nm-remote-connection.c b/libnm/nm-remote-connection.c index c4a0b6aeb0..eb2874a049 100644 --- a/libnm/nm-remote-connection.c +++ b/libnm/nm-remote-connection.c @@ -26,6 +26,7 @@ #include "nm-dbus-interface.h" #include "nm-utils.h" #include "nm-setting-connection.h" +#include "nm-core-internal.h" #include "nm-remote-connection.h" #include "nm-remote-connection-private.h" @@ -563,13 +564,11 @@ replace_settings (NMRemoteConnection *self, GVariant *new_settings) { GError *error = NULL; - if (!nm_connection_replace_settings (NM_CONNECTION (self), new_settings, &error)) { - g_warning ("%s: error updating connection %s settings: %s", - __func__, - nm_connection_get_path (NM_CONNECTION (self)), - error->message); + if (!_nm_connection_replace_settings ((NMConnection *) self, + new_settings, + NM_SETTING_PARSE_FLAGS_BEST_EFFORT, + &error)) g_clear_error (&error); - } } static void diff --git a/libnm/nm-secret-agent-old.c b/libnm/nm-secret-agent-old.c index 8edb224cb1..60b7a624e2 100644 --- a/libnm/nm-secret-agent-old.c +++ b/libnm/nm-secret-agent-old.c @@ -27,6 +27,7 @@ #include "nm-enum-types.h" #include "nm-dbus-helpers.h" #include "nm-simple-connection.h" +#include "nm-core-internal.h" #include "nmdbus-secret-agent.h" #include "nmdbus-agent-manager.h" @@ -273,7 +274,7 @@ verify_request (NMSecretAgentOld *self, /* Make sure the given connection is valid */ g_assert (out_connection); - connection = nm_simple_connection_new_from_dbus (connection_dict, &local); + connection = _nm_simple_connection_new_from_dbus (connection_dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &local); if (connection) { nm_connection_set_path (connection, connection_path); *out_connection = connection; diff --git a/libnm/nm-vpn-plugin-old.c b/libnm/nm-vpn-plugin-old.c index 74861edc46..634e61a232 100644 --- a/libnm/nm-vpn-plugin-old.c +++ b/libnm/nm-vpn-plugin-old.c @@ -465,7 +465,7 @@ _connect_generic (NMVpnPluginOld *plugin, return; } - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, @@ -547,7 +547,7 @@ impl_vpn_plugin_old_need_secrets (NMVpnPluginOld *plugin, gboolean needed; GError *error = NULL; - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, @@ -606,7 +606,7 @@ impl_vpn_plugin_old_new_secrets (NMVpnPluginOld *plugin, return; } - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index 876d479817..82e29ee8a3 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -481,7 +481,7 @@ _connect_generic (NMVpnServicePlugin *plugin, return; } - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, @@ -567,7 +567,7 @@ impl_vpn_service_plugin_need_secrets (NMVpnServicePlugin *plugin, gboolean needed; GError *error = NULL; - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, @@ -626,7 +626,7 @@ impl_vpn_service_plugin_new_secrets (NMVpnServicePlugin *plugin, return; } - connection = nm_simple_connection_new_from_dbus (properties, &error); + connection = _nm_simple_connection_new_from_dbus (properties, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); if (!connection) { g_dbus_method_invocation_return_error (context, NM_VPN_PLUGIN_ERROR, diff --git a/libnm/tests/test-nm-client.c b/libnm/tests/test-nm-client.c index 107cc58871..3a7c4d5dde 100644 --- a/libnm/tests/test-nm-client.c +++ b/libnm/tests/test-nm-client.c @@ -1243,10 +1243,12 @@ _test_connection_invalid_find_connections (gpointer element, gpointer needle, gp } #define ASSERT_IDX(i) \ - g_assert_cmpint (idx[i], >=, 0); \ - g_assert (path##i && *path##i); \ - g_assert (NM_IS_REMOTE_CONNECTION (connections->pdata[idx[i]])); \ - g_assert_cmpstr (nm_connection_get_path (connections->pdata[idx[i]]), ==, path##i); + G_STMT_START { \ + g_assert_cmpint (idx[i], >=, 0); \ + g_assert (path##i && *path##i); \ + g_assert (NM_IS_REMOTE_CONNECTION (connections->pdata[idx[i]])); \ + g_assert_cmpstr (nm_connection_get_path (connections->pdata[idx[i]]), ==, path##i); \ + } G_STMT_END static void test_connection_invalid (void) @@ -1260,12 +1262,14 @@ test_connection_invalid (void) gs_free char *path0 = NULL; gs_free char *path1 = NULL; gs_free char *path2 = NULL; + gs_free char *path3 = NULL; gs_free char *uuid2 = NULL; gsize n_found; - gssize idx[3]; + gssize idx[4]; + gs_unref_variant GVariant *variant = NULL; /************************************************************************** - * Add two connection before starting libnm. One valid, one invalid. + * Add three connections before starting libnm. One valid, two invalid. *************************************************************************/ connection = nmtst_create_minimal_connection ("test-connection-invalid-0", NULL, NM_SETTING_WIRED_SETTING_NAME, &s_con); @@ -1289,6 +1293,21 @@ test_connection_invalid (void) FALSE, &path1); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "test-connection-invalid-2", + NM_SETTING_CONNECTION_TYPE, "invalid-type-2", + NM_SETTING_CONNECTION_UUID, nmtst_uuid_generate (), + NULL); + variant = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); + NMTST_VARIANT_EDITOR (variant, + NMTST_VARIANT_ADD_SETTING ("invalid-type-2", + nmtst_variant_new_vardict ("some-key1", g_variant_new_string ("some-value1"), + "some-key2", g_variant_new_uint32 (4722)))); + g_variant_ref_sink (variant); + nmtstc_service_add_connection_variant (my_sinfo, + variant, + FALSE, + &path2); client = nm_client_new (NULL, &error); g_assert_no_error (error); @@ -1296,19 +1315,21 @@ test_connection_invalid (void) connections = nm_client_get_connections (client); g_assert (connections); - g_assert_cmpint (connections->len, ==, 2); + g_assert_cmpint (connections->len, ==, 3); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, - (gpointer *) ((const char *[]) { path0, path1 }), - 2, + (gpointer *) ((const char *[]) { path0, path1, path2 }), + 3, _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 2); + g_assert_cmpint (n_found, ==, 3); ASSERT_IDX (0); ASSERT_IDX (1); + ASSERT_IDX (2); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0); /************************************************************************** * After having the client up and running, add another invalid connection @@ -1322,7 +1343,7 @@ test_connection_invalid (void) nmtstc_service_add_connection (my_sinfo, connection, FALSE, - &path2); + &path3); nmtst_main_loop_run (loop, 100); @@ -1331,21 +1352,97 @@ test_connection_invalid (void) connections = nm_client_get_connections (client); g_assert (connections); - g_assert_cmpint (connections->len, ==, 3); + g_assert_cmpint (connections->len, ==, 4); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, - (gpointer *) ((const char *[]) { path0, path1, path2 }), - 3, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 3); + g_assert_cmpint (n_found, ==, 4); + ASSERT_IDX (0); + ASSERT_IDX (1); + ASSERT_IDX (2); + ASSERT_IDX (3); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[3]], 0, 0); + + /************************************************************************** + * Modify the invalid connection (still invalid) + *************************************************************************/ + + NMTST_VARIANT_EDITOR (variant, + NMTST_VARIANT_CHANGE_PROPERTY ("invalid-type-2", + "some-key2", "u", 4721)); + g_variant_ref_sink (variant); + nmtstc_service_update_connection_variant (my_sinfo, + path2, + variant, + FALSE); + + nmtst_main_loop_run (loop, 100); + + connections = nm_client_get_connections (client); + g_assert (connections); + + g_assert_cmpint (connections->len, ==, 4); + n_found = nmtst_find_all_indexes (connections->pdata, + connections->len, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, + _test_connection_invalid_find_connections, + NULL, + idx); + g_assert_cmpint (n_found, ==, 4); ASSERT_IDX (0); ASSERT_IDX (1); ASSERT_IDX (2); + ASSERT_IDX (3); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[3]], 0, 0); + + /************************************************************************** + * Modify the invalid connection (becomes valid) + *************************************************************************/ + + NMTST_VARIANT_EDITOR (variant, + NMTST_VARIANT_DROP_SETTING ("invalid-type-2")); + NMTST_VARIANT_EDITOR (variant, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE, "s", NM_SETTING_WIRED_SETTING_NAME)); + g_variant_ref_sink (variant); + nmtstc_service_update_connection_variant (my_sinfo, + path2, + variant, + FALSE); + + nmtst_main_loop_run (loop, 100); + + connections = nm_client_get_connections (client); + g_assert (connections); + + g_assert_cmpint (connections->len, ==, 4); + n_found = nmtst_find_all_indexes (connections->pdata, + connections->len, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, + _test_connection_invalid_find_connections, + NULL, + idx); + g_assert_cmpint (n_found, ==, 4); + ASSERT_IDX (0); + ASSERT_IDX (1); + ASSERT_IDX (2); + ASSERT_IDX (3); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); + nmtst_assert_connection_verifies_after_normalization (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[3]], 0, 0); /************************************************************************** * Modify the invalid connection (still invalid) @@ -1355,7 +1452,7 @@ test_connection_invalid (void) NM_SETTING_CONNECTION_ID, "test-connection-invalid-2x", NULL); nmtstc_service_update_connection (my_sinfo, - path2, + path3, connection, FALSE); @@ -1364,22 +1461,24 @@ test_connection_invalid (void) connections = nm_client_get_connections (client); g_assert (connections); - g_assert_cmpint (connections->len, ==, 3); + g_assert_cmpint (connections->len, ==, 4); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, - (gpointer *) ((const char *[]) { path0, path1, path2 }), - 3, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 3); + g_assert_cmpint (n_found, ==, 4); ASSERT_IDX (0); ASSERT_IDX (1); ASSERT_IDX (2); + ASSERT_IDX (3); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); - nmtst_assert_connection_unnormalizable (connections->pdata[idx[2]], 0, 0); - g_assert_cmpstr ("test-connection-invalid-2x", ==, nm_connection_get_id (connections->pdata[idx[2]])); + nmtst_assert_connection_verifies_after_normalization (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_unnormalizable (connections->pdata[idx[3]], 0, 0); + g_assert_cmpstr ("test-connection-invalid-2x", ==, nm_connection_get_id (connections->pdata[idx[3]])); /************************************************************************** * Modify the invalid connection (now becomes valid) @@ -1395,7 +1494,7 @@ test_connection_invalid (void) NULL); nmtstc_service_update_connection (my_sinfo, - path2, + path3, connection, FALSE); @@ -1404,22 +1503,24 @@ test_connection_invalid (void) connections = nm_client_get_connections (client); g_assert (connections); - g_assert_cmpint (connections->len, ==, 3); + g_assert_cmpint (connections->len, ==, 4); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, - (gpointer *) ((const char *[]) { path0, path1, path2 }), - 3, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 3); + g_assert_cmpint (n_found, ==, 4); ASSERT_IDX (0); ASSERT_IDX (1); ASSERT_IDX (2); + ASSERT_IDX (3); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_unnormalizable (connections->pdata[idx[1]], 0, 0); - nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]); - g_assert_cmpstr ("test-connection-invalid-2z", ==, nm_connection_get_id (connections->pdata[idx[2]])); + nmtst_assert_connection_verifies_after_normalization (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[3]]); + g_assert_cmpstr ("test-connection-invalid-2z", ==, nm_connection_get_id (connections->pdata[idx[3]])); /************************************************************************** * Modify the invalid connection and make it valid @@ -1444,23 +1545,25 @@ test_connection_invalid (void) connections = nm_client_get_connections (client); g_assert (connections); - g_assert_cmpint (connections->len, ==, 3); + g_assert_cmpint (connections->len, ==, 4); n_found = nmtst_find_all_indexes (connections->pdata, connections->len, - (gpointer *) ((const char *[]) { path0, path1, path2 }), - 3, + (gpointer *) ((const char *[]) { path0, path1, path2, path3 }), + 4, _test_connection_invalid_find_connections, NULL, idx); - g_assert_cmpint (n_found, ==, 3); + g_assert_cmpint (n_found, ==, 4); ASSERT_IDX (0); ASSERT_IDX (1); ASSERT_IDX (2); + ASSERT_IDX (3); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[0]]); nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[1]]); - nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[2]]); + nmtst_assert_connection_verifies_after_normalization (connections->pdata[idx[2]], 0, 0); + nmtst_assert_connection_verifies_without_normalization (connections->pdata[idx[3]]); g_assert_cmpstr ("test-connection-invalid-1x", ==, nm_connection_get_id (connections->pdata[idx[1]])); - g_assert_cmpstr ("test-connection-invalid-2z", ==, nm_connection_get_id (connections->pdata[idx[2]])); + g_assert_cmpstr ("test-connection-invalid-2z", ==, nm_connection_get_id (connections->pdata[idx[3]])); #undef ASSERT_IDX } diff --git a/po/POTFILES.in b/po/POTFILES.in index 9c37b7ed89..b247e54817 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -140,6 +140,7 @@ libnm/nm-remote-settings.c libnm/nm-vpn-plugin-old.c libnm/nm-vpn-service-plugin.c policy/org.freedesktop.NetworkManager.policy.in.in +shared/nm-shared-utils.c src/NetworkManagerUtils.c src/main.c src/main-utils.c diff --git a/shared/Makefile.am b/shared/Makefile.am index 03fad123fd..c042fdbe80 100644 --- a/shared/Makefile.am +++ b/shared/Makefile.am @@ -4,6 +4,8 @@ EXTRA_DIST = \ nm-default.h \ nm-glib.h \ nm-macros-internal.h \ + nm-shared-utils.c \ + nm-shared-utils.h \ nm-test-libnm-utils.h \ nm-test-utils.h \ nm-test-utils-impl.c \ diff --git a/shared/nm-default.h b/shared/nm-default.h index 365277724d..aae4777a2f 100644 --- a/shared/nm-default.h +++ b/shared/nm-default.h @@ -52,6 +52,7 @@ #include "nm-version.h" #include "gsystem-local-alloc.h" #include "nm-macros-internal.h" +#include "nm-shared-utils.h" /*****************************************************************************/ diff --git a/shared/nm-macros-internal.h b/shared/nm-macros-internal.h index 152cbf67ee..4176231800 100644 --- a/shared/nm-macros-internal.h +++ b/shared/nm-macros-internal.h @@ -36,6 +36,13 @@ #define nm_auto_free nm_auto(_nm_auto_free_impl) GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free) +static inline void +_nm_auto_unset_gvalue_impl (GValue *v) +{ + g_value_unset (v); +} +#define nm_auto_unset_gvalue nm_auto(_nm_auto_unset_gvalue_impl) + /********************************************************/ /* http://stackoverflow.com/a/11172679 */ diff --git a/shared/nm-shared-utils.c b/shared/nm-shared-utils.c new file mode 100644 index 0000000000..0ae54bdcf0 --- /dev/null +++ b/shared/nm-shared-utils.c @@ -0,0 +1,228 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2016 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-shared-utils.h" + +#include <errno.h> + +/*****************************************************************************/ + +/* _nm_utils_ascii_str_to_int64: + * + * A wrapper for g_ascii_strtoll, that checks whether the whole string + * can be successfully converted to a number and is within a given + * range. On any error, @fallback will be returned and %errno will be set + * to a non-zero value. On success, %errno will be set to zero, check %errno + * for errors. Any trailing or leading (ascii) white space is ignored and the + * functions is locale independent. + * + * The function is guaranteed to return a value between @min and @max + * (inclusive) or @fallback. Also, the parsing is rather strict, it does + * not allow for any unrecognized characters, except leading and trailing + * white space. + **/ +gint64 +_nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback) +{ + gint64 v; + size_t len; + char buf[64], *s, *str_free = NULL; + + if (str) { + while (g_ascii_isspace (str[0])) + str++; + } + if (!str || !str[0]) { + errno = EINVAL; + return fallback; + } + + len = strlen (str); + if (g_ascii_isspace (str[--len])) { + /* backward search the first non-ws character. + * We already know that str[0] is non-ws. */ + while (g_ascii_isspace (str[--len])) + ; + + /* str[len] is now the last non-ws character... */ + len++; + + if (len >= sizeof (buf)) + s = str_free = g_malloc (len + 1); + else + s = buf; + + memcpy (s, str, len); + s[len] = 0; + + nm_assert (len > 0 && len < strlen (str) && len == strlen (s)); + nm_assert (!g_ascii_isspace (str[len-1]) && g_ascii_isspace (str[len])); + nm_assert (strncmp (str, s, len) == 0); + + str = s; + } + + errno = 0; + v = g_ascii_strtoll (str, &s, base); + + if (errno != 0) + v = fallback; + else if (s[0] != 0) { + errno = EINVAL; + v = fallback; + } else if (v > max || v < min) { + errno = ERANGE; + v = fallback; + } + + if (G_UNLIKELY (str_free)) + g_free (str_free); + return v; +} + +/*****************************************************************************/ + +G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error) + +void +nm_utils_error_set_cancelled (GError **error, + gboolean is_disposing, + const char *instance_name) +{ + if (is_disposing) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING, + "Disposing %s instance", + instance_name && *instance_name ? instance_name : "source"); + } else { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, + "Request cancelled"); + } +} + +gboolean +nm_utils_error_is_cancelled (GError *error, + gboolean consider_is_disposing) +{ + if (error) { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + return TRUE; + if ( consider_is_disposing + && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) + return TRUE; + } + return FALSE; +} + +/*****************************************************************************/ + +/** + * nm_g_object_set_property: + * @object: the target object + * @property_name: the property name + * @value: the #GValue to set + * @error: (allow-none): optional error argument + * + * A reimplementation of g_object_set_property(), but instead + * returning an error instead of logging a warning. All g_object_set*() + * versions in glib require you to not pass invalid types or they will + * log a g_warning() -- without reporting an error. We don't want that, + * so we need to hack error checking around it. + * + * Returns: whether the value was successfully set. + */ +gboolean +nm_g_object_set_property (GObject *object, + const gchar *property_name, + const GValue *value, + GError **error) +{ + GParamSpec *pspec; + nm_auto_unset_gvalue GValue tmp_value = G_VALUE_INIT; + GObjectClass *klass; + + g_return_val_if_fail (G_IS_OBJECT (object), FALSE); + g_return_val_if_fail (property_name != NULL, FALSE); + g_return_val_if_fail (G_IS_VALUE (value), FALSE); + g_return_val_if_fail (!error || !*error, FALSE); + + /* g_object_class_find_property() does g_param_spec_get_redirect_target(), + * where we differ from a plain g_object_set_property(). */ + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), property_name); + + if (!pspec) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("object class '%s' has no property named '%s'"), + G_OBJECT_TYPE_NAME (object), + property_name); + return FALSE; + } + if (!(pspec->flags & G_PARAM_WRITABLE)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("property '%s' of object class '%s' is not writable"), + pspec->name, + G_OBJECT_TYPE_NAME (object)); + return FALSE; + } + if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("construct property \"%s\" for object '%s' can't be set after construction"), + pspec->name, G_OBJECT_TYPE_NAME (object)); + return FALSE; + } + + klass = g_type_class_peek (pspec->owner_type); + if (klass == NULL) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("'%s::%s' is not a valid property name; '%s' is not a GObject subtype"), + g_type_name (pspec->owner_type), pspec->name, g_type_name (pspec->owner_type)); + return FALSE; + } + + /* provide a copy to work from, convert (if necessary) and validate */ + g_value_init (&tmp_value, pspec->value_type); + if (!g_value_transform (value, &tmp_value)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("unable to set property '%s' of type '%s' from value of type '%s'"), + pspec->name, + g_type_name (pspec->value_type), + G_VALUE_TYPE_NAME (value)); + return FALSE; + } + if ( g_param_value_validate (pspec, &tmp_value) + && !(pspec->flags & G_PARAM_LAX_VALIDATION)) { + gs_free char *contents = g_strdup_value_contents (value); + + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_UNKNOWN, + _("value \"%s\" of type '%s' is invalid or out of range for property '%s' of type '%s'"), + contents, + G_VALUE_TYPE_NAME (value), + pspec->name, + g_type_name (pspec->value_type)); + return FALSE; + } + + g_object_set_property (object, property_name, &tmp_value); + return TRUE; +} + +/*****************************************************************************/ diff --git a/shared/nm-shared-utils.h b/shared/nm-shared-utils.h new file mode 100644 index 0000000000..f80c850c69 --- /dev/null +++ b/shared/nm-shared-utils.h @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* NetworkManager -- Network link manager + * + * 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 + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + * (C) Copyright 2016 Red Hat, Inc. + */ + +#ifndef __NM_SHARED_UTILS_H__ +#define __NM_SHARED_UTILS_H__ + +/******************************************************************************/ + +gint64 _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 max, gint64 fallback); + +/******************************************************************************/ + +/** + * NMUtilsError: + * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error + * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has + * pending aynchronous operations, the operation is cancelled with this + * error reason. Depending on the usage, this might indicate a bug because + * usually the target object should stay alive as long as there are pending + * operations. + */ +typedef enum { + NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/ + NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/ +} NMUtilsError; + +#define NM_UTILS_ERROR (nm_utils_error_quark ()) +GQuark nm_utils_error_quark (void); + +void nm_utils_error_set_cancelled (GError **error, + gboolean is_disposing, + const char *instance_name); +gboolean nm_utils_error_is_cancelled (GError *error, + gboolean consider_is_disposing); + +/******************************************************************************/ + +gboolean nm_g_object_set_property (GObject *object, + const gchar *property_name, + const GValue *value, + GError **error); + +/******************************************************************************/ + +#endif /* __NM_SHARED_UTILS_H__ */ diff --git a/shared/nm-test-utils.h b/shared/nm-test-utils.h index a7d0f93cda..2503245761 100644 --- a/shared/nm-test-utils.h +++ b/shared/nm-test-utils.h @@ -1793,6 +1793,27 @@ nmtst_create_connection_from_keyfile (const char *keyfile_str, const char *keyfi #ifdef __NM_CONNECTION_H__ +inline static GVariant * +_nmtst_variant_new_vardict (int dummy, ...) +{ + GVariantBuilder builder; + va_list ap; + const char *name; + GVariant *variant; + + g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); + + va_start (ap, dummy); + while ((name = va_arg (ap, const char *))) { + variant = va_arg (ap, GVariant *); + g_variant_builder_add (&builder, "{sv}", name, variant); + } + va_end (ap); + + return g_variant_builder_end (&builder); +} +#define nmtst_variant_new_vardict(...) _nmtst_variant_new_vardict (0, __VA_ARGS__, NULL) + #define nmtst_assert_variant_is_of_type(variant, type) \ G_STMT_START { \ GVariant *_variantx = (variant); \ @@ -1863,6 +1884,8 @@ typedef enum { \ if (__cur_setting_name) \ g_variant_builder_add (&__connection_builder, "{sa{sv}}", __cur_setting_name, &__setting_builder); \ + else \ + g_variant_builder_clear (&__setting_builder); \ g_variant_iter_free (__setting_iter); \ } \ \ diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c index de3d8ea693..fba1100640 100644 --- a/src/devices/nm-device.c +++ b/src/devices/nm-device.c @@ -7378,7 +7378,10 @@ impl_device_reapply (NMDevice *self, if (settings && g_variant_n_children (settings)) { /* New settings specified inline. */ - connection = nm_simple_connection_new_from_dbus (settings, &error); + connection = _nm_simple_connection_new_from_dbus (settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (!connection) { g_prefix_error (&error, "The settings specified are invalid: "); nm_audit_log_device_op (NM_AUDIT_OP_DEVICE_REAPPLY, self, FALSE, context, error->message); diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c index 1a6d00f973..b98b6e8abd 100644 --- a/src/nm-core-utils.c +++ b/src/nm-core-utils.c @@ -109,39 +109,6 @@ _nm_utils_set_testing (NMUtilsTestFlags flags) /*****************************************************************************/ -G_DEFINE_QUARK (nm-utils-error-quark, nm_utils_error) - -void -nm_utils_error_set_cancelled (GError **error, - gboolean is_disposing, - const char *instance_name) -{ - if (is_disposing) { - g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING, - "Disposing %s instance", - instance_name && *instance_name ? instance_name : "source"); - } else { - g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_CANCELLED, - "Request cancelled"); - } -} - -gboolean -nm_utils_error_is_cancelled (GError *error, - gboolean consider_is_disposing) -{ - if (error) { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) - return TRUE; - if ( consider_is_disposing - && g_error_matches (error, NM_UTILS_ERROR, NM_UTILS_ERROR_CANCELLED_DISPOSING)) - return TRUE; - } - return FALSE; -} - -/*****************************************************************************/ - static GSList *_singletons = NULL; static gboolean _singletons_shutdown = FALSE; diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h index 2fb5273d74..f77b43e2a3 100644 --- a/src/nm-core-utils.h +++ b/src/nm-core-utils.h @@ -91,31 +91,6 @@ GETTER (void) \ /*****************************************************************************/ -/** - * NMUtilsError: - * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error - * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has - * pending aynchronous operations, the operation is cancelled with this - * error reason. Depending on the usage, this might indicate a bug because - * usually the target object should stay alive as long as there are pending - * operations. - */ -typedef enum { - NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/ - NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/ -} NMUtilsError; - -#define NM_UTILS_ERROR (nm_utils_error_quark ()) -GQuark nm_utils_error_quark (void); - -void nm_utils_error_set_cancelled (GError **error, - gboolean is_disposing, - const char *instance_name); -gboolean nm_utils_error_is_cancelled (GError *error, - gboolean consider_is_disposing); - -/*****************************************************************************/ - gint nm_utils_ascii_str_to_bool (const char *str, gint default_value); diff --git a/src/nm-manager.c b/src/nm-manager.c index 27241c26f0..5b618af0c2 100644 --- a/src/nm-manager.c +++ b/src/nm-manager.c @@ -3612,7 +3612,7 @@ impl_manager_add_and_activate_connection (NMManager *self, */ connection = nm_simple_connection_new (); if (settings && g_variant_n_children (settings)) - nm_connection_replace_settings (connection, settings, NULL); + _nm_connection_replace_settings (connection, settings, NM_SETTING_PARSE_FLAGS_STRICT, NULL); subject = validate_activation_request (self, context, diff --git a/src/nm-policy.c b/src/nm-policy.c index ef0e7d975f..545a68728a 100644 --- a/src/nm-policy.c +++ b/src/nm-policy.c @@ -60,7 +60,6 @@ typedef struct { NMManager *manager; NMDefaultRouteManager *default_route_manager; NMFirewallManager *firewall_manager; - guint update_state_id; GSList *pending_activation_checks; GSList *manager_ids; GSList *settings_ids; @@ -92,16 +91,17 @@ typedef struct { G_DEFINE_TYPE (NMPolicy, nm_policy, G_TYPE_OBJECT) -enum { - PROP_0, - +NM_GOBJECT_PROPERTIES_DEFINE (NMPolicy, + PROP_MANAGER, + PROP_SETTINGS, + PROP_DEFAULT_ROUTE_MANAGER, PROP_DEFAULT_IP4_DEVICE, PROP_DEFAULT_IP6_DEVICE, PROP_ACTIVATING_IP4_DEVICE, - PROP_ACTIVATING_IP6_DEVICE -}; + PROP_ACTIVATING_IP6_DEVICE, +); -static void schedule_activate_all (NMPolicy *policy); +static void schedule_activate_all (NMPolicy *self); static NMDevice * @@ -128,9 +128,10 @@ get_best_ip6_device (NMPolicy *self, gboolean fully_activated) #define FALLBACK_HOSTNAME4 "localhost.localdomain" -static void settings_set_hostname_cb (const char *hostname, - gboolean result, - gpointer user_data) +static void +settings_set_hostname_cb (const char *hostname, + gboolean result, + gpointer user_data) { int ret = 0; @@ -151,11 +152,11 @@ static void settings_set_hostname_cb (const char *hostname, } static void -_set_hostname (NMPolicy *policy, +_set_hostname (NMPolicy *self, const char *new_hostname, const char *msg) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); char old_hostname[HOST_NAME_MAX + 1]; const char *name; int ret; @@ -232,8 +233,8 @@ lookup_callback (GObject *source, GAsyncResult *result, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *hostname; GError *error = NULL; @@ -245,9 +246,9 @@ lookup_callback (GObject *source, } if (hostname) - _set_hostname (policy, hostname, "from address lookup"); + _set_hostname (self, hostname, "from address lookup"); else { - _set_hostname (policy, NULL, error->message); + _set_hostname (self, NULL, error->message); g_error_free (error); } @@ -255,15 +256,15 @@ lookup_callback (GObject *source, } static void -update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) +update_system_hostname (NMPolicy *self, NMDevice *best4, NMDevice *best6) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); char *configured_hostname = NULL; const char *dhcp_hostname, *p; NMIP4Config *ip4_config; NMIP6Config *ip6_config; - g_return_if_fail (policy != NULL); + g_return_if_fail (self != NULL); if (priv->lookup_cancellable) { g_cancellable_cancel (priv->lookup_cancellable); @@ -282,7 +283,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try a persistent hostname first */ g_object_get (G_OBJECT (priv->manager), NM_MANAGER_HOSTNAME, &configured_hostname, NULL); if (configured_hostname && nm_utils_is_specific_hostname (configured_hostname)) { - _set_hostname (policy, configured_hostname, "from system configuration"); + _set_hostname (self, configured_hostname, "from system configuration"); g_free (configured_hostname); return; } @@ -290,15 +291,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Try automatically determined hostname from the best device's IP config */ if (!best4) - best4 = get_best_ip4_device (policy, TRUE); + best4 = get_best_ip4_device (self, TRUE); if (!best6) - best6 = get_best_ip6_device (policy, TRUE); + best6 = get_best_ip6_device (self, TRUE); if (!best4 && !best6) { /* No best device; fall back to original hostname or if there wasn't * one, 'localhost.localdomain' */ - _set_hostname (policy, priv->orig_hostname, "no default device"); + _set_hostname (self, priv->orig_hostname, "no default device"); return; } @@ -313,7 +314,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Sanity check; strip leading spaces */ while (*p) { if (!g_ascii_isspace (*p++)) { - _set_hostname (policy, p-1, "from DHCPv4"); + _set_hostname (self, p-1, "from DHCPv4"); return; } } @@ -332,7 +333,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) /* Sanity check; strip leading spaces */ while (*p) { if (!g_ascii_isspace (*p++)) { - _set_hostname (policy, p-1, "from DHCPv6"); + _set_hostname (self, p-1, "from DHCPv6"); return; } } @@ -346,7 +347,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) * when NM started up. */ if (priv->orig_hostname) { - _set_hostname (policy, priv->orig_hostname, "from system startup"); + _set_hostname (self, priv->orig_hostname, "from system startup"); return; } @@ -372,7 +373,7 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) G_SOCKET_FAMILY_IPV6); } else { /* No valid IP config; fall back to localhost.localdomain */ - _set_hostname (policy, NULL, "no IP config"); + _set_hostname (self, NULL, "no IP config"); return; } @@ -380,15 +381,15 @@ update_system_hostname (NMPolicy *policy, NMDevice *best4, NMDevice *best6) g_resolver_lookup_by_address_async (priv->resolver, priv->lookup_addr, priv->lookup_cancellable, - lookup_callback, policy); + lookup_callback, self); } static void -update_default_ac (NMPolicy *policy, +update_default_ac (NMPolicy *self, NMActiveConnection *best, void (*set_active_func)(NMActiveConnection*, gboolean)) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *connections, *iter; /* Clear the 'default[6]' flag on all active connections that aren't the new @@ -425,14 +426,14 @@ get_best_ip4_config (NMPolicy *self, } static void -update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +update_ip4_dns (NMPolicy *self, NMDnsManager *dns_mgr) { NMIP4Config *ip4_config; const char *ip_iface = NULL; NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip4_config = get_best_ip4_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); + ip4_config = get_best_ip4_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip4_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -445,9 +446,9 @@ update_ip4_dns (NMPolicy *policy, NMDnsManager *dns_mgr) } static void -update_ip4_routing (NMPolicy *policy, gboolean force_update) +update_ip4_routing (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMDevice *best = NULL, *default_device; NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; @@ -457,13 +458,13 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) /* Note that we might have an IPv4 VPN tunneled over an IPv6-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip4_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { + if (!get_best_ip4_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device4 != NULL); priv->default_device4 = NULL; if (changed) - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); + _notify (self, PROP_DEFAULT_IP4_DEVICE); return; } @@ -491,7 +492,7 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) else default_device = best; - update_default_ac (policy, best_ac, nm_active_connection_set_default); + update_default_ac (self, best_ac, nm_active_connection_set_default); if (default_device == priv->default_device4) return; @@ -500,7 +501,7 @@ update_ip4_routing (NMPolicy *policy, gboolean force_update) connection = nm_active_connection_get_applied_connection (best_ac); _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv4 routing and DNS", nm_connection_get_id (connection), ip_iface); - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP4_DEVICE); + _notify (self, PROP_DEFAULT_IP4_DEVICE); } static NMIP6Config * @@ -522,14 +523,14 @@ get_best_ip6_config (NMPolicy *self, } static void -update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) +update_ip6_dns (NMPolicy *self, NMDnsManager *dns_mgr) { NMIP6Config *ip6_config; const char *ip_iface = NULL; NMVpnConnection *vpn = NULL; NMDnsIPConfigType dns_type = NM_DNS_IP_CONFIG_TYPE_BEST_DEVICE; - ip6_config = get_best_ip6_config (policy, TRUE, &ip_iface, NULL, NULL, &vpn); + ip6_config = get_best_ip6_config (self, TRUE, &ip_iface, NULL, NULL, &vpn); if (ip6_config) { if (vpn) dns_type = NM_DNS_IP_CONFIG_TYPE_VPN; @@ -542,9 +543,9 @@ update_ip6_dns (NMPolicy *policy, NMDnsManager *dns_mgr) } static void -update_ip6_routing (NMPolicy *policy, gboolean force_update) +update_ip6_routing (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMDevice *best = NULL, *default_device6; NMConnection *connection = NULL; NMVpnConnection *vpn = NULL; @@ -554,13 +555,13 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) /* Note that we might have an IPv6 VPN tunneled over an IPv4-only device, * so we can get (vpn != NULL && best == NULL). */ - if (!get_best_ip6_config (policy, FALSE, &ip_iface, &best_ac, &best, &vpn)) { + if (!get_best_ip6_config (self, FALSE, &ip_iface, &best_ac, &best, &vpn)) { gboolean changed; changed = (priv->default_device6 != NULL); priv->default_device6 = NULL; if (changed) - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); + _notify (self, PROP_DEFAULT_IP6_DEVICE); return; } @@ -588,7 +589,7 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) else default_device6 = best; - update_default_ac (policy, best_ac, nm_active_connection_set_default6); + update_default_ac (self, best_ac, nm_active_connection_set_default6); if (default_device6 == priv->default_device6) return; @@ -597,47 +598,47 @@ update_ip6_routing (NMPolicy *policy, gboolean force_update) connection = nm_active_connection_get_applied_connection (best_ac); _LOGI (LOGD_CORE, "set '%s' (%s) as default for IPv6 routing and DNS", nm_connection_get_id (connection), ip_iface); - g_object_notify (G_OBJECT (policy), NM_POLICY_DEFAULT_IP6_DEVICE); + _notify (self, PROP_DEFAULT_IP6_DEVICE); } static void -update_routing_and_dns (NMPolicy *policy, gboolean force_update) +update_routing_and_dns (NMPolicy *self, gboolean force_update) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); nm_dns_manager_begin_updates (priv->dns_manager, __func__); - update_ip4_dns (policy, priv->dns_manager); - update_ip6_dns (policy, priv->dns_manager); + update_ip4_dns (self, priv->dns_manager); + update_ip6_dns (self, priv->dns_manager); - update_ip4_routing (policy, force_update); - update_ip6_routing (policy, force_update); + update_ip4_routing (self, force_update); + update_ip6_routing (self, force_update); /* Update the system hostname */ - update_system_hostname (policy, priv->default_device4, priv->default_device6); + update_system_hostname (self, priv->default_device4, priv->default_device6); nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void -check_activating_devices (NMPolicy *policy) +check_activating_devices (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); - GObject *object = G_OBJECT (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + GObject *object = G_OBJECT (self); NMDevice *best4, *best6 = NULL; - best4 = get_best_ip4_device (policy, FALSE); - best6 = get_best_ip6_device (policy, FALSE); + best4 = get_best_ip4_device (self, FALSE); + best6 = get_best_ip6_device (self, FALSE); g_object_freeze_notify (object); if (best4 != priv->activating_device4) { priv->activating_device4 = best4; - g_object_notify (object, NM_POLICY_ACTIVATING_IP4_DEVICE); + _notify (self, PROP_ACTIVATING_IP4_DEVICE); } if (best6 != priv->activating_device6) { priv->activating_device6 = best6; - g_object_notify (object, NM_POLICY_ACTIVATING_IP6_DEVICE); + _notify (self, PROP_ACTIVATING_IP6_DEVICE); } g_object_thaw_notify (object); @@ -660,14 +661,15 @@ activate_data_free (ActivateData *data) if (data->autoactivate_id) g_source_remove (data->autoactivate_id); g_object_unref (data->device); - g_free (data); + + g_slice_free (ActivateData, data); } static gboolean auto_activate_device (gpointer user_data) { ActivateData *data = (ActivateData *) user_data; - NMPolicy *policy; + NMPolicy *self; NMPolicyPrivate *priv; NMSettingsConnection *best_connection; char *specific_object = NULL; @@ -676,8 +678,8 @@ auto_activate_device (gpointer user_data) guint i; g_assert (data); - policy = data->policy; - priv = NM_POLICY_GET_PRIVATE (policy); + self = data->policy; + priv = NM_POLICY_GET_PRIVATE (self); data->autoactivate_id = 0; @@ -764,7 +766,7 @@ pending_secondary_data_new (NMDevice *device, GSList *secondaries) { PendingSecondaryData *data; - data = g_malloc0 (sizeof (PendingSecondaryData)); + data = g_slice_new (PendingSecondaryData); data->device = g_object_ref (device); data->secondaries = secondaries; return data; @@ -775,16 +777,15 @@ pending_secondary_data_free (PendingSecondaryData *data) { g_object_unref (data->device); g_slist_free_full (data->secondaries, g_object_unref); - memset (data, 0, sizeof (*data)); - g_free (data); + g_slice_free (PendingSecondaryData, data); } static void -process_secondaries (NMPolicy *policy, +process_secondaries (NMPolicy *self, NMActiveConnection *active, gboolean connected) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *iter, *iter2, *next, *next2; /* Loop through devices waiting for secondary connections to activate */ @@ -849,9 +850,9 @@ hostname_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) } static void -reset_autoconnect_all (NMPolicy *policy, NMDevice *device) +reset_autoconnect_all (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; if (device) { @@ -871,9 +872,9 @@ reset_autoconnect_all (NMPolicy *policy, NMDevice *device) } static void -reset_autoconnect_for_failed_secrets (NMPolicy *policy) +reset_autoconnect_for_failed_secrets (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; _LOGD (LOGD_DEVICE, "re-enabling autoconnect for all connections with failed secrets"); @@ -891,9 +892,9 @@ reset_autoconnect_for_failed_secrets (NMPolicy *policy) } static void -block_autoconnect_for_device (NMPolicy *policy, NMDevice *device) +block_autoconnect_for_device (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; _LOGD (LOGD_DEVICE, "blocking autoconnect for all connections on %s", @@ -918,7 +919,7 @@ block_autoconnect_for_device (NMPolicy *policy, NMDevice *device) static void sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) { - NMPolicy *policy = user_data; + NMPolicy *self = user_data; gboolean sleeping = FALSE, enabled = FALSE; g_object_get (G_OBJECT (manager), NM_MANAGER_SLEEPING, &sleeping, NULL); @@ -926,13 +927,13 @@ sleeping_changed (NMManager *manager, GParamSpec *pspec, gpointer user_data) /* Reset retries on all connections so they'll checked on wakeup */ if (sleeping || !enabled) - reset_autoconnect_all (policy, NULL); + reset_autoconnect_all (self, NULL); } static void -schedule_activate_check (NMPolicy *policy, NMDevice *device) +schedule_activate_check (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); ActivateData *data; const GSList *active_connections, *iter; @@ -956,17 +957,17 @@ schedule_activate_check (NMPolicy *policy, NMDevice *device) nm_device_add_pending_action (device, "autoactivate", TRUE); - data = g_malloc0 (sizeof (ActivateData)); - data->policy = policy; + data = g_slice_new0 (ActivateData); + data->policy = self; data->device = g_object_ref (device); data->autoactivate_id = g_idle_add (auto_activate_device, data); priv->pending_activation_checks = g_slist_append (priv->pending_activation_checks, data); } static void -clear_pending_activate_check (NMPolicy *policy, NMDevice *device) +clear_pending_activate_check (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); ActivateData *data; data = find_pending_activation (priv->pending_activation_checks, device); @@ -977,8 +978,8 @@ clear_pending_activate_check (NMPolicy *policy, NMDevice *device) static gboolean reset_connections_retries (gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *connections, *iter; gint32 con_stamp, min_stamp, now; gboolean changed = FALSE; @@ -1005,21 +1006,21 @@ reset_connections_retries (gpointer user_data) /* Schedule the handler again if there are some stamps left */ if (min_stamp != 0) - priv->reset_retries_id = g_timeout_add_seconds (min_stamp - now, reset_connections_retries, policy); + priv->reset_retries_id = g_timeout_add_seconds (min_stamp - now, reset_connections_retries, self); /* If anything changed, try to activate the newly re-enabled connections */ if (changed) - schedule_activate_all (policy); + schedule_activate_all (self); return FALSE; } -static void schedule_activate_all (NMPolicy *policy); +static void schedule_activate_all (NMPolicy *self); static void -activate_slave_connections (NMPolicy *policy, NMDevice *device) +activate_slave_connections (NMPolicy *self, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *master_device, *master_uuid_settings = NULL, *master_uuid_applied = NULL; GSList *connections, *iter; NMActRequest *req; @@ -1065,15 +1066,15 @@ activate_slave_connections (NMPolicy *policy, NMDevice *device) g_slist_free (connections); - schedule_activate_all (policy); + schedule_activate_all (self); } static gboolean -activate_secondary_connections (NMPolicy *policy, +activate_secondary_connections (NMPolicy *self, NMConnection *connection, NMDevice *device) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMSettingConnection *s_con; NMSettingsConnection *settings_con; NMActiveConnection *ac; @@ -1145,8 +1146,8 @@ device_state_changed (NMDevice *device, NMDeviceStateReason reason, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMSettingsConnection *connection = nm_device_get_settings_connection (device); @@ -1184,7 +1185,7 @@ device_state_changed (NMDevice *device, gint32 retry_time = nm_settings_connection_get_autoconnect_retry_time (connection); g_warn_if_fail (retry_time != 0); - priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, policy); + priv->reset_retries_id = g_timeout_add_seconds (MAX (0, retry_time - nm_utils_get_monotonic_timestamp_s ()), reset_connections_retries, self); } } nm_connection_clear_secrets (NM_CONNECTION (connection)); @@ -1213,20 +1214,20 @@ device_state_changed (NMDevice *device, if (ip6_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); nm_dns_manager_end_updates (priv->dns_manager, __func__); break; case NM_DEVICE_STATE_UNMANAGED: case NM_DEVICE_STATE_UNAVAILABLE: if (old_state > NM_DEVICE_STATE_DISCONNECTED) - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); break; case NM_DEVICE_STATE_DEACTIVATING: if (reason == NM_DEVICE_STATE_REASON_USER_REQUESTED) { if (!nm_device_get_autoconnect (device)) { /* The device was disconnected; block all connections on it */ - block_autoconnect_for_device (policy, device); + block_autoconnect_for_device (self, device); } else { if (connection) { /* The connection was deactivated, so block just this connection */ @@ -1243,19 +1244,19 @@ device_state_changed (NMDevice *device, * was unplugged and plugged in again, we should try to reconnect. */ if (reason == NM_DEVICE_STATE_REASON_CARRIER && old_state == NM_DEVICE_STATE_UNAVAILABLE) - reset_autoconnect_all (policy, device); + reset_autoconnect_all (self, device); if (old_state > NM_DEVICE_STATE_DISCONNECTED) - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); /* Device is now available for auto-activation */ - schedule_activate_check (policy, device); + schedule_activate_check (self, device); break; case NM_DEVICE_STATE_PREPARE: /* Reset auto-connect retries of all slaves and schedule them for * activation. */ - activate_slave_connections (policy, device); + activate_slave_connections (self, device); break; case NM_DEVICE_STATE_IP_CONFIG: /* We must have secrets if we got here. */ @@ -1267,10 +1268,10 @@ device_state_changed (NMDevice *device, s_con = nm_connection_get_setting_connection (NM_CONNECTION (connection)); if (s_con && nm_setting_connection_get_num_secondaries (s_con) > 0) { /* Make routes and DNS up-to-date before activating dependent connections */ - update_routing_and_dns (policy, FALSE); + update_routing_and_dns (self, FALSE); /* Activate secondary (VPN) connections */ - if (!activate_secondary_connections (policy, NM_CONNECTION (connection), device)) + if (!activate_secondary_connections (self, NM_CONNECTION (connection), device)) nm_device_queue_state (device, NM_DEVICE_STATE_FAILED, NM_DEVICE_STATE_REASON_SECONDARY_CONNECTION_FAILED); } else @@ -1282,7 +1283,7 @@ device_state_changed (NMDevice *device, break; } - check_activating_devices (policy); + check_activating_devices (self); } static void @@ -1291,8 +1292,8 @@ device_ip4_config_changed (NMDevice *device, NMIP4Config *old_config, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *ip_iface = nm_device_get_ip_iface (device); nm_dns_manager_begin_updates (priv->dns_manager, __func__); @@ -1308,8 +1309,8 @@ device_ip4_config_changed (NMDevice *device, if (new_config) nm_dns_manager_add_ip4_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); } - update_ip4_dns (policy, priv->dns_manager); - update_ip4_routing (policy, TRUE); + update_ip4_dns (self, priv->dns_manager); + update_ip4_routing (self, TRUE); } else { /* Old configs get removed immediately */ if (old_config) @@ -1325,8 +1326,8 @@ device_ip6_config_changed (NMDevice *device, NMIP6Config *old_config, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const char *ip_iface = nm_device_get_ip_iface (device); nm_dns_manager_begin_updates (priv->dns_manager, __func__); @@ -1342,8 +1343,8 @@ device_ip6_config_changed (NMDevice *device, if (new_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, new_config, NM_DNS_IP_CONFIG_TYPE_DEFAULT); } - update_ip6_dns (policy, priv->dns_manager); - update_ip6_routing (policy, TRUE); + update_ip6_dns (self, priv->dns_manager); + update_ip6_routing (self, TRUE); } else { /* Old configs get removed immediately */ if (old_config) @@ -1374,21 +1375,21 @@ typedef struct { } DeviceSignalId; static void -_connect_device_signal (NMPolicy *policy, +_connect_device_signal (NMPolicy *self, NMDevice *device, const char *name, gpointer callback, gboolean after) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); DeviceSignalId *data; data = g_slice_new0 (DeviceSignalId); g_assert (data); if (after) - data->id = g_signal_connect_after (device, name, callback, policy); + data->id = g_signal_connect_after (device, name, callback, self); else - data->id = g_signal_connect (device, name, callback, policy); + data->id = g_signal_connect (device, name, callback, self); data->device = device; priv->dev_ids = g_slist_prepend (priv->dev_ids, data); } @@ -1396,25 +1397,25 @@ _connect_device_signal (NMPolicy *policy, static void device_added (NMManager *manager, NMDevice *device, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; + NMPolicy *self = (NMPolicy *) user_data; /* Connect state-changed with _after, so that the handler is invoked after other handlers. */ - _connect_device_signal (policy, device, NM_DEVICE_STATE_CHANGED, device_state_changed, TRUE); - _connect_device_signal (policy, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed, FALSE); - _connect_device_signal (policy, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed, FALSE); - _connect_device_signal (policy, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed, FALSE); - _connect_device_signal (policy, device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, device_recheck_auto_activate, FALSE); + _connect_device_signal (self, device, NM_DEVICE_STATE_CHANGED, device_state_changed, TRUE); + _connect_device_signal (self, device, NM_DEVICE_IP4_CONFIG_CHANGED, device_ip4_config_changed, FALSE); + _connect_device_signal (self, device, NM_DEVICE_IP6_CONFIG_CHANGED, device_ip6_config_changed, FALSE); + _connect_device_signal (self, device, "notify::" NM_DEVICE_AUTOCONNECT, device_autoconnect_changed, FALSE); + _connect_device_signal (self, device, NM_DEVICE_RECHECK_AUTO_ACTIVATE, device_recheck_auto_activate, FALSE); } static void device_removed (NMManager *manager, NMDevice *device, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); GSList *iter; /* Clear any idle callbacks for this device */ - clear_pending_activate_check (policy, device); + clear_pending_activate_check (self, device); /* Clear any signal handlers for this device */ iter = priv->dev_ids; @@ -1438,9 +1439,9 @@ device_removed (NMManager *manager, NMDevice *device, gpointer user_data) /**************************************************************************/ static void -vpn_connection_activated (NMPolicy *policy, NMVpnConnection *vpn) +vpn_connection_activated (NMPolicy *self, NMVpnConnection *vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMIP4Config *ip4_config; NMIP6Config *ip6_config; const char *ip_iface; @@ -1459,15 +1460,15 @@ vpn_connection_activated (NMPolicy *policy, NMVpnConnection *vpn) if (ip6_config) nm_dns_manager_add_ip6_config (priv->dns_manager, ip_iface, ip6_config, NM_DNS_IP_CONFIG_TYPE_VPN); - update_routing_and_dns (policy, TRUE); + update_routing_and_dns (self, TRUE); nm_dns_manager_end_updates (priv->dns_manager, __func__); } static void -vpn_connection_deactivated (NMPolicy *policy, NMVpnConnection *vpn) +vpn_connection_deactivated (NMPolicy *self, NMVpnConnection *vpn) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMIP4Config *ip4_config; NMIP6Config *ip6_config; @@ -1485,7 +1486,7 @@ vpn_connection_deactivated (NMPolicy *policy, NMVpnConnection *vpn) nm_dns_manager_remove_ip6_config (priv->dns_manager, ip6_config); } - update_routing_and_dns (policy, TRUE); + update_routing_and_dns (self, TRUE); nm_dns_manager_end_updates (priv->dns_manager, __func__); } @@ -1495,22 +1496,22 @@ vpn_connection_state_changed (NMVpnConnection *vpn, NMVpnConnectionState new_state, NMVpnConnectionState old_state, NMVpnConnectionStateReason reason, - NMPolicy *policy) + NMPolicy *self) { if (new_state == NM_VPN_CONNECTION_STATE_ACTIVATED) - vpn_connection_activated (policy, vpn); + vpn_connection_activated (self, vpn); else if (new_state >= NM_VPN_CONNECTION_STATE_FAILED) { /* Only clean up IP/DNS if the connection ever got past IP_CONFIG */ if (old_state >= NM_VPN_CONNECTION_STATE_IP_CONFIG_GET && old_state <= NM_VPN_CONNECTION_STATE_ACTIVATED) - vpn_connection_deactivated (policy, vpn); + vpn_connection_deactivated (self, vpn); } } static void -vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy) +vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); NMActiveConnection *ac = NM_ACTIVE_CONNECTION (vpn); NMSettingsConnection *connection = nm_active_connection_get_settings_connection (ac); GError *error = NULL; @@ -1532,14 +1533,14 @@ vpn_connection_retry_after_failure (NMVpnConnection *vpn, NMPolicy *policy) static void active_connection_state_changed (NMActiveConnection *active, GParamSpec *pspec, - NMPolicy *policy) + NMPolicy *self) { NMActiveConnectionState state = nm_active_connection_get_state (active); if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - process_secondaries (policy, active, TRUE); + process_secondaries (self, active, TRUE); else if (state == NM_ACTIVE_CONNECTION_STATE_DEACTIVATED) - process_secondaries (policy, active, FALSE); + process_secondaries (self, active, FALSE); } static void @@ -1547,20 +1548,20 @@ active_connection_added (NMManager *manager, NMActiveConnection *active, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); if (NM_IS_VPN_CONNECTION (active)) { g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_STATE_CHANGED, G_CALLBACK (vpn_connection_state_changed), - policy); + self); g_signal_connect (active, NM_VPN_CONNECTION_INTERNAL_RETRY_AFTER_FAILURE, G_CALLBACK (vpn_connection_retry_after_failure), - policy); + self); } g_signal_connect (active, "notify::" NM_ACTIVE_CONNECTION_STATE, G_CALLBACK (active_connection_state_changed), - policy); + self); } static void @@ -1568,29 +1569,29 @@ active_connection_removed (NMManager *manager, NMActiveConnection *active, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); g_signal_handlers_disconnect_by_func (active, vpn_connection_state_changed, - policy); + self); g_signal_handlers_disconnect_by_func (active, vpn_connection_retry_after_failure, - policy); + self); g_signal_handlers_disconnect_by_func (active, active_connection_state_changed, - policy); + self); } /**************************************************************************/ static void -schedule_activate_all (NMPolicy *policy) +schedule_activate_all (NMPolicy *self) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; for (iter = nm_manager_get_devices (priv->manager); iter; iter = g_slist_next (iter)) - schedule_activate_check (policy, NM_DEVICE (iter->data)); + schedule_activate_check (self, NM_DEVICE (iter->data)); } static void @@ -1598,17 +1599,17 @@ connection_added (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); - schedule_activate_all (policy); + schedule_activate_all (self); } static void firewall_started (NMFirewallManager *manager, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; /* add interface of each device to correct zone */ @@ -1619,8 +1620,8 @@ firewall_started (NMFirewallManager *manager, static void dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); /* Restart a thread for reverse-DNS lookup after we are signalled that * DNS changed. Because the result from a previous run may not be right @@ -1645,7 +1646,7 @@ dns_config_changed (NMDnsManager *dns_manager, gpointer user_data) g_resolver_lookup_by_address_async (priv->resolver, priv->lookup_addr, priv->lookup_cancellable, - lookup_callback, policy); + lookup_callback, self); } } @@ -1662,8 +1663,8 @@ connection_updated_by_user (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = (NMPolicy *) user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = (NMPolicy *) user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *iter; NMDevice *device = NULL; @@ -1716,8 +1717,8 @@ connection_removed (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); _deactivate_if_active (priv->manager, connection); } @@ -1727,11 +1728,11 @@ connection_visibility_changed (NMSettings *settings, NMSettingsConnection *connection, gpointer user_data) { - NMPolicy *policy = user_data; - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = user_data; + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); if (nm_settings_connection_is_visible (connection)) - schedule_activate_all (policy); + schedule_activate_all (self); else _deactivate_if_active (priv->manager, connection); } @@ -1741,55 +1742,130 @@ secret_agent_registered (NMSettings *settings, NMSecretAgent *agent, gpointer user_data) { - NMPolicy *policy = NM_POLICY (user_data); + NMPolicy *self = NM_POLICY (user_data); /* The registered secret agent may provide some missing secrets. Thus we * reset retries count here and schedule activation, so that the * connections failed due to missing secrets may re-try auto-connection. */ - reset_autoconnect_for_failed_secrets (policy); - schedule_activate_all (policy); + reset_autoconnect_for_failed_secrets (self); + schedule_activate_all (self); +} + +NMDevice * +nm_policy_get_default_ip4_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->default_device4; +} + +NMDevice * +nm_policy_get_default_ip6_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->default_device6; +} + +NMDevice * +nm_policy_get_activating_ip4_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->activating_device4; } +NMDevice * +nm_policy_get_activating_ip6_device (NMPolicy *self) +{ + return NM_POLICY_GET_PRIVATE (self)->activating_device6; +} + +/*****************************************************************************/ + static void -_connect_manager_signal (NMPolicy *policy, const char *name, gpointer callback) +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_DEFAULT_IP4_DEVICE: + g_value_set_object (value, priv->default_device4); + break; + case PROP_DEFAULT_IP6_DEVICE: + g_value_set_object (value, priv->default_device6); + break; + case PROP_ACTIVATING_IP4_DEVICE: + g_value_set_object (value, priv->activating_device4); + break; + case PROP_ACTIVATING_IP6_DEVICE: + g_value_set_object (value, priv->activating_device6); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + + switch (prop_id) { + case PROP_MANAGER: + /* construct-only */ + priv->manager = g_value_get_object (value); + g_return_if_fail (NM_IS_MANAGER (priv->manager)); + break; + case PROP_SETTINGS: + /* construct-only */ + priv->settings = g_value_dup_object (value); + g_return_if_fail (NM_IS_SETTINGS (priv->settings)); + break; + case PROP_DEFAULT_ROUTE_MANAGER: + /* construct-only */ + priv->default_route_manager = g_value_dup_object (value); + g_return_if_fail (NM_IS_SETTINGS (priv->default_route_manager)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/*****************************************************************************/ + +static void +_connect_manager_signal (NMPolicy *self, const char *name, gpointer callback) +{ + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); gulong id; - id = g_signal_connect (priv->manager, name, callback, policy); + id = g_signal_connect (priv->manager, name, callback, self); priv->manager_ids = g_slist_prepend (priv->manager_ids, (gpointer) id); } static void -_connect_settings_signal (NMPolicy *policy, const char *name, gpointer callback) +_connect_settings_signal (NMPolicy *self, const char *name, gpointer callback) { - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); gulong id; - id = g_signal_connect (priv->settings, name, callback, policy); + id = g_signal_connect (priv->settings, name, callback, self); priv->settings_ids = g_slist_prepend (priv->settings_ids, (gpointer) id); } -NMPolicy * -nm_policy_new (NMManager *manager, - NMSettings *settings, - NMDefaultRouteManager *default_route_manager) +static void +nm_policy_init (NMPolicy *self) { - NMPolicy *policy; - NMPolicyPrivate *priv; - static gboolean initialized = FALSE; - char hostname[HOST_NAME_MAX + 2]; - - g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); - g_return_val_if_fail (initialized == FALSE, NULL); +} - policy = g_object_new (NM_TYPE_POLICY, NULL); - priv = NM_POLICY_GET_PRIVATE (policy); - priv->manager = manager; - priv->default_route_manager = g_object_ref (default_route_manager); - priv->settings = g_object_ref (settings); - priv->update_state_id = 0; +static void +constructed (GObject *object) +{ + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); + char hostname[HOST_NAME_MAX + 2]; /* Grab hostname on startup and use that if nothing provides one */ memset (hostname, 0, sizeof (hostname)); @@ -1802,103 +1878,60 @@ nm_policy_new (NMManager *manager, priv->firewall_manager = g_object_ref (nm_firewall_manager_get ()); priv->fw_started_id = g_signal_connect (priv->firewall_manager, "started", - G_CALLBACK (firewall_started), policy); + G_CALLBACK (firewall_started), self); priv->dns_manager = g_object_ref (nm_dns_manager_get ()); nm_dns_manager_set_initial_hostname (priv->dns_manager, priv->orig_hostname); priv->config_changed_id = g_signal_connect (priv->dns_manager, "config-changed", - G_CALLBACK (dns_config_changed), policy); + G_CALLBACK (dns_config_changed), self); priv->resolver = g_resolver_get_default (); - _connect_manager_signal (policy, NM_MANAGER_STATE_CHANGED, global_state_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_HOSTNAME, hostname_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_SLEEPING, sleeping_changed); - _connect_manager_signal (policy, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed); - _connect_manager_signal (policy, "internal-device-added", device_added); - _connect_manager_signal (policy, "internal-device-removed", device_removed); - _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added); - _connect_manager_signal (policy, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed); - - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, connection_updated_by_user); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, + _connect_manager_signal (self, NM_MANAGER_STATE_CHANGED, global_state_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_HOSTNAME, hostname_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_SLEEPING, sleeping_changed); + _connect_manager_signal (self, "notify::" NM_MANAGER_NETWORKING_ENABLED, sleeping_changed); + _connect_manager_signal (self, "internal-device-added", device_added); + _connect_manager_signal (self, "internal-device-removed", device_removed); + _connect_manager_signal (self, NM_MANAGER_ACTIVE_CONNECTION_ADDED, active_connection_added); + _connect_manager_signal (self, NM_MANAGER_ACTIVE_CONNECTION_REMOVED, active_connection_removed); + + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_ADDED, connection_added); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED, connection_updated); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_UPDATED_BY_USER, connection_updated_by_user); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED, connection_removed); + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_CONNECTION_VISIBILITY_CHANGED, connection_visibility_changed); - _connect_settings_signal (policy, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); - - initialized = TRUE; - return policy; -} + _connect_settings_signal (self, NM_SETTINGS_SIGNAL_AGENT_REGISTERED, secret_agent_registered); -NMDevice * -nm_policy_get_default_ip4_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->default_device4; -} - -NMDevice * -nm_policy_get_default_ip6_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->default_device6; -} - -NMDevice * -nm_policy_get_activating_ip4_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->activating_device4; + G_OBJECT_CLASS (nm_policy_parent_class)->constructed (object); } -NMDevice * -nm_policy_get_activating_ip6_device (NMPolicy *policy) -{ - return NM_POLICY_GET_PRIVATE (policy)->activating_device6; -} - -static void -nm_policy_init (NMPolicy *policy) -{ -} - -static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +NMPolicy * +nm_policy_new (NMManager *manager, + NMSettings *settings, + NMDefaultRouteManager *default_route_manager) { - NMPolicy *policy = NM_POLICY (object); - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + g_return_val_if_fail (NM_IS_MANAGER (manager), NULL); + g_return_val_if_fail (NM_IS_SETTINGS (settings), NULL); + g_return_val_if_fail (NM_IS_DEFAULT_ROUTE_MANAGER (default_route_manager), NULL); - switch (prop_id) { - case PROP_DEFAULT_IP4_DEVICE: - g_value_set_object (value, priv->default_device4); - break; - case PROP_DEFAULT_IP6_DEVICE: - g_value_set_object (value, priv->default_device6); - break; - case PROP_ACTIVATING_IP4_DEVICE: - g_value_set_object (value, priv->activating_device4); - break; - case PROP_ACTIVATING_IP6_DEVICE: - g_value_set_object (value, priv->activating_device6); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + return g_object_new (NM_TYPE_POLICY, + NM_POLICY_MANAGER, manager, + NM_POLICY_SETTINGS, settings, + NM_POLICY_DEFAULT_ROUTE_MANAGER, default_route_manager, + NULL); } static void dispose (GObject *object) { - NMPolicy *policy = NM_POLICY (object); - NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (policy); + NMPolicy *self = NM_POLICY (object); + NMPolicyPrivate *priv = NM_POLICY_GET_PRIVATE (self); const GSList *connections, *iter; - /* Tell any existing hostname lookup thread to die. */ - if (priv->lookup_cancellable) { - g_cancellable_cancel (priv->lookup_cancellable); - g_clear_object (&priv->lookup_cancellable); - } + nm_clear_g_cancellable (&priv->lookup_cancellable); + g_clear_object (&priv->lookup_addr); g_clear_object (&priv->resolver); @@ -1910,13 +1943,12 @@ dispose (GObject *object) if (priv->firewall_manager) { g_assert (priv->fw_started_id); - g_signal_handler_disconnect (priv->firewall_manager, priv->fw_started_id); - priv->fw_started_id = 0; + nm_clear_g_signal_handler (priv->firewall_manager, &priv->fw_started_id); g_clear_object (&priv->firewall_manager); } if (priv->dns_manager) { - g_signal_handler_disconnect (priv->dns_manager, priv->config_changed_id); + nm_clear_g_signal_handler (priv->dns_manager, &priv->config_changed_id); g_clear_object (&priv->dns_manager); } @@ -1951,6 +1983,8 @@ dispose (GObject *object) g_clear_object (&priv->settings); g_clear_object (&priv->default_route_manager); + nm_assert (NM_IS_MANAGER (priv->manager)); + G_OBJECT_CLASS (nm_policy_parent_class)->dispose (object); } @@ -1962,30 +1996,47 @@ nm_policy_class_init (NMPolicyClass *policy_class) g_type_class_add_private (policy_class, sizeof (NMPolicyPrivate)); object_class->get_property = get_property; + object_class->set_property = set_property; + object_class->constructed = constructed; object_class->dispose = dispose; - g_object_class_install_property - (object_class, PROP_DEFAULT_IP4_DEVICE, - g_param_spec_object (NM_POLICY_DEFAULT_IP4_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_DEFAULT_IP6_DEVICE, - g_param_spec_object (NM_POLICY_DEFAULT_IP6_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_ACTIVATING_IP4_DEVICE, - g_param_spec_object (NM_POLICY_ACTIVATING_IP4_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property - (object_class, PROP_ACTIVATING_IP6_DEVICE, - g_param_spec_object (NM_POLICY_ACTIVATING_IP6_DEVICE, "", "", - NM_TYPE_DEVICE, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + obj_properties[PROP_MANAGER] = + g_param_spec_object (NM_POLICY_MANAGER, "", "", + NM_TYPE_MANAGER, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_SETTINGS] = + g_param_spec_object (NM_POLICY_SETTINGS, "", "", + NM_TYPE_SETTINGS, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEFAULT_ROUTE_MANAGER] = + g_param_spec_object (NM_POLICY_DEFAULT_ROUTE_MANAGER, "", "", + NM_TYPE_DEFAULT_ROUTE_MANAGER, + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEFAULT_IP4_DEVICE] = + g_param_spec_object (NM_POLICY_DEFAULT_IP4_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_DEFAULT_IP6_DEVICE] = + g_param_spec_object (NM_POLICY_DEFAULT_IP6_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ACTIVATING_IP4_DEVICE] = + g_param_spec_object (NM_POLICY_ACTIVATING_IP4_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + obj_properties[PROP_ACTIVATING_IP6_DEVICE] = + g_param_spec_object (NM_POLICY_ACTIVATING_IP6_DEVICE, "", "", + NM_TYPE_DEVICE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); } diff --git a/src/nm-policy.h b/src/nm-policy.h index f41f743d7e..9ccb209269 100644 --- a/src/nm-policy.h +++ b/src/nm-policy.h @@ -31,8 +31,11 @@ #define NM_IS_POLICY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLICY)) #define NM_POLICY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLICY, NMPolicyClass)) -#define NM_POLICY_DEFAULT_IP4_DEVICE "default-ip4-device" -#define NM_POLICY_DEFAULT_IP6_DEVICE "default-ip6-device" +#define NM_POLICY_MANAGER "manager" +#define NM_POLICY_SETTINGS "settings" +#define NM_POLICY_DEFAULT_ROUTE_MANAGER "default-route-manager" +#define NM_POLICY_DEFAULT_IP4_DEVICE "default-ip4-device" +#define NM_POLICY_DEFAULT_IP6_DEVICE "default-ip6-device" #define NM_POLICY_ACTIVATING_IP4_DEVICE "activating-ip4-device" #define NM_POLICY_ACTIVATING_IP6_DEVICE "activating-ip6-device" diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 10aa77ab41..6bed3fe5f2 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -1735,7 +1735,10 @@ settings_connection_update_helper (NMSettingsConnection *self, /* Check if the settings are valid first */ if (new_settings) { - tmp = nm_simple_connection_new_from_dbus (new_settings, &error); + tmp = _nm_simple_connection_new_from_dbus (new_settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (!tmp) goto error; } diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c index a189d7b1b0..1798dc477d 100644 --- a/src/settings/nm-settings.c +++ b/src/settings/nm-settings.c @@ -1411,7 +1411,10 @@ impl_settings_add_connection_helper (NMSettings *self, NMConnection *connection; GError *error = NULL; - connection = nm_simple_connection_new_from_dbus (settings, &error); + connection = _nm_simple_connection_new_from_dbus (settings, + NM_SETTING_PARSE_FLAGS_STRICT + | NM_SETTING_PARSE_FLAGS_NORMALIZE, + &error); if (connection) { if (!nm_connection_verify_secrets (connection, &error)) |