From 85563b7fc7ec2cd21e38debb9b28db342e2e8e7c Mon Sep 17 00:00:00 2001 From: Michael Biebl Date: Sun, 21 Apr 2019 21:09:51 +0200 Subject: New upstream version 1.18.0 --- clients/common/meson.build | 4 +- clients/common/nm-client-utils.c | 4 + clients/common/nm-client-utils.h | 8 +- clients/common/nm-meta-setting-access.c | 16 + clients/common/nm-meta-setting-access.h | 2 + clients/common/nm-meta-setting-desc.c | 4128 ++++++++++++++----------------- clients/common/nm-meta-setting-desc.h | 83 +- clients/common/nm-secret-agent-simple.c | 49 +- clients/common/nm-vpn-helpers.c | 67 +- clients/common/settings-docs.h | 4 + clients/common/settings-docs.h.in | 4 + clients/common/tests/meson.build | 2 +- 12 files changed, 2049 insertions(+), 2322 deletions(-) (limited to 'clients/common') diff --git a/clients/common/meson.build b/clients/common/meson.build index b4b6bcac..fed0f3bf 100644 --- a/clients/common/meson.build +++ b/clients/common/meson.build @@ -4,7 +4,7 @@ nm_polkit_listener = files('nm-polkit-listener.c') deps = [ libnm_dep, - nm_core_dep, + shared_nm_libnm_core_aux_dep, ] cflags = clients_cflags + [ @@ -55,7 +55,7 @@ libnmc = static_library( sources: files( 'nm-meta-setting-access.c', 'nm-meta-setting-desc.c', - ) + shared_nm_meta_setting_c + shared_nm_ethtool_utils_c + [settings_docs_source], + ) + shared_nm_meta_setting_c + [settings_docs_source], dependencies: deps, c_args: cflags, link_with: libnmc_base, diff --git a/clients/common/nm-client-utils.c b/clients/common/nm-client-utils.c index 1241131a..0a155dae 100644 --- a/clients/common/nm-client-utils.c +++ b/clients/common/nm-client-utils.c @@ -82,6 +82,10 @@ nmc_string_to_uint_base (const char *str, char *end; unsigned long int tmp; + if (!str || !str[0]) + return FALSE; + + /* FIXME: don't use this function, replace by _nm_utils_ascii_str_to_int64() */ errno = 0; tmp = strtoul (str, &end, base); if (errno || *end != '\0' || (range_check && (tmp < min || tmp > max))) { diff --git a/clients/common/nm-client-utils.h b/clients/common/nm-client-utils.h index a5bc05fa..08a39f03 100644 --- a/clients/common/nm-client-utils.h +++ b/clients/common/nm-client-utils.h @@ -23,13 +23,7 @@ #include "nm-meta-setting.h" #include "nm-active-connection.h" #include "nm-device.h" - - -#define nm_auto_unref_ip_address nm_auto (_nm_ip_address_unref) -NM_AUTO_DEFINE_FCN0 (NMIPAddress *, _nm_ip_address_unref, nm_ip_address_unref) - -#define nm_auto_unref_wgpeer nm_auto (_nm_auto_unref_wgpeer) -NM_AUTO_DEFINE_FCN0 (NMWireGuardPeer *, _nm_auto_unref_wgpeer, nm_wireguard_peer_unref) +#include "nm-libnm-core-intern/nm-libnm-core-utils.h" const NMObject **nmc_objects_sort_by_path (const NMObject *const*objs, gssize len); diff --git a/clients/common/nm-meta-setting-access.c b/clients/common/nm-meta-setting-access.c index bd4064de..8399f29d 100644 --- a/clients/common/nm-meta-setting-access.c +++ b/clients/common/nm-meta-setting-access.c @@ -101,6 +101,22 @@ nm_meta_setting_info_editor_get_property_info (const NMMetaSettingInfoEditor *se return NULL; } +gboolean +nm_meta_setting_info_editor_has_secrets (const NMMetaSettingInfoEditor *setting_info) +{ + guint i; + + if (!setting_info) + return FALSE; + + for (i = 0; i < setting_info->properties_num; i++) { + if (setting_info->properties[i]->is_secret) + return TRUE; + } + + return FALSE; +} + const NMMetaPropertyInfo * nm_meta_property_info_find_by_name (const char *setting_name, const char *property_name) { diff --git a/clients/common/nm-meta-setting-access.h b/clients/common/nm-meta-setting-access.h index 9898cc5a..ec1c2ba0 100644 --- a/clients/common/nm-meta-setting-access.h +++ b/clients/common/nm-meta-setting-access.h @@ -39,6 +39,8 @@ const NMMetaPropertyInfo *nm_meta_property_info_find_by_name (const char *settin const NMMetaPropertyInfo *nm_meta_property_info_find_by_setting (NMSetting *setting, const char *property_name); +gboolean nm_meta_setting_info_editor_has_secrets (const NMMetaSettingInfoEditor *setting_info); + /*****************************************************************************/ const NMMetaSettingInfoEditor *const*nm_meta_setting_infos_editor_p (void); diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c index 6e35228a..698ded86 100644 --- a/clients/common/nm-meta-setting-desc.c +++ b/clients/common/nm-meta-setting-desc.c @@ -24,8 +24,10 @@ #include #include -#include "nm-common-macros.h" -#include "nm-utils/nm-enum-utils.h" +#include "nm-libnm-core-intern/nm-common-macros.h" +#include "nm-glib-aux/nm-enum-utils.h" +#include "nm-glib-aux/nm-secret-utils.h" +#include "nm-libnm-core-intern/nm-libnm-core-utils.h" #include "nm-vpn-helpers.h" #include "nm-client-utils.h" @@ -74,6 +76,196 @@ _gtype_property_get_gtype (GType gtype, const char *property_name) /*****************************************************************************/ +static int +_int64_cmp_desc (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + NM_CMP_DIRECT (*((const gint64 *) b), *((const gint64 *) a)); + return 0; +} + +static gint64 * +_value_str_as_index_list (const char *value, gsize *out_len) +{ + gs_free char *str_clone_free = NULL; + gboolean str_cloned = FALSE; + char *str; + gsize i, j; + gsize n_alloc; + gsize len; + gs_free gint64 *arr = NULL; + + *out_len = 0; + + if (!value) + return NULL; + + str = (char *) value; + n_alloc = 0; + len = 0; + while (TRUE) { + gint64 i64; + const char *s; + gsize good; + + good = strcspn (str, ","NM_ASCII_SPACES); + if (good == 0) { + if (str[0] == '\0') + break; + str++; + continue; + } + if (str[good] == '\0') { + s = str; + str += good; + } else { + if (!str_cloned) { + str_cloned = TRUE; + str = nm_strndup_a (200, str, strlen (str), &str_clone_free); + } + s = str; + str[good] = '\0'; + str += good + 1; + } + + i64 = _nm_utils_ascii_str_to_int64 (s, 10, 0, G_MAXINT64, -1); + if (i64 == -1) + return NULL; + + if (len >= n_alloc) { + if (n_alloc > 0) { + n_alloc = n_alloc * 2; + arr = g_realloc (arr, n_alloc * sizeof (gint64)); + } else { + n_alloc = 4; + arr = g_new (gint64, n_alloc); + } + } + arr[len++] = i64; + } + + if (len > 1) { + /* sort the list of indexes descendingly, and drop duplicates. */ + g_qsort_with_data (arr, + len, + sizeof (gint64), + _int64_cmp_desc, + NULL); + j = 1; + for (i = 1; i < len; i++) { + nm_assert (arr[i - 1] >= arr[i]); + if (arr[i - 1] > arr[i]) + arr[j++] = arr[i]; + } + len = j; + } + + *out_len = len; + return g_steal_pointer (&arr); +} + +#define ESCAPED_TOKENS_WITH_SPACES_DELIMTER ' ' +#define ESCAPED_TOKENS_WITH_SPACES_DELIMTERS NM_ASCII_SPACES"," + +#define ESCAPED_TOKENS_DELIMITER ',' +#define ESCAPED_TOKENS_DELIMITERS "," + +typedef enum { + VALUE_STRSPLIT_MODE_OBJLIST, + VALUE_STRSPLIT_MODE_MULTILIST, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES, +} ValueStrsplitMode; + +static const char ** +_value_strsplit (const char *value, + ValueStrsplitMode split_mode, + gsize *out_len) +{ + gs_free const char **strv = NULL; + gsize i; + gsize len; + + /* FIXME: some modes should support backslash escaping. + * In particular, to distingish from _value_str_as_index_list(), which + * does not accept '\\'. */ + + /* note that all modes remove empty tokens (",", "a,,b", ",,"). */ + switch (split_mode) { + case VALUE_STRSPLIT_MODE_OBJLIST: + strv = nm_utils_strsplit_set (value, ESCAPED_TOKENS_DELIMITERS); + break; + case VALUE_STRSPLIT_MODE_MULTILIST: + strv = nm_utils_strsplit_set (value, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS); + break; + case VALUE_STRSPLIT_MODE_ESCAPED_TOKENS: + strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_DELIMITERS); + NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv)); + return g_steal_pointer (&strv); + case VALUE_STRSPLIT_MODE_ESCAPED_TOKENS_WITH_SPACES: + strv = nm_utils_escaped_tokens_split (value, ESCAPED_TOKENS_WITH_SPACES_DELIMTERS); + NM_SET_OUT (out_len, NM_PTRARRAY_LEN (strv)); + return g_steal_pointer (&strv); + default: + nm_assert_not_reached (); + break; + } + + NM_SET_OUT (out_len, 0); + + if (!strv) + return NULL; + + len = 0; + for (i = 0; strv[i]; i++) { + const char *s = strv[i]; + + s = nm_str_skip_leading_spaces (s); + if (s[0] == '\0') + continue; + + g_strchomp ((char *) s); + strv[len++] = s; + } + strv[len] = NULL; + + NM_SET_OUT (out_len, len); + return g_steal_pointer (&strv); +} + +static gboolean +_value_strsplit_assert_unsplitable (const char *str) +{ +#if NM_MORE_ASSERTS > 5 + gs_free const char **strv_test = NULL; + gsize j, l; + + /* Assert that we cannot split the token and that it + * has no unescaped delimiters. */ + + strv_test = _value_strsplit (str, + VALUE_STRSPLIT_MODE_ESCAPED_TOKENS, + NULL); + nm_assert (NM_PTRARRAY_LEN (strv_test) == 1); + + for (j = 0; str[j] != '\0'; ) { + if (str[j] == '\\') { + j++; + nm_assert (str[j] != '\0'); + } else + nm_assert (!NM_IN_SET (str[j], '\0', ',')); + j++; + } + l = j; + nm_assert ( !g_ascii_isspace (str[l - 1]) + || ( l >= 2 + && str[l - 2] == '\\')); +#endif + + return TRUE; +} + static NMIPAddress * _parse_ip_address (int family, const char *address, GError **error) { @@ -123,20 +315,20 @@ _parse_ip_route (int family, gint64 metric = -1; guint i; gs_free const char **routev = NULL; - gs_free char *str_clean = NULL; + gs_free char *str_clean_free = NULL; + const char *str_clean; gs_free char *dest_clone = NULL; const char *dest; const char *plen; gs_unref_hashtable GHashTable *attrs = NULL; - GHashTable *tmp_attrs; #define ROUTE_SYNTAX _("The valid syntax is: 'ip[/prefix] [next-hop] [metric] [attribute=val]... [,ip[/prefix] ...]'") nm_assert (NM_IN_SET (family, AF_INET, AF_INET6)); nm_assert (str); nm_assert (!error || !*error); - str_clean = g_strstrip (g_strdup (str)); - routev = nm_utils_strsplit_set (str_clean, " \t", FALSE); + str_clean = nm_strstrip_avoid_copy_a (300, str, &str_clean_free); + routev = nm_utils_strsplit_set (str_clean, " \t"); if (!routev) { g_set_error (error, 1, 0, "'%s' is not valid. %s", @@ -182,6 +374,7 @@ _parse_ip_route (int family, GHashTableIter iter; char *iter_key; GVariant *iter_value; + gs_unref_hashtable GHashTable *tmp_attrs = NULL; tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE, nm_ip_route_get_variant_attribute_spec(), @@ -207,13 +400,11 @@ _parse_ip_route (int family, if (!nm_ip_route_attribute_validate (iter_key, iter_value, family, NULL, error)) { g_prefix_error (error, "%s: ", iter_key); - g_hash_table_unref (tmp_attrs); return NULL; } g_hash_table_insert (attrs, iter_key, iter_value); g_hash_table_iter_steal (&iter); } - g_hash_table_unref (tmp_attrs); } else { g_set_error (error, 1, 0, "%s", ROUTE_SYNTAX); return NULL; @@ -298,7 +489,8 @@ _parse_team_link_watcher (const char *str, GError **error) { gs_free const char **watcherv = NULL; - gs_free char *str_clean = NULL; + gs_free char *str_clean_free = NULL; + const char *str_clean; guint i; gs_free const char *name = NULL; int val1 = 0, val2 = 0, val3 = 3, val4 = -1; @@ -309,8 +501,8 @@ _parse_team_link_watcher (const char *str, nm_assert (str); nm_assert (!error || !*error); - str_clean = g_strstrip (g_strdup (str)); - watcherv = nm_utils_strsplit_set (str_clean, " \t", FALSE); + str_clean = nm_strstrip_avoid_copy_a (300, str, &str_clean_free); + watcherv = nm_utils_strsplit_set (str_clean, " \t"); if (!watcherv) { g_set_error (error, 1, 0, "'%s' is not valid", str); return NULL; @@ -319,7 +511,7 @@ _parse_team_link_watcher (const char *str, for (i = 0; watcherv[i]; i++) { gs_free const char **pair = NULL; - pair = nm_utils_strsplit_set (watcherv[i], "=", FALSE); + pair = nm_utils_strsplit_set (watcherv[i], "="); if (!pair) { g_set_error (error, 1, 0, "'%s' is not valid: %s", watcherv[i], "properties should be specified as 'key=value'"); @@ -397,62 +589,6 @@ _parse_team_link_watcher (const char *str, #define MAX_SKB_PRIO G_MAXUINT32 #define MAX_8021P_PRIO 7 /* Max 802.1p priority */ -/* - * Parse VLAN priority mappings from the following format: 2:1,3:4,7:3 - * and verify if the priority numbers are valid - * - * Return: string array with split maps, or NULL on error - * Caller is responsible for freeing the array. - */ -static char ** -_parse_vlan_priority_maps (const char *priority_map, - NMVlanPriorityMap map_type, - GError **error) -{ - char **mapping = NULL, **iter; - unsigned long from, to, from_max, to_max; - - g_return_val_if_fail (priority_map != NULL, NULL); - g_return_val_if_fail (error == NULL || *error == NULL, NULL); - - if (map_type == NM_VLAN_INGRESS_MAP) { - from_max = MAX_8021P_PRIO; - to_max = MAX_SKB_PRIO; - } else { - from_max = MAX_SKB_PRIO; - to_max = MAX_8021P_PRIO; - } - - mapping = g_strsplit (priority_map, ",", 0); - for (iter = mapping; iter && *iter; iter++) { - char *left, *right; - - left = g_strstrip (*iter); - right = strchr (left, ':'); - if (!right) { - g_set_error (error, 1, 0, _("invalid priority map '%s'"), *iter); - g_strfreev (mapping); - return NULL; - } - *right++ = '\0'; - - if (!nmc_string_to_uint (left, TRUE, 0, from_max, &from)) { - g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"), - left, from_max); - g_strfreev (mapping); - return NULL; - } - if (!nmc_string_to_uint (right, TRUE, 0, to_max, &to)) { - g_set_error (error, 1, 0, _("priority '%s' is not valid (<0-%ld>)"), - right, to_max); - g_strfreev (mapping); - return NULL; - } - *(right-1) = ':'; /* Put back ':' */ - } - return mapping; -} - /* * nmc_proxy_check_script: * @script: file name with PAC script, or raw PAC Script data @@ -646,10 +782,10 @@ _env_warn_fcn (const NMMetaEnvironment *environment, const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, gboolean *out_is_default, gpointer *out_to_free #define ARGS_SET_FCN \ - const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, GError **error + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, char modifier, const char *value, GError **error #define ARGS_REMOVE_FCN \ - const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, guint32 idx, GError **error + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, GError **error #define ARGS_COMPLETE_FCN \ const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, const NMMetaOperationContext *operation_context, const char *text, char ***out_to_free @@ -660,6 +796,46 @@ _env_warn_fcn (const NMMetaEnvironment *environment, #define ARGS_SETTING_INIT_FCN \ const NMMetaSettingInfoEditor *setting_info, NMSetting *setting, NMMetaAccessorSettingInitType init_type +static gboolean +_SET_FCN_DO_RESET_DEFAULT (const NMMetaPropertyInfo *property_info, char modifier, const char *value) +{ + nm_assert (property_info); + nm_assert (!property_info->property_type->set_supports_remove); + nm_assert (NM_IN_SET (modifier, '\0', '+')); + nm_assert (value || modifier == '\0'); + + return value == NULL; +} + +static gboolean +_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE (const NMMetaPropertyInfo *property_info, char modifier, const char *value) +{ + nm_assert (property_info); + nm_assert (property_info->property_type->set_supports_remove); + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value || modifier == '\0'); + + return value == NULL; +} + +static gboolean +_SET_FCN_DO_SET_ALL (char modifier, const char *value) +{ + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value); + + return modifier == '\0'; +} + +static gboolean +_SET_FCN_DO_REMOVE (char modifier, const char *value) +{ + nm_assert (NM_IN_SET (modifier, '\0', '+', '-')); + nm_assert (value); + + return modifier == '-'; +} + #define RETURN_UNSUPPORTED_GET_TYPE() \ G_STMT_START { \ if (!NM_IN_SET (get_type, \ @@ -677,7 +853,7 @@ _env_warn_fcn (const NMMetaEnvironment *environment, } G_STMT_END static gboolean -property_is_default (NMSetting *setting, const char *prop_name) +_gobject_property_is_default (NMSetting *setting, const char *prop_name) { nm_auto_unset_gvalue GValue v = G_VALUE_INIT; GParamSpec *pspec; @@ -703,32 +879,30 @@ property_is_default (NMSetting *setting, const char *prop_name) return g_param_value_defaults (pspec, &v); } -static gconstpointer -_get_fcn_nmc_with_default (ARGS_GET_FCN) +static gboolean +_gobject_property_reset (NMSetting *setting, + const char *prop_name, + gboolean reset_default) { - const char *s; - char *s_full; - GValue val = G_VALUE_INIT; - - RETURN_UNSUPPORTED_GET_TYPE (); - NM_SET_OUT (out_is_default, property_is_default (setting, property_info->property_name)); + nm_auto_unset_gvalue GValue v = G_VALUE_INIT; + GParamSpec *pspec; - if (property_info->property_typ_data->subtype.get_with_default.fcn (setting)) { - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - return _("(default)"); - return ""; - } + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), + prop_name); + if (!G_IS_PARAM_SPEC (pspec)) + g_return_val_if_reached (FALSE); - g_value_init (&val, G_TYPE_STRING); - g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); - s = g_value_get_string (&val); - if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - s_full = s ? g_strdup_printf ("\"%s\"", s) : g_strdup (""); - else - s_full = g_strdup (s && *s ? s : " "); - g_value_unset (&val); + g_value_init (&v, pspec->value_type); + if (reset_default) + g_param_value_defaults (pspec, &v); + g_object_set_property (G_OBJECT (setting), prop_name, &v); + return TRUE; +} - RETURN_STR_TO_FREE (s_full); +static gboolean +_gobject_property_reset_default (NMSetting *setting, const char *prop_name) +{ + return _gobject_property_reset (setting, prop_name, TRUE); } static gconstpointer @@ -738,13 +912,20 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, gboolean *out_is_default, gpointer *out_to_free) { - char *s; - const char *s_c; + const char *cstr; GType gtype_prop; nm_auto_unset_gvalue GValue val = G_VALUE_INIT; RETURN_UNSUPPORTED_GET_TYPE (); - NM_SET_OUT (out_is_default, property_is_default (setting, property_info->property_name)); + NM_SET_OUT (out_is_default, _gobject_property_is_default (setting, property_info->property_name)); + + if ( property_info->property_typ_data + && property_info->property_typ_data->is_default_fcn + && property_info->property_typ_data->is_default_fcn (setting)) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _("(default)"); + return ""; + } gtype_prop = _gobject_property_get_gtype (G_OBJECT (setting), property_info->property_name); @@ -755,15 +936,35 @@ _get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); b = g_value_get_boolean (&val); if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) - s_c = b ? _("yes") : _("no"); + cstr = b ? _("yes") : _("no"); else - s_c = b ? "yes" : "no"; - return s_c; + cstr = b ? "yes" : "no"; + return cstr; } else { + char *str; + + /* Note that we register certain transform functions in nmc_value_transforms_register(). + * This makes G_TYPE_STRV working. + * + * FIXME: that is particularly ugly because it's non-obvious which code relies + * on nmc_value_transforms_register(). Also, nmc_value_transforms_register() is + * in clients/cli, while we are here in clients/common. */ g_value_init (&val, G_TYPE_STRING); g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); - s = g_value_dup_string (&val); - RETURN_STR_TO_FREE (s); + cstr = g_value_get_string (&val); + + if ( property_info->property_typ_data + && property_info->property_typ_data->is_default_fcn) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) { + str = cstr + ? g_strdup_printf ("\"%s\"", cstr) + : g_strdup (""); + } else + str = g_strdup (cstr && cstr[0] ? cstr : " "); + } else + str = cstr ? g_strdup (cstr) : NULL; + + RETURN_STR_TO_FREE (str); } } @@ -842,10 +1043,9 @@ _get_fcn_gobject_int (ARGS_GET_FCN) for (; value_infos->nick; value_infos++) { if ( ( is_uint64 && value_infos->value.u64 == v.u64) || (!is_uint64 && value_infos->value.i64 == v.i64)) { - char *old_str = return_str; + gs_free char *old_str = return_str; return_str = g_strdup_printf ("%s (%s)", old_str, value_infos->nick); - g_free (old_str); break; } } @@ -1033,6 +1233,9 @@ _set_fcn_gobject_string (ARGS_SET_FCN) { gs_free char *to_free = NULL; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) { if (property_info->property_typ_data->subtype.gobject_string.validate_fcn) { value = property_info->property_typ_data->subtype.gobject_string.validate_fcn (value, &to_free, error); @@ -1055,6 +1258,9 @@ _set_fcn_gobject_bool (ARGS_SET_FCN) { gboolean val_bool; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (!nmc_string_to_bool (value, &val_bool, error)) return FALSE; @@ -1076,6 +1282,9 @@ _set_fcn_gobject_int (ARGS_SET_FCN) guint base = 10; const NMMetaUtilsIntValueInfo *value_infos; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), property_info->property_name); if (!G_IS_PARAM_SPEC (pspec)) g_return_val_if_reached (FALSE); @@ -1085,14 +1294,10 @@ _set_fcn_gobject_int (ARGS_SET_FCN) if (property_info->property_typ_data) { if ( value && (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) { - gs_free char *vv_stripped = NULL; - const char *vv = nm_str_skip_leading_spaces (value); - - if (vv[0] && g_ascii_isspace (vv[strlen (vv) - 1])) { - vv_stripped = g_strstrip (g_strdup (vv)); - vv = vv_stripped; - } + gs_free char *vv_free = NULL; + const char *vv; + vv = nm_strstrip_avoid_copy_a (300, value, &vv_free); for (; value_infos->nick; value_infos++) { if (nm_streq (value_infos->nick, vv)) { v = value_infos->value; @@ -1216,7 +1421,10 @@ _set_fcn_gobject_mtu (ARGS_SET_FCN) const GParamSpec *pspec; gint64 v; - if (nm_streq0 (value, "auto")) + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + + if (nm_streq (value, "auto")) value = "0"; pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), @@ -1254,6 +1462,9 @@ _set_fcn_gobject_mac (ARGS_SET_FCN) NMMetaPropertyTypeMacMode mode; gboolean valid; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) mode = property_info->property_typ_data->subtype.mac.mode; else @@ -1289,6 +1500,9 @@ _set_fcn_gobject_enum (ARGS_SET_FCN) gboolean is_flags; int v; + if (_SET_FCN_DO_RESET_DEFAULT (property_info, modifier, value)) + return _gobject_property_reset_default (setting, property_info->property_name); + if (property_info->property_typ_data) { if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) { gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype (); @@ -1558,25 +1772,6 @@ vlan_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) return g_string_free (flag_str, FALSE); } -static char * -vlan_priorities_to_string (NMSettingVlan *s_vlan, NMVlanPriorityMap map) -{ - GString *priorities; - int i; - - priorities = g_string_new (NULL); - for (i = 0; i < nm_setting_vlan_get_num_priorities (s_vlan, map); i++) { - guint32 from, to; - - if (nm_setting_vlan_get_priority (s_vlan, map, i, &from, &to)) - g_string_append_printf (priorities, "%d:%d,", from, to); - } - if (priorities->len) - g_string_truncate (priorities, priorities->len-1); /* chop off trailing ',' */ - - return g_string_free (priorities, FALSE); -} - static char * secret_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) { @@ -1619,166 +1814,204 @@ vpn_data_item (const char *key, const char *value, gpointer user_data) g_string_append_printf (ret_str, "%s = %s", key, value); } -#define DEFINE_SETTER_STR_LIST_MULTI(def_func, s_macro, set_func) \ - static gboolean \ - def_func (NMSetting *setting, \ - const char *prop, \ - const char *value, \ - const char **valid_strv, \ - GError **error) \ - { \ - gs_free const char **strv = NULL; \ - gsize i; \ - const char *item; \ - nm_assert (!error || !*error); \ - strv = nm_utils_strsplit_set (value, " \t,", FALSE); \ - if (strv) { \ - for (i = 0; strv[i]; i++) { \ - if (!(item = nmc_string_is_valid (strv[i], valid_strv, error))) { \ - return FALSE; \ - } \ - set_func (s_macro (setting), item); \ - } \ - } \ - return TRUE; \ +static const char * +_multilist_do_validate (const NMMetaPropertyInfo *property_info, + NMSetting *setting, + const char *item, + GError **error) +{ + if (property_info->property_typ_data->values_static) { + nm_assert (!property_info->property_typ_data->subtype.multilist.validate_fcn); + return nmc_string_is_valid (item, + (const char **) property_info->property_typ_data->values_static, + error); + } + if (property_info->property_typ_data->subtype.multilist.validate_fcn) { + return property_info->property_typ_data->subtype.multilist.validate_fcn (item, + error); + } + if (property_info->property_typ_data->subtype.multilist.validate2_fcn) { + return property_info->property_typ_data->subtype.multilist.validate2_fcn (setting, + item, + error); } -#define DEFINE_SETTER_OPTIONS(def_func, s_macro, s_type, add_func, valid_func1, valid_func2) \ - static gboolean \ - def_func (ARGS_SET_FCN) \ - { \ - gs_free const char **strv = NULL; \ - const char **iter; \ - const char **(*valid_func1_p) (s_type *) = valid_func1; \ - const char * (*valid_func2_p) (const char *, const char *, GError **) = valid_func2; \ - const char *opt_name, *opt_val; \ - \ - nm_assert (!error || !*error); \ - \ - strv = nm_utils_strsplit_set (value, ",", FALSE); \ - for (iter = strv; iter && *iter; iter++) { \ - gs_free char *left_clone = g_strstrip (g_strdup (*iter)); \ - char *left = left_clone; \ - char *right = strchr (left, '='); \ - if (!right) { \ - g_set_error (error, 1, 0, _("'%s' is not valid; use