diff options
Diffstat (limited to 'clients/common/nm-meta-setting-desc.c')
| -rw-r--r-- | clients/common/nm-meta-setting-desc.c | 7284 |
1 files changed, 7284 insertions, 0 deletions
diff --git a/clients/common/nm-meta-setting-desc.c b/clients/common/nm-meta-setting-desc.c new file mode 100644 index 00000000..1ed6b433 --- /dev/null +++ b/clients/common/nm-meta-setting-desc.c @@ -0,0 +1,7284 @@ +/* nmcli - command-line tool to control NetworkManager + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Copyright 2010 - 2017 Red Hat, Inc. + */ + +#include "nm-default.h" + +#include "nm-meta-setting-desc.h" + +#include <stdlib.h> +#include <arpa/inet.h> + +#include "nm-common-macros.h" +#include "nm-utils/nm-hash-utils.h" +#include "nm-utils/nm-enum-utils.h" + +#include "NetworkManager.h" +#include "nm-vpn-helpers.h" +#include "nm-client-utils.h" +#include "nm-meta-setting-access.h" + +/*****************************************************************************/ + +static char *secret_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type); + +#define ALL_SECRET_FLAGS \ + (NM_SETTING_SECRET_FLAG_NONE | \ + NM_SETTING_SECRET_FLAG_AGENT_OWNED | \ + NM_SETTING_SECRET_FLAG_NOT_SAVED | \ + NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + +/*****************************************************************************/ + +static GType +_gobject_property_get_gtype (GObject *gobject, const char *property_name) +{ + GParamSpec *param_spec; + + param_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (gobject), property_name); + if (param_spec) + return param_spec->value_type; + g_return_val_if_reached (G_TYPE_INVALID); +} + +static GType +_gtype_property_get_gtype (GType gtype, const char *property_name) +{ + /* given @gtype, a type for a GObject, lookup the property @property_name + * and return its value_type. */ + if (G_TYPE_IS_CLASSED (gtype)) { + GParamSpec *param_spec; + nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref (gtype); + + if (G_IS_OBJECT_CLASS (gtypeclass)) { + param_spec = g_object_class_find_property (G_OBJECT_CLASS (gtypeclass), property_name); + if (param_spec) + return param_spec->value_type; + } + } + g_return_val_if_reached (G_TYPE_INVALID); +} + +/*****************************************************************************/ + +static NMIPAddress * +_parse_ip_address (int family, const char *address, GError **error) +{ + gs_free char *ip_str = NULL; + const int MAX_PREFIX = (family == AF_INET) ? 32 : 128; + NMIPAddress *addr; + char *plen; + int prefix; + GError *local = NULL; + + g_return_val_if_fail (address, NULL); + g_return_val_if_fail (!error || !*error, NULL); + + ip_str = g_strstrip (g_strdup (address)); + + prefix = MAX_PREFIX; + + plen = strchr (ip_str, '/'); + if (plen) { + *plen++ = '\0'; + if ((prefix = _nm_utils_ascii_str_to_int64 (plen, 10, 1, MAX_PREFIX, -1)) == -1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid prefix '%s'; <1-%d> allowed"), plen, MAX_PREFIX); + return NULL; + } + } + + addr = nm_ip_address_new (family, ip_str, prefix, &local); + if (!addr) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid IP address: %s"), local->message); + g_clear_error (&local); + } + return addr; +} + +static NMIPRoute * +_parse_ip_route (int family, + const char *str, + GError **error) +{ + const int MAX_PREFIX = (family == AF_INET) ? 32 : 128; + char *plen = NULL; + const char *next_hop = NULL; + const char *canon_dest; + int prefix; + NMIPRoute *route = NULL; + GError *local = NULL; + gint64 metric = -1; + guint i; + gs_strfreev char **routev = NULL; + gs_free char *str_clean = NULL; + char *dest; + 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 = nmc_strsplit_set (str_clean, " \t", 0); + if (!routev || !routev[0]) { + g_set_error (error, 1, 0, + "'%s' is not valid. %s", + str, ROUTE_SYNTAX); + return NULL; + } + + dest = routev[0]; + plen = strchr (dest, '/'); /* prefix delimiter */ + if (plen) + *plen++ = '\0'; + prefix = MAX_PREFIX; + if (plen) { + if ((prefix = _nm_utils_ascii_str_to_int64 (plen, 10, 1, MAX_PREFIX, -1)) == -1) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid prefix '%s'; <1-%d> allowed"), + plen, MAX_PREFIX); + return NULL; + } + } + + for (i = 1; routev[i]; i++) { + gint64 tmp64; + + if (nm_utils_ipaddr_valid (family, routev[i])) { + if (metric != -1 || attrs) { + g_set_error (error, 1, 0, _("the next hop ('%s') must be first"), routev[i]); + return NULL; + } + next_hop = routev[i]; + } else if ((tmp64 = _nm_utils_ascii_str_to_int64 (routev[i], 10, 0, G_MAXUINT32, -1)) != -1) { + if (attrs) { + g_set_error (error, 1, 0, _("the metric ('%s') must be before attributes"), routev[i]); + return NULL; + } + metric = tmp64; + } else if (strchr (routev[i], '=')) { + GHashTableIter iter; + char *iter_key; + GVariant *iter_value; + + tmp_attrs = nm_utils_parse_variant_attributes (routev[i], ' ', '=', FALSE, + nm_ip_route_get_variant_attribute_spec(), + error); + if (!tmp_attrs) { + g_prefix_error (error, "invalid option '%s': ", routev[i]); + return NULL; + } + + if (!attrs) + attrs = g_hash_table_new (nm_str_hash, g_str_equal); + + g_hash_table_iter_init (&iter, tmp_attrs); + while (g_hash_table_iter_next (&iter, (gpointer *) &iter_key, (gpointer *) &iter_value)) { + 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; + } + } + + route = nm_ip_route_new (family, dest, prefix, next_hop, metric, &local); + if (!route) { + g_set_error (error, 1, 0, + _("invalid route: %s. %s"), local->message, ROUTE_SYNTAX); + g_clear_error (&local); + return NULL; + } + + /* We don't accept default routes as NetworkManager handles it + * itself. But we have to check this after @route has normalized the + * dest string. + */ + canon_dest = nm_ip_route_get_dest (route); + if (!strcmp (canon_dest, "0.0.0.0") || !strcmp (canon_dest, "::")) { + g_set_error_literal (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("default route cannot be added (NetworkManager handles it by itself)")); + g_clear_pointer (&route, nm_ip_route_unref); + return NULL; + } + + if (attrs) { + GHashTableIter iter; + char *name; + GVariant *variant; + + g_hash_table_iter_init (&iter, attrs); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, (gpointer *) &variant)) + nm_ip_route_set_attribute (route, name, variant); + } + + return route; +} + +/* Max priority values from libnm-core/nm-setting-vlan.c */ +#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 + * @out_script: raw PAC Script (with removed new-line characters) + * @error: location to store error, or %NULL + * + * Check PAC Script from @script parameter and return the checked/sanitized + * config in @out_script. + * + * Returns: %TRUE if the script is valid, %FALSE if it is invalid + */ +static gboolean +nmc_proxy_check_script (const char *script, char **out_script, GError **error) +{ + enum { + _PAC_SCRIPT_TYPE_GUESS, + _PAC_SCRIPT_TYPE_FILE, + _PAC_SCRIPT_TYPE_JSON, + } desired_type = _PAC_SCRIPT_TYPE_GUESS; + const char *filename = NULL; + size_t c_len = 0; + gs_free char *script_clone = NULL; + + *out_script = NULL; + + if (!script || !script[0]) + return TRUE; + + if (g_str_has_prefix (script, "file://")) { + script += NM_STRLEN ("file://"); + desired_type = _PAC_SCRIPT_TYPE_FILE; + } else if (g_str_has_prefix (script, "js://")) { + script += NM_STRLEN ("js://"); + desired_type = _PAC_SCRIPT_TYPE_JSON; + } + + if (NM_IN_SET (desired_type, _PAC_SCRIPT_TYPE_FILE, _PAC_SCRIPT_TYPE_GUESS)) { + gs_free char *contents = NULL; + + if (!g_file_get_contents (script, &contents, &c_len, NULL)) { + if (desired_type == _PAC_SCRIPT_TYPE_FILE) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("cannot read pac-script from file '%s'"), + script); + return FALSE; + } + } else { + if (c_len != strlen (contents)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("file '%s' contains non-valid utf-8"), + script); + return FALSE; + } + filename = script; + script = script_clone = g_steal_pointer (&contents); + } + } + + if ( !strstr (script, "FindProxyForURL") + || !g_utf8_validate (script, -1, NULL)) { + if (filename) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' does not contain a valid PAC Script"), filename); + } else { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("Not a valid PAC Script")); + } + return FALSE; + } + + *out_script = (script == script_clone) + ? g_steal_pointer (&script_clone) + : g_strdup (script); + return TRUE; +} + +/* + * nmc_team_check_config: + * @config: file name with team config, or raw team JSON config data + * @out_config: raw team JSON config data + * The value must be freed with g_free(). + * @error: location to store error, or %NUL + * + * Check team config from @config parameter and return the checked + * config in @out_config. + * + * Returns: %TRUE if the config is valid, %FALSE if it is invalid + */ +static gboolean +nmc_team_check_config (const char *config, char **out_config, GError **error) +{ + enum { + _TEAM_CONFIG_TYPE_GUESS, + _TEAM_CONFIG_TYPE_FILE, + _TEAM_CONFIG_TYPE_JSON, + } desired_type = _TEAM_CONFIG_TYPE_GUESS; + const char *filename = NULL; + size_t c_len = 0; + gs_free char *config_clone = NULL; + + *out_config = NULL; + + if (!config || !config[0]) + return TRUE; + + if (g_str_has_prefix (config, "file://")) { + config += NM_STRLEN ("file://"); + desired_type = _TEAM_CONFIG_TYPE_FILE; + } else if (g_str_has_prefix (config, "json://")) { + config += NM_STRLEN ("json://"); + desired_type = _TEAM_CONFIG_TYPE_JSON; + } + + if (NM_IN_SET (desired_type, _TEAM_CONFIG_TYPE_FILE, _TEAM_CONFIG_TYPE_GUESS)) { + gs_free char *contents = NULL; + + if (!g_file_get_contents (config, &contents, &c_len, NULL)) { + if (desired_type == _TEAM_CONFIG_TYPE_FILE) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("cannot read team config from file '%s'"), + config); + return FALSE; + } + } else { + if (c_len != strlen (contents)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("team config file '%s' contains non-valid utf-8"), + config); + return FALSE; + } + filename = config; + config = config_clone = g_steal_pointer (&contents); + } + } + + if (!nm_utils_is_json_object (config, NULL)) { + if (filename) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' does not contain a valid team configuration"), filename); + } else { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("team configuration must be a JSON object")); + } + return FALSE; + } + + *out_config = (config == config_clone) + ? g_steal_pointer (&config_clone) + : g_strdup (config); + return TRUE; +} + +static const char * +_get_text_hidden (NMMetaAccessorGetType get_type) +{ + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _(NM_META_TEXT_HIDDEN); + return NM_META_TEXT_HIDDEN; +} + +/*****************************************************************************/ + +G_GNUC_PRINTF (4, 5) +static void +_env_warn_fcn (const NMMetaEnvironment *environment, + gpointer environment_user_data, + NMMetaEnvWarnLevel warn_level, + const char *fmt_l10n, + ...) +{ + va_list ap; + + if (!environment || !environment->warn_fcn) + return; + + va_start (ap, fmt_l10n); + environment->warn_fcn (environment, + environment_user_data, + warn_level, + fmt_l10n, + ap); + va_end (ap); +} + +/*****************************************************************************/ + +#define ARGS_DESCRIBE_FCN \ + const NMMetaPropertyInfo *property_info, char **out_to_free + +#define ARGS_GET_FCN \ + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, 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 + +#define ARGS_REMOVE_FCN \ + const NMMetaPropertyInfo *property_info, const NMMetaEnvironment *environment, gpointer environment_user_data, NMSetting *setting, const char *value, guint32 idx, 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 + +#define ARGS_VALUES_FCN \ + const NMMetaPropertyInfo *property_info, char ***out_to_free + +#define ARGS_SETTING_INIT_FCN \ + const NMMetaSettingInfoEditor *setting_info, NMSetting *setting, NMMetaAccessorSettingInitType init_type + +#define RETURN_UNSUPPORTED_GET_TYPE() \ + G_STMT_START { \ + if (!NM_IN_SET (get_type, \ + NM_META_ACCESSOR_GET_TYPE_PARSABLE, \ + NM_META_ACCESSOR_GET_TYPE_PRETTY)) { \ + nm_assert_not_reached (); \ + return NULL; \ + } \ + } G_STMT_END; + +#define RETURN_STR_TO_FREE(val) \ + G_STMT_START { \ + char *_val = (val); \ + return ((*(out_to_free)) = _val); \ + } G_STMT_END + +static gconstpointer +_get_fcn_nmc_with_default (ARGS_GET_FCN) +{ + const char *s; + char *s_full; + GValue val = G_VALUE_INIT; + + RETURN_UNSUPPORTED_GET_TYPE (); + + if (property_info->property_typ_data->subtype.get_with_default.fcn (setting)) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _("(default)"); + return ""; + } + + 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); + RETURN_STR_TO_FREE (s_full); +} + +static gconstpointer +_get_fcn_gobject_impl (const NMMetaPropertyInfo *property_info, + NMSetting *setting, + NMMetaAccessorGetType get_type, + gpointer *out_to_free) +{ + char *s; + const char *s_c; + GType gtype_prop; + nm_auto_unset_gvalue GValue val = G_VALUE_INIT; + + RETURN_UNSUPPORTED_GET_TYPE (); + + gtype_prop = _gobject_property_get_gtype (G_OBJECT (setting), property_info->property_name); + + if (gtype_prop == G_TYPE_BOOLEAN) { + gboolean b; + + g_value_init (&val, gtype_prop); + 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"); + else + s_c = b ? "yes" : "no"; + return s_c; + } else { + 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); + } +} + +static gconstpointer +_get_fcn_gobject (ARGS_GET_FCN) +{ + return _get_fcn_gobject_impl (property_info, setting, get_type, out_to_free); +} + +static gconstpointer +_get_fcn_gobject_int (ARGS_GET_FCN) +{ + const GParamSpec *pspec; + nm_auto_unset_gvalue GValue gval = G_VALUE_INIT; + gint64 v; + const NMMetaUtilsIntValueInfo *value_infos; + + RETURN_UNSUPPORTED_GET_TYPE (); + + 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); + + g_value_init (&gval, pspec->value_type); + g_object_get_property (G_OBJECT (setting), property_info->property_name, &gval); + switch (pspec->value_type) { + case G_TYPE_INT: + v = g_value_get_int (&gval); + break; + case G_TYPE_UINT: + v = g_value_get_uint (&gval); + break; + case G_TYPE_INT64: + v = g_value_get_int64 (&gval); + break; + default: + g_return_val_if_reached (NULL); + break; + } + + if ( get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY + && property_info->property_typ_data + && (value_infos = property_info->property_typ_data->subtype.gobject_int.value_infos)) { + for (; value_infos->nick; value_infos++) { + if (value_infos->value == v) { + RETURN_STR_TO_FREE (g_strdup_printf ("%lli (%s)", + (long long) v, + value_infos->nick)); + } + } + } + + RETURN_STR_TO_FREE (g_strdup_printf ("%"G_GINT64_FORMAT, v)); +} + +static gconstpointer +_get_fcn_gobject_mtu (ARGS_GET_FCN) +{ + guint32 mtu; + + RETURN_UNSUPPORTED_GET_TYPE (); + + if ( !property_info->property_typ_data + || !property_info->property_typ_data->subtype.mtu.get_fcn) + return _get_fcn_gobject_impl (property_info, setting, get_type, out_to_free); + + mtu = property_info->property_typ_data->subtype.mtu.get_fcn (setting); + if (mtu == 0) { + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _("auto"); + return "auto"; + } + RETURN_STR_TO_FREE (g_strdup_printf ("%u", (unsigned) mtu)); +} + +static gconstpointer +_get_fcn_gobject_secret_flags (ARGS_GET_FCN) +{ + guint v; + GValue val = G_VALUE_INIT; + + RETURN_UNSUPPORTED_GET_TYPE (); + + g_value_init (&val, G_TYPE_UINT); + g_object_get_property (G_OBJECT (setting), property_info->property_name, &val); + v = g_value_get_uint (&val); + g_value_unset (&val); + RETURN_STR_TO_FREE (secret_flags_to_string (v, get_type)); +} + +static gconstpointer +_get_fcn_gobject_enum (ARGS_GET_FCN) +{ + GType gtype = 0; + GType gtype_prop; + nm_auto_unref_gtypeclass GTypeClass *gtype_class = NULL; + nm_auto_unref_gtypeclass GTypeClass *gtype_prop_class = NULL; + gboolean has_gtype = FALSE; + nm_auto_unset_gvalue GValue gval = G_VALUE_INIT; + gint64 v; + gboolean format_numeric = FALSE; + gboolean format_numeric_hex = FALSE; + gboolean format_numeric_hex_unknown = FALSE; + gboolean format_text = FALSE; + gboolean format_text_l10n = FALSE; + gs_free char *s = NULL; + char s_numeric[64]; + + RETURN_UNSUPPORTED_GET_TYPE (); + + 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 (); + has_gtype = TRUE; + } + } + + if ( property_info->property_typ_data + && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY + && NM_FLAGS_ANY (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N)) { + format_numeric_hex = NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC_HEX); + format_numeric = format_numeric_hex || NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC); + format_text_l10n = NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT_L10N); + format_text = format_text_l10n || NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT); + } else if ( property_info->property_typ_data + && get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY + && NM_FLAGS_ANY (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT)) { + format_numeric_hex = NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC_HEX); + format_numeric = format_numeric && NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_NUMERIC); + format_text = NM_FLAGS_HAS (property_info->property_typ_data->typ_flags, NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT); + } else if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) { + /* by default, output in format "%u (%s)" (with hex for flags and l10n). */ + format_numeric = TRUE; + format_numeric_hex_unknown = TRUE; + format_text = TRUE; + format_text_l10n = TRUE; + } else { + /* by default, output only numeric (with hex for flags). */ + format_numeric = TRUE; + format_numeric_hex_unknown = TRUE; + } + + nm_assert (format_text || format_numeric); + + gtype_prop = _gobject_property_get_gtype (G_OBJECT (setting), property_info->property_name); + + g_value_init (&gval, gtype_prop); + + g_object_get_property (G_OBJECT (setting), property_info->property_name, &gval); + + if ( gtype_prop == G_TYPE_INT + || ( G_TYPE_IS_CLASSED (gtype_prop) + && G_IS_ENUM_CLASS ((gtype_prop_class ?: (gtype_prop_class = g_type_class_ref (gtype_prop)))))) { + if (gtype_prop == G_TYPE_INT) { + if (!has_gtype) + g_return_val_if_reached (NULL); + v = g_value_get_int (&gval); + } else + v = g_value_get_enum (&gval); + } else if ( gtype_prop == G_TYPE_UINT + || ( G_TYPE_IS_CLASSED (gtype_prop) + && G_IS_FLAGS_CLASS ((gtype_prop_class ?: (gtype_prop_class = g_type_class_ref (gtype_prop)))))) { + if (gtype_prop == G_TYPE_UINT) { + if (!has_gtype) + g_return_val_if_reached (NULL); + v = g_value_get_uint (&gval); + } else + v = g_value_get_flags (&gval); + } else + g_return_val_if_reached (NULL); + + if (!has_gtype) { + gtype = gtype_prop; + gtype_class = g_steal_pointer (>ype_prop_class); + } + + nm_assert (({ + nm_auto_unref_gtypeclass GTypeClass *t = NULL; + + ( G_TYPE_IS_CLASSED (gtype) + && (t = g_type_class_ref (gtype)) + && (G_IS_ENUM_CLASS (t) || G_IS_FLAGS_CLASS (t))); + })); + + if (format_numeric && !format_text) { + s = format_numeric_hex + || ( format_numeric_hex_unknown + && !G_IS_ENUM_CLASS (gtype_class ?: (gtype_class = g_type_class_ref (gtype)))) + ? g_strdup_printf ("0x%"G_GINT64_FORMAT, v) + : g_strdup_printf ("%"G_GINT64_FORMAT, v); + RETURN_STR_TO_FREE (g_steal_pointer (&s)); + } + + /* the gobject_enum.value_infos are currently ignored for the getter. They + * only declare additional aliases for the setter. */ + + s = nm_utils_enum_to_str (gtype, (int) v); + + if (!format_numeric) + RETURN_STR_TO_FREE (g_steal_pointer (&s)); + + if ( format_numeric_hex + || ( format_numeric_hex_unknown + && !G_IS_ENUM_CLASS (gtype_class ?: (gtype_class = g_type_class_ref (gtype))))) + nm_sprintf_buf (s_numeric, "0x%"G_GINT64_FORMAT, v); + else + nm_sprintf_buf (s_numeric, "%"G_GINT64_FORMAT, v); + + if (nm_streq0 (s, s_numeric)) + RETURN_STR_TO_FREE (g_steal_pointer (&s)); + + if (format_text_l10n) + RETURN_STR_TO_FREE (g_strdup_printf (_("%s (%s)"), s_numeric, s)); + else + RETURN_STR_TO_FREE (g_strdup_printf ("%s (%s)", s_numeric, s)); +} + +/*****************************************************************************/ + +static gboolean +_set_fcn_gobject_string (ARGS_SET_FCN) +{ + gs_free char *to_free = NULL; + + 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); + if (!value) + return FALSE; + } else if (property_info->property_typ_data->values_static) { + value = nmc_string_is_valid (value, + (const char **) property_info->property_typ_data->values_static, + error); + if (!value) + return FALSE; + } + } + g_object_set (setting, property_info->property_name, value, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_bool (ARGS_SET_FCN) +{ + gboolean val_bool; + + if (!nmc_string_to_bool (value, &val_bool, error)) + return FALSE; + + g_object_set (setting, property_info->property_name, val_bool, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_int (ARGS_SET_FCN) +{ + int errsv; + const GParamSpec *pspec; + nm_auto_unset_gvalue GValue gval = G_VALUE_INIT; + gint64 v = 0; + gboolean has_minmax = FALSE; + gint64 min = G_MININT64; + gint64 max = G_MAXINT64; + guint base = 10; + const NMMetaUtilsIntValueInfo *value_infos = NULL; + gboolean has_value = FALSE; + + 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; + } + + for (; value_infos->nick; value_infos++) { + if (nm_streq (value_infos->nick, vv)) { + v = value_infos->value; + has_value = TRUE; + break; + } + } + } + + if (property_info->property_typ_data->subtype.gobject_int.base > 0) + base = property_info->property_typ_data->subtype.gobject_int.base; + if ( property_info->property_typ_data->subtype.gobject_int.min + || property_info->property_typ_data->subtype.gobject_int.max) { + min = property_info->property_typ_data->subtype.gobject_int.min; + max = property_info->property_typ_data->subtype.gobject_int.max; + has_minmax = TRUE; + } + } + + 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); + switch (pspec->value_type) { + case G_TYPE_INT: + if (!has_minmax) { + const GParamSpecInt *p = (GParamSpecInt *) pspec; + + min = p->minimum; + max = p->maximum; + } + break; + case G_TYPE_UINT: + if (!has_minmax) { + const GParamSpecUInt *p = (GParamSpecUInt *) pspec; + + min = p->minimum; + max = p->maximum; + } + break; + case G_TYPE_INT64: + if (!has_minmax) { + const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec; + + min = p->minimum; + max = p->maximum; + } + break; + default: + g_return_val_if_reached (FALSE); + } + + if (!has_value) { + v = _nm_utils_ascii_str_to_int64 (value, base, min, max, 0); + + if ((errsv = errno) != 0) { + if (errsv == ERANGE) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' is out of range [%lli, %lli]"), + value, + (long long) min, + (long long) max); + } else { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' is not a valid number"), value); + } + return FALSE; + } + } + + g_value_init (&gval, pspec->value_type); + switch (pspec->value_type) { + case G_TYPE_INT: + g_value_set_int (&gval, v); + break; + case G_TYPE_UINT: + g_value_set_uint (&gval, v); + break; + case G_TYPE_INT64: + g_value_set_int64 (&gval, v); + break; + default: + nm_assert_not_reached (); + break; + } + + /* Validate the number according to the property spec */ + if (!nm_g_object_set_property (G_OBJECT (setting), + property_info->property_name, + &gval, + error)) + g_return_val_if_reached (FALSE); + + return TRUE; +} + +static gboolean +_set_fcn_gobject_mtu (ARGS_SET_FCN) +{ + nm_auto_unset_gvalue GValue gval = G_VALUE_INIT; + const GParamSpec *pspec; + gint64 v; + + if (nm_streq0 (value, "auto")) + value = "0"; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), + property_info->property_name); + if (!pspec || pspec->value_type != G_TYPE_UINT) + g_return_val_if_reached (FALSE); + + v = _nm_utils_ascii_str_to_int64 (value, 10, 0, G_MAXUINT32, -1); + if (v < 0) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("'%s' is out of range [0, %u]"), value, (unsigned) G_MAXUINT32); + return FALSE; + } + + g_value_init (&gval, pspec->value_type); + g_value_set_uint (&gval, v); + + if (!nm_g_object_set_property (G_OBJECT (setting), + property_info->property_name, + &gval, + error)) + g_return_val_if_reached (FALSE); + + return TRUE; +} + +static gboolean +_set_fcn_gobject_mac (ARGS_SET_FCN) +{ + NMMetaPropertyTypeMacMode mode; + gboolean valid; + + if (property_info->property_typ_data) + mode = property_info->property_typ_data->subtype.mac.mode; + else + mode = NM_META_PROPERTY_TYPE_MAC_MODE_DEFAULT; + + + if (mode == NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND) + valid = nm_utils_hwaddr_valid (value, INFINIBAND_ALEN); + else { + valid = nm_utils_hwaddr_valid (value, ETH_ALEN) + || ( mode == NM_META_PROPERTY_TYPE_MAC_MODE_CLONED + && NM_CLONED_MAC_IS_SPECIAL (value)); + } + + if (!valid) { + g_set_error (error, 1, 0, _("'%s' is not a valid Ethernet MAC"), value); + return FALSE; + } + + g_object_set (setting, property_info->property_name, value, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_secret_flags (ARGS_SET_FCN) +{ + char **strv = NULL, **iter; + unsigned long flags = 0, val_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + for (iter = strv; iter && *iter; iter++) { + if (!nmc_string_to_uint (*iter, TRUE, 0, ALL_SECRET_FLAGS, &val_int)) { + g_set_error (error, 1, 0, _("'%s' is not a valid flag number; use <0-%d>"), + *iter, ALL_SECRET_FLAGS); + g_strfreev (strv); + return FALSE; + } + flags += val_int; + } + g_strfreev (strv); + + /* Validate the flags number */ + if (flags > ALL_SECRET_FLAGS) { + flags = ALL_SECRET_FLAGS; + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_WARN, + N_("'%s' sum is higher than all flags => all flags set"), + value); + } + + g_object_set (setting, property_info->property_name, (guint) flags, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_enum (ARGS_SET_FCN) +{ + GType gtype = 0; + GType gtype_prop; + gboolean has_gtype = FALSE; + nm_auto_unset_gvalue GValue gval = G_VALUE_INIT; + nm_auto_unref_gtypeclass GTypeClass *gtype_class = NULL; + gboolean is_flags; + int v; + + 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 (); + has_gtype = TRUE; + } + } + + gtype_prop = _gobject_property_get_gtype (G_OBJECT (setting), property_info->property_name); + + if ( has_gtype + && NM_IN_SET (gtype_prop, + G_TYPE_INT, + G_TYPE_UINT) + && G_TYPE_IS_CLASSED (gtype) + && (gtype_class = g_type_class_ref (gtype)) + && ( (is_flags = G_IS_FLAGS_CLASS (gtype_class)) + || G_IS_ENUM_CLASS (gtype_class))) { + /* valid */ + } else if ( !has_gtype + && G_TYPE_IS_CLASSED (gtype_prop) + && (gtype_class = g_type_class_ref (gtype_prop)) + && ( (is_flags = G_IS_FLAGS_CLASS (gtype_class)) + || G_IS_ENUM_CLASS (gtype_class))) { + gtype = gtype_prop; + } else + g_return_val_if_reached (FALSE); + + if (!_nm_utils_enum_from_str_full (gtype, value, &v, NULL, + property_info->property_typ_data + ? property_info->property_typ_data->subtype.gobject_enum.value_infos + : NULL)) + goto fail; + + if ( property_info->property_typ_data + && property_info->property_typ_data->subtype.gobject_enum.pre_set_notify) { + property_info->property_typ_data->subtype.gobject_enum.pre_set_notify (property_info, + environment, + environment_user_data, + setting, + v); + } + + g_value_init (&gval, gtype_prop); + if (gtype_prop == G_TYPE_INT) + g_value_set_int (&gval, v); + else if (gtype_prop == G_TYPE_UINT) + g_value_set_uint (&gval, v); + else if (G_IS_ENUM_CLASS (gtype_class)) + g_value_set_enum (&gval, v); + else if (G_IS_FLAGS_CLASS (gtype_class)) + g_value_set_flags (&gval, v); + else + g_return_val_if_reached (FALSE); + + if (!nm_g_object_set_property (G_OBJECT (setting), property_info->property_name, &gval, NULL)) + goto fail; + + return TRUE; + +fail: + if (error) { + gs_free const char **valid_all = NULL; + gs_free const char *valid_str = NULL; + gboolean has_minmax = FALSE; + int min = G_MININT; + int max = G_MAXINT; + + if (property_info->property_typ_data) { + if ( property_info->property_typ_data->subtype.gobject_enum.min + || property_info->property_typ_data->subtype.gobject_enum.max) { + min = property_info->property_typ_data->subtype.gobject_enum.min; + max = property_info->property_typ_data->subtype.gobject_enum.max; + has_minmax = TRUE; + } + } + + if (!has_minmax && is_flags) { + min = 0; + max = (gint) G_MAXUINT; + } + + valid_all = nm_utils_enum_get_values (gtype, min, max); + valid_str = g_strjoinv (",", (char **) valid_all); + if (is_flags) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid option '%s', use a combination of [%s]"), + value, + valid_str); + } else { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid option '%s', use one of [%s]"), + value, + valid_str); + } + } + return FALSE; +} + +/*****************************************************************************/ + +static const char *const* +_values_fcn_gobject_enum (ARGS_VALUES_FCN) +{ + GType gtype = 0; + gboolean has_gtype = FALSE; + gboolean has_minmax = FALSE; + int min = G_MININT; + int max = G_MAXINT; + char **v, **w; + + if (property_info->property_typ_data) { + if ( property_info->property_typ_data->subtype.gobject_enum.min + || property_info->property_typ_data->subtype.gobject_enum.max) { + min = property_info->property_typ_data->subtype.gobject_enum.min; + max = property_info->property_typ_data->subtype.gobject_enum.max; + has_minmax = TRUE; + } + if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) { + gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype (); + has_gtype = TRUE; + } + } + + if (!has_gtype) { + gtype = _gtype_property_get_gtype (property_info->setting_info->general->get_setting_gtype (), + property_info->property_name); + } + + if ( !has_minmax + && G_TYPE_IS_CLASSED (gtype)) { + nm_auto_unref_gtypeclass GTypeClass *class = NULL; + + class = g_type_class_ref (gtype); + if (G_IS_FLAGS_CLASS (class)) { + min = 0; + max = (gint) G_MAXUINT; + } + } + + /* the gobject_enum.value_infos are currently ignored for the list of + * values. They only declare additional (hidden) aliases for the setter. */ + + v = (char **) nm_utils_enum_get_values (gtype, min, max); + if (v) { + for (w = v; *w; w++) + *w = g_strdup (*w); + } + return (const char *const*) (*out_to_free = v); +} + +/*****************************************************************************/ + +static const char *const* +_complete_fcn_gobject_bool (ARGS_COMPLETE_FCN) +{ + static const char *const v[] = { + "true", + "false", + "on", + "off", + "1", + "0", + "yes", + "no", + NULL, + }; + + if (!text || !text[0]) + return &v[6]; + return v; +} + +static const char *const* +_complete_fcn_gobject_devices (ARGS_COMPLETE_FCN) +{ + NMDevice *const*devices = NULL; + guint i, j; + guint len = 0; + char **ifnames; + + if ( environment + && environment->get_nm_devices) { + devices = environment->get_nm_devices (environment, + environment_user_data, + &len); + } + + if (len == 0) + return NULL; + + ifnames = g_new (char *, len + 1); + for (i = 0, j = 0; i < len; i++) { + const char *ifname; + + nm_assert (NM_IS_DEVICE (devices[i])); + + ifname = nm_device_get_iface (devices[i]); + if (ifname) + ifnames[j++] = g_strdup (ifname); + } + ifnames[j++] = NULL; + + *out_to_free = ifnames; + return (const char *const*) ifnames; +} + +/*****************************************************************************/ + +static char * +wep_key_type_to_string (NMWepKeyType type) +{ + switch (type) { + case NM_WEP_KEY_TYPE_KEY: + return g_strdup_printf (_("%d (key)"), type); + case NM_WEP_KEY_TYPE_PASSPHRASE: + return g_strdup_printf (_("%d (passphrase)"), type); + case NM_WEP_KEY_TYPE_UNKNOWN: + default: + return g_strdup_printf (_("%d (unknown)"), type); + } +} + +static char * +bytes_to_string (GBytes *bytes) +{ + const guint8 *data; + gsize len; + GString *cert = NULL; + int i; + + if (!bytes) + return NULL; + data = g_bytes_get_data (bytes, &len); + + cert = g_string_new (NULL); + for (i = 0; i < len; i++) + g_string_append_printf (cert, "%02X", data[i]); + + return g_string_free (cert, FALSE); +} + +static char * +vlan_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) +{ + GString *flag_str; + + if (get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf ("%u", flags); + + if (flags == 0) + return g_strdup (_("0 (NONE)")); + + flag_str = g_string_new (NULL); + g_string_printf (flag_str, "%d (", flags); + + if (flags & NM_VLAN_FLAG_REORDER_HEADERS) + g_string_append (flag_str, _("REORDER_HEADERS, ")); + if (flags & NM_VLAN_FLAG_GVRP) + g_string_append (flag_str, _("GVRP, ")); + if (flags & NM_VLAN_FLAG_LOOSE_BINDING) + g_string_append (flag_str, _("LOOSE_BINDING, ")); + if (flags & NM_VLAN_FLAG_MVRP) + g_string_append (flag_str, _("MVRP, ")); + + if (flag_str->str[flag_str->len-1] == '(') + g_string_append (flag_str, _("unknown")); + else + g_string_truncate (flag_str, flag_str->len-2); /* chop off trailing ', ' */ + + g_string_append_c (flag_str, ')'); + + 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 * +ip6_privacy_to_string (NMSettingIP6ConfigPrivacy ip6_privacy, NMMetaAccessorGetType get_type) +{ + if (get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf ("%d", ip6_privacy); + + switch (ip6_privacy) { + case NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED: + return g_strdup_printf (_("%d (disabled)"), ip6_privacy); + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR: + return g_strdup_printf (_("%d (enabled, prefer public IP)"), ip6_privacy); + case NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR: + return g_strdup_printf (_("%d (enabled, prefer temporary IP)"), ip6_privacy); + default: + return g_strdup_printf (_("%d (unknown)"), ip6_privacy); + } +} + +static char * +secret_flags_to_string (guint32 flags, NMMetaAccessorGetType get_type) +{ + GString *flag_str; + + if (get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) + return g_strdup_printf ("%u", flags); + + if (flags == 0) + return g_strdup (_("0 (none)")); + + flag_str = g_string_new (NULL); + g_string_printf (flag_str, "%u (", flags); + + if (flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED) + g_string_append (flag_str, _("agent-owned, ")); + if (flags & NM_SETTING_SECRET_FLAG_NOT_SAVED) + g_string_append (flag_str, _("not saved, ")); + if (flags & NM_SETTING_SECRET_FLAG_NOT_REQUIRED) + g_string_append (flag_str, _("not required, ")); + + if (flag_str->str[flag_str->len-1] == '(') + g_string_append (flag_str, _("unknown")); + else + g_string_truncate (flag_str, flag_str->len-2); /* chop off trailing ', ' */ + + g_string_append_c (flag_str, ')'); + + return g_string_free (flag_str, FALSE); +} + +static void +vpn_data_item (const char *key, const char *value, gpointer user_data) +{ + GString *ret_str = (GString *) user_data; + + if (ret_str->len != 0) + g_string_append (ret_str, ", "); + + 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) \ + { \ + char **strv = NULL, **iter; \ + const char *item; \ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); \ + strv = nmc_strsplit_set (value, " \t,", 0); \ + for (iter = strv; iter && *iter; iter++) { \ + if (!(item = nmc_string_is_valid (g_strstrip (*iter), valid_strv, error))) { \ + g_strfreev (strv); \ + return FALSE; \ + } \ + set_func (s_macro (setting), item); \ + } \ + g_strfreev (strv); \ + return TRUE; \ + } + +#define DEFINE_SETTER_OPTIONS(def_func, s_macro, s_type, add_func, valid_func1, valid_func2) \ + static gboolean \ + def_func (ARGS_SET_FCN) \ + { \ + char **strv = NULL, **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; \ + \ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); \ + \ + strv = nmc_strsplit_set (value, ",", 0); \ + for (iter = strv; iter && *iter; iter++) { \ + char *left = g_strstrip (*iter); \ + char *right = strchr (left, '='); \ + if (!right) { \ + g_set_error (error, 1, 0, _("'%s' is not valid; use <option>=<value>"), *iter); \ + g_strfreev (strv); \ + return FALSE; \ + } \ + *right++ = '\0'; \ + \ + if (valid_func1_p) { \ + const char **valid_options = valid_func1_p (s_macro (setting)); \ + if (!(opt_name = nmc_string_is_valid (g_strstrip (left), valid_options, error))) { \ + g_strfreev (strv); \ + return FALSE; \ + } \ + } else \ + opt_name = g_strstrip (left);\ + \ + opt_val = g_strstrip (right); \ + if (valid_func2_p) { \ + if (!(opt_val = valid_func2_p ((const char *) left, (const char *) opt_val, error))) { \ + g_strfreev (strv); \ + return FALSE; \ + }\ + }\ + add_func (s_macro (setting), opt_name, opt_val); \ + } \ + g_strfreev (strv); \ + return TRUE; \ + } + +#define DEFINE_REMOVER_INDEX_OR_VALUE(def_func, s_macro, num_func, rem_func_idx, rem_func_val) \ + static gboolean \ + def_func (ARGS_REMOVE_FCN) \ + { \ + guint32 num; \ + if (value) { \ + gboolean ret; \ + char *value_stripped = g_strstrip (g_strdup (value)); \ + ret = rem_func_val (s_macro (setting), value_stripped, error); \ + g_free (value_stripped); \ + return ret; \ + } \ + num = num_func (s_macro (setting)); \ + if (num == 0) { \ + g_set_error_literal (error, 1, 0, _("no item to remove")); \ + return FALSE; \ + } \ + if (idx >= num) { \ + g_set_error (error, 1, 0, _("index '%d' is not in range <0-%d>"), idx, num - 1); \ + return FALSE; \ + } \ + rem_func_idx (s_macro (setting), idx); \ + return TRUE; \ + } + +#define DEFINE_REMOVER_OPTION(def_func, s_macro, rem_func) \ + static gboolean \ + def_func (ARGS_REMOVE_FCN) \ + { \ + gboolean success = FALSE; \ + if (value && *value) { \ + success = rem_func (s_macro (setting), value); \ + if (!success) \ + g_set_error (error, 1, 0, _("invalid option '%s'"), value); \ + } else \ + g_set_error_literal (error, 1, 0, _("missing option")); \ + return success; \ + } + +#define DEFINE_ALLOWED_VAL_FUNC(def_func, valid_values) \ + static const char *const* \ + def_func (NMSetting *setting, const char *prop) \ + { \ + return valid_values; \ + } + +#define DEFINE_SETTER_MAC_BLACKLIST(def_func, s_macro, add_func) \ + static gboolean \ + def_func (ARGS_SET_FCN) \ + { \ + guint8 buf[32]; \ + char **list = NULL, **iter; \ + GSList *macaddr_blacklist = NULL; \ + \ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); \ + \ + list = nmc_strsplit_set (value, " \t,", 0); \ + for (iter = list; iter && *iter; iter++) { \ + if (!nm_utils_hwaddr_aton (*iter, buf, ETH_ALEN)) { \ + g_set_error (error, 1, 0, _("'%s' is not a valid MAC"), *iter); \ + g_strfreev (list); \ + g_slist_free (macaddr_blacklist); \ + return FALSE; \ + } \ + } \ + \ + for (iter = list; iter && *iter; iter++) \ + add_func (s_macro (setting), *iter); \ + \ + g_strfreev (list); \ + return TRUE; \ + } + + +static gboolean +verify_string_list (char **strv, + const char *prop, + gboolean (*validate_func) (const char *), + GError **error) +{ + char **iter; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + for (iter = strv; iter && *iter; iter++) { + if (**iter == '\0') + continue; + if (validate_func) { + if (!validate_func (*iter)) { + g_set_error (error, 1, 0, _("'%s' is not valid"), + *iter); + return FALSE; + } + } + } + return TRUE; +} + +static char * +flag_values_to_string (GFlagsValue *array, guint n) +{ + GString *str; + guint i; + + str = g_string_new (NULL); + for (i = 0; i < n; i++) + g_string_append_printf (str, "%u, ", array[i].value); + if (str->len) + g_string_truncate (str, str->len-2); /* chop off trailing ', ' */ + return g_string_free (str, FALSE); +} + +static gboolean +validate_flags (NMSetting *setting, const char* prop, guint val, GError **error) +{ + GParamSpec *pspec; + GValue value = G_VALUE_INIT; + gboolean success = TRUE; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), prop); + g_assert (G_IS_PARAM_SPEC (pspec)); + + g_value_init (&value, pspec->value_type); + g_value_set_flags (&value, val); + + if (g_param_value_validate (pspec, &value)) { + GParamSpecFlags *pspec_flags = (GParamSpecFlags *) pspec; + char *flag_values = flag_values_to_string (pspec_flags->flags_class->values, + pspec_flags->flags_class->n_values); + g_set_error (error, 1, 0, _("'%u' flags are not valid; use combination of %s"), + val, flag_values); + g_free (flag_values); + success = FALSE; + } + g_value_unset (&value); + return success; +} + +static gboolean +check_and_set_string (NMSetting *setting, + const char *prop, + const char *val, + const char **valid_strv, + GError **error) +{ + const char *checked_val; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + checked_val = nmc_string_is_valid (val, valid_strv, error); + if (!checked_val) + return FALSE; + + g_object_set (setting, prop, checked_val, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_flags (ARGS_SET_FCN) +{ + unsigned long val_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nmc_string_to_uint (value, TRUE, 0, G_MAXUINT, &val_int)) { + g_set_error (error, 1, 0, _("'%s' is not a valid number (or out of range)"), value); + return FALSE; + } + + /* Validate the flags according to the property spec */ + if (!validate_flags (setting, property_info->property_name, (guint) val_int, error)) + return FALSE; + + g_object_set (setting, property_info->property_name, (guint) val_int, NULL); + return TRUE; +} + +static gboolean +_set_fcn_gobject_ssid (ARGS_SET_FCN) +{ + GBytes *ssid; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (strlen (value) > 32) { + g_set_error (error, 1, 0, _("'%s' is not valid"), value); + return FALSE; + } + + ssid = g_bytes_new (value, strlen (value)); + g_object_set (setting, property_info->property_name, ssid, NULL); + g_bytes_unref (ssid); + return TRUE; +} + +static gboolean +_set_fcn_gobject_ifname (ARGS_SET_FCN) +{ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nm_utils_is_valid_iface_name (value, error)) + return FALSE; + g_object_set (setting, property_info->property_name, value, NULL); + return TRUE; +} + +static gboolean +_set_fcn_vpn_service_type (ARGS_SET_FCN) +{ + gs_free char *service_name = NULL; + + service_name = nm_vpn_plugin_info_list_find_service_type (nm_vpn_get_plugin_infos (), value); + g_object_set (setting, property_info->property_name, service_name ? : value, NULL); + return TRUE; +} + +static const char *const* +_complete_fcn_vpn_service_type (ARGS_COMPLETE_FCN) +{ + gsize i, j; + char **values; + + values = nm_vpn_plugin_info_list_get_service_types (nm_vpn_get_plugin_infos (), FALSE, TRUE); + if (!values) + return NULL; + + if (!text || !*text) { + /* If the prompt text is empty or contains no '.', + * filter out full names. */ + for (i = 0, j = 0; values[i]; i++) { + if (strchr (values[i], '.')) { + g_free (values[i]); + continue; + } + + if (i != j) + values[j] = values[i]; + j++; + } + if (j) + values[j++] = NULL; + else { + g_free (values); + values = NULL; + } + } + return (const char *const*) (*out_to_free = values); +} + +static gboolean +nmc_util_is_domain (const char *domain) +{ + //FIXME: implement + return TRUE; +} + +static gboolean +nmc_property_set_bytes (NMSetting *setting, const char *prop, const char *value, GError **error) +{ + gs_free char *val_strip = NULL; + gs_strfreev char **strv = NULL; + const char *delimiters = " \t,"; + char **iter; + GBytes *bytes; + GByteArray *array = NULL; + gboolean success = TRUE; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + val_strip = g_strstrip (g_strdup (value)); + + /* First try hex string in the format of AAbbCCDd */ + bytes = nm_utils_hexstr2bin (val_strip); + if (bytes) + goto done; + + /* Otherwise, consider the following format: AA b 0xCc D */ + strv = nmc_strsplit_set (val_strip, delimiters, 0); + array = g_byte_array_sized_new (g_strv_length (strv)); + for (iter = strv; iter && *iter; iter++) { + int v; + guint8 v8; + + v = _nm_utils_ascii_str_to_int64 (*iter, 16, 0, 255, -1); + if (v == -1) { + g_set_error (error, 1, 0, _("'%s' is not a valid hex character"), *iter); + g_byte_array_free (array, TRUE); + success = FALSE; + goto done; + } + v8 = v; + g_byte_array_append (array, &v8, 1); + } + bytes = g_byte_array_free_to_bytes (array); + +done: + if (success) + g_object_set (setting, prop, bytes, NULL); + + if (bytes) + g_bytes_unref (bytes); + + return success; +} + +/*****************************************************************************/ + +static gconstpointer +_get_fcn_802_1x_ca_cert (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *ca_cert_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_ca_cert_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + ca_cert_str = bytes_to_string (nm_setting_802_1x_get_ca_cert_blob (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + ca_cert_str = g_strdup (nm_setting_802_1x_get_ca_cert_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + ca_cert_str = g_strdup (nm_setting_802_1x_get_ca_cert_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (ca_cert_str); +} + +static gconstpointer +_get_fcn_802_1x_client_cert (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *cert_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_client_cert_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + cert_str = bytes_to_string (nm_setting_802_1x_get_client_cert_blob (s_8021X)); + else + return _get_text_hidden (get_type); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + cert_str = g_strdup (nm_setting_802_1x_get_client_cert_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + cert_str = g_strdup (nm_setting_802_1x_get_client_cert_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (cert_str); +} + +static gconstpointer +_get_fcn_802_1x_phase2_ca_cert (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *phase2_ca_cert_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_phase2_ca_cert_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + phase2_ca_cert_str = bytes_to_string (nm_setting_802_1x_get_phase2_ca_cert_blob (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + phase2_ca_cert_str = g_strdup (nm_setting_802_1x_get_phase2_ca_cert_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + phase2_ca_cert_str = g_strdup (nm_setting_802_1x_get_phase2_ca_cert_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (phase2_ca_cert_str); +} + +static gconstpointer +_get_fcn_802_1x_phase2_client_cert (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *cert_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_phase2_client_cert_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + cert_str = bytes_to_string (nm_setting_802_1x_get_phase2_client_cert_blob (s_8021X)); + else + return _get_text_hidden (get_type); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + cert_str = g_strdup (nm_setting_802_1x_get_phase2_client_cert_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + cert_str = g_strdup (nm_setting_802_1x_get_phase2_client_cert_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (cert_str); +} + +static gconstpointer +_get_fcn_802_1x_password_raw (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (bytes_to_string (nm_setting_802_1x_get_password_raw (s_8021X))); +} + +static gconstpointer +_get_fcn_802_1x_private_key (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *key_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_private_key_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + key_str = bytes_to_string (nm_setting_802_1x_get_private_key_blob (s_8021X)); + else + return _get_text_hidden (get_type); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + key_str = g_strdup (nm_setting_802_1x_get_private_key_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + key_str = g_strdup (nm_setting_802_1x_get_private_key_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (key_str); +} + +static gconstpointer +_get_fcn_802_1x_phase2_private_key (ARGS_GET_FCN) +{ + NMSetting8021x *s_8021X = NM_SETTING_802_1X (setting); + char *key_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_802_1x_get_phase2_private_key_scheme (s_8021X)) { + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + if (NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + key_str = bytes_to_string (nm_setting_802_1x_get_phase2_private_key_blob (s_8021X)); + else + return _get_text_hidden (get_type); + break; + case NM_SETTING_802_1X_CK_SCHEME_PATH: + key_str = g_strdup (nm_setting_802_1x_get_phase2_private_key_path (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_PKCS11: + key_str = g_strdup (nm_setting_802_1x_get_phase2_private_key_uri (s_8021X)); + break; + case NM_SETTING_802_1X_CK_SCHEME_UNKNOWN: + break; + } + + RETURN_STR_TO_FREE (key_str); +} + +#define DEFINE_SETTER_STR_LIST(def_func, set_func) \ + static gboolean \ + def_func (ARGS_SET_FCN) \ + { \ + char **strv = NULL; \ + guint i = 0; \ + \ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); \ + \ + strv = nmc_strsplit_set (value, " \t,", 0); \ + while (strv && strv[i]) \ + set_func (NM_SETTING_802_1X (setting), strv[i++]); \ + g_strfreev (strv); \ + return TRUE; \ + } + +#define DEFINE_SETTER_CERT(def_func, set_func) \ + static gboolean \ + def_func (ARGS_SET_FCN) \ + { \ + char *val_strip = g_strstrip (g_strdup (value)); \ + char *p = val_strip; \ + NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; \ + gboolean success; \ + \ + if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11)) == 0) \ + scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; \ + else if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0) \ + p += NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); \ + \ + success = set_func (NM_SETTING_802_1X (setting), p, scheme, NULL, error); \ + g_free (val_strip); \ + return success; \ + } + +#define DEFINE_SETTER_PRIV_KEY(def_func, pwd_func, set_func) \ + static gboolean \ + def_func (ARGS_SET_FCN) \ + { \ + char **strv = NULL; \ + char *val_strip = g_strstrip (g_strdup (value)); \ + char *p = val_strip; \ + const char *path, *password; \ + gs_free char *password_free = NULL; \ + NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; \ + gboolean success; \ + \ + if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PKCS11)) == 0) \ + scheme = NM_SETTING_802_1X_CK_SCHEME_PKCS11; \ + else if (strncmp (val_strip, NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH)) == 0) \ + p += NM_STRLEN (NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH); \ + \ + strv = nmc_strsplit_set (p, " \t,", 2); \ + path = strv[0]; \ + if (g_strv_length (strv) == 2) \ + password = strv[1]; \ + else \ + password = password_free = g_strdup (pwd_func (NM_SETTING_802_1X (setting))); \ + success = set_func (NM_SETTING_802_1X (setting), path, password, scheme, NULL, error); \ + g_free (val_strip); \ + g_strfreev (strv); \ + return success; \ + } + +DEFINE_SETTER_STR_LIST_MULTI (check_and_add_eap_method, + NM_SETTING_802_1X, + nm_setting_802_1x_add_eap_method) + +static gboolean +_set_fcn_802_1x_eap (ARGS_SET_FCN) +{ + return check_and_add_eap_method (setting, + property_info->property_name, + value, + (const char **) property_info->property_typ_data->values_static, + error); +} + +static gboolean +_validate_and_remove_eap_method (NMSetting8021x *setting, + const char *eap, + GError **error) +{ + gboolean ret; + + ret = nm_setting_802_1x_remove_eap_method_by_value (setting, eap); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain EAP method '%s'"), eap); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_802_1x_eap, + NM_SETTING_802_1X, + nm_setting_802_1x_get_num_eap_methods, + nm_setting_802_1x_remove_eap_method, + _validate_and_remove_eap_method) + +DEFINE_SETTER_CERT (_set_fcn_802_1x_ca_cert, nm_setting_802_1x_set_ca_cert) + +DEFINE_SETTER_STR_LIST (_set_fcn_802_1x_altsubject_matches, nm_setting_802_1x_add_altsubject_match) + +static gboolean +_validate_and_remove_altsubject_match (NMSetting8021x *setting, + const char *altsubject_match, + GError **error) +{ + gboolean ret; + + ret = nm_setting_802_1x_remove_altsubject_match_by_value (setting, altsubject_match); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain alternative subject match '%s'"), + altsubject_match); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_802_1x_altsubject_matches, + NM_SETTING_802_1X, + nm_setting_802_1x_get_num_altsubject_matches, + nm_setting_802_1x_remove_altsubject_match, + _validate_and_remove_altsubject_match) + +DEFINE_SETTER_CERT (_set_fcn_802_1x_client_cert, nm_setting_802_1x_set_client_cert) + +DEFINE_SETTER_CERT (_set_fcn_802_1x_phase2_ca_cert, nm_setting_802_1x_set_phase2_ca_cert) + +DEFINE_SETTER_STR_LIST (_set_fcn_802_1x_phase2_altsubject_matches, nm_setting_802_1x_add_phase2_altsubject_match) + +static gboolean +_validate_and_remove_phase2_altsubject_match (NMSetting8021x *setting, + const char *phase2_altsubject_match, + GError **error) +{ + gboolean ret; + + ret = nm_setting_802_1x_remove_phase2_altsubject_match_by_value (setting, phase2_altsubject_match); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain \"phase2\" alternative subject match '%s'"), + phase2_altsubject_match); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_802_1x_phase2_altsubject_matches, + NM_SETTING_802_1X, + nm_setting_802_1x_get_num_phase2_altsubject_matches, + nm_setting_802_1x_remove_phase2_altsubject_match, + _validate_and_remove_phase2_altsubject_match) + +DEFINE_SETTER_CERT (_set_fcn_802_1x_phase2_client_cert, nm_setting_802_1x_set_phase2_client_cert) + +DEFINE_SETTER_PRIV_KEY (_set_fcn_802_1x_private_key, + nm_setting_802_1x_get_private_key_password, + nm_setting_802_1x_set_private_key) + +DEFINE_SETTER_PRIV_KEY (_set_fcn_802_1x_phase2_private_key, + nm_setting_802_1x_get_phase2_private_key_password, + nm_setting_802_1x_set_phase2_private_key) + +static gboolean +_set_fcn_802_1x_password_raw (ARGS_SET_FCN) +{ + return nmc_property_set_bytes (setting, property_info->property_name, value, error); +} + +static gconstpointer +_get_fcn_bond_options (ARGS_GET_FCN) +{ + NMSettingBond *s_bond = NM_SETTING_BOND (setting); + GString *bond_options_s; + int i; + + RETURN_UNSUPPORTED_GET_TYPE (); + + bond_options_s = g_string_new (NULL); + for (i = 0; i < nm_setting_bond_get_num_options (s_bond); i++) { + const char *key, *value; + gs_free char *tmp_value = NULL; + char *p; + + nm_setting_bond_get_option (s_bond, i, &key, &value); + + if (nm_streq0 (key, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + value = tmp_value = g_strdup (value); + for (p = tmp_value; p && *p; p++) { + if (*p == ',') + *p = ' '; + } + } + + g_string_append_printf (bond_options_s, "%s=%s,", key, value); + } + g_string_truncate (bond_options_s, bond_options_s->len-1); /* chop off trailing ',' */ + + RETURN_STR_TO_FREE (g_string_free (bond_options_s, FALSE)); +} + +/* example: miimon=100,mode=balance-rr, updelay=5 */ +static gboolean +_validate_and_remove_bond_option (NMSettingBond *setting, const char *option) +{ + const char *opt; + const char **valid_options; + + valid_options = nm_setting_bond_get_valid_options (setting); + opt = nmc_string_is_valid (option, valid_options, NULL); + + if (opt) + return nm_setting_bond_remove_option (setting, opt); + else + return FALSE; +} + +static const char * +_validate_bond_option_value (const char *option, const char *value, GError **error) +{ + if (!g_strcmp0 (option, NM_SETTING_BOND_OPTION_MODE)) + return nmc_bond_validate_mode (value, error); + + return value; +} + +static gboolean +_bond_add_option (NMSettingBond *setting, + const char *name, + const char *value) +{ + gs_free char *tmp_value = NULL; + char *p; + + if (nm_streq0 (name, NM_SETTING_BOND_OPTION_ARP_IP_TARGET)) { + value = tmp_value = g_strdup (value); + for (p = tmp_value; p && *p; p++) + if (*p == ' ') + *p = ','; + } + + return nm_setting_bond_add_option (setting, name, value); +} + +DEFINE_SETTER_OPTIONS (_set_fcn_bond_options, + NM_SETTING_BOND, + NMSettingBond, + _bond_add_option, + nm_setting_bond_get_valid_options, + _validate_bond_option_value) +DEFINE_REMOVER_OPTION (_remove_fcn_bond_options, + NM_SETTING_BOND, + _validate_and_remove_bond_option) + +static const char * +_describe_fcn_bond_options (ARGS_DESCRIBE_FCN) +{ + gs_free char *options_str = NULL; + const char **valid_options; + char *s; + + valid_options = nm_setting_bond_get_valid_options (NULL); + options_str = g_strjoinv (", ", (char **) valid_options); + + s = g_strdup_printf (_("Enter a list of bonding options formatted as:\n" + " option = <value>, option = <value>,... \n" + "Valid options are: %s\n" + "'mode' can be provided as a name or a number:\n" + "balance-rr = 0\n" + "active-backup = 1\n" + "balance-xor = 2\n" + "broadcast = 3\n" + "802.3ad = 4\n" + "balance-tlb = 5\n" + "balance-alb = 6\n\n" + "Example: mode=2,miimon=120\n"), options_str); + return (*out_to_free = s); +} + +static const char *const* +_values_fcn_bond_options (ARGS_VALUES_FCN) +{ + return nm_setting_bond_get_valid_options (NULL); +} + +static gconstpointer +_get_fcn_connection_permissions (ARGS_GET_FCN) +{ + NMSettingConnection *s_con = NM_SETTING_CONNECTION (setting); + GString *perm = NULL; + const char *perm_item; + const char *perm_type; + int i; + + RETURN_UNSUPPORTED_GET_TYPE (); + + perm = g_string_new (NULL); + for (i = 0; i < nm_setting_connection_get_num_permissions (s_con); i++) { + if (nm_setting_connection_get_permission (s_con, i, &perm_type, &perm_item, NULL)) + g_string_append_printf (perm, "%s:%s,", perm_type, perm_item); + } + if (perm->len > 0) { + g_string_truncate (perm, perm->len-1); /* remove trailing , */ + RETURN_STR_TO_FREE (g_string_free (perm, FALSE)); + } + + /* No value from get_permission */ + g_string_free (perm, TRUE); + return NULL; +} + +static gboolean +_set_fcn_connection_type (ARGS_SET_FCN) +{ + gs_free char *uuid = NULL; + + if (nm_setting_connection_get_uuid (NM_SETTING_CONNECTION (setting))) { + /* Don't allow setting type unless the connection is brand new. + * Just because it's a bad idea and the user wouldn't probably want that. + * No technical reason, really. + * Also, using uuid to see if the connection is brand new is a bit + * hacky: we can not see if the type is already set, because + * nmc_setting_set_property() is called only after the property + * we're setting (type) has been removed. */ + g_set_error (error, 1, 0, _("Can not change the connection type")); + return FALSE; + } + + uuid = nm_utils_uuid_generate (); + g_object_set (G_OBJECT (setting), + NM_SETTING_CONNECTION_UUID, uuid, + NULL); + + g_object_set (G_OBJECT (setting), property_info->property_name, value, NULL); + return TRUE; +} + +static const char *const* +_complete_fcn_connection_type (ARGS_COMPLETE_FCN) +{ + guint i, j; + char **result; + gsize text_len; + + result = g_new (char *, _NM_META_SETTING_TYPE_NUM * 2 + 1); + + text_len = text ? strlen (text) : 0; + + for (i = 0, j = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + const NMMetaSettingInfoEditor *setting_info = &nm_meta_setting_infos_editor[i]; + const char *v; + + v = setting_info->alias; + if (v) { + if (!text || strncmp (text, v, text_len) == 0) + result[j++] = g_strdup (v); + } + if (!text || !*text || !v) { + v = setting_info->general->setting_name; + if (!text || strncmp (text, v, text_len) == 0) + result[j++] = g_strdup (v); + } + } + if (j) + result[j++] = NULL; + else { + g_free (result); + result = NULL; + } + + return (const char *const*) (*out_to_free = result); +} + +/* define from libnm-core/nm-setting-connection.c */ +#define PERM_USER_PREFIX "user:" + +static gboolean +permissions_valid (const char *perm) +{ + if (!perm || perm[0] == '\0') + return FALSE; + + if (strncmp (perm, PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0) { + if ( strlen (perm) <= strlen (PERM_USER_PREFIX) + || strchr (perm + strlen (PERM_USER_PREFIX), ':')) + return FALSE; + } else { + if (strchr (perm, ':')) + return FALSE; + } + + return TRUE; +} + +static gboolean +_set_fcn_connection_permissions (ARGS_SET_FCN) +{ + char **strv = NULL; + guint i = 0; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + if (!verify_string_list (strv, property_info->property_name, permissions_valid, error)) { + g_strfreev (strv); + return FALSE; + } + + for (i = 0; strv && strv[i]; i++) { + const char *user; + + if (strncmp (strv[i], PERM_USER_PREFIX, strlen (PERM_USER_PREFIX)) == 0) + user = strv[i]+strlen (PERM_USER_PREFIX); + else + user = strv[i]; + + nm_setting_connection_add_permission (NM_SETTING_CONNECTION (setting), "user", user, NULL); + } + + return TRUE; +} + +static gboolean +_validate_and_remove_connection_permission (NMSettingConnection *setting, + const char *perm, + GError **error) +{ + gboolean ret; + + ret = nm_setting_connection_remove_permission_by_value (setting, "user", perm, NULL); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain permission '%s'"), perm); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_connection_permissions, + NM_SETTING_CONNECTION, + nm_setting_connection_get_num_permissions, + nm_setting_connection_remove_permission, + _validate_and_remove_connection_permission) + +static gboolean +_set_fcn_connection_master (ARGS_SET_FCN) +{ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!value) + ; + else if (!*value) + value = NULL; + else if ( !nm_utils_is_valid_iface_name (value, NULL) + && !nm_utils_is_uuid (value)) { + g_set_error (error, 1, 0, + _("'%s' is not valid master; use ifname or connection UUID"), + value); + return FALSE; + } + g_object_set (setting, property_info->property_name, value, NULL); + return TRUE; +} + +static const char *const* +_complete_fcn_connection_master (ARGS_COMPLETE_FCN) +{ + NMRemoteConnection *const*connections = NULL; + guint len = 0; + guint i, j; + char **result; + NMSettingConnection *s_con; + const char *expected_type = NULL; + gsize text_len; + + if ( environment + && environment->get_nm_connections) { + connections = environment->get_nm_connections (environment, + environment_user_data, + &len); + } + if (!len) + return NULL; + + if ( (!text || !*text) + && operation_context + && operation_context->connection) { + /* if we have no text yet, initially only complete for matching + * slave-type. */ + s_con = nm_connection_get_setting_connection (operation_context->connection); + if (s_con) + expected_type = nm_setting_connection_get_slave_type (s_con); + } + + text_len = strlen (text); + + result = g_new (char *, (2 * len) + 1); + for (i = 0, j = 0; i < len; i++) { + const char *v; + + s_con = nm_connection_get_setting_connection (NM_CONNECTION (connections[i])); + if (!s_con) + continue; + + if ( expected_type + && !nm_streq0 (nm_setting_connection_get_connection_type (s_con), + expected_type)) + continue; + + if (text && text[0]) { + /* if we have text, also complete for the UUID. */ + v = nm_setting_connection_get_uuid (s_con); + if (v && (!text || strncmp (text, v, text_len) == 0)) + result[j++] = g_strdup (v); + } + + v = nm_setting_connection_get_interface_name (s_con); + if (v && (!text || strncmp (text, v, text_len) == 0)) + result[j++] = g_strdup (v); + } + if (j) + result[j++] = NULL; + else { + g_free (result); + result = NULL; + } + + return (const char *const*) (*out_to_free = result); +} + +static gboolean +_set_fcn_connection_secondaries (ARGS_SET_FCN) +{ + gs_strfreev char **strv = NULL; + char **iter; + + strv = nmc_strsplit_set (value, " \t,", 0); + if (strv) { + for (iter = strv; *iter; iter++) { + if (**iter) + nm_setting_connection_add_secondary (NM_SETTING_CONNECTION (setting), *iter); + } + } + return TRUE; +} + +static gboolean +_validate_and_remove_connection_secondary (NMSettingConnection *setting, + const char *secondary_uuid, + GError **error) +{ + gboolean ret; + + if (!nm_utils_is_uuid (secondary_uuid)) { + g_set_error (error, 1, 0, + _("the value '%s' is not a valid UUID"), secondary_uuid); + return FALSE; + } + + ret = nm_setting_connection_remove_secondary_by_value (setting, secondary_uuid); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain UUID '%s'"), secondary_uuid); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_connection_secondaries, + NM_SETTING_CONNECTION, + nm_setting_connection_get_num_secondaries, + nm_setting_connection_remove_secondary, + _validate_and_remove_connection_secondary) + +static gconstpointer +_get_fcn_connection_metered (ARGS_GET_FCN) +{ + NMSettingConnection *s_conn = NM_SETTING_CONNECTION (setting); + const char *s; + + RETURN_UNSUPPORTED_GET_TYPE (); + + switch (nm_setting_connection_get_metered (s_conn)) { + case NM_METERED_YES: + s = N_("yes"); + break; + case NM_METERED_NO: + s = N_("no"); + break; + case NM_METERED_UNKNOWN: + default: + s = N_("unknown"); + break; + } + if (get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY) + return _(s); + return s; +} + +static gboolean +_set_fcn_connection_metered (ARGS_SET_FCN) +{ + NMMetered metered; + NMCTriStateValue ts_val; + + if (!nmc_string_to_tristate (value, &ts_val, error)) + return FALSE; + + switch (ts_val) { + case NMC_TRI_STATE_YES: + metered = NM_METERED_YES; + break; + case NMC_TRI_STATE_NO: + metered = NM_METERED_NO; + break; + case NMC_TRI_STATE_UNKNOWN: + metered = NM_METERED_UNKNOWN; + break; + default: + g_assert_not_reached(); + } + + g_object_set (setting, property_info->property_name, metered, NULL); + return TRUE; +} + +static char * +dcb_flags_to_string (NMSettingDcbFlags flags) +{ + GString *flag_str; + + if (flags == 0) + return g_strdup (_("0 (disabled)")); + + flag_str = g_string_new (NULL); + g_string_printf (flag_str, "%d (", flags); + + if (flags & NM_SETTING_DCB_FLAG_ENABLE) + g_string_append (flag_str, _("enabled, ")); + if (flags & NM_SETTING_DCB_FLAG_ADVERTISE) + g_string_append (flag_str, _("advertise, ")); + if (flags & NM_SETTING_DCB_FLAG_WILLING) + g_string_append (flag_str, _("willing, ")); + + if (flag_str->str[flag_str->len-1] == '(') + g_string_append (flag_str, _("unknown")); + else + g_string_truncate (flag_str, flag_str->len-2); /* chop off trailing ', ' */ + + g_string_append_c (flag_str, ')'); + + return g_string_free (flag_str, FALSE); +} + +#define DEFINE_DCB_FLAGS_GETTER(func_name, property_name) \ + static gconstpointer \ + func_name (ARGS_GET_FCN) \ + { \ + guint v; \ + GValue val = G_VALUE_INIT; \ + \ + RETURN_UNSUPPORTED_GET_TYPE (); \ + g_value_init (&val, G_TYPE_UINT); \ + g_object_get_property (G_OBJECT (setting), property_name, &val); \ + v = g_value_get_uint (&val); \ + g_value_unset (&val); \ + RETURN_STR_TO_FREE (dcb_flags_to_string (v)); \ + } + +#define DEFINE_DCB_BOOL_GETTER(func_name, getter_func_name) \ + static gconstpointer \ + func_name (ARGS_GET_FCN) \ + { \ + NMSettingDcb *s_dcb = NM_SETTING_DCB (setting); \ + GString *str; \ + guint i; \ + \ + RETURN_UNSUPPORTED_GET_TYPE (); \ + \ + str = g_string_new (NULL); \ + for (i = 0; i < 8; i++) { \ + if (getter_func_name (s_dcb, i)) \ + g_string_append_c (str, '1'); \ + else \ + g_string_append_c (str, '0'); \ + if (i < 7) \ + g_string_append_c (str, ','); \ + } \ + \ + RETURN_STR_TO_FREE (g_string_free (str, FALSE)); \ + } + +#define DEFINE_DCB_UINT_GETTER(func_name, getter_func_name) \ + static gconstpointer \ + func_name (ARGS_GET_FCN) \ + { \ + NMSettingDcb *s_dcb = NM_SETTING_DCB (setting); \ + GString *str; \ + guint i; \ + \ + RETURN_UNSUPPORTED_GET_TYPE (); \ + \ + str = g_string_new (NULL); \ + for (i = 0; i < 8; i++) { \ + g_string_append_printf (str, "%u", getter_func_name (s_dcb, i)); \ + if (i < 7) \ + g_string_append_c (str, ','); \ + } \ + \ + RETURN_STR_TO_FREE (g_string_free (str, FALSE)); \ + } + +DEFINE_DCB_FLAGS_GETTER (_get_fcn_dcb_app_fcoe_flags, NM_SETTING_DCB_APP_FCOE_FLAGS) +DEFINE_DCB_FLAGS_GETTER (_get_fcn_dcb_app_iscsi_flags, NM_SETTING_DCB_APP_ISCSI_FLAGS) +DEFINE_DCB_FLAGS_GETTER (_get_fcn_dcb_app_fip_flags, NM_SETTING_DCB_APP_FIP_FLAGS) + +DEFINE_DCB_FLAGS_GETTER (_get_fcn_dcb_priority_flow_control_flags, NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS) +DEFINE_DCB_BOOL_GETTER (_get_fcn_dcb_priority_flow_control, nm_setting_dcb_get_priority_flow_control) + +DEFINE_DCB_FLAGS_GETTER (_get_fcn_dcb_priority_group_flags, NM_SETTING_DCB_PRIORITY_GROUP_FLAGS) +DEFINE_DCB_UINT_GETTER (_get_fcn_dcb_priority_group_id, nm_setting_dcb_get_priority_group_id) +DEFINE_DCB_UINT_GETTER (_get_fcn_dcb_priority_group_bandwidth, nm_setting_dcb_get_priority_group_bandwidth) +DEFINE_DCB_UINT_GETTER (_get_fcn_dcb_priority_bandwidth, nm_setting_dcb_get_priority_bandwidth) +DEFINE_DCB_BOOL_GETTER (_get_fcn_dcb_priority_strict, nm_setting_dcb_get_priority_strict_bandwidth) +DEFINE_DCB_UINT_GETTER (_get_fcn_dcb_priority_traffic_class, nm_setting_dcb_get_priority_traffic_class) + +#define DCB_ALL_FLAGS (NM_SETTING_DCB_FLAG_ENABLE | NM_SETTING_DCB_FLAG_ADVERTISE | NM_SETTING_DCB_FLAG_WILLING) + +static gboolean +_set_fcn_dcb_flags (ARGS_SET_FCN) +{ + char **strv = NULL, **iter; + NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE; + long int t; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* Check for overall hex numeric value */ + t = _nm_utils_ascii_str_to_int64 (value, 0, 0, DCB_ALL_FLAGS, -1); + if (t != -1) + flags = (guint) t; + else { + /* Check for individual flag numbers */ + strv = nmc_strsplit_set (value, " \t,", 0); + for (iter = strv; iter && *iter; iter++) { + t = _nm_utils_ascii_str_to_int64 (*iter, 0, 0, DCB_ALL_FLAGS, -1); + + if ( g_ascii_strcasecmp (*iter, "enable") == 0 + || g_ascii_strcasecmp (*iter, "enabled") == 0 + || t == NM_SETTING_DCB_FLAG_ENABLE) + flags |= NM_SETTING_DCB_FLAG_ENABLE; + else if ( g_ascii_strcasecmp (*iter, "advertise") == 0 + || t == NM_SETTING_DCB_FLAG_ADVERTISE) + flags |= NM_SETTING_DCB_FLAG_ADVERTISE; + else if ( g_ascii_strcasecmp (*iter, "willing") == 0 + || t == NM_SETTING_DCB_FLAG_WILLING) + flags |= NM_SETTING_DCB_FLAG_WILLING; + else if ( g_ascii_strcasecmp (*iter, "disable") == 0 + || g_ascii_strcasecmp (*iter, "disabled") == 0 + || t == 0) { + /* pass */ + } else { + g_set_error (error, 1, 0, _("'%s' is not a valid DCB flag"), *iter); + return FALSE; + } + } + g_strfreev (strv); + } + + /* Validate the flags according to the property spec */ + if (!validate_flags (setting, property_info->property_name, (guint) flags, error)) + return FALSE; + + g_object_set (setting, property_info->property_name, (guint) flags, NULL); + return TRUE; +} + +static gboolean +dcb_parse_uint_array (const char *val, + guint max, + guint other, + guint *out_array, + GError **error) +{ + gs_strfreev char **items = NULL; + char **iter; + gsize i; + + nm_assert (out_array); + + items = g_strsplit_set (val, ",", -1); + if (g_strv_length (items) != 8) { + g_set_error_literal (error, 1, 0, _("must contain 8 comma-separated numbers")); + return FALSE; + } + + i = 0; + for (iter = items; *iter; iter++) { + gint64 num; + + *iter = g_strstrip (*iter); + + num = _nm_utils_ascii_str_to_int64 (*iter, 10, 0, other ? other : max, -1); + + /* If number is greater than 'max' it must equal 'other' */ + if ( num == -1 + || (other && (num > max) && (num != other))) { + if (other) { + g_set_error (error, 1, 0, _("'%s' not a number between 0 and %u (inclusive) or %u"), + *iter, max, other); + } else { + g_set_error (error, 1, 0, _("'%s' not a number between 0 and %u (inclusive)"), + *iter, max); + } + return FALSE; + } + nm_assert (i < 8); + out_array[i++] = (guint) num; + } + + return TRUE; +} + +static void +dcb_check_feature_enabled (const NMMetaEnvironment *environment, gpointer *environment_user_data, NMSettingDcb *s_dcb, const char *flags_prop) +{ + NMSettingDcbFlags flags = NM_SETTING_DCB_FLAG_NONE; + + g_object_get (s_dcb, flags_prop, &flags, NULL); + if (!(flags & NM_SETTING_DCB_FLAG_ENABLE)) { + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_WARN, + N_("changes will have no effect until '%s' includes 1 (enabled)"), + flags_prop); + } +} + +static gboolean +_set_fcn_dcb_priority_flow_control (ARGS_SET_FCN) +{ + guint i = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 1, 0, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_flow_control (NM_SETTING_DCB (setting), i, !!nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_dcb_priority_group_id (ARGS_SET_FCN) +{ + guint i = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 7, 15, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_group_id (NM_SETTING_DCB (setting), i, nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_dcb_priority_group_bandwidth (ARGS_SET_FCN) +{ + guint i = 0, sum = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 100, 0, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + sum += nums[i]; + if (sum != 100) { + g_set_error_literal (error, 1, 0, _("bandwidth percentages must total 100%%")); + return FALSE; + } + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_group_bandwidth (NM_SETTING_DCB (setting), i, nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_dcb_priority_bandwidth (ARGS_SET_FCN) +{ + guint i = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 100, 0, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_bandwidth (NM_SETTING_DCB (setting), i, nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_dcb_priority_strict (ARGS_SET_FCN) +{ + guint i = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 1, 0, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_strict_bandwidth (NM_SETTING_DCB (setting), i, !!nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_dcb_priority_traffic_class (ARGS_SET_FCN) +{ + guint i = 0; + guint nums[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!dcb_parse_uint_array (value, 7, 0, nums, error)) + return FALSE; + + for (i = 0; i < 8; i++) + nm_setting_dcb_set_priority_traffic_class (NM_SETTING_DCB (setting), i, nums[i]); + + dcb_check_feature_enabled (environment, environment_user_data, NM_SETTING_DCB (setting), NM_SETTING_DCB_PRIORITY_GROUP_FLAGS); + return TRUE; +} + +static gboolean +_set_fcn_gsm_sim_operator_id (ARGS_SET_FCN) +{ + const char *p = value; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (strlen (value) != 5 && strlen (value) != 6) { + g_set_error_literal (error, 1, 0, _("SIM operator ID must be a 5 or 6 number MCCMNC code")); + return FALSE; + } + + while (p && *p) { + if (!g_ascii_isdigit (*p++)) { + g_set_error_literal (error, 1, 0, _("SIM operator ID must be a 5 or 6 number MCCMNC code")); + return FALSE; + } + } + g_object_set (G_OBJECT (setting), + NM_SETTING_GSM_SIM_OPERATOR_ID, + value, + NULL); + return TRUE; +} + +static gboolean +_set_fcn_infiniband_p_key (ARGS_SET_FCN) +{ + const gint64 INVALID = G_MININT64; + gint64 p_key; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (nm_streq (value, "default")) + p_key = -1; + else { + p_key = _nm_utils_ascii_str_to_int64 (value, 0, -1, G_MAXUINT16, INVALID); + if (p_key == INVALID) { + g_set_error (error, 1, 0, _("'%s' is not a valid IBoIP P_Key"), value); + return FALSE; + } + } + + g_object_set (setting, property_info->property_name, (int) p_key, NULL); + return TRUE; +} + + +static gconstpointer +_get_fcn_infiniband_p_key (ARGS_GET_FCN) +{ + NMSettingInfiniband *s_infiniband = NM_SETTING_INFINIBAND (setting); + int p_key; + + RETURN_UNSUPPORTED_GET_TYPE (); + + p_key = nm_setting_infiniband_get_p_key (s_infiniband); + if (p_key == -1) { + if (get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) + return "default"; + else + return _("default"); + } else + RETURN_STR_TO_FREE (g_strdup_printf ("0x%04x", p_key)); +} + +static gconstpointer +_get_fcn_ip_config_addresses (ARGS_GET_FCN) +{ + NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); + GString *printable; + guint32 num_addresses, i; + NMIPAddress *addr; + + RETURN_UNSUPPORTED_GET_TYPE (); + + printable = g_string_new (NULL); + + num_addresses = nm_setting_ip_config_get_num_addresses (s_ip); + for (i = 0; i < num_addresses; i++) { + addr = nm_setting_ip_config_get_address (s_ip, i); + + if (printable->len > 0) + g_string_append (printable, ", "); + + g_string_append_printf (printable, "%s/%u", + nm_ip_address_get_address (addr), + nm_ip_address_get_prefix (addr)); + } + + RETURN_STR_TO_FREE (g_string_free (printable, FALSE)); +} + +static gconstpointer +_get_fcn_ip_config_routes (ARGS_GET_FCN) +{ + NMSettingIPConfig *s_ip = NM_SETTING_IP_CONFIG (setting); + GString *printable; + guint32 num_routes, i; + NMIPRoute *route; + + RETURN_UNSUPPORTED_GET_TYPE (); + + printable = g_string_new (NULL); + + num_routes = nm_setting_ip_config_get_num_routes (s_ip); + for (i = 0; i < num_routes; i++) { + gs_free char *attr_str = NULL; + gs_strfreev char **attr_names = NULL; + gs_unref_hashtable GHashTable *hash = g_hash_table_new (nm_str_hash, g_str_equal); + int j; + + route = nm_setting_ip_config_get_route (s_ip, i); + + attr_names = nm_ip_route_get_attribute_names (route); + for (j = 0; attr_names && attr_names[j]; j++) { + g_hash_table_insert (hash, attr_names[j], + nm_ip_route_get_attribute (route, attr_names[j])); + } + + attr_str = nm_utils_format_variant_attributes (hash, ' ', '='); + + if (get_type != NM_META_ACCESSOR_GET_TYPE_PRETTY) { + if (printable->len > 0) + g_string_append (printable, ", "); + + g_string_append_printf (printable, "%s/%u", + nm_ip_route_get_dest (route), + nm_ip_route_get_prefix (route)); + + if (nm_ip_route_get_next_hop (route)) + g_string_append_printf (printable, " %s", nm_ip_route_get_next_hop (route)); + if (nm_ip_route_get_metric (route) != -1) + g_string_append_printf (printable, " %u", (guint32) nm_ip_route_get_metric (route)); + if (attr_str) + g_string_append_printf (printable, " %s", attr_str); + } else { + + if (printable->len > 0) + g_string_append (printable, "; "); + + g_string_append (printable, "{ "); + + g_string_append_printf (printable, "ip = %s/%u", + nm_ip_route_get_dest (route), + nm_ip_route_get_prefix (route)); + + if (nm_ip_route_get_next_hop (route)) { + g_string_append_printf (printable, ", nh = %s", + nm_ip_route_get_next_hop (route)); + } + + if (nm_ip_route_get_metric (route) != -1) + g_string_append_printf (printable, ", mt = %u", (guint32) nm_ip_route_get_metric (route)); + if (attr_str) + g_string_append_printf (printable, " %s", attr_str); + + g_string_append (printable, " }"); + } + } + + RETURN_STR_TO_FREE (g_string_free (printable, FALSE)); +} + +static const char *ipv4_valid_methods[] = { + NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NM_SETTING_IP4_CONFIG_METHOD_SHARED, + NM_SETTING_IP4_CONFIG_METHOD_DISABLED, + NULL +}; + +static gboolean +_set_fcn_ip4_config_method (ARGS_SET_FCN) +{ + /* Silently accept "static" and convert to "manual" */ + if (value && strlen (value) > 1 && matches (value, "static")) + value = NM_SETTING_IP4_CONFIG_METHOD_MANUAL; + + return check_and_set_string (setting, property_info->property_name, value, ipv4_valid_methods, error); +} + +static gboolean +_set_fcn_ip4_config_dns (ARGS_SET_FCN) +{ + char **strv = NULL, **iter, *addr; + guint32 ip4_addr; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + for (iter = strv; iter && *iter; iter++) { + addr = g_strstrip (*iter); + if (inet_pton (AF_INET, addr, &ip4_addr) < 1) { + g_set_error (error, 1, 0, _("invalid IPv4 address '%s'"), addr); + g_strfreev (strv); + return FALSE; + } + nm_setting_ip_config_add_dns (NM_SETTING_IP_CONFIG (setting), addr); + } + g_strfreev (strv); + return TRUE; +} + +static gboolean +_validate_and_remove_ipv4_dns (NMSettingIPConfig *setting, + const char *dns, + GError **error) +{ + guint32 ip4_addr; + gboolean ret; + + if (inet_pton (AF_INET, dns, &ip4_addr) < 1) { + g_set_error (error, 1, 0, _("invalid IPv4 address '%s'"), dns); + return FALSE; + } + + ret = nm_setting_ip_config_remove_dns_by_value (setting, dns); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain DNS server '%s'"), dns); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns, + nm_setting_ip_config_remove_dns, + _validate_and_remove_ipv4_dns) + +static gboolean +_set_fcn_ip4_config_dns_search (ARGS_SET_FCN) +{ + char **strv = NULL; + guint i = 0; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + if (!verify_string_list (strv, property_info->property_name, nmc_util_is_domain, error)) { + g_strfreev (strv); + return FALSE; + } + + while (strv && strv[i]) + nm_setting_ip_config_add_dns_search (NM_SETTING_IP_CONFIG (setting), strv[i++]); + g_strfreev (strv); + + return TRUE; +} + +static gboolean +_validate_and_remove_ipv4_dns_search (NMSettingIPConfig *setting, + const char *dns_search, + GError **error) +{ + gboolean ret; + + ret = nm_setting_ip_config_remove_dns_search_by_value (setting, dns_search); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain DNS search domain '%s'"), + dns_search); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns_search, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns_searches, + nm_setting_ip_config_remove_dns_search, + _validate_and_remove_ipv4_dns_search) + +static gboolean +_set_fcn_ip4_config_dns_options (ARGS_SET_FCN) +{ + char **strv = NULL; + guint i = 0; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + nm_setting_ip_config_clear_dns_options (NM_SETTING_IP_CONFIG (setting), TRUE); + strv = nmc_strsplit_set (value, " \t,", 0); + while (strv && strv[i]) + nm_setting_ip_config_add_dns_option (NM_SETTING_IP_CONFIG (setting), strv[i++]); + g_strfreev (strv); + + return TRUE; +} + +static gboolean +_validate_and_remove_ipv4_dns_option (NMSettingIPConfig *setting, + const char *dns_option, + GError **error) +{ + gboolean ret; + + ret = nm_setting_ip_config_remove_dns_option_by_value (setting, dns_option); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain DNS option '%s'"), + dns_option); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_dns_options, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns_options, + nm_setting_ip_config_remove_dns_option, + _validate_and_remove_ipv4_dns_option) + +static gboolean +_set_fcn_ip4_config_addresses (ARGS_SET_FCN) +{ + gs_strfreev char **strv = NULL; + const char *const*iter; + NMIPAddress *ip4addr; + + strv = nmc_strsplit_set (value, ",", 0); + for (iter = (const char *const*) strv; *iter; iter++) { + ip4addr = _parse_ip_address (AF_INET, *iter, error); + if (!ip4addr) + return FALSE; + nm_setting_ip_config_add_address (NM_SETTING_IP_CONFIG (setting), ip4addr); + nm_ip_address_unref (ip4addr); + } + return TRUE; +} + +static gboolean +_validate_and_remove_ipv4_address (NMSettingIPConfig *setting, + const char *address, + GError **error) +{ + NMIPAddress *ip4addr; + gboolean ret; + + ip4addr = _parse_ip_address (AF_INET, address, error); + if (!ip4addr) + return FALSE; + + ret = nm_setting_ip_config_remove_address_by_value (setting, ip4addr); + if (!ret) { + g_set_error (error, 1, 0, + _("the property doesn't contain IP address '%s'"), address); + } + nm_ip_address_unref (ip4addr); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_addresses, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_addresses, + nm_setting_ip_config_remove_address, + _validate_and_remove_ipv4_address) + +static gboolean +_set_fcn_ip4_config_gateway (ARGS_SET_FCN) +{ + gs_free char *addr = NULL; + + addr = g_strstrip (g_strdup (value)); + + if (!nm_utils_ipaddr_valid (AF_INET, addr)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid gateway address '%s'"), value); + return FALSE; + } + g_object_set (setting, property_info->property_name, addr, NULL); + return TRUE; +} + +static gboolean +_set_fcn_ip4_config_routes (ARGS_SET_FCN) +{ + gs_strfreev char **strv = NULL; + const char *const*iter; + NMIPRoute *ip4route; + + strv = nmc_strsplit_set (value, ",", 0); + for (iter = (const char *const*) strv; *iter; iter++) { + ip4route = _parse_ip_route (AF_INET, *iter, error); + if (!ip4route) + return FALSE; + nm_setting_ip_config_add_route (NM_SETTING_IP_CONFIG (setting), ip4route); + nm_ip_route_unref (ip4route); + } + return TRUE; +} + +static gboolean +_validate_and_remove_ipv4_route (NMSettingIPConfig *setting, + const char *route, + GError **error) +{ + NMIPRoute *ip4route; + gboolean ret; + + ip4route = _parse_ip_route (AF_INET, route, error); + if (!ip4route) + return FALSE; + + ret = nm_setting_ip_config_remove_route_by_value (setting, ip4route); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain route '%s'"), route); + nm_ip_route_unref (ip4route); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv4_config_routes, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_routes, + nm_setting_ip_config_remove_route, + _validate_and_remove_ipv4_route) + +static gconstpointer +_get_fcn_ip6_config_ip6_privacy (ARGS_GET_FCN) +{ + NMSettingIP6Config *s_ip6 = NM_SETTING_IP6_CONFIG (setting); + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (ip6_privacy_to_string (nm_setting_ip6_config_get_ip6_privacy (s_ip6), get_type)); +} + +static const char *ipv6_valid_methods[] = { + NM_SETTING_IP6_CONFIG_METHOD_IGNORE, + NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NM_SETTING_IP6_CONFIG_METHOD_DHCP, + NM_SETTING_IP6_CONFIG_METHOD_LINK_LOCAL, + NM_SETTING_IP6_CONFIG_METHOD_MANUAL, + NM_SETTING_IP6_CONFIG_METHOD_SHARED, + NULL +}; + +static gboolean +_set_fcn_ip6_config_method (ARGS_SET_FCN) +{ + /* Silently accept "static" and convert to "manual" */ + if (value && strlen (value) > 1 && matches (value, "static")) + value = NM_SETTING_IP6_CONFIG_METHOD_MANUAL; + + return check_and_set_string (setting, property_info->property_name, value, ipv6_valid_methods, error); +} + +static gboolean +_set_fcn_ip6_config_dns (ARGS_SET_FCN) +{ + char **strv = NULL, **iter, *addr; + struct in6_addr ip6_addr; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + for (iter = strv; iter && *iter; iter++) { + addr = g_strstrip (*iter); + if (inet_pton (AF_INET6, addr, &ip6_addr) < 1) { + g_set_error (error, 1, 0, _("invalid IPv6 address '%s'"), addr); + g_strfreev (strv); + return FALSE; + } + nm_setting_ip_config_add_dns (NM_SETTING_IP_CONFIG (setting), addr); + } + g_strfreev (strv); + return TRUE; +} + +static gboolean +_validate_and_remove_ipv6_dns (NMSettingIPConfig *setting, + const char *dns, + GError **error) +{ + struct in6_addr ip6_addr; + gboolean ret; + + if (inet_pton (AF_INET6, dns, &ip6_addr) < 1) { + g_set_error (error, 1, 0, _("invalid IPv6 address '%s'"), dns); + return FALSE; + } + + ret = nm_setting_ip_config_remove_dns_by_value (setting, dns); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain DNS server '%s'"), dns); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns, + nm_setting_ip_config_remove_dns, + _validate_and_remove_ipv6_dns) + +static gboolean +_set_fcn_ip6_config_dns_search (ARGS_SET_FCN) +{ + char **strv = NULL; + guint i = 0; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + strv = nmc_strsplit_set (value, " \t,", 0); + if (!verify_string_list (strv, property_info->property_name, nmc_util_is_domain, error)) { + g_strfreev (strv); + return FALSE; + } + + while (strv && strv[i]) + nm_setting_ip_config_add_dns_search (NM_SETTING_IP_CONFIG (setting), strv[i++]); + g_strfreev (strv); + + return TRUE; +} + +static gboolean +_validate_and_remove_ipv6_dns_search (NMSettingIPConfig *setting, + const char *dns_search, + GError **error) +{ + gboolean ret; + + ret = nm_setting_ip_config_remove_dns_search_by_value (setting, dns_search); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain DNS search domain '%s'"), + dns_search); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns_search, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns_searches, + nm_setting_ip_config_remove_dns_search, + _validate_and_remove_ipv6_dns_search) + +static gboolean +_set_fcn_ip6_config_dns_options (ARGS_SET_FCN) +{ + char **strv = NULL; + guint i = 0; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + nm_setting_ip_config_clear_dns_options (NM_SETTING_IP_CONFIG (setting), TRUE); + strv = nmc_strsplit_set (value, " \t,", 0); + while (strv && strv[i]) + nm_setting_ip_config_add_dns_option (NM_SETTING_IP_CONFIG (setting), strv[i++]); + g_strfreev (strv); + + return TRUE; +} + +static gboolean +_validate_and_remove_ipv6_dns_option (NMSettingIPConfig *setting, + const char *dns_option, + GError **error) +{ + gboolean ret; + + ret = nm_setting_ip_config_remove_dns_option_by_value (setting, dns_option); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain DNS option '%s'"), + dns_option); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_dns_options, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_dns_options, + nm_setting_ip_config_remove_dns_option, + _validate_and_remove_ipv6_dns_option) + +static gboolean +_set_fcn_ip6_config_addresses (ARGS_SET_FCN) +{ + gs_strfreev char **strv = NULL; + const char *const*iter; + NMIPAddress *ip6addr; + + strv = nmc_strsplit_set (value, ",", 0); + for (iter = (const char *const*) strv; *iter; iter++) { + ip6addr = _parse_ip_address (AF_INET6, *iter, error); + if (!ip6addr) + return FALSE; + nm_setting_ip_config_add_address (NM_SETTING_IP_CONFIG (setting), ip6addr); + nm_ip_address_unref (ip6addr); + } + return TRUE; +} + +static gboolean +_validate_and_remove_ipv6_address (NMSettingIPConfig *setting, + const char *address, + GError **error) +{ + NMIPAddress *ip6addr; + gboolean ret; + + ip6addr = _parse_ip_address (AF_INET6, address, error); + if (!ip6addr) + return FALSE; + + ret = nm_setting_ip_config_remove_address_by_value (setting, ip6addr); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain IP address '%s'"), address); + nm_ip_address_unref (ip6addr); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_addresses, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_addresses, + nm_setting_ip_config_remove_address, + _validate_and_remove_ipv6_address) + +static gboolean +_set_fcn_ip6_config_gateway (ARGS_SET_FCN) +{ + gs_free char *addr = NULL; + + addr = g_strstrip (g_strdup (value)); + + if (!nm_utils_ipaddr_valid (AF_INET6, addr)) { + g_set_error (error, NM_UTILS_ERROR, NM_UTILS_ERROR_INVALID_ARGUMENT, + _("invalid gateway address '%s'"), + addr); + return FALSE; + } + + g_object_set (setting, property_info->property_name, addr, NULL); + return TRUE; +} + +static gboolean +_set_fcn_ip6_config_routes (ARGS_SET_FCN) +{ + gs_strfreev char **strv = NULL; + const char *const*iter; + NMIPRoute *ip6route; + + strv = nmc_strsplit_set (value, ",", 0); + for (iter = (const char *const*) strv; *iter; iter++) { + ip6route = _parse_ip_route (AF_INET6, *iter, error); + if (!ip6route) + return FALSE; + nm_setting_ip_config_add_route (NM_SETTING_IP_CONFIG (setting), ip6route); + nm_ip_route_unref (ip6route); + } + return TRUE; +} + +static gboolean +_validate_and_remove_ipv6_route (NMSettingIPConfig *setting, + const char *route, + GError **error) +{ + NMIPRoute *ip6route; + gboolean ret; + + ip6route = _parse_ip_route (AF_INET6, route, error); + if (!ip6route) + return FALSE; + + ret = nm_setting_ip_config_remove_route_by_value (setting, ip6route); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain route '%s'"), route); + nm_ip_route_unref (ip6route); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_ipv6_config_routes, + NM_SETTING_IP_CONFIG, + nm_setting_ip_config_get_num_routes, + nm_setting_ip_config_remove_route, + _validate_and_remove_ipv6_route) + +static gboolean +_set_fcn_ip6_config_ip6_privacy (ARGS_SET_FCN) +{ + unsigned long val_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nmc_string_to_uint (value, FALSE, 0, 0, &val_int)) { + g_set_error (error, 1, 0, _("'%s' is not a number"), value); + return FALSE; + } + + if ( val_int != NM_SETTING_IP6_CONFIG_PRIVACY_DISABLED + && val_int != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR + && val_int != NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR) { + g_set_error (error, 1, 0, _("'%s' is not valid; use 0, 1, or 2"), value); + return FALSE; + } + + g_object_set (setting, property_info->property_name, val_int, NULL); + return TRUE; +} + +static gconstpointer +_get_fcn_olpc_mesh_ssid (ARGS_GET_FCN) +{ + NMSettingOlpcMesh *s_olpc_mesh = NM_SETTING_OLPC_MESH (setting); + GBytes *ssid; + char *ssid_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + ssid = nm_setting_olpc_mesh_get_ssid (s_olpc_mesh); + if (ssid) { + ssid_str = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), + g_bytes_get_size (ssid)); + } + + RETURN_STR_TO_FREE (ssid_str); +} + +static gboolean +_set_fcn_olpc_mesh_channel (ARGS_SET_FCN) +{ + unsigned long chan_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nmc_string_to_uint (value, TRUE, 1, 13, &chan_int)) { + g_set_error (error, 1, 0, _("'%s' is not a valid channel; use <1-13>"), value); + return FALSE; + } + g_object_set (setting, property_info->property_name, chan_int, NULL); + return TRUE; +} + +static const char * +_validate_fcn_proxy_pac_script (const char *value, char **out_to_free, GError **error) +{ + char *script = NULL; + + if (!nmc_proxy_check_script (value, &script, error)) + return NULL; + RETURN_STR_TO_FREE (script); +} + +static const char * +_validate_fcn_team_config (const char *value, char **out_to_free, GError **error) +{ + char *json = NULL; + + if (!nmc_team_check_config (value, &json, error)) + return NULL; + RETURN_STR_TO_FREE (json); +} + +static gconstpointer +_get_fcn_vlan_flags (ARGS_GET_FCN) +{ + NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting); + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (vlan_flags_to_string (nm_setting_vlan_get_flags (s_vlan), get_type)); +} + +static gconstpointer +_get_fcn_vlan_ingress_priority_map (ARGS_GET_FCN) +{ + NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting); + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (vlan_priorities_to_string (s_vlan, NM_VLAN_INGRESS_MAP)); +} + +static gconstpointer +_get_fcn_vlan_egress_priority_map (ARGS_GET_FCN) +{ + NMSettingVlan *s_vlan = NM_SETTING_VLAN (setting); + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (vlan_priorities_to_string (s_vlan, NM_VLAN_EGRESS_MAP)); +} + +static gboolean +_set_vlan_xgress_priority_map (NMSetting *setting, + const char *value, + NMVlanPriorityMap map_type, + GError **error) +{ + char **prio_map, **p; + + prio_map = _parse_vlan_priority_maps (value, map_type, error); + if (!prio_map) + return FALSE; + + for (p = prio_map; p && *p; p++) + nm_setting_vlan_add_priority_str (NM_SETTING_VLAN (setting), map_type, *p); + + g_strfreev (prio_map); + return TRUE; +} + +static gboolean +_set_fcn_vlan_ingress_priority_map (ARGS_SET_FCN) +{ + return _set_vlan_xgress_priority_map (setting, value, NM_VLAN_INGRESS_MAP, error); +} + +static gboolean +_set_fcn_vlan_egress_priority_map (ARGS_SET_FCN) +{ + return _set_vlan_xgress_priority_map (setting, value, NM_VLAN_EGRESS_MAP, error); +} + +static gboolean +_remove_vlan_xgress_priority_map (const NMMetaEnvironment *environment, + gpointer environment_user_data, + NMSetting *setting, + const NMMetaPropertyInfo *property_info, + const char *value, + guint32 idx, + NMVlanPriorityMap map_type, + GError **error) +{ + guint32 num; + + /* If value != NULL, remove by value */ + if (value) { + gboolean ret; + char **prio_map; + gs_free char *v = g_strdup (value); + + prio_map = _parse_vlan_priority_maps (v, map_type, error); + if (!prio_map) + return FALSE; + if (prio_map[1]) { + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_WARN, + N_("only one mapping at a time is supported; taking the first one (%s)"), + prio_map[0]); + } + ret = nm_setting_vlan_remove_priority_str_by_value (NM_SETTING_VLAN (setting), + map_type, + prio_map[0]); + + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain mapping '%s'"), prio_map[0]); + g_strfreev (prio_map); + return ret; + } + + /* Else remove by index */ + num = nm_setting_vlan_get_num_priorities (NM_SETTING_VLAN (setting), map_type); + if (num == 0) { + g_set_error_literal (error, 1, 0, _("no priority to remove")); + return FALSE; + } + if (idx >= num) { + g_set_error (error, 1, 0, _("index '%d' is not in the range of <0-%d>"), + idx, num - 1); + return FALSE; + } + + nm_setting_vlan_remove_priority (NM_SETTING_VLAN (setting), map_type, idx); + return TRUE; +} + +static gboolean +_remove_fcn_vlan_ingress_priority_map (ARGS_REMOVE_FCN) +{ + return _remove_vlan_xgress_priority_map (environment, + environment_user_data, + setting, + property_info, + value, + idx, + NM_VLAN_INGRESS_MAP, + error); +} + +static gboolean +_remove_fcn_vlan_egress_priority_map (ARGS_REMOVE_FCN) +{ + return _remove_vlan_xgress_priority_map (environment, + environment_user_data, + setting, + property_info, + value, + idx, + NM_VLAN_EGRESS_MAP, + error); +} + +static gconstpointer +_get_fcn_vpn_data (ARGS_GET_FCN) +{ + NMSettingVpn *s_vpn = NM_SETTING_VPN (setting); + GString *data_item_str; + + RETURN_UNSUPPORTED_GET_TYPE (); + + data_item_str = g_string_new (NULL); + nm_setting_vpn_foreach_data_item (s_vpn, &vpn_data_item, data_item_str); + + RETURN_STR_TO_FREE (g_string_free (data_item_str, FALSE)); +} + +static gconstpointer +_get_fcn_vpn_secrets (ARGS_GET_FCN) +{ + NMSettingVpn *s_vpn = NM_SETTING_VPN (setting); + GString *secret_str; + + RETURN_UNSUPPORTED_GET_TYPE (); + + secret_str = g_string_new (NULL); + nm_setting_vpn_foreach_secret (s_vpn, &vpn_data_item, secret_str); + + RETURN_STR_TO_FREE (g_string_free (secret_str, FALSE)); +} + +static const char * +_validate_vpn_hash_value (const char *option, const char *value, GError **error) +{ + /* nm_setting_vpn_add_data_item() and nm_setting_vpn_add_secret() does not + * allow empty strings */ + if (!value || !*value) { + g_set_error (error, 1, 0, _("'%s' cannot be empty"), option); + return NULL; + } + return value; +} + +DEFINE_SETTER_OPTIONS (_set_fcn_vpn_data, + NM_SETTING_VPN, + NMSettingVpn, + nm_setting_vpn_add_data_item, + NULL, + _validate_vpn_hash_value) +DEFINE_REMOVER_OPTION (_remove_fcn_vpn_data, + NM_SETTING_VPN, + nm_setting_vpn_remove_data_item) + +DEFINE_SETTER_OPTIONS (_set_fcn_vpn_secrets, + NM_SETTING_VPN, + NMSettingVpn, + nm_setting_vpn_add_secret, + NULL, + _validate_vpn_hash_value) +DEFINE_REMOVER_OPTION (_remove_fcn_vpn_secrets, + NM_SETTING_VPN, + nm_setting_vpn_remove_secret) + +DEFINE_SETTER_MAC_BLACKLIST (_set_fcn_wired_mac_address_blacklist, + NM_SETTING_WIRED, + nm_setting_wired_add_mac_blacklist_item) + +static gboolean +_validate_and_remove_wired_mac_blacklist_item (NMSettingWired *setting, + const char *mac, + GError **error) +{ + gboolean ret; + guint8 buf[32]; + + if (!nm_utils_hwaddr_aton (mac, buf, ETH_ALEN)) { + g_set_error (error, 1, 0, _("'%s' is not a valid MAC address"), mac); + return FALSE; + } + + ret = nm_setting_wired_remove_mac_blacklist_item_by_value (setting, mac); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain MAC address '%s'"), mac); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_wired_mac_address_blacklist, + NM_SETTING_WIRED, + nm_setting_wired_get_num_mac_blacklist_items, + nm_setting_wired_remove_mac_blacklist_item, + _validate_and_remove_wired_mac_blacklist_item) + +static gboolean +_set_fcn_wired_s390_subchannels (ARGS_SET_FCN) +{ + char **strv = NULL; + int len; + + strv = nmc_strsplit_set (value, " ,\t", 0); + len = g_strv_length (strv); + if (len != 2 && len != 3) { + g_set_error (error, 1, 0, _("'%s' is not valid; 2 or 3 strings should be provided"), + value); + g_strfreev (strv); + return FALSE; + } + + g_object_set (setting, property_info->property_name, strv, NULL); + g_strfreev (strv); + return TRUE; +} + +static const char * +_validate_s390_option_value (const char *option, const char *value, GError **error) +{ + /* nm_setting_wired_add_s390_option() requires value len in <1,199> interval */ + if (!value || !*value || strlen (value) >= 200) { + g_set_error (error, 1, 0, _("'%s' string value should consist of 1 - 199 characters"), option); + return NULL; + } + return value; +} +DEFINE_SETTER_OPTIONS (_set_fcn_wired_s390_options, + NM_SETTING_WIRED, + NMSettingWired, + nm_setting_wired_add_s390_option, + nm_setting_wired_get_valid_s390_options, + _validate_s390_option_value) +DEFINE_REMOVER_OPTION (_remove_fcn_wired_s390_options, + NM_SETTING_WIRED, + nm_setting_wired_remove_s390_option) + +static const char *const* +_values_fcn__wired_s390_options (ARGS_VALUES_FCN) +{ + return nm_setting_wired_get_valid_s390_options (NULL); +} + +static const char * +_describe_fcn_wired_s390_options (ARGS_DESCRIBE_FCN) +{ + gs_free char *options_str = NULL; + const char **valid_options; + char *s; + + valid_options = nm_setting_wired_get_valid_s390_options (NULL); + + options_str = g_strjoinv (", ", (char **) valid_options); + + s = g_strdup_printf (_("Enter a list of S/390 options formatted as:\n" + " option = <value>, option = <value>,...\n" + "Valid options are: %s\n"), + options_str); + return (*out_to_free = s); +} + + +static gconstpointer +_get_fcn_wireless_ssid (ARGS_GET_FCN) +{ + NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting); + GBytes *ssid; + char *ssid_str = NULL; + + RETURN_UNSUPPORTED_GET_TYPE (); + + ssid = nm_setting_wireless_get_ssid (s_wireless); + if (ssid) { + ssid_str = nm_utils_ssid_to_utf8 (g_bytes_get_data (ssid, NULL), + g_bytes_get_size (ssid)); + } + + RETURN_STR_TO_FREE (ssid_str); +} + +static gboolean +_set_fcn_wireless_channel (ARGS_SET_FCN) +{ + unsigned long chan_int; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + if (!nmc_string_to_uint (value, FALSE, 0, 0, &chan_int)) { + g_set_error (error, 1, 0, _("'%s' is not a valid channel"), value); + return FALSE; + } + + if ( !nm_utils_wifi_is_channel_valid (chan_int, "a") + && !nm_utils_wifi_is_channel_valid (chan_int, "bg")) { + g_set_error (error, 1, 0, _("'%ld' is not a valid channel"), chan_int); + return FALSE; + } + + g_object_set (setting, property_info->property_name, chan_int, NULL); + return TRUE; +} + +DEFINE_SETTER_MAC_BLACKLIST (_set_fcn_wireless_mac_address_blacklist, + NM_SETTING_WIRELESS, + nm_setting_wireless_add_mac_blacklist_item) + +static gboolean +_validate_and_remove_wifi_mac_blacklist_item (NMSettingWireless *setting, + const char *mac, + GError **error) +{ + gboolean ret; + guint8 buf[32]; + + if (!nm_utils_hwaddr_aton (mac, buf, ETH_ALEN)) { + g_set_error (error, 1, 0, _("'%s' is not a valid MAC address"), mac); + return FALSE; + } + + ret = nm_setting_wireless_remove_mac_blacklist_item_by_value (setting, mac); + if (!ret) + g_set_error (error, 1, 0, _("the property doesn't contain MAC address '%s'"), mac); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_wireless_mac_address_blacklist, + NM_SETTING_WIRELESS, + nm_setting_wireless_get_num_mac_blacklist_items, + nm_setting_wireless_remove_mac_blacklist_item, + _validate_and_remove_wifi_mac_blacklist_item) + +static gconstpointer +_get_fcn_wireless_security_wep_key0 (ARGS_GET_FCN) +{ + NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting); + + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 0))); +} + +static gconstpointer +_get_fcn_wireless_security_wep_key1 (ARGS_GET_FCN) +{ + NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting); + + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 1))); +} + +static gconstpointer +_get_fcn_wireless_security_wep_key2 (ARGS_GET_FCN) +{ + NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting); + + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 2))); +} + +static gconstpointer +_get_fcn_wireless_security_wep_key3 (ARGS_GET_FCN) +{ + NMSettingWirelessSecurity *s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (setting); + + RETURN_UNSUPPORTED_GET_TYPE (); + RETURN_STR_TO_FREE (g_strdup (nm_setting_wireless_security_get_wep_key (s_wireless_sec, 3))); +} + +static const char *wifi_sec_valid_protos[] = { "wpa", "rsn", NULL }; + +DEFINE_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_proto, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_add_proto) + +static gboolean +_set_fcn_wireless_security_proto (ARGS_SET_FCN) +{ + return check_and_add_wifi_sec_proto (setting, property_info->property_name, value, wifi_sec_valid_protos, error); +} + +static gboolean +_validate_and_remove_wifi_sec_proto (NMSettingWirelessSecurity *setting, + const char *proto, + GError **error) +{ + gboolean ret; + const char *valid; + + valid = nmc_string_is_valid (proto, wifi_sec_valid_protos, error); + if (!valid) + return FALSE; + + ret = nm_setting_wireless_security_remove_proto_by_value (setting, proto); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain protocol '%s'"), proto); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_wireless_security_proto, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_get_num_protos, + nm_setting_wireless_security_remove_proto, + _validate_and_remove_wifi_sec_proto) + +static const char *wifi_sec_valid_pairwises[] = { "tkip", "ccmp", NULL }; + +DEFINE_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_pairwise, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_add_pairwise) + +static gboolean +_set_fcn_wireless_security_pairwise (ARGS_SET_FCN) +{ + return check_and_add_wifi_sec_pairwise (setting, property_info->property_name, value, wifi_sec_valid_pairwises, error); +} + +static gboolean +_validate_and_remove_wifi_sec_pairwise (NMSettingWirelessSecurity *setting, + const char *pairwise, + GError **error) +{ + gboolean ret; + const char *valid; + + valid = nmc_string_is_valid (pairwise, wifi_sec_valid_pairwises, error); + if (!valid) + return FALSE; + + ret = nm_setting_wireless_security_remove_pairwise_by_value (setting, pairwise); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain protocol '%s'"), pairwise); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_wireless_security_pairwise, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_get_num_pairwise, + nm_setting_wireless_security_remove_pairwise, + _validate_and_remove_wifi_sec_pairwise) + +static const char *wifi_sec_valid_groups[] = { "wep40", "wep104", "tkip", "ccmp", NULL }; + +DEFINE_SETTER_STR_LIST_MULTI (check_and_add_wifi_sec_group, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_add_group) + +static gboolean +_set_fcn_wireless_security_group (ARGS_SET_FCN) +{ + return check_and_add_wifi_sec_group (setting, property_info->property_name, value, wifi_sec_valid_groups, error); +} + +static gboolean +_validate_and_remove_wifi_sec_group (NMSettingWirelessSecurity *setting, + const char *group, + GError **error) +{ + gboolean ret; + const char *valid; + + valid = nmc_string_is_valid (group, wifi_sec_valid_groups, error); + if (!valid) + return FALSE; + + ret = nm_setting_wireless_security_remove_group_by_value (setting, group); + if (!ret) + g_set_error (error, 1, 0, + _("the property doesn't contain protocol '%s'"), group); + return ret; +} +DEFINE_REMOVER_INDEX_OR_VALUE (_remove_fcn_wireless_security_group, + NM_SETTING_WIRELESS_SECURITY, + nm_setting_wireless_security_get_num_groups, + nm_setting_wireless_security_remove_group, + _validate_and_remove_wifi_sec_group) + +static gboolean +_set_fcn_wireless_wep_key (ARGS_SET_FCN) +{ + NMWepKeyType guessed_type = NM_WEP_KEY_TYPE_UNKNOWN; + NMWepKeyType type; + guint32 prev_idx, idx; + + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* Get currently set type */ + type = nm_setting_wireless_security_get_wep_key_type (NM_SETTING_WIRELESS_SECURITY (setting)); + + /* Guess key type */ + if (nm_utils_wep_key_valid (value, NM_WEP_KEY_TYPE_KEY)) + guessed_type = NM_WEP_KEY_TYPE_KEY; + else if (nm_utils_wep_key_valid (value, NM_WEP_KEY_TYPE_PASSPHRASE)) + guessed_type = NM_WEP_KEY_TYPE_PASSPHRASE; + + if (guessed_type == NM_WEP_KEY_TYPE_UNKNOWN) { + g_set_error (error, 1, 0, _("'%s' is not valid"), value); + return FALSE; + } + + if (type != NM_WEP_KEY_TYPE_UNKNOWN && type != guessed_type) { + if (nm_utils_wep_key_valid (value, type)) + guessed_type = type; + else { + g_set_error (error, 1, 0, + _("'%s' not compatible with %s '%s', please change the key or set the right %s first."), + value, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, wep_key_type_to_string (type), + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE); + return FALSE; + } + } + prev_idx = nm_setting_wireless_security_get_wep_tx_keyidx (NM_SETTING_WIRELESS_SECURITY (setting)); + idx = property_info->property_name[strlen (property_info->property_name) - 1] - '0'; + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_INFO, + N_("WEP key is guessed to be of '%s'"), + wep_key_type_to_string (guessed_type)); + if (idx != prev_idx) { + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_INFO, + N_("WEP key index set to '%d'"), + idx); + } + + g_object_set (setting, property_info->property_name, value, NULL); + g_object_set (setting, NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, guessed_type, NULL); + if (idx != prev_idx) + g_object_set (setting, NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, idx, NULL); + return TRUE; +} + +static void +_gobject_enum_pre_set_notify_fcn_wireless_security_wep_key_type (const NMMetaPropertyInfo *property_info, + const NMMetaEnvironment *environment, + gpointer environment_user_data, + NMSetting *setting, + int value) +{ + guint i; + const char *key; + const char *keynames[] = { + NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, + }; + + /* Check type compatibility with set keys */ + if (!NM_IN_SET (value, + NM_WEP_KEY_TYPE_UNKNOWN, + NM_WEP_KEY_TYPE_KEY, + NM_WEP_KEY_TYPE_PASSPHRASE)) + return; + + for (i = 0; i < 4; i++) { + key = nm_setting_wireless_security_get_wep_key (NM_SETTING_WIRELESS_SECURITY (setting), i); + if (key && !nm_utils_wep_key_valid (key, value)) { + _env_warn_fcn (environment, environment_user_data, + NM_META_ENV_WARN_LEVEL_WARN, + N_("'%s' is not compatible with '%s' type, please change or delete the key."), + keynames[i], wep_key_type_to_string (value)); + } + } +} + +static const char * +_validate_fcn_wireless_security_psk (const char *value, char **out_to_free, GError **error) +{ + if (!nm_utils_wpa_psk_valid (value)) { + g_set_error (error, 1, 0, _("'%s' is not a valid PSK"), value); + return NULL; + } + return value; +} + +/*****************************************************************************/ + +static const NMMetaPropertyInfo property_info_BOND_OPTIONS; + +#define NESTED_PROPERTY_INFO_BOND(...) \ + .parent_info = &property_info_BOND_OPTIONS, \ + .base = { \ + .meta_type = &nm_meta_type_nested_property_info, \ + .setting_info = &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_BOND], \ + __VA_ARGS__ \ + } + +static const NMMetaNestedPropertyInfo meta_nested_property_infos_bond[] = { + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "mode", + .prompt = NM_META_TEXT_PROMPT_BOND_MODE, + .def_hint = "[balance-rr]", + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "primary", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding primary interface [none]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + /* this is a virtual property, only needed during "ask" mode. */ + .prompt = N_("Bonding monitoring mode"), + .def_hint = NM_META_TEXT_PROMPT_BOND_MON_MODE_CHOICES, + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "miimon", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding miimon [100]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "downdelay", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding downdelay [0]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "updelay", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding updelay [0]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "arp-interval", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding arp-interval [0]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "arp-ip-target", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("Bonding arp-ip-target [none]"), + ) + }, + { + NESTED_PROPERTY_INFO_BOND ( + .property_name = NM_SETTING_BOND_OPTIONS, + .property_alias = "lacp-rate", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = N_("LACP rate ('slow' or 'fast') [slow]"), + ) + }, +}; + +const NMMetaPropertyTypDataNested nm_meta_property_typ_data_bond = { + .nested = meta_nested_property_infos_bond, + .nested_len = G_N_ELEMENTS (meta_nested_property_infos_bond), +}; + +/*****************************************************************************/ + +#define DEFINE_PROPERTY_TYPE(...) \ + (&((NMMetaPropertyType) { __VA_ARGS__ } )) + +#define DEFINE_PROPERTY_TYP_DATA(...) \ + (&((NMMetaPropertyTypData) { __VA_ARGS__ } )) + +#define PROPERTY_TYP_DATA_SUBTYPE(stype, ...) \ + .subtype = { \ + .stype = { __VA_ARGS__ }, \ + } + +#define DEFINE_PROPERTY_TYP_DATA_SUBTYPE(stype, ...) \ + DEFINE_PROPERTY_TYP_DATA ( \ + PROPERTY_TYP_DATA_SUBTYPE (stype, __VA_ARGS__), \ + ) + +static const NMMetaPropertyType _pt_gobject_readonly = { + .get_fcn = _get_fcn_gobject, +}; + +static const NMMetaPropertyType _pt_gobject_string = { + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_string, +}; + +static const NMMetaPropertyType _pt_gobject_bool = { + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_bool, + .complete_fcn = _complete_fcn_gobject_bool, +}; + +static const NMMetaPropertyType _pt_gobject_int = { + .get_fcn = _get_fcn_gobject_int, + .set_fcn = _set_fcn_gobject_int, +}; + +static const NMMetaPropertyType _pt_gobject_mtu = { + .get_fcn = _get_fcn_gobject_mtu, + .set_fcn = _set_fcn_gobject_mtu, +}; + +static const NMMetaPropertyType _pt_gobject_mac = { + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_mac, +}; + +static const NMMetaPropertyType _pt_gobject_secret_flags = { + .get_fcn = _get_fcn_gobject_secret_flags, + .set_fcn = _set_fcn_gobject_secret_flags, +}; + +static const NMMetaPropertyType _pt_gobject_enum = { + .get_fcn = _get_fcn_gobject_enum, + .set_fcn = _set_fcn_gobject_enum, + .values_fcn = _values_fcn_gobject_enum, +}; + +static const NMMetaPropertyType _pt_gobject_devices = { + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_string, + .complete_fcn = _complete_fcn_gobject_devices, +}; + +/*****************************************************************************/ + +#include "settings-docs.c" + +/*****************************************************************************/ + +#define PROPERTY_INFO_INIT(name, doc, ...) \ + { \ + .meta_type = &nm_meta_type_property_info, \ + .setting_info = &nm_meta_setting_infos_editor[_CURRENT_NM_META_SETTING_TYPE], \ + .property_name = name, \ + .describe_doc = doc, \ + __VA_ARGS__ \ + } + +#define PROPERTY_INFO(name, doc, ...) \ + (&((const NMMetaPropertyInfo) PROPERTY_INFO_INIT (name, doc, __VA_ARGS__))) + +#define PROPERTY_INFO_WITH_DESC(name, ...) \ + PROPERTY_INFO (name, DESCRIBE_DOC_##name, ##__VA_ARGS__) + +#define VALUES_STATIC(...) (((const char *[]) { __VA_ARGS__, NULL })) + +#define ENUM_VALUE_INFOS(...) (((const NMUtilsEnumValueInfo []) { __VA_ARGS__, { 0 } })) +#define INT_VALUE_INFOS(...) (((const NMMetaUtilsIntValueInfo []) { __VA_ARGS__, { 0 } })) + +#define GET_FCN_WITH_DEFAULT(type, func) \ + /* macro that returns @func as const (gboolean(*)(NMSetting*)) type, but checks + * that the actual type is (gboolean(*)(type *)). */ \ + ((gboolean (*) (NMSetting *)) ((sizeof (func == ((gboolean (*) (type *)) func))) ? func : func) ) + +#define MTU_GET_FCN(type, func) \ + /* macro that returns @func as const (guint32(*)(NMSetting*)) type, but checks + * that the actual type is (guint32(*)(type *)). */ \ + ((guint32 (*) (NMSetting *)) ((sizeof (func == ((guint32 (*) (type *)) func))) ? func : func) ) + +#define TEAM_DESCRIBE_MESSAGE \ + N_("nmcli can accepts both direct JSON configuration data and a file name containing " \ + "the configuration. In the latter case the file is read and the contents is put " \ + "into this property.\n\n" \ + "Examples: set team.config " \ + "{ \"device\": \"team0\", \"runner\": {\"name\": \"roundrobin\"}, \"ports\": {\"eth1\": {}, \"eth2\": {}} }\n" \ + " set team.config /etc/my-team.conf\n") + +#define DEFINE_DCB_PROPRITY_PROPERTY_TYPE \ + .property_type = &_pt_gobject_int, \ + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, \ + .value_infos = INT_VALUE_INFOS ( \ + { \ + .value = -1, \ + .nick = "unset", \ + } \ + ), \ + ), + +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_802_1X +static const NMMetaPropertyInfo *const property_infos_802_1X[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_EAP, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_802_1x_eap, + .remove_fcn = _remove_fcn_802_1x_eap, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("leap", "md5", "tls", "peap", "ttls", "sim", "fast", "pwd"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_IDENTITY, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_ANONYMOUS_IDENTITY, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PAC_FILE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CA_CERT, + .describe_message = + N_("Enter file path to CA certificate (optionally prefixed with file://).\n" + " [file://]<file path>\n" + "Note that nmcli does not support specifying certificates as raw blob data.\n" + "Example: /home/cimrman/cacert.crt\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_ca_cert, + .set_fcn = _set_fcn_802_1x_ca_cert, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CA_CERT_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CA_CERT_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CA_PATH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_SUBJECT_MATCH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_ALTSUBJECT_MATCHES, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_802_1x_altsubject_matches, + .remove_fcn = _remove_fcn_802_1x_altsubject_matches, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_DOMAIN_SUFFIX_MATCH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CLIENT_CERT, + .describe_message = + N_("Enter file path to client certificate (optionally prefixed with file://).\n" + " [file://]<file path>\n" + "Note that nmcli does not support specifying certificates as raw blob data.\n" + "Example: /home/cimrman/jara.crt\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_client_cert, + .set_fcn = _set_fcn_802_1x_client_cert, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_CLIENT_CERT_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_PEAPVER, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("0", "1"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_PEAPLABEL, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("0", "1"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_FAST_PROVISIONING, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("0", "1", "2", "3"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE1_AUTH_FLAGS, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_802_1x_auth_flags_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_AUTH, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("pap", "chap", "mschap", "mschapv2", "gtc", "otp", "md5", "tls"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_AUTHEAP, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("md5", "mschapv2", "otp", "gtc", "tls"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CA_CERT, + .describe_message = + N_("Enter file path to CA certificate for inner authentication (optionally prefixed\n" + "with file://).\n" + " [file://]<file path>\n" + "Note that nmcli does not support specifying certificates as raw blob data.\n" + "Example: /home/cimrman/ca-zweite-phase.crt\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_phase2_ca_cert, + .set_fcn = _set_fcn_802_1x_phase2_ca_cert, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CA_CERT_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CA_PATH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_SUBJECT_MATCH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_ALTSUBJECT_MATCHES, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_802_1x_phase2_altsubject_matches, + .remove_fcn = _remove_fcn_802_1x_phase2_altsubject_matches, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_DOMAIN_SUFFIX_MATCH, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CLIENT_CERT, + .describe_message = + N_("Enter file path to client certificate for inner authentication (optionally prefixed\n" + "with file://).\n" + " [file://]<file path>\n" + "Note that nmcli does not support specifying certificates as raw blob data.\n" + "Example: /home/cimrman/jara-zweite-phase.crt\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_phase2_client_cert, + .set_fcn = _set_fcn_802_1x_phase2_client_cert, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_CLIENT_CERT_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PASSWORD_RAW, + .is_secret = TRUE, + .describe_message = + N_("Enter bytes as a list of hexadecimal values.\n" + "Two formats are accepted:\n" + "(a) a string of hexadecimal digits, where each two digits represent one byte\n" + "(b) space-separated list of bytes written as hexadecimal digits " + "(with optional 0x/0X prefix, and optional leading 0).\n\n" + "Examples: ab0455a6ea3a74C2\n" + " ab 4 55 0xa6 ea 3a 74 C2\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_password_raw, + .set_fcn = _set_fcn_802_1x_password_raw, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PASSWORD_RAW_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PRIVATE_KEY, + .describe_message = + N_("Enter path to a private key and the key password (if not set yet):\n" + " [file://]<file path> [<password>]\n" + "Note that nmcli does not support specifying private key as raw blob data.\n" + "Example: /home/cimrman/jara-priv-key Dardanely\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_private_key, + .set_fcn = _set_fcn_802_1x_private_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PRIVATE_KEY_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY, + .describe_message = + N_("Enter path to a private key and the key password (if not set yet):\n" + " [file://]<file path> [<password>]\n" + "Note that nmcli does not support specifying private key as raw blob data.\n" + "Example: /home/cimrman/jara-priv-key Dardanely\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_802_1x_phase2_private_key, + .set_fcn = _set_fcn_802_1x_phase2_private_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PHASE2_PRIVATE_KEY_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PIN, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_PIN_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_SYSTEM_CA_CERTS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_802_1X_AUTH_TIMEOUT, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_ADSL +static const NMMetaPropertyInfo *const property_infos_ADSL[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_USERNAME, + .is_cli_option = TRUE, + .property_alias = "username", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Username"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_PASSWORD, + .is_cli_option = TRUE, + .property_alias = "password", + .prompt = N_("Password [none]"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_PROTOCOL, + .is_cli_option = TRUE, + .property_alias = "protocol", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_ADSL_PROTO, + .def_hint = NM_META_TEXT_PROMPT_ADSL_PROTO_CHOICES, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_ADSL_PROTOCOL_PPPOA, + NM_SETTING_ADSL_PROTOCOL_PPPOE, + NM_SETTING_ADSL_PROTOCOL_IPOATM), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_ENCAPSULATION, + .is_cli_option = TRUE, + .property_alias = "encapsulation", + .prompt = NM_META_TEXT_PROMPT_ADSL_ENCAP, + .def_hint = NM_META_TEXT_PROMPT_ADSL_ENCAP_CHOICES, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_ADSL_ENCAPSULATION_VCMUX, + NM_SETTING_ADSL_ENCAPSULATION_LLC), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_VPI, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_ADSL_VCI, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_BLUETOOTH +static const NMMetaPropertyInfo *const property_infos_BLUETOOTH[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_BLUETOOTH_BDADDR, + .is_cli_option = TRUE, + .property_alias = "addr", + .prompt = N_("Bluetooth device address"), + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BLUETOOTH_TYPE, + .is_cli_option = TRUE, + .property_alias = "bt-type", + .prompt = NM_META_TEXT_PROMPT_BT_TYPE, + .def_hint = NM_META_TEXT_PROMPT_BT_TYPE_CHOICES, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_BLUETOOTH_TYPE_DUN, + NM_SETTING_BLUETOOTH_TYPE_PANU, + NM_SETTING_BLUETOOTH_TYPE_NAP), + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_BOND +static const NMMetaPropertyInfo property_info_BOND_OPTIONS = + PROPERTY_INFO_INIT (NM_SETTING_BOND_OPTIONS, DESCRIBE_DOC_NM_SETTING_BOND_OPTIONS, + .property_type = DEFINE_PROPERTY_TYPE ( + .describe_fcn = _describe_fcn_bond_options, + .get_fcn = _get_fcn_bond_options, + .set_fcn = _set_fcn_bond_options, + .remove_fcn = _remove_fcn_bond_options, + .values_fcn = _values_fcn_bond_options, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .nested = &nm_meta_property_typ_data_bond, + ), + ); + +static const NMMetaPropertyInfo *const property_infos_BOND[] = { + &property_info_BOND_OPTIONS, + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_BRIDGE +static const NMMetaPropertyInfo *const property_infos_BRIDGE[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "mac", + .prompt = N_("MAC [none]"), + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_STP, + .is_cli_option = TRUE, + .property_alias = "stp", + .prompt = N_("Enable STP [no]"), + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_PRIORITY, + .is_cli_option = TRUE, + .property_alias = "priority", + .prompt = N_("STP priority [32768]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_FORWARD_DELAY, + .is_cli_option = TRUE, + .property_alias = "forward-delay", + .prompt = N_("Forward delay [15]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_HELLO_TIME, + .is_cli_option = TRUE, + .property_alias = "hello-time", + .prompt = N_("Hello time [2]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MAX_AGE, + .is_cli_option = TRUE, + .property_alias = "max-age", + .prompt = N_("Max age [20]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_AGEING_TIME, + .is_cli_option = TRUE, + .property_alias = "ageing-time", + .prompt = N_("MAC address ageing time [300]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_GROUP_FORWARD_MASK, + .is_cli_option = TRUE, + .property_alias = "group-forward-mask", + .prompt = N_("Group forward mask [0]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_MULTICAST_SNOOPING, + .is_cli_option = TRUE, + .property_alias = "multicast-snooping", + .prompt = N_("Enable IGMP snooping [no]"), + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_BRIDGE_PORT +static const NMMetaPropertyInfo *const property_infos_BRIDGE_PORT[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_PORT_PRIORITY, + .is_cli_option = TRUE, + .property_alias = "priority", + .prompt = N_("Bridge port priority [32]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_PORT_PATH_COST, + .is_cli_option = TRUE, + .property_alias = "path-cost", + .prompt = N_("Bridge port STP path cost [100]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_BRIDGE_PORT_HAIRPIN_MODE, + .is_cli_option = TRUE, + .property_alias = "hairpin", + .prompt = N_("Hairpin [no]"), + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_CDMA +static const NMMetaPropertyInfo *const property_infos_CDMA[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_CDMA_NUMBER, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CDMA_USERNAME, + .is_cli_option = TRUE, + .property_alias = "user", + .prompt = N_("Username [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CDMA_PASSWORD, + .is_cli_option = TRUE, + .property_alias = "password", + .prompt = N_("Password [none]"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CDMA_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CDMA_MTU, + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingCdma, nm_setting_cdma_get_mtu), + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_CONNECTION +static const NMMetaPropertyInfo *const property_infos_CONNECTION[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_ID, + .is_cli_option = TRUE, + .property_alias = "con-name", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_UUID, + .property_type = DEFINE_PROPERTY_TYPE ( .get_fcn = _get_fcn_gobject ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_STABLE_ID, + .property_type = &_pt_gobject_string, + ), +[_NM_META_PROPERTY_TYPE_CONNECTION_TYPE] = + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_TYPE, + .is_cli_option = TRUE, + .property_alias = "type", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_CON_TYPE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_connection_type, + .complete_fcn = _complete_fcn_connection_type, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_INTERFACE_NAME, + .is_cli_option = TRUE, + .property_alias = "ifname", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_IFNAME, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_ifname, + .complete_fcn = _complete_fcn_gobject_devices, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT, + .is_cli_option = TRUE, + .property_alias = "autoconnect", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT_PRIORITY, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT_RETRIES, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, + .value_infos = INT_VALUE_INFOS ( + { + .value = -1, + .nick = "default", + }, + { + .value = 0, + .nick = "forever", + } + ), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTH_RETRIES, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_TIMESTAMP, + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_READ_ONLY, + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_PERMISSIONS, + .describe_message = + N_("Enter a list of user permissions. This is a list of user names formatted as:\n" + " [user:]<user name 1>, [user:]<user name 2>,...\n" + "The items can be separated by commas or spaces.\n\n" + "Example: alice bob charlie\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_connection_permissions, + .set_fcn = _set_fcn_connection_permissions, + .remove_fcn = _remove_fcn_connection_permissions, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_ZONE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_MASTER, + .is_cli_option = TRUE, + .property_alias = "master", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .prompt = NM_META_TEXT_PROMPT_MASTER, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_connection_master, + .complete_fcn = _complete_fcn_connection_master, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_SLAVE_TYPE, + .is_cli_option = TRUE, + .property_alias = "slave-type", + .inf_flags = NM_META_PROPERTY_INF_FLAG_DONT_ASK, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_BOND_SETTING_NAME, + NM_SETTING_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_BRIDGE_SETTING_NAME, + NM_SETTING_OVS_PORT_SETTING_NAME, + NM_SETTING_TEAM_SETTING_NAME), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES, + .property_type = &_pt_gobject_enum, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_SECONDARIES, + .describe_message = + N_("Enter secondary connections that should be activated when this connection is\n" + "activated. Connections can be specified either by UUID or ID (name). nmcli\n" + "transparently translates names to UUIDs. Note that NetworkManager only supports\n" + "VPNs as secondary connections at the moment.\n" + "The items can be separated by commas or spaces.\n\n" + "Example: private-openvpn, fe6ba5d8-c2fc-4aae-b2e3-97efddd8d9a7\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_connection_secondaries, + .remove_fcn = _remove_fcn_connection_secondaries, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_GATEWAY_PING_TIMEOUT, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_METERED, + .describe_message = + N_("Enter a value which indicates whether the connection is subject to a data\n" + "quota, usage costs or other limitations. Accepted options are:\n" + "'true','yes','on' to set the connection as metered\n" + "'false','no','off' to set the connection as not metered\n" + "'unknown' to let NetworkManager choose a value using some heuristics\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_connection_metered, + .set_fcn = _set_fcn_connection_metered, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("yes", "no", "unknown"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_CONNECTION_LLDP, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_connection_lldp_get_type, + .value_infos = ENUM_VALUE_INFOS ( + { + .value = NM_SETTING_CONNECTION_LLDP_ENABLE_RX, + .nick = "enable", + } + ), + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_DCB +static const NMMetaPropertyInfo *const property_infos_DCB[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FCOE_FLAGS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_app_fcoe_flags, + .set_fcn = _set_fcn_dcb_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FCOE_PRIORITY, + DEFINE_DCB_PROPRITY_PROPERTY_TYPE + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FCOE_MODE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_DCB_FCOE_MODE_FABRIC, + NM_SETTING_DCB_FCOE_MODE_VN2VN), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_ISCSI_FLAGS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_app_iscsi_flags, + .set_fcn = _set_fcn_dcb_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_ISCSI_PRIORITY, + DEFINE_DCB_PROPRITY_PROPERTY_TYPE + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FIP_FLAGS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_app_fip_flags, + .set_fcn = _set_fcn_dcb_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_APP_FIP_PRIORITY, + DEFINE_DCB_PROPRITY_PROPERTY_TYPE + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL_FLAGS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_flow_control_flags, + .set_fcn = _set_fcn_dcb_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_FLOW_CONTROL, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_flow_control, + .set_fcn = _set_fcn_dcb_priority_flow_control, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_GROUP_FLAGS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_group_flags, + .set_fcn = _set_fcn_dcb_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_GROUP_ID, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_group_id, + .set_fcn = _set_fcn_dcb_priority_group_id, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_GROUP_BANDWIDTH, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_group_bandwidth, + .set_fcn = _set_fcn_dcb_priority_group_bandwidth, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_BANDWIDTH, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_bandwidth, + .set_fcn = _set_fcn_dcb_priority_bandwidth, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_STRICT_BANDWIDTH, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_strict, + .set_fcn = _set_fcn_dcb_priority_strict, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_DCB_PRIORITY_TRAFFIC_CLASS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_dcb_priority_traffic_class, + .set_fcn = _set_fcn_dcb_priority_traffic_class, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_GSM +static const NMMetaPropertyInfo *const property_infos_GSM[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_NUMBER, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_USERNAME, + .is_cli_option = TRUE, + .property_alias = "user", + .prompt = N_("Username [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_PASSWORD, + .is_cli_option = TRUE, + .property_alias = "password", + .prompt = N_("Password [none]"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_APN, + .is_cli_option = TRUE, + .property_alias = "apn", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("APN"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_NETWORK_ID, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_PIN, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_PIN_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_HOME_ONLY, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_DEVICE_ID, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_SIM_ID, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_SIM_OPERATOR_ID, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gsm_sim_operator_id, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_GSM_MTU, + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingGsm, nm_setting_gsm_get_mtu), + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_INFINIBAND +static const NMMetaPropertyInfo *const property_infos_INFINIBAND[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "mac", + .prompt = N_("MAC [none]"), + .property_type = &_pt_gobject_mac, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mac, + .mode = NM_META_PROPERTY_TYPE_MAC_MODE_INFINIBAND, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_MTU, + .is_cli_option = TRUE, + .property_alias = "mtu", + .prompt = N_("MTU [auto]"), + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingInfiniband, nm_setting_infiniband_get_mtu), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_TRANSPORT_MODE, + .is_cli_option = TRUE, + .property_alias = "transport-mode", + .prompt = NM_META_TEXT_PROMPT_IB_MODE, + .def_hint = NM_META_TEXT_PROMPT_IB_MODE_CHOICES, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("datagram", "connected"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_P_KEY, + .is_cli_option = TRUE, + .property_alias = "p-key", + .prompt = N_("P_KEY [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_infiniband_p_key, + .set_fcn = _set_fcn_infiniband_p_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_INFINIBAND_PARENT, + .is_cli_option = TRUE, + .property_alias = "parent", + .prompt = N_("Parent interface [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_gobject_ifname, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_IP4_CONFIG +static const NMMetaPropertyInfo *const property_infos_IP4_CONFIG[] = { + PROPERTY_INFO (NM_SETTING_IP_CONFIG_METHOD, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_METHOD, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip4_config_method, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = ipv4_valid_methods, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS, + .describe_message = + N_("Enter a list of IPv4 addresses of DNS servers.\n\n" + "Example: 8.8.8.8, 8.8.4.4\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip4_config_dns, + .remove_fcn = _remove_fcn_ipv4_config_dns, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_SEARCH, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_SEARCH, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip4_config_dns_search, + .remove_fcn = _remove_fcn_ipv4_config_dns_search, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_OPTIONS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_nmc_with_default, + .set_fcn = _set_fcn_ip4_config_dns_options, + .remove_fcn = _remove_fcn_ipv4_config_dns_options, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (get_with_default, + .fcn = GET_FCN_WITH_DEFAULT (NMSettingIPConfig, nm_setting_ip_config_has_dns_options), + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_PRIORITY, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DNS_PRIORITY, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ADDRESSES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ADDRESSES, + .is_cli_option = TRUE, + .property_alias = "ip4", + .inf_flags = NM_META_PROPERTY_INF_FLAG_MULTI, + .prompt = N_("IPv4 address (IP[/plen]) [none]"), + .describe_message = + N_("Enter a list of IPv4 addresses formatted as:\n" + " ip[/prefix], ip[/prefix],...\n" + "Missing prefix is regarded as prefix of 32.\n\n" + "Example: 192.168.1.5/24, 10.0.0.11/24\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_ip_config_addresses, + .set_fcn = _set_fcn_ip4_config_addresses, + .remove_fcn = _remove_fcn_ipv4_config_addresses, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_GATEWAY, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_GATEWAY, + .is_cli_option = TRUE, + .property_alias = "gw4", + .prompt = N_("IPv4 gateway [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip4_config_gateway, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTES, + .describe_message = + N_("Enter a list of IPv4 routes formatted as:\n" + " ip[/prefix] [next-hop] [metric],...\n\n" + "Missing prefix is regarded as a prefix of 32.\n" + "Missing next-hop is regarded as 0.0.0.0.\n" + "Missing metric means default (NM/kernel will set a default value).\n\n" + "Examples: 192.168.2.0/24 192.168.2.1 3, 10.1.0.0/16 10.0.0.254\n" + " 10.1.2.0/24\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_ip_config_routes, + .set_fcn = _set_fcn_ip4_config_routes, + .remove_fcn = _remove_fcn_ipv4_config_routes, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_METRIC, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_METRIC, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_ROUTE_TABLE, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, + .value_infos = INT_VALUE_INFOS ( + { + .value = 0, + .nick = "unspec", + }, + { + .value = 254, + .nick = "main", + } + ), + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_ROUTES, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_IGNORE_AUTO_DNS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP4_CONFIG_DHCP_CLIENT_ID, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_TIMEOUT, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, + .value_infos = INT_VALUE_INFOS ( + { + .value = 0, + .nick = "default", + }, + { + .value = G_MAXINT32, + .nick = "infinity", + } + ), + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_SEND_HOSTNAME, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DHCP_HOSTNAME, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP4_CONFIG_DHCP_FQDN, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_MAY_FAIL, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_MAY_FAIL, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DAD_TIMEOUT, DESCRIBE_DOC_NM_SETTING_IP4_CONFIG_DAD_TIMEOUT, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, + .value_infos = INT_VALUE_INFOS ( + { + .value = -1, + .nick = "default", + }, + { + .value = 0, + .nick = "off", + } + ), + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_IP6_CONFIG +static const NMMetaPropertyInfo *const property_infos_IP6_CONFIG[] = { + PROPERTY_INFO (NM_SETTING_IP_CONFIG_METHOD, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_METHOD, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip6_config_method, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = ipv6_valid_methods, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS, + .describe_message = + N_("Enter a list of IPv6 addresses of DNS servers. If the IPv6 " + "configuration method is 'auto' these DNS servers are appended " + "to those (if any) returned by automatic configuration. DNS " + "servers cannot be used with the 'shared' or 'link-local' IPv6 " + "configuration methods, as there is no upstream network. In " + "all other IPv6 configuration methods, these DNS " + "servers are used as the only DNS servers for this connection.\n\n" + "Example: 2607:f0d0:1002:51::4, 2607:f0d0:1002:51::1\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip6_config_dns, + .remove_fcn = _remove_fcn_ipv6_config_dns, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_SEARCH, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_SEARCH, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip6_config_dns_search, + .remove_fcn = _remove_fcn_ipv6_config_dns_search, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_OPTIONS, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_OPTIONS, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_nmc_with_default, + .set_fcn = _set_fcn_ip6_config_dns_options, + .remove_fcn = _remove_fcn_ipv6_config_dns_options, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (get_with_default, + .fcn = GET_FCN_WITH_DEFAULT (NMSettingIPConfig, nm_setting_ip_config_has_dns_options), + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DNS_PRIORITY, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DNS_PRIORITY, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ADDRESSES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ADDRESSES, + .is_cli_option = TRUE, + .property_alias = "ip6", + .inf_flags = NM_META_PROPERTY_INF_FLAG_MULTI, + .prompt = N_("IPv6 address (IP[/plen]) [none]"), + .describe_message = + N_("Enter a list of IPv6 addresses formatted as:\n" + " ip[/prefix], ip[/prefix],...\n" + "Missing prefix is regarded as prefix of 128.\n\n" + "Example: 2607:f0d0:1002:51::4/64, 1050:0:0:0:5:600:300c:326b\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_ip_config_addresses, + .set_fcn = _set_fcn_ip6_config_addresses, + .remove_fcn = _remove_fcn_ipv6_config_addresses, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_GATEWAY, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_GATEWAY, + .is_cli_option = TRUE, + .property_alias = "gw6", + .prompt = N_("IPv6 gateway [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_ip6_config_gateway, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTES, + .describe_message = + N_("Enter a list of IPv6 routes formatted as:\n" + " ip[/prefix] [next-hop] [metric],...\n\n" + "Missing prefix is regarded as a prefix of 128.\n" + "Missing next-hop is regarded as \"::\".\n" + "Missing metric means default (NM/kernel will set a default value).\n\n" + "Examples: 2001:db8:beef:2::/64 2001:db8:beef::2, 2001:db8:beef:3::/64 2001:db8:beef::3 2\n" + " abbe::/64 55\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_ip_config_routes, + .set_fcn = _set_fcn_ip6_config_routes, + .remove_fcn = _remove_fcn_ipv6_config_routes, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_METRIC, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_METRIC, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_ROUTE_TABLE, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_ROUTE_TABLE, + .property_type = &_pt_gobject_int, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_int, + .value_infos = INT_VALUE_INFOS ( + { + .value = 0, + .nick = "unspec", + }, + { + .value = 254, + .nick = "main", + } + ), + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_ROUTES, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_ROUTES, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_IGNORE_AUTO_DNS, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_IGNORE_AUTO_DNS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_NEVER_DEFAULT, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_NEVER_DEFAULT, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_MAY_FAIL, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_MAY_FAIL, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_ip6_config_ip6_privacy, + .set_fcn = _set_fcn_ip6_config_ip6_privacy, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_ip6_config_addr_gen_mode_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_SEND_HOSTNAME, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_SEND_HOSTNAME, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO (NM_SETTING_IP_CONFIG_DHCP_HOSTNAME, DESCRIBE_DOC_NM_SETTING_IP6_CONFIG_DHCP_HOSTNAME, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP6_CONFIG_TOKEN, + .property_type = &_pt_gobject_string, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_IP_TUNNEL +static const NMMetaPropertyInfo *const property_infos_IP_TUNNEL[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_MODE, + .is_cli_option = TRUE, + .property_alias = "mode", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_IP_TUNNEL_MODE, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_ip_tunnel_mode_get_type, + .min = NM_IP_TUNNEL_MODE_UNKNOWN + 1, + .max = G_MAXINT, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .prompt = N_("Parent device [none]"), + .property_type = &_pt_gobject_devices, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_LOCAL, + .is_cli_option = TRUE, + .property_alias = "local", + .prompt = N_("Local endpoint [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_REMOTE, + .is_cli_option = TRUE, + .property_alias = "remote", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Remote"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_TTL, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_TOS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_PATH_MTU_DISCOVERY, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_INPUT_KEY, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_OUTPUT_KEY, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_ENCAPSULATION_LIMIT, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_FLOW_LABEL, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_IP_TUNNEL_MTU, + .property_type = &_pt_gobject_mtu, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_MACSEC +static const NMMetaPropertyInfo *const property_infos_MACSEC[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("MACsec parent device or connection UUID"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_MODE, + .is_cli_option = TRUE, + .property_alias = "mode", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_MACSEC_MODE, + .def_hint = NM_META_TEXT_PROMPT_MACSEC_MODE_CHOICES, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_macsec_mode_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_ENCRYPT, + .is_cli_option = TRUE, + .property_alias = "encrypt", + .prompt = N_("Enable encryption [yes]"), + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_MKA_CAK, + .is_cli_option = TRUE, + .property_alias = "cak", + .prompt = N_("MKA CAK"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_MKA_CAK_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_MKA_CKN, + .is_cli_option = TRUE, + .property_alias = "ckn", + .prompt = N_("MKA_CKN"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_PORT, + .is_cli_option = TRUE, + .property_alias = "port", + .prompt = N_("SCI port [1]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACSEC_VALIDATION, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_macsec_validation_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_MACVLAN +static const NMMetaPropertyInfo *const property_infos_MACVLAN[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACVLAN_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("MACVLAN parent device or connection UUID"), + .property_type = &_pt_gobject_devices, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACVLAN_MODE, + .is_cli_option = TRUE, + .property_alias = "mode", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_MACVLAN_MODE, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_macvlan_mode_get_type, + .min = NM_SETTING_MACVLAN_MODE_UNKNOWN + 1, + .max = G_MAXINT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACVLAN_PROMISCUOUS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_MACVLAN_TAP, + .is_cli_option = TRUE, + .property_alias = "tap", + .prompt = N_("Tap [no]"), + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OLPC_MESH +static const NMMetaPropertyInfo *const property_infos_OLPC_MESH[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_OLPC_MESH_SSID, + .is_cli_option = TRUE, + .property_alias = "ssid", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("SSID"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_olpc_mesh_ssid, + .set_fcn = _set_fcn_gobject_ssid, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OLPC_MESH_CHANNEL, + .is_cli_option = TRUE, + .property_alias = "channel", + .prompt = N_("OLPC Mesh channel [1]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_olpc_mesh_channel, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OLPC_MESH_DHCP_ANYCAST_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "dhcp-anycast", + .prompt = N_("DHCP anycast MAC address [none]"), + .property_type = &_pt_gobject_mac, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PPPOE +static const NMMetaPropertyInfo *const property_infos_PPPOE[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PARENT, + .is_cli_option = TRUE, + .property_alias = "parent", + .prompt = N_("PPPoE parent device"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_SERVICE, + .is_cli_option = TRUE, + .property_alias = "service", + .prompt = N_("Service [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_USERNAME, + .is_cli_option = TRUE, + .property_alias = "username", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("PPPoE username"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD, + .is_cli_option = TRUE, + .property_alias = "password", + .prompt = N_("Password [none]"), + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPPOE_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OVS_BRIDGE +static const NMMetaPropertyInfo *const property_infos_OVS_BRIDGE[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_FAIL_MODE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("secure", "standalone"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_MCAST_SNOOPING_ENABLE, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_RSTP_ENABLE, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_BRIDGE_STP_ENABLE, + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OVS_INTERFACE +static const NMMetaPropertyInfo *const property_infos_OVS_INTERFACE[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_INTERFACE_TYPE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("internal", "patch"), + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OVS_PATCH +static const NMMetaPropertyInfo *const property_infos_OVS_PATCH[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PATCH_PEER, + .property_type = &_pt_gobject_string, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_OVS_PORT +static const NMMetaPropertyInfo *const property_infos_OVS_PORT[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_VLAN_MODE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("access", "native-tagged", "native-untagged", "trunk"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_TAG, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_LACP, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("active", "off", "passive"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_BOND_MODE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("active-backup", "balance-slb", "balance-tcp"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_BOND_UPDELAY, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_OVS_PORT_BOND_DOWNDELAY, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PPP +static const NMMetaPropertyInfo *const property_infos_PPP[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_NOAUTH, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REFUSE_EAP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REFUSE_PAP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REFUSE_CHAP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REFUSE_MSCHAP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REFUSE_MSCHAPV2, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_NOBSDCOMP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_NODEFLATE, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_NO_VJ_COMP, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REQUIRE_MPPE, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_REQUIRE_MPPE_128, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_MPPE_STATEFUL, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_CRTSCTS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_BAUD, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_MRU, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_MTU, + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingPpp, nm_setting_ppp_get_mtu), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_LCP_ECHO_FAILURE, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PPP_LCP_ECHO_INTERVAL, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_PROXY +static const NMMetaPropertyInfo *const property_infos_PROXY[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_PROXY_METHOD, + .is_cli_option = TRUE, + .property_alias = "method", + .prompt = NM_META_TEXT_PROMPT_PROXY_METHOD, + .def_hint = NM_META_TEXT_PROMPT_PROXY_METHOD_CHOICES, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_proxy_method_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PROXY_BROWSER_ONLY, + .is_cli_option = TRUE, + .property_alias = "browser-only", + .prompt = N_("Browser only [no]"), + .property_type = &_pt_gobject_bool + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PROXY_PAC_URL, + .is_cli_option = TRUE, + .property_alias = "pac-url", + .prompt = N_("PAC URL"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_PROXY_PAC_SCRIPT, + .is_cli_option = TRUE, + .property_alias = "pac-script", + .prompt = N_("PAC script"), + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_string, + .validate_fcn = _validate_fcn_proxy_pac_script, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_TEAM +static const NMMetaPropertyInfo *const property_infos_TEAM[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_CONFIG, + .is_cli_option = TRUE, + .property_alias = "config", + .prompt = N_("Team JSON configuration [none]"), + .describe_message = TEAM_DESCRIBE_MESSAGE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_string, + .validate_fcn = _validate_fcn_team_config, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_TEAM_PORT +static const NMMetaPropertyInfo *const property_infos_TEAM_PORT[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_TEAM_PORT_CONFIG, + .is_cli_option = TRUE, + .property_alias = "config", + .prompt = N_("Team JSON configuration [none]"), + .describe_message = TEAM_DESCRIBE_MESSAGE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_string, + .validate_fcn = _validate_fcn_team_config, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_SERIAL +static const NMMetaPropertyInfo *const property_infos_SERIAL[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BAUD, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_BITS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_PARITY, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_serial_parity_get_type, + .value_infos = ENUM_VALUE_INFOS ( + { + .value = NM_SETTING_SERIAL_PARITY_EVEN, + .nick = "E", + }, + { + .value = NM_SETTING_SERIAL_PARITY_EVEN, + .nick = "e", + }, + { + .value = NM_SETTING_SERIAL_PARITY_ODD, + .nick = "O", + }, + { + .value = NM_SETTING_SERIAL_PARITY_ODD, + .nick = "o", + }, + { + .value = NM_SETTING_SERIAL_PARITY_NONE, + .nick = "N", + }, + { + .value = NM_SETTING_SERIAL_PARITY_NONE, + .nick = "n", + } + ), + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_STOPBITS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_SERIAL_SEND_DELAY, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_TUN +static const NMMetaPropertyInfo *const property_infos_TUN[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_MODE, + .is_cli_option = TRUE, + .property_alias = "mode", + .prompt = NM_META_TEXT_PROMPT_TUN_MODE, + .def_hint = NM_META_TEXT_PROMPT_TUN_MODE_CHOICES, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_tun_mode_get_type, + .min = NM_SETTING_TUN_MODE_UNKNOWN + 1, + .max = G_MAXINT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_OWNER, + .is_cli_option = TRUE, + .property_alias = "owner", + .prompt = N_("User ID [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_GROUP, + .is_cli_option = TRUE, + .property_alias = "group", + .prompt = N_("Group ID [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_PI, + .is_cli_option = TRUE, + .property_alias = "pi", + .prompt = N_("Enable PI [no]"), + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_VNET_HDR, + .is_cli_option = TRUE, + .property_alias = "vnet-hdr", + .prompt = N_("Enable VNET header [no]"), + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_TUN_MULTI_QUEUE, + .is_cli_option = TRUE, + .property_alias = "multi-queue", + .prompt = N_("Enable multi queue [no]"), + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VLAN +static const NMMetaPropertyInfo *const property_infos_VLAN[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_VLAN_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("VLAN parent device or connection UUID"), + .property_type = &_pt_gobject_devices, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VLAN_ID, + .is_cli_option = TRUE, + .property_alias = "id", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("VLAN ID (<0-4094>)"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VLAN_FLAGS, + .is_cli_option = TRUE, + .property_alias = "flags", + .prompt = N_("VLAN flags (<0-7>) [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_vlan_flags, + .set_fcn = _set_fcn_gobject_flags, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VLAN_INGRESS_PRIORITY_MAP, + .is_cli_option = TRUE, + .property_alias = "ingress", + .prompt = N_("Ingress priority maps [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_vlan_ingress_priority_map, + .set_fcn = _set_fcn_vlan_ingress_priority_map, + .remove_fcn = _remove_fcn_vlan_ingress_priority_map, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VLAN_EGRESS_PRIORITY_MAP, + .is_cli_option = TRUE, + .property_alias = "egress", + .prompt = N_("Egress priority maps [none]"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_vlan_egress_priority_map, + .set_fcn = _set_fcn_vlan_egress_priority_map, + .remove_fcn = _remove_fcn_vlan_egress_priority_map, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VPN +static const NMMetaPropertyInfo *const property_infos_VPN[] = { +[_NM_META_PROPERTY_TYPE_VPN_SERVICE_TYPE] = + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_SERVICE_TYPE, + .is_cli_option = TRUE, + .property_alias = "vpn-type", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = NM_META_TEXT_PROMPT_VPN_TYPE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_vpn_service_type, + .complete_fcn = _complete_fcn_vpn_service_type, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_USER_NAME, + .is_cli_option = TRUE, + .property_alias = "user", + .prompt = N_("Username [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_DATA, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_vpn_data, + .set_fcn = _set_fcn_vpn_data, + .remove_fcn = _remove_fcn_vpn_data, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_SECRETS, + .is_secret = TRUE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_vpn_secrets, + .set_fcn = _set_fcn_vpn_secrets, + .remove_fcn = _remove_fcn_vpn_secrets, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_PERSISTENT, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VPN_TIMEOUT, + .property_type = &_pt_gobject_int, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_VXLAN +static const NMMetaPropertyInfo *const property_infos_VXLAN[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_PARENT, + .is_cli_option = TRUE, + .property_alias = "dev", + .prompt = N_("Parent device [none]"), + .property_type = &_pt_gobject_devices, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_ID, + .is_cli_option = TRUE, + .property_alias = "id", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("VXLAN ID"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_LOCAL, + .is_cli_option = TRUE, + .property_alias = "local", + .prompt = N_("Local address [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_REMOTE, + .is_cli_option = TRUE, + .property_alias = "remote", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("Remote"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_SOURCE_PORT_MIN, + .is_cli_option = TRUE, + .property_alias = "source-port-min", + .prompt = N_("Minimum source port [0]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_SOURCE_PORT_MAX, + .is_cli_option = TRUE, + .property_alias = "source-port-max", + .prompt = N_("Maximum source port [0]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_DESTINATION_PORT, + .is_cli_option = TRUE, + .property_alias = "destination-port", + .prompt = N_("Destination port [8472]"), + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_TOS, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_TTL, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_AGEING, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_LIMIT, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_LEARNING, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_PROXY, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_RSC, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_L2_MISS, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_VXLAN_L3_MISS, + .property_type = &_pt_gobject_bool, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIMAX +static const NMMetaPropertyInfo *const property_infos_WIMAX[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIMAX_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "mac", + .prompt = N_("MAC [none]"), + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIMAX_NETWORK_NAME, + .is_cli_option = TRUE, + .property_alias = "nsp", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("WiMAX NSP name"), + .property_type = &_pt_gobject_mac, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIRED +static const NMMetaPropertyInfo *const property_infos_WIRED[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_PORT, + /* Do not allow setting 'port' for now. It is not implemented in + * NM core, nor in ifcfg-rh plugin. Enable this when it gets done. + * wired_valid_ports[] = { "tp", "aui", "bnc", "mii", NULL }; + */ + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_SPEED, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_DUPLEX, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("half", "full"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_AUTO_NEGOTIATE, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "mac", + .prompt = N_("MAC [none]"), + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_CLONED_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "cloned-mac", + .prompt = N_("Cloned MAC [none]"), + .property_type = &_pt_gobject_mac, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mac, + .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_GENERATE_MAC_ADDRESS_MASK, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_MAC_ADDRESS_BLACKLIST, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wired_mac_address_blacklist, + .remove_fcn = _remove_fcn_wired_mac_address_blacklist, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_MTU, + .is_cli_option = TRUE, + .property_alias = "mtu", + .prompt = N_("MTU [auto]"), + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingWired, nm_setting_wired_get_mtu), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_S390_SUBCHANNELS, + .describe_message = + N_("Enter a list of subchannels (comma or space separated).\n\n" + "Example: 0.0.0e20 0.0.0e21 0.0.0e22\n"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wired_s390_subchannels, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_S390_NETTYPE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("qeth", "lcs", "ctc"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_S390_OPTIONS, + .property_type = DEFINE_PROPERTY_TYPE ( + .describe_fcn = _describe_fcn_wired_s390_options, + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wired_s390_options, + .remove_fcn = _remove_fcn_wired_s390_options, + .values_fcn = _values_fcn__wired_s390_options, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_WAKE_ON_LAN, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wired_wake_on_lan_get_type, + .value_infos = ENUM_VALUE_INFOS ( + { + .value = NM_SETTING_WIRED_WAKE_ON_LAN_NONE, + .nick = "none", + }, + { + .value = NM_SETTING_WIRED_WAKE_ON_LAN_NONE, + .nick = "disable", + }, + { + .value = NM_SETTING_WIRED_WAKE_ON_LAN_NONE, + .nick = "disabled", + } + ), + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRED_WAKE_ON_LAN_PASSWORD, + .property_type = &_pt_gobject_mac, + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIRELESS +static const NMMetaPropertyInfo *const property_infos_WIRELESS[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SSID, + .is_cli_option = TRUE, + .property_alias = "ssid", + .inf_flags = NM_META_PROPERTY_INF_FLAG_REQD, + .prompt = N_("SSID"), + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_wireless_ssid, + .set_fcn = _set_fcn_gobject_ssid, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_MODE, + .is_cli_option = TRUE, + .property_alias = "mode", + .prompt = NM_META_TEXT_PROMPT_WIFI_MODE, + .def_hint = NM_META_TEXT_PROMPT_WIFI_MODE_CHOICES, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC (NM_SETTING_WIRELESS_MODE_INFRA, + NM_SETTING_WIRELESS_MODE_ADHOC, + NM_SETTING_WIRELESS_MODE_AP), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_BAND, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("a", "bg"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_CHANNEL, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wireless_channel, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_BSSID, + .property_type = &_pt_gobject_mac, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_RATE, + /* Do not allow setting 'rate'. It is not implemented in NM core. */ + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_TX_POWER, + /* Do not allow setting 'tx-power'. It is not implemented in NM core. */ + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_MAC_ADDRESS, + .property_type = &_pt_gobject_mac, + .is_cli_option = TRUE, + .property_alias = "mac", + .prompt = N_("MAC [none]"), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS, + .is_cli_option = TRUE, + .property_alias = "cloned-mac", + .prompt = N_("Cloned MAC [none]"), + .property_type = &_pt_gobject_mac, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mac, + .mode = NM_META_PROPERTY_TYPE_MAC_MODE_CLONED, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_GENERATE_MAC_ADDRESS_MASK, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_MAC_ADDRESS_BLACKLIST, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wireless_mac_address_blacklist, + .remove_fcn = _remove_fcn_wireless_mac_address_blacklist, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_MAC_ADDRESS_RANDOMIZATION, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_mac_randomization_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_MTU, + .is_cli_option = TRUE, + .property_alias = "mtu", + .prompt = N_("MTU [auto]"), + .property_type = &_pt_gobject_mtu, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (mtu, + .get_fcn = MTU_GET_FCN (NMSettingWireless, nm_setting_wireless_get_mtu), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SEEN_BSSIDS, + .property_type = &_pt_gobject_readonly, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_HIDDEN, + .property_type = &_pt_gobject_bool, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_POWERSAVE, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_powersave_get_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT, + ), + ), + NULL +}; + +#undef _CURRENT_NM_META_SETTING_TYPE +#define _CURRENT_NM_META_SETTING_TYPE NM_META_SETTING_TYPE_WIRELESS_SECURITY +static const NMMetaPropertyInfo *const property_infos_WIRELESS_SECURITY[] = { + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("none", "ieee8021x", "wpa-none", "wpa-psk", "wpa-eap"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_TX_KEYIDX, + .property_type = &_pt_gobject_int, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = VALUES_STATIC ("open", "shared", "leap"), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PROTO, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wireless_security_proto, + .remove_fcn = _remove_fcn_wireless_security_proto, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = wifi_sec_valid_protos, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PAIRWISE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wireless_security_pairwise, + .remove_fcn = _remove_fcn_wireless_security_pairwise, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = wifi_sec_valid_pairwises, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_GROUP, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_gobject, + .set_fcn = _set_fcn_wireless_security_group, + .remove_fcn = _remove_fcn_wireless_security_group, + ), + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + .values_static = wifi_sec_valid_groups, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PMF, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_security_pmf_get_type, + ), + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY0, + .is_secret = TRUE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_wireless_security_wep_key0, + .set_fcn = _set_fcn_wireless_wep_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY1, + .is_secret = TRUE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_wireless_security_wep_key1, + .set_fcn = _set_fcn_wireless_wep_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY2, + .is_secret = TRUE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_wireless_security_wep_key2, + .set_fcn = _set_fcn_wireless_wep_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY3, + .is_secret = TRUE, + .property_type = DEFINE_PROPERTY_TYPE ( + .get_fcn = _get_fcn_wireless_security_wep_key3, + .set_fcn = _set_fcn_wireless_wep_key, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WEP_KEY_TYPE, + .describe_message = + N_("Enter the type of WEP keys. The accepted values are: " + "0 or unknown, 1 or key, and 2 or passphrase.\n"), + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .pre_set_notify = _gobject_enum_pre_set_notify_fcn_wireless_security_wep_key_type, + ), + .typ_flags = NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PARSABLE_TEXT + | NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_TEXT, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PSK, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA_SUBTYPE (gobject_string, + .validate_fcn = _validate_fcn_wireless_security_psk, + ), + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, + .is_secret = TRUE, + .property_type = &_pt_gobject_string, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, + .property_type = &_pt_gobject_secret_flags, + ), + PROPERTY_INFO_WITH_DESC (NM_SETTING_WIRELESS_SECURITY_WPS_METHOD, + .property_type = &_pt_gobject_enum, + .property_typ_data = DEFINE_PROPERTY_TYP_DATA ( + PROPERTY_TYP_DATA_SUBTYPE (gobject_enum, + .get_gtype = nm_setting_wireless_security_wps_method_get_type, + ), + ), + ), + NULL +}; + +/*****************************************************************************/ + +static void +_setting_init_fcn_adsl (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + /* Initialize a protocol */ + g_object_set (NM_SETTING_ADSL (setting), + NM_SETTING_ADSL_PROTOCOL, NM_SETTING_ADSL_PROTOCOL_PPPOE, + NULL); + } +} + +static void +_setting_init_fcn_cdma (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + /* Initialize 'number' so that 'cdma' is valid */ + g_object_set (NM_SETTING_CDMA (setting), + NM_SETTING_CDMA_NUMBER, "#777", + NULL); + } +} + +static void +_setting_init_fcn_gsm (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + /* Initialize 'number' so that 'gsm' is valid */ + g_object_set (NM_SETTING_GSM (setting), + NM_SETTING_GSM_NUMBER, "*99#", + NULL); + } +} + +static void +_setting_init_fcn_infiniband (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + /* Initialize 'transport-mode' so that 'infiniband' is valid */ + g_object_set (NM_SETTING_INFINIBAND (setting), + NM_SETTING_INFINIBAND_TRANSPORT_MODE, "datagram", + NULL); + } +} + +static void +_setting_init_fcn_ip4_config (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (NM_SETTING_IP_CONFIG (setting), + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, + NULL); + } +} + +static void +_setting_init_fcn_ip6_config (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (NM_SETTING_IP_CONFIG (setting), + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); + } +} + +static void +_setting_init_fcn_olpc_mesh (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (NM_SETTING_OLPC_MESH (setting), + NM_SETTING_OLPC_MESH_CHANNEL, 1, + NULL); + } +} + +static void +_setting_init_fcn_proxy (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (NM_SETTING_PROXY (setting), + NM_SETTING_PROXY_METHOD, (int) NM_SETTING_PROXY_METHOD_NONE, + NULL); + } +} + +static void +_setting_init_fcn_tun (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (NM_SETTING_TUN (setting), + NM_SETTING_TUN_MODE, NM_SETTING_TUN_MODE_TUN, + NULL); + } +} + +static void +_setting_init_fcn_vlan (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + g_object_set (setting, + NM_SETTING_VLAN_ID, 1, + NULL); + } +} + +static void +_setting_init_fcn_wireless (ARGS_SETTING_INIT_FCN) +{ + if (init_type == NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI) { + /* For Wi-Fi set mode to "infrastructure". Even though mode == NULL + * is regarded as "infrastructure", explicit value makes no doubts. + */ + g_object_set (NM_SETTING_WIRELESS (setting), + NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, + NULL); + } +} + +/*****************************************************************************/ + +#define SETTING_PRETTY_NAME_802_1X N_("802-1x settings") +#define SETTING_PRETTY_NAME_ADSL N_("ADSL connection") +#define SETTING_PRETTY_NAME_BLUETOOTH N_("bluetooth connection") +#define SETTING_PRETTY_NAME_BOND N_("Bond device") +#define SETTING_PRETTY_NAME_BRIDGE N_("Bridge device") +#define SETTING_PRETTY_NAME_BRIDGE_PORT N_("Bridge port") +#define SETTING_PRETTY_NAME_CDMA N_("CDMA mobile broadband connection") +#define SETTING_PRETTY_NAME_CONNECTION N_("General settings") +#define SETTING_PRETTY_NAME_DCB N_("DCB settings") +#define SETTING_PRETTY_NAME_DUMMY N_("Dummy settings") +#define SETTING_PRETTY_NAME_GENERIC N_("Generic settings") +#define SETTING_PRETTY_NAME_GSM N_("GSM mobile broadband connection") +#define SETTING_PRETTY_NAME_INFINIBAND N_("InfiniBand connection") +#define SETTING_PRETTY_NAME_IP4_CONFIG N_("IPv4 protocol") +#define SETTING_PRETTY_NAME_IP6_CONFIG N_("IPv6 protocol") +#define SETTING_PRETTY_NAME_IP_TUNNEL N_("IP-tunnel settings") +#define SETTING_PRETTY_NAME_MACSEC N_("MACsec connection") +#define SETTING_PRETTY_NAME_MACVLAN N_("macvlan connection") +#define SETTING_PRETTY_NAME_OLPC_MESH N_("OLPC Mesh connection") +#define SETTING_PRETTY_NAME_OVS_BRIDGE N_("OpenVSwitch bridge settings") +#define SETTING_PRETTY_NAME_OVS_INTERFACE N_("OpenVSwitch interface settings") +#define SETTING_PRETTY_NAME_OVS_PATCH N_("OpenVSwitch patch interface settings") +#define SETTING_PRETTY_NAME_OVS_PORT N_("OpenVSwitch port settings") +#define SETTING_PRETTY_NAME_PPP N_("PPP settings") +#define SETTING_PRETTY_NAME_PPPOE N_("PPPoE") +#define SETTING_PRETTY_NAME_PROXY N_("Proxy") +#define SETTING_PRETTY_NAME_SERIAL N_("Serial settings") +#define SETTING_PRETTY_NAME_TEAM N_("Team device") +#define SETTING_PRETTY_NAME_TEAM_PORT N_("Team port") +#define SETTING_PRETTY_NAME_TUN N_("Tun device") +#define SETTING_PRETTY_NAME_USER N_("User settings") +#define SETTING_PRETTY_NAME_VLAN N_("VLAN connection") +#define SETTING_PRETTY_NAME_VPN N_("VPN connection") +#define SETTING_PRETTY_NAME_VXLAN N_("VXLAN connection") +#define SETTING_PRETTY_NAME_WIMAX N_("WiMAX connection") +#define SETTING_PRETTY_NAME_WIRED N_("Wired Ethernet") +#define SETTING_PRETTY_NAME_WIRELESS N_("Wi-Fi connection") +#define SETTING_PRETTY_NAME_WIRELESS_SECURITY N_("Wi-Fi security settings") + +#define NM_META_SETTING_VALID_PARTS(...) \ + ((const NMMetaSettingValidPartItem *const[]) { __VA_ARGS__ NULL }) + +#define NM_META_SETTING_VALID_PART_ITEM(type, mand) \ + (&((const NMMetaSettingValidPartItem) { \ + .setting_info = &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_##type], \ + .mandatory = mand, \ + })) + +const NMMetaSettingInfoEditor nm_meta_setting_infos_editor[] = { +#define SETTING_INFO_EMPTY(type, ...) \ + [NM_META_SETTING_TYPE_##type] = { \ + .meta_type = &nm_meta_type_setting_info_editor, \ + .general = &nm_meta_setting_infos[NM_META_SETTING_TYPE_##type], \ + .pretty_name = SETTING_PRETTY_NAME_##type, \ + __VA_ARGS__ \ + } +#define SETTING_INFO(type, ...) \ + [NM_META_SETTING_TYPE_##type] = { \ + .meta_type = &nm_meta_type_setting_info_editor, \ + .general = &nm_meta_setting_infos[NM_META_SETTING_TYPE_##type], \ + .properties = property_infos_##type, \ + .properties_num = G_N_ELEMENTS (property_infos_##type) - 1, \ + .pretty_name = SETTING_PRETTY_NAME_##type, \ + __VA_ARGS__ \ + } + SETTING_INFO (802_1X), + SETTING_INFO (ADSL, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (ADSL, TRUE), + ), + .setting_init_fcn = _setting_init_fcn_adsl, + ), + SETTING_INFO (BLUETOOTH, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (BLUETOOTH, TRUE), + NM_META_SETTING_VALID_PART_ITEM (BRIDGE, FALSE), + NM_META_SETTING_VALID_PART_ITEM (GSM, FALSE), + NM_META_SETTING_VALID_PART_ITEM (CDMA, FALSE), + ), + ), + SETTING_INFO (BOND, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (BOND, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (BRIDGE, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (BRIDGE, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (BRIDGE_PORT), + SETTING_INFO (CDMA, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (CDMA, TRUE), + NM_META_SETTING_VALID_PART_ITEM (SERIAL, FALSE), + NM_META_SETTING_VALID_PART_ITEM (PPP, FALSE), + ), + .setting_init_fcn = _setting_init_fcn_cdma, + ), + SETTING_INFO (CONNECTION), + SETTING_INFO (DCB), + SETTING_INFO_EMPTY (DUMMY, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (DUMMY, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO_EMPTY (GENERIC, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (GENERIC, TRUE), + ), + ), + SETTING_INFO (GSM, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (GSM, TRUE), + NM_META_SETTING_VALID_PART_ITEM (SERIAL, FALSE), + NM_META_SETTING_VALID_PART_ITEM (PPP, FALSE), + ), + .setting_init_fcn = _setting_init_fcn_gsm, + ), + SETTING_INFO (INFINIBAND, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (INFINIBAND, TRUE), + ), + .setting_init_fcn = _setting_init_fcn_infiniband, + ), + SETTING_INFO (IP4_CONFIG, + .setting_init_fcn = _setting_init_fcn_ip4_config, + ), + SETTING_INFO (IP6_CONFIG, + .setting_init_fcn = _setting_init_fcn_ip6_config, + ), + SETTING_INFO (IP_TUNNEL, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (IP_TUNNEL, TRUE), + ), + ), + SETTING_INFO (MACSEC, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (MACSEC, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + ), + ), + SETTING_INFO (MACVLAN, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (MACVLAN, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (OLPC_MESH, + .alias = "olpc-mesh", + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (OLPC_MESH, TRUE), + ), + .setting_init_fcn = _setting_init_fcn_olpc_mesh, + ), + SETTING_INFO (OVS_BRIDGE, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (OVS_BRIDGE, TRUE), + ), + ), + SETTING_INFO (OVS_INTERFACE, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (OVS_INTERFACE, TRUE), + NM_META_SETTING_VALID_PART_ITEM (OVS_PATCH, FALSE), + NM_META_SETTING_VALID_PART_ITEM (IP4_CONFIG, FALSE), + NM_META_SETTING_VALID_PART_ITEM (IP6_CONFIG, FALSE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (OVS_PATCH), + SETTING_INFO (OVS_PORT, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (OVS_PORT, TRUE), + ), + ), + SETTING_INFO (PPPOE, + /* PPPoE is a base connection type from historical reasons. + * See libnm-core/nm-setting.c:_nm_setting_is_base_type() + */ + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (PPPOE, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, TRUE), + NM_META_SETTING_VALID_PART_ITEM (PPP, FALSE), + NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + ), + ), + SETTING_INFO (PPP), + SETTING_INFO (PROXY, + .setting_init_fcn = _setting_init_fcn_proxy, + ), + SETTING_INFO (SERIAL), + SETTING_INFO (TEAM, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (TEAM, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (TEAM_PORT), + SETTING_INFO (TUN, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (TUN, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + .setting_init_fcn = _setting_init_fcn_tun, + ), + SETTING_INFO_EMPTY (USER), + SETTING_INFO (VLAN, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (VLAN, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + .setting_init_fcn = _setting_init_fcn_vlan, + ), + SETTING_INFO (VPN, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (VPN, TRUE), + ), + ), + SETTING_INFO (VXLAN, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (VXLAN, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, FALSE), + ), + ), + SETTING_INFO (WIMAX, + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIMAX, TRUE), + ), + ), + SETTING_INFO (WIRED, + .alias = "ethernet", + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRED, TRUE), + NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + NM_META_SETTING_VALID_PART_ITEM (DCB, FALSE), + ), + ), + SETTING_INFO (WIRELESS, + .alias = "wifi", + .valid_parts = NM_META_SETTING_VALID_PARTS ( + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRELESS, TRUE), + NM_META_SETTING_VALID_PART_ITEM (WIRELESS_SECURITY, FALSE), + NM_META_SETTING_VALID_PART_ITEM (802_1X, FALSE), + ), + .setting_init_fcn = _setting_init_fcn_wireless, + ), + SETTING_INFO (WIRELESS_SECURITY, + .alias = "wifi-sec", + ), +}; + +/*****************************************************************************/ + +const NMMetaSettingValidPartItem *const nm_meta_setting_info_valid_parts_default[] = { + NM_META_SETTING_VALID_PART_ITEM (CONNECTION, TRUE), + NULL +}; + +/*****************************************************************************/ + +static const NMMetaSettingValidPartItem *const valid_settings_noslave[] = { + NM_META_SETTING_VALID_PART_ITEM (IP4_CONFIG, FALSE), + NM_META_SETTING_VALID_PART_ITEM (IP6_CONFIG, FALSE), + NM_META_SETTING_VALID_PART_ITEM (PROXY, FALSE), + NULL, +}; + +static const NMMetaSettingValidPartItem *const valid_settings_slave_bridge[] = { + NM_META_SETTING_VALID_PART_ITEM (BRIDGE_PORT, TRUE), + NULL, +}; + +static const NMMetaSettingValidPartItem *const valid_settings_slave_ovs_bridge[] = { + NM_META_SETTING_VALID_PART_ITEM (OVS_PORT, FALSE), + NULL, +}; + +static const NMMetaSettingValidPartItem *const valid_settings_slave_ovs_port[] = { + NM_META_SETTING_VALID_PART_ITEM (OVS_INTERFACE, FALSE), + NULL, +}; + +static const NMMetaSettingValidPartItem *const valid_settings_slave_team[] = { + NM_META_SETTING_VALID_PART_ITEM (TEAM_PORT, TRUE), + NULL, +}; + +const NMMetaSettingValidPartItem *const* +nm_meta_setting_info_valid_parts_for_slave_type (const char *slave_type, const char **out_slave_name) +{ + if (!slave_type) { + NM_SET_OUT (out_slave_name, NULL); + return valid_settings_noslave; + } + if (nm_streq (slave_type, NM_SETTING_BOND_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "bond-slave"); + return NM_PTRARRAY_EMPTY (const NMMetaSettingValidPartItem *); + } + if (nm_streq (slave_type, NM_SETTING_BRIDGE_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "bridge-slave"); + return valid_settings_slave_bridge; + } + if (nm_streq (slave_type, NM_SETTING_OVS_BRIDGE_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "ovs-slave"); + return valid_settings_slave_ovs_bridge; + } + if (nm_streq (slave_type, NM_SETTING_OVS_PORT_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "ovs-slave"); + return valid_settings_slave_ovs_port; + } + if (nm_streq (slave_type, NM_SETTING_TEAM_SETTING_NAME)) { + NM_SET_OUT (out_slave_name, "team-slave"); + return valid_settings_slave_team; + } + return NULL; +} + +/*****************************************************************************/ + +static const char * +_meta_type_setting_info_editor_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header) +{ + if (for_header) + return N_("name"); + return ((const NMMetaSettingInfoEditor *) abstract_info)->general->setting_name; +} + +static const char * +_meta_type_property_info_get_name (const NMMetaAbstractInfo *abstract_info, gboolean for_header) +{ + return ((const NMMetaPropertyInfo *) abstract_info)->property_name; +} + +static gconstpointer +_meta_type_setting_info_editor_get_fcn (const NMMetaAbstractInfo *abstract_info, + const NMMetaEnvironment *environment, + gpointer environment_user_data, + gpointer target, + NMMetaAccessorGetType get_type, + NMMetaAccessorGetFlags get_flags, + NMMetaAccessorGetOutFlags *out_flags, + gpointer *out_to_free) +{ + const NMMetaSettingInfoEditor *info = (const NMMetaSettingInfoEditor *) abstract_info; + + nm_assert (!out_to_free || !*out_to_free); + nm_assert (out_flags && !*out_flags); + + if (!NM_IN_SET (get_type, + NM_META_ACCESSOR_GET_TYPE_PARSABLE, + NM_META_ACCESSOR_GET_TYPE_PRETTY)) + return NULL; + + nm_assert (out_to_free); + + return info->general->setting_name; +} + +static gconstpointer +_meta_type_property_info_get_fcn (const NMMetaAbstractInfo *abstract_info, + const NMMetaEnvironment *environment, + gpointer environment_user_data, + gpointer target, + NMMetaAccessorGetType get_type, + NMMetaAccessorGetFlags get_flags, + NMMetaAccessorGetOutFlags *out_flags, + gpointer *out_to_free) +{ + const NMMetaPropertyInfo *info = (const NMMetaPropertyInfo *) abstract_info; + + nm_assert (!out_to_free || !*out_to_free); + nm_assert (out_flags && !*out_flags); + + if (!NM_IN_SET (get_type, + NM_META_ACCESSOR_GET_TYPE_PARSABLE, + NM_META_ACCESSOR_GET_TYPE_PRETTY)) + return NULL; + + nm_assert (out_to_free); + + if ( info->is_secret + && !NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS)) + return _get_text_hidden (get_type); + + return info->property_type->get_fcn (info, + environment, + environment_user_data, + target, + get_type, + get_flags, + out_flags, + out_to_free); + +} + +static const NMMetaAbstractInfo *const* +_meta_type_setting_info_editor_get_nested (const NMMetaAbstractInfo *abstract_info, + guint *out_len, + gpointer *out_to_free) +{ + const NMMetaSettingInfoEditor *info; + + info = (const NMMetaSettingInfoEditor *) abstract_info; + + NM_SET_OUT (out_len, info->properties_num); + *out_to_free = NULL; + return (const NMMetaAbstractInfo *const*) info->properties; +} + +static const NMMetaAbstractInfo *const* +_meta_type_property_info_get_nested (const NMMetaAbstractInfo *abstract_info, + guint *out_len, + gpointer *out_to_free) +{ + NM_SET_OUT (out_len, 0); + *out_to_free = NULL; + return NULL; +} + +static const char *const* +_meta_type_property_info_complete_fcn (const NMMetaAbstractInfo *abstract_info, + const NMMetaEnvironment *environment, + gpointer environment_user_data, + const NMMetaOperationContext *operation_context, + const char *text, + char ***out_to_free) +{ + const NMMetaPropertyInfo *info = (const NMMetaPropertyInfo *) abstract_info; + + nm_assert (out_to_free && !*out_to_free); + + if (info->property_type->complete_fcn) { + return info->property_type->complete_fcn (info, + environment, + environment_user_data, + operation_context, + text, + out_to_free); + } + + if (info->property_type->values_fcn) { + return info->property_type->values_fcn (info, + out_to_free); + } + + if ( info->property_typ_data + && info->property_typ_data->values_static) + return info->property_typ_data->values_static; + + return NULL; +} + +const NMMetaType nm_meta_type_setting_info_editor = { + .type_name = "setting_info_editor", + .get_name = _meta_type_setting_info_editor_get_name, + .get_nested = _meta_type_setting_info_editor_get_nested, + .get_fcn = _meta_type_setting_info_editor_get_fcn, +}; + +const NMMetaType nm_meta_type_property_info = { + .type_name = "property_info", + .get_name = _meta_type_property_info_get_name, + .get_nested = _meta_type_property_info_get_nested, + .get_fcn = _meta_type_property_info_get_fcn, + .complete_fcn = _meta_type_property_info_complete_fcn, +}; + +const NMMetaType nm_meta_type_nested_property_info = { + .type_name = "nested_property_info", +}; |